1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #pragma prototyped 23*4887Schin 24*4887Schin /* 25*4887Schin * spawnveg -- spawnve with process group or session control 26*4887Schin * 27*4887Schin * pgid <0 setsid() [session group leader] 28*4887Schin * 0 nothing [retain session and process group] 29*4887Schin * 1 setpgid(0,0) [process group leader] 30*4887Schin * >1 setpgid(0,pgid) [join process group] 31*4887Schin */ 32*4887Schin 33*4887Schin #include <ast.h> 34*4887Schin 35*4887Schin #if _lib_spawnveg 36*4887Schin 37*4887Schin NoN(spawnveg) 38*4887Schin 39*4887Schin #else 40*4887Schin 41*4887Schin #if _lib_posix_spawn > 1 /* reports underlying exec() errors */ 42*4887Schin 43*4887Schin #include <spawn.h> 44*4887Schin #include <error.h> 45*4887Schin #include <wait.h> 46*4887Schin 47*4887Schin pid_t 48*4887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 49*4887Schin { 50*4887Schin int err; 51*4887Schin pid_t pid; 52*4887Schin posix_spawnattr_t attr; 53*4887Schin 54*4887Schin if (err = posix_spawnattr_init(&attr)) 55*4887Schin goto bad; 56*4887Schin if (pgid) 57*4887Schin { 58*4887Schin if (pgid <= 1) 59*4887Schin pgid = 0; 60*4887Schin if (err = posix_spawnattr_setpgroup(&attr, pgid)) 61*4887Schin goto bad; 62*4887Schin if (err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP)) 63*4887Schin goto bad; 64*4887Schin } 65*4887Schin if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ)) 66*4887Schin goto bad; 67*4887Schin posix_spawnattr_destroy(&attr); 68*4887Schin #if _lib_posix_spawn < 2 69*4887Schin if (waitpid(pid, &err, WNOHANG|WNOWAIT) == pid && EXIT_STATUS(err) == 127) 70*4887Schin { 71*4887Schin while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); 72*4887Schin if (!access(path, X_OK)) 73*4887Schin errno = ENOEXEC; 74*4887Schin pid = -1; 75*4887Schin } 76*4887Schin #endif 77*4887Schin return pid; 78*4887Schin bad: 79*4887Schin errno = err; 80*4887Schin return -1; 81*4887Schin } 82*4887Schin 83*4887Schin #else 84*4887Schin 85*4887Schin #if _lib_spawn_mode 86*4887Schin 87*4887Schin #include <process.h> 88*4887Schin 89*4887Schin #ifndef P_NOWAIT 90*4887Schin #define P_NOWAIT _P_NOWAIT 91*4887Schin #endif 92*4887Schin #ifndef P_DETACH 93*4887Schin #define P_DETACH _P_DETACH 94*4887Schin #endif 95*4887Schin 96*4887Schin pid_t 97*4887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 98*4887Schin { 99*4887Schin return spawnve(pgid ? P_DETACH : P_NOWAIT, path, argv, envv ? envv : environ); 100*4887Schin } 101*4887Schin 102*4887Schin #else 103*4887Schin 104*4887Schin #if _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance 105*4887Schin 106*4887Schin #include <spawn.h> 107*4887Schin 108*4887Schin /* 109*4887Schin * open-edition/mvs/zos fork+exec+(setpgid) 110*4887Schin */ 111*4887Schin 112*4887Schin pid_t 113*4887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 114*4887Schin { 115*4887Schin struct inheritance inherit; 116*4887Schin 117*4887Schin inherit.flags = 0; 118*4887Schin if (pgid) 119*4887Schin { 120*4887Schin inherit.flags |= SPAWN_SETGROUP; 121*4887Schin inherit.pgroup = (pgid > 1) ? pgid : SPAWN_NEWPGROUP; 122*4887Schin } 123*4887Schin return spawn(path, 0, (int*)0, &inherit, (const char**)argv, (const char**)envv); 124*4887Schin } 125*4887Schin 126*4887Schin #else 127*4887Schin 128*4887Schin #include <error.h> 129*4887Schin #include <wait.h> 130*4887Schin #include <sig.h> 131*4887Schin #include <ast_vfork.h> 132*4887Schin 133*4887Schin #ifndef ENOSYS 134*4887Schin #define ENOSYS EINVAL 135*4887Schin #endif 136*4887Schin 137*4887Schin #if _lib_spawnve && _hdr_process 138*4887Schin #include <process.h> 139*4887Schin #if defined(P_NOWAIT) || defined(_P_NOWAIT) 140*4887Schin #undef _lib_spawnve 141*4887Schin #endif 142*4887Schin #endif 143*4887Schin 144*4887Schin #if !_lib_vfork 145*4887Schin #undef _real_vfork 146*4887Schin #endif 147*4887Schin 148*4887Schin /* 149*4887Schin * fork+exec+(setsid|setpgid) 150*4887Schin */ 151*4887Schin 152*4887Schin pid_t 153*4887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 154*4887Schin { 155*4887Schin #if _lib_fork || _lib_vfork 156*4887Schin int n; 157*4887Schin int m; 158*4887Schin pid_t pid; 159*4887Schin pid_t rid; 160*4887Schin #if _real_vfork 161*4887Schin volatile int exec_errno; 162*4887Schin volatile int* volatile exec_errno_ptr; 163*4887Schin #else 164*4887Schin int err[2]; 165*4887Schin #endif 166*4887Schin #endif 167*4887Schin 168*4887Schin #if 0 169*4887Schin if (access(path, X_OK)) 170*4887Schin return -1; 171*4887Schin #endif 172*4887Schin if (!envv) 173*4887Schin envv = environ; 174*4887Schin #if _lib_spawnve 175*4887Schin #if _lib_fork || _lib_vfork 176*4887Schin if (!pgid) 177*4887Schin #endif 178*4887Schin return spawnve(path, argv, envv); 179*4887Schin #endif 180*4887Schin #if _lib_fork || _lib_vfork 181*4887Schin n = errno; 182*4887Schin #if _real_vfork 183*4887Schin exec_errno = 0; 184*4887Schin exec_errno_ptr = &exec_errno; 185*4887Schin #else 186*4887Schin if (pipe(err) < 0) 187*4887Schin err[0] = -1; 188*4887Schin else 189*4887Schin { 190*4887Schin fcntl(err[0], F_SETFD, FD_CLOEXEC); 191*4887Schin fcntl(err[1], F_SETFD, FD_CLOEXEC); 192*4887Schin } 193*4887Schin #endif 194*4887Schin sigcritical(1); 195*4887Schin #if _lib_vfork 196*4887Schin pid = vfork(); 197*4887Schin #else 198*4887Schin pid = fork(); 199*4887Schin #endif 200*4887Schin sigcritical(0); 201*4887Schin if (!pid) 202*4887Schin { 203*4887Schin if (pgid < 0) 204*4887Schin setsid(); 205*4887Schin else if (pgid > 0) 206*4887Schin { 207*4887Schin if (pgid == 1) 208*4887Schin pgid = 0; 209*4887Schin if (setpgid(0, pgid) < 0 && pgid && errno == EPERM) 210*4887Schin setpgid(0, 0); 211*4887Schin } 212*4887Schin execve(path, argv, envv); 213*4887Schin #if _real_vfork 214*4887Schin *exec_errno_ptr = errno; 215*4887Schin #else 216*4887Schin if (err[0] != -1) 217*4887Schin { 218*4887Schin n = errno; 219*4887Schin write(err[1], &n, sizeof(n)); 220*4887Schin } 221*4887Schin #endif 222*4887Schin _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC); 223*4887Schin } 224*4887Schin rid = pid; 225*4887Schin #if _real_vfork 226*4887Schin if (pid != -1 && (m = *exec_errno_ptr)) 227*4887Schin { 228*4887Schin while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); 229*4887Schin rid = pid = -1; 230*4887Schin n = m; 231*4887Schin } 232*4887Schin #else 233*4887Schin if (pid != -1 && err[0] != -1) 234*4887Schin { 235*4887Schin close(err[1]); 236*4887Schin if (read(err[0], &m, sizeof(m)) == sizeof(m) && m) 237*4887Schin { 238*4887Schin while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); 239*4887Schin rid = pid = -1; 240*4887Schin n = m; 241*4887Schin } 242*4887Schin close(err[0]); 243*4887Schin } 244*4887Schin #endif 245*4887Schin if (pid != -1 && pgid > 0) 246*4887Schin { 247*4887Schin /* 248*4887Schin * parent and child are in a race here 249*4887Schin */ 250*4887Schin 251*4887Schin if (pgid == 1) 252*4887Schin pgid = pid; 253*4887Schin if (setpgid(pid, pgid) < 0 && pid != pgid && errno == EPERM) 254*4887Schin setpgid(pid, pid); 255*4887Schin } 256*4887Schin errno = n; 257*4887Schin return rid; 258*4887Schin #else 259*4887Schin errno = ENOSYS; 260*4887Schin return -1; 261*4887Schin #endif 262*4887Schin } 263*4887Schin 264*4887Schin #endif 265*4887Schin 266*4887Schin #endif 267*4887Schin 268*4887Schin #endif 269*4887Schin 270*4887Schin #endif 271