Beispiel #1
0
int setup_log()
{
    if ((rploglen =str_len(rplog)) < 7)
    {
        warn3x("log must have at least seven characters.", 0, 0);
        return(0);
    }
    if (pipe(logpipe) == -1)
    {
        warn3x("unable to create pipe for log.", 0, 0);
        return(-1);
    }
    coe(logpipe[1]);
    coe(logpipe[0]);
    ndelay_on(logpipe[0]);
    ndelay_on(logpipe[1]);
    if (fd_copy(2, logpipe[1]) == -1)
    {
        warn3x("unable to set filedescriptor for log.", 0, 0);
        return(-1);
    }
    io[0].fd =logpipe[0];
    io[0].events =IOPAUSE_READ;
    taia_now(&stamplog);
    return(1);
}
Beispiel #2
0
int selfpipe_init (void) {
  if (selfpipe[0] >= 0) return (errno = EBUSY, -1);
  if (pipe(selfpipe) == -1) return -1;
  if ((ndelay_on(selfpipe[1]) == -1)
      || (coe(selfpipe[1]) == -1)
      || (ndelay_on(selfpipe[0]) == -1)
      || (coe(selfpipe[0]) == -1))
    selfpipe_close();
  return selfpipe[0];
}
Beispiel #3
0
/********************************************************************
 * mkpqf()
 *
 * Function `mkpqf()' returns a pointer to a `pqf' data structure
 *  containing the coefficients, length and the pre-periodized filter
 *  named by the input parameters.
 *
 * Calling sequence:
 *       mkpqf( coefs, alpha, omega, flags )
 * 
 * Inputs:
 *	(const real *)coefs     These are the filter coefficients,
 *				  assumed to be given in the array
 *				  `coefs[0],...,coefs[omega-alpha]'
 *				  are the only nonzero values.
 *
 *      (int)alpha      These are to be the first and last valid
 *      (int)omega        indices of the pqf->f struct member.
 *
 *	(int)flags	This is reserved for later uses, such as 
 *			  indicating when to generate a full QF
 *			  sequence from just one symmetric half.
 *
 * Return value:
 *	(pqf *)mkpqf  The return value is a pointer to a newly 
 *			  allocated pqf struct containing `coefs[]',
 *			  `alpha', `omega', and the preperiodized
 *			  version of  `coefs[]'.
 * Assumptions:
 *     (1) Conventional indexing: `alpha <= 0 <= omega'.
 */
