da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
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* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * common process execution support with
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * proper sfio, signal and wait() syncronization
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * _ contains the process path name and is
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * placed at the top of the environment
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "proclib.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ls.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * not quite ready for _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg && _lib_fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef DEBUG_PROC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEBUG_PROC 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _sys_socket
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sys/types.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sys/socket.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef _lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinProc_t proc_default = { -1 };
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if DEBUG_PROC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <namval.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PROC_ENV_OPTIONS "PROC_OPTIONS"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PROC_OPT_ENVIRONMENT (1<<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PROC_OPT_EXEC (1<<1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PROC_OPT_TRACE (1<<2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define PROC_OPT_VERBOSE (1<<3)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const Namval_t options[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "debug", PROC_OPT_VERBOSE,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "environment", PROC_OPT_ENVIRONMENT,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "exec", PROC_OPT_EXEC,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "trace", PROC_OPT_TRACE,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "verbose", PROC_OPT_VERBOSE,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 0, 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * called by stropt() to set options
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsetopt(register void* a, register const void* p, register int n, const char* v)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(v);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *((int*)a) |= ((Namval_t*)p)->value;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *((int*)a) &= ~((Namval_t*)p)->value;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Fd_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short flag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Fd_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Mod_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct Mod_s* next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short op;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin short save;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin union
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Fd_t parent;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Fd_t child;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Handler_t handler;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } arg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Modify_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGPIPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * catch but ignore sig
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * avoids SIG_IGN being passed to children
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinignoresig(int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(sig, ignoresig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * do modification op and save previous state for restore()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinmodify(Proc_t* proc, int forked, int op, long arg1, long arg2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (forked)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (arg1 != arg2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (arg2 != PROC_ARG_NULL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(arg2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (fcntl(arg1, F_DUPFD, arg2) != arg2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (op & PROC_FD_CHILD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(arg1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sig_dfl:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(arg1, SIG_DFL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sig_ign:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(arg1, SIG_IGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sys_pgrp:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (arg1 < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setsid();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (arg1 > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (arg1 == 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin arg1 = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (setpgid(0, arg1) < 0 && arg1 && errno == EPERM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setpgid(0, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sys_umask:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin umask(arg1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(forked);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Modify_t* m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(m = newof(NiL, Modify_t, 1, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m->next = proc->mods;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->mods = m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (m->op = op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m->arg.fd.parent.fd = (short)arg1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m->arg.fd.parent.flag = fcntl(arg1, F_GETFD, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((m->arg.fd.child.fd = (short)arg2) != arg1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (arg2 != PROC_ARG_NULL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m->arg.fd.child.flag = fcntl(arg2, F_GETFD, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((m->save = fcntl(arg2, F_DUPFD, 3)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m->op = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->save, F_SETFD, FD_CLOEXEC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(arg2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (fcntl(arg1, F_DUPFD, arg2) != arg2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (op & PROC_FD_CHILD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(arg1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (op & PROC_FD_CHILD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m->arg.fd.parent.flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(arg1, F_SETFD, FD_CLOEXEC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!m->arg.fd.parent.flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(arg1, F_SETFD, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sig_dfl:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((m->arg.handler = signal(arg1, SIG_DFL)) == SIG_DFL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m->save = (short)arg1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sig_ign:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((m->arg.handler = signal(arg1, SIG_IGN)) == SIG_IGN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m->save = (short)arg1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sys_pgrp:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pgrp = arg1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sys_umask:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((m->save = (short)umask(arg1)) == arg1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->mods = m->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(m);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->mods = m->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(m);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(proc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * restore modifications
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinrestore(Proc_t* proc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Modify_t* m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Modify_t* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int oerrno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(proc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin oerrno = errno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = proc->mods;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->mods = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (m)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (m->op)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m->op & PROC_FD_PARENT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(m->arg.fd.parent.fd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m->arg.fd.child.fd != m->arg.fd.parent.fd && m->arg.fd.child.fd != PROC_ARG_NULL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(m->op & PROC_FD_PARENT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m->op & PROC_FD_CHILD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(m->arg.fd.parent.fd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->arg.fd.child.fd, F_DUPFD, m->arg.fd.parent.fd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->arg.fd.parent.fd, F_SETFD, m->arg.fd.parent.flag);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(m->arg.fd.child.fd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->save, F_DUPFD, m->arg.fd.child.fd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(m->save);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m->arg.fd.child.flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->arg.fd.child.fd, F_SETFD, FD_CLOEXEC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((m->op & (PROC_FD_PARENT|PROC_FD_CHILD)) == PROC_FD_CHILD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(m->arg.fd.parent.fd, F_SETFD, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sig_dfl:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sig_ign:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(m->save, m->arg.handler);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sys_umask:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin umask(m->save);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = m->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(p);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = oerrno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define restore(p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fork and exec or spawn proc(argv) and return a Proc_t handle
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
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
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinProc_t*
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinprocopen(const char* cmd, char** argv, char** envv, long* modv, int flags)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Proc_t* proc = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int procfd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char** p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char** v;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int forked = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int signalled = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char path[PATH_MAX];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char env[PATH_MAX + 2];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int pio[2];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_pipe_rw && !_lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int poi[2];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD) && ( _lib_sigprocmask || _lib_sigsetmask )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sig_mask_t mask;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int newenv = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if DEBUG_PROC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int debug = PROC_OPT_EXEC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!argv && (flags & PROC_OVERLAY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!argv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = ENOEXEC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pio[0] = pio[1] = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_pipe_rw && !_lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin poi[0] = poi[1] = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (cmd && (!*cmd || !pathpath(path, cmd, NiL, PATH_REGULAR|PATH_EXECUTE)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (flags & (PROC_READ|PROC_WRITE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin procfd = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_READ:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin procfd = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_WRITE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin procfd = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_READ|PROC_WRITE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin procfd = 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc_default.pid == -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc = &proc_default;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(proc = newof(0, Proc_t, 1, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pid = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pgrp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->rfd = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->wfd = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->flags = flags;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (environ && envv != (char**)environ && (envv || (flags & PROC_PARANOID) || argv && (environ[0][0] != '_' || environ[0][1] != '=')))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!setenviron(NiL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin newenv = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (procfd >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _pipe_rw
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pipe(pio))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (procfd > 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (socketpair(AF_UNIX, SOCK_STREAM, 0, pio))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pipe(pio) || pipe(poi))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (pipe(pio))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & PROC_OVERLAY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin forked = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (argv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(flags & PROC_FOREGROUND))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signalled = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->sigint = signal(SIGINT, SIG_IGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->sigquit = signal(SIGQUIT, SIG_IGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigprocmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigemptyset(&mask);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigaddset(&mask, SIGCHLD);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigprocmask(SIG_BLOCK, &mask, &proc->mask);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_sigsetmask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mask = sigmask(SIGCHLD);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->mask = sigblock(mask);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin proc->sigchld = signal(SIGCHLD, SIG_DFL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pid = fork();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(flags & PROC_FOREGROUND))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigcritical(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!proc->pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->sigint != SIG_IGN)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->sigint = SIG_DFL;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signal(SIGINT, proc->sigint);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->sigquit != SIG_IGN)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->sigquit = SIG_DFL;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signal(SIGQUIT, proc->sigquit);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if _lib_sigprocmask
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sigprocmask(SIG_SETMASK, &proc->mask, NiL);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if _lib_sigsetmask
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sigsetmask(proc->mask);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->sigchld != SIG_IGN)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signal(SIGCHLD, SIG_DFL);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if (proc->pid == -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin forked = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!proc->pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char** oenviron = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* oenviron0 = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if DEBUG_PROC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin stropt(getenv(PROC_ENV_OPTIONS), options, sizeof(*options), setopt, &debug);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (debug & PROC_OPT_TRACE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!fork())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsprintf(path, sizeof(path), "%d", getppid());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin execlp("trace", "trace", "-p", path, NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _exit(EXIT_NOTFOUND);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sleep(2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & PROC_DAEMON)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGHUP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sig_ign, SIGHUP, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sig_dfl, SIGTERM, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sig_ign, SIGTSTP, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTTIN
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sig_ign, SIGTTIN, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTTOU
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sig_ign, SIGTTOU, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & (PROC_BACKGROUND|PROC_DAEMON))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sig_ign, SIGINT, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGQUIT
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sig_ign, SIGQUIT, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & (PROC_DAEMON|PROC_SESSION))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin modify(proc, forked, PROC_sys_pgrp, -1, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (forked || (flags & PROC_OVERLAY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((flags & PROC_PRIVELEGED) && !geteuid())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setuid(geteuid());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setgid(getegid());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & (PROC_PARANOID|PROC_GID))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setgid(getgid());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & (PROC_PARANOID|PROC_UID))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setuid(getuid());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (procfd > 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[0], PROC_ARG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[1], 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _pipe_rw || _lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup, 1, 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[0], 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (poi[1] != 0 && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[1], PROC_ARG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (procfd >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!!procfd], !!procfd))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pio[!procfd] != !!procfd && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!procfd], PROC_ARG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; n = modv[i]; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (PROC_OP(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), PROC_ARG(n, 2)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (forked && (flags & PROC_ENVCLEAR))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin environ = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (newenv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = environ;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(oenviron = (char**)memdup(environ, (p - environ) * sizeof(char*))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (argv && envv != (char**)environ)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!newenv && environ[0][0] == '_' && environ[0][1] == '=')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin oenviron0 = environ[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env[0] = '_';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env[1] = '=';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env[2] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!setenviron(env))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((flags & PROC_PARANOID) && setenv("PATH", astconf("PATH", NiL, NiL), 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((p = envv) && p != (char**)environ)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!setenviron(*p++))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = argv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fork
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (forked && !p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return proc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if DEBUG_PROC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(debug & PROC_OPT_EXEC) || (debug & PROC_OPT_VERBOSE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((debug & PROC_OPT_ENVIRONMENT) && (p = environ))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%s\n", *p++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "+ %s", cmd ? path : "sh");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((p = argv) && *p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*++p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, " %s", *p);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "\n");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(debug & PROC_OPT_EXEC))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _exit(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = argv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (cmd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcpy(env + 2, path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (forked || (flags & PROC_OVERLAY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin execve(path, p, environ);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((proc->pid = spawnveg(path, p, environ, proc->pgrp)) != -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (errno != ENOEXEC)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * try cmd as a shell script
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(flags & PROC_ARGMOD))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(v = newof(0, char*, p - argv + 2, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto cleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = v + 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*argv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p++ = *argv++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = v + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *p = path;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *--p = "sh";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcpy(env + 2, (flags & PROC_PARANOID) ? astconf("SH", NiL, NiL) : pathshell());
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (forked || (flags & PROC_OVERLAY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin execve(env + 2, p, environ);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pid = spawnveg(env + 2, p, environ, proc->pgrp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cleanup:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (forked)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(flags & PROC_OVERLAY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _use_spawnveg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (v)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(v);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (p = oenviron)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin environ = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*p)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!setenviron(*p++))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto bad;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(oenviron);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (oenviron0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin environ[0] = oenviron0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin restore(proc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & PROC_OVERLAY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin exit(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->pid != -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!forked)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & PROC_FOREGROUND)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signalled = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->sigint = signal(SIGINT, SIG_IGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->sigquit = signal(SIGQUIT, SIG_IGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGCHLD)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if _lib_sigprocmask
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sigemptyset(&mask);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sigaddset(&mask, SIGCHLD);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sigprocmask(SIG_BLOCK, &mask, &proc->mask);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if _lib_sigsetmask
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mask = sigmask(SIGCHLD);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin proc->mask = sigblock(mask);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->sigchld = signal(SIGCHLD, SIG_DFL);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (modv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; n = modv[i]; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (PROC_OP(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(PROC_ARG(n, 1));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_sys_pgrp:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->pgrp < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pgrp = proc->pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (proc->pgrp > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->pgrp == 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pgrp = proc->pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (setpgid(proc->pid, proc->pgrp) < 0 && proc->pid != proc->pgrp && errno == EPERM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin setpgid(proc->pid, proc->pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (procfd >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGPIPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((flags & (PROC_WRITE|PROC_IGNORE)) == (PROC_WRITE|PROC_IGNORE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Handler_t handler;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL && handler != ignoresig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGPIPE, handler);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (procfd)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->wfd = pio[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(pio[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _pipe_rw || _lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->wfd = pio[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->wfd = poi[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(poi[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 1:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->rfd = pio[0];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(pio[1]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->rfd > 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(proc->rfd, F_SETFD, FD_CLOEXEC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (proc->wfd > 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fcntl(proc->wfd, F_SETFD, FD_CLOEXEC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!proc->pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin proc->pid = getpid();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return proc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bad:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (signalled)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (proc->sigint != SIG_IGN)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signal(SIGINT, proc->sigint);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (proc->sigquit != SIG_IGN)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signal(SIGQUIT, proc->sigquit);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if defined(SIGCHLD)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if _lib_sigprocmask
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sigprocmask(SIG_SETMASK, &proc->mask, NiL);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if _lib_sigsetmask
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sigsetmask(proc->mask);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (proc->sigchld != SIG_DFL)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin signal(SIGCHLD, proc->sigchld);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#endif
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((flags & PROC_CLEANUP) && modv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; n = modv[i]; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (PROC_OP(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (PROC_ARG(n, 2) != PROC_ARG_NULL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(PROC_ARG(n, 1));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pio[0] >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(pio[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pio[1] >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(pio[1]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_pipe_rw && !_lib_socketpair
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (poi[0] >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(poi[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (poi[1] >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(poi[1]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin procfree(proc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}