# HG changeset patch # User Rob Landley # Date 1373522072 18000 # Node ID dad40f8a408d747b998312505ac33ebbb21065d3 # Parent ee6db9e5cce3bbea9c81240d96c3e6cef0755c65 Add some stuff John Spencer needed so sabotage can bootstrap itself. diff -r ee6db9e5cce3 -r dad40f8a408d sources/baseconfig-busybox --- a/sources/baseconfig-busybox Thu Jul 11 00:29:06 2013 -0500 +++ b/sources/baseconfig-busybox Thu Jul 11 00:54:32 2013 -0500 @@ -135,6 +135,11 @@ CONFIG_LSPCI=y CONFIG_PING=y +CONFIG_SHA512SUM=y +CONFIG_FDISK=y +CONFIG_FEATURE_FDISK_WRITABLE=y +CONFIG_FEATURE_FDISK_ADVANCED=y + # Stuff in toybox CONFIG_CAT=y diff -r ee6db9e5cce3 -r dad40f8a408d sources/patches/uClibc-posix_spawn.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sources/patches/uClibc-posix_spawn.patch Thu Jul 11 00:54:32 2013 -0500 @@ -0,0 +1,830 @@ +Sabotage needs posix_spawn to bootstrap musl. + +Upstream, uClibc added posix_spawn and did it horribly. It's a straight copy +from glibc, checked in before 0.9.33.2 released but not _in_ 0.9.33.2. Commit +a969b3f3c08e removed the "we have this" indicator from the headers, but +then commit 0dcf66744f53 didn't add it back... + + +diff -ruN uClibc/include/spawn.h uClibc.bak/include/spawn.h +--- uClibc/include/spawn.h 1969-12-31 18:00:00.000000000 -0600 ++++ uClibc.bak/include/spawn.h 2013-07-11 00:04:24.024324269 -0500 +@@ -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 ++ . */ ++ ++#ifndef _SPAWN_H ++#define _SPAWN_H 1 ++ ++#include ++#include ++#include ++ ++#include ++#include ++#define __need_sigset_t ++#include ++#include ++ ++ ++/* 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 -ruN uClibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h uClibc.bak/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h +--- uClibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-05-15 02:20:09.000000000 -0500 ++++ uClibc.bak/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h 2013-07-10 21:49:10.087986094 -0500 +@@ -149,10 +149,8 @@ + /* We support spinlocks. */ + #define _POSIX_SPIN_LOCKS 200809L + +-#if 0 /* no support in uClibc (yet) */ + /* The `spawn' function family is supported. */ + #define _POSIX_SPAWN 200809L +-#endif + + /* We have POSIX timers. */ + #define _POSIX_TIMERS 200809L +diff -ruN uClibc/librt/Makefile.in uClibc.bak/librt/Makefile.in +--- uClibc/librt/Makefile.in 2012-05-15 02:20:09.000000000 -0500 ++++ uClibc.bak/librt/Makefile.in 2013-07-10 21:48:33.191984555 -0500 +@@ -33,6 +33,14 @@ + 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 -ruN uClibc/librt/spawn.c uClibc.bak/librt/spawn.c +--- uClibc/librt/spawn.c 1969-12-31 18:00:00.000000000 -0600 ++++ uClibc.bak/librt/spawn.c 2013-07-10 21:48:33.191984555 -0500 +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#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 -ruN uClibc/librt/spawn_faction_addclose.c uClibc.bak/librt/spawn_faction_addclose.c +--- uClibc/librt/spawn_faction_addclose.c 1969-12-31 18:00:00.000000000 -0600 ++++ uClibc.bak/librt/spawn_faction_addclose.c 2013-07-10 21:48:33.191984555 -0500 +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++ ++#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 -ruN uClibc/librt/spawn_faction_adddup2.c uClibc.bak/librt/spawn_faction_adddup2.c +--- uClibc/librt/spawn_faction_adddup2.c 1969-12-31 18:00:00.000000000 -0600 ++++ uClibc.bak/librt/spawn_faction_adddup2.c 2013-07-10 21:48:33.219984556 -0500 +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++ ++#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 -ruN uClibc/librt/spawn_faction_addopen.c uClibc.bak/librt/spawn_faction_addopen.c +--- uClibc/librt/spawn_faction_addopen.c 1969-12-31 18:00:00.000000000 -0600 ++++ uClibc.bak/librt/spawn_faction_addopen.c 2013-07-10 21:48:33.219984556 -0500 +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++ ++#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 -ruN uClibc/librt/spawn_faction_init.c uClibc.bak/librt/spawn_faction_init.c +--- uClibc/librt/spawn_faction_init.c 1969-12-31 18:00:00.000000000 -0600 ++++ uClibc.bak/librt/spawn_faction_init.c 2013-07-10 21:48:33.219984556 -0500 +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++#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 -ruN uClibc/librt/spawn_int.h uClibc.bak/librt/spawn_int.h +--- uClibc/librt/spawn_int.h 1969-12-31 18:00:00.000000000 -0600 ++++ uClibc.bak/librt/spawn_int.h 2013-07-10 21:48:33.219984556 -0500 +@@ -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); +diff -ruN uClibc/Makefile.in uClibc.bak/Makefile.in +--- uClibc/Makefile.in 2013-07-11 00:46:58.388430731 -0500 ++++ uClibc.bak/Makefile.in 2013-07-10 21:48:33.187984555 -0500 +@@ -293,6 +293,7 @@ + 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)):