diff options
Diffstat (limited to 'libc-top-half/musl/src/process')
41 files changed, 893 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/process/_Fork.c b/libc-top-half/musl/src/process/_Fork.c new file mode 100644 index 0000000..da06386 --- /dev/null +++ b/libc-top-half/musl/src/process/_Fork.c @@ -0,0 +1,38 @@ +#include <unistd.h> +#include <signal.h> +#include "syscall.h" +#include "libc.h" +#include "lock.h" +#include "pthread_impl.h" +#include "aio_impl.h" + +static void dummy(int x) { } +weak_alias(dummy, __aio_atfork); + +pid_t _Fork(void) +{ + pid_t ret; + sigset_t set; + __block_all_sigs(&set); + __aio_atfork(-1); + LOCK(__abort_lock); +#ifdef SYS_fork + ret = __syscall(SYS_fork); +#else + ret = __syscall(SYS_clone, SIGCHLD, 0); +#endif + if (!ret) { + pthread_t self = __pthread_self(); + self->tid = __syscall(SYS_gettid); + self->robust_list.off = 0; + self->robust_list.pending = 0; + self->next = self->prev = self; + __thread_list_lock = 0; + libc.threads_minus_1 = 0; + if (libc.need_locks) libc.need_locks = -1; + } + UNLOCK(__abort_lock); + __aio_atfork(!ret); + __restore_sigs(&set); + return __syscall_ret(ret); +} diff --git a/libc-top-half/musl/src/process/arm/vfork.s b/libc-top-half/musl/src/process/arm/vfork.s new file mode 100644 index 0000000..d7ec41b --- /dev/null +++ b/libc-top-half/musl/src/process/arm/vfork.s @@ -0,0 +1,10 @@ +.syntax unified +.global vfork +.type vfork,%function +vfork: + mov ip, r7 + mov r7, 190 + svc 0 + mov r7, ip + .hidden __syscall_ret + b __syscall_ret diff --git a/libc-top-half/musl/src/process/execl.c b/libc-top-half/musl/src/process/execl.c new file mode 100644 index 0000000..5ee5c81 --- /dev/null +++ b/libc-top-half/musl/src/process/execl.c @@ -0,0 +1,22 @@ +#include <unistd.h> +#include <stdarg.h> + +int execl(const char *path, const char *argv0, ...) +{ + int argc; + va_list ap; + va_start(ap, argv0); + for (argc=1; va_arg(ap, const char *); argc++); + va_end(ap); + { + int i; + char *argv[argc+1]; + va_start(ap, argv0); + argv[0] = (char *)argv0; + for (i=1; i<argc; i++) + argv[i] = va_arg(ap, char *); + argv[i] = NULL; + va_end(ap); + return execv(path, argv); + } +} diff --git a/libc-top-half/musl/src/process/execle.c b/libc-top-half/musl/src/process/execle.c new file mode 100644 index 0000000..37ca503 --- /dev/null +++ b/libc-top-half/musl/src/process/execle.c @@ -0,0 +1,23 @@ +#include <unistd.h> +#include <stdarg.h> + +int execle(const char *path, const char *argv0, ...) +{ + int argc; + va_list ap; + va_start(ap, argv0); + for (argc=1; va_arg(ap, const char *); argc++); + va_end(ap); + { + int i; + char *argv[argc+1]; + char **envp; + va_start(ap, argv0); + argv[0] = (char *)argv0; + for (i=1; i<=argc; i++) + argv[i] = va_arg(ap, char *); + envp = va_arg(ap, char **); + va_end(ap); + return execve(path, argv, envp); + } +} diff --git a/libc-top-half/musl/src/process/execlp.c b/libc-top-half/musl/src/process/execlp.c new file mode 100644 index 0000000..5eed886 --- /dev/null +++ b/libc-top-half/musl/src/process/execlp.c @@ -0,0 +1,22 @@ +#include <unistd.h> +#include <stdarg.h> + +int execlp(const char *file, const char *argv0, ...) +{ + int argc; + va_list ap; + va_start(ap, argv0); + for (argc=1; va_arg(ap, const char *); argc++); + va_end(ap); + { + int i; + char *argv[argc+1]; + va_start(ap, argv0); + argv[0] = (char *)argv0; + for (i=1; i<argc; i++) + argv[i] = va_arg(ap, char *); + argv[i] = NULL; + va_end(ap); + return execvp(file, argv); + } +} diff --git a/libc-top-half/musl/src/process/execv.c b/libc-top-half/musl/src/process/execv.c new file mode 100644 index 0000000..2ac0dec --- /dev/null +++ b/libc-top-half/musl/src/process/execv.c @@ -0,0 +1,8 @@ +#include <unistd.h> + +extern char **__environ; + +int execv(const char *path, char *const argv[]) +{ + return execve(path, argv, __environ); +} diff --git a/libc-top-half/musl/src/process/execve.c b/libc-top-half/musl/src/process/execve.c new file mode 100644 index 0000000..70286a1 --- /dev/null +++ b/libc-top-half/musl/src/process/execve.c @@ -0,0 +1,8 @@ +#include <unistd.h> +#include "syscall.h" + +int execve(const char *path, char *const argv[], char *const envp[]) +{ + /* do we need to use environ if envp is null? */ + return syscall(SYS_execve, path, argv, envp); +} diff --git a/libc-top-half/musl/src/process/execvp.c b/libc-top-half/musl/src/process/execvp.c new file mode 100644 index 0000000..ef3b9dd --- /dev/null +++ b/libc-top-half/musl/src/process/execvp.c @@ -0,0 +1,60 @@ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <limits.h> + +extern char **__environ; + +int __execvpe(const char *file, char *const argv[], char *const envp[]) +{ + const char *p, *z, *path = getenv("PATH"); + size_t l, k; + int seen_eacces = 0; + + errno = ENOENT; + if (!*file) return -1; + + if (strchr(file, '/')) + return execve(file, argv, envp); + + if (!path) path = "/usr/local/bin:/bin:/usr/bin"; + k = strnlen(file, NAME_MAX+1); + if (k > NAME_MAX) { + errno = ENAMETOOLONG; + return -1; + } + l = strnlen(path, PATH_MAX-1)+1; + + for(p=path; ; p=z) { + char b[l+k+1]; + z = __strchrnul(p, ':'); + if (z-p >= l) { + if (!*z++) break; + continue; + } + memcpy(b, p, z-p); + b[z-p] = '/'; + memcpy(b+(z-p)+(z>p), file, k+1); + execve(b, argv, envp); + switch (errno) { + case EACCES: + seen_eacces = 1; + case ENOENT: + case ENOTDIR: + break; + default: + return -1; + } + if (!*z++) break; + } + if (seen_eacces) errno = EACCES; + return -1; +} + +int execvp(const char *file, char *const argv[]) +{ + return __execvpe(file, argv, __environ); +} + +weak_alias(__execvpe, execvpe); diff --git a/libc-top-half/musl/src/process/fdop.h b/libc-top-half/musl/src/process/fdop.h new file mode 100644 index 0000000..7cf733b --- /dev/null +++ b/libc-top-half/musl/src/process/fdop.h @@ -0,0 +1,17 @@ +#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[]; +}; + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc undef +#define free __libc_free diff --git a/libc-top-half/musl/src/process/fexecve.c b/libc-top-half/musl/src/process/fexecve.c new file mode 100644 index 0000000..554c198 --- /dev/null +++ b/libc-top-half/musl/src/process/fexecve.c @@ -0,0 +1,16 @@ +#define _GNU_SOURCE +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include "syscall.h" + +int fexecve(int fd, char *const argv[], char *const envp[]) +{ + int r = __syscall(SYS_execveat, fd, "", argv, envp, AT_EMPTY_PATH); + if (r != -ENOSYS) return __syscall_ret(r); + char buf[15 + 3*sizeof(int)]; + __procfdname(buf, fd); + execve(buf, argv, envp); + if (errno == ENOENT) errno = EBADF; + return -1; +} diff --git a/libc-top-half/musl/src/process/fork.c b/libc-top-half/musl/src/process/fork.c new file mode 100644 index 0000000..54bc289 --- /dev/null +++ b/libc-top-half/musl/src/process/fork.c @@ -0,0 +1,86 @@ +#include <unistd.h> +#include <errno.h> +#include "libc.h" +#include "lock.h" +#include "pthread_impl.h" +#include "fork_impl.h" + +static volatile int *const dummy_lockptr = 0; + +weak_alias(dummy_lockptr, __at_quick_exit_lockptr); +weak_alias(dummy_lockptr, __atexit_lockptr); +weak_alias(dummy_lockptr, __dlerror_lockptr); +weak_alias(dummy_lockptr, __gettext_lockptr); +weak_alias(dummy_lockptr, __locale_lockptr); +weak_alias(dummy_lockptr, __random_lockptr); +weak_alias(dummy_lockptr, __sem_open_lockptr); +weak_alias(dummy_lockptr, __stdio_ofl_lockptr); +weak_alias(dummy_lockptr, __syslog_lockptr); +weak_alias(dummy_lockptr, __timezone_lockptr); +weak_alias(dummy_lockptr, __bump_lockptr); + +weak_alias(dummy_lockptr, __vmlock_lockptr); + +static volatile int *const *const atfork_locks[] = { + &__at_quick_exit_lockptr, + &__atexit_lockptr, + &__dlerror_lockptr, + &__gettext_lockptr, + &__locale_lockptr, + &__random_lockptr, + &__sem_open_lockptr, + &__stdio_ofl_lockptr, + &__syslog_lockptr, + &__timezone_lockptr, + &__bump_lockptr, +}; + +static void dummy(int x) { } +weak_alias(dummy, __fork_handler); +weak_alias(dummy, __malloc_atfork); +weak_alias(dummy, __ldso_atfork); + +static void dummy_0(void) { } +weak_alias(dummy_0, __tl_lock); +weak_alias(dummy_0, __tl_unlock); + +pid_t fork(void) +{ + sigset_t set; + __fork_handler(-1); + __block_app_sigs(&set); + int need_locks = libc.need_locks > 0; + if (need_locks) { + __ldso_atfork(-1); + __inhibit_ptc(); + for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++) + if (*atfork_locks[i]) LOCK(*atfork_locks[i]); + __malloc_atfork(-1); + __tl_lock(); + } + pthread_t self=__pthread_self(), next=self->next; + pid_t ret = _Fork(); + int errno_save = errno; + if (need_locks) { + if (!ret) { + for (pthread_t td=next; td!=self; td=td->next) + td->tid = -1; + if (__vmlock_lockptr) { + __vmlock_lockptr[0] = 0; + __vmlock_lockptr[1] = 0; + } + } + __tl_unlock(); + __malloc_atfork(!ret); + for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++) + if (*atfork_locks[i]) + if (ret) UNLOCK(*atfork_locks[i]); + else **atfork_locks[i] = 0; + __release_ptc(); + __ldso_atfork(!ret); + } + __restore_sigs(&set); + __fork_handler(!ret); + if (ret<0) errno = errno_save; + return ret; +} diff --git a/libc-top-half/musl/src/process/i386/vfork.s b/libc-top-half/musl/src/process/i386/vfork.s new file mode 100644 index 0000000..3d0e6d6 --- /dev/null +++ b/libc-top-half/musl/src/process/i386/vfork.s @@ -0,0 +1,12 @@ +.global vfork +.type vfork,@function +vfork: + pop %edx + mov $190,%eax + int $128 + push %edx + push %eax + .hidden __syscall_ret + call __syscall_ret + pop %edx + ret diff --git a/libc-top-half/musl/src/process/posix_spawn.c b/libc-top-half/musl/src/process/posix_spawn.c new file mode 100644 index 0000000..728551b --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn.c @@ -0,0 +1,214 @@ +#define _GNU_SOURCE +#include <spawn.h> +#include <sched.h> +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/wait.h> +#include "syscall.h" +#include "lock.h" +#include "pthread_impl.h" +#include "fdop.h" + +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 __sys_dup2(int old, int new) +{ +#ifdef SYS_dup2 + return __syscall(SYS_dup2, old, new); +#else + return __syscall(SYS_dup3, old, new, 0); +#endif +} + +static int child(void *args_vp) +{ + int i, ret; + struct sigaction sa = {0}; + struct args *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; + + 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<3U) { + sa.sa_handler = SIG_IGN; + } else { + __libc_sigaction(i, 0, &sa); + if (sa.sa_handler==SIG_IGN) continue; + sa.sa_handler = SIG_DFL; + } + } else { + continue; + } + __libc_sigaction(i, &sa, 0); + } + + if (attr->__flags & POSIX_SPAWN_SETSID) + if ((ret=__syscall(SYS_setsid)) < 0) + goto fail; + + if (attr->__flags & POSIX_SPAWN_SETPGROUP) + if ((ret=__syscall(SYS_setpgid, 0, attr->__pgrp))) + goto fail; + + /* Use syscalls directly because the library functions attempt + * to do a multi-threaded synchronized id-change, which would + * trash the parent's state. */ + if (attr->__flags & POSIX_SPAWN_RESETIDS) + if ((ret=__syscall(SYS_setgid, __syscall(SYS_getgid))) || + (ret=__syscall(SYS_setuid, __syscall(SYS_getuid))) ) + goto fail; + + if (fa && fa->__actions) { + struct fdop *op; + int fd; + for (op = 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 = __syscall(SYS_dup, p); + if (ret < 0) goto fail; + __syscall(SYS_close, p); + p = ret; + } + switch(op->cmd) { + case FDOP_CLOSE: + __syscall(SYS_close, op->fd); + break; + case FDOP_DUP2: + fd = op->srcfd; + if (fd == p) { + ret = -EBADF; + goto fail; + } + if (fd != op->fd) { + if ((ret=__sys_dup2(fd, op->fd))<0) + goto fail; + } else { + ret = __syscall(SYS_fcntl, fd, F_GETFD); + ret = __syscall(SYS_fcntl, fd, F_SETFD, + ret & ~FD_CLOEXEC); + if (ret<0) + goto fail; + } + break; + case FDOP_OPEN: + fd = __sys_open(op->path, op->oflag, op->mode); + if ((ret=fd) < 0) goto fail; + if (fd != op->fd) { + if ((ret=__sys_dup2(fd, op->fd))<0) + goto fail; + __syscall(SYS_close, fd); + } + break; + case FDOP_CHDIR: + ret = __syscall(SYS_chdir, op->path); + if (ret<0) goto fail; + break; + case FDOP_FCHDIR: + ret = __syscall(SYS_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. We don't use F_DUPFD_CLOEXEC above because + * it would fail on older kernels and atomicity is not needed -- + * in this process there are no threads or signal handlers. */ + __syscall(SYS_fcntl, p, F_SETFD, FD_CLOEXEC); + + pthread_sigmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) + ? &attr->__mask : &args->oldmask, 0); + + int (*exec)(const char *, char *const *, char *const *) = + attr->__fn ? (int (*)())attr->__fn : execve; + + exec(args->path, args->argv, args->envp); + ret = -errno; + +fail: + /* Since sizeof errno < PIPE_BUF, the write is atomic. */ + ret = -ret; + if (ret) while (__syscall(SYS_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 *fa, + const posix_spawnattr_t *restrict attr, + char *const argv[restrict], char *const envp[restrict]) +{ + pid_t pid; + char stack[1024+PATH_MAX]; + int ec=0, cs; + struct args args; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + + args.path = path; + args.fa = fa; + args.attr = attr ? attr : &(const posix_spawnattr_t){0}; + args.argv = argv; + args.envp = envp; + pthread_sigmask(SIG_BLOCK, SIGALL_SET, &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; + } + + pid = __clone(child, stack+sizeof stack, + CLONE_VM|CLONE_VFORK|SIGCHLD, &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, &(int){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; +} diff --git a/libc-top-half/musl/src/process/posix_spawn_file_actions_addchdir.c b/libc-top-half/musl/src/process/posix_spawn_file_actions_addchdir.c new file mode 100644 index 0000000..7f2590a --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn_file_actions_addchdir.c @@ -0,0 +1,18 @@ +#include <spawn.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "fdop.h" + +int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *restrict fa, const char *restrict path) +{ + struct fdop *op = malloc(sizeof *op + strlen(path) + 1); + if (!op) return ENOMEM; + op->cmd = FDOP_CHDIR; + op->fd = -1; + strcpy(op->path, path); + if ((op->next = fa->__actions)) op->next->prev = op; + op->prev = 0; + fa->__actions = op; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawn_file_actions_addclose.c b/libc-top-half/musl/src/process/posix_spawn_file_actions_addclose.c new file mode 100644 index 0000000..0c2ef8f --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn_file_actions_addclose.c @@ -0,0 +1,17 @@ +#include <spawn.h> +#include <stdlib.h> +#include <errno.h> +#include "fdop.h" + +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, int fd) +{ + if (fd < 0) return EBADF; + struct fdop *op = malloc(sizeof *op); + if (!op) return ENOMEM; + op->cmd = FDOP_CLOSE; + op->fd = fd; + if ((op->next = fa->__actions)) op->next->prev = op; + op->prev = 0; + fa->__actions = op; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawn_file_actions_adddup2.c b/libc-top-half/musl/src/process/posix_spawn_file_actions_adddup2.c new file mode 100644 index 0000000..addca4d --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn_file_actions_adddup2.c @@ -0,0 +1,18 @@ +#include <spawn.h> +#include <stdlib.h> +#include <errno.h> +#include "fdop.h" + +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int srcfd, int fd) +{ + if (srcfd < 0 || fd < 0) return EBADF; + struct fdop *op = malloc(sizeof *op); + if (!op) return ENOMEM; + op->cmd = FDOP_DUP2; + op->srcfd = srcfd; + op->fd = fd; + if ((op->next = fa->__actions)) op->next->prev = op; + op->prev = 0; + fa->__actions = op; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawn_file_actions_addfchdir.c b/libc-top-half/musl/src/process/posix_spawn_file_actions_addfchdir.c new file mode 100644 index 0000000..e89ede8 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn_file_actions_addfchdir.c @@ -0,0 +1,18 @@ +#include <spawn.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "fdop.h" + +int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *fa, int fd) +{ + if (fd < 0) return EBADF; + struct fdop *op = malloc(sizeof *op); + if (!op) return ENOMEM; + op->cmd = FDOP_FCHDIR; + op->fd = fd; + if ((op->next = fa->__actions)) op->next->prev = op; + op->prev = 0; + fa->__actions = op; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawn_file_actions_addopen.c b/libc-top-half/musl/src/process/posix_spawn_file_actions_addopen.c new file mode 100644 index 0000000..82bbcec --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn_file_actions_addopen.c @@ -0,0 +1,21 @@ +#include <spawn.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "fdop.h" + +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict fa, int fd, const char *restrict path, int flags, mode_t mode) +{ + if (fd < 0) return EBADF; + struct fdop *op = malloc(sizeof *op + strlen(path) + 1); + if (!op) return ENOMEM; + op->cmd = FDOP_OPEN; + op->fd = fd; + op->oflag = flags; + op->mode = mode; + strcpy(op->path, path); + if ((op->next = fa->__actions)) op->next->prev = op; + op->prev = 0; + fa->__actions = op; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawn_file_actions_destroy.c b/libc-top-half/musl/src/process/posix_spawn_file_actions_destroy.c new file mode 100644 index 0000000..3251bab --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn_file_actions_destroy.c @@ -0,0 +1,14 @@ +#include <spawn.h> +#include <stdlib.h> +#include "fdop.h" + +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) +{ + struct fdop *op = fa->__actions, *next; + while (op) { + next = op->next; + free(op); + op = next; + } + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawn_file_actions_init.c b/libc-top-half/musl/src/process/posix_spawn_file_actions_init.c new file mode 100644 index 0000000..89d5e12 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawn_file_actions_init.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa) +{ + fa->__actions = 0; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_destroy.c b/libc-top-half/musl/src/process/posix_spawnattr_destroy.c new file mode 100644 index 0000000..fc714a1 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_destroy.c @@ -0,0 +1,6 @@ +#include <spawn.h> + +int posix_spawnattr_destroy(posix_spawnattr_t *attr) +{ + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_getflags.c b/libc-top-half/musl/src/process/posix_spawnattr_getflags.c new file mode 100644 index 0000000..aa635dd --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_getflags.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_getflags(const posix_spawnattr_t *restrict attr, short *restrict flags) +{ + *flags = attr->__flags; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_getpgroup.c b/libc-top-half/musl/src/process/posix_spawnattr_getpgroup.c new file mode 100644 index 0000000..0480527 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_getpgroup.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict attr, pid_t *restrict pgrp) +{ + *pgrp = attr->__pgrp; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_getsigdefault.c b/libc-top-half/musl/src/process/posix_spawnattr_getsigdefault.c new file mode 100644 index 0000000..a49050a --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_getsigdefault.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict attr, sigset_t *restrict def) +{ + *def = attr->__def; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_getsigmask.c b/libc-top-half/musl/src/process/posix_spawnattr_getsigmask.c new file mode 100644 index 0000000..f60ad7f --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_getsigmask.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict attr, sigset_t *restrict mask) +{ + *mask = attr->__mask; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_init.c b/libc-top-half/musl/src/process/posix_spawnattr_init.c new file mode 100644 index 0000000..0dcd868 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_init.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_init(posix_spawnattr_t *attr) +{ + *attr = (posix_spawnattr_t){ 0 }; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_sched.c b/libc-top-half/musl/src/process/posix_spawnattr_sched.c new file mode 100644 index 0000000..3143635 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_sched.c @@ -0,0 +1,25 @@ +#include <spawn.h> +#include <sched.h> +#include <errno.h> + +int posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict attr, + struct sched_param *restrict schedparam) +{ + return ENOSYS; +} + +int posix_spawnattr_setschedparam(posix_spawnattr_t *restrict attr, + const struct sched_param *restrict schedparam) +{ + return ENOSYS; +} + +int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict attr, int *restrict policy) +{ + return ENOSYS; +} + +int posix_spawnattr_setschedpolicy(posix_spawnattr_t *attr, int policy) +{ + return ENOSYS; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_setflags.c b/libc-top-half/musl/src/process/posix_spawnattr_setflags.c new file mode 100644 index 0000000..6878099 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_setflags.c @@ -0,0 +1,18 @@ +#include <spawn.h> +#include <errno.h> + +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; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_setpgroup.c b/libc-top-half/musl/src/process/posix_spawnattr_setpgroup.c new file mode 100644 index 0000000..f39596a --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_setpgroup.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_setpgroup(posix_spawnattr_t *attr, pid_t pgrp) +{ + attr->__pgrp = pgrp; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_setsigdefault.c b/libc-top-half/musl/src/process/posix_spawnattr_setsigdefault.c new file mode 100644 index 0000000..5686972 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_setsigdefault.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict attr, const sigset_t *restrict def) +{ + attr->__def = *def; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnattr_setsigmask.c b/libc-top-half/musl/src/process/posix_spawnattr_setsigmask.c new file mode 100644 index 0000000..f2532f8 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnattr_setsigmask.c @@ -0,0 +1,7 @@ +#include <spawn.h> + +int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict attr, const sigset_t *restrict mask) +{ + attr->__mask = *mask; + return 0; +} diff --git a/libc-top-half/musl/src/process/posix_spawnp.c b/libc-top-half/musl/src/process/posix_spawnp.c new file mode 100644 index 0000000..aad6133 --- /dev/null +++ b/libc-top-half/musl/src/process/posix_spawnp.c @@ -0,0 +1,13 @@ +#include <spawn.h> +#include <unistd.h> + +int posix_spawnp(pid_t *restrict res, const char *restrict file, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *restrict attr, + char *const argv[restrict], char *const envp[restrict]) +{ + posix_spawnattr_t spawnp_attr = { 0 }; + if (attr) spawnp_attr = *attr; + spawnp_attr.__fn = (void *)__execvpe; + return posix_spawn(res, file, fa, &spawnp_attr, argv, envp); +} diff --git a/libc-top-half/musl/src/process/s390x/vfork.s b/libc-top-half/musl/src/process/s390x/vfork.s new file mode 100644 index 0000000..744f9d7 --- /dev/null +++ b/libc-top-half/musl/src/process/s390x/vfork.s @@ -0,0 +1,6 @@ + .global vfork + .type vfork,%function +vfork: + svc 190 + .hidden __syscall_ret + jg __syscall_ret diff --git a/libc-top-half/musl/src/process/sh/vfork.s b/libc-top-half/musl/src/process/sh/vfork.s new file mode 100644 index 0000000..91dbde7 --- /dev/null +++ b/libc-top-half/musl/src/process/sh/vfork.s @@ -0,0 +1,20 @@ +.global vfork +.type vfork,@function +vfork: + mov #95, r3 + add r3, r3 + + trapa #31 + or r0, r0 + or r0, r0 + or r0, r0 + or r0, r0 + or r0, r0 + + mov r0, r4 + mov.l 1f, r0 +2: braf r0 + nop + .align 2 + .hidden __syscall_ret +1: .long __syscall_ret@PLT-(2b+4-.) diff --git a/libc-top-half/musl/src/process/system.c b/libc-top-half/musl/src/process/system.c new file mode 100644 index 0000000..5af59b8 --- /dev/null +++ b/libc-top-half/musl/src/process/system.c @@ -0,0 +1,46 @@ +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <sys/wait.h> +#include <spawn.h> +#include <errno.h> +#include "pthread_impl.h" + +extern char **__environ; + +int system(const char *cmd) +{ + pid_t pid; + sigset_t old, reset; + struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit; + int status = -1, ret; + posix_spawnattr_t attr; + + pthread_testcancel(); + + if (!cmd) return 1; + + sigaction(SIGINT, &sa, &oldint); + sigaction(SIGQUIT, &sa, &oldquit); + sigaddset(&sa.sa_mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &sa.sa_mask, &old); + + sigemptyset(&reset); + if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT); + if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT); + posix_spawnattr_init(&attr); + posix_spawnattr_setsigmask(&attr, &old); + posix_spawnattr_setsigdefault(&attr, &reset); + posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK); + ret = posix_spawn(&pid, "/bin/sh", 0, &attr, + (char *[]){"sh", "-c", (char *)cmd, 0}, __environ); + posix_spawnattr_destroy(&attr); + + if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR); + sigaction(SIGINT, &oldint, NULL); + sigaction(SIGQUIT, &oldquit, NULL); + sigprocmask(SIG_SETMASK, &old, NULL); + + if (ret) errno = ret; + return status; +} diff --git a/libc-top-half/musl/src/process/vfork.c b/libc-top-half/musl/src/process/vfork.c new file mode 100644 index 0000000..d430c13 --- /dev/null +++ b/libc-top-half/musl/src/process/vfork.c @@ -0,0 +1,14 @@ +#define _GNU_SOURCE +#include <unistd.h> +#include <signal.h> +#include "syscall.h" + +pid_t vfork(void) +{ + /* vfork syscall cannot be made from C code */ +#ifdef SYS_fork + return syscall(SYS_fork); +#else + return syscall(SYS_clone, SIGCHLD, 0); +#endif +} diff --git a/libc-top-half/musl/src/process/wait.c b/libc-top-half/musl/src/process/wait.c new file mode 100644 index 0000000..34da102 --- /dev/null +++ b/libc-top-half/musl/src/process/wait.c @@ -0,0 +1,6 @@ +#include <sys/wait.h> + +pid_t wait(int *status) +{ + return waitpid((pid_t)-1, status, 0); +} diff --git a/libc-top-half/musl/src/process/waitid.c b/libc-top-half/musl/src/process/waitid.c new file mode 100644 index 0000000..d688650 --- /dev/null +++ b/libc-top-half/musl/src/process/waitid.c @@ -0,0 +1,7 @@ +#include <sys/wait.h> +#include "syscall.h" + +int waitid(idtype_t type, id_t id, siginfo_t *info, int options) +{ + return syscall_cp(SYS_waitid, type, id, info, options, 0); +} diff --git a/libc-top-half/musl/src/process/waitpid.c b/libc-top-half/musl/src/process/waitpid.c new file mode 100644 index 0000000..1b65bf0 --- /dev/null +++ b/libc-top-half/musl/src/process/waitpid.c @@ -0,0 +1,7 @@ +#include <sys/wait.h> +#include "syscall.h" + +pid_t waitpid(pid_t pid, int *status, int options) +{ + return syscall_cp(SYS_wait4, pid, status, options, 0); +} diff --git a/libc-top-half/musl/src/process/x32/vfork.s b/libc-top-half/musl/src/process/x32/vfork.s new file mode 100644 index 0000000..0f0ca3e --- /dev/null +++ b/libc-top-half/musl/src/process/x32/vfork.s @@ -0,0 +1,10 @@ +.global vfork +.type vfork,@function +vfork: + pop %rdx + mov $0x4000003a,%eax /* SYS_vfork */ + syscall + push %rdx + mov %rax,%rdi + .hidden __syscall_ret + jmp __syscall_ret diff --git a/libc-top-half/musl/src/process/x86_64/vfork.s b/libc-top-half/musl/src/process/x86_64/vfork.s new file mode 100644 index 0000000..9114439 --- /dev/null +++ b/libc-top-half/musl/src/process/x86_64/vfork.s @@ -0,0 +1,10 @@ +.global vfork +.type vfork,@function +vfork: + pop %rdx + mov $58,%eax + syscall + push %rdx + mov %rax,%rdi + .hidden __syscall_ret + jmp __syscall_ret |