1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <unistd.h>
4 #include "strerr.h"
5 #include "error.h"
6 #include "sgetopt.h"
7 #include "open.h"
8 #include "buffer.h"
9 #include "tai.h"
10 #include "fmt.h"
11
12 #define USAGE " [ -l ] service ..."
13
14
15 #define FATAL "runsvstat: fatal: "
16 #define WARNING "runsvstat: warning: "
17
18 const char *progname;
19 unsigned int rc =0;
20 struct stat s;
21 int showlog =0;
22
usage()23 void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); }
24
fatal(char * m1)25 void fatal(char *m1) { strerr_die3sys(111, FATAL, m1, ": "); }
warn(char * m1,char * m2)26 void warn(char *m1, char *m2) {
27 rc++;
28 strerr_warn5(WARNING, m1, ": ", m2, ": ", &strerr_sys);
29 }
warnx(char * m1,char * m2)30 void warnx(char *m1, char *m2) {
31 rc++;
32 strerr_warn4(WARNING, m1, ": ", m2, 0);
33 }
34
show_status(char * name)35 int show_status(char *name) {
36 char status[20];
37 int pid;
38 int fd;
39 int normallyup =0;
40 char sulong[FMT_ULONG];
41 struct tai when;
42 struct tai now;
43
44 if (stat("down", &s) == -1) {
45 if (errno != error_noent) {
46 warn(name, "unable to stat down");
47 return(-1);
48 }
49 normallyup = 1;
50 }
51 if ((fd =open_write("supervise/ok")) == -1) {
52 if (errno == error_nodevice)
53 warnx(name, "runsv not running.");
54 else
55 warn(name, "unable to open supervise/ok");
56 return(-1);
57 }
58 close(fd);
59 if ((fd =open_read("supervise/status")) == -1) {
60 warn(name, "unable to open supervise/status");
61 return(-1);
62 }
63 switch(read(fd, status, 20)) {
64 case 20: break;
65 case -1:
66 warn(name, "unable to read supervise/status");
67 return(-1);
68 default:
69 warnx(name, "unable to read supervise/status: bad format.");
70 return(-1);
71 }
72 pid =(unsigned char) status[15];
73 pid <<=8; pid +=(unsigned char)status[14];
74 pid <<=8; pid +=(unsigned char)status[13];
75 pid <<=8; pid +=(unsigned char)status[12];
76
77 tai_unpack(status,&when);
78 tai_now(&now);
79 if (tai_less(&now,&when)) when =now;
80 tai_sub(&when,&now,&when);
81
82 buffer_puts(buffer_1, name);
83 buffer_puts(buffer_1, ": ");
84 if (pid) {
85 switch (status[19]) {
86 case 1: buffer_puts(buffer_1, "run "); break;
87 case 2: buffer_puts(buffer_1, "finish "); break;
88 }
89 buffer_puts(buffer_1, "(pid ");
90 buffer_put(buffer_1, sulong, fmt_ulong(sulong, pid));
91 buffer_puts(buffer_1, ") ");
92 }
93 else
94 buffer_puts(buffer_1, "down ");
95 buffer_put(buffer_1, sulong, fmt_ulong(sulong, tai_approx(&when)));
96 buffer_puts(buffer_1, " seconds");
97 if (pid && !normallyup) buffer_puts(buffer_1,", normally down");
98 if (!pid && normallyup) buffer_puts(buffer_1,", normally up");
99 if (pid && status[16]) buffer_puts(buffer_1,", paused");
100 if (!pid && (status[17] == 'u')) buffer_puts(buffer_1,", want up");
101 if (pid && (status[17] == 'd')) buffer_puts(buffer_1,", want down");
102 if (pid && status[18]) buffer_puts(buffer_1, ", got TERM");
103 /* buffer_putsflush(buffer_1, "\n"); */
104 return(1);
105 }
106
main(int argc,char ** argv)107 int main(int argc, char **argv) {
108 int opt;
109 int curdir;
110 char **dir;
111
112 progname =*argv;
113
114 while ((opt =getopt(argc, (const char * const *)argv, "l")) != opteof) {
115 switch(opt) {
116 case 'l':
117 showlog =1;
118 break;
119 case '?':
120 usage();
121 }
122 }
123 argv +=optind;
124
125 dir =argv;
126 if (! dir || ! *dir) usage();
127
128 if ((curdir =open_read(".")) == -1) {
129 rc =100;
130 fatal("unable to open current directory");
131 }
132 for (; dir && *dir; dir++) {
133 if (chdir(*dir) == -1) {
134 warn(*dir, "unable to change directory");
135 continue;
136 }
137 if (show_status(*dir) == 1) {
138 if (showlog) {
139 if (stat("log", &s) == -1) {
140 if (errno != error_noent)
141 warn("unable to stat()", "./log");
142 }
143 else {
144 if (! S_ISDIR(s.st_mode))
145 warnx("./log", "not a directory.");
146 else {
147 if (chdir("log") == -1) {
148 warn(*dir, "unable to change directory");
149 continue;
150 }
151 show_status("\n log");
152 }
153 }
154 }
155 buffer_puts(buffer_1, "\n"); buffer_flush(buffer_1);
156 }
157 if (fchdir(curdir) == -1) {
158 rc =100;
159 fatal("unable to change directory");
160 }
161 }
162 if (rc > 100) rc =100;
163 _exit(rc);
164 }
165