diff options
Diffstat (limited to 'lib/mlibc/options/posix/generic/spawn-stubs.cpp')
-rw-r--r-- | lib/mlibc/options/posix/generic/spawn-stubs.cpp | 376 |
1 files changed, 0 insertions, 376 deletions
diff --git a/lib/mlibc/options/posix/generic/spawn-stubs.cpp b/lib/mlibc/options/posix/generic/spawn-stubs.cpp deleted file mode 100644 index cf7edfc..0000000 --- a/lib/mlibc/options/posix/generic/spawn-stubs.cpp +++ /dev/null @@ -1,376 +0,0 @@ - -#include <spawn.h> -#include <errno.h> -#include <pthread.h> -#include <fcntl.h> -#include <unistd.h> -#include <limits.h> -#include <sched.h> -#include <stdlib.h> -#include <signal.h> -#include <sys/wait.h> - -#include <bits/ensure.h> -#include <mlibc/debug.hpp> - -/* - * Musl places this in a seperate header called fdop.h - * This header isn't present in glibc, or on my host, so I - * include it's contents here - */ - -#define FDOP_CLOSE 1 -#define FDOP_DUP2 2 -#define FDOP_OPEN 3 -#define FDOP_CHDIR 4 -#define FDOP_FCHDIR 5 - -struct fdop { - struct fdop *next, *prev; - int cmd, fd, srcfd, oflag; - mode_t mode; - char path[]; -}; - -/* - * This posix_spawn implementation is taken from musl - */ - -static unsigned long handler_set[NSIG / (8 * sizeof(long))]; - -static void __get_handler_set(sigset_t *set) { - memcpy(set, handler_set, sizeof handler_set); -} - -struct args { - int p[2]; - sigset_t oldmask; - const char *path; - const posix_spawn_file_actions_t *fa; - const posix_spawnattr_t *__restrict attr; - char *const *argv, *const *envp; -}; - -static int child(void *args_vp) { - int i, ret; - struct sigaction sa = {}; - struct args *args = (struct args *)args_vp; - int p = args->p[1]; - const posix_spawn_file_actions_t *fa = args->fa; - const posix_spawnattr_t *__restrict attr = args->attr; - sigset_t hset; - bool use_execvpe = false; - - if(attr->__fn) - use_execvpe = true; - - close(args->p[0]); - - /* All signal dispositions must be either SIG_DFL or SIG_IGN - * before signals are unblocked. Otherwise a signal handler - * from the parent might get run in the child while sharing - * memory, with unpredictable and dangerous results. To - * reduce overhead, sigaction has tracked for us which signals - * potentially have a signal handler. */ - __get_handler_set(&hset); - for(i = 1; i < NSIG; i++) { - if((attr->__flags & POSIX_SPAWN_SETSIGDEF) && sigismember(&attr->__def, i)) { - sa.sa_handler = SIG_DFL; - } else if(sigismember(&hset, i)) { - if (i - 32 < 3) { - sa.sa_handler = SIG_IGN; - } else {; - sigaction(i, 0, &sa); - if(sa.sa_handler == SIG_IGN) - continue; - sa.sa_handler = SIG_DFL; - } - } else { - continue; - } - sigaction(i, &sa, 0); - } - - if(attr->__flags & POSIX_SPAWN_SETSID) { - if((ret = setsid()) < 0) - goto fail; - } - - if(attr->__flags & POSIX_SPAWN_SETPGROUP) { - mlibc::infoLogger() << "mlibc: posix_spawn: ignoring SETPGROUP" << frg::endlog; - //if((ret = setpgid(0, attr->__pgrp))) - // goto fail; - } - - if(attr->__flags & POSIX_SPAWN_RESETIDS) { - if((ret = setgid(getgid())) || (ret = setuid(getuid())) ) - goto fail; - } - - if(fa && fa->__actions) { - struct fdop *op; - int fd; - for(op = (struct fdop *)fa->__actions; op->next; op = op->next); - for(; op; op = op->prev) { - /* It's possible that a file operation would clobber - * the pipe fd used for synchronizing with the - * parent. To avoid that, we dup the pipe onto - * an unoccupied fd. */ - if(op->fd == p) { - ret = dup(p); - if(ret < 0) - goto fail; - close(p); - p = ret; - } - switch(op->cmd) { - case FDOP_CLOSE: - close(op->fd); - break; - case FDOP_DUP2: - fd = op->srcfd; - if(fd == p) { - ret = -EBADF; - goto fail; - } - if(fd != op->fd) { - if((ret = dup2(fd, op->fd)) < 0) - goto fail; - } else { - ret = fcntl(fd, F_GETFD); - ret = fcntl(fd, F_SETFD, ret & ~FD_CLOEXEC); - if(ret < 0) - goto fail; - } - break; - case FDOP_OPEN: - fd = open(op->path, op->oflag, op->mode); - if((ret = fd) < 0) - goto fail; - if(fd != op->fd) { - if((ret = dup2(fd, op->fd)) < 0) - goto fail; - close(fd); - } - break; - case FDOP_CHDIR: - ret = chdir(op->path); - if(ret < 0) - goto fail; - break; - case FDOP_FCHDIR: - ret = fchdir(op->fd); - if(ret < 0) - goto fail; - break; - } - } - } - - /* Close-on-exec flag may have been lost if we moved the pipe - * to a different fd. */ - fcntl(p, F_SETFD, FD_CLOEXEC); - - pthread_sigmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) - ? &attr->__mask : &args->oldmask, 0); - - if(use_execvpe) - execvpe(args->path, args->argv, args->envp); - else - execve(args->path, args->argv, args->envp); - ret = -errno; - -fail: - /* Since sizeof errno < PIPE_BUF, the write is atomic. */ - ret = -ret; - if(ret) - while(write(p, &ret, sizeof ret) < 0); - _exit(127); -} - -int posix_spawn(pid_t *__restrict res, const char *__restrict path, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *__restrict attrs, - char *const argv[], char *const envp[]) { - pid_t pid; - int ec = 0, cs; - struct args args; - const posix_spawnattr_t empty_attr = {}; - sigset_t full_sigset; - sigfillset(&full_sigset); - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - - args.path = path; - args.fa = file_actions; - args.attr = attrs ? attrs : &empty_attr; - args.argv = argv; - args.envp = envp; - pthread_sigmask(SIG_BLOCK, &full_sigset, &args.oldmask); - - /* The lock guards both against seeing a SIGABRT disposition change - * by abort and against leaking the pipe fd to fork-without-exec. */ - //LOCK(__abort_lock); - - if(pipe2(args.p, O_CLOEXEC)) { - //UNLOCK(__abort_lock); - ec = errno; - goto fail; - } - - /* Mlibc change: We use fork + execve, as clone is not implemented. - * This yields the same result in the end. */ - //pid = clone(child, stack + sizeof stack, CLONE_VM | CLONE_VFORK | SIGCHLD, &args); - pid = fork(); - if(!pid) { - child(&args); - } - close(args.p[1]); - //UNLOCK(__abort_lock); - - if(pid > 0) { - if(read(args.p[0], &ec, sizeof ec) != sizeof ec) - ec = 0; - else - waitpid(pid, 0, 0); - } else { - ec = -pid; - } - - close(args.p[0]); - - if(!ec && res) - *res = pid; - -fail: - pthread_sigmask(SIG_SETMASK, &args.oldmask, 0); - pthread_setcancelstate(cs, 0); - - return ec; -} - -int posix_spawnattr_init(posix_spawnattr_t *attr) { - *attr = (posix_spawnattr_t){}; - return 0; -} - -int posix_spawnattr_destroy(posix_spawnattr_t *) { - return 0; -} - -int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) { - const unsigned all_flags = - POSIX_SPAWN_RESETIDS | - POSIX_SPAWN_SETPGROUP | - POSIX_SPAWN_SETSIGDEF | - POSIX_SPAWN_SETSIGMASK | - POSIX_SPAWN_SETSCHEDPARAM | - POSIX_SPAWN_SETSCHEDULER | - POSIX_SPAWN_USEVFORK | - POSIX_SPAWN_SETSID; - if(flags & ~all_flags) - return EINVAL; - attr->__flags = flags; - return 0; -} - -int posix_spawnattr_setsigdefault(posix_spawnattr_t *__restrict attr, - const sigset_t *__restrict sigdefault) { - attr->__def = *sigdefault; - return 0; -} - -int posix_spawnattr_setschedparam(posix_spawnattr_t *__restrict, - const struct sched_param *__restrict) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -int posix_spawnattr_setsigmask(posix_spawnattr_t *__restrict attr, - const sigset_t *__restrict sigmask) { - attr->__mask = *sigmask; - return 0; -} - -int posix_spawnattr_setpgroup(posix_spawnattr_t *attr, pid_t pgroup) { - attr->__pgrp = pgroup; - return 0; -} - -int posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions) { - file_actions->__actions = 0; - return 0; -} - -int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions) { - struct fdop *op = (struct fdop *)file_actions->__actions, *next; - while(op) { - next = op->next; - free(op); - op = next; - } - return 0; -} - -int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions, - int fildes, int newfildes) { - struct fdop *op = (struct fdop *)malloc(sizeof *op); - if(!op) - return ENOMEM; - op->cmd = FDOP_DUP2; - op->srcfd = fildes; - op->fd = newfildes; - if((op->next = (struct fdop *)file_actions->__actions)) - op->next->prev = op; - op->prev = 0; - file_actions->__actions = op; - return 0; -} - -int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions, - int fildes) { - struct fdop *op = (struct fdop *)malloc(sizeof *op); - if(!op) - return ENOMEM; - op->cmd = FDOP_CLOSE; - op->fd = fildes; - if((op->next = (struct fdop *)file_actions->__actions)) - op->next->prev = op; - op->prev = 0; - file_actions->__actions = op; - return 0; -} - -int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *__restrict file_actions, - int fildes, const char *__restrict path, int oflag, mode_t mode) { - struct fdop *op = (struct fdop *)malloc(sizeof *op + strlen(path) + 1); - if(!op) - return ENOMEM; - op->cmd = FDOP_OPEN; - op->fd = fildes; - op->oflag = oflag; - op->mode = mode; - strcpy(op->path, path); - if((op->next = (struct fdop *)file_actions->__actions)) - op->next->prev = op; - op->prev = 0; - file_actions->__actions = op; - return 0; -} - -int posix_spawnp(pid_t *__restrict pid, const char *__restrict file, - const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *__restrict attrp, - char *const argv[], char *const envp[]) { - posix_spawnattr_t spawnp_attr = {}; - if(attrp) - spawnp_attr = *attrp; - spawnp_attr.__fn = (void *)execvpe; - return posix_spawn(pid, file, file_actions, &spawnp_attr, argv, envp); -} - |