s6

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

s6-sudoc.c (4005B)


      1 /* ISC license. */
      2 
      3 #include <string.h>
      4 #include <stdint.h>
      5 #include <errno.h>
      6 #include <fcntl.h>
      7 #include <signal.h>
      8 #include <sys/uio.h>
      9 #include <sys/wait.h>
     10 
     11 #include <skalibs/types.h>
     12 #include <skalibs/sgetopt.h>
     13 #include <skalibs/buffer.h>
     14 #include <skalibs/stralloc.h>
     15 #include <skalibs/strerr.h>
     16 #include <skalibs/djbunix.h>
     17 #include <skalibs/tai.h>
     18 #include <skalibs/env.h>
     19 #include <skalibs/unix-timed.h>
     20 #include <skalibs/unixmessage.h>
     21 
     22 #include "s6-sudo.h"
     23 
     24 #define USAGE "s6-sudoc [ -e ] [ -t timeoutconn ] [ -T timeoutrun ] [ args... ]"
     25 #define dieusage() strerr_dieusage(100, USAGE)
     26 #define dienomem() strerr_diefu1sys(111, "stralloc_catb")
     27 
     28 int main (int argc, char const *const *argv, char const *const *envp)
     29 {
     30   char buf6[64] ;
     31   buffer b6 = BUFFER_INIT(&buffer_read, 6, buf6, 64) ;
     32   unixmessage_sender b7 = UNIXMESSAGE_SENDER_INIT(7) ;
     33   subgetopt l = SUBGETOPT_ZERO ;
     34   unsigned int t = 0, T = 0 ;
     35   int doenv = 1 ;
     36   
     37   tain deadline = TAIN_INFINITE_RELATIVE ;
     38   PROG = "s6-sudoc" ;
     39   for (;;)
     40   {
     41     int opt = subgetopt_r(argc, argv, "et:T:", &l) ;
     42     if (opt < 0) break ;
     43     switch (opt)
     44     {
     45       case 'e' : doenv = 0 ; break ;
     46       case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
     47       case 'T' : if (!uint0_scan(l.arg, &T)) dieusage() ; break ;
     48       default : dieusage() ;
     49     }
     50   }
     51   argc -= l.ind ; argv += l.ind ;
     52   if (t) tain_from_millisecs(&deadline, t) ;
     53   if ((ndelay_on(6) < 0) || (ndelay_on(7) < 0))
     54     strerr_diefu1sys(111, "make socket non-blocking") ;
     55   if (!fd_sanitize() || !fd_ensure_open(2, 1))
     56     strerr_diefu1sys(111, "sanitize stdin/stdout/stderr") ;
     57 
     58   tain_now_set_stopwatch_g() ;
     59   tain_add_g(&deadline, &deadline) ;
     60   {
     61     size_t r ;
     62     char tmp[S6_SUDO_BANNERB_LEN] ;
     63     r = buffer_timed_get_g(&b6, tmp, S6_SUDO_BANNERB_LEN, &deadline) ;
     64     if (!r)
     65       strerr_diefu1x(111, "connect to the s6-sudod server - check that you have appropriate permissions") ;
     66     if (r < S6_SUDO_BANNERB_LEN)
     67       strerr_diefu1sys(111, "read banner from s6-sudod") ;
     68     if (strncmp(tmp, S6_SUDO_BANNERB, S6_SUDO_BANNERB_LEN))
     69       strerr_dief1x(100, "wrong banner - check that you are connecting to a s6-sudod server") ;
     70   }
     71   {
     72     int fds[3] = { 0, 1, 2 } ;
     73     char pack[16] ;
     74     struct iovec v[4] = {
     75       { .iov_base = S6_SUDO_BANNERA, .iov_len = S6_SUDO_BANNERA_LEN },
     76       { .iov_base = pack, .iov_len = 16 },
     77       { .iov_base = 0, .iov_len = 0 },
     78       { .iov_base = 0, .iov_len = 0 } } ;
     79     unixmessagev mv = { .v = v, .vlen = 4, .fds = fds, .nfds = 3 } ;
     80     stralloc sa = STRALLOC_ZERO ;
     81     size_t envlen = doenv ? env_len(envp) : 0 ;
     82     uint32_pack_big(pack, (uint32_t)argc) ;
     83     uint32_pack_big(pack + 4, (uint32_t)envlen) ;
     84     if (!env_string(&sa, argv, argc)) dienomem() ;
     85     v[2].iov_len = sa.len ;
     86     uint32_pack_big(pack + 8, (uint32_t)v[2].iov_len) ;
     87     if (doenv)
     88     {
     89       if (!env_string(&sa, envp, envlen)) dienomem() ;
     90       v[3].iov_len = sa.len - v[2].iov_len ;
     91     }
     92     uint32_pack_big(pack + 12, (uint32_t)v[3].iov_len) ;
     93     v[2].iov_base = sa.s ;
     94     v[3].iov_base = sa.s + v[2].iov_len ;
     95     if (!unixmessage_putv_and_close(&b7, &mv, (unsigned char const *)"\003"))
     96       strerr_diefu1sys(111, "unixmessage_putv") ;
     97     stralloc_free(&sa) ;
     98   }
     99   if (!unixmessage_sender_timed_flush_g(&b7, &deadline))
    100     strerr_diefu1sys(111, "send args to server") ;
    101   unixmessage_sender_free(&b7) ;
    102   {
    103     char c ;
    104     if (buffer_timed_get_g(&b6, &c, 1, &deadline) < 1)
    105       strerr_diefu1sys(111, "get confirmation from server") ;
    106     if (c)
    107     {
    108       errno = c ;
    109       strerr_diefu1sys(111, "start privileged program: server answered: ") ;
    110     }
    111   }
    112 
    113   if (T) tain_from_millisecs(&deadline, T) ; else deadline = tain_infinite_relative ;
    114   tain_add_g(&deadline, &deadline) ;
    115   {
    116     char pack[UINT_PACK] ;
    117     if (buffer_timed_get_g(&b6, pack, UINT_PACK, &deadline) < UINT_PACK)
    118       strerr_diefu1sys(111, "get exit status from server") ;
    119     uint_unpack_big(pack, &t) ;
    120   }
    121   return wait_estatus(t) ;
    122 }