1 /* ISC license. */
2
3 #include <unistd.h>
4 #include <errno.h>
5
6 #include <skalibs/sgetopt.h>
7 #include <skalibs/types.h>
8 #include <skalibs/strerr2.h>
9 #include <skalibs/exec.h>
10 #include <skalibs/djbunix.h>
11
12 #include <execline/execline.h>
13
14 #define USAGE "pipeline [ -d ] [ -r | -w ] { command... } command..."
15 #define dieusage() strerr_dieusage(100, USAGE)
16
main(int argc,char const ** argv,char const * const * envp)17 int main (int argc, char const **argv, char const *const *envp)
18 {
19 int df = 0, w = 0 ;
20 PROG = "pipeline" ;
21 {
22 subgetopt_t l = SUBGETOPT_ZERO ;
23 for (;;)
24 {
25 int opt = subgetopt_r(argc, argv, "drw", &l) ;
26 if (opt == -1) break ;
27 switch (opt)
28 {
29 case 'd' : df = 1 ; break ;
30 case 'r' : w = 0 ; break ;
31 case 'w' : w = 1 ; break ;
32 default : dieusage() ;
33 }
34 }
35 argc -= l.ind ; argv += l.ind ;
36 }
37 {
38 pid_t pid ;
39 int fd ;
40 int argc1 = el_semicolon(argv) ;
41 if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
42 if (argc1 + 1 == argc) strerr_dief1x(100, "empty remainder") ;
43 argv[argc1] = 0 ;
44 if (df)
45 {
46 int p[2] ;
47 if (pipe(p) < 0) strerr_diefu1sys(111, "create pipe") ;
48 pid = doublefork() ;
49 switch (pid)
50 {
51 case -1: strerr_diefu1sys(111, "doublefork") ;
52 case 0:
53 PROG = "pipeline (grandchild)" ;
54 fd_close(p[w]) ;
55 if (fd_move(!w, p[!w]) < 0) strerr_diefu1sys(111, "fd_move") ;
56 xexec0_e(argv, envp) ;
57 }
58 fd_close(p[!w]) ;
59 fd = p[w] ;
60 }
61 else
62 {
63 pid = el_spawn1(argv[0], argv, envp, &fd, !w) ;
64 if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ;
65 }
66 if (fd_move(w, fd) < 0) strerr_diefu1sys(111, "fd_move") ;
67 if (w == fd) uncoe(fd) ;
68 {
69 char fmt[PID_FMT + 2] = "!=" ;
70 size_t i = 2 ;
71 i += pid_fmt(fmt+i, pid) ; fmt[i++] = 0 ;
72 xmexec_en(argv + argc1 + 1, envp, fmt, i, 1) ;
73 }
74 }
75 }
76