rustit/mirror_runit/runit-2.1.2/src/runsvstat.c
2024-03-24 23:51:57 +00:00

167 lines
4.1 KiB
C

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "strerr.h"
#include "error.h"
#include "sgetopt.h"
#include "open.h"
#include "buffer.h"
#include "tai.h"
#include "fmt.h"
#define USAGE " [ -l ] service ..."
#define VERSION "$Id: c17bbd3eda6f3c57027dfb47ff676bdd3fefff9f $"
#define FATAL "runsvstat: fatal: "
#define WARNING "runsvstat: warning: "
const char *progname;
unsigned int rc =0;
struct stat s;
int showlog =0;
void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); }
void fatal(char *m1) { strerr_die3sys(111, FATAL, m1, ": "); }
void warn(char *m1, char *m2) {
rc++;
strerr_warn5(WARNING, m1, ": ", m2, ": ", &strerr_sys);
}
void warnx(char *m1, char *m2) {
rc++;
strerr_warn4(WARNING, m1, ": ", m2, 0);
}
int show_status(char *name) {
char status[20];
int pid;
int fd;
int normallyup =0;
char sulong[FMT_ULONG];
struct tai when;
struct tai now;
if (stat("down", &s) == -1) {
if (errno != error_noent) {
warn(name, "unable to stat down");
return(-1);
}
normallyup = 1;
}
if ((fd =open_write("supervise/ok")) == -1) {
if (errno == error_nodevice)
warnx(name, "runsv not running.");
else
warn(name, "unable to open supervise/ok");
return(-1);
}
close(fd);
if ((fd =open_read("supervise/status")) == -1) {
warn(name, "unable to open supervise/status");
return(-1);
}
switch(read(fd, status, 20)) {
case 20: break;
case -1:
warn(name, "unable to read supervise/status");
return(-1);
default:
warnx(name, "unable to read supervise/status: bad format.");
return(-1);
}
pid =(unsigned char) status[15];
pid <<=8; pid +=(unsigned char)status[14];
pid <<=8; pid +=(unsigned char)status[13];
pid <<=8; pid +=(unsigned char)status[12];
tai_unpack(status,&when);
tai_now(&now);
if (tai_less(&now,&when)) when =now;
tai_sub(&when,&now,&when);
buffer_puts(buffer_1, name);
buffer_puts(buffer_1, ": ");
if (pid) {
switch (status[19]) {
case 1: buffer_puts(buffer_1, "run "); break;
case 2: buffer_puts(buffer_1, "finish "); break;
}
buffer_puts(buffer_1, "(pid ");
buffer_put(buffer_1, sulong, fmt_ulong(sulong, pid));
buffer_puts(buffer_1, ") ");
}
else
buffer_puts(buffer_1, "down ");
buffer_put(buffer_1, sulong, fmt_ulong(sulong, tai_approx(&when)));
buffer_puts(buffer_1, " seconds");
if (pid && !normallyup) buffer_puts(buffer_1,", normally down");
if (!pid && normallyup) buffer_puts(buffer_1,", normally up");
if (pid && status[16]) buffer_puts(buffer_1,", paused");
if (!pid && (status[17] == 'u')) buffer_puts(buffer_1,", want up");
if (pid && (status[17] == 'd')) buffer_puts(buffer_1,", want down");
if (pid && status[18]) buffer_puts(buffer_1, ", got TERM");
/* buffer_putsflush(buffer_1, "\n"); */
return(1);
}
int main(int argc, char **argv) {
int opt;
int curdir;
char **dir;
progname =*argv;
while ((opt =getopt(argc, (const char * const *)argv, "lV")) != opteof) {
switch(opt) {
case 'l':
showlog =1;
break;
case 'V':
strerr_warn1(VERSION, 0);
case '?':
usage();
}
}
argv +=optind;
dir =argv;
if (! dir || ! *dir) usage();
if ((curdir =open_read(".")) == -1) {
rc =100;
fatal("unable to open current directory");
}
for (; dir && *dir; dir++) {
if (chdir(*dir) == -1) {
warn(*dir, "unable to change directory");
continue;
}
if (show_status(*dir) == 1) {
if (showlog) {
if (stat("log", &s) == -1) {
if (errno != error_noent)
warn("unable to stat()", "./log");
}
else {
if (! S_ISDIR(s.st_mode))
warnx("./log", "not a directory.");
else {
if (chdir("log") == -1) {
warn(*dir, "unable to change directory");
continue;
}
show_status("\n log");
}
}
}
buffer_puts(buffer_1, "\n"); buffer_flush(buffer_1);
}
if (fchdir(curdir) == -1) {
rc =100;
fatal("unable to change directory");
}
}
if (rc > 100) rc =100;
_exit(rc);
}