1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
/* ISC license. */
#include <fcntl.h>
#include <errno.h>
#include <skalibs/sgetopt.h>
#include <skalibs/uint.h>
#include <skalibs/strerr2.h>
#include <skalibs/djbunix.h>
#define USAGE "redirfd -[ r | w | u | a | c | x ] [ -n ] [ -b ] fd file prog..."
#define dieusage() strerr_dieusage(100, USAGE)
int main (int argc, char const *const *argv, char const *const *envp)
{
int fd, fd2 ;
unsigned int flags = 0 ;
int what = -1 ;
int changemode = 0 ;
PROG = "redirfd" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
register int opt = subgetopt_r(argc, argv, "rwuacxnb", &l) ;
if (opt == -1) break ;
switch (opt)
{
case 'r' : what = O_RDONLY ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ;
case 'w' : what = O_WRONLY ; flags |= O_CREAT|O_TRUNC ; flags &= ~(O_APPEND|O_EXCL) ; break ;
case 'u' : what = O_RDWR ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ;
case 'a' : what = O_WRONLY ; flags |= O_CREAT|O_APPEND ; flags &= ~(O_TRUNC|O_EXCL) ; break ;
case 'c' : what = O_WRONLY ; flags |= O_APPEND ; flags &= ~(O_CREAT|O_TRUNC|O_EXCL) ; break ;
case 'x' : what = O_WRONLY ; flags |= O_CREAT|O_EXCL ; flags &= ~(O_APPEND|O_TRUNC) ; break ;
case 'n' : flags |= O_NONBLOCK ; break ;
case 'b' : changemode = 1 ; break ;
default : dieusage() ;
}
}
argc -= l.ind ; argv += l.ind ;
}
if ((argc < 3) || (what == -1)) dieusage() ;
if (!uint0_scan(argv[0], (unsigned int *)&fd)) dieusage() ;
flags |= what ;
fd2 = open3(argv[1], flags, 0666) ;
if ((fd2 == -1) && (what == O_WRONLY) && (errno == ENXIO))
{
register int e ;
int fdr = open_read(argv[1]) ;
if (fdr == -1) strerr_diefu2sys(111, "open_read ", argv[1]) ;
fd2 = open3(argv[1], flags, 0666) ;
e = errno ;
fd_close(fdr) ;
errno = e ;
}
if (fd2 == -1) strerr_diefu2sys(111, "open ", argv[1]) ;
if (fd_move(fd, fd2) == -1)
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, fd2)] = 0 ;
strerr_diefu4sys(111, "move fd ", fmt, " to fd ", argv[0]) ;
}
if (changemode)
{
if (((flags & O_NONBLOCK) ? ndelay_off(fd) : ndelay_on(fd)) < 0)
strerr_diefu1sys(111, "change blocking mode") ;
}
pathexec_run(argv[2], argv+2, envp) ;
strerr_dieexec(111, argv[2]) ;
}
|