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