1 #include <unistd.h>
2 #include "strerr.h"
3 #include "error.h"
4 #include "sgetopt.h"
5 #include "scan.h"
6 #include "open.h"
7 #include "tai.h"
8 #include "buffer.h"
9 #include "fmt.h"
10 
11 #define FATAL "svwaitup: fatal: "
12 #define WARN "svwaitup: warning: "
13 #define INFO "svwaitup: "
14 #define USAGE " [-v] [-s 1..600] service ..."
15 
16 const char *progname;
17 unsigned long sec =2;
18 unsigned int rc =0;
19 const char * const *dir;
20 
fatal(const char * m)21 void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); }
warn(const char * s1,const char * s2,struct strerr * e)22 void warn(const char *s1, const char *s2, struct strerr *e) {
23   dir++; rc++;
24   strerr_warn3(WARN, s1, s2, e);
25 }
usage()26 void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); }
27 
main(int argc,const char * const * argv)28 int main(int argc, const char * const *argv) {
29   int opt;
30   int verbose =0;
31   char status[18];
32   int fd;
33   int is;
34   int r;
35   int wdir;
36   unsigned long pid;
37   struct tai when;
38   struct tai now;
39   char sulong[FMT_ULONG];
40 
41   progname =*argv;
42 
43   while ((opt =getopt(argc, argv, "s:vV")) != opteof) {
44     switch(opt) {
45     case 's':
46       scan_ulong(optarg, &sec);
47       if ((sec < 1) || (sec > 600)) usage();
48       break;
49     case 'v':
50       verbose =1;
51       break;
52     case 'V':
53       strerr_warn1("$Id: e2d6c574c5e56f9931323fbc0e539c7f9b829b73 $", 0);
54     case '?':
55       usage();
56     }
57   }
58   argv +=optind;
59   if (! argv || ! *argv) usage();
60 
61   if ((wdir =open_read(".")) == -1)
62     fatal("unable to open current working directory");
63 
64   dir =argv;
65   while (*dir) {
66     if (dir != argv)
67       if (fchdir(wdir) == -1) fatal("unable to switch to starting directory");
68     if (chdir(*dir) == -1) {
69       warn(*dir, ": unable to change directory: ", &strerr_sys);
70       continue;
71     }
72     if ((fd =open_write("supervise/ok")) == -1) {
73       if (errno == error_nodevice)
74         warn(*dir, ": runsv not running.", 0);
75       else
76         warn(*dir, ": unable to open supervise/ok: ", &strerr_sys);
77       continue;
78     }
79     close(fd);
80 
81     if ((fd =open_read("supervise/status")) == -1) {
82       warn(*dir, "unable to open supervise/status: ", &strerr_sys);
83       continue;
84     }
85     r =buffer_unixread(fd, status, sizeof status);
86     close(fd);
87     if (r < sizeof status) {
88       if (r == -1)
89         warn(*dir, "unable to read supervise/status: ", &strerr_sys);
90       else
91         warn(*dir, ": unable to read supervise/status: bad format.", 0);
92       continue;
93     }
94 
95     pid =(unsigned char)status[15];
96     pid <<=8; pid +=(unsigned char)status[14];
97     pid <<=8; pid +=(unsigned char)status[13];
98     pid <<=8; pid +=(unsigned char)status[12];
99     if (! pid) {
100       warn(*dir, ": is down.", 0);
101       continue;
102     }
103 
104     tai_unpack(status, &when);
105     tai_now(&now);
106     if (tai_less(&now, &when)) when =now;
107     tai_sub(&when, &now, &when);
108     is =tai_approx(&when);
109 
110     if (is >= sec) {
111       /* ok */
112       if (verbose) {
113         sulong[fmt_ulong(sulong, is)] =0;
114         strerr_warn5(INFO, *dir, ": is up (", sulong, " seconds)", 0);
115       }
116       dir++;
117       continue;
118     }
119     sleep(sec -is);
120   }
121   if (fchdir(wdir) == -1)
122     strerr_warn2(WARN, "unable to switch to starting directory: ", &strerr_sys);
123   close(wdir);
124   if (rc > 100) rc =100;
125   _exit(rc);
126 }
127