extern pqf *
  mkpqf(
	const real *coefs,	/* Original filter coefficients. */
	int alpha,		/* Least valid index of `?->f[]'.    */
	int omega,		/* Greatest valid index of `?->f[]'. */
	int flags)		/* Reserved for future use. */
{
  pqf *qm;
  int M;

  assert(alpha <= 0);		/* Conventional indexing. */
  assert(0 <= omega);		/* Conventional indexing. */

  qm = (pqf *)calloc(1,sizeof(pqf)); assert(qm);
  qm->alpha = alpha;
  qm->omega = omega;
  qm->f = coefs-alpha;
  M = IFH( omega-alpha );
  qm->fp = (real *)calloc( PQFL(M), sizeof(real)); assert(qm->fp);
  qfcirc( qm->fp, qm->f, alpha, omega );

  qm->center = coe( qm->f, alpha, omega );
  qm->deviation = lphdev( qm->f, alpha, omega );
  return(qm);
}
Beispiel #4
0
void f_init(char **script)
{
  int i;
  int fd;

  for (i = 0;script[i];++i)
    ;

  f = (int *) alloc(i * sizeof(*f));
  if (!f) strerr_die2x(111,FATAL,"out of memory");

  for (i = 0;script[i];++i) {
    fd = -1;
    if (script[i][0] == '=') {
      if (fchdir(fdstartdir) == -1)
        strerr_die2sys(111,FATAL,"unable to switch to starting directory: ");
      fd = open_append(script[i] + 1);
      if (fd == -1)
        strerr_die4sys(111,FATAL,"unable to create ",script[i] + 1,": ");
      close(fd);
      fd = open_write(script[i] + 1);
      if (fd == -1)
        strerr_die4sys(111,FATAL,"unable to write ",script[i] + 1,": ");
      coe(fd);
    }
    f[i] = fd;
  }
}
pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to)
{
  int e ;
  int syncp[2] ;
  pid_t pid ;
  if (coe(p[0]) < 0 || pipecoe(syncp) < 0)
  {
    e = errno ;
    fd_close(p[1]) ;
    fd_close(p[0]) ;
    errno = e ;
    return 0 ;
  }
  pid = fork() ;
  if (pid < 0)
  {
    e = errno ;
    fd_close(syncp[1]) ;
    fd_close(syncp[0]) ;
    fd_close(p[1]) ;
    fd_close(p[0]) ;
    errno = e ;
    return 0 ;
  }
  if (!pid)
  {
    fd_close(syncp[0]) ;
    fd_close(p[!(to & 1)]) ;
    if (fd_move(to & 1, p[to & 1]) < 0) goto err ;
    if ((to & 2) && (fd_copy(!(to & 1), to & 1) < 0)) goto err ;
    sig_blocknone() ;
    pathexec_run(prog, argv, envp) ;
err:
    e = errno ;
    fd_write(syncp[1], (char *)&e, sizeof(e)) ;
    _exit(127) ;
  }
  fd_close(syncp[1]) ;
  fd_close(p[to & 1]) ;
  syncp[1] = fd_read(syncp[0], (char *)&e, sizeof(e)) ;
  if (syncp[1] < 0)
  {
    e = errno ;
    fd_close(syncp[0]) ;
    fd_close(p[!(to & 1)]) ;
    errno = e ;
    return 0 ;
  }
  fd_close(syncp[0]) ;
  if (syncp[1] == sizeof(e))
  {
    fd_close(p[!(to & 1)]) ;
    wait_pid(pid, &syncp[1]) ;
    errno = e ;
    return 0 ;
  }
  return pid ;
}
Beispiel #6
0
int
call_open(struct call *cc, const char *prog, int timeout, int flagstar)
{
  int pit[2];
  int pif[2];
  const char *(args[2]);

  args[0] = prog;
  args[1] = 0;

  if (pipe(pit) == -1) return -1;
  if (pipe(pif) == -1) { close(pit[0]); close(pit[1]); return -1; }
 
  switch(cc->pid = vfork()) {
    case -1:
      close(pit[0]); close(pit[1]);
      close(pif[0]); close(pif[1]);
      return -1;
    case 0:
      close(pit[1]);
      close(pif[0]);
      if (fd_move(0,pit[0]) == -1) _exit(120);
      if (fd_move(1,pif[1]) == -1) _exit(120);
      if (chdir(auto_qmail) == -1) _exit(61);
      execv(*args,(char **)args);
      _exit(120);
  }

  if (timeout != 0) mytimeout = timeout;
  cc->flagerr = 0;
  cc->flagabort = 0;
  cc->flagstar = flagstar;
  cc->tofd = pit[1]; close(pit[0]);
  cc->fromfd = pif[0]; close(pif[1]);
  coe(cc->tofd); coe(cc->fromfd);
  substdio_fdbuf(&cc->ssto, mywrite, cc->tofd,
      cc->tobuf, sizeof(cc->tobuf));
  substdio_fdbuf(&cc->ssfrom, myread, cc->fromfd,
      cc->frombuf, sizeof(cc->frombuf));
  return 0;
}
Beispiel #7
0
int main(int argc,char **argv)
{
  struct stat st;

  dir = argv[1];
  if (!dir || argv[2])
    strerr_die1x(100,"supervise: usage: supervise dir");

  if (pipe(selfpipe) == -1)
    strerr_die4sys(111,FATAL,"unable to create pipe for ",dir,": ");
  coe(selfpipe[0]);
  coe(selfpipe[1]);
  ndelay_on(selfpipe[0]);
  ndelay_on(selfpipe[1]);

  sig_block(sig_child);
  sig_catch(sig_child,trigger);

  if (chdir(dir) == -1)
    strerr_die4sys(111,FATAL,"unable to chdir to ",dir,": ");

  if (stat("down",&st) != -1)
    flagwantup = 0;
  else
    if (errno != error_noent)
      strerr_die4sys(111,FATAL,"unable to stat ",dir,"/down: ");

  mkdir("supervise",0700);
  fdlock = open_append("supervise/lock");
  if ((fdlock == -1) || (lock_exnb(fdlock) == -1))
    strerr_die4sys(111,FATAL,"unable to acquire ",dir,"/supervise/lock: ");
  coe(fdlock);

  fifo_make("supervise/control",0600);
  fdcontrol = open_read("supervise/control");
  if (fdcontrol == -1)
    strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/control: ");
  coe(fdcontrol);
  ndelay_on(fdcontrol); /* shouldn't be necessary */
  fdcontrolwrite = open_write("supervise/control");
  if (fdcontrolwrite == -1)
    strerr_die4sys(111,FATAL,"unable to write ",dir,"/supervise/control: ");
  coe(fdcontrolwrite);

  pidchange();
  announce();

  fifo_make("supervise/ok",0600);
  fdok = open_read("supervise/ok");
  if (fdok == -1)
    strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/ok: ");
  coe(fdok);

  if (!flagwant || flagwantup) trystart();

  doit();
  announce();
  _exit(0);
}
Beispiel #8
0
static void write_log(int fd, int level, const char *info0, const char *info1, const char *info2)
{
	struct stat st;
	int fdx, ret;
	char tmp[2048];
	char timestr[128];
	char loglevel[3][16] = { "NOTICE", "WARNING", "FATAL" };
	if (fd == fdlog)
	{
		if ((ret = stat(status_files[5], &st)) < 0 || st.st_size > 1800000000)
		{
			close(fdlog);
			if (ret == 0)
				unlink(status_files[5]);
			fdlog = open_append(status_files[5]);
			coe(fdlog);
		}
		fdx = fdlog;
	}
	else if (fd == fdlogwf)
	{
		if ((ret = stat(status_files[6], &st)) < 0 || st.st_size > 1800000000)
		{
			close(fdlogwf);
			if (ret == 0)
				unlink(status_files[6]);
			fdlogwf = open_append(status_files[6]);
			coe(fdlogwf);
		}
		fdx = fdlogwf;
	}
	else
		return;
	bzero(timestr, 128);
	gettimenow(timestr, 128);
	snprintf(tmp, 2048, "[%s] %s %s%s%s", level >= 0 && level < 3 ? loglevel[level] : "", timestr, info0, info1, info2);
	write(fdx, tmp, strlen(tmp));
}
Beispiel #9
0
int unirandomegd_sinit (union unirandominfo *u, char const *path)
{
  register int s = randomegd_open(path) ;
  if (s == -1) return 0 ;
  if (coe(s) == -1)
  {
    register int e = errno ;
    fd_close(s) ;
    errno = e ;
    return 0 ;
  }
  u->egd.fd = s ;
  return 1 ;
}
int pipe_internal (int *p, unsigned int flags)
{
#ifdef HASPIPE2
  return pipe2(p, ((flags & DJBUNIX_FLAG_COE) ? O_CLOEXEC : 0) | ((flags & DJBUNIX_FLAG_NB) ? O_NONBLOCK : 0)) ;
#else
  int pi[2] ;
  if (pipe(pi) < 0) return -1 ;
  if (flags & DJBUNIX_FLAG_COE)
    if ((coe(pi[0]) < 0) || (coe(pi[1]) < 0)) goto err ;
  if (flags & DJBUNIX_FLAG_NB)
    if ((ndelay_on(pi[0]) < 0) || (ndelay_on(pi[1]) < 0)) goto err ;
  p[0] = pi[0] ; p[1] = pi[1] ;
  return 0 ;
 err:
  {
    register int e = errno ;
    fd_close(pi[1]) ;
    fd_close(pi[0]) ;
    errno = e ;
  }
  return -1 ;
#endif
}
Beispiel #11
0
int socket_internal (int domain, int type, int protocol, unsigned int flags)
{
  int s = socket(domain, type, protocol) ;
  if (s == -1) return -1 ;
  if ((((flags & DJBUNIX_FLAG_NB) ? ndelay_on(s) : ndelay_off(s)) < 0)
   || (((flags & DJBUNIX_FLAG_COE) ? coe(s) : uncoe(s)) < 0))
  {
    register int e = errno ;
    fd_close(s) ;
    errno = e ;
    return -1 ;
  }
  return s ;
}
Beispiel #12
0
int socketpair_internal (int domain, int type, int protocol, unsigned int flags, int *sv)
{
  int fd[2] ;
  if (socketpair(domain, type, protocol, fd) < 0) return -1 ;
  if (flags & DJBUNIX_FLAG_NB)
  {
    if (ndelay_on(fd[0]) < 0) goto err ;
    if (ndelay_on(fd[1]) < 0) goto err ;
  }
  else
  {
    if (ndelay_off(fd[0]) < 0) goto err ;
    if (ndelay_off(fd[1]) < 0) goto err ;
  }
  if (flags & DJBUNIX_FLAG_COE)
  {
    if (coe(fd[0]) < 0) goto err ;
    if (coe(fd[1]) < 0) goto err ;
  }
  else
  {
    if (uncoe(fd[0]) < 0) goto err ;
    if (uncoe(fd[1]) < 0) goto err ;
  }
  sv[0] = fd[0] ;
  sv[1] = fd[1] ;
  return 0 ;

 err:
  {
    register int e = errno ;
    fd_close(fd[1]) ;
    fd_close(fd[0]) ;
    errno = e ;
  }
  return -1 ;
}
pid_t child_spawn1_internal (char const *prog, char const *const *argv, char const *const *envp, int *p, int to)
{
  posix_spawn_file_actions_t actions ;
  posix_spawnattr_t attr ;
  int e ;
  pid_t pid ;
  int haspath = !!env_get("PATH") ;
  if (coe(p[!(to & 1)]) < 0) { e = errno ; goto err ; }
  e = posix_spawnattr_init(&attr) ;
  if (e) goto err ;
  {
    sigset_t set ;
    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, p[to & 1], to & 1) ;
  if (e) goto erractions ;
  e = posix_spawn_file_actions_addclose(&actions, p[to & 1]) ;
  if (e) goto erractions ;
  if (to & 2)
  {
    e = posix_spawn_file_actions_adddup2(&actions, to & 1, !(to & 1)) ;
    if (e) goto erractions ;
  }
  if (!haspath && (setenv("PATH", SKALIBS_DEFAULTPATH, 0) < 0)) { e = errno ; goto erractions ; }
  e = posix_spawnp(&pid, prog, &actions, &attr, (char *const *)argv, (char *const *)envp) ;
  if (!haspath) unsetenv("PATH") ;
  posix_spawn_file_actions_destroy(&actions) ;
  posix_spawnattr_destroy(&attr) ;
  fd_close(p[to & 1]) ;
  if (e) goto errp ;
  return pid ;

 erractions:
  posix_spawn_file_actions_destroy(&actions) ;
 errattr:
  posix_spawnattr_destroy(&attr) ;
 err:
  fd_close(p[to & 1]) ;
 errp:
  fd_close(p[!(to & 1)]) ;
  errno = e ;
  return 0 ;
}
Beispiel #14
0
static int setup_log(void)
{
	rploglen = strlen(rplog);
	if (rploglen < 7) {
		warnx("log must have at least seven characters");
		return 0;
	}
	if (pipe(logpipe)) {
		warnx("cannot create pipe for log");
		return -1;
	}
	coe(logpipe[1]);
	coe(logpipe[0]);
	ndelay_on(logpipe[0]);
	ndelay_on(logpipe[1]);
	if (dup2(logpipe[1], 2) == -1) {
		warnx("cannot set filedescriptor for log");
		return -1;
	}
	pfd[0].fd = logpipe[0];
	pfd[0].events = POLLIN;
	stamplog = monotonic_sec();
	return 1;
}
Beispiel #15
0
static int setup_log(void)
{
	rploglen = strlen(rplog);
	if (rploglen < 7) {
		warnx("log must have at least seven characters");
		return 0;
	}
	if (pipe(logpipe)) {
		warnx("cannot create pipe for log");
		return -1;
	}
	coe(logpipe[1]);
	coe(logpipe[0]);
	ndelay_on(logpipe[0]);
	ndelay_on(logpipe[1]);
	if (dup2(logpipe[1], 2) == -1) {
		warnx("cannot set filedescriptor for log");
		return -1;
	}
	io[0].fd = logpipe[0];
	io[0].events = IOPAUSE_READ;
	taia_now(&stamplog);
	return 1;
}
Beispiel #16
0
static void show_config()
{
	int i, len;
	struct stat st;
	char buf[4096];
	if (stat(status_files[5], &st) < 0)
	{
		close(fdlog);
		fdlog = open_append(status_files[5]);
		coe(fdlog);
	}
	bzero(buf, 4096);
	snprintf(buf, 4096, "alarm_interval: %u\nmax_tries: %d\nmax_tries_if_coredumped: %d\nalarm_mail : %s\ngsm_list_len: %d\n",
			alarm_interval, max_tries, max_tries_if_coredumped, alarm_mail, gsm_list_len);
	for (i = 0; i < gsm_list_len; i++)
	{
		len = strlen(buf);
		snprintf(buf + len, 4096 - len, "alarm_gsm[%d]: %s\n", i, alarm_gsm[i]);
	}
	write(fdlog, buf, strlen(buf));
}
Beispiel #17
0
int main(int argc,char **argv)
{
  umask(022);

  fdstartdir = open_read(".");
  if (fdstartdir == -1)
    strerr_die2sys(111,FATAL,"unable to switch to current directory: ");
  coe(fdstartdir);

  sig_block(sig_term);
  sig_block(sig_alarm);
  sig_catch(sig_term,exitasap);
  sig_catch(sig_alarm,forcerotate);

  ++argv;
  f_init(argv);
  c_init(argv);
  doit(argv);
  c_quit();
  _exit(0);
}
Beispiel #18
0
int ipc_accept_internal (int s, char *p, unsigned int l, int *trunc, unsigned int options)
{
  struct sockaddr_un sa ;
  socklen_t dummy = sizeof sa ;
  register int fd ;
  byte_zero((char*)&sa, (unsigned int)dummy) ;
  do
#ifdef SKALIBS_HASACCEPT4
    fd = accept4(s, (struct sockaddr *)&sa, &dummy, ((options & DJBUNIX_FLAG_NB) ? SOCK_NONBLOCK : 0) | ((options & DJBUNIX_FLAG_COE) ? SOCK_CLOEXEC : 0)) ;
#else
    fd = accept(s, (struct sockaddr *)&sa, &dummy) ;
#endif
  while ((fd == -1) && (errno == EINTR)) ;
  if (fd == -1) return -1 ;
#ifndef SKALIBS_HASACCEPT4
  if ((((options & DJBUNIX_FLAG_NB) ? ndelay_on(fd) : ndelay_off(fd)) < 0)
   || (((options & DJBUNIX_FLAG_COE) ? coe(fd) : uncoe(fd)) < 0))
  {
    register int e = errno ;
    fd_close(fd) ;
    errno = e ;
    return -1 ;
  }
#endif

  if (p)
  {
    dummy = byte_chr(sa.sun_path, dummy, 0) ;
    *trunc = 1 ;
    if (!l) return fd ;
    if (l < (dummy + 1)) dummy = l - 1 ;
    else *trunc = 0 ;
    byte_copy(p, dummy, sa.sun_path) ;
    p[dummy] = 0 ;
  }
  return fd ;
}
Beispiel #19
0
int main (int argc, const char * const *argv, char * const *envp) {
  const char * prog[2];
  int pid, pid2;
  int wstat;
  int st;
  iopause_fd x;
#ifndef IOPAUSE_POLL
  fd_set rfds;
  struct timeval t;
#endif
  char ch;
  int ttyfd;
  struct stat s;

  if (getpid() != 1) strerr_die2x(111, FATAL, "must be run as process no 1.");
  setsid();

  sig_block(sig_alarm);
  sig_block(sig_child);
  sig_catch(sig_child, sig_child_handler);
  sig_block(sig_cont);
  sig_catch(sig_cont, sig_cont_handler);
  sig_block(sig_hangup);
  sig_block(sig_int);
  sig_catch(sig_int, sig_int_handler);
  sig_block(sig_pipe);
  sig_block(sig_term);

  /* console */
  if ((ttyfd =open_write("/dev/console")) != -1) {
    dup2(ttyfd, 0); dup2(ttyfd, 1); dup2(ttyfd, 2);
    if (ttyfd > 2) close(ttyfd);
  }

  /* create selfpipe */
  while (pipe(selfpipe) == -1) {
    strerr_warn2(FATAL, "unable to create selfpipe, pausing: ", &strerr_sys);
    sleep(5);
  }
  coe(selfpipe[0]);
  coe(selfpipe[1]);
  ndelay_on(selfpipe[0]);
  ndelay_on(selfpipe[1]);

#ifdef RB_DISABLE_CAD
  /* activate ctrlaltdel handling, glibc, dietlibc */
  if (RB_DISABLE_CAD == 0) reboot_system(0);
#endif

  strerr_warn3(INFO, "$Id: 25da3b86f7bed4038b8a039d2f8e8c9bbcf0822b $",
               ": booting.", 0);

  /* runit */
  for (st =0; st < 3; st++) {
    /* if (st == 2) logwtmp("~", "reboot", ""); */
    while ((pid =fork()) == -1) {
      strerr_warn4(FATAL, "unable to fork for \"", stage[st], "\" pausing: ",
                   &strerr_sys);
      sleep(5);
    }
    if (!pid) {
      /* child */
      prog[0] =stage[st];
      prog[1] =0;

      /* stage 1 gets full control of console */
      if (st == 0) {
        if ((ttyfd =open("/dev/console", O_RDWR)) != -1) {
#ifdef TIOCSCTTY 
          ioctl(ttyfd, TIOCSCTTY, (char *)0);
#endif
          dup2(ttyfd, 0);
          if (ttyfd > 2) close(ttyfd);
        }
        else
          strerr_warn2(WARNING, "unable to open /dev/console: ", &strerr_sys);
      }
      else
        setsid();

      sig_unblock(sig_alarm);
      sig_unblock(sig_child);
      sig_uncatch(sig_child);
      sig_unblock(sig_cont);
      sig_ignore(sig_cont);
      sig_unblock(sig_hangup);
      sig_unblock(sig_int);
      sig_uncatch(sig_int);
      sig_unblock(sig_pipe);
      sig_unblock(sig_term);
            
      strerr_warn3(INFO, "enter stage: ", stage[st], 0);
      execve(*prog, (char *const *)prog, envp);
      strerr_die4sys(0, FATAL, "unable to start child: ", stage[st], ": ");
    }

    x.fd =selfpipe[0];
    x.events =IOPAUSE_READ;
    for (;;) {
      int child;

      sig_unblock(sig_child);
      sig_unblock(sig_cont);
      sig_unblock(sig_int);
#ifdef IOPAUSE_POLL
      poll(&x, 1, 14000);
#else
      t.tv_sec =14; t.tv_usec =0;
      FD_ZERO(&rfds);
      FD_SET(x.fd, &rfds);
      select(x.fd +1, &rfds, (fd_set*)0, (fd_set*)0, &t);
#endif
      sig_block(sig_cont);
      sig_block(sig_child);
      sig_block(sig_int);
      
      while (read(selfpipe[0], &ch, 1) == 1) {}
      while ((child =wait_nohang(&wstat)) > 0)
        if (child == pid) break;
      if (child == -1) {
        strerr_warn2(WARNING, "wait_nohang, pausing: ", &strerr_sys);
        sleep(5);
      }

      /* reget stderr */
      if ((ttyfd =open_write("/dev/console")) != -1) {
        dup2(ttyfd, 2);
        if (ttyfd > 2) close(ttyfd);
      }

      if (child == pid) {
        if (wait_exitcode(wstat) != 0) {
          if (wait_crashed(wstat))
            strerr_warn3(WARNING, "child crashed: ", stage[st], 0);
          else
            strerr_warn3(WARNING, "child failed: ", stage[st], 0);
          if (st == 0)
            /* this is stage 1 */
            if (wait_crashed(wstat) || (wait_exitcode(wstat) == 100)) {
              strerr_warn3(INFO, "leave stage: ", stage[st], 0);
              strerr_warn2(WARNING, "skipping stage 2...", 0);
              st++;
              break;
            }
          if (st == 1)
            /* this is stage 2 */
            if (wait_crashed(wstat) || (wait_exitcode(wstat) == 111)) {
              strerr_warn2(WARNING, "killing all processes in stage 2...", 0);
              kill(-pid, 9);
              sleep(5);
              strerr_warn2(WARNING, "restarting.", 0);
              st--;
              break;
            }
        }
        strerr_warn3(INFO, "leave stage: ", stage[st], 0);
        break;
      }
      if (child != 0) {
        /* collect terminated children */
        write(selfpipe[1], "", 1);
        continue;
      }

      /* sig? */
      if (!sigc  && !sigi) {
#ifdef DEBUG
        strerr_warn2(WARNING, "poll: ", &strerr_sys);
#endif
        continue;
      }
      if (st != 1) {
        strerr_warn2(WARNING, "signals only work in stage 2.", 0);
        sigc =sigi =0;
        continue;
      }
      if (sigi && (stat(CTRLALTDEL, &s) != -1) && (s.st_mode & S_IXUSR)) {
        strerr_warn2(INFO, "ctrl-alt-del request...", 0);
        prog[0] =CTRLALTDEL; prog[1] =0;
        while ((pid2 =fork()) == -1) {
          strerr_warn4(FATAL, "unable to fork for \"", CTRLALTDEL,
                       "\" pausing: ", &strerr_sys);
          sleep(5);
        }
        if (!pid2) {
          /* child */
          strerr_warn3(INFO, "enter stage: ", prog[0], 0);
          execve(*prog, (char *const *) prog, envp);
          strerr_die4sys(0, FATAL, "unable to start child: ", prog[0], ": ");
        }
        if (wait_pid(&wstat, pid2) == -1)
          strerr_warn2(FATAL, "wait_pid: ", &strerr_sys);
        if (wait_crashed(wstat))
          strerr_warn3(WARNING, "child crashed: ", CTRLALTDEL, 0);
        strerr_warn3(INFO, "leave stage: ", prog[0], 0);
        sigi =0;
        sigc++;
      }
      if (sigc && (stat(STOPIT, &s) != -1) && (s.st_mode & S_IXUSR)) {
        int i;
        /* unlink(STOPIT); */
        chmod(STOPIT, 0);

        /* kill stage 2 */
#ifdef DEBUG
        strerr_warn2(WARNING, "sending sigterm...", 0);
#endif
        kill(pid, sig_term);
        i =0;
        while (i < 5) {
          if ((child =wait_nohang(&wstat)) == pid) {
#ifdef DEBUG
            strerr_warn2(WARNING, "stage 2 terminated.", 0);
#endif
            pid =0;
            break;
          }
          if (child) continue;
          if (child == -1) 
            strerr_warn2(WARNING, "wait_nohang: ", &strerr_sys);
#ifdef DEBUG
          strerr_warn2(WARNING, "waiting...", 0);
#endif
          sleep(1);
          i++;
        }
        if (pid) {
          /* still there */
          strerr_warn2(WARNING,
                       "stage 2 not terminated, sending sigkill...", 0);
          kill(pid, 9);
          if (wait_pid(&wstat, pid) == -1)
            strerr_warn2(WARNING, "wait_pid: ", &strerr_sys);
        }
        sigc =0;
        strerr_warn3(INFO, "leave stage: ", stage[st], 0);

        /* enter stage 3 */
        break;
      }
      sigc =sigi =0;
#ifdef DEBUG
      strerr_warn2(WARNING, "no request.", 0);
#endif
    }
  }

  /* reget stderr */
  if ((ttyfd =open_write("/dev/console")) != -1) {
    dup2(ttyfd, 2);
    if (ttyfd > 2) close(ttyfd);
  }

#ifdef RB_AUTOBOOT
  /* fallthrough stage 3 */
  strerr_warn2(INFO, "sending KILL signal to all processes...", 0);
  kill(-1, SIGKILL);

  pid =fork();
  switch (pid) {
  case  0:
  case -1:
  if ((stat(REBOOT, &s) != -1) && (s.st_mode & S_IXUSR)) {
    strerr_warn2(INFO, "system reboot.", 0);
    sync();
    reboot_system(RB_AUTOBOOT);
  }
  else {
#ifdef RB_POWER_OFF
    strerr_warn2(INFO, "power off...", 0);
    sync();
    reboot_system(RB_POWER_OFF);
    sleep(2);
#endif
#ifdef RB_HALT_SYSTEM
    strerr_warn2(INFO, "system halt.", 0);
    sync();
    reboot_system(RB_HALT_SYSTEM);
#else
#ifdef RB_HALT
    strerr_warn2(INFO, "system halt.", 0);
    sync();
    reboot_system(RB_HALT);
#else
    strerr_warn2(INFO, "system reboot.", 0);
    sync();
    reboot_system(RB_AUTOBOOT);
#endif
#endif
  }
  if (pid == 0) _exit(0);
  break;
  default:
  sig_unblock(sig_child);
  while (wait_pid(0, pid) == -1);
  }
#endif

  for (;;) sig_pause();
  /* not reached */
  strerr_die2x(0, INFO, "exit.");
  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 ;
}
Beispiel #21
0
int main(int argc, char **argv)
{
  int fdfifo, fdfifowrite;
  char *x;
  unsigned long id;

  VERSIONINFO;

  x = env_get("WORKDIR");
  if (!x)
    strerr_die2x(111, FATAL, "$WORKDIR not set");
  if (chdir(x) == -1)
    strerr_die4sys(111, FATAL, "unable to chdir to ", x, ": ");

  x = env_get("GID");
  if (!x)
    strerr_die2x(111, FATAL, "$GID not set");
  scan_ulong(x,&id);
  if (prot_gid((int) id) == -1)
    strerr_die2sys(111, FATAL, "unable to setgid: ");

  x = env_get("UID");
  if (!x)
    strerr_die2x(111, FATAL, "$UID not set");
  scan_ulong(x,&id);

  /* undocumented feature */
  if(id == 0)
    if(!env_get("IWANTTORUNASROOTANDKNOWWHATIDO"))
      strerr_die2x(111, FATAL, "unable to run under uid 0: please change $UID");

  if (prot_uid((int) id) == -1)
    strerr_die2sys(111, FATAL, "unable to setuid: ");

  buffer_putsflush(buffer_2, ARGV0 "starting\n");

  if(fifo_make(FIFONAME, 0620) == -1)
    strerr_warn4(ARGV0, "unable to create fifo ", FIFONAME, " ", &strerr_sys);

  fdfifo = open_read(FIFONAME);
  if(fdfifo == -1)
    strerr_die4sys(111, FATAL, "unable to open for read ", FIFONAME, " ");
  coe(fdfifo);
  ndelay_on(fdfifo); /* DJB says: shouldn't be necessary */

  /* we need this to keep the fifo from beeing closed */
  fdfifowrite = open_write(FIFONAME);
  if (fdfifowrite == -1)
    strerr_die4sys(111, FATAL, "unable to open for write ", FIFONAME, " ");
  coe(fdfifowrite);

  /* init a buffer for nonblocking reading */
  buffer_init(&wr, waitread, fdfifo, waitreadspace, sizeof waitreadspace);

  t = dAVLAllocTree();

  /* read snapshot of dnsdatatree */ 
  fill_db();

  /* SIGALRM can be used to check if dumping the database is needed */
  sig_catch(sig_alarm, sigalrm);

  /* SIGHUP can be used to force dumping the database */
  sig_catch(sig_hangup, sighup);  

  /* check if out child is done */
  sig_catch(sig_child, sigchld);  

  // XXX SIGINT, SIGTERM,

  /* do our normal workloop */
  doit();

  /* we shouldn't get here */
  return 1;
}
Beispiel #22
0
void restart(struct cyclog *d)
{
  struct stat st;
  int fd;
  int flagprocessed;

  if (fchdir(fdstartdir) == -1)
    strerr_die2sys(111,FATAL,"unable to switch to starting directory: ");

  mkdir(d->dir,0700);
  d->fddir = open_read(d->dir);
  if ((d->fddir == -1) || (fchdir(d->fddir) == -1))
    strerr_die4sys(111,FATAL,"unable to open directory ",d->dir,": ");
  coe(d->fddir);

  d->fdlock = open_append("lock");
  if ((d->fdlock == -1) || (lock_exnb(d->fdlock) == -1))
    strerr_die4sys(111,FATAL,"unable to lock directory ",d->dir,": ");
  coe(d->fdlock);

  if (stat("current",&st) == -1) {
    if (errno != error_noent)
      strerr_die4sys(111,FATAL,"unable to stat ",d->dir,"/current: ");
  }
  else
    if (st.st_mode & 0100) {
      fd = open_append("current");
      if (fd == -1)
        strerr_die4sys(111,FATAL,"unable to append to ",d->dir,"/current: ");
      if (fchmod(fd,0644) == -1)
        strerr_die4sys(111,FATAL,"unable to set mode of ",d->dir,"/current: ");
      coe(fd);
      d->fdcurrent = fd;
      d->bytes = st.st_size;
      return;
    }

  unlink("state");
  unlink("newstate");

  flagprocessed = 0;
  if (stat("processed",&st) == -1) {
    if (errno != error_noent)
      strerr_die4sys(111,FATAL,"unable to stat ",d->dir,"/processed: ");
  }
  else if (st.st_mode & 0100)
    flagprocessed = 1;

  if (flagprocessed) {
    unlink("previous");
    finish(d,"processed","s");
  }
  else {
    unlink("processed");
    finish(d,"previous","u");
  }

  finish(d,"current","u");

  fd = open_trunc("state");
  if (fd == -1)
    strerr_die4sys(111,FATAL,"unable to write to ",d->dir,"/state: ");
  close(fd);
  fd = open_append("current");
  if (fd == -1)
    strerr_die4sys(111,FATAL,"unable to write to ",d->dir,"/current: ");
  if (fchmod(fd,0644) == -1)
    strerr_die4sys(111,FATAL,"unable to set mode of ",d->dir,"/current: ");
  coe(fd);
  d->fdcurrent = fd;
  d->bytes = 0;
}
Beispiel #23
0
void fullcurrent(struct cyclog *d)
{
  int fd;
  int pid;
  int wstat;

  while (fchdir(d->fddir) == -1)
    pause3("unable to switch to ",d->dir,", pausing: ");

  while (fsync(d->fdcurrent) == -1)
    pause3("unable to write ",d->dir,"/current to disk, pausing: ");
  close(d->fdcurrent);

  while (rename("current","previous") == -1)
    pause3("unable to rename current to previous in directory ",d->dir,", pausing: ");
  while ((d->fdcurrent = open_append("current")) == -1)
    pause3("unable to create ",d->dir,"/current, pausing: ");
  coe(d->fdcurrent);
  d->bytes = 0;
  while (fchmod(d->fdcurrent,0644) == -1)
    pause3("unable to set mode of ",d->dir,"/current, pausing: ");

  while (chmod("previous",0744) == -1)
    pause3("unable to set mode of ",d->dir,"/previous, pausing: ");

  if (!d->processor)
    finish(d,"previous","s");
  else {
    for (;;) {
      while ((pid = fork()) == -1)
        pause3("unable to fork for processor in ",d->dir,", pausing: ");
      if (!pid) {
        startprocessor(d);
        strerr_die4sys(111,FATAL,"unable to run ",d->processor,": ");
      }
      if (wait_pid(&wstat,pid) == -1)
        pause3("wait failed for processor in ",d->dir,", pausing: ");
      else if (wait_crashed(wstat))
        pause3("processor crashed in ",d->dir,", pausing: ");
      else if (!wait_exitcode(wstat))
        break;
      strerr_warn4(WARNING,"processor failed in ",d->dir,", pausing",0);
      deepsleep(5);
    }

    while ((fd = open_append("processed")) == -1)
      pause3("unable to create ",d->dir,"/processed, pausing: ");
    while (fsync(fd) == -1)
      pause3("unable to write ",d->dir,"/processed to disk, pausing: ");
    while (fchmod(fd,0744) == -1)
      pause3("unable to set mode of ",d->dir,"/processed, pausing: ");
    close(fd);

    while ((fd = open_append("newstate")) == -1)
      pause3("unable to create ",d->dir,"/newstate, pausing: ");
    while (fsync(fd) == -1)
      pause3("unable to write ",d->dir,"/newstate to disk, pausing: ");
    close(fd);

    while (unlink("previous") == -1)
      pause3("unable to remove ",d->dir,"/previous, pausing: ");
    while (rename("newstate","state") == -1)
      pause3("unable to rename newstate to state in directory ",d->dir,", pausing: ");
    finish(d,"processed","s");
  }
}
Beispiel #24
0
int runsvdir_main(int argc, char **argv)
{
	struct stat s;
	dev_t last_dev = last_dev; /* for gcc */
	ino_t last_ino = last_ino; /* for gcc */
	time_t last_mtime = 0;
	int wstat;
	int curdir;
	int pid;
	unsigned deadline;
	unsigned now;
	unsigned stampcheck;
	char ch;
	int i;

	argv++;
	if (!*argv)
		bb_show_usage();
	if (argv[0][0] == '-') {
		switch (argv[0][1]) {
		case 'P': set_pgrp = 1;
		case '-': ++argv;
		}
		if (!*argv)
			bb_show_usage();
	}

	sig_catch(SIGTERM, s_term);
	sig_catch(SIGHUP, s_hangup);
	svdir = *argv++;
	if (argv && *argv) {
		rplog = *argv;
		if (setup_log() != 1) {
			rplog = 0;
			warnx("log service disabled");
		}
	}
	curdir = open_read(".");
	if (curdir == -1)
		fatal2_cannot("open current directory", "");
	coe(curdir);

	stampcheck = monotonic_sec();

	for (;;) {
		/* collect children */
		for (;;) {
			pid = wait_nohang(&wstat);
			if (pid <= 0)
				break;
			for (i = 0; i < svnum; i++) {
				if (pid == sv[i].pid) {
					/* runsv has gone */
					sv[i].pid = 0;
					check = 1;
					break;
				}
			}
		}

		now = monotonic_sec();
		if ((int)(now - stampcheck) >= 0) {
			/* wait at least a second */
			stampcheck = now + 1;

			if (stat(svdir, &s) != -1) {
				if (check || s.st_mtime != last_mtime
				 || s.st_ino != last_ino || s.st_dev != last_dev
				) {
					/* svdir modified */
					if (chdir(svdir) != -1) {
						last_mtime = s.st_mtime;
						last_dev = s.st_dev;
						last_ino = s.st_ino;
						check = 0;
						//if (now <= mtime)
						//	sleep(1);
						runsvdir();
						while (fchdir(curdir) == -1) {
							warn2_cannot("change directory, pausing", "");
							sleep(5);
						}
					} else
						warn2_cannot("change directory to ", svdir);
				}
			} else
				warn2_cannot("stat ", svdir);
		}

		if (rplog) {
			if ((int)(now - stamplog) >= 0) {
				write(logpipe[1], ".", 1);
				stamplog = now + 900;
			}
		}

		pfd[0].revents = 0;
		sig_block(SIGCHLD);
		deadline = (check ? 1 : 5);
		if (rplog)
			poll(pfd, 1, deadline*1000);
		else
			sleep(deadline);
		sig_unblock(SIGCHLD);

		if (pfd[0].revents & POLLIN) {
			while (read(logpipe[0], &ch, 1) > 0) {
				if (ch) {
					for (i = 6; i < rploglen; i++)
						rplog[i-1] = rplog[i];
					rplog[rploglen-1] = ch;
				}
			}
		}

		switch (exitsoon) {
		case 1:
			_exit(0);
		case 2:
			for (i = 0; i < svnum; i++)
				if (sv[i].pid)
					kill(sv[i].pid, SIGTERM);
			_exit(111);
		}
	}
	/* not reached */
	return 0;
}
Beispiel #25
0
int main(int argc, char **argv)
{
	struct sigaction sa;

	if (parse_argv(argc, argv) < 0)
		_exit(100);

	snprintf(status_files[0], 1024, "%s/lock", status_dir);
	snprintf(status_files[1], 1024, "%s/control", status_dir);
	snprintf(status_files[2], 1024, "%s/ok", status_dir);
	snprintf(status_files[3], 1024, "%s/status", status_dir);
	snprintf(status_files[4], 1024, "%s/status.new", status_dir);
	snprintf(status_files[5], 1024, "%s/supervise.log", status_dir);
	snprintf(status_files[6], 1024, "%s/supervise.log.wf", status_dir);

	sa.sa_handler = SIG_IGN;
	sigemptyset(&sa.sa_mask);
	if (sigaction(SIGHUP, &sa, NULL) < 0)
	{
		printf("unable to ignore SIGHUP for %s\n", service);  
		_exit(110);
	}

	if (mkdir(status_dir, 0700) < 0 && errno !=  EEXIST)
	{
		printf("unable to create dir: %s\n", status_dir);  
		_exit(110);
	}

	fdlog = open_append(status_files[5]);
	if (fdlog == -1)
	{
		printf("unable to open %s%s", status_dir, "/supervise.log");
		_exit(111);
	}
	coe(fdlog);

	fdlogwf = open_append(status_files[6]);
	if (fdlogwf == -1)
	{
		printf("unable to open %s%s", status_dir, "/supervise.log.wf");
		_exit(1);
	}
	coe(fdlogwf);

	if (daemon(1, 0) < 0)
	{
		printf("failed to daemonize supervise!\n");
		_exit(111);
	}

	if (pipe(selfpipe) == -1)
	{
		write_log(fdlogwf, FATAL, "unable to create pipe for ", service, "\n");
		_exit(111);
	}
	coe(selfpipe[0]);
	coe(selfpipe[1]);
	ndelay_on(selfpipe[0]);
	ndelay_on(selfpipe[1]);

	sig_block(sig_child);
	sig_catch(sig_child, trigger);

	sig_block(sig_alarm);
	sig_catch(sig_alarm, timer_handler);
	sig_unblock(sig_alarm);

	fdlock = open_append(status_files[0]);
	if ((fdlock == -1) || (lock_exnb(fdlock) == -1))
	{
		write_log(fdlogwf, FATAL, "Unable to acquier ", status_dir, "/lock\n");
		_exit(111);
	}
	coe(fdlock);

	fifo_make(status_files[1], 0600);
	fdcontrol = open_read(status_files[1]);
	if (fdcontrol == -1)
	{
		write_log(fdlogwf, FATAL, "unable to read ", status_dir, "/control\n");
		_exit(1);
	}
	coe(fdcontrol);
	ndelay_on(fdcontrol);

	fdcontrolwrite = open_write(status_files[1]);
	if (fdcontrolwrite == -1)
	{
		write_log(fdlogwf, FATAL, "unable to write ", status_dir, "/control\n");
		_exit(1);
	}
	coe(fdcontrolwrite);

	fifo_make(status_files[2], 0600);
	fdok = open_read(status_files[2]);
	if (fdok == -1)
	{
		write_log(fdlogwf, FATAL, "unable to read ", status_dir, "/ok\n");
		_exit(1);
	}
	coe(fdok);
	
	if (!restart_sh[0])
	{
		parse_conf(); 
	}
	pidchange();
	announce();

	if (!flagwant || flagwantup)
		trystart();
	doit();
	announce();

	_exit(0);
}
Beispiel #26
0
int main(int argc, char **argv)
{
    struct stat s;
    time_t mtime =0;
    int wstat;
    int curdir;
    int pid;
    struct taia deadline;
    struct taia now;
    struct taia stampcheck;
    char ch;
    int i;

    progname =*argv++;
    if (! argv || ! *argv) usage();
    if (**argv == '-')
    {
        switch (*(*argv +1))
        {
        case 'P':
            pgrp =1;
        case '-':
            ++argv;
        }
        if (! argv || ! *argv) usage();
    }

    sig_catch(sig_term, s_term);
    sig_catch(sig_hangup, s_hangup);
    svdir =*argv++;
    if (argv && *argv)
    {
        rplog =*argv;
        if (setup_log() != 1)
        {
            rplog =0;
            warn3x("log service disabled.", 0, 0);
        }
    }
    if ((curdir =open_read(".")) == -1)
        fatal("unable to open current directory", 0);
    coe(curdir);

    taia_now(&stampcheck);

    for (;;)
    {
        /* collect children */
        for (;;)
        {
            if ((pid =wait_nohang(&wstat)) <= 0) break;
            for (i =0; i < svnum; i++)
            {
                if (pid == sv[i].pid)
                {
                    /* runsv has gone */
                    sv[i].pid =0;
                    check =1;
                    break;
                }
            }
        }

        taia_now(&now);
        if (now.sec.x < (stampcheck.sec.x -3))
        {
            /* time warp */
            warn3x("time warp: resetting time stamp.", 0, 0);
            taia_now(&stampcheck);
            taia_now(&now);
            if (rplog) taia_now(&stamplog);
        }
        if (taia_less(&now, &stampcheck) == 0)
        {
            /* wait at least a second */
            taia_uint(&deadline, 1);
            taia_add(&stampcheck, &now, &deadline);

            if (stat(svdir, &s) != -1)
            {
                if (check || \
                        s.st_mtime != mtime || s.st_ino != ino || s.st_dev != dev)
                {
                    /* svdir modified */
                    if (chdir(svdir) != -1)
                    {
                        mtime =s.st_mtime;
                        dev =s.st_dev;
                        ino =s.st_ino;
                        check =0;
                        if (now.sec.x <= (4611686018427387914ULL +(uint64)mtime))
                            sleep(1);
                        runsvdir();
                        while (fchdir(curdir) == -1)
                        {
                            warn("unable to change directory, pausing", 0);
                            sleep(5);
                        }
                    }
                    else
                        warn("unable to change directory to ", svdir);
                }
            }
            else
                warn("unable to stat ", svdir);
        }

        if (rplog)
            if (taia_less(&now, &stamplog) == 0)
            {
                write(logpipe[1], ".", 1);
                taia_uint(&deadline, 900);
                taia_add(&stamplog, &now, &deadline);
            }
        /* half a second */
        deadline.sec.x =0;
        deadline.nano =500000000UL;
        deadline.atto =0;
        taia_add(&deadline, &now, &deadline);

        sig_block(sig_child);
        if (rplog)
            iopause(io, 1, &deadline, &now);
        else
            iopause(0, 0, &deadline, &now);
        sig_unblock(sig_child);

        if (rplog && (io[0].revents | IOPAUSE_READ))
            while (read(logpipe[0], &ch, 1) > 0)
                if (ch)
                {
                    for (i =6; i < rploglen; i++)
                        rplog[i -1] =rplog[i];
                    rplog[rploglen -1] =ch;
                }

        switch(exitsoon)
        {
        case 1:
            _exit(0);
        case 2:
            for (i =0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM);
            _exit(111);
        }
    } /* for (;;) */
    /* not reached */
    _exit(0);
}