diff options
Diffstat (limited to 'lib/libc/gen/posix_spawn.c')
-rw-r--r-- | lib/libc/gen/posix_spawn.c | 475 |
1 files changed, 0 insertions, 475 deletions
diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c deleted file mode 100644 index 20f2c16..0000000 --- a/lib/libc/gen/posix_spawn.c +++ /dev/null @@ -1,475 +0,0 @@ -/*- - * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <sys/queue.h> - -#include <errno.h> -#include <fcntl.h> -#include <sched.h> -#include <spawn.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "un-namespace.h" -#include "libc_private.h" - -extern char **environ; - -struct __posix_spawnattr { - short sa_flags; - pid_t sa_pgroup; - struct sched_param sa_schedparam; - int sa_schedpolicy; - sigset_t sa_sigdefault; - sigset_t sa_sigmask; -}; - -struct __posix_spawn_file_actions { - STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; -}; - -typedef struct __posix_spawn_file_actions_entry { - STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; - enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; - - int fae_fildes; - union { - struct { - char *path; -#define fae_path fae_data.open.path - int oflag; -#define fae_oflag fae_data.open.oflag - mode_t mode; -#define fae_mode fae_data.open.mode - } open; - struct { - int newfildes; -#define fae_newfildes fae_data.dup2.newfildes - } dup2; - } fae_data; -} posix_spawn_file_actions_entry_t; - -/* - * Spawn routines - */ - -static int -process_spawnattr(const posix_spawnattr_t sa) -{ - struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL }; - int i; - - /* - * POSIX doesn't really describe in which order everything - * should be set. We'll just set them in the order in which they - * are mentioned. - */ - - /* Set process group */ - if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) { - if (setpgid(0, sa->sa_pgroup) != 0) - return (errno); - } - - /* Set scheduler policy */ - if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) { - if (sched_setscheduler(0, sa->sa_schedpolicy, - &sa->sa_schedparam) != 0) - return (errno); - } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) { - if (sched_setparam(0, &sa->sa_schedparam) != 0) - return (errno); - } - - /* Reset user ID's */ - if (sa->sa_flags & POSIX_SPAWN_RESETIDS) { - if (setegid(getgid()) != 0) - return (errno); - if (seteuid(getuid()) != 0) - return (errno); - } - - /* Set signal masks/defaults */ - if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) { - _sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL); - } - - if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) { - for (i = 1; i <= _SIG_MAXSIG; i++) { - if (sigismember(&sa->sa_sigdefault, i)) - if (_sigaction(i, &sigact, NULL) != 0) - return (errno); - } - } - - return (0); -} - -static int -process_file_actions_entry(posix_spawn_file_actions_entry_t *fae) -{ - int fd; - - switch (fae->fae_action) { - case FAE_OPEN: - /* Perform an open(), make it use the right fd */ - fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); - if (fd < 0) - return (errno); - if (fd != fae->fae_fildes) { - if (_dup2(fd, fae->fae_fildes) == -1) - return (errno); - if (_close(fd) != 0) { - if (errno == EBADF) - return (EBADF); - } - } - if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1) - return (errno); - break; - case FAE_DUP2: - /* Perform a dup2() */ - if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1) - return (errno); - if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) - return (errno); - break; - case FAE_CLOSE: - /* Perform a close() */ - if (_close(fae->fae_fildes) != 0) { - if (errno == EBADF) - return (EBADF); - } - break; - } - return (0); -} - -static int -process_file_actions(const posix_spawn_file_actions_t fa) -{ - posix_spawn_file_actions_entry_t *fae; - int error; - - /* Replay all file descriptor modifications */ - STAILQ_FOREACH(fae, &fa->fa_list, fae_list) { - error = process_file_actions_entry(fae); - if (error) - return (error); - } - return (0); -} - -static int -do_posix_spawn(pid_t *pid, const char *path, - const posix_spawn_file_actions_t *fa, - const posix_spawnattr_t *sa, - char * const argv[], char * const envp[], int use_env_path) -{ - pid_t p; - volatile int error = 0; - - p = vfork(); - switch (p) { - case -1: - return (errno); - case 0: - if (sa != NULL) { - error = process_spawnattr(*sa); - if (error) - _exit(127); - } - if (fa != NULL) { - error = process_file_actions(*fa); - if (error) - _exit(127); - } - if (use_env_path) - _execvpe(path, argv, envp != NULL ? envp : environ); - else - _execve(path, argv, envp != NULL ? envp : environ); - error = errno; - _exit(127); - default: - if (pid != NULL) - *pid = p; - return (error); - } -} - -int -posix_spawn(pid_t *pid, const char *path, - const posix_spawn_file_actions_t *fa, - const posix_spawnattr_t *sa, - char * const argv[], char * const envp[]) -{ - return do_posix_spawn(pid, path, fa, sa, argv, envp, 0); -} - -int -posix_spawnp(pid_t *pid, const char *path, - const posix_spawn_file_actions_t *fa, - const posix_spawnattr_t *sa, - char * const argv[], char * const envp[]) -{ - return do_posix_spawn(pid, path, fa, sa, argv, envp, 1); -} - -/* - * File descriptor actions - */ - -int -posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret) -{ - posix_spawn_file_actions_t fa; - - fa = malloc(sizeof(struct __posix_spawn_file_actions)); - if (fa == NULL) - return (-1); - - STAILQ_INIT(&fa->fa_list); - *ret = fa; - return (0); -} - -int -posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) -{ - posix_spawn_file_actions_entry_t *fae; - - while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) { - /* Remove file action entry from the queue */ - STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); - - /* Deallocate file action entry */ - if (fae->fae_action == FAE_OPEN) - free(fae->fae_path); - free(fae); - } - - free(*fa); - return (0); -} - -int -posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, - int fildes, const char * __restrict path, int oflag, mode_t mode) -{ - posix_spawn_file_actions_entry_t *fae; - int error; - - if (fildes < 0) - return (EBADF); - - /* Allocate object */ - fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); - if (fae == NULL) - return (errno); - - /* Set values and store in queue */ - fae->fae_action = FAE_OPEN; - fae->fae_path = strdup(path); - if (fae->fae_path == NULL) { - error = errno; - free(fae); - return (error); - } - fae->fae_fildes = fildes; - fae->fae_oflag = oflag; - fae->fae_mode = mode; - - STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); - return (0); -} - -int -posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, - int fildes, int newfildes) -{ - posix_spawn_file_actions_entry_t *fae; - - if (fildes < 0 || newfildes < 0) - return (EBADF); - - /* Allocate object */ - fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); - if (fae == NULL) - return (errno); - - /* Set values and store in queue */ - fae->fae_action = FAE_DUP2; - fae->fae_fildes = fildes; - fae->fae_newfildes = newfildes; - - STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); - return (0); -} - -int -posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, - int fildes) -{ - posix_spawn_file_actions_entry_t *fae; - - if (fildes < 0) - return (EBADF); - - /* Allocate object */ - fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); - if (fae == NULL) - return (errno); - - /* Set values and store in queue */ - fae->fae_action = FAE_CLOSE; - fae->fae_fildes = fildes; - - STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); - return (0); -} - -/* - * Spawn attributes - */ - -int -posix_spawnattr_init(posix_spawnattr_t *ret) -{ - posix_spawnattr_t sa; - - sa = calloc(1, sizeof(struct __posix_spawnattr)); - if (sa == NULL) - return (errno); - - /* Set defaults as specified by POSIX, cleared above */ - *ret = sa; - return (0); -} - -int -posix_spawnattr_destroy(posix_spawnattr_t *sa) -{ - free(*sa); - return (0); -} - -int -posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa, - short * __restrict flags) -{ - *flags = (*sa)->sa_flags; - return (0); -} - -int -posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa, - pid_t * __restrict pgroup) -{ - *pgroup = (*sa)->sa_pgroup; - return (0); -} - -int -posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa, - struct sched_param * __restrict schedparam) -{ - *schedparam = (*sa)->sa_schedparam; - return (0); -} - -int -posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa, - int * __restrict schedpolicy) -{ - *schedpolicy = (*sa)->sa_schedpolicy; - return (0); -} - -int -posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa, - sigset_t * __restrict sigdefault) -{ - *sigdefault = (*sa)->sa_sigdefault; - return (0); -} - -int -posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa, - sigset_t * __restrict sigmask) -{ - *sigmask = (*sa)->sa_sigmask; - return (0); -} - -int -posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) -{ - (*sa)->sa_flags = flags; - return (0); -} - -int -posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup) -{ - (*sa)->sa_pgroup = pgroup; - return (0); -} - -int -posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa, - const struct sched_param * __restrict schedparam) -{ - (*sa)->sa_schedparam = *schedparam; - return (0); -} - -int -posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy) -{ - (*sa)->sa_schedpolicy = schedpolicy; - return (0); -} - -int -posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa, - const sigset_t * __restrict sigdefault) -{ - (*sa)->sa_sigdefault = *sigdefault; - return (0); -} - -int -posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa, - const sigset_t * __restrict sigmask) -{ - (*sa)->sa_sigmask = *sigmask; - return (0); -} |