diff options
Diffstat (limited to 'src/libstddjb/child_spawn1_internal.c')
-rw-r--r-- | src/libstddjb/child_spawn1_internal.c | 79 |
1 files changed, 43 insertions, 36 deletions
diff --git a/src/libstddjb/child_spawn1_internal.c b/src/libstddjb/child_spawn1_internal.c index be154f0..2fe0ee2 100644 --- a/src/libstddjb/child_spawn1_internal.c +++ b/src/libstddjb/child_spawn1_internal.c @@ -1,9 +1,11 @@ /* ISC license. */ #include <skalibs/sysdeps.h> -#include <unistd.h> + #include <errno.h> +#include <skalibs/djbunix.h> + #ifdef SKALIBS_HASPOSIXSPAWN #include <signal.h> @@ -11,26 +13,33 @@ #include <stdlib.h> #include <skalibs/config.h> -#include <skalibs/djbunix.h> + +#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN +# include "child_spawn-internal.h" +#endif pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to) { pid_t pid ; posix_spawn_file_actions_t actions ; posix_spawnattr_t attr ; + sigset_t set ; int e ; int nopath = !getenv("PATH") ; - if (coe(p[!(to & 1)]) < 0) goto err ; + +#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN + int syncpipe[2] ; + if (pipecoe(syncpipe) == -1) goto err ; +#endif + + if (coe(p[!(to & 1)]) == -1) goto errp ; e = posix_spawnattr_init(&attr) ; if (e) goto erre ; - { - sigset_t set ; - sigemptyset(&set) ; - e = posix_spawnattr_setsigmask(&attr, &set) ; - if (e) goto errattr ; - e = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK) ; - if (e) goto errattr ; - } + sigemptyset(&set) ; + e = posix_spawnattr_setsigmask(&attr, &set) ; + if (e) goto errattr ; + e = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK) ; + if (e) goto errattr ; e = posix_spawn_file_actions_init(&actions) ; if (e) goto errattr ; if (p[to & 1] != (to & 1)) @@ -49,10 +58,16 @@ pid_t child_spawn1_internal (char const *prog, char const *const *argv, char con e = posix_spawnp(&pid, prog, &actions, &attr, (char *const *)argv, (char *const *)envp) ; if (nopath) unsetenv("PATH") ; if (e) goto erractions ; + posix_spawn_file_actions_destroy(&actions) ; posix_spawnattr_destroy(&attr) ; fd_close(p[to & 1]) ; + +#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN + return child_spawn_workaround(pid, syncpipe) ; +#else return pid ; +#endif erractions: posix_spawn_file_actions_destroy(&actions) ; @@ -60,7 +75,12 @@ pid_t child_spawn1_internal (char const *prog, char const *const *argv, char con posix_spawnattr_destroy(&attr) ; erre: errno = e ; + errp: +#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN + fd_close(syncpipe[1]) ; + fd_close(syncpipe[0]) ; err: +#endif fd_close(p[1]) ; fd_close(p[0]) ; return 0 ; @@ -68,59 +88,46 @@ pid_t child_spawn1_internal (char const *prog, char const *const *argv, char con #else -#include <string.h> +#include <unistd.h> #include <skalibs/allreadwrite.h> -#include <skalibs/strerr.h> #include <skalibs/sig.h> -#include <skalibs/djbunix.h> #include <skalibs/exec.h> pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to) { pid_t pid ; int syncpipe[2] ; + char c ; + if (coe(p[0]) < 0 || pipecoe(syncpipe) < 0) goto err ; pid = fork() ; if (pid < 0) goto errsp ; if (!pid) { - size_t len = strlen(PROG) ; - char name[len + 9] ; - memcpy(name, PROG, len) ; - memcpy(name + len, " (child)", 9) ; - PROG = name ; fd_close(p[!(to & 1)]) ; if (fd_move(to & 1, p[to & 1]) < 0) goto syncdie ; if ((to & 2) && (fd_copy(!(to & 1), to & 1) < 0)) goto syncdie ; sig_blocknone() ; exec_ae(prog, argv, envp) ; - syncdie: - { - unsigned char c = errno ; - fd_write(syncpipe[1], (char *)&c, 1) ; - } + c = errno ; + fd_write(syncpipe[1], &c, 1) ; _exit(127) ; } fd_close(syncpipe[1]) ; - + syncpipe[1] = fd_read(syncpipe[0], &c, 1) ; + if (syncpipe[1]) { - unsigned char c ; - syncpipe[1] = fd_read(syncpipe[0], (char *)&c, 1) ; - if (syncpipe[1]) - { - int e = c ; - if (syncpipe[1] < 0) e = errno ; - if (wait_pid(pid, &syncpipe[1]) < 0) e = errno ; - errno = e ; - goto errsp0 ; - } + int e = (unsigned char)c ; + if (syncpipe[1] == -1) e = errno ; + if (wait_pid(pid, 0) == -1) e = errno ; + errno = e ; + goto errsp0 ; } fd_close(syncpipe[0]) ; - fd_close(p[to & 1]) ; return pid ; |