|
Packit Service |
a8c26c |
/***********************************************************************
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* This software is part of the ast package *
|
|
Packit Service |
a8c26c |
* Copyright (c) 1985-2012 AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* and is licensed under the *
|
|
Packit Service |
a8c26c |
* Eclipse Public License, Version 1.0 *
|
|
Packit Service |
a8c26c |
* by AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* A copy of the License is available at *
|
|
Packit Service |
a8c26c |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit Service |
a8c26c |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Information and Software Systems Research *
|
|
Packit Service |
a8c26c |
* AT&T Research *
|
|
Packit Service |
a8c26c |
* Florham Park NJ *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Glenn Fowler <gsf@research.att.com> *
|
|
Packit Service |
a8c26c |
* David Korn <dgk@research.att.com> *
|
|
Packit Service |
a8c26c |
* Phong Vo <kpv@research.att.com> *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
***********************************************************************/
|
|
Packit Service |
a8c26c |
#pragma prototyped
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* spawnveg -- spawnve with process group or session control
|
|
Packit Service |
a8c26c |
*
|
|
Packit Service |
a8c26c |
* pgid <0 setsid() [session group leader]
|
|
Packit Service |
a8c26c |
* 0 nothing [retain session and process group]
|
|
Packit Service |
a8c26c |
* 1 setpgid(0,0) [process group leader]
|
|
Packit Service |
a8c26c |
* >1 setpgid(0,pgid) [join process group]
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <ast.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if _lib_spawnveg
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
NoN(spawnveg)
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if _lib_posix_spawn > 1 /* reports underlying exec() errors */
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <spawn.h>
|
|
Packit Service |
a8c26c |
#include <error.h>
|
|
Packit Service |
a8c26c |
#include <wait.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
pid_t
|
|
Packit Service |
a8c26c |
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
int err;
|
|
Packit Service |
a8c26c |
pid_t pid;
|
|
Packit Service |
a8c26c |
posix_spawnattr_t attr;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (err = posix_spawnattr_init(&attr))
|
|
Packit Service |
a8c26c |
goto nope;
|
|
Packit Service |
a8c26c |
if (pgid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (pgid <= 1)
|
|
Packit Service |
a8c26c |
pgid = 0;
|
|
Packit Service |
a8c26c |
if (err = posix_spawnattr_setpgroup(&attr, pgid))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
if (err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
posix_spawnattr_destroy(&attr);
|
|
Packit Service |
a8c26c |
#if _lib_posix_spawn < 2
|
|
Packit Service |
a8c26c |
if (waitpid(pid, &err, WNOHANG|WNOWAIT) == pid && EXIT_STATUS(err) == 127)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
while (waitpid(pid, NiL, 0) == -1 && errno == EINTR);
|
|
Packit Service |
a8c26c |
if (!access(path, X_OK))
|
|
Packit Service |
a8c26c |
errno = ENOEXEC;
|
|
Packit Service |
a8c26c |
pid = -1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
return pid;
|
|
Packit Service |
a8c26c |
bad:
|
|
Packit Service |
a8c26c |
posix_spawnattr_destroy(&attr);
|
|
Packit Service |
a8c26c |
nope:
|
|
Packit Service |
a8c26c |
errno = err;
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if _lib_spawn_mode
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <process.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#ifndef P_NOWAIT
|
|
Packit Service |
a8c26c |
#define P_NOWAIT _P_NOWAIT
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
#ifndef P_DETACH
|
|
Packit Service |
a8c26c |
#define P_DETACH _P_DETACH
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
pid_t
|
|
Packit Service |
a8c26c |
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
return spawnve(pgid ? P_DETACH : P_NOWAIT, path, argv, envv ? envv : environ);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <spawn.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* open-edition/mvs/zos fork+exec+(setpgid)
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
pid_t
|
|
Packit Service |
a8c26c |
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
struct inheritance inherit;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
inherit.flags = 0;
|
|
Packit Service |
a8c26c |
if (pgid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
inherit.flags |= SPAWN_SETGROUP;
|
|
Packit Service |
a8c26c |
inherit.pgroup = (pgid > 1) ? pgid : SPAWN_NEWPGROUP;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
return spawn(path, 0, (int*)0, &inherit, (const char**)argv, (const char**)envv);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <error.h>
|
|
Packit Service |
a8c26c |
#include <wait.h>
|
|
Packit Service |
a8c26c |
#include <sig.h>
|
|
Packit Service |
a8c26c |
#include <ast_tty.h>
|
|
Packit Service |
a8c26c |
#include <ast_vfork.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#ifndef ENOSYS
|
|
Packit Service |
a8c26c |
#define ENOSYS EINVAL
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if _lib_spawnve && _hdr_process
|
|
Packit Service |
a8c26c |
#include <process.h>
|
|
Packit Service |
a8c26c |
#if defined(P_NOWAIT) || defined(_P_NOWAIT)
|
|
Packit Service |
a8c26c |
#undef _lib_spawnve
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if !_lib_vfork
|
|
Packit Service |
a8c26c |
#undef _real_vfork
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* fork+exec+(setsid|setpgid)
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
pid_t
|
|
Packit Service |
a8c26c |
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
#if _lib_fork || _lib_vfork
|
|
Packit Service |
a8c26c |
int n;
|
|
Packit Service |
a8c26c |
int m;
|
|
Packit Service |
a8c26c |
pid_t pid;
|
|
Packit Service |
a8c26c |
pid_t rid;
|
|
Packit Service |
a8c26c |
#if _real_vfork
|
|
Packit Service |
a8c26c |
volatile int exec_errno;
|
|
Packit Service |
a8c26c |
volatile int* volatile exec_errno_ptr;
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
int err[2];
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#if 0
|
|
Packit Service |
a8c26c |
if (access(path, X_OK))
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
if (!envv)
|
|
Packit Service |
a8c26c |
envv = environ;
|
|
Packit Service |
a8c26c |
#if _lib_spawnve
|
|
Packit Service |
a8c26c |
#if _lib_fork || _lib_vfork
|
|
Packit Service |
a8c26c |
if (!pgid)
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
return spawnve(path, argv, envv);
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
#if _lib_fork || _lib_vfork
|
|
Packit Service |
a8c26c |
n = errno;
|
|
Packit Service |
a8c26c |
#if _real_vfork
|
|
Packit Service |
a8c26c |
exec_errno = 0;
|
|
Packit Service |
a8c26c |
exec_errno_ptr = &exec_errno;
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
if (pipe(err) < 0)
|
|
Packit Service |
a8c26c |
err[0] = -1;
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
fcntl(err[0], F_SETFD, FD_CLOEXEC);
|
|
Packit Service |
a8c26c |
fcntl(err[1], F_SETFD, FD_CLOEXEC);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
|
|
Packit Service |
a8c26c |
#if _lib_vfork
|
|
Packit Service |
a8c26c |
pid = vfork();
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
pid = fork();
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
if (pid == -1)
|
|
Packit Service |
a8c26c |
n = errno;
|
|
Packit Service |
a8c26c |
else if (!pid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
sigcritical(0);
|
|
Packit Service |
a8c26c |
if (pgid == -1)
|
|
Packit Service |
a8c26c |
setsid();
|
|
Packit Service |
a8c26c |
else if (pgid)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
m = 0;
|
|
Packit Service |
a8c26c |
if (pgid == 1 || pgid == -2 && (m = 1))
|
|
Packit Service |
a8c26c |
pgid = getpid();
|
|
Packit Service |
a8c26c |
if (setpgid(0, pgid) < 0 && errno == EPERM)
|
|
Packit Service |
a8c26c |
setpgid(pgid, 0);
|
|
Packit Service |
a8c26c |
#if _lib_tcgetpgrp
|
|
Packit Service |
a8c26c |
if (m)
|
|
Packit Service |
a8c26c |
tcsetpgrp(2, pgid);
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
#ifdef TIOCSPGRP
|
|
Packit Service |
a8c26c |
if (m)
|
|
Packit Service |
a8c26c |
ioctl(2, TIOCSPGRP, &pgid);
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
execve(path, argv, envv);
|
|
Packit Service |
a8c26c |
#if _real_vfork
|
|
Packit Service |
a8c26c |
*exec_errno_ptr = errno;
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
if (err[0] != -1)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
m = errno;
|
|
Packit Service |
a8c26c |
write(err[1], &m, sizeof(m));
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
_exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
rid = pid;
|
|
Packit Service |
a8c26c |
#if _real_vfork
|
|
Packit Service |
a8c26c |
if (pid != -1 && (m = *exec_errno_ptr))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
while (waitpid(pid, NiL, 0) == -1 && errno == EINTR);
|
|
Packit Service |
a8c26c |
rid = pid = -1;
|
|
Packit Service |
a8c26c |
n = m;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
if (err[0] != -1)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
close(err[1]);
|
|
Packit Service |
a8c26c |
if (pid != -1)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
m = 0;
|
|
Packit Service |
a8c26c |
while (read(err[0], &m, sizeof(m)) == -1)
|
|
Packit Service |
a8c26c |
if (errno != EINTR)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
m = errno;
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (m)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
while (waitpid(pid, &n, 0) && errno == EINTR);
|
|
Packit Service |
a8c26c |
rid = pid = -1;
|
|
Packit Service |
a8c26c |
n = m;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
close(err[0]);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
sigcritical(0);
|
|
Packit Service |
a8c26c |
if (pid != -1 && pgid > 0)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* parent and child are in a race here
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (pgid == 1)
|
|
Packit Service |
a8c26c |
pgid = pid;
|
|
Packit Service |
a8c26c |
if (setpgid(pid, pgid) < 0 && pid != pgid && errno == EPERM)
|
|
Packit Service |
a8c26c |
setpgid(pid, pid);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
errno = n;
|
|
Packit Service |
a8c26c |
return rid;
|
|
Packit Service |
a8c26c |
#else
|
|
Packit Service |
a8c26c |
errno = ENOSYS;
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#endif
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#endif
|