1 #include <unistd.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include "strerr.h"
5 #include "error.h"
6 #include "open.h"
7 #include "fmt.h"
8 #include "tai.h"
9 #include "buffer.h"
10 #include "sgetopt.h"
11 #include "svpath.h"
12 #include "svstatus.h"
13
14 #define FATAL "svstat: fatal: "
15 #define WARNING "svstat: warning: "
16
17 char bspace[1024];
18 buffer b = BUFFER_INIT(buffer_unixwrite,1,bspace,sizeof bspace);
19
20 char strnum[FMT_ULONG];
21
22 int check_log = -1;
23
die_nomem(void)24 static void die_nomem(void)
25 {
26 strerr_die2sys(111,FATAL,"unable to allocate memory");
27 }
28
die_usage(void)29 static void die_usage(void)
30 {
31 strerr_die1x(100,"svstat: usage: svstat [-L] [-l] dir [dir ...]");
32 }
33
showstatus(const char status[19],int r,int normallyup)34 static void showstatus(const char status[19], int r, int normallyup)
35 {
36 const char *x;
37 struct tai when;
38 struct tai now;
39 unsigned long pid;
40 unsigned char want;
41 unsigned char paused;
42 enum svstatus statusflag;
43
44 pid = (unsigned char) status[15];
45 pid <<= 8; pid += (unsigned char) status[14];
46 pid <<= 8; pid += (unsigned char) status[13];
47 pid <<= 8; pid += (unsigned char) status[12];
48
49 paused = status[16];
50 want = status[17];
51 statusflag = status[18];
52
53 tai_unpack(status,&when);
54 tai_now(&now);
55 if (tai_less(&now,&when)) when = now;
56 tai_sub(&when,&now,&when);
57
58 if (pid) {
59 buffer_puts(&b,"up (pid ");
60 buffer_put(&b,strnum,fmt_ulong(strnum,pid));
61 buffer_puts(&b,") ");
62 }
63 else
64 buffer_puts(&b,"down ");
65
66 buffer_put(&b,strnum,fmt_ulong(strnum,tai_approx(&when)));
67 buffer_puts(&b," seconds");
68
69 if (pid && !normallyup)
70 buffer_puts(&b,", normally down");
71 if (!pid && normallyup)
72 buffer_puts(&b,", normally up");
73 if (pid && paused)
74 buffer_puts(&b,", paused");
75 if (!pid && (want == 'u'))
76 buffer_puts(&b,", want up");
77 if (pid && (want == 'd'))
78 buffer_puts(&b,", want down");
79 if (r > 18) {
80 switch (statusflag) {
81 case svstatus_stopped: x = ", stopped"; break;
82 case svstatus_starting: x = ", starting"; break;
83 case svstatus_started: x = ", started"; break;
84 case svstatus_running: x = ", running"; break;
85 case svstatus_stopping: x = ", stopping"; break;
86 case svstatus_failed: x=", failed"; break;
87 default: x = ", status unknown";
88 }
89 if (pid && (want == '\000'))
90 buffer_puts(&b,", once");
91 if (x)
92 buffer_puts(&b,x);
93 }
94 }
95
doit(const char * dir)96 void doit(const char *dir)
97 {
98 struct stat st;
99 int r;
100 int fd;
101 const char *x;
102 const char *fntemp;
103 char status[40];
104 unsigned char normallyup;
105
106 buffer_puts(&b,dir);
107
108 if (chdir(dir) == -1) {
109 x = error_str(errno);
110 buffer_puts(&b,": unable to chdir: ");
111 buffer_puts(&b,x);
112 return;
113 }
114 if (!svpath_init()) {
115 strerr_warn4sys(WARNING,"unable to set up control path for ",dir,"");
116 return;
117 }
118
119 normallyup = 0;
120 if (stat("down",&st) == -1) {
121 if (errno != error_noent) {
122 x = error_str(errno);
123 buffer_puts(&b,": unable to stat down: ");
124 buffer_puts(&b,x);
125 return;
126 }
127 normallyup = 1;
128 }
129
130 if ((fntemp = svpath_make("/ok")) == 0) die_nomem();
131 fd = open_write(fntemp);
132 if (fd == -1) {
133 if (errno == error_nodevice) {
134 buffer_puts(&b,": supervise not running");
135 return;
136 }
137 x = error_str(errno);
138 buffer_puts(&b,": unable to open ");
139 buffer_puts(&b,fntemp);
140 buffer_puts(&b,": ");
141 buffer_puts(&b,x);
142 return;
143 }
144 close(fd);
145
146 if ((fntemp = svpath_make("/status")) == 0) die_nomem();
147 fd = open_read(fntemp);
148 if (fd == -1) {
149 x = error_str(errno);
150 buffer_puts(&b,": unable to open ");
151 buffer_puts(&b,fntemp);
152 buffer_puts(&b,": ");
153 buffer_puts(&b,x);
154 return;
155 }
156 r = buffer_unixread(fd,status,sizeof status);
157 close(fd);
158 if (r < 18) {
159 if (r == -1)
160 x = error_str(errno);
161 else
162 x = "bad format";
163 buffer_puts(&b,": unable to read ");
164 buffer_puts(&b,fntemp);
165 buffer_puts(&b,": ");
166 buffer_puts(&b,x);
167 return;
168 }
169 if (check_log != 1) {
170 buffer_puts(&b,": ");
171 showstatus(status,r,normallyup);
172 }
173 if (check_log != 0) {
174 if (r >= 20+18) {
175 if (check_log < 0) {
176 buffer_puts(&b,"\n");
177 buffer_puts(&b,dir);
178 }
179 buffer_puts(&b," log: ");
180 showstatus(status+20,r-20,normallyup);
181 }
182 else if (check_log == 1)
183 buffer_puts(&b,": no log service");
184 }
185 }
186
main(int argc,const char * const * argv)187 int main(int argc,const char *const *argv)
188 {
189 int fdorigdir;
190 const char *dir;
191 int opt;
192
193 while ((opt = getopt(argc,argv,"lL")) != opteof) {
194 switch (opt) {
195 case 'L':
196 check_log = 1;
197 break;
198 case 'l':
199 check_log = 0;
200 break;
201 default:
202 die_usage();
203 }
204 }
205 argv += optind;
206
207 if (!argv[0])
208 die_usage();
209
210 fdorigdir = open_read(".");
211 if (fdorigdir == -1)
212 strerr_die2sys(111,FATAL,"unable to open current directory");
213
214 while ((dir = *argv++) != 0) {
215 doit(dir);
216 buffer_puts(&b,"\n");
217 if (fchdir(fdorigdir) == -1)
218 strerr_die2sys(111,FATAL,"unable to set directory");
219 }
220
221 buffer_flush(&b);
222
223 _exit(0);
224 }
225