14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin 244887Schin /* 254887Schin * spawnveg -- spawnve with process group or session control 264887Schin * 274887Schin * pgid <0 setsid() [session group leader] 284887Schin * 0 nothing [retain session and process group] 294887Schin * 1 setpgid(0,0) [process group leader] 304887Schin * >1 setpgid(0,pgid) [join process group] 314887Schin */ 324887Schin 334887Schin #include <ast.h> 344887Schin 354887Schin #if _lib_spawnveg 364887Schin 374887Schin NoN(spawnveg) 384887Schin 394887Schin #else 404887Schin 414887Schin #if _lib_posix_spawn > 1 /* reports underlying exec() errors */ 424887Schin 434887Schin #include <spawn.h> 444887Schin #include <error.h> 454887Schin #include <wait.h> 464887Schin 474887Schin pid_t 484887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 494887Schin { 504887Schin int err; 514887Schin pid_t pid; 524887Schin posix_spawnattr_t attr; 534887Schin 544887Schin if (err = posix_spawnattr_init(&attr)) 5510898Sroland.mainz@nrubsig.org goto nope; 564887Schin if (pgid) 574887Schin { 584887Schin if (pgid <= 1) 594887Schin pgid = 0; 604887Schin if (err = posix_spawnattr_setpgroup(&attr, pgid)) 614887Schin goto bad; 624887Schin if (err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP)) 634887Schin goto bad; 644887Schin } 654887Schin if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ)) 664887Schin goto bad; 674887Schin posix_spawnattr_destroy(&attr); 684887Schin #if _lib_posix_spawn < 2 694887Schin if (waitpid(pid, &err, WNOHANG|WNOWAIT) == pid && EXIT_STATUS(err) == 127) 704887Schin { 714887Schin while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); 724887Schin if (!access(path, X_OK)) 734887Schin errno = ENOEXEC; 744887Schin pid = -1; 754887Schin } 764887Schin #endif 774887Schin return pid; 784887Schin bad: 7910898Sroland.mainz@nrubsig.org posix_spawnattr_destroy(&attr); 8010898Sroland.mainz@nrubsig.org nope: 814887Schin errno = err; 824887Schin return -1; 834887Schin } 844887Schin 854887Schin #else 864887Schin 874887Schin #if _lib_spawn_mode 884887Schin 894887Schin #include <process.h> 904887Schin 914887Schin #ifndef P_NOWAIT 924887Schin #define P_NOWAIT _P_NOWAIT 934887Schin #endif 944887Schin #ifndef P_DETACH 954887Schin #define P_DETACH _P_DETACH 964887Schin #endif 974887Schin 984887Schin pid_t 994887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 1004887Schin { 1014887Schin return spawnve(pgid ? P_DETACH : P_NOWAIT, path, argv, envv ? envv : environ); 1024887Schin } 1034887Schin 1044887Schin #else 1054887Schin 1064887Schin #if _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance 1074887Schin 1084887Schin #include <spawn.h> 1094887Schin 1104887Schin /* 1114887Schin * open-edition/mvs/zos fork+exec+(setpgid) 1124887Schin */ 1134887Schin 1144887Schin pid_t 1154887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 1164887Schin { 1174887Schin struct inheritance inherit; 1184887Schin 1194887Schin inherit.flags = 0; 1204887Schin if (pgid) 1214887Schin { 1224887Schin inherit.flags |= SPAWN_SETGROUP; 1234887Schin inherit.pgroup = (pgid > 1) ? pgid : SPAWN_NEWPGROUP; 1244887Schin } 1254887Schin return spawn(path, 0, (int*)0, &inherit, (const char**)argv, (const char**)envv); 1264887Schin } 1274887Schin 1284887Schin #else 1294887Schin 1304887Schin #include <error.h> 1314887Schin #include <wait.h> 1324887Schin #include <sig.h> 1334887Schin #include <ast_vfork.h> 1344887Schin 1354887Schin #ifndef ENOSYS 1364887Schin #define ENOSYS EINVAL 1374887Schin #endif 1384887Schin 1394887Schin #if _lib_spawnve && _hdr_process 1404887Schin #include <process.h> 1414887Schin #if defined(P_NOWAIT) || defined(_P_NOWAIT) 1424887Schin #undef _lib_spawnve 1434887Schin #endif 1444887Schin #endif 1454887Schin 1464887Schin #if !_lib_vfork 1474887Schin #undef _real_vfork 1484887Schin #endif 1494887Schin 1504887Schin /* 1514887Schin * fork+exec+(setsid|setpgid) 1524887Schin */ 1534887Schin 1544887Schin pid_t 1554887Schin spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid) 1564887Schin { 1574887Schin #if _lib_fork || _lib_vfork 1584887Schin int n; 1594887Schin int m; 1604887Schin pid_t pid; 1614887Schin pid_t rid; 1624887Schin #if _real_vfork 1634887Schin volatile int exec_errno; 1644887Schin volatile int* volatile exec_errno_ptr; 1654887Schin #else 1664887Schin int err[2]; 1674887Schin #endif 1684887Schin #endif 1694887Schin 1704887Schin #if 0 1714887Schin if (access(path, X_OK)) 1724887Schin return -1; 1734887Schin #endif 1744887Schin if (!envv) 1754887Schin envv = environ; 1764887Schin #if _lib_spawnve 1774887Schin #if _lib_fork || _lib_vfork 1784887Schin if (!pgid) 1794887Schin #endif 1804887Schin return spawnve(path, argv, envv); 1814887Schin #endif 1824887Schin #if _lib_fork || _lib_vfork 1834887Schin n = errno; 1844887Schin #if _real_vfork 1854887Schin exec_errno = 0; 1864887Schin exec_errno_ptr = &exec_errno; 1874887Schin #else 1884887Schin if (pipe(err) < 0) 1894887Schin err[0] = -1; 1904887Schin else 1914887Schin { 1924887Schin fcntl(err[0], F_SETFD, FD_CLOEXEC); 1934887Schin fcntl(err[1], F_SETFD, FD_CLOEXEC); 1944887Schin } 1954887Schin #endif 1964887Schin sigcritical(1); 1974887Schin #if _lib_vfork 1984887Schin pid = vfork(); 1994887Schin #else 2004887Schin pid = fork(); 2014887Schin #endif 2024887Schin sigcritical(0); 2038462SApril.Chin@Sun.COM if (pid == -1) 2048462SApril.Chin@Sun.COM n = errno; 2058462SApril.Chin@Sun.COM else if (!pid) 2064887Schin { 2074887Schin if (pgid < 0) 2084887Schin setsid(); 2094887Schin else if (pgid > 0) 2104887Schin { 2114887Schin if (pgid == 1) 2124887Schin pgid = 0; 2134887Schin if (setpgid(0, pgid) < 0 && pgid && errno == EPERM) 2144887Schin setpgid(0, 0); 2154887Schin } 2164887Schin execve(path, argv, envv); 2174887Schin #if _real_vfork 2184887Schin *exec_errno_ptr = errno; 2194887Schin #else 2204887Schin if (err[0] != -1) 2214887Schin { 2224887Schin n = errno; 2234887Schin write(err[1], &n, sizeof(n)); 2244887Schin } 2254887Schin #endif 2264887Schin _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC); 2274887Schin } 2284887Schin rid = pid; 2294887Schin #if _real_vfork 2304887Schin if (pid != -1 && (m = *exec_errno_ptr)) 2314887Schin { 2324887Schin while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); 2334887Schin rid = pid = -1; 2344887Schin n = m; 2354887Schin } 2364887Schin #else 2378462SApril.Chin@Sun.COM if (err[0] != -1) 2384887Schin { 2394887Schin close(err[1]); 2408462SApril.Chin@Sun.COM if (pid != -1 && read(err[0], &m, sizeof(m)) == sizeof(m) && m) 2414887Schin { 2424887Schin while (waitpid(pid, NiL, 0) == -1 && errno == EINTR); 2434887Schin rid = pid = -1; 2444887Schin n = m; 2454887Schin } 2464887Schin close(err[0]); 2474887Schin } 2484887Schin #endif 2494887Schin if (pid != -1 && pgid > 0) 2504887Schin { 2514887Schin /* 2524887Schin * parent and child are in a race here 2534887Schin */ 2544887Schin 2554887Schin if (pgid == 1) 2564887Schin pgid = pid; 2574887Schin if (setpgid(pid, pgid) < 0 && pid != pgid && errno == EPERM) 2584887Schin setpgid(pid, pid); 2594887Schin } 2604887Schin errno = n; 2614887Schin return rid; 2624887Schin #else 2634887Schin errno = ENOSYS; 2644887Schin return -1; 2654887Schin #endif 2664887Schin } 2674887Schin 2684887Schin #endif 2694887Schin 2704887Schin #endif 2714887Schin 2724887Schin #endif 2734887Schin 2744887Schin #endif 275