diff options
Diffstat (limited to 'src/libstddjb/cspawn.c')
-rw-r--r-- | src/libstddjb/cspawn.c | 297 |
1 files changed, 0 insertions, 297 deletions
diff --git a/src/libstddjb/cspawn.c b/src/libstddjb/cspawn.c deleted file mode 100644 index 683a0a3..0000000 --- a/src/libstddjb/cspawn.c +++ /dev/null @@ -1,297 +0,0 @@ -/* ISC license. */ - -#include <skalibs/sysdeps.h> - -#ifdef SKALIBS_HASPOSIXSPAWN -#include <skalibs/nonposix.h> -#endif - -#include <errno.h> -#include <unistd.h> - -#include <skalibs/allreadwrite.h> -#include <skalibs/sig.h> -#include <skalibs/djbunix.h> -#include <skalibs/selfpipe.h> -#include <skalibs/exec.h> -#include <skalibs/cspawn.h> - -static inline void cspawn_child_exec (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) -{ - for (size_t i = 0 ; i < n ; i++) - { - switch (fa[i].type) - { - case CSPAWN_FA_CLOSE : fd_close(fa[i].x.fd) ; break ; - case CSPAWN_FA_COPY : - if (fd_copy(fa[i].x.fd2[0], fa[i].x.fd2[1]) == -1) return ; - break ; - case CSPAWN_FA_MOVE : - if (fd_move(fa[i].x.fd2[0], fa[i].x.fd2[1]) == -1) return ; - if (fa[i].x.fd2[0] == fa[i].x.fd2[1] && uncoe(fa[i].x.fd2[0]) == -1) return ; - break ; - case CSPAWN_FA_OPEN : - { - int fd = open3(fa[i].x.openinfo.file, fa[i].x.openinfo.oflag, fa[i].x.openinfo.mode) ; - if (fd == -1) return ; - if (fd_move(fa[i].x.openinfo.fd, fd) == -1) return ; - break ; - } - case CSPAWN_FA_CHDIR : - if (chdir(fa[i].x.path) == -1) return ; - break ; - case CSPAWN_FA_FCHDIR : - if (fchdir(fa[i].x.fd) == -1) return ; - break ; - default : - errno = EINVAL ; return ; - } - } - - if (flags & CSPAWN_FLAGS_SELFPIPE_FINISH) selfpipe_finish() ; - if (flags & CSPAWN_FLAGS_SIGBLOCKNONE) sig_blocknone() ; - if (flags & CSPAWN_FLAGS_SETSID) setsid() ; - - exec_ae(prog, argv, envp) ; -} - -static inline pid_t cspawn_fork (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) -{ - pid_t pid ; - int p[2] ; - char c ; - - if (pipecoe(p) == -1) return 0 ; - pid = fork() ; - if (pid == -1) - { - fd_close(p[1]) ; - fd_close(p[0]) ; - return 0 ; - } - if (!pid) - { - cspawn_child_exec(prog, argv, envp, flags, fa, n) ; - c = errno ; - fd_write(p[1], &c, 1) ; - _exit(127) ; - } - - fd_close(p[1]) ; - p[1] = fd_read(p[0], &c, 1) ; - if (p[1] < 0) - { - fd_close(p[0]) ; - return 0 ; - } - fd_close(p[0]) ; - if (p[1]) - { - wait_pid(pid, &p[0]) ; - errno = (unsigned char)c ; - return 0 ; - } - return pid ; -} - - /* - guess who has a buggy posix_spawn() *and* doesn't have waitid() to work around it? - if you guessed OpenBSD, you're right! - */ - -#if defined(SKALIBS_HASPOSIXSPAWN) && (!defined(SKALIBS_HASPOSIXSPAWNEARLYRETURN) || defined(SKALIBS_HASWAITID)) - -#include <signal.h> -#include <stdlib.h> -#include <spawn.h> - -#include <skalibs/config.h> -#include <skalibs/djbunix.h> - -#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN - -#include <sys/wait.h> - -static inline pid_t cspawn_workaround (pid_t pid, int const *p) -{ - siginfo_t si ; - int e ; - ssize_t r ; - char c ; - - fd_close(p[1]) ; - r = fd_read(p[0], &c, 1) ; - fd_close(p[0]) ; - if (r == -1) return 0 ; - if (r) return (errno = EILSEQ, 0) ; /* child wrote, wtf */ - - do e = waitid(P_PID, pid, &si, WEXITED | WNOHANG | WNOWAIT) ; - while (e == -1 && errno == EINTR) ; - if (e == -1) return pid ; /* we're in trouble, but don't leak a child */ - if (!si.si_pid) return pid ; /* child is running */ - if (si.si_code != CLD_EXITED || si.si_status != 127) return pid ; /* child died after execve(), let caller handle it */ - /* - child exited 127, so either execve() failed, which is what we want to catch, - or it raced like a mofo, execve()d and then exited 127 on its own, in which - case, tough luck, it never existed. - */ - wait_pid(pid, 0) ; - return (errno = 0, 0) ; -} - -#endif - -static inline pid_t cspawn_pspawn (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) -{ - pid_t pid ; - posix_spawnattr_t attr ; - posix_spawn_file_actions_t actions ; - int e ; - int nopath = !getenv("PATH") ; -#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN - int p[2] ; - if (pipecoe(p) == -1) return 0 ; -#endif - - if (flags) - { - short pfff = 0 ; - e = posix_spawnattr_init(&attr) ; - if (e) goto err ; - if (flags & (CSPAWN_FLAGS_SIGBLOCKNONE | CSPAWN_FLAGS_SELFPIPE_FINISH)) - { - sigset_t set ; - sigemptyset(&set) ; - e = posix_spawnattr_setsigmask(&attr, &set) ; - if (e) goto errattr ; - pfff |= POSIX_SPAWN_SETSIGMASK ; - } -#ifdef SKALIBS_HASPOSIXSPAWNSETSID - if (flags & CSPAWN_FLAGS_SETSID) pfff |= POSIX_SPAWN_SETSID ; -#else -#ifdef SKALIBS_HASPOSIXSPAWNSETSIDNP - if (flags & CSPAWN_FLAGS_SETSID) pfff |= POSIX_SPAWN_SETSID_NP ; -#endif -#endif - e = posix_spawnattr_setflags(&attr, pfff) ; - if (e) goto errattr ; - } - - if (n) - { - e = posix_spawn_file_actions_init(&actions) ; - if (e) goto errattr ; - for (size_t i = 0 ; i < n ; i++) - { - switch (fa[i].type) - { - case CSPAWN_FA_CLOSE : - e = posix_spawn_file_actions_addclose(&actions, fa[i].x.fd) ; - if (e) goto erractions ; - break ; - case CSPAWN_FA_COPY : - e = posix_spawn_file_actions_adddup2(&actions, fa[i].x.fd2[1], fa[i].x.fd2[0]) ; - if (e) goto erractions ; - break ; - case CSPAWN_FA_MOVE : - e = posix_spawn_file_actions_adddup2(&actions, fa[i].x.fd2[1], fa[i].x.fd2[0]) ; - if (e) goto erractions ; - if (fa[i].x.fd2[0] != fa[i].x.fd2[1]) - { - e = posix_spawn_file_actions_addclose(&actions, fa[i].x.fd2[1]) ; - if (e) goto erractions ; - } - break ; - case CSPAWN_FA_OPEN : - e = posix_spawn_file_actions_addopen(&actions, fa[i].x.openinfo.fd, fa[i].x.openinfo.file, fa[i].x.openinfo.oflag, fa[i].x.openinfo.mode) ; - if (e) goto erractions ; - break ; -#ifdef SKALIBS_HASPOSIXSPAWNCHDIR - case CSPAWN_FA_CHDIR : - e = posix_spawn_file_actions_addchdir(&actions, fa[i].x.path) ; - if (e) goto erractions ; - break ; - case CSPAWN_FA_FCHDIR : - e = posix_spawn_file_actions_addfchdir(&actions, fa[i].x.fd) ; - if (e) goto erractions ; - break ; -#else -#ifdef SKALIBS_HASPOSIXSPAWNCHDIRNP - case CSPAWN_FA_CHDIR : - e = posix_spawn_file_actions_addchdir_np(&actions, fa[i].x.path) ; - if (e) goto erractions ; - break ; - case CSPAWN_FA_FCHDIR : - e = posix_spawn_file_actions_addfchdir_np(&actions, fa[i].x.fd) ; - if (e) goto erractions ; - break ; -#endif -#endif - default : - e = EINVAL ; - goto erractions ; - } - } - } - - if (nopath && (setenv("PATH", SKALIBS_DEFAULTPATH, 0) == -1)) { e = errno ; goto erractions ; } - e = posix_spawnp(&pid, prog, n ? &actions : 0, flags ? &attr : 0, (char *const *)argv, (char *const *)envp) ; - if (nopath) unsetenv("PATH") ; - if (e) goto erractions ; - - if (n) posix_spawn_file_actions_destroy(&actions) ; - if (flags) posix_spawnattr_destroy(&attr) ; -#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN - return cspawn_workaround(pid, p) ; -#else - return pid ; -#endif - - erractions: - if (n) posix_spawn_file_actions_destroy(&actions) ; - errattr: - if (flags) posix_spawnattr_destroy(&attr) ; - err: -#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN - fd_close(p[1]) ; - fd_close(p[0]) ; -#endif - errno = e ; - return 0 ; -} - -#if (defined(SKALIBS_HASPOSIXSPAWNSETSID) || defined(SKALIBS_HASPOSIXSPAWNSETSIDNP)) && (defined(SKALIBS_HASPOSIXSPAWNCHDIR) || defined(SKALIBS_HASPOSIXSPAWNCHDIRNP)) - -pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) -{ - return cspawn_pspawn(prog, argv, envp, flags, fa, n) ; -} - -#else - -pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) -{ -#if !defined(SKALIBS_HASPOSIXSPAWNSETSID) && !defined(SKALIBS_HASPOSIXSPAWNSETSIDNP) - if (flags & CSPAWN_FLAGS_SETSID) goto dofork ; -#endif -#if !defined(SKALIBS_HASPOSIXSPAWNCHDIR) && !defined(SKALIBS_HASPOSIXSPAWNCHDIRNP) - for (size_t i = 0 ; i < n ; i++) - if (fa[i].type == CSPAWN_FA_CHDIR || fa[i].type == CSPAWN_FA_FCHDIR) - goto dofork ; -#endif - return cspawn_pspawn(prog, argv, envp, flags, fa, n) ; - - dofork: - return cspawn_fork(prog, argv, envp, flags, fa, n) ; -} - -#endif - -#else - -pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) -{ - return cspawn_fork(prog, argv, envp, flags, fa, n) ; -} - -#endif |