xref: /onnv-gate/usr/src/lib/libast/common/comp/spawnveg.c (revision 12068:08a39a083754)
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