mirror of
https://git.busybox.net/uClibc
synced 2025-05-08 23:02:28 +08:00
librt: add posix_spawn support
Signed-off-by: Ismael Luceno <ismael.luceno@gmail.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
parent
d1bc0c9915
commit
0dcf66744f
@ -290,6 +290,7 @@ HEADERS_RM-$(UCLIBC_SUPPORT_AI_ADDRCONFIG) += ifaddrs.h
|
||||
HEADERS_RM-$(UCLIBC_SV4_DEPRECATED) += ustat.h sys/ustat.h bits/ustat.h
|
||||
HEADERS_RM-$(UCLIBC_SUSV3_LEGACY) += sys/timeb.h regexp.h
|
||||
HEADERS_RM-$(UCLIBC_SUSV4_LEGACY) += utime.h ucontext.h
|
||||
HEADERS_RM-$(UCLIBC_HAS_ADVANCED_REALTIME) += spawn.h
|
||||
|
||||
ifneq ($(findstring install,$(MAKECMDGOALS)),)
|
||||
$(addprefix $(PREFIX)$(DEVEL_PREFIX),include $(MULTILIB_DIR)):
|
||||
|
266
include/spawn.h
Normal file
266
include/spawn.h
Normal file
@ -0,0 +1,266 @@
|
||||
/* Definitions for POSIX spawn interface.
|
||||
Copyright (C) 2000,2003,2004,2009,2011,2012 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _SPAWN_H
|
||||
#define _SPAWN_H 1
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <features.h>
|
||||
#include <sched.h>
|
||||
#define __need_sigset_t
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/* Data structure to contain attributes for thread creation. */
|
||||
typedef struct {
|
||||
short int __flags;
|
||||
pid_t __pgrp;
|
||||
sigset_t __sd;
|
||||
sigset_t __ss;
|
||||
struct sched_param __sp;
|
||||
int __policy;
|
||||
int __pad[16];
|
||||
} posix_spawnattr_t;
|
||||
|
||||
|
||||
/* Data structure to contain information about the actions to be
|
||||
performed in the new process with respect to file descriptors. */
|
||||
typedef struct {
|
||||
int __allocated;
|
||||
int __used;
|
||||
struct __spawn_action *__actions;
|
||||
int __pad[16];
|
||||
} posix_spawn_file_actions_t;
|
||||
|
||||
|
||||
/* Flags to be set in the `posix_spawnattr_t'. */
|
||||
#define POSIX_SPAWN_RESETIDS 0x01
|
||||
#define POSIX_SPAWN_SETPGROUP 0x02
|
||||
#define POSIX_SPAWN_SETSIGDEF 0x04
|
||||
#define POSIX_SPAWN_SETSIGMASK 0x08
|
||||
#define POSIX_SPAWN_SETSCHEDPARAM 0x10
|
||||
#define POSIX_SPAWN_SETSCHEDULER 0x20
|
||||
#define POSIX_SPAWN_USEVFORK 0x40 /* GNU extension */
|
||||
|
||||
|
||||
#define __POSIX_SPAWN_MASK (POSIX_SPAWN_RESETIDS \
|
||||
| POSIX_SPAWN_SETPGROUP \
|
||||
| POSIX_SPAWN_SETSIGDEF \
|
||||
| POSIX_SPAWN_SETSIGMASK \
|
||||
| POSIX_SPAWN_SETSCHEDPARAM \
|
||||
| POSIX_SPAWN_SETSCHEDULER \
|
||||
| POSIX_SPAWN_USEVFORK)
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Spawn a new process executing PATH with the attributes describes in *ATTRP.
|
||||
Before running the process perform the actions described in FILE-ACTIONS.
|
||||
|
||||
This function is a possible cancellation point and therefore not
|
||||
marked with __THROW. */
|
||||
int posix_spawn(pid_t * restrict pid, const char * restrict path,
|
||||
const posix_spawn_file_actions_t * restrict file_actions,
|
||||
const posix_spawnattr_t * restrict attrp,
|
||||
char * const argv[restrict],
|
||||
char * const envp[restrict]);
|
||||
|
||||
/* Similar to `posix_spawn' but search for FILE in the PATH.
|
||||
|
||||
This function is a possible cancellation point and therefore not
|
||||
marked with __THROW. */
|
||||
int posix_spawnp(pid_t *pid, const char *file,
|
||||
const posix_spawn_file_actions_t *file_actions,
|
||||
const posix_spawnattr_t *attrp,
|
||||
char * const argv[], char * const envp[]);
|
||||
|
||||
/* Initialize data structure with attributes for `spawn' to default values. */
|
||||
inline static int
|
||||
posix_spawnattr_init(posix_spawnattr_t *attr)
|
||||
{
|
||||
memset(attr, 0, sizeof(*attr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free resources associated with ATTR. */
|
||||
inline static int
|
||||
posix_spawnattr_destroy(posix_spawnattr_t *attr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store signal mask for signals with default handling from ATTR in
|
||||
SIGDEFAULT. */
|
||||
inline static int
|
||||
posix_spawnattr_getsigdefault(const posix_spawnattr_t *attr,
|
||||
sigset_t *sigdefault)
|
||||
{
|
||||
memcpy(sigdefault, &attr->__sd, sizeof(sigset_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Set signal mask for signals with default handling in ATTR to SIGDEFAULT. */
|
||||
inline static int
|
||||
posix_spawnattr_setsigdefault(posix_spawnattr_t *attr,
|
||||
const sigset_t *sigdefault)
|
||||
{
|
||||
memcpy(&attr->__sd, sigdefault, sizeof(sigset_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store signal mask for the new process from ATTR in SIGMASK. */
|
||||
inline static int
|
||||
posix_spawnattr_getsigmask(const posix_spawnattr_t *attr,
|
||||
sigset_t *sigmask)
|
||||
{
|
||||
memcpy(sigmask, &attr->__ss, sizeof(sigset_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Set signal mask for the new process in ATTR to SIGMASK. */
|
||||
inline static int
|
||||
posix_spawnattr_setsigmask(posix_spawnattr_t *attr,
|
||||
const sigset_t *sigmask)
|
||||
{
|
||||
memcpy(&attr->__ss, sigmask, sizeof(sigset_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get flag word from the attribute structure. */
|
||||
inline static int
|
||||
posix_spawnattr_getflags(const posix_spawnattr_t *attr, short int *flags)
|
||||
{
|
||||
*flags = attr->__flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store flags in the attribute structure. */
|
||||
inline static int
|
||||
posix_spawnattr_setflags(posix_spawnattr_t *attr, short int flags)
|
||||
{
|
||||
/* Check no invalid bits are set. */
|
||||
if (flags & ~__POSIX_SPAWN_MASK)
|
||||
return EINVAL;
|
||||
|
||||
attr->__flags = flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get process group ID from the attribute structure. */
|
||||
inline static int
|
||||
posix_spawnattr_getpgroup(const posix_spawnattr_t *attr, pid_t *pgroup)
|
||||
{
|
||||
*pgroup = attr->__pgrp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store process group ID in the attribute structure. */
|
||||
inline static int
|
||||
posix_spawnattr_setpgroup(posix_spawnattr_t *attr, pid_t pgroup)
|
||||
{
|
||||
attr->__pgrp = pgroup;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get scheduling policy from the attribute structure. */
|
||||
inline static int
|
||||
posix_spawnattr_getschedpolicy(const posix_spawnattr_t *attr,
|
||||
int *schedpolicy)
|
||||
{
|
||||
*schedpolicy = attr->__policy;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store scheduling policy in the attribute structure. */
|
||||
inline static int
|
||||
posix_spawnattr_setschedpolicy(posix_spawnattr_t *attr, int schedpolicy)
|
||||
{
|
||||
switch (schedpolicy) {
|
||||
case SCHED_OTHER:
|
||||
case SCHED_FIFO:
|
||||
case SCHED_RR:
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
attr->__policy = schedpolicy;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get scheduling parameters from the attribute structure. */
|
||||
static inline int
|
||||
posix_spawnattr_getschedparam(const posix_spawnattr_t *attr,
|
||||
struct sched_param *schedparam)
|
||||
{
|
||||
memcpy(schedparam, &attr->__sp, sizeof(attr->__sp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store scheduling parameters in the attribute structure. */
|
||||
static inline int
|
||||
posix_spawnattr_setschedparam(posix_spawnattr_t *attr,
|
||||
const struct sched_param *schedparam)
|
||||
{
|
||||
attr->__sp = *schedparam;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize data structure for file attribute for `spawn' call. */
|
||||
inline static int
|
||||
posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions)
|
||||
{
|
||||
memset(file_actions, 0, sizeof(*file_actions));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free resources associated with FILE-ACTIONS. */
|
||||
inline static int
|
||||
posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions)
|
||||
{
|
||||
free(file_actions->__actions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add an action to FILE-ACTIONS which tells the implementation to call
|
||||
`open' for the given file during the `spawn' call. */
|
||||
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * restrict
|
||||
file_actions, int fd,
|
||||
const char * restrict path,
|
||||
int oflag, mode_t mode)
|
||||
__THROW;
|
||||
|
||||
/* Add an action to FILE-ACTIONS which tells the implementation to call
|
||||
`close' for the given file descriptor during the `spawn' call. */
|
||||
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions,
|
||||
int fd)
|
||||
__THROW;
|
||||
|
||||
/* Add an action to FILE-ACTIONS which tells the implementation to call
|
||||
`dup2' for the given file descriptors during the `spawn' call. */
|
||||
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions,
|
||||
int fd, int newfd) __THROW;
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* spawn.h */
|
@ -33,6 +33,14 @@ else
|
||||
librt_filter_SRC += clock_nanosleep.c clock_getcpuclockid.c clock_gettime.c
|
||||
librt_SSRC :=
|
||||
endif
|
||||
|
||||
librt_filter_SRC += $(if $(UCLIBC_HAS_ADVANCED_REALTIME),, \
|
||||
spawn.c \
|
||||
spawn_faction_addclose.c \
|
||||
spawn_faction_adddup2.c \
|
||||
spawn_faction_addopen.c \
|
||||
spawn_faction_init.c)
|
||||
|
||||
librt_SRC := $(filter-out $(librt_filter_SRC),$(librt_SRC))
|
||||
|
||||
librt_OBJ := $(patsubst %.c,$(librt_OUT)/%.o,$(librt_SRC))
|
||||
|
259
librt/spawn.c
Normal file
259
librt/spawn.c
Normal file
@ -0,0 +1,259 @@
|
||||
/* Copyright (C) 2000, 2011 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <alloca.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/resource.h>
|
||||
#include <not-cancel.h>
|
||||
|
||||
#include <spawn.h>
|
||||
#include "spawn_int.h"
|
||||
|
||||
/* The Unix standard contains a long explanation of the way to signal
|
||||
an error after the fork() was successful. Since no new wait status
|
||||
was wanted there is no way to signal an error using one of the
|
||||
available methods. The committee chose to signal an error by a
|
||||
normal program exit with the exit code 127. */
|
||||
#define SPAWN_ERROR 127
|
||||
|
||||
/* Execute file actions.
|
||||
* Returns true on error.
|
||||
*/
|
||||
inline static bool execute_file_actions(const posix_spawn_file_actions_t *fa)
|
||||
{
|
||||
struct rlimit64 fdlimit;
|
||||
bool have_fdlimit = false;
|
||||
|
||||
for (int cnt = 0; cnt < fa->__used; ++cnt) {
|
||||
struct __spawn_action *action = &fa->__actions[cnt];
|
||||
|
||||
switch (action->tag) {
|
||||
case spawn_do_close:
|
||||
if (close_not_cancel(action->action.close_action.fd) != 0) {
|
||||
if (!have_fdlimit) {
|
||||
getrlimit64(RLIMIT_NOFILE, &fdlimit);
|
||||
have_fdlimit = true;
|
||||
}
|
||||
|
||||
/* Only signal errors for file descriptors out of range. */
|
||||
if (0 > action->action.close_action.fd
|
||||
|| action->action.close_action.fd >= fdlimit.rlim_cur)
|
||||
/* Signal the error. */
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case spawn_do_open:;
|
||||
int new_fd = open_not_cancel(action->action.open_action.path,
|
||||
action->action.open_action.oflag
|
||||
| O_LARGEFILE,
|
||||
action->action.open_action.mode);
|
||||
|
||||
if (new_fd == -1)
|
||||
return true;
|
||||
|
||||
/* Make sure the desired file descriptor is used. */
|
||||
if (new_fd != action->action.open_action.fd) {
|
||||
if (dup2(new_fd, action->action.open_action.fd)
|
||||
!= action->action.open_action.fd)
|
||||
return true;
|
||||
|
||||
if (close_not_cancel(new_fd) != 0)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case spawn_do_dup2:
|
||||
if (dup2(action->action.dup2_action.fd,
|
||||
action->action.dup2_action.newfd)
|
||||
!= action->action.dup2_action.newfd)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DANGEROUS (POSIX_SPAWN_SETSIGMASK \
|
||||
| POSIX_SPAWN_SETSIGDEF \
|
||||
| POSIX_SPAWN_SETSCHEDPARAM \
|
||||
| POSIX_SPAWN_SETSCHEDULER \
|
||||
| POSIX_SPAWN_SETPGROUP \
|
||||
| POSIX_SPAWN_RESETIDS)
|
||||
inline static bool is_vfork_safe(short int flags)
|
||||
{
|
||||
return ((flags & POSIX_SPAWN_USEVFORK) || !(flags & DANGEROUS));
|
||||
}
|
||||
|
||||
|
||||
/* Spawn a new process executing PATH with the attributes describes in *ATTRP.
|
||||
Before running the process perform the actions described in FILE-ACTIONS. */
|
||||
static int
|
||||
__spawni(pid_t *pid, const char *file,
|
||||
const posix_spawn_file_actions_t *fa,
|
||||
const posix_spawnattr_t *attrp, char *const argv[],
|
||||
char *const envp[], const char *path)
|
||||
{
|
||||
short int flags = attrp ? attrp->__flags : 0;
|
||||
|
||||
pid_t new_pid;
|
||||
if (is_vfork_safe(flags) && !fa)
|
||||
new_pid = vfork();
|
||||
else
|
||||
new_pid = fork();
|
||||
|
||||
if (new_pid) {
|
||||
if (new_pid < 0)
|
||||
return errno;
|
||||
|
||||
if (pid)
|
||||
*pid = new_pid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & POSIX_SPAWN_SETSIGMASK) {
|
||||
if (sigprocmask(SIG_SETMASK, &attrp->__ss, NULL) != 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (flags & POSIX_SPAWN_SETSIGDEF) {
|
||||
/* We have to iterate over all signals. This could possibly be
|
||||
done better but it requires system specific solutions since
|
||||
the sigset_t data type can be very different on different
|
||||
architectures. */
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = SIG_DFL;
|
||||
|
||||
for (int sig = 1; sig <= _NSIG; ++sig) {
|
||||
if (sigismember(&attrp->__sd, sig)) {
|
||||
if (sigaction(sig, &sa, NULL) != 0)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & POSIX_SPAWN_SETSCHEDULER) {
|
||||
if (sched_setscheduler(0, attrp->__policy, &attrp->__sp) == -1)
|
||||
goto error;
|
||||
} else if (flags & POSIX_SPAWN_SETSCHEDPARAM) {
|
||||
if (sched_setparam(0, &attrp->__sp) == -1)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (flags & POSIX_SPAWN_SETPGROUP) {
|
||||
if (setpgid(0, attrp->__pgrp) != 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (flags & POSIX_SPAWN_RESETIDS) {
|
||||
if (seteuid(getuid()) || setegid(getgid()))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (fa && execute_file_actions(fa))
|
||||
goto error;
|
||||
|
||||
if (!path || strchr(file, '/')) {
|
||||
execve(file, argv, envp);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
char *name;
|
||||
{
|
||||
size_t filelen = strlen(file) + 1;
|
||||
size_t pathlen = strlen(path) + 1;
|
||||
name = alloca(pathlen + filelen);
|
||||
|
||||
/* Copy the file name at the top. */
|
||||
name = (char *) memcpy(name + pathlen, file, filelen);
|
||||
|
||||
/* And add the slash. */
|
||||
*--name = '/';
|
||||
}
|
||||
|
||||
char *p;
|
||||
do {
|
||||
char *startp;
|
||||
p = strchrnul(path, ':');
|
||||
|
||||
/* Two adjacent colons, or a colon at the beginning or the end
|
||||
of `PATH' means to search the current directory. */
|
||||
if (p == path)
|
||||
startp = name + 1;
|
||||
else
|
||||
startp = (char *) memcpy(name - (p - path), path, p - path);
|
||||
|
||||
execve(startp, argv, envp);
|
||||
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
case ENOENT:
|
||||
case ESTALE:
|
||||
case ENOTDIR:
|
||||
/* Those errors indicate the file is missing or not
|
||||
executable by us, in which case we want to just try
|
||||
the next path directory. */
|
||||
break;
|
||||
default:
|
||||
/* Some other error means we found an executable file,
|
||||
but something went wrong executing it; return the
|
||||
error to our caller. */
|
||||
goto error;
|
||||
}
|
||||
|
||||
path = p;
|
||||
} while (*p++ != '\0');
|
||||
|
||||
error:
|
||||
_exit(SPAWN_ERROR);
|
||||
}
|
||||
|
||||
/* Spawn a new process executing PATH with the attributes describes in *ATTRP.
|
||||
Before running the process perform the actions described in FILE-ACTIONS. */
|
||||
int posix_spawn (pid_t *pid, const char *path,
|
||||
const posix_spawn_file_actions_t *fa,
|
||||
const posix_spawnattr_t *attrp, char *const argv[],
|
||||
char *const envp[])
|
||||
{
|
||||
return __spawni(pid, path, fa, attrp, argv, envp, NULL);
|
||||
}
|
||||
|
||||
/* Spawn a new process executing FILE with the attributes describes in *ATTRP.
|
||||
Before running the process perform the actions described in FILE-ACTIONS. */
|
||||
int
|
||||
posix_spawnp(pid_t *pid, const char *file,
|
||||
const posix_spawn_file_actions_t *fa,
|
||||
const posix_spawnattr_t *attrp, char *const argv[],
|
||||
char *const envp[])
|
||||
{
|
||||
const char *path = getenv("PATH");
|
||||
|
||||
if (!path)
|
||||
path = ":/bin:/usr/bin";
|
||||
|
||||
return __spawni(pid, file, fa, attrp, argv, envp, path);
|
||||
}
|
51
librt/spawn_faction_addclose.c
Normal file
51
librt/spawn_faction_addclose.c
Normal file
@ -0,0 +1,51 @@
|
||||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <spawn.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "spawn_int.h"
|
||||
|
||||
/* Add an action to FILE-ACTIONS which tells the implementation to call
|
||||
`close' for the given file descriptor during the `spawn' call. */
|
||||
int
|
||||
posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions,
|
||||
int fd)
|
||||
{
|
||||
int maxfd = sysconf(_SC_OPEN_MAX);
|
||||
struct __spawn_action *rec;
|
||||
|
||||
/* Test for the validity of the file descriptor. */
|
||||
if (fd < 0 || fd >= maxfd)
|
||||
return EBADF;
|
||||
|
||||
/* Allocate more memory if needed. */
|
||||
if (file_actions->__used == file_actions->__allocated
|
||||
&& __posix_spawn_file_actions_realloc(file_actions) != 0)
|
||||
/* This can only mean we ran out of memory. */
|
||||
return ENOMEM;
|
||||
|
||||
/* Add the new value. */
|
||||
rec = &file_actions->__actions[file_actions->__used];
|
||||
rec->tag = spawn_do_close;
|
||||
rec->action.open_action.fd = fd;
|
||||
|
||||
/* Account for the new entry. */
|
||||
++file_actions->__used;
|
||||
return 0;
|
||||
}
|
52
librt/spawn_faction_adddup2.c
Normal file
52
librt/spawn_faction_adddup2.c
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <spawn.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "spawn_int.h"
|
||||
|
||||
/* Add an action to FILE-ACTIONS which tells the implementation to call
|
||||
`dup2' for the given file descriptors during the `spawn' call. */
|
||||
int
|
||||
posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions,
|
||||
int fd, int newfd)
|
||||
{
|
||||
int maxfd = sysconf(_SC_OPEN_MAX);
|
||||
struct __spawn_action *rec;
|
||||
|
||||
/* Test for the validity of the file descriptor. */
|
||||
if (fd < 0 || newfd < 0 || fd >= maxfd || newfd >= maxfd)
|
||||
return EBADF;
|
||||
|
||||
/* Allocate more memory if needed. */
|
||||
if (file_actions->__used == file_actions->__allocated
|
||||
&& __posix_spawn_file_actions_realloc (file_actions) != 0)
|
||||
/* This can only mean we ran out of memory. */
|
||||
return ENOMEM;
|
||||
|
||||
/* Add the new value. */
|
||||
rec = &file_actions->__actions[file_actions->__used];
|
||||
rec->tag = spawn_do_dup2;
|
||||
rec->action.dup2_action.fd = fd;
|
||||
rec->action.dup2_action.newfd = newfd;
|
||||
|
||||
/* Account for the new entry. */
|
||||
++file_actions->__used;
|
||||
return 0;
|
||||
}
|
55
librt/spawn_faction_addopen.c
Normal file
55
librt/spawn_faction_addopen.c
Normal file
@ -0,0 +1,55 @@
|
||||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <spawn.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "spawn_int.h"
|
||||
|
||||
/* Add an action to FILE-ACTIONS which tells the implementation to call
|
||||
`open' for the given file during the `spawn' call. */
|
||||
int
|
||||
posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *file_actions,
|
||||
int fd, const char *path, int oflag,
|
||||
mode_t mode)
|
||||
{
|
||||
int maxfd = sysconf(_SC_OPEN_MAX);
|
||||
struct __spawn_action *rec;
|
||||
|
||||
/* Test for the validity of the file descriptor. */
|
||||
if (fd < 0 || fd >= maxfd)
|
||||
return EBADF;
|
||||
|
||||
/* Allocate more memory if needed. */
|
||||
if (file_actions->__used == file_actions->__allocated
|
||||
&& __posix_spawn_file_actions_realloc (file_actions) != 0)
|
||||
/* This can only mean we ran out of memory. */
|
||||
return ENOMEM;
|
||||
|
||||
/* Add the new value. */
|
||||
rec = &file_actions->__actions[file_actions->__used];
|
||||
rec->tag = spawn_do_open;
|
||||
rec->action.open_action.fd = fd;
|
||||
rec->action.open_action.path = path;
|
||||
rec->action.open_action.oflag = oflag;
|
||||
rec->action.open_action.mode = mode;
|
||||
|
||||
/* Account for the new entry. */
|
||||
++file_actions->__used;
|
||||
return 0;
|
||||
}
|
42
librt/spawn_faction_init.c
Normal file
42
librt/spawn_faction_init.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <spawn.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "spawn_int.h"
|
||||
|
||||
|
||||
/* Function used to increase the size of the allocated array. This
|
||||
function is called from the `add'-functions. */
|
||||
int
|
||||
__posix_spawn_file_actions_realloc(posix_spawn_file_actions_t *file_actions)
|
||||
{
|
||||
int newalloc = file_actions->__allocated + 8;
|
||||
void *newmem = realloc(file_actions->__actions,
|
||||
newalloc * sizeof(struct __spawn_action));
|
||||
|
||||
if (newmem == NULL)
|
||||
/* Not enough memory. */
|
||||
return ENOMEM;
|
||||
|
||||
file_actions->__actions = (struct __spawn_action *)newmem;
|
||||
file_actions->__allocated = newalloc;
|
||||
return 0;
|
||||
}
|
26
librt/spawn_int.h
Normal file
26
librt/spawn_int.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* Data structure to contain the action information. */
|
||||
struct __spawn_action {
|
||||
enum {
|
||||
spawn_do_close,
|
||||
spawn_do_dup2,
|
||||
spawn_do_open
|
||||
} tag;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int fd;
|
||||
} close_action;
|
||||
struct {
|
||||
int fd;
|
||||
int newfd;
|
||||
} dup2_action;
|
||||
struct {
|
||||
int fd;
|
||||
const char *path;
|
||||
int oflag;
|
||||
mode_t mode;
|
||||
} open_action;
|
||||
} action;
|
||||
};
|
||||
|
||||
int __posix_spawn_file_actions_realloc(posix_spawn_file_actions_t *fa);
|
Loading…
x
Reference in New Issue
Block a user