child_spawn3.c (1599B)
1 /* ISC license. */ 2 3 #include <unistd.h> 4 5 #include <skalibs/types.h> 6 #include <skalibs/env.h> 7 #include <skalibs/djbunix.h> 8 #include <skalibs/cspawn.h> 9 10 pid_t child_spawn3 (char const *prog, char const *const *argv, char const *const *envp, int *fds) 11 { 12 pid_t pid ; 13 int p[3][2] ; 14 15 if (pipe(p[0]) == -1) return 0 ; 16 if (ndelay_on(p[0][0]) == -1 || coe(p[0][0]) == -1 || pipe(p[1]) == -1) goto errp0 ; 17 if (ndelay_on(p[1][1]) == -1 || coe(p[1][1]) == -1 || pipe(p[2]) == -1) goto errp1 ; 18 if (ndelay_on(p[2][0]) == -1 || coe(p[2][0]) == -1) goto err ; 19 20 { 21 cspawn_fileaction fa[2] = 22 { 23 [0] = { .type = CSPAWN_FA_MOVE, .x = { .fd2 = { [0] = fds[0], [1] = p[1][0] } } }, 24 [1] = { .type = CSPAWN_FA_MOVE, .x = { .fd2 = { [0] = fds[1], [1] = p[0][1] } } } 25 } ; 26 size_t envlen = env_len(envp) ; 27 size_t m = sizeof(SKALIBS_CHILD_SPAWN_FDS_ENVVAR) ; 28 char modifs[sizeof(SKALIBS_CHILD_SPAWN_FDS_ENVVAR) + UINT_FMT] = SKALIBS_CHILD_SPAWN_FDS_ENVVAR "=" ; 29 char const *newenv[envlen + 2] ; 30 m += uint_fmt(modifs + sizeof(SKALIBS_CHILD_SPAWN_FDS_ENVVAR), p[2][1]) ; 31 modifs[m++] = 0 ; 32 env_mergen(newenv, envlen + 2, envp, envlen, modifs, m, 1) ; 33 pid = cspawn(prog, argv, newenv, CSPAWN_FLAGS_SIGBLOCKNONE, fa, 2) ; 34 if (!pid) goto err ; 35 } 36 37 fd_close(p[2][1]) ; 38 fd_close(p[1][0]) ; 39 fd_close(p[0][1]) ; 40 fds[0] = p[0][0] ; 41 fds[1] = p[1][1] ; 42 fds[2] = p[2][0] ; 43 return pid ; 44 45 err: 46 fd_close(p[2][1]) ; 47 fd_close(p[2][0]) ; 48 errp1: 49 fd_close(p[1][1]) ; 50 fd_close(p[1][0]) ; 51 errp0: 52 fd_close(p[0][1]) ; 53 fd_close(p[0][0]) ; 54 return 0 ; 55 }