void el_execsequence (char const *const *argv1, char const *const *argv2, char const *const *envp) { if (!argv2[0]) { pathexec0_run(argv1, envp) ; strerr_dieexec(111, argv1[0]) ; } else { int wstat ; unsigned int j = 2 ; #ifdef EXECLINE_OLD_VARNAMES char fmt[UINT_FMT * 2 + 15] = "?=" ; #else char fmt[UINT_FMT + 1] = "?=" ; #endif pid_t pid = el_spawn0(argv1[0], argv1, envp) ; if (!pid) strerr_warnwu2sys("spawn ", argv1[0]) ; if (wait_pid(pid, &wstat) < 0) strerr_diefu2sys(111, "wait for ", argv1[0]) ; j += uint_fmt(fmt + j, wait_status(wstat)) ; fmt[j++] = 0 ; #ifdef EXECLINE_OLD_VARNAMES byte_copy(fmt + j, 13, "LASTEXITCODE=") ; j += 13 ; j += uint_fmt(fmt + j, wait_status(wstat)) ; fmt[j++] = 0 ; #endif pathexec_r(argv2, envp, env_len(envp), fmt, j) ; } strerr_dieexec(111, argv2[0]) ; }
void el_substandrun_str (stralloc *src, unsigned int srcbase, char const *const *envp, exlsn_t const *info) { stralloc dst = STRALLOC_ZERO ; register int r = el_substitute(&dst, src->s + srcbase, src->len, info->vars.s, info->values.s, genalloc_s(elsubst_t const, &info->data), genalloc_len(elsubst_t const, &info->data)) ; if (r < 0) strerr_diefu1sys(111, "el_substitute") ; if (!r) _exit(0) ; stralloc_free(src) ; { char const *v[r + 1] ; if (!env_make(v, r, dst.s, dst.len)) strerr_diefu1sys(111, "env_make") ; v[r] = 0 ; pathexec_r(v, envp, env_len(envp), info->modifs.s, info->modifs.len) ; } strerr_dieexec(111, dst.s) ; }
int main (int argc, char const *const *argv, char const *const *envp) { char const *s = env_get2(envp, VAR) ; unsigned int fd = 1 ; unsigned int timeout = 0 ; int df = 1, keep = 0 ; PROG = "sdnotify-wrapper" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "d:ft:k", &l) ; if (opt == -1) break ; switch (opt) { case 'd' : if (!uint0_scan(l.arg, &fd)) dieusage() ; break ; case 'f' : df = 0 ; break ; case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; case 'k' : keep = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) dieusage() ; if (!s) xpathexec_run(argv[0], argv, envp) ; else { pid_t parent = getpid() ; pid_t child ; int p[2] ; if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ; child = df ? doublefork() : fork() ; if (child < 0) strerr_diefu1sys(111, df ? "doublefork" : "fork") ; else if (!child) { PROG = "sdnotify-wrapper (child)" ; close(p[1]) ; return run_child(p[0], timeout, parent, s) ; } close(p[0]) ; if (fd_move((int)fd, p[1]) < 0) strerr_diefu1sys(111, "move descriptor") ; if (keep) xpathexec_run(argv[0], argv, envp) ; else xpathexec_r(argv, envp, env_len(envp), VAR, sizeof(VAR)) ; } }
int main (int argc, char const **argv, char const *const *envp) { char const *x ; int argc1 ; unsigned short okcodes[256] ; unsigned int nbc = 0 ; int flagpar = 0, not = 1 ; PROG = "forx" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "epo:x:", &l) ; if (opt == -1) break ; switch (opt) { case 'e' : break ; /* compat */ case 'p' : flagpar = 1 ; break ; case 'o' : not = 0 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; case 'x' : not = 1 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; x = argv[0] ; if (!*x) dieusage() ; argv++ ; argc-- ; argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (!argc1 || (argc1 + 1 == argc)) return 0 ; { unsigned int envlen = env_len(envp) ; unsigned int varlen = str_len(x) ; unsigned int i = 0 ; pid_t pids[flagpar ? argc1 : 1] ; char const *newenv[envlen + 2] ; for (; i < (unsigned int)argc1 ; i++) { pid_t pid ; unsigned int vallen = str_len(argv[i]) ; char modif[varlen + vallen + 2] ; byte_copy(modif, varlen, x) ; modif[varlen] = '=' ; byte_copy(modif + varlen + 1, vallen, argv[i]) ; modif[varlen + vallen + 1] = 0 ; if (!env_merge(newenv, envlen + 2, envp, envlen, modif, varlen + vallen + 2)) strerr_diefu1sys(111, "build new environment") ; pid = el_spawn0(argv[argc1+1], argv + argc1 + 1, newenv) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1+1]) ; if (flagpar) pids[i] = pid ; else { int wstat ; if (wait_pid(pid, &wstat) == -1) strerr_diefu2sys(111, "wait for ", argv[argc1+1]) ; if (not == isok(okcodes, nbc, wait_estatus(wstat))) return wait_estatus(wstat) ; } } if (flagpar) if (!waitn(pids, argc1)) strerr_diefu1sys(111, "waitn") ; } return 0 ; }
unsigned int NAME (char const *prog, char const *const *argv, char const *const *envp, unsigned int uid, unsigned int gid, int *fds) { int p[NPIPES][2] ; int syncpipe[2] ; int pid ; int e ; if (pipe(p[0]) < 0) return 0 ; if (pipe(p[1]) < 0) { e = errno ; goto errp0 ; } #ifdef _CHILD_SPAWN2_ if (pipe(p[2]) < 0) { e = errno ; goto errp1 ; } #endif if (pipe(syncpipe) < 0) { e = errno ; goto errp2 ; } if (coe(syncpipe[1]) < 0) { e = errno ; goto errsp ; } pid = fork() ; if (pid < 0) { e = errno ; goto errsp ; } else if (!pid) { unsigned int m = 25 ; unsigned int n = str_len(PROG) ; char fmt[25 + UINT_FMT] = "SKACLIENT2_ADDITIONAL_FD" ; char name[n + 9] ; byte_copy(name, n, PROG) ; byte_copy(name + n, 9, " (child)") ; PROG = name ; #ifdef _CHILD_SPAWN2_ fmt[m-1] = '=' ; m += uint_fmt(fmt + m, p[2][1]) ; fmt[m++] = 0 ; fd_close(p[2][0]) ; #endif fd_close(syncpipe[0]) ; fd_close(p[1][1]) ; fd_close(p[0][0]) ; if ((fd_move(0, p[1][0]) < 0) || (fd_move(1, p[0][1]) < 0)) goto syncdie ; if (gid && (prot_gid(gid) < 0)) goto syncdie ; if (uid && (prot_uid(uid) < 0)) goto syncdie ; /* XXX: we should unignore signals here, but there's a compromise to be XXX: found between bloat, API complexity, and theoretical correctness. XXX: Not sure what The Right Thing is; just not unignoring atm. XXX: 20130326 edit: The Right Thing is probably to leave the ignore XXX: status alone, because programs that do actual signal handling XXX: are likely to use a selfpipe, and selfpipe_finish() restores XXX: old signal handlers - it knows what to do and we don't. So, XXX: leave that work to selfpipe_finish(). */ sig_blocknone() ; /* empty sigprocmask in the child, always */ pathexec_r_name(prog, argv, envp, env_len(envp), fmt, m) ; syncdie: { char c = errno ; fd_write(syncpipe[1], &c, 1) ; } _exit(111) ; } { char c ; fd_close(syncpipe[1]) ; #ifdef _CHILD_SPAWN2_ fd_close(p[2][1]) ; #endif fd_close(p[1][0]) ; fd_close(p[0][1]) ; p[1][0] = fd_read(syncpipe[0], &c, 1) ; if (p[1][0] < 0) goto killclosewait ; else if (p[1][0]) { e = c ; goto closewait ; } } fd_close(syncpipe[0]) ; if ((ndelay_on(p[0][0]) < 0) || (coe(p[0][0]) < 0) || (ndelay_on(p[1][1]) < 0) || (coe(p[1][1]) < 0)) goto killclosewait ; #ifdef _CHILD_SPAWN2_ if ((ndelay_on(p[2][0]) < 0) || (coe(p[2][0]) < 0)) goto killclosewait ; fds[2] = p[2][0] ; #endif fds[0] = p[0][0] ; fds[1] = p[1][1] ; return (unsigned int)pid ; errsp: fd_close(syncpipe[1]) ; fd_close(syncpipe[0]) ; errp2: #ifdef _CHILD_SPAWN2_ fd_close(p[2][1]) ; fd_close(p[2][0]) ; errp1: #endif fd_close(p[1][1]) ; fd_close(p[1][0]) ; errp0: fd_close(p[0][1]) ; fd_close(p[0][0]) ; errno = e ; return 0 ; killclosewait: e = errno ; kill(pid, SIGKILL) ; closewait: #ifdef _CHILD_SPAWN2_ fd_close(p[2][0]) ; #endif fd_close(p[1][1]) ; fd_close(p[0][0]) ; wait_pid(&syncpipe[1], pid) ; errno = e ; return 0 ; }