Example #1
0
static void usage()
{
	struct tai t;
	tai_now(&t);
	printf("converter taiToIso|isoToTai tai|iso\n");
	printf("Current TAI: %lld\n", t.x);
}
Example #2
0
int respond(char *q,char qtype[2],char ip[4])
{
  int fd;
  int r;
  char key[6];

  tai_now(&now);
  fd = open_read("data.cdb");
  if (fd == -1) return 0;
  cdb_init(&c,fd);

  byte_zero(clientloc,2);
  key[0] = 0;
  key[1] = '%';
  byte_copy(key + 2,4,ip);
  r = cdb_find(&c,key,6);
  if (!r) r = cdb_find(&c,key,5);
  if (!r) r = cdb_find(&c,key,4);
  if (!r) r = cdb_find(&c,key,3);
  if (!r) r = cdb_find(&c,key,2);
  if (r == -1) return 0;
  if (r && (cdb_datalen(&c) == 2))
    if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) return 0;

  r = doit(q,qtype);

  cdb_free(&c);
  close(fd);
  return r;
}
Example #3
0
int main(int argc, char **argv)
{
  FILE *infile;
  int64_t l;
  char buffer[512*3];
  kum_6d6_header start_header[1], end_header[1];
  int e;

  i18n_set_lang(getenv("LANG"));

  int outdated = tai_leapsecs_need_update(tai_now());
  if (outdated) {
    fprintf(stderr, "%s", i18n->leapsec_outdated);
  }

  program = argv[0];
  parse_options(&argc, &argv, OPTIONS(
    FLAG_CALLBACK('h', "help", help)
  ));

  if (argc != 2) help(0);

  infile = fopen(argv[1], "rb");
  if (!infile) {
    e = errno;
    snprintf(buffer, sizeof(buffer), "/dev/%s", argv[1]);
    infile = fopen(buffer, "rb");
    if (!infile) {
      fprintf(stderr, i18n->could_not_open_ss, argv[1], i18n_error(e));
      exit(1);
    }
  }

  /* Drop root privileges if we had any. */
  uid_t uid = getuid();
  if (uid > 0 && setuid(uid) < 0) {
    fprintf(stderr, "%s", i18n->could_not_restore_uid);
    exit(1);
  }

  l = fread(buffer, 1, sizeof(buffer), infile);
  if (l < 1024 || kum_6d6_header_read(start_header, buffer) || kum_6d6_header_read(end_header, buffer + 512)) {
    /* Try to skip first 512 bytes. */
    if (l >= 3 * 512 &&
      kum_6d6_header_read(start_header, buffer + 512) == 0 &&
      kum_6d6_header_read(end_header, buffer + 1024) == 0) {
    } else {
      fprintf(stderr, "%s", i18n->malformed_6d6_header);
      exit(1);
    }
  }

  /* Show all the info. */
  kum_6d6_show_info(stdout, start_header, end_header);

  return 0;
}
Example #4
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);
  }
}
Example #5
0
int main() {
  int ret;
  tai_t a = TAI_INIT;
  tai_t b = TAI_INIT;
  tai_now(&a);
  tai_now(&b);
  
  b.sec++;
  
  ret = tai_cmp(&a, &a);
  if (ret != 0)
    return 1;
    
  ret = tai_cmp(&a, &b);
  if (ret != -1)
    return 2;
    
  ret = tai_cmp(&b, &a);
  if (ret != 1)
    return 3;
    
  return 0;
}
Example #6
0
int main(int argc, const char * argv[])
{
    int i; char str[111],str2[111],str3[111],str4[111]; struct taitime ct;
    struct tai t,start = tai_now();
    for (i=0; i<100; i++)
    {
        sleep(1);
        t = tai_now();
        taidate_str(str2,tai2date(t));
        printf("(%s) time.%s date.%s %ld start.%ld %s %u %u\n",tai_str(str3,t),taitime_str(str,ct),str2,(long)tai2utime(t),(long)tai2utime(start),utime_str(str4,t),tai2utc(t),(uint32_t)time(NULL));
    }
    // insert code here...
    {
        char str[65]; struct tai t; double startmillis; int32_t datenum,seconds; uint64_t i,checkval,timestamp,now = (uint32_t)time(NULL);
        startmillis = OS_milliseconds();
        for (i=0; i<1000000; i++)
        {
            timestamp = now - (rand() % 100000000LL); // range -100000000LL to +500000000LL
            datenum = OS_conv_unixtime(&t,&seconds,timestamp); // gmtime -> datenum + number of seconds
            checkval = OS_conv_datenum(datenum,seconds/3600,(seconds/60)%60,seconds%60); // datenum+H:M:S -> unix time
            if ( checkval != timestamp )
                printf("%s i.%lld timestamp.%-12llu -> (%d:%06d) -> checkval.%-12llu diff.[%lld]\n",tai_str(str,t),(long long)i,(long long)timestamp,datenum,seconds,(long long)checkval,(long long)(timestamp-checkval));
        }
        printf("million tai compares in %.3f microseconds per encode/decode\n",1000. * (OS_milliseconds()-startmillis)/i);
    }
   /* struct tai t = tai_now(); double diff,lastdiff = 0.;
    for (i=0; i<1000000; i++)
    {
        diff = tai_diff(t,tai_now());
        if ( diff < lastdiff )
            printf("embargo.x %f %llu.%3.3f %llu.%3.3f\n",tai_diff(t,tai_now()),(long long)t.x,t.millis,(long long)tai_now().x,tai_now().millis);
        lastdiff = diff;
        //usleep(100000);
    } getchar();
*/
    return 0;
}
Example #7
0
int main() {
  tai_t a = TAI_INIT;
  tai_t b = TAI_INIT;
  tai_t t = TAI_INIT;
  
  tai_now(&a);
  b.sec = TAI_EPOCH;
  
  tai_sub(&t, &a, &b);
  
  if (a.sec == (t.sec + TAI_EPOCH))
    return 0;
    
  return 1;
}
Example #8
0
/* Some versions of ls also fail to show the year for future dates. */
static long 
guess_year(unsigned long month,unsigned long day)
{
  static long this_year;
  static struct tai yearstart;
  struct tai x;
  struct tai now;
  tai_now(&now);

  if (!this_year) {
    struct tai n;
    tai_now(&n);
    this_year=1970;
    while (1) {
      utcdate2tai(&yearstart,this_year+1,0,1,0,0,0);
      if (tai_less(&n,&yearstart)) break;
      this_year++;
    }
  }
  utcdate2tai(&x,this_year,month,day,0,0,0);
  if (tai_less(&now,&x))
    return this_year-1;
  return this_year;
}
Example #9
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;
}
Example #10
0
int main()
{
    tai_t now = tai_now();
    printf("Current time:                    %"PRIi64"\n", now);

    tain_t now_ns = tain_now();
    printf("Current time (with nanoseconds): %"PRIi64".%"PRIi32"\n", now_ns.sec, now_ns.ns);

    printf("\n");

    printf("Accounting for leap seconds:\n");

    struct tm tm;
    printf("2015-06-30T23:59:59Z\n");
    strptime("2015-06-30T23:59:59Z", "%Y-%m-%dT%H:%M:%SZ", &tm);
    printf("TAI:  %"PRIi64"\n", tai_mktime(&tm));
    printf("UNIX: %ld\n", mktime(&tm));

    printf("2015-06-30T23:59:60Z\n");
    strptime("2015-06-30T23:59:60Z", "%Y-%m-%dT%H:%M:%SZ", &tm);
    printf("TAI:  %"PRIi64"\n", tai_mktime(&tm));
    printf("UNIX: %ld <== REPEATS\n", mktime(&tm));

    printf("2015-07-01T00:00:00Z\n");
    strptime("2015-07-01T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ", &tm);
    printf("TAI:  %"PRIi64"\n", tai_mktime(&tm));
    printf("UNIX: %ld\n", mktime(&tm));

    printf("\n");
    printf("Date with nanoseconds:\n");
    printf("2015-07-02T12:34:56,28931029Z\n");

    strptime("2015-07-02T12:34:56Z", "%Y-%m-%dT%H:%M:%SZ", &tm);
    tain_t time = tain_mktime(&tm, 28931029);

    printf("TAI:  %"PRIi64".%"PRIi32"\n", time.sec, time.ns);

    return 0;
}
Example #11
0
int respond(char *q,char qtype[2],char ip[4])
{
  static struct tai cdb_valid = { 0 };
  static int fd = -1;
  struct tai one_second;
  int r;
  char key[6];

  tai_now(&now);

  if (tai_less(&cdb_valid, &now)) {
    if (fd != -1) {
      cdb_free(&c);
      close(fd);
    }
    fd = open_read("data.cdb");
    if (fd == -1) return 0;
    cdb_init(&c,fd);
    tai_uint(&one_second, 1);
    tai_add(&cdb_valid, &now, &one_second);
  }
  byte_zero(clientloc,2);
  key[0] = 0;
  key[1] = '%';
  byte_copy(key + 2,4,ip);
  r = cdb_find(&c,key,6);
  if (!r) r = cdb_find(&c,key,5);
  if (!r) r = cdb_find(&c,key,4);
  if (!r) r = cdb_find(&c,key,3);
  if (!r) r = cdb_find(&c,key,2);
  if (r == -1) return 0;
  if (r && (cdb_datalen(&c) == 2))
    if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) return 0;

  r = doit(q,qtype);

  return r;
}
Example #12
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");
}
Example #13
0
void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *retjson,cJSON *json,char *hexmsg,char *remoteaddr)
{
    int32_t len,flag=0; char *str; uint8_t _buf[8192],*buf = _buf; bits256 categoryhash,subhash; struct category_info *cat;
    if ( hexmsg != 0 )
    {
        len = (int32_t)strlen(hexmsg);
        if ( is_hexstr(hexmsg,len) > 0 )
        {
            len >>= 1;
            if ( len > sizeof(_buf) )
                buf = malloc(len);
            decode_hex(buf,len,hexmsg);
            categoryhash = jbits256(json,"categoryhash");
            subhash = jbits256(json,"categoryhash");
            if ( bits256_nonz(subhash) == 0 )
                subhash = GENESIS_PUBKEY;
            if ( (cat= category_find(categoryhash,subhash)) != 0 )
            {
                if ( cat->processfunc != 0 )
                {
                    if ( (str= (*cat->processfunc)(myinfo,buf,len,remoteaddr)) != 0 )
                    {
                        if ( retjson != 0 )
                            jaddstr(retjson,"processfunc",str);
                        else free(str);
                    }
                    flag = 1;
                    //printf("PROCESSFUNC\n");
                }
            }
            if ( flag == 0 )
            {
                printf("no processfunc, posthexmsg\n");
                category_posthexmsg(myinfo,categoryhash,jbits256(json,"subhash"),hexmsg,tai_now(),remoteaddr);
            }
            //char str[65]; printf("HEXPROCESS.(%s) -> %s\n",hexmsg,bits256_str(str,categoryhash));
            if ( buf != _buf )
                free(buf);
        }
Example #14
0
void
doaxfr (char id[2])
{
    int r = 0;
    char num[4];
    char key[512];
    uint32 klen = 0;
    uint32 eod = 0, pos = 0;

    axfrcheck (zone);

    tai_now (&now);
    cdb_init (&c, fdcdb);

    byte_zero (clientloc, 2);
    key[0] = 0;
    key[1] = '%';
    byte_copy (key + 2, 4, ip);
    r = cdb_find (&c, key, 6);

    if (!r)
        r = cdb_find (&c, key, 5);
    if (!r)
        r = cdb_find (&c, key, 4);
    if (!r)
        r = cdb_find (&c, key, 3);
    if (!r)
        r = cdb_find (&c, key, 2);
    if (r == -1)
        errx (-1, "could not read from file `data.cdb'");
    if (r && (cdb_datalen (&c) == 2))
        if (cdb_read (&c, clientloc, 2, cdb_datapos (&c)) == -1)
            err (-1, "could not read from file `data.cdb'");

    cdb_findstart (&c);
    for (;;)
    {
        r = cdb_findnext (&c, zone, zonelen);
        if (r == -1)
            errx (-1, "could not read from file `data.cdb'");
        if (!r)
            errx (-1, "could not find information in `data.cdb'");
        dlen = cdb_datalen (&c);
        if (dlen > sizeof data)
            errx (-1, "could not read from file `data.cdb': format error");
        if (cdb_read (&c, data, dlen, cdb_datapos (&c)) == -1)
            errx (-1, "could not read from file `data.cdb': format error");
        if (build (&soa, zone, 1, id))
            break;
    }

    cdb_free (&c);
    print (soa.s, soa.len);

    seek_begin (fdcdb);
    buffer_init (&bcdb, buffer_unixread, fdcdb, bcdbspace, sizeof (bcdbspace));

    pos = 0;
    get (num, 4);
    pos += 4;
    uint32_unpack (num, &eod);
    while (pos < 2048)
    {
        get (num, 4);
        pos += 4;
    }

    while (pos < eod)
    {
        if (eod - pos < 8)
            errx (-1, "could not read from file `data.cdb': format error");
        get (num, 4);
        pos += 4;
        uint32_unpack (num, &klen);
        get (num,4);
        pos += 4;
        uint32_unpack (num, &dlen);
        if (eod - pos < klen)
            errx (-1, "could not read from file `data.cdb': format error");
        pos += klen;
        if (eod - pos < dlen)
            errx (-1, "could not read from file `data.cdb': format error");
        pos += dlen;

        if (klen > sizeof key)
            errx (-1, "could not read from file `data.cdb': format error");
        get (key, klen);
        if (dlen > sizeof data)
            errx (-1, "could not read from file `data.cdb': format error");
        get (data, dlen);

        if ((klen > 1) && (key[0] == 0))
            continue; /* location */
        if (klen < 1)
            errx (-1, "could not read from file `data.cdb': format error");
        if (dns_packet_getname (key, klen, 0, &q) != klen)
            errx (-1, "could not read from file `data.cdb': format error");
        if (!dns_domain_suffix (q, zone))
            continue;
        if (!build (&message, q, 0, id))
            continue;
        print (message.s, message.len);
    }

    print (soa.s, soa.len);
}
Example #15
0
void doaxfr(char id[2])
{
  char key[512];
  uint32 klen;
  char num[4];
  uint32 eod;
  uint32 pos;
  int r;

  axfrcheck(zone);

  find_client_loc(clientloc, ip);

  tai_now(&now);
  cdb_init(&c,fdcdb);

  cdb_findstart(&c);
  for (;;) {
    r = cdb_findnext(&c,zone,zonelen);
    if (r == -1) die_cdbread();
    if (!r) die_outside();
    dlen = cdb_datalen(&c);
    if (dlen > sizeof data) die_cdbformat();
    if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) die_cdbformat();
    if (build(&soa,zone,1,id)) break;
  }

  cdb_free(&c);
  print(soa.s,soa.len);

  seek_begin(fdcdb);
  buffer_init(&bcdb,buffer_unixread,fdcdb,bcdbspace,sizeof bcdbspace);

  pos = 0;
  get(num,4); pos += 4;
  uint32_unpack(num,&eod);
  while (pos < 2048) { get(num,4); pos += 4; }

  while (pos < eod) {
    if (eod - pos < 8) die_cdbformat();
    get(num,4); pos += 4;
    uint32_unpack(num,&klen);
    get(num,4); pos += 4;
    uint32_unpack(num,&dlen);
    if (eod - pos < klen) die_cdbformat();
    pos += klen;
    if (eod - pos < dlen) die_cdbformat();
    pos += dlen;

    if (klen > sizeof key) die_cdbformat();
    get(key,klen);
    if (dlen > sizeof data) die_cdbformat();
    get(data,dlen);

    if ((klen > 1) && (key[0] == 0)) continue; /* location */
    if (klen < 1) die_cdbformat();
    if (dns_packet_getname(key,klen,0,&q) != klen) die_cdbformat();
    if (!dns_domain_suffix(q,zone)) continue;
    if (!build(&message,q,0,id)) continue;
    print(message.s,message.len);
  }

  print(soa.s,soa.len);
}
Example #16
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);
}
Example #17
0
int main(int argc, const char * const *argv) {
  int opt;
  unsigned long sec =600;
  int verbose =0;
  int doexit =0;
  int dokill =0;
  int wdir;
  int fd;
  char status[20];
  int r;
  unsigned long pid;
  struct tai start;
  struct tai now;
  
  progname =*argv;
  
  while ((opt =getopt(argc, argv, "t:xkvV")) != opteof) {
    switch(opt) {
    case 't':
      scan_ulong(optarg, &sec);
      if ((sec < 1) || (sec > 6000)) usage();
      break;
    case 'x':
      doexit =1;
      break;
    case 'k':
      dokill =1;
      break;
    case 'v':
      verbose =1;
      break;
    case 'V':
      strerr_warn1(VERSION, 0);
    case '?':
      usage();
    }
  }
  argv +=optind;
  if (! argv || ! *argv) usage();

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

  for (dir =argv; *dir; ++dir) {
    if (dir != argv)
      if (fchdir(wdir) == -1) fatal("unable to switch to starting directory");
    if (chdir(*dir) == -1) continue; /* bummer */
    if ((fd =open_write("supervise/control")) == -1) continue; /* bummer */
    if (write(fd, "dx", 1 +doexit) != (1 +doexit)) {
      close(fd); continue; /* bummer */
    }
    close(fd);
  }
  dir =argv;

  tai_now(&start);
  while (*dir) {
    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) {
        if (verbose) strerr_warn3(INFO, *dir, ": runsv not running.", 0);
        dir++;
      }
      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, 20);
    close(fd);
    if ((r < 18) || (r == 19)) { /* supervise compatibility */
      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 (! doexit && ! pid) {
      /* ok, service is down */
      if (verbose) strerr_warn3(INFO, *dir, ": down.", 0);
      dir++;
      continue;
    }

    if (status[17] != 'd') { /* catch previous failures */
      if ((fd =open_write("supervise/control")) == -1) {
        warn(*dir, ": unable to open supervise/control: ", &strerr_sys);
        continue;
      }
      if (write(fd, "dx", 1 +doexit) != (1 +doexit)) {
        warn(*dir, ": unable to write to supervise/control: ", &strerr_sys);
        close(fd);
        continue;
      }
      close(fd);
    }
  
    tai_now(&now);
    tai_sub(&now, &now, &start);
    if (tai_approx(&now) >= sec) {
      /* timeout */
      if (verbose) strerr_warn2(INFO, "timeout.", 0);
      if (dokill) {
        if (chdir(*dir) == -1) {
          warn(*dir, ": unable to change directory: ", &strerr_sys);
          continue;
        }
        if ((fd =open_write("supervise/control")) == -1) {
          if (errno == error_nodevice) {
            if (verbose)
              strerr_warn3(INFO, *dir, ": runsv not running.", 0);
            dir++;
          }
          else
            warn(*argv, ": unable to open supervise/control: ", &strerr_sys);
          continue;
        }
        if (write(fd, "k", 1) != 1)
          warn(*argv, ": unable to write to supervise/control: ", &strerr_sys);
        else
          strerr_warn3(INFO, *dir, ": killed.", 0);
        close(fd);
        dir++;
        if (! *dir) _exit(111);
        continue;
      }
      _exit(111);
    }
    sleep(1);
  }
  if (fchdir(wdir) == -1) 
    strerr_warn2(WARN, "unable to switch to starting directory: ", &strerr_sys);
  close(wdir);
  if (rc > 100) rc =100;
  _exit(rc);
}