1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
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]
41 #if _lib_posix_spawn > 1 /* reports underlying exec() errors */
48 spawnveg(const char* path
, char* const argv
[], char* const envv
[], pid_t pgid
)
52 posix_spawnattr_t attr
;
54 if (err
= posix_spawnattr_init(&attr
))
60 if (err
= posix_spawnattr_setpgroup(&attr
, pgid
))
62 if (err
= posix_spawnattr_setflags(&attr
, POSIX_SPAWN_SETPGROUP
))
65 if (err
= posix_spawn(&pid
, path
, NiL
, &attr
, argv
, envv
? envv
: environ
))
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
))
79 posix_spawnattr_destroy(&attr
);
92 #define P_NOWAIT _P_NOWAIT
95 #define P_DETACH _P_DETACH
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
);
106 #if _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance
111 * open-edition/mvs/zos fork+exec+(setpgid)
115 spawnveg(const char* path
, char* const argv
[], char* const envv
[], pid_t pgid
)
117 struct inheritance inherit
;
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
);
133 #include <ast_vfork.h>
136 #define ENOSYS EINVAL
139 #if _lib_spawnve && _hdr_process
141 #if defined(P_NOWAIT) || defined(_P_NOWAIT)
151 * fork+exec+(setsid|setpgid)
155 spawnveg(const char* path
, char* const argv
[], char* const envv
[], pid_t pgid
)
157 #if _lib_fork || _lib_vfork
163 volatile int exec_errno
;
164 volatile int* volatile exec_errno_ptr
;
171 if (access(path
, X_OK
))
177 #if _lib_fork || _lib_vfork
180 return spawnve(path
, argv
, envv
);
182 #if _lib_fork || _lib_vfork
186 exec_errno_ptr
= &exec_errno
;
192 fcntl(err
[0], F_SETFD
, FD_CLOEXEC
);
193 fcntl(err
[1], F_SETFD
, FD_CLOEXEC
);
213 if (setpgid(0, pgid
) < 0 && pgid
&& errno
== EPERM
)
216 execve(path
, argv
, envv
);
218 *exec_errno_ptr
= errno
;
223 write(err
[1], &n
, sizeof(n
));
226 _exit(errno
== ENOENT
? EXIT_NOTFOUND
: EXIT_NOEXEC
);
230 if (pid
!= -1 && (m
= *exec_errno_ptr
))
232 while (waitpid(pid
, NiL
, 0) == -1 && errno
== EINTR
);
240 if (pid
!= -1 && read(err
[0], &m
, sizeof(m
)) == sizeof(m
) && m
)
242 while (waitpid(pid
, NiL
, 0) == -1 && errno
== EINTR
);
249 if (pid
!= -1 && pgid
> 0)
252 * parent and child are in a race here
257 if (setpgid(pid
, pgid
) < 0 && pid
!= pgid
&& errno
== EPERM
)