Beispiel #1
0
void el_execsequence (char const *const *argv1, char const *const *argv2, char const *const *envp)
{
  if (!argv2[0])
  {
    pathexec0_run(argv1, envp) ;
    strerr_dieexec(111, argv1[0]) ;
  }
  else
  {
    int wstat ;
    unsigned int j = 2 ;
#ifdef EXECLINE_OLD_VARNAMES
    char fmt[UINT_FMT * 2 + 15] = "?=" ;
#else
    char fmt[UINT_FMT + 1] = "?=" ;
#endif
    pid_t pid = el_spawn0(argv1[0], argv1, envp) ;
    if (!pid) strerr_warnwu2sys("spawn ", argv1[0]) ;
    if (wait_pid(pid, &wstat) < 0)
      strerr_diefu2sys(111, "wait for ", argv1[0]) ;
    j += uint_fmt(fmt + j, wait_status(wstat)) ; fmt[j++] = 0 ;
#ifdef EXECLINE_OLD_VARNAMES
    byte_copy(fmt + j, 13, "LASTEXITCODE=") ; j += 13 ;
    j += uint_fmt(fmt + j, wait_status(wstat)) ; fmt[j++] = 0 ;
#endif
    pathexec_r(argv2, envp, env_len(envp), fmt, j) ;
  }
  strerr_dieexec(111, argv2[0]) ;
}
void el_substandrun_str (stralloc *src, unsigned int srcbase, char const *const *envp, exlsn_t const *info)
{
    stralloc dst = STRALLOC_ZERO ;
    register int r = el_substitute(&dst, src->s + srcbase, src->len, info->vars.s, info->values.s, genalloc_s(elsubst_t const, &info->data), genalloc_len(elsubst_t const, &info->data)) ;
    if (r < 0) strerr_diefu1sys(111, "el_substitute") ;
    if (!r) _exit(0) ;
    stralloc_free(src) ;
    {
        char const *v[r + 1] ;
        if (!env_make(v, r, dst.s, dst.len)) strerr_diefu1sys(111, "env_make") ;
        v[r] = 0 ;
        pathexec_r(v, envp, env_len(envp), info->modifs.s, info->modifs.len) ;
    }
    strerr_dieexec(111, dst.s) ;
}
int main (int argc, char const *const *argv, char const *const *envp)
{
  char const *s = env_get2(envp, VAR) ;
  unsigned int fd = 1 ;
  unsigned int timeout = 0 ;
  int df = 1, keep = 0 ;
  PROG = "sdnotify-wrapper" ;
  {
    subgetopt_t l = SUBGETOPT_ZERO ;
    for (;;)
    {
      register int opt = subgetopt_r(argc, argv, "d:ft:k", &l) ;
      if (opt == -1) break ;
      switch (opt)
      {
        case 'd' : if (!uint0_scan(l.arg, &fd)) dieusage() ; break ;
        case 'f' : df = 0 ; break ;
        case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ;
        case 'k' : keep = 1 ; break ;
        default : dieusage() ;
      }
    }
    argc -= l.ind ; argv += l.ind ;
  }
  if (!argc) dieusage() ;

  if (!s) xpathexec_run(argv[0], argv, envp) ;
  else
  {
    pid_t parent = getpid() ;
    pid_t child ;
    int p[2] ;
    if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ;
    child = df ? doublefork() : fork() ;
    if (child < 0) strerr_diefu1sys(111, df ? "doublefork" : "fork") ;
    else if (!child)
    {
      PROG = "sdnotify-wrapper (child)" ;
      close(p[1]) ;
      return run_child(p[0], timeout, parent, s) ;
    }
    close(p[0]) ;
    if (fd_move((int)fd, p[1]) < 0) strerr_diefu1sys(111, "move descriptor") ;
    if (keep) xpathexec_run(argv[0], argv, envp) ;
    else xpathexec_r(argv, envp, env_len(envp), VAR, sizeof(VAR)) ;
  }
}
Beispiel #4
0
int main (int argc, char const **argv, char const *const *envp)
{
  char const *x ;
  int argc1 ;
  unsigned short okcodes[256] ;
  unsigned int nbc = 0 ;
  int flagpar = 0, not = 1 ;
  PROG = "forx" ;
  {
    subgetopt_t l = SUBGETOPT_ZERO ;
    for (;;)
    {
      register int opt = subgetopt_r(argc, argv, "epo:x:", &l) ;
      if (opt == -1) break ;
      switch (opt)
      {
        case 'e' : break ; /* compat */
        case 'p' : flagpar = 1 ; break ;
        case 'o' :
          not = 0 ;
          if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
          break ;
        case 'x' :
          not = 1 ;
          if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
          break ;
        default : dieusage() ;
      }
    }
    argc -= l.ind ; argv += l.ind ;
  }

  if (argc < 2) dieusage() ;
  x = argv[0] ; if (!*x) dieusage() ;
  argv++ ; argc-- ;
  argc1 = el_semicolon(argv) ;
  if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
  if (!argc1 || (argc1 + 1 == argc)) return 0 ;
  {
    unsigned int envlen = env_len(envp) ;
    unsigned int varlen = str_len(x) ;
    unsigned int i = 0 ;
    pid_t pids[flagpar ? argc1 : 1] ;
    char const *newenv[envlen + 2] ;

    for (; i < (unsigned int)argc1 ; i++)
    {
      pid_t pid ;
      unsigned int vallen = str_len(argv[i]) ;
      char modif[varlen + vallen + 2] ;
      byte_copy(modif, varlen, x) ;
      modif[varlen] = '=' ;
      byte_copy(modif + varlen + 1, vallen, argv[i]) ;
      modif[varlen + vallen + 1] = 0 ;
      if (!env_merge(newenv, envlen + 2, envp, envlen, modif, varlen + vallen + 2))
        strerr_diefu1sys(111, "build new environment") ;
      pid = el_spawn0(argv[argc1+1], argv + argc1 + 1, newenv) ;
      if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1+1]) ;
      if (flagpar) pids[i] = pid ;
      else
      {
        int wstat ;
        if (wait_pid(pid, &wstat) == -1)
          strerr_diefu2sys(111, "wait for ", argv[argc1+1]) ;
        if (not == isok(okcodes, nbc, wait_estatus(wstat)))
          return wait_estatus(wstat) ;
      }
    }
    if (flagpar)
      if (!waitn(pids, argc1)) strerr_diefu1sys(111, "waitn") ;
  }
  return 0 ;
}
unsigned int NAME (char const *prog, char const *const *argv, char const *const *envp, unsigned int uid, unsigned int gid, int *fds)
{
  int p[NPIPES][2] ;
  int syncpipe[2] ;
  int pid ;
  int e ;
  if (pipe(p[0]) < 0) return 0 ;
  if (pipe(p[1]) < 0) { e = errno ; goto errp0 ; }
#ifdef _CHILD_SPAWN2_
  if (pipe(p[2]) < 0) { e = errno ; goto errp1 ; }
#endif
  if (pipe(syncpipe) < 0) { e = errno ; goto errp2 ; }
  if (coe(syncpipe[1]) < 0) { e = errno ; goto errsp ; }
  pid = fork() ;
  if (pid < 0) { e = errno ; goto errsp ; }
  else if (!pid)
  {
    unsigned int m = 25 ;
    unsigned int n = str_len(PROG) ;
    char fmt[25 + UINT_FMT] = "SKACLIENT2_ADDITIONAL_FD" ;
    char name[n + 9] ;
    byte_copy(name, n, PROG) ;
    byte_copy(name + n, 9, " (child)") ;
    PROG = name ;
#ifdef _CHILD_SPAWN2_
    fmt[m-1] = '=' ;
    m += uint_fmt(fmt + m, p[2][1]) ;
    fmt[m++] = 0 ;
    fd_close(p[2][0]) ;
#endif
    fd_close(syncpipe[0]) ;
    fd_close(p[1][1]) ;
    fd_close(p[0][0]) ;
    if ((fd_move(0, p[1][0]) < 0) || (fd_move(1, p[0][1]) < 0)) goto syncdie ;
    if (gid && (prot_gid(gid) < 0)) goto syncdie ;
    if (uid && (prot_uid(uid) < 0)) goto syncdie ;
    /*
       XXX: we should unignore signals here, but there's a compromise to be
       XXX: found between bloat, API complexity, and theoretical correctness.
       XXX: Not sure what The Right Thing is; just not unignoring atm.
       XXX: 20130326 edit: The Right Thing is probably to leave the ignore
       XXX: status alone, because programs that do actual signal handling
       XXX: are likely to use a selfpipe, and selfpipe_finish() restores
       XXX: old signal handlers - it knows what to do and we don't. So,
       XXX: leave that work to selfpipe_finish().
    */
    sig_blocknone() ; /* empty sigprocmask in the child, always */
    pathexec_r_name(prog, argv, envp, env_len(envp), fmt, m) ;

   syncdie:
    {
      char c = errno ;
      fd_write(syncpipe[1], &c, 1) ;
    }
    _exit(111) ;
  }
  {
    char c ;
    fd_close(syncpipe[1]) ;
#ifdef _CHILD_SPAWN2_
    fd_close(p[2][1]) ;
#endif
    fd_close(p[1][0]) ;
    fd_close(p[0][1]) ;
    p[1][0] = fd_read(syncpipe[0], &c, 1) ;
    if (p[1][0] < 0) goto killclosewait ;
    else if (p[1][0]) { e = c ; goto closewait ; }
  }
  fd_close(syncpipe[0]) ;
  if ((ndelay_on(p[0][0]) < 0) || (coe(p[0][0]) < 0)
   || (ndelay_on(p[1][1]) < 0) || (coe(p[1][1]) < 0)) goto killclosewait ;
#ifdef _CHILD_SPAWN2_
  if ((ndelay_on(p[2][0]) < 0) || (coe(p[2][0]) < 0)) goto killclosewait ;
  fds[2] = p[2][0] ;
#endif
  fds[0] = p[0][0] ;
  fds[1] = p[1][1] ;
  return (unsigned int)pid ;

 errsp:
  fd_close(syncpipe[1]) ;
  fd_close(syncpipe[0]) ;  
 errp2:
#ifdef _CHILD_SPAWN2_
  fd_close(p[2][1]) ;
  fd_close(p[2][0]) ;
 errp1:
#endif  
  fd_close(p[1][1]) ;
  fd_close(p[1][0]) ;  
 errp0:
  fd_close(p[0][1]) ;
  fd_close(p[0][0]) ;  
  errno = e ;
  return 0 ;

 killclosewait:
  e = errno ;
  kill(pid, SIGKILL) ;
 closewait:
#ifdef _CHILD_SPAWN2_
  fd_close(p[2][0]) ;
#endif
  fd_close(p[1][1]) ;
  fd_close(p[0][0]) ;
  wait_pid(&syncpipe[1], pid) ;
  errno = e ;
  return 0 ;
}