1ref	-D_def_map_ast=1
2
3hdr	spawn
4lib	spawn,spawnve,spawnveg,spawnvex
5lib	posix_spawnattr_setfchdir,posix_spawnattr_setsid,posix_spawnattr_setumask spawn.h
6
7mem	inheritance.pgroup spawn.h
8
9tst	lib_posix_spawn unistd.h stdlib.h spawn.h -Dfork=______fork note{ posix_spawn exists and it works and its worth using }end status{
10	#include <sys/types.h>
11	#include <sys/stat.h>
12	#include <sys/wait.h>
13	#include <spawn.h>
14	#include <signal.h>
15	#include <fcntl.h>
16	#include <string.h>
17	/* if it uses fork() why bother? */
18	#undef fork
19	pid_t fork _ARG_((void)) { NOTE("uses fork()"); return -1; }
20	pid_t _fork _ARG_((void)) { NOTE("uses _fork()"); return -1; }
21	pid_t __fork _ARG_((void)) { NOTE("uses __fork()"); return -1; }
22	int
23	main(argc, argv)
24	int	argc;
25	char**	argv;
26	{
27		char*			s;
28		pid_t			pid;
29		posix_spawnattr_t	attr;
30		int			n;
31		int			status;
32		char*			cmd[4];
33		char			tmp[1024];
34		if (argv[2])
35			_exit(signal(SIGHUP, SIG_DFL) != SIG_IGN);
36		signal(SIGHUP, SIG_IGN);
37		if (posix_spawnattr_init(&attr))
38		{
39			NOTE("posix_spawnattr_init() FAILED");
40			_exit(0);
41		}
42		if (posix_spawnattr_setpgroup(&attr, 0))
43		{
44			NOTE("posix_spawnattr_setpgroup() FAILED");
45			_exit(0);
46		}
47		if (posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP))
48		{
49			NOTE("posix_spawnattr_setflags() FAILED");
50			_exit(0);
51		}
52		/* first try an a.out and verify that SIGHUP is ignored */
53		cmd[0] = argv[0];
54		cmd[1] = argv[1];
55		cmd[2] = "test";
56		cmd[3] = 0;
57		if (posix_spawn(&pid, cmd[0], 0, &attr, cmd, 0))
58		{
59			NOTE("posix_spawn() FAILED");
60			_exit(0);
61		}
62		status = 1;
63		if (wait(&status) < 0)
64		{
65			NOTE("wait() FAILED");
66			_exit(0);
67		}
68		if (status != 0)
69		{
70			NOTE("SIGHUP ignored in parent not ignored in child");
71			_exit(0);
72		}
73		/* must return exec-type errors or its useless to us *unless* there is no [v]fork() */
74		n = strlen(cmd[0]);
75		if (n >= (sizeof(tmp) - 3))
76		{
77			NOTE("test executable path too long");
78			_exit(0);
79		}
80		strcpy(tmp, cmd[0]);
81		tmp[n] = '.';
82		tmp[n+1] = 's';
83		tmp[n+2] = 'h';
84		tmp[n+3] = 0;
85		if ((n = open(tmp, O_CREAT|O_WRONLY, S_IRWXU|S_IRWXG|S_IRWXO)) < 0 ||
86		    chmod(tmp, S_IRWXU|S_IRWXG|S_IRWXO) < 0 ||
87		    write(n, "exit 99\n", 8) != 8 ||
88		    close(n) < 0)
89		{
90			NOTE("test script create FAILED");
91			_exit(0);
92		}
93		cmd[0] = tmp;
94		n = 0; /* 0 means reject */
95		pid = -1;
96		if (posix_spawn(&pid, cmd[0], 0, &attr, cmd, 0))
97		{
98			n = 2;
99			NOTE("ENOEXEC produces posix_spawn() error (BEST)");
100		}
101		else if (pid == -1)
102			NOTE("ENOEXEC returns pid == -1");
103		else if (wait(&status) != pid)
104			NOTE("ENOEXEC produces no child process");
105		else if (!WIFEXITED(status))
106			NOTE("ENOEXEC produces signal exit");
107		else
108		{
109			status = WEXITSTATUS(status);
110			if (status == 127)
111			{
112				n = 1;
113				NOTE("ENOEXEC produces exit status 127 (GOOD)");
114			}
115			else if (status == 99)
116				NOTE("ENOEXEC invokes sh");
117			else if (status == 0)
118				NOTE("ENOEXEC reports no error");
119			else
120				NOTE("ENOEXEC produces non-zero exit status");
121		}
122		_exit(n);
123 	}
124}end
125
126tst	lib_spawn_mode unistd.h stdlib.h note{ first spawn arg is mode and it works }end execute{
127	#include <signal.h>
128	#include <process.h>
129	#ifndef P_NOWAIT
130	#define P_NOWAIT _P_NOWAIT
131	#endif
132	int
133	main(argc, argv)
134	int	argc;
135	char**	argv;
136	{
137		int	status;
138		char*	cmd[4];
139		if (argv[2])
140			_exit(signal(SIGHUP, SIG_DFL) != SIG_IGN);
141		signal(SIGHUP, SIG_IGN);
142		cmd[0] = argv[0];
143		cmd[1] = argv[1];
144		cmd[2] = "test";
145		cmd[3] = 0;
146		if (spawnv(P_NOWAIT, cmd[0], cmd) < 0)
147			_exit(1);
148		status = 1;
149		_exit(wait(&status) < 0 || status != 0);
150	}
151}end
152
153tst	use_spawn_exec note{ interpreter exec as efficient as fork() }end run{
154	exit 1
155}end
156