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