da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * common process execution support with
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * proper sfio, signal and wait() syncronization
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * _ contains the process path name and is
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * placed at the top of the environment
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * not quite ready for _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * called by stropt() to set options
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsetopt(register void* a, register const void* p, register int n, const char* v)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * catch but ignore sig
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * avoids SIG_IGN being passed to children
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * do modification op and save previous state for restore()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinmodify(Proc_t* proc, int forked, int op, long arg1, long arg2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (arg1 > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Modify_t* m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((m->arg.handler = signal(arg1, SIG_DFL)) == SIG_DFL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((m->arg.handler = signal(arg1, SIG_IGN)) == SIG_IGN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * restore modifications
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Modify_t* m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Modify_t* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (m->op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m->arg.fd.child.fd != m->arg.fd.parent.fd && m->arg.fd.child.fd != PROC_ARG_NULL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->arg.fd.child.fd, F_DUPFD, m->arg.fd.parent.fd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->arg.fd.parent.fd, F_SETFD, m->arg.fd.parent.flag);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((m->op & (PROC_FD_PARENT|PROC_FD_CHILD)) == PROC_FD_CHILD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fork and exec or spawn proc(argv) and return a Proc_t handle
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pipe not used when PROC_READ|PROC_WRITE omitted
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * argv==0 duplicates current process if possible
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * cmd==0 names the current shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * cmd=="" does error cleanup
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * envv is the child environment
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * modv is the child modification vector of PROC_*() ops
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinprocopen(const char* cmd, char** argv, char** envv, long* modv, int flags)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char** p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD) && ( _lib_sigprocmask || _lib_sigsetmask )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (cmd && (!*cmd || !pathpath(path, cmd, NiL, PATH_REGULAR|PATH_EXECUTE)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (environ && envv != (char**)environ && (envv || (flags & PROC_PARANOID) || argv && (environ[0][0] != '_' || environ[0][1] != '=')))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stropt(getenv(PROC_ENV_OPTIONS), options, sizeof(*options), setopt, &debug);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[0], PROC_ARG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[1], 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[0], 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (poi[1] != 0 && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[1], PROC_ARG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (procfd >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!!procfd], !!procfd))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pio[!procfd] != !!procfd && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!procfd], PROC_ARG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; n = modv[i]; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (PROC_OP(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), PROC_ARG(n, 2)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(oenviron = (char**)memdup(environ, (p - environ) * sizeof(char*))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!newenv && environ[0][0] == '_' && environ[0][1] == '=')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((flags & PROC_PARANOID) && setenv("PATH", astconf("PATH", NiL, NiL), 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(debug & PROC_OPT_EXEC) || (debug & PROC_OPT_VERBOSE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((p = argv) && *p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*++p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((proc->pid = spawnveg(path, p, environ, proc->pgrp)) != -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * try cmd as a shell script
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = v + 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p++ = *argv++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = v + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *--p = "sh";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcpy(env + 2, (flags & PROC_PARANOID) ? astconf("SH", NiL, NiL) : pathshell());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; n = modv[i]; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (PROC_OP(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (setpgid(proc->pid, proc->pgrp) < 0 && proc->pid != proc->pgrp && errno == EPERM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((flags & (PROC_WRITE|PROC_IGNORE)) == (PROC_WRITE|PROC_IGNORE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL && handler != ignoresig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; n = modv[i]; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (PROC_OP(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pio[0] >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (poi[0] >= 0)