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