Exemple #1
0
static int check(char *a)
{
	unsigned pid;

	if ((r = svstatus_get()) == -1) return -1;
	if (r == 0) { if (*a == 'x') return 1; return -1; }
	pid = (unsigned char)svstatus[15];
	pid <<= 8; pid += (unsigned char)svstatus[14];
	pid <<= 8; pid += (unsigned char)svstatus[13];
	pid <<= 8; pid += (unsigned char)svstatus[12];
	switch (*a) {
	case 'x': return 0;
	case 'u':
		if (!pid || svstatus[19] != 1) return 0;
		if (!checkscript()) return 0;
		break;
	case 'd': if (pid) return 0; break;
	case 'c': if (pid) if (!checkscript()) return 0; break;
	case 't':
		if (!pid && svstatus[17] == 'd') break;
		tai_unpack(svstatus, &tstatus);
		if ((tstart.sec.x > tstatus.x) || !pid || svstatus[18] || !checkscript())
			return 0;
		break;
	case 'o':
		tai_unpack(svstatus, &tstatus);
		if ((!pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd'))
			return 0;
	}
	printf(OK); svstatus_print(*service); puts(""); /* will also flush the output */
	return 1;
}
Exemple #2
0
Datum tai_lte_pg(PG_FUNCTION_ARGS) {
  void *p1 = PG_GETARG_POINTER(0);
  void *p2 = PG_GETARG_POINTER(1);
  tai_t t1;
  tai_t t2;
  
  tai_unpack(&t1, p1);
  tai_unpack(&t2, p2);
  
  PG_RETURN_BOOL(tai_cmp(&t1, &t2) <= 0);
}
Exemple #3
0
static void showstatus(const char status[19], int r)
{
  const char *x;
  struct tai when;
  struct tai now;

  pid = (unsigned char) status[15];
  pid <<= 8; pid += (unsigned char) status[14];
  pid <<= 8; pid += (unsigned char) status[13];
  pid <<= 8; pid += (unsigned char) status[12];

  paused = status[16];
  want = status[17];
  statusflag = status[18];

  tai_unpack(status,&when);
  tai_now(&now);
  if (tai_less(&now,&when)) when = now;
  tai_sub(&when,&now,&when);

  if (pid) {
    buffer_puts(&b,"up (pid ");
    buffer_put(&b,strnum,fmt_ulong(strnum,pid));
    buffer_puts(&b,") ");
  }
  else
    buffer_puts(&b,"down ");

  buffer_put(&b,strnum,fmt_ulong(strnum,tai_approx(&when)));
  buffer_puts(&b," seconds");

  if (pid && !normallyup)
    buffer_puts(&b,", normally down");
  if (!pid && normallyup)
    buffer_puts(&b,", normally up");
  if (pid && paused)
    buffer_puts(&b,", paused");
  if (!pid && (want == 'u'))
    buffer_puts(&b,", want up");
  if (pid && (want == 'd'))
    buffer_puts(&b,", want down");
  if (r > 18) {
    switch (statusflag) {
    case svstatus_stopped: x = ", stopped"; break;
    case svstatus_starting: x = ", starting"; break;
    case svstatus_started: x = ", started"; break;
    case svstatus_running: x = ", running"; break;
    case svstatus_stopping: x = ", stopping"; break;
    case svstatus_failed: x=", failed"; break;
    default: x = ", status unknown";
    }
    if (x)
      buffer_puts(&b,x);
  }
}
Exemple #4
0
int leapsecs_read(void)
{
  char fbuf[1024];
  struct sstring sstr;
  struct stat sb;
  struct tai tai;
  struct tai *mem = 0;
  unsigned long size;
  unsigned long ind;
  int fd = -1;

  /* build path to leapsecs.dat */
  sstring_init(&sstr, fbuf, sizeof (fbuf));
  sstring_cats(&sstr, leapsecs_dir);
  if (sstr.len + sizeof("/leapsecs.dat") >= 1024) {
    errno = error_nametoolong;
    return -1;
  }
  sstring_cats(&sstr, "/leapsecs.dat");
  sstring_0(&sstr);

  /* open leapsecs.dat */
  fd = open_ro(sstr.s);
  if (fd == -1) {
    if (errno != error_noent) return -1;
    leapsecs_free();
    return 0;
  }

  if (fstat(fd, &sb) == -1) goto FAIL;

  /* map and unpack packed tai structures */
  mem = alloc(sb.st_size);
  if (!mem) goto FAIL;

  size = read(fd, mem, sb.st_size);
  if (size != (unsigned long) sb.st_size) { dealloc(mem); goto FAIL; }

  size = sb.st_size / sizeof(struct tai);
  for (ind = 0; ind < size; ++ind) {
    tai_unpack((unsigned char *) &mem[ind], &tai);
    mem[ind] = tai;
  }

  leapsecs_free();
  leapsecs_list = (struct tai *) mem;
  leapsecs_size = size;

  if (fd != -1) close(fd);
  return 0;

  FAIL:
  if (fd != -1) close(fd);
  return -1;
}
Exemple #5
0
int32_t leapsecs_sub(struct tai *lt)
{
#ifndef DISABLE_LEAPS
    char out[101],x[TAI_PACK]; double packerr;
    int32_t weekday,yearday,i,j,s; uint64_t u; struct tai t,t2; struct taitime ct2;
    if ( leaptais[0].x == 0 )
    {
        for (i=0; i<sizeof(leapseconds)/sizeof(*leapseconds); i++)
        {
            t = taidate_scan(leapseconds[i],i);
            if ( t.x == 0 )
                printf("unable to parse.(%s)\n",leapseconds[i]);
            else
            {
                //t = taitime2tai(ct);
                leaptais[i] = t;
                ct2 = tai2time(t,&weekday,&yearday);
                tai_pack(x,&t);
                tai_unpack(x,&t2);
                tai_sub(&t2,&t2,&t);
                packerr = tai_approx(&t2);
                for (j=0; j<TAI_PACK; j++)
                    printf("%2.2x",(uint32_t)(uint8_t)x[j]);
                if ( packerr != 0 )
                    printf(" packerr=%f",packerr);
                taitime_str(out,ct2);
                printf(" %03d  %s %s",yearday,dayname[weekday],out);
                printf("\n");
            }
        }
    }
    u = lt->x;
    if ( u > leaptais[sizeof(leaptais)/sizeof(*leaptais)-1].x )
        lt->x -= (sizeof(leaptais)/sizeof(*leaptais) - 1);
    else
    {
        s = 0;
        for (i=0; i<sizeof(leaptais)/sizeof(*leaptais); i++)
        {
            if ( u < leaptais[i].x )
                break;
            ++s;
            if ( u == leaptais[i].x )
            {
                lt->x = u - s;
                return(1);
            }
        }
        lt->x = u - s;
    }
#endif
    return(0);
}
Exemple #6
0
int check(char *a) {
  unsigned int pid;

  if ((r =svstatus_get()) == -1) return(-1);
  while (*a) {
    if (r == 0) { if (*a == 'x') return(1); return(-1); }
    pid =(unsigned char)svstatus[15];
    pid <<=8; pid +=(unsigned char)svstatus[14];
    pid <<=8; pid +=(unsigned char)svstatus[13];
    pid <<=8; pid +=(unsigned char)svstatus[12];
    switch (*a) {
    case 'x': return(0);
    case 'u':
      if (!pid || svstatus[19] != 1) return(0);
      if (!checkscript()) return(0);
      break;
    case 'd': if (pid || svstatus[19] != 0) return(0); break;
    case 'C': if (pid) if (!checkscript()) return(0); break;
    case 't':
    case 'k':
      if (!pid && svstatus[17] == 'd') break;
      tai_unpack(svstatus, &tstatus);
      if ((tstart.sec.x > tstatus.x) || !pid || svstatus[18] || !checkscript())
        return(0);
      break;
    case 'o':
      tai_unpack(svstatus, &tstatus);
      if ((!pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd'))
        return(0);
      break;
    case 'p': if (pid && !svstatus[16]) return(0); break;
    case 'c': if (pid && svstatus[16]) return(0); break;
    }
    ++a;
  }
  outs(OK); svstatus_print(*service); flush("\n");
  return(1);
}
Exemple #7
0
int main() {
  tai_t t = TAI_INIT;
  uint64_t x;
  char buf[TAI_PACK_SIZE];
  
  tai_now(&t);
  x = t.sec;
  
  tai_pack(&buf[0], &t);
  tai_unpack(&t, &buf[0]);
  
  if (t.sec == x)
    return 0;
    
  return 1;
}
Exemple #8
0
void taia_unpack(struct taia *ta, const char *s)
{
    unsigned long x;

    tai_unpack(&ta->sec, s);
    s += 8;
    x = (unsigned char)s[4];
    x <<= 8; x += (unsigned char)s[5];
    x <<= 8; x += (unsigned char)s[6];
    x <<= 8; x += (unsigned char)s[7];
    ta->atto = x;
    x = (unsigned char)s[0];
    x <<= 8; x += (unsigned char)s[1];
    x <<= 8; x += (unsigned char)s[2];
    x <<= 8; x += (unsigned char)s[3];
    ta->nano = x;
}
Exemple #9
0
void
taia_unpack(const char * s, struct taia * t)
{
    unsigned long x;

    tai_unpack(s, &t->sec);
    s += 8;

    x = (unsigned char)s[0];
    x <<= 8;
    x += (unsigned char)s[1];
    x <<= 8;
    x += (unsigned char)s[2];
    x <<= 8;
    x += (unsigned char)s[3];
    t->nano = x;
}
Exemple #10
0
void taia_unpack(const char *s, struct taia *t)
{
  uint32_t x;

  tai_unpack(s, &t->sec);
  s += 8;

  x = (unsigned char) s[4];
  x <<= 8; x += (unsigned char) s[5];
  x <<= 8; x += (unsigned char) s[6];
  x <<= 8; x += (unsigned char) s[7];
  t->atto = x;
  x = (unsigned char) s[0];
  x <<= 8; x += (unsigned char) s[1];
  x <<= 8; x += (unsigned char) s[2];
  x <<= 8; x += (unsigned char) s[3];
  t->nano = x;
}
Exemple #11
0
static int find(char *d,int flagwild)
{
  int r;
  char ch;
  struct tai cutoff;
  char ttd[8];
  char ttlstr[4];
  char recordloc[2];
  double newttl;

  for (;;) {
    r = cdb_findnext(&c,d,dns_domain_length(d));
    if (r <= 0) return r;
    dlen = cdb_datalen(&c);
    if (dlen > sizeof data) return -1;
    if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return -1;
    dpos = dns_packet_copy(data,dlen,0,type,2); if (!dpos) return -1;
    dpos = dns_packet_copy(data,dlen,dpos,&ch,1); if (!dpos) return -1;
    if ((ch == '=' + 1) || (ch == '*' + 1)) {
      --ch;
      dpos = dns_packet_copy(data,dlen,dpos,recordloc,2); if (!dpos) return -1;
      if (byte_diff(recordloc,2,clientloc)) continue;
    }
    if (flagwild != (ch == '*')) continue;
    dpos = dns_packet_copy(data,dlen,dpos,ttlstr,4); if (!dpos) return -1;
    uint32_unpack_big(ttlstr,&ttl);
    dpos = dns_packet_copy(data,dlen,dpos,ttd,8); if (!dpos) return -1;
    if (byte_diff(ttd,8,"\0\0\0\0\0\0\0\0")) {
      tai_unpack(ttd,&cutoff);
      if (ttl == 0) {
	if (tai_less(&cutoff,&now)) continue;
	tai_sub(&cutoff,&cutoff,&now);
	newttl = tai_approx(&cutoff);
	if (newttl <= 2.0) newttl = 2.0;
	if (newttl >= 3600.0) newttl = 3600.0;
	ttl = newttl;
      }
      else
	if (!tai_less(&cutoff,&now)) continue;
    }
    return 1;
  }
}
Exemple #12
0
unsigned int svstatus_print(char *m) {
  int pid;
  int normallyup =0;
  struct stat s;
 
  if (stat("down", &s) == -1) {
    if (errno != error_noent) {
      outs2(WARN); outs2("unable to stat "); outs2(*service); outs2("/down: ");
      outs2(error_str(errno)); flush2("\n");
      return(0);
    }
    normallyup =1;
  }
  pid =(unsigned char) svstatus[15];
  pid <<=8; pid +=(unsigned char)svstatus[14];
  pid <<=8; pid +=(unsigned char)svstatus[13];
  pid <<=8; pid +=(unsigned char)svstatus[12];
  tai_unpack(svstatus, &tstatus);
  switch (svstatus[19]) {
  case 0: outs(DOWN); break;
  case 1: outs(RUN); break;
  case 2: outs(FINISH); break;
  }
  outs(m); outs(": ");
  if (svstatus[19]) {
    outs("(pid "); sulong[fmt_ulong(sulong, pid)] =0;
    outs(sulong); outs(") ");
  }
  buffer_put(buffer_1, sulong,
    fmt_ulong(sulong, tnow.sec.x < tstatus.x ? 0 : tnow.sec.x -tstatus.x));
  outs("s");
  if (pid && !normallyup) outs(", normally down");
  if (!pid && normallyup) outs(", normally up");
  if (pid && svstatus[16]) outs(", paused");
  if (!pid && (svstatus[17] == 'u')) outs(", want up");
  if (pid && (svstatus[17] == 'd')) outs(", want down");
  if (pid && svstatus[18]) outs(", got TERM");
  return(pid ? 1 : 2);
}
Exemple #13
0
main()
{
  struct tai t;
  struct tai t2;
  struct caltime ct;
  struct caltime ct2;
  int weekday;
  int yearday;
  int i;
  double packerr;

  if (leapsecs_init() == -1)
    printf("unable to init leapsecs\n");

  while (fgets(line,sizeof line,stdin))
    if (!caltime_scan(line,&ct))
      printf("unable to parse\n");
    else {
      caltime_tai(&ct,&t);
      caltime_utc(&ct2,&t,&weekday,&yearday);
      tai_pack(x,&t);
      tai_unpack(x,&t2);
      tai_sub(&t2,&t2,&t);
      packerr = tai_approx(&t2);
      for (i = 0;i < TAI_PACK;++i)
        printf("%2.2x",(unsigned long) (unsigned char) x[i]);
      if (packerr)
        printf(" packerr=%f",packerr);
      printf(" %03d  %s",yearday,dayname[weekday]);
      if (caltime_fmt((char *) 0,&ct2) + 1 < sizeof out) {
        out[caltime_fmt(out,&ct2)] = 0;
        printf(" %s",out);
      }
      printf("\n");
    }
  return(0);
}
Exemple #14
0
static unsigned svstatus_print(char *m)
{
	int pid;
	int normallyup = 0;
	struct stat s;

	if (stat("down", &s) == -1) {
		if (errno != ENOENT) {
			bb_perror_msg(WARN"cannot stat %s/down", *service);
			return 0;
		}
		normallyup = 1;
	}
	pid = (unsigned char) svstatus[15];
	pid <<= 8; pid += (unsigned char)svstatus[14];
	pid <<= 8; pid += (unsigned char)svstatus[13];
	pid <<= 8; pid += (unsigned char)svstatus[12];
	tai_unpack(svstatus, &tstatus);
	if (pid) {
		switch (svstatus[19]) {
		case 1: printf(RUN); break;
		case 2: printf(FINISH); break;
		}
		printf("%s: (pid %d) ", m, pid);
	}
	else {
		printf(DOWN"%s: ", m);
	}
	printf("%lus", (unsigned long)(tnow.sec.x < tstatus.x ? 0 : tnow.sec.x-tstatus.x));
	if (pid && !normallyup) printf(", normally down");
	if (!pid && normallyup) printf(", normally up");
	if (pid && svstatus[16]) printf(", paused");
	if (!pid && (svstatus[17] == 'u')) printf(", want up");
	if (pid && (svstatus[17] == 'd')) printf(", want down");
	if (pid && svstatus[18]) printf(", got TERM");
	return pid ? 1 : 2;
}
Exemple #15
0
int
build (stralloc *sa, char *q, int flagsoa, char id[2])
{
    char ttl[4];
    char ttd[8];
    char type[2];
    char misc[20];
    char recordloc[2];
    struct tai cutoff;
    unsigned int rdatapos = 0;

    dpos = 0;
    copy (type, 2);
    if (flagsoa)
        if (byte_diff (type, 2, DNS_T_SOA))
            return 0;

    if (!flagsoa)
        if (byte_equal (type, 2, DNS_T_SOA))
            return 0;

    if (!stralloc_copyb (sa, id, 2))
        err (-1, "could not allocate enough memory");
    if (!stralloc_catb (sa, "\204\000\0\0\0\1\0\0\0\0", 10))
        err (-1, "could not allocate enough memory");
    copy (misc, 1);

    if ((misc[0] == '=' + 1) || (misc[0] == '*' + 1))
    {
        --misc[0];
        copy (recordloc, 2);
        if (byte_diff (recordloc, 2, clientloc))
            return 0;
    }
    if (misc[0] == '*')
    {
        if (flagsoa)
            return 0;
        if (!stralloc_catb (sa, "\1*", 2))
            err (-1, "could not allocate enough memory");
    }
    if (!stralloc_catb (sa, q, dns_domain_length (q)))
        err (-1, "could not allocate enough memory");
    if (!stralloc_catb (sa, type, 2))
        err (-1, "could not allocate enough memory");

    copy (ttl, 4);
    copy (ttd, 8);
    if (byte_diff (ttd, 8, "\0\0\0\0\0\0\0\0"))
    {
        tai_unpack (ttd, &cutoff);
        if (byte_equal (ttl, 4, "\0\0\0\0"))
        {
            if (tai_less (&cutoff, &now))
                return 0;
            uint32_pack_big (ttl, 2);
        }
        else
            if (!tai_less (&cutoff, &now))
                return 0;
    }

    if (!stralloc_catb (sa, DNS_C_IN, 2))
        err (-1, "could not allocate enough memory");
    if (!stralloc_catb (sa, ttl, 4))
        err (-1, "could not allocate enough memory");
    if (!stralloc_catb(sa,"\0\0",2))
        err (-1, "could not allocate enough memory");
    rdatapos = sa->len;

    if (byte_equal (type, 2, DNS_T_SOA))
    {
        doname (sa);
        doname (sa);
        copy (misc, 20);
        if (!stralloc_catb (sa, misc, 20))
            err (-1, "could not allocate enough memory");
    }
    else if (byte_equal (type, 2, DNS_T_NS)
             || byte_equal (type, 2, DNS_T_PTR)
             || byte_equal (type, 2, DNS_T_CNAME))
    {
        doname (sa);
    }
    else if (byte_equal (type, 2, DNS_T_MX))
    {
        copy (misc, 2);
        if (!stralloc_catb (sa, misc, 2))
            err (-1, "could not allocate enough memory");
        doname (sa);
    }
    else
    {
        if (!stralloc_catb (sa, data + dpos, dlen - dpos))
            err (-1, "could not allocate enough memory");
    }

    if (sa->len > 65535)
        errx (-1, "could not read from file `data.cdb': format error");
    uint16_pack_big (sa->s + rdatapos - 2, sa->len - rdatapos);

    return 1;
}
Exemple #16
0
void tain_unpack (char const *s, tain_t *t)
{
  tai_unpack(s, &t->sec) ;
  uint32_unpack_big(s+8, &t->nano) ;
}
Exemple #17
0
void doit(char *dir)
{
  struct stat st;
  int r;
  int fd;
  const char *x;
  struct tai when;
  struct tai now;

  buffer_puts(&b,dir);
  buffer_puts(&b,": ");

  if (chdir(dir) == -1) {
    x = error_str(errno);
    buffer_puts(&b,"unable to chdir: ");
    buffer_puts(&b,x);
    return;
  }

  normallyup = 0;
  if (stat("down",&st) == -1) {
    if (errno != error_noent) {
      x = error_str(errno);
      buffer_puts(&b,"unable to stat down: ");
      buffer_puts(&b,x);
      return;
    }
    normallyup = 1;
  }

  fd = open_write("supervise/ok");
  if (fd == -1) {
    if (errno == error_nodevice) {
      buffer_puts(&b,"supervise not running");
      return;
    }
    x = error_str(errno);
    buffer_puts(&b,"unable to open supervise/ok: ");
    buffer_puts(&b,x);
    return;
  }
  close(fd);

  fd = open_read("supervise/status");
  if (fd == -1) {
    x = error_str(errno);
    buffer_puts(&b,"unable to open supervise/status: ");
    buffer_puts(&b,x);
    return;
  }
  r = buffer_unixread(fd,status,sizeof status);
  close(fd);
  if (r < sizeof status) {
    if (r == -1)
      x = error_str(errno);
    else
      x = "bad format";
    buffer_puts(&b,"unable to read supervise/status: ");
    buffer_puts(&b,x);
    return;
  }

  pid = (unsigned char) status[15];
  pid <<= 8; pid += (unsigned char) status[14];
  pid <<= 8; pid += (unsigned char) status[13];
  pid <<= 8; pid += (unsigned char) status[12];

  paused = status[16];
  want = status[17];

  tai_unpack(status,&when);
  tai_now(&now);
  if (tai_less(&now,&when)) when = now;
  tai_sub(&when,&now,&when);

  if (pid) {
    buffer_puts(&b,"up (pid ");
    buffer_put(&b,strnum,fmt_ulong(strnum,pid));
    buffer_puts(&b,") ");
  }
  else
    buffer_puts(&b,"down ");

  buffer_put(&b,strnum,fmt_ulong(strnum,tai_approx(&when)));
  buffer_puts(&b," seconds");

  if (pid && !normallyup)
    buffer_puts(&b,", normally down");
  if (!pid && normallyup)
    buffer_puts(&b,", normally up");
  if (pid && paused)
    buffer_puts(&b,", paused");
  if (!pid && (want == 'u'))
    buffer_puts(&b,", want up");
  if (pid && (want == 'd'))
    buffer_puts(&b,", want down");
}
Exemple #18
0
int main(int argc, const char * const *argv)
{
    int opt;
    int verbose =0;
    char status[18];
    int fd;
    int is;
    int r;
    int wdir;
    unsigned long pid;
    struct tai when;
    struct tai now;
    char sulong[FMT_ULONG];

    progname =*argv;

    while ((opt =getopt(argc, argv, "s:vV")) != opteof)
    {
        switch(opt)
        {
        case 's':
            scan_ulong(optarg, &sec);
            if ((sec < 1) || (sec > 600)) usage();
            break;
        case 'v':
            verbose =1;
            break;
        case 'V':
            strerr_warn1("$Id: e2d6c574c5e56f9931323fbc0e539c7f9b829b73 $", 0);
        case '?':
            usage();
        }
    }
    argv +=optind;
    if (! argv || ! *argv) usage();

    if ((wdir =open_read(".")) == -1)
        fatal("unable to open current working directory");

    dir =argv;
    while (*dir)
    {
        if (dir != argv)
            if (fchdir(wdir) == -1) fatal("unable to switch to starting directory");
        if (chdir(*dir) == -1)
        {
            warn(*dir, ": unable to change directory: ", &strerr_sys);
            continue;
        }
        if ((fd =open_write("supervise/ok")) == -1)
        {
            if (errno == error_nodevice)
                warn(*dir, ": runsv not running.", 0);
            else
                warn(*dir, ": unable to open supervise/ok: ", &strerr_sys);
            continue;
        }
        close(fd);

        if ((fd =open_read("supervise/status")) == -1)
        {
            warn(*dir, "unable to open supervise/status: ", &strerr_sys);
            continue;
        }
        r =buffer_unixread(fd, status, sizeof status);
        close(fd);
        if (r < sizeof status)
        {
            if (r == -1)
                warn(*dir, "unable to read supervise/status: ", &strerr_sys);
            else
                warn(*dir, ": unable to read supervise/status: bad format.", 0);
            continue;
        }

        pid =(unsigned char)status[15];
        pid <<=8;
        pid +=(unsigned char)status[14];
        pid <<=8;
        pid +=(unsigned char)status[13];
        pid <<=8;
        pid +=(unsigned char)status[12];
        if (! pid)
        {
            warn(*dir, ": is down.", 0);
            continue;
        }

        tai_unpack(status, &when);
        tai_now(&now);
        if (tai_less(&now, &when)) when =now;
        tai_sub(&when, &now, &when);
        is =tai_approx(&when);

        if (is >= sec)
        {
            /* ok */
            if (verbose)
            {
                sulong[fmt_ulong(sulong, is)] =0;
                strerr_warn5(INFO, *dir, ": is up (", sulong, " seconds)", 0);
            }
            dir++;
            continue;
        }
        sleep(sec -is);
    }
    if (fchdir(wdir) == -1)
        strerr_warn2(WARN, "unable to switch to starting directory: ", &strerr_sys);
    close(wdir);
    if (rc > 100) rc =100;
    _exit(rc);
}