summaryrefslogtreecommitdiff
path: root/src/libs6
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-09-08 04:06:34 +0000
committerLaurent Bercot <ska@appnovation.com>2023-09-08 04:06:34 +0000
commit15ebb5b8add8ee6a304981dd604fae78f491b34c (patch)
treeead3340839fdd15066ce95f51235e21740a07d8f /src/libs6
parent1cbe4b09e027e31d258c24feee0be46958888b93 (diff)
downloads6-15ebb5b8add8ee6a304981dd604fae78f491b34c.tar.xz
Add ucspiserver.h, support posix_spawn() in s6-ipcserverd
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/libs6')
-rw-r--r--src/libs6/deps-lib/s61
-rw-r--r--src/libs6/s6_ucspiserver_spawn.c116
2 files changed, 117 insertions, 0 deletions
diff --git a/src/libs6/deps-lib/s6 b/src/libs6/deps-lib/s6
index 9924d83..13b9a83 100644
--- a/src/libs6/deps-lib/s6
+++ b/src/libs6/deps-lib/s6
@@ -70,4 +70,5 @@ s6_supervise_link.o
s6_supervise_link_names.o
s6_supervise_unlink.o
s6_supervise_unlink_names.o
+s6_ucspiserver_spawn.o
-lskarnet
diff --git a/src/libs6/s6_ucspiserver_spawn.c b/src/libs6/s6_ucspiserver_spawn.c
new file mode 100644
index 0000000..982d754
--- /dev/null
+++ b/src/libs6/s6_ucspiserver_spawn.c
@@ -0,0 +1,116 @@
+/* ISC license. */
+
+#include <skalibs/sysdeps.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <skalibs/uint16.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/djbunix.h>
+
+#include <s6/ucspiserver.h>
+
+#ifdef SKALIBS_HASPOSIXSPAWN
+
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <spawn.h>
+
+#include <skalibs/config.h>
+#include <skalibs/env.h>
+
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+extern pid_t child_spawn_workaround (pid_t, int const *) ; /* XXX: non-public skalibs function */
+#endif
+
+pid_t s6_ucspiserver_spawn (int fd, char const *const *argv, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen, size_t modifn)
+{
+ pid_t pid ;
+ posix_spawn_file_actions_t actions ;
+ posix_spawnattr_t attr ;
+ sigset_t set ;
+ int e ;
+ int nopath = !getenv("PATH") ;
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+ int p[2] ;
+#endif
+ char const *newenvp[envlen + modifn + 1] ;
+
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+ if (pipecoe(p) == -1) return 0 ;
+#endif
+ e = posix_spawnattr_init(&attr) ;
+ if (e) goto err ;
+ 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 ;
+ e = posix_spawn_file_actions_adddup2(&actions, fd, 0) ;
+ if (e) goto erractions ;
+ e = posix_spawn_file_actions_adddup2(&actions, fd, 1) ;
+ if (e) goto erractions ;
+ if (fd > 1)
+ {
+ e = posix_spawn_file_actions_addclose(&actions, fd) ;
+ if (e) goto erractions ;
+ }
+
+ env_mergen(newenvp, envlen + modifn + 1, envp, envlen, modifs, modiflen, modifn) ;
+ if (nopath && (setenv("PATH", SKALIBS_DEFAULTPATH, 0) < 0)) { e = errno ; goto erractions ; }
+ e = posix_spawnp(&pid, argv[0], &actions, &attr, (char *const *)argv, (char *const *)newenvp) ;
+ if (nopath) unsetenv("PATH") ;
+ if (e) goto erractions ;
+
+ posix_spawn_file_actions_destroy(&actions) ;
+ posix_spawnattr_destroy(&attr) ;
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+ return child_spawn_workaround(pid, p) ;
+#else
+ return pid ;
+#endif
+
+ erractions:
+ posix_spawn_file_actions_destroy(&actions) ;
+ errattr:
+ posix_spawnattr_destroy(&attr) ;
+ err:
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+ fd_close(p[1]) ;
+ fd_close(p[0]) ;
+#endif
+ errno = e ;
+ return 0 ;
+}
+
+#else
+
+#include <skalibs/strerr.h>
+#include <skalibs/selfpipe.h>
+#include <skalibs/exec.h>
+
+pid_t s6_ucspiserver_spawn (int fd, char const *const *argv, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen, size_t modifn)
+{
+ pid_t pid = fork() ;
+ if (pid == -1) return 0 ;
+ if (!pid)
+ {
+ size_t proglen = strlen(PROG) ;
+ char newprog[proglen + 9] ;
+ memcpy(newprog, PROG, proglen) ;
+ memcpy(newprog, " (child)", 9) ;
+ PROG = newprog ;
+ if ((fd_move(1, fd) == -1) || (fd_copy(0, 1) == -1))
+ strerr_diefu1sys(111, "move fds") ;
+ selfpipe_finish() ;
+ xmexec_fn(argv, envp, envlen, modifs, modiflen, modifn) ;
+ }
+ return pid ;
+}
+
+#endif