From c9e1c2f80fc508cc561d2d0d5de663ab05fa8402 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 10 Apr 2021 11:51:29 +0200 Subject: [PATCH] initctl: show exit status/signaled like systemctl - Show if exited/signaled - Show status code and the std /NAME - Show signal value and the std /NAME Signed-off-by: Joachim Wiberg --- src/initctl.c | 47 +++++++++++++++++++++++--- src/util.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 4 ++- 3 files changed, 139 insertions(+), 6 deletions(-) diff --git a/src/initctl.c b/src/initctl.c index dc3db66e..e7c80d62 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -607,15 +607,32 @@ static char *svc_environ(svc_t *svc, char *buf, size_t len) return buf; } -static char *status(svc_t *svc, int pretty) +static char *exit_status(int status, char *buf, size_t len) { - static char buf[25]; + int rc, sig; + + rc = WEXITSTATUS(status); + sig = WTERMSIG(status); + + if (WIFEXITED(status)) + snprintf(buf, len, " (code=exited, status=%d%s)", rc, code2str(rc)); + else if (WIFSIGNALED(status)) + snprintf(buf, len, " (code=signaled, signal=%d%s)", sig, sig2str(sig)); + + return buf; +} + +static char *status(svc_t *svc, int full) +{ + static char buf[64]; const char *color; + char ok[64] = {0}; char *s; s = svc_status(svc); switch (svc->state) { case SVC_HALTED_STATE: + exit_status(svc->status, ok, sizeof(ok)); color = "\e[1m"; break; @@ -623,16 +640,36 @@ static char *status(svc_t *svc, int pretty) color = "\e[1;32m"; break; + case SVC_DONE_STATE: + exit_status(svc->status, ok, sizeof(ok)); + if (WIFEXITED(svc->status)) { + if (WEXITSTATUS(svc->status)) + color = "\e[1;31m"; + else + color = "\e[1;32m"; + } else { + if (full && WIFSIGNALED(svc->status)) + color = "\e[1;31m"; + else + color = "\e[1;33m"; + } + break; + default: + exit_status(svc->status, ok, sizeof(ok)); color = "\e[1;33m"; break; } - if (!pretty || plain) + if (!full || plain) color = NULL; - snprintf(buf, sizeof(buf), "%s%-8.8s%s", - color ? color : "", s, color ? "\e[0m" : ""); + if (!full) + snprintf(buf, sizeof(buf), "%s%-8.8s%s", + color ? color : "", s, color ? "\e[0m" : ""); + else + snprintf(buf, sizeof(buf), "%s%s%s%s", + color ? color : "", s, ok, color ? "\e[0m" : ""); return buf; } diff --git a/src/util.c b/src/util.c index 306f0597..e4928a3c 100644 --- a/src/util.c +++ b/src/util.c @@ -61,6 +61,77 @@ int ttrows = 24; int ttcols = 80; char *prognm = NULL; +static char *signames[] = { + "" + "HUP", /* 1 */ + "INT", + "QUIT", + "ILL", + "TRAP", + "ABRT", + "BUS", + "FPE", /* 8 */ + "KILL", + "USR1", + "SEGV", + "USR2", + "PIPE", + "ALRM", + "TERM", + "STKFLT", /* 16 */ + "CHLD", + "CONT", + "STOP", + "TSTP", + "TTIN", + "TTOU", + "URG", + "XCPU", /* 24 */ + "XFSZ", + "VTALRM", + "PROF", + "WINCH", + "IO", + "PWR", + "SYS", +}; + +/* https://freedesktop.org/software/systemd/man/systemd.exec.html#id-1.20.8 */ +static char *exitcodes[] = { + "SUCCESS", /* 0: Std C exit OK */ + "FAILURE", /* 1: Std C exit FAIL */ + /* 2-7: LSB init scripts (usually) */ + "INVALIDARGUMENT", /* 2: Invalid or excess args */ + "NOTIMPLEMENTED", /* 3: Unimplemented feature, e.g. 'reload' */ + "NOPERMISSION", /* 4: Insufficient privilege */ + "NOTINSTALLED", /* 5: Program is not installed */ + "NOTCONFIGURED", /* 6: Program is not configured */ + "NOTRUNNING", /* 7: Program is not running */ + "", "", "", "", "", "", "", "", /* 8-63: Not standardized */ + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */ + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 32-47 */ + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 48-63 */ + /* 64-78: BSD, from sysexit.h */ + "USAGE", /* 64: Command line usage error */ + "DATAERR", /* 65: data format error */ + "NOINPUT", /* 66: cannot open input */ + "NOUSER", /* 67: addressee unknown */ + "NOHOST", /* 68: host name unknown */ + "UNAVAILABLE", /* 69: service unavailable */ + "SOFTWARE", /* 70: internal software error */ + "OSERR", /* 71: system error (e.g., can't fork) */ + "OSFILE", /* 72: critical OS file missing */ + "CANTCREAT", /* 73: can't create (user) output file */ + "IOERR", /* 74: input/output error */ + "TEMPFAIL", /* 75: temp failure; user is invited to retry */ + "PROTOCOL", /* 76: remote error in protocol */ + "NOPERM", /* 77: permission denied */ + "CONFIG", /* 78: configuration error */ + /* 79-199: Not standardized, typically 127 == -1 */ + /* >= 200: reserved (LSB), used by systemd */ +}; + + char *progname(char *arg0) { prognm = strrchr(arg0, '/'); @@ -154,6 +225,29 @@ int strtobytes(char *arg) return bytes; } +char *sig2str(int sig) +{ + static char signame[8]; + + if (sig < 1 || sig >= (int)NELEMS(signames)) + return ""; + + snprintf(signame, sizeof(signame), "/%s", signames[sig]); + return signame; +} + +char *code2str(int code) +{ + static char codename[20]; + + if (code < 0 || code >= (int)NELEMS(exitcodes)) + return ""; + + snprintf(codename, sizeof(codename), "/%s", exitcodes[code]); + return codename; +} + + void do_sleep(unsigned int sec) { struct timespec requested_sleep = { diff --git a/src/util.h b/src/util.h index 9d37d24e..0302e18d 100644 --- a/src/util.h +++ b/src/util.h @@ -52,8 +52,10 @@ int fnwrite (char *value, char *fmt, ...); int has_utmp (void); int strtobytes (char *arg); -void do_sleep (unsigned int sec); +char *sig2str (int sig); +char *code2str (int code); +void do_sleep (unsigned int sec); long jiffies (void); char *uptime (long secs, char *buf, size_t len); char *memsz (uint64_t sz, char *buf, size_t len);