summaryrefslogtreecommitdiff
path: root/src/conn-tools/s6-sudod.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/conn-tools/s6-sudod.c')
-rw-r--r--src/conn-tools/s6-sudod.c233
1 files changed, 0 insertions, 233 deletions
diff --git a/src/conn-tools/s6-sudod.c b/src/conn-tools/s6-sudod.c
deleted file mode 100644
index 8c52bb9..0000000
--- a/src/conn-tools/s6-sudod.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/* ISC license. */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <skalibs/uint.h>
-#include <skalibs/allreadwrite.h>
-#include <skalibs/sgetopt.h>
-#include <skalibs/bytestr.h>
-#include <skalibs/buffer.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/strerr2.h>
-#include <skalibs/tai.h>
-#include <skalibs/iopause.h>
-#include <skalibs/selfpipe.h>
-#include <skalibs/env.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/unix-timed.h>
-#include <skalibs/unixmessage.h>
-#include "s6-sudo.h"
-
-#define USAGE "s6-sudod [ -0 ] [ -1 ] [ -2 ] [ -t timeout ] args..."
-#define dieusage() strerr_dieusage(100, USAGE)
-#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
-
-int main (int argc, char const *const *argv, char const *const *envp)
-{
- subgetopt_t l = SUBGETOPT_ZERO ;
- unixmessage_t m ;
- unsigned int nullfds = 0, t = 2000 ;
- pid_t pid ;
- uint32 envc = env_len(envp) ;
- uint32 cargc, cenvc, carglen, cenvlen ;
- int spfd ;
- tain_t deadline = TAIN_INFINITE_RELATIVE ;
- PROG = "s6-sudod" ;
- for (;;)
- {
- register int opt = subgetopt_r(argc, argv, "012t:", &l) ;
- if (opt < 0) break ;
- switch (opt)
- {
- case '0' : nullfds |= 1 ; break ;
- case '1' : nullfds |= 2 ; break ;
- case '2' : nullfds |= 4 ; break ;
- case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
- if (t) tain_from_millisecs(&deadline, t) ;
- if ((ndelay_on(0) < 0) || (ndelay_on(1) < 0))
- strerr_diefu1sys(111, "make socket non-blocking") ;
-
- tain_now_g() ;
- tain_add_g(&deadline, &deadline) ;
- buffer_putnoflush(buffer_1small, S6_SUDO_BANNERB, S6_SUDO_BANNERB_LEN) ;
- if (!buffer_timed_flush_g(buffer_1small, &deadline))
- strerr_diefu1sys(111, "write banner to client") ;
- if (unixmessage_timed_receive_g(unixmessage_receiver_0, &m, &deadline) <= 0)
- strerr_diefu1sys(111, "read message from client") ;
- if (m.nfds != 3)
- strerr_dief1x(100, "client did not send 3 fds") ;
- if (m.len < 16 + S6_SUDO_BANNERA_LEN)
- strerr_dief1x(100, "wrong client message") ;
- if (str_diffn(m.s, S6_SUDO_BANNERA, S6_SUDO_BANNERA_LEN))
- strerr_dief1x(100, "wrong client banner") ;
- uint32_unpack_big(m.s + S6_SUDO_BANNERA_LEN, &cargc) ;
- uint32_unpack_big(m.s + S6_SUDO_BANNERA_LEN + 4, &cenvc) ;
- uint32_unpack_big(m.s + S6_SUDO_BANNERA_LEN + 8, &carglen) ;
- uint32_unpack_big(m.s + S6_SUDO_BANNERA_LEN + 12, &cenvlen) ;
- if (S6_SUDO_BANNERA_LEN + 16 + carglen + cenvlen != m.len)
- strerr_dief1x(100, "wrong client argc/envlen") ;
- if ((cargc > 131072) || (cenvc > 131072))
- strerr_dief1x(100, "too many args/envvars from client") ;
-
- if (nullfds & 1)
- {
- close(m.fds[0]) ;
- m.fds[0] = open2("/dev/null", O_RDONLY) ;
- if (m.fds[0] < 0) strerr_diefu2sys(111, "open /dev/null for ", "reading") ;
- }
- if (nullfds & 2)
- {
- close(m.fds[1]) ;
- m.fds[1] = open2("/dev/null", O_WRONLY) ;
- if (m.fds[1] < 0) strerr_diefu2sys(111, "open /dev/null for ", "writing") ;
- }
- if (nullfds & 4)
- {
- close(m.fds[2]) ;
- m.fds[2] = 2 ;
- }
-
- {
- char const *targv[argc + 1 + cargc] ;
- char const *tenvp[envc + 1 + cenvc] ;
- int p[2] ;
- register unsigned int i = 0 ;
- for (; i < (unsigned int)argc ; i++) targv[i] = argv[i] ;
- for (i = 0 ; i <= envc ; i++) tenvp[i] = envp[i] ;
- if (!env_make(targv + argc, cargc, m.s + S6_SUDO_BANNERA_LEN + 16, carglen))
- {
- char c = errno ;
- buffer_putnoflush(buffer_1small, &c, 1) ;
- buffer_timed_flush_g(buffer_1small, &deadline) ;
- errno = c ;
- strerr_diefu1sys(111, "make child argv") ;
- }
- if (!env_make(tenvp + envc + 1, cenvc, m.s + S6_SUDO_BANNERA_LEN + 16 + carglen, cenvlen))
- {
- char c = errno ;
- buffer_putnoflush(buffer_1small, &c, 1) ;
- buffer_timed_flush_g(buffer_1small, &deadline) ;
- errno = c ;
- strerr_diefu1sys(111, "make child envp") ;
- }
- targv[argc + cargc] = 0 ;
-
- for (i = 0 ; i < cenvc ; i++)
- {
- char const *var = tenvp[envc + 1 + i] ;
- register unsigned int j = 0 ;
- register unsigned int len = str_chr(var, '=') ;
- if (!var[len])
- {
- char c = EINVAL ;
- buffer_putnoflush(buffer_1small, &c, 1) ;
- buffer_timed_flush_g(buffer_1small, &deadline) ;
- strerr_dief1x(100, "bad environment from client") ;
- }
- for (; j < envc ; j++) if (!str_diffn(var, tenvp[j], len+1)) break ;
- if ((j < envc) && !tenvp[j][len+1]) tenvp[j] = var ;
- }
-
- spfd = selfpipe_init() ;
- if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ;
- if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "trap SIGCHLD") ;
- if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ;
- if (coe(p[1]) < 0) strerr_diefu1sys(111, "coe pipe") ;
- pid = fork() ;
- if (pid < 0) strerr_diefu1sys(111, "fork") ;
- if (!pid)
- {
- PROG = "s6-sudod (child)" ;
- fd_close(p[0]) ;
- if ((fd_move(2, m.fds[2]) < 0)
- || (fd_move(1, m.fds[1]) < 0)
- || (fd_move(0, m.fds[0]) < 0))
- {
- char c = errno ;
- fd_write(p[1], &c, 1) ;
- strerr_diefu1sys(111, "move fds") ;
- }
- selfpipe_finish() ;
- pathexec0_run(targv, tenvp) ;
- {
- char c = errno ;
- fd_write(p[1], &c, 1) ;
- }
- strerr_dieexec(111, targv[0]) ;
- }
- fd_close(p[1]) ;
- {
- char c ;
- register int r = fd_read(p[0], &c, 1) ;
- if (r < 0) strerr_diefu1sys(111, "read from child") ;
- if (r)
- {
- buffer_putnoflush(buffer_1small, &c, 1) ;
- buffer_timed_flush_g(buffer_1small, &deadline) ;
- return 111 ;
- }
- }
- fd_close(p[0]) ;
- }
-
- fd_close(m.fds[0]) ;
- fd_close(m.fds[1]) ;
- if (!(nullfds & 4)) fd_close(m.fds[2]) ;
- unixmessage_receiver_free(unixmessage_receiver_0) ;
- buffer_putnoflush(buffer_1small, "", 1) ;
- if (!buffer_timed_flush_g(buffer_1small, &deadline))
- strerr_diefu1sys(111, "send confirmation to client") ;
-
- {
- iopause_fd x[2] = { { .fd = 0, .events = 0 }, { .fd = spfd, .events = IOPAUSE_READ } } ;
- int cont = 1 ;
- while (cont)
- {
- if (iopause_g(x, 2, 0) < 0) strerr_diefu1sys(111, "iopause") ;
- if (x[1].revents)
- {
- for (;;)
- {
- int c = selfpipe_read() ;
- if (c < 0) strerr_diefu1sys(111, "read from selfpipe") ;
- else if (!c) break ;
- else if (c == SIGCHLD)
- {
- int wstat ;
- register int r = wait_pid_nohang(pid, &wstat) ;
- if ((r < 0) && (errno != ECHILD))
- strerr_diefu1sys(111, "wait_pid_nohang") ;
- else if (r > 0)
- {
- char pack[UINT_PACK] ;
- uint_pack_big(pack, (unsigned int)wstat) ;
- buffer_putnoflush(buffer_1small, pack, UINT_PACK) ;
- cont = 0 ;
- }
- }
- else
- strerr_dief1sys(101, "internal inconsistency, please submit a bug-report") ;
- }
- }
- if (x[0].revents && cont)
- {
- kill(pid, SIGTERM) ;
- kill(pid, SIGCONT) ;
- x[0].fd = -1 ;
- return 1 ;
- }
- }
- }
- if (ndelay_off(1) < 0)
- strerr_diefu1sys(111, "set stdout blocking") ;
- if (!buffer_flush(buffer_1small))
- strerr_diefu1sys(111, "write status to client") ;
- return 0 ;
-}