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