1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/src/lib/libast/comp/spawnveg.c
Martijn Dekker 71bfe0283d libast: consolidate errno ID fallbacks into error.h
In various places in libast and libcmd there are preprocessor
fallbacks like this, for systems that don't define all the commonly
used errno value IDs:

    #ifndef ENOSYS
    #define ENOSYS	EINVAL
    #endif

and many others. It is better to have these all in one place so
they are not duplicated and we don't risk inconsistencies when
adding new code.

src/lib/libast/include/error.h includes the OS's <errno.h>, so it
is the logical file to move all these fallbacks into.

Quite possibly there is no remotely current system that needs any
of these, but they won't do any harm either.

Most files already use <error.h> directly or indirectly. Four
needed new #include <error.h> directives to use the fallbacks if
needed. The libast Mamfile is updated to make those files depend on
that header.
2021-03-22 14:55:16 +00:00

299 lines
6.2 KiB
C

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