diff options
Diffstat (limited to 'main/libc0.9.32/0001-librt-add-posix_spawn-support.patch')
-rw-r--r-- | main/libc0.9.32/0001-librt-add-posix_spawn-support.patch | 853 |
1 files changed, 853 insertions, 0 deletions
diff --git a/main/libc0.9.32/0001-librt-add-posix_spawn-support.patch b/main/libc0.9.32/0001-librt-add-posix_spawn-support.patch new file mode 100644 index 0000000000..29725529ce --- /dev/null +++ b/main/libc0.9.32/0001-librt-add-posix_spawn-support.patch @@ -0,0 +1,853 @@ +From 0dcf66744f533e160232072bd03273ca1c448879 Mon Sep 17 00:00:00 2001 +From: Ismael Luceno <ismael.luceno@gmail.com> +Date: Mon, 5 Mar 2012 06:43:49 -0200 +Subject: [PATCH] librt: add posix_spawn support + +Signed-off-by: Ismael Luceno <ismael.luceno@gmail.com> +Signed-off-by: Mike Frysinger <vapier@gentoo.org> +--- + Makefile.in | 1 + + include/spawn.h | 266 +++++++++++++++++++++++++++++++++++++++++ + librt/Makefile.in | 8 ++ + librt/spawn.c | 259 +++++++++++++++++++++++++++++++++++++++ + librt/spawn_faction_addclose.c | 51 ++++++++ + librt/spawn_faction_adddup2.c | 52 ++++++++ + librt/spawn_faction_addopen.c | 55 +++++++++ + librt/spawn_faction_init.c | 42 +++++++ + librt/spawn_int.h | 26 ++++ + 9 files changed, 760 insertions(+) + create mode 100644 include/spawn.h + create mode 100644 librt/spawn.c + create mode 100644 librt/spawn_faction_addclose.c + create mode 100644 librt/spawn_faction_adddup2.c + create mode 100644 librt/spawn_faction_addopen.c + create mode 100644 librt/spawn_faction_init.c + create mode 100644 librt/spawn_int.h + +diff --git a/Makefile.in b/Makefile.in +index d0ac6c0..82a2eff 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -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)): +diff --git a/include/spawn.h b/include/spawn.h +new file mode 100644 +index 0000000..8b07bb8 +--- /dev/null ++++ b/include/spawn.h +@@ -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 */ +diff --git a/librt/Makefile.in b/librt/Makefile.in +index 909afd8..857efb5 100644 +--- a/librt/Makefile.in ++++ b/librt/Makefile.in +@@ -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)) +diff --git a/librt/spawn.c b/librt/spawn.c +new file mode 100644 +index 0000000..b5935a1 +--- /dev/null ++++ b/librt/spawn.c +@@ -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); ++} +diff --git a/librt/spawn_faction_addclose.c b/librt/spawn_faction_addclose.c +new file mode 100644 +index 0000000..b418f96 +--- /dev/null ++++ b/librt/spawn_faction_addclose.c +@@ -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; ++} +diff --git a/librt/spawn_faction_adddup2.c b/librt/spawn_faction_adddup2.c +new file mode 100644 +index 0000000..6d73313 +--- /dev/null ++++ b/librt/spawn_faction_adddup2.c +@@ -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; ++} +diff --git a/librt/spawn_faction_addopen.c b/librt/spawn_faction_addopen.c +new file mode 100644 +index 0000000..285ca71 +--- /dev/null ++++ b/librt/spawn_faction_addopen.c +@@ -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; ++} +diff --git a/librt/spawn_faction_init.c b/librt/spawn_faction_init.c +new file mode 100644 +index 0000000..fb398a5 +--- /dev/null ++++ b/librt/spawn_faction_init.c +@@ -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; ++} +diff --git a/librt/spawn_int.h b/librt/spawn_int.h +new file mode 100644 +index 0000000..89c88db +--- /dev/null ++++ b/librt/spawn_int.h +@@ -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); +-- +1.8.4 + |