Example #1
0
static void handle_control (int fd)
{
  for (;;)
  {
    char c ;
    int r = sanitize_read(fd_read(fd, &c, 1)) ;
    if (r == -1) panic("read control pipe") ;
    else if (!r) break ;
    else switch (c)
    {
      case 'p' : finish_arg = "poweroff" ; break ;
      case 'h' : hup() ; return ;
      case 'r' : finish_arg = "reboot" ; break ;
      case 'a' : wantscan = 1 ; break ;
      case 't' : term() ; return ;
      case 's' : finish_arg = "halt" ; break ;
      case 'z' : wantreap = 1 ; break ;
      case 'b' : cont = 0 ; return ;
      case 'n' : wantkill = 2 ; break ;
      case 'N' : wantkill = 6 ; break ;
      case '6' :
      case 'i' : intr() ; return ;
      case 'q' : quit() ; return ;
      case '0' : finish_arg = "halt" ; term() ; return ;
      case '7' : usr1() ; return ;
      case '8' : finish_arg = "other" ; term() ; return ;
      default :
      {
        char s[2] = { c, 0 } ;
        strerr_warnw2x("received unknown control command: ", s) ;
      }
    }
  }
}
int s6net_ident_reply_get (char *s, ip46_t const *remoteip, uint16 remoteport, ip46_t const *localip, uint16 localport, tain_t const *deadline, tain_t *stamp)
{
  unsigned int len ;
  int fd ;
  if (ip46_is6(remoteip) != ip46_is6(localip)) return (errno = EAFNOSUPPORT, -1) ;
  fd = socket_tcp46(ip46_is6(remoteip)) ;
  if (fd < 0) return -1 ;
  if (socket_bind46(fd, localip, 0) < 0) goto err ;
  if (!socket_deadlineconnstamp46(fd, remoteip, 113, deadline, stamp)) goto err ;
  {
    char buf[S6NET_IDENT_REPLY_SIZE + 1] ;
    char fmt[UINT16_FMT] ;
    buffer b = BUFFER_INIT(&buffer_write, fd, buf, 256) ;
    unsigned int n = uint16_fmt(fmt, remoteport) ;
    buffer_putnoflush(&b, fmt, n) ;
    buffer_putnoflush(&b, " , ", 3) ;
    n = uint16_fmt(fmt, localport) ;
    buffer_putnoflush(&b, fmt, n) ;
    buffer_putnoflush(&b, "\r\n", 2) ;
    if (!buffer_timed_flush(&b, deadline, stamp)) goto err ;
    buffer_init(&b, &buffer_read, fd, buf, S6NET_IDENT_REPLY_SIZE + 1) ;
    if (sanitize_read(timed_getlnmax(&b, s, S6NET_IDENT_REPLY_SIZE, &len, '\n', deadline, stamp)) <= 0) goto err ;
  }
  fd_close(fd) ;
  if (!len--) return (errno = EPROTO, -1) ;
  s[len] = 0 ;
  return (int)len ;

err:
  fd_close(fd) ;
  return -1 ;
}
Example #3
0
static inline int ftrigio_read (ftrigio_t *p)
{
  unsigned int i = FTRIGRD_MAXREADS ;
  while (i--)
  {
    regmatch_t pmatch ;
    unsigned int blen ;
    register int r = sanitize_read(buffer_fill(&p->b)) ;
    if (!r) break ;
    if (r < 0) return (trig(p->id, 'd', errno), 0) ;
    blen = buffer_len(&p->b) ;
    if (!stralloc_readyplus(&p->sa, blen+1)) dienomem() ;
    buffer_getnofill(&p->b, p->sa.s + p->sa.len, blen) ;
    p->sa.len += blen ;
    p->sa.s[p->sa.len] = 0 ;
    while (!regexec(&p->re, p->sa.s, 1, &pmatch, REG_NOTBOL | REG_NOTEOL))
    {
      trig(p->id, '!', p->sa.s[pmatch.rm_eo - 1]) ;
      if (!(p->options & FTRIGR_REPEAT)) return 0 ;
      byte_copy(p->sa.s, p->sa.len + 1 - pmatch.rm_eo, p->sa.s + pmatch.rm_eo) ;
      p->sa.len -= pmatch.rm_eo ;
    }
  }
  return 1 ;
}
unsigned int rrandom_read (rrandom_ref z, char *s, unsigned int n, unsigned int (*f) (unirandom_ref, char *, unsigned int))
{
  unsigned int i = 0 ;
  for (; i < 3 ; i++)
  {
    int r ;
    if (!z->tries[i].ok) continue ;
    r = sanitize_read((*f)(&z->tries[i].it, s, n)) ;
    if (r > 0) return r ;
    z->tries[i].ok = error_temp(errno) ? z->tries[i].ok - 1 : 0 ;
  }
  return (errno = ENOENT, 0) ;
}
unsigned int randomegd_readnb (int s, char *x, unsigned int n)
{
  unsigned int w = 0 ;
  while ((n - w) >= 255)
  {
    char c[2] = { 0x01, 0xFF } ;
    register unsigned char wtmp ;
    if (allwrite(s, c, 2) < 2) return w ;
    if (sanitize_read(fd_read(s, c+1, 1)) < 1) return w ;
    wtmp = allread(s, x + w, c[1]) ;
    w += wtmp ;
    if ((wtmp < (unsigned char)c[1]) || ((unsigned char)c[1] < 0xFF)) return w ;
  }
  if (w < n)
  {
    char c[2] = "\001" ;
    c[1] = n - w ;
    if (allwrite(s, c, 2) < 2) return w ;
    if (sanitize_read(fd_read(s, c+1, 1)) < 1) return w ;
    w += allread(s, x + w, c[1]) ;
  }
  return w ;
}
Example #6
0
static void handle_control (int fd)
{
  for (;;)
  {
    char c ;
    register int r = sanitize_read(fd_read(fd, &c, 1)) ;
    if (r < 0) strerr_diefu1sys(111, "read " S6_SUPERVISE_CTLDIR "/control") ;
    else if (!r) break ;
    else
    {
      register unsigned int pos = byte_chr("abqhkti12fFpcoduxO", 18, c) ;
      if (pos < 18) (*actions[state][V_a + pos])() ;
    }
  }
}
Example #7
0
int timed_ancil_fds_recv (int fdsocket, int *fds, unsigned int n, struct taia const *deadline, struct taia *stamp)
{
  iopause_fd x = { fdsocket, IOPAUSE_READ, 0 } ;
  for (;;)
  {
    register int r = iopause_stamp(&x, 1, deadline, stamp) ;
    if (r < 0) return 0 ;
    else if (!r) return (errno = ETIMEDOUT, 0) ;
    else if (x.revents & IOPAUSE_READ)
    {
      r = sanitize_read(ancil_recv_fds(fdsocket, fds, n)) ;
      if (r < 0) return 0 ;
      else if (r > 0) break ;
    }
  }
  return 1 ;
}
static inline int run_child (int fd, unsigned int timeout, pid_t pid, char const *s)
{
  char dummy[4096] ;
  iopause_fd x = { .fd = fd, .events = IOPAUSE_READ } ;
  tain_t deadline ;
  tain_now_g() ;
  if (timeout) tain_from_millisecs(&deadline, timeout) ;
  else deadline = tain_infinite_relative ;
  tain_add_g(&deadline, &deadline) ;
  for (;;)
  {
    int r = iopause_g(&x, 1, &deadline) ;
    if (r < 0) strerr_diefu1sys(111, "iopause") ;
    if (!r) return 99 ;
    r = sanitize_read(fd_read(fd, dummy, 4096)) ;
    if (r < 0)
      if (errno == EPIPE) return 1 ;
      else strerr_diefu1sys(111, "read from parent") ;
    else if (r && memchr(dummy, '\n', r)) break ;
  }
  close(fd) ;
  notify_systemd(pid, s) ;
  return 0 ;
}
Example #9
0
int s6_fdholder_setdump (s6_fdholder_t *a, s6_fdholder_fd_t const *list, unsigned int ntot, tain_t const *deadline, tain_t *stamp)
{
  uint32 trips ;
  if (!ntot) return 1 ;
  unsigned int i = 0 ;
  for (; i < ntot ; i++)
  {
    unsigned int zpos = byte_chr(list[i].id, S6_FDHOLDER_ID_SIZE + 1, 0) ;
    if (!zpos || zpos >= S6_FDHOLDER_ID_SIZE + 1) return (errno = EINVAL, 0) ;
  }
  {
    char pack[5] = "!" ;
    unixmessage_t m = { .s = pack, .len = 5, .fds = 0, .nfds = 0 } ;
    uint32_pack_big(pack+1, ntot) ;
    if (!unixmessage_put(&a->connection.out, &m)) return 0 ;
    if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ;
    if (sanitize_read(unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) < 0) return 0 ;
    if (!m.len || m.nfds) { unixmessage_drop(&m) ; return (errno = EPROTO, 0) ; }
    if (m.s[0]) return (errno = m.s[0], 0) ;
    if (m.len != 5) return (errno = EPROTO, 0) ;
    uint32_unpack_big(m.s + 1, &trips) ;
    if (trips != 1 + (ntot-1) / UNIXMESSAGE_MAXFDS) return (errno = EPROTO, 0) ;
  }
  for (i = 0 ; i < trips ; i++, ntot -= UNIXMESSAGE_MAXFDS)
  {
    {
      unsigned int n = ntot > UNIXMESSAGE_MAXFDS ? UNIXMESSAGE_MAXFDS : ntot ;
      unsigned int j = 0 ;
      siovec_t v[1 + (n<<1)] ;
      int fds[n] ;
      unixmessage_v_t m = { .v = v, .vlen = 1 + (n<<1), .fds = fds, .nfds = n } ;
      char pack[n * (TAIN_PACK+1)] ;
      v[0].s = "." ; v[0].len = 1 ;
      for (; j < n ; j++, list++, ntot--)
      {
        unsigned int len = str_len(list->id) ;
        v[1 + (j<<1)].s = pack + j * (TAIN_PACK+1) ;
        v[1 + (j<<1)].len = TAIN_PACK + 1 ;
        tain_pack(pack + j * (TAIN_PACK+1), &list->limit) ;
        pack[j * (TAIN_PACK+1) + TAIN_PACK] = (unsigned char)len ;
        v[2 + (j<<1)].s = (char *)list->id ;
        v[2 + (j<<1)].len = len + 1 ;
        fds[j] = list->fd ;
      }
      if (!unixmessage_putv(&a->connection.out, &m)) return 0 ;
    }
    if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ;
    {
      unixmessage_t m ;
      if (sanitize_read(unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) < 0) return 0 ;
      if (m.len != 1 || m.nfds)
      {
        unixmessage_drop(&m) ;
        return (errno = EPROTO, 0) ;
      }
      if (!error_isagain(m.s[0]) && i < trips-1)
        return errno = m.s[0] ? m.s[0] : EPROTO, 0 ;
      if (i == trips - 1 && m.s[0])
        return errno = error_isagain(m.s[0]) ? EPROTO : m.s[0], 0 ;
    }
  }
  return 1 ;
}
Example #10
0
int main (void)
{
  stralloc indata = STRALLOC_ZERO ;
  unsigned int instate = 0 ;
  PROG = "s6-ftrigrd" ;

  if (ndelay_on(0) < 0) strerr_diefu2sys(111, "ndelay_on ", "0") ;
  if (ndelay_on(1) < 0) strerr_diefu2sys(111, "ndelay_on ", "1") ;
  if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ;

  {
    struct taia deadline, stamp ;
    taia_now(&stamp) ;
    taia_addsec(&deadline, &stamp, 2) ;
    if (!skaserver2_sync(&asyncout, FTRIGR_BANNER1, FTRIGR_BANNER1_LEN, FTRIGR_BANNER2, FTRIGR_BANNER2_LEN, &deadline, &stamp))
      strerr_diefu1sys(111, "sync with client") ;
  }

  for (;;)
  {
    register unsigned int n = genalloc_len(ftrigio_t, &a) ;
    iopause_fd x[3 + n] ;
    unsigned int i = 0 ;
    int r ;

    x[0].fd = 0 ; x[0].events = IOPAUSE_EXCEPT | IOPAUSE_READ ;
    x[1].fd = 1 ; x[1].events = IOPAUSE_EXCEPT | (bufalloc_len(bufalloc_1) ? IOPAUSE_WRITE : 0) ;
    x[2].fd = bufalloc_fd(&asyncout) ; x[2].events = IOPAUSE_EXCEPT | (bufalloc_len(&asyncout) ? IOPAUSE_WRITE : 0) ;
    for (; i < n ; i++)
    {
      register ftrigio_t_ref p = genalloc_s(ftrigio_t, &a) + i ;
      p->xindex = 3 + i ;
      x[3+i].fd = p->trig.fd ;
      x[3+i].events = IOPAUSE_READ ;
    }

    r = iopause(x, 3 + n, 0, 0) ;
    if (r < 0)
    {
      cleanup() ;
      strerr_diefu1sys(111, "iopause") ;
    }

   /* client closed => exit */
    if ((x[0].revents | x[1].revents) & IOPAUSE_EXCEPT) break ;

   /* client reading => flush pending data */
    if (x[1].revents & IOPAUSE_WRITE)
      if ((bufalloc_flush(bufalloc_1) == -1) && !error_isagain(errno))
      {
        cleanup() ;
        strerr_diefu1sys(111, "flush stdout") ;
      }
    if (x[2].revents & IOPAUSE_WRITE)
      if ((bufalloc_flush(&asyncout) == -1) && !error_isagain(errno))
      {
        cleanup() ;
        strerr_diefu1sys(111, "flush asyncout") ;
      }

   /* scan listening ftrigs */
    for (i = 0 ; i < genalloc_len(ftrigio_t, &a) ; i++)
    {
      register ftrigio_t_ref p = genalloc_s(ftrigio_t, &a) + i ;
      if (x[p->xindex].revents & IOPAUSE_READ)
      {
        char c ;
        register int r = sanitize_read(fd_read(p->trig.fd, &c, 1)) ;
        if (!r) continue ;
        if (r < 0)
        {
          trig(p->id, 'd', errno) ;
          remove(i--) ;
        }
        else if (!sredfa_feed(p->re, &p->dfastate, c))
        {
          trig(p->id, 'd', ENOEXEC) ;
          remove(i--) ;
        }
        else if (p->dfastate & SREDFA_ACCEPT)
        {
          trig(p->id, '!', c) ;
          if (p->options & FTRIGR_REPEAT)
            p->dfastate = SREDFA_START ;
          else remove(i--) ;
        }
      }
    }

   /* client writing => get data and parse it */
    if (buffer_len(buffer_0small) || x[0].revents & IOPAUSE_READ)
    {
      int r ;
      for (;;)
      {
        uint16 id ;
        r = sanitize_read(netstring_get(buffer_0small, &indata, &instate)) ;
        if (r <= 0) break ;
        if (indata.len < 3)
        {
          cleanup() ;
          strerr_dief1x(100, "invalid client request") ;
        }
        uint16_unpack_big(indata.s, &id) ;
        switch (indata.s[2])  /* protocol parsing */
        {
          case 'U' : /* unsubscribe */
          {
            register unsigned int i = genalloc_len(ftrigio_t, &a) ;
            for (; i ; i--) if (genalloc_s(ftrigio_t, &a)[i-1].id == id) break ;
            if (i) remove(i-1) ;
            answer(0) ;
            break ;
          }
          case 'L' : /* subscribe to path and match re */
          {
            ftrigio_t f = FTRIGIO_ZERO ;
            uint32 pathlen, relen ;
            if (indata.len < 18)
            {
              answer(EPROTO) ;
              break ;
            }
            uint32_unpack_big(indata.s + 3, &f.options) ;
            uint32_unpack_big(indata.s + 7, &pathlen) ;
            uint32_unpack_big(indata.s + 11, &relen) ;
            if (((pathlen + relen + 16) != indata.len) || indata.s[15 + pathlen])
            {
              answer(EPROTO) ;
              break ;
            }
            f.id = id ;
            if (!stralloc_0(&indata))
            {
              answer(errno) ;
              break ;
            }
            f.re = sredfa_new() ;
            if (!f.re)
            {
              answer(errno) ;
              break ;
            }
            if (!sredfa_from_regexp(f.re, indata.s + 16 + pathlen)
             || !ftrig1_make(&f.trig, indata.s + 15))
            {
              sredfa_delete(f.re) ;
              answer(errno) ;
              break ;
            }
            if (!genalloc_append(ftrigio_t, &a, &f))
            {
              ftrigio_deepfree(&f) ;
              answer(errno) ;
              break ;
            }
            answer(0) ;
            break ;
          }
          default :
          {
            cleanup() ;
            strerr_dief1x(100, "invalid client request") ;
          }
        }
        indata.len = 0 ;
      } /* end loop: parse input from client */

      if (r < 0)
      {
        if (errno == EPIPE) break ; /* client closed */
        else
        {
          cleanup() ;
          strerr_diefu1sys(111, "read a netstring") ;
        }
      } 
    } /* end if: stuff to read on stdin */
  } /* end loop: main iopause */

  cleanup() ;
  return 0 ;
}
Example #11
0
File: s6-setlock.c Project: 8l/s6
int main (int argc, char const *const *argv, char const *const *envp)
{
  unsigned int nb = 0, ex = 1 ;
  unsigned int timeout = 0 ;
  PROG = "s6-setlock" ;
  for (;;)
  {
    register int opt = subgetopt(argc, argv, "nNrwt:") ;
    if (opt == -1) break ;
    switch (opt)
    {
      case 'n' : nb = 1 ; break ;
      case 'N' : nb = 0 ; break ;
      case 'r' : ex = 0 ; break ;
      case 'w' : ex = 1 ; break ;
      case 't' : if (!uint0_scan(subgetopt_here.arg, &timeout)) dieusage() ;
                 nb = 2 ; break ;
      default : dieusage() ;
    }
  }
  argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
  if (argc < 2) dieusage() ;

  if (nb < 2)
  {
    int fd = open_create(argv[0]) ;
    if (fd == -1) strerr_diefu2sys(111, "open_create ", argv[0]) ;
    if ((*f[ex][nb])(fd) == -1) strerr_diefu2sys(1, "lock ", argv[0]) ;
  }
  else
  {
    char const *cargv[3] = { "s6lockd-helper", argv[0], 0 } ;
    char const *cenvp[2] = { ex ? "S6LOCK_EX=1" : 0, 0 } ;
    iopause_fd x = { .events = IOPAUSE_READ } ;
    tain_t deadline ;
    int p[2] ;
    unsigned int pid ;
    char c ;
    tain_now_g() ;
    tain_from_millisecs(&deadline, timeout) ;
    tain_add_g(&deadline, &deadline) ;
    pid = child_spawn(S6_LIBEXECPREFIX "s6lockd-helper", cargv, cenvp, p, 2) ;
    if (!pid) strerr_diefu2sys(111, "spawn ", S6_LIBEXECPREFIX "s6lockd-helper") ;
    x.fd = p[0] ;
    for (;;)
    {
      register int r = iopause_g(&x, 1, &deadline) ;
      if (r < 0) strerr_diefu1sys(111, "iopause") ;
      if (!r)
      {
        kill(pid, SIGTERM) ;
        errno = ETIMEDOUT ;
        strerr_diefu1sys(1, "acquire lock") ;
      }
      r = sanitize_read(fd_read(p[0], &c, 1)) ;
      if (r < 0) strerr_diefu1sys(111, "read ack from helper") ;
      if (r) break ;
    }
    if (c != '!') strerr_dief1x(111, "helper sent garbage ack") ;
    fd_close(p[0]) ;
    if (uncoe(p[1]) < 0) strerr_diefu1sys(111, "uncoe fd to helper") ;
  }
  pathexec_run(argv[1], argv+1, envp) ;
  strerr_dieexec(111, argv[1]) ;
}