skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

commit 252e2ad869637ca3ef8690854a8fac784b869ec9
parent 8ba811fb48d666a23d60a5ce3a947dcac7baf6ea
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date:   Sun, 10 Sep 2023 04:59:41 +0000

 Add POSIX_SPAWN_SETSID support to cspawn

Signed-off-by: Laurent Bercot <ska@appnovation.com>

Diffstat:
Mconfigure | 3++-
Mpackage/deps.mak | 2+-
Msrc/include/skalibs/cspawn.h | 1+
Msrc/libstddjb/cspawn.c | 168++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Asrc/sysdeps/tryposixspawnsetsid.c | 30++++++++++++++++++++++++++++++
5 files changed, 131 insertions(+), 73 deletions(-)

diff --git a/configure b/configure @@ -640,10 +640,11 @@ choose cl explicit_bzero 'explicit_bzero()' choose cl getrandom 'getrandom()' choose cl grndinsecure 'GRND_INSECURE' choose cl chroot 'chroot()' +choose cl posixspawnsetsid 'POSIX_SPAWN_SETSID' ${spawn_lib} # Here are the evil irreducible run-time sysdeps. choose clr devurandom '/dev/urandom' -choose clr posixspawnearlyreturn 'posix_spawn() returning early' +choose clr posixspawnearlyreturn 'posix_spawn() incorrectly returning early' ${spawn_lib} # Finally, produce config.mak and config.h diff --git a/package/deps.mak b/package/deps.mak @@ -309,7 +309,7 @@ src/libstddjb/child_spawn1_socket.o src/libstddjb/child_spawn1_socket.lo: src/li src/libstddjb/child_spawn2.o src/libstddjb/child_spawn2.lo: src/libstddjb/child_spawn2.c src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h src/libstddjb/child_spawn3.o src/libstddjb/child_spawn3.lo: src/libstddjb/child_spawn3.c src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/types.h src/libstddjb/coe.o src/libstddjb/coe.lo: src/libstddjb/coe.c src/include/skalibs/djbunix.h -src/libstddjb/cspawn.o src/libstddjb/cspawn.lo: src/libstddjb/cspawn.c src/include/skalibs/allreadwrite.h src/include/skalibs/config.h src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h src/include/skalibs/exec.h src/include/skalibs/selfpipe.h src/include/skalibs/sig.h src/include/skalibs/sysdeps.h +src/libstddjb/cspawn.o src/libstddjb/cspawn.lo: src/libstddjb/cspawn.c src/include/skalibs/allreadwrite.h src/include/skalibs/config.h src/include/skalibs/cspawn.h src/include/skalibs/djbunix.h src/include/skalibs/exec.h src/include/skalibs/nonposix.h src/include/skalibs/selfpipe.h src/include/skalibs/sig.h src/include/skalibs/sysdeps.h src/libstddjb/deepsleepuntil.o src/libstddjb/deepsleepuntil.lo: src/libstddjb/deepsleepuntil.c src/include/skalibs/iopause.h src/include/skalibs/tai.h src/libstddjb/devino_cmp.o src/libstddjb/devino_cmp.lo: src/libstddjb/devino_cmp.c src/include/skalibs/devino.h src/libstddjb/dir_close.o src/libstddjb/dir_close.lo: src/libstddjb/dir_close.c src/include/skalibs/direntry.h diff --git a/src/include/skalibs/cspawn.h b/src/include/skalibs/cspawn.h @@ -8,6 +8,7 @@ #define CSPAWN_FLAGS_SELFPIPE_FINISH 0x0001U #define CSPAWN_FLAGS_SIGBLOCKNONE 0x0002U +#define CSPAWN_FLAGS_SETSID 0x0004U #define CSPAWN_FA_CLOSE 0x0000U #define CSPAWN_FA_COPY 0x0001U diff --git a/src/libstddjb/cspawn.c b/src/libstddjb/cspawn.c @@ -2,10 +2,93 @@ #include <skalibs/sysdeps.h> +#ifdef SKALIBS_HASPOSIXSPAWN +#include <skalibs/nonposix.h> +#endif + #include <errno.h> +#include <fcntl.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, uint32_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 ; + break ; + case CSPAWN_FA_OPEN : + { + int fd = open(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 ; + } + 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, uint32_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 ; +} + #ifdef SKALIBS_HASPOSIXSPAWN #include <signal.h> @@ -19,8 +102,6 @@ #include <sys/wait.h> -#include <skalibs/allreadwrite.h> - static inline pid_t cspawn_workaround (pid_t pid, int const *p) { siginfo_t si ; @@ -50,7 +131,7 @@ static inline pid_t cspawn_workaround (pid_t pid, int const *p) #endif -pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n) +static inline pid_t cspawn_pspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n) { pid_t pid ; posix_spawnattr_t attr ; @@ -139,82 +220,27 @@ pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp return 0 ; } -#else - -#include <fcntl.h> -#include <unistd.h> - -#include <skalibs/allreadwrite.h> -#include <skalibs/sig.h> -#include <skalibs/selfpipe.h> -#include <skalibs/exec.h> +#ifdef SKALIBS_HASPOSIXSPAWNSETSID -static inline void cspawn_child_exec (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n) +pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_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 ; - break ; - case CSPAWN_FA_OPEN : - { - int fd = open(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 ; - } - default : - errno = EINVAL ; return ; - } - } - - if (flags & CSPAWN_FLAGS_SELFPIPE_FINISH) selfpipe_finish() ; - if (flags & CSPAWN_FLAGS_SIGBLOCKNONE) sig_blocknone() ; + return cspawn_pspawn(prog, argv, envp, flags, fa, n) ; } +#else + pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n) { - pid_t pid ; - int p[2] ; - char c ; + return flags & CSPAWN_FLAGS_SETSID ? cspawn_fork(prog, argv, envp, flags, fa, n) : cspawn_pspawn(prog, argv, envp, flags, fa, n) ; +} - 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) ; - } +#endif - 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 ; +#else + +pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint32_t flags, cspawn_fileaction const *fa, size_t n) +{ + return cspawn_fork(prog, argv, envp, flags, fa, n) ; } #endif diff --git a/src/sysdeps/tryposixspawnsetsid.c b/src/sysdeps/tryposixspawnsetsid.c @@ -0,0 +1,30 @@ +/* ISC license. */ + +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE + +#ifndef _XPG4_2 +#define _XPG4_2 +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif + +#include <spawn.h> + +int main (void) +{ + pid_t pid ; + posix_spawn_file_actions_t actions ; + posix_spawnattr_t attr ; + char *const argv[2] = { "/bin/true", 0 } ; + char *const envp[1] = { 0 } ; + posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSID) ; + posix_spawn_file_actions_init(&actions) ; + return posix_spawn(&pid, argv[0], 0, 0, argv, envp) ; +}