diff --git a/include/spawn.h b/include/spawn.h new file mode 100644 index 0000000000000000000000000000000000000000..1bcb1bbf34bc7c32235778c89e1e672273a0c8aa --- /dev/null +++ b/include/spawn.h @@ -0,0 +1,67 @@ +#ifndef _SPAWN_H +#define _SPAWN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_mode_t +#define __NEED_pid_t +#define __NEED_sigset_t + +#include + +struct sched_param; + +#define POSIX_SPAWN_RESETIDS 1 +#define POSIX_SPAWN_SETPGROUP 2 +#define POSIX_SPAWN_SETSIGDEF 4 +#define POSIX_SPAWN_SETSIGMASK 8 +#define POSIX_SPAWN_SETSCHEDPARAM 16 +#define POSIX_SPAWN_SETSCHEDULER 32 + +typedef struct { + int __flags; + pid_t __pgrp; + sigset_t __def, __mask; + int __prio, __pol, __pad[16]; +} posix_spawnattr_t; + +typedef struct { + int __pad0[2]; + void *__actions; + int __pad[16]; +} posix_spawn_file_actions_t; + +int posix_spawn(pid_t *, const char *, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char **, char **); +int posix_spawnp(pid_t *, const char *, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char **, char **); + +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_destroy(posix_spawnattr_t *); + +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_getflags(const posix_spawnattr_t *, short *); + +int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t); +int posix_spawnattr_getpgroup(const posix_spawnattr_t *, pid_t *); + +int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *); +int posix_spawnattr_getsigmask(const posix_spawnattr_t *, sigset_t *); + +int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *); +int posix_spawnattr_getsigdefault(const posix_spawnattr_t *, sigset_t *); + +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); + +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *, int, const char *, int, mode_t); +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c new file mode 100644 index 0000000000000000000000000000000000000000..e718cee30c2af9b4d3e0d8527f2bcff868ed4662 --- /dev/null +++ b/src/process/posix_spawn.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include "syscall.h" + +extern char **environ; + +int __posix_spawnx(pid_t *res, const char *path, + int (*exec)(const char *, char *const *), + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *attr, char **argv, char **envp) +{ + pid_t pid; + sigset_t oldmask; + int i; + posix_spawnattr_t dummy_attr = { 0 }; + + if (!attr) attr = &dummy_attr; + + sigprocmask(SIG_BLOCK, (void *)(uint64_t []){-1}, &oldmask); + pid = __syscall(SYS_fork); + + if (pid) { + sigprocmask(SIG_SETMASK, &oldmask, 0); + if (pid < 0) return -pid; + *res = pid; + return 0; + } + + for (i=1; i<=64; i++) { + struct sigaction sa; + sigaction(i, 0, &sa); + if (sa.sa_handler!=SIG_IGN || sigismember(&attr->__def, i)) { + sa.sa_handler = SIG_DFL; + sigaction(i, &sa, 0); + } + } + + if ((attr->__flags&POSIX_SPAWN_SETPGROUP) && setpgid(0, attr->__pgrp)) + _exit(127); + + /* Use syscalls directly because pthread state is not consistent + * for making calls to the library wrappers... */ + if ((attr->__flags&POSIX_SPAWN_RESETIDS) && ( + __syscall(SYS_setgid, __syscall(SYS_getgid)) || + __syscall(SYS_setuid, __syscall(SYS_getuid)) )) + _exit(127); + + sigprocmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) + ? &attr->__mask : &oldmask, 0); + + if (envp) environ = envp; + exec(path, argv); + _exit(127); + + return 0; +} + +int posix_spawn(pid_t *res, const char *path, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *attr, char **argv, char **envp) +{ + return __posix_spawnx(res, path, execv, fa, attr, argv, envp); +} diff --git a/src/process/posix_spawn_file_actions_destroy.c b/src/process/posix_spawn_file_actions_destroy.c new file mode 100644 index 0000000000000000000000000000000000000000..c2501ddfaf60a6941812b09e702c6c06f4bb7298 --- /dev/null +++ b/src/process/posix_spawn_file_actions_destroy.c @@ -0,0 +1,9 @@ +#include +#include + +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) +{ + // FIXME + free(fa->__actions); + return 0; +} diff --git a/src/process/posix_spawn_file_actions_init.c b/src/process/posix_spawn_file_actions_init.c new file mode 100644 index 0000000000000000000000000000000000000000..89d5e1278908d4026292c31be6b0a6d958b41f47 --- /dev/null +++ b/src/process/posix_spawn_file_actions_init.c @@ -0,0 +1,7 @@ +#include + +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa) +{ + fa->__actions = 0; + return 0; +} diff --git a/src/process/posix_spawnattr_getflags.c b/src/process/posix_spawnattr_getflags.c new file mode 100644 index 0000000000000000000000000000000000000000..7353d24a6c0e01f93cb82313b1eaed18983fb63a --- /dev/null +++ b/src/process/posix_spawnattr_getflags.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_getflags(const posix_spawnattr_t *attr, short *flags) +{ + *flags = attr->__flags; + return 0; +} diff --git a/src/process/posix_spawnattr_getpgroup.c b/src/process/posix_spawnattr_getpgroup.c new file mode 100644 index 0000000000000000000000000000000000000000..2c72e9851ad0cacc058d04ed963af4952c8d448f --- /dev/null +++ b/src/process/posix_spawnattr_getpgroup.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_getpgroup(const posix_spawnattr_t *attr, pid_t *pgrp) +{ + *pgrp = attr->__pgrp; + return 0; +} diff --git a/src/process/posix_spawnattr_getsigdefault.c b/src/process/posix_spawnattr_getsigdefault.c new file mode 100644 index 0000000000000000000000000000000000000000..5f0dfb58c192350b34a4d69b0d2503b7118c7032 --- /dev/null +++ b/src/process/posix_spawnattr_getsigdefault.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_getsigdefault(const posix_spawnattr_t *attr, sigset_t *def) +{ + *def = attr->__def; + return 0; +} diff --git a/src/process/posix_spawnattr_getsigmask.c b/src/process/posix_spawnattr_getsigmask.c new file mode 100644 index 0000000000000000000000000000000000000000..b44907561dd1884a544a4c9233e612d7d88f1abb --- /dev/null +++ b/src/process/posix_spawnattr_getsigmask.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_getsigmask(const posix_spawnattr_t *attr, sigset_t *mask) +{ + *mask = attr->__mask; + return 0; +} diff --git a/src/process/posix_spawnattr_setflags.c b/src/process/posix_spawnattr_setflags.c new file mode 100644 index 0000000000000000000000000000000000000000..f750c040bcaf6a9c9eb7c12436173fd07a9edde8 --- /dev/null +++ b/src/process/posix_spawnattr_setflags.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) +{ + attr->__flags = flags; + return 0; +} diff --git a/src/process/posix_spawnattr_setpgroup.c b/src/process/posix_spawnattr_setpgroup.c new file mode 100644 index 0000000000000000000000000000000000000000..f39596a6ec62d2dacc4ae6b6ac1a379940b77519 --- /dev/null +++ b/src/process/posix_spawnattr_setpgroup.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_setpgroup(posix_spawnattr_t *attr, pid_t pgrp) +{ + attr->__pgrp = pgrp; + return 0; +} diff --git a/src/process/posix_spawnattr_setsigdefault.c b/src/process/posix_spawnattr_setsigdefault.c new file mode 100644 index 0000000000000000000000000000000000000000..a6ddd4d81169b471875e4a901526a6fdbe7a662e --- /dev/null +++ b/src/process/posix_spawnattr_setsigdefault.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_setsigdefault(posix_spawnattr_t *attr, const sigset_t *def) +{ + attr->__def = *def; + return 0; +} diff --git a/src/process/posix_spawnattr_setsigmask.c b/src/process/posix_spawnattr_setsigmask.c new file mode 100644 index 0000000000000000000000000000000000000000..6afbf8760870ff9a847e139962274a0cf8607516 --- /dev/null +++ b/src/process/posix_spawnattr_setsigmask.c @@ -0,0 +1,7 @@ +#include + +int posix_spawnattr_setsigmask(posix_spawnattr_t *attr, const sigset_t *mask) +{ + attr->__mask = *mask; + return 0; +} diff --git a/src/process/posix_spawnp.c b/src/process/posix_spawnp.c new file mode 100644 index 0000000000000000000000000000000000000000..7434bb690b6402c5ddd8b697f164bb06f70851ec --- /dev/null +++ b/src/process/posix_spawnp.c @@ -0,0 +1,14 @@ +#include +#include + +int __posix_spawnx(pid_t *, const char *, + int (*)(const char *, char *const *), + const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char **, char **); + +int posix_spawnp(pid_t *res, const char *file, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *attr, char **argv, char **envp) +{ + return __posix_spawnx(res, file, execvp, fa, attr, argv, envp); +}