diff options
author | Elliott Hughes <enh@google.com> | 2019-06-07 22:52:38 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-06-10 15:08:08 -0500 |
commit | 1e229a235d9e011c4f64169e51be7ac4fa78bbde (patch) | |
tree | e68712c60331b51dfeff685916bc4c00ff3c7d6b | |
parent | e2551dbf740941572607f6eb50cab2cc23e59548 (diff) | |
download | toybox-1e229a235d9e011c4f64169e51be7ac4fa78bbde.tar.gz |
Improve signal name<->number conversions.
Include all the signals, not just the POSIX ones.
In particular, improve support for real-time signals. My attempt to
switch AOSP builds over to toybox timeout got reverted when I broke the
ART build bots which use SIGRTMIN+2.
Also fix `kill -l 3` to show "QUIT" and `kill -l QUIT` to show "3".
Also make the `kill -l` output include numbers and names, and format it
to look better on a 80x24 tty, because it's always August 1978 somewhere.
-rw-r--r-- | lib/lib.c | 81 | ||||
-rw-r--r-- | lib/lib.h | 2 | ||||
-rw-r--r-- | toys/lsb/killall.c | 2 | ||||
-rw-r--r-- | toys/posix/kill.c | 5 |
4 files changed, 71 insertions, 19 deletions
@@ -454,6 +454,16 @@ int strstart(char **a, char *b) return i; } +// If *a starts with b, advance *a past it and return 1, else return 0; +int strcasestart(char **a, char *b) +{ + int len = strlen(b), i = !strncasecmp(*a, b, len); + + if (i) *a += len; + + return i; +} + // Return how long the file at fd is, if there's any way to determine it. off_t fdlength(int fd) { @@ -843,21 +853,22 @@ struct signame { #define SIGNIFY(x) {SIG##x, #x} static struct signame signames[] = { + // POSIX SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS), SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL), SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(TERM), SIGNIFY(USR1), SIGNIFY(USR2), SIGNIFY(SYS), SIGNIFY(TRAP), SIGNIFY(VTALRM), SIGNIFY(XCPU), SIGNIFY(XFSZ), + // Non-POSIX terminal signals + SIGNIFY(STKFLT), SIGNIFY(PROF), SIGNIFY(POLL), SIGNIFY(IO), SIGNIFY(PWR), - // Start of non-terminal signals - + // POSIX non-terminal signals SIGNIFY(CHLD), SIGNIFY(CONT), SIGNIFY(STOP), SIGNIFY(TSTP), - SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(URG) + SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(URG), + // Non-POSIX non-terminal signals + SIGNIFY(WINCH), }; -// not in posix: SIGNIFY(STKFLT), SIGNIFY(WINCH), SIGNIFY(IO), SIGNIFY(PWR) -// obsolete: SIGNIFY(PROF) SIGNIFY(POLL) - // Handler that sets toys.signal, and writes to toys.signalfd if set void generic_signal(int sig) { @@ -898,22 +909,35 @@ void sigatexit(void *handler) } } -// Convert name to signal number. If name == NULL print names. +// Convert a string like "9", "KILL", "SIGHUP", or "SIGRTMIN+2" to a number. int sig_to_num(char *pidstr) { - int i; + int i, offset; + char *s; - if (pidstr) { - char *s; + // Numeric? + i = estrtol(pidstr, &s, 10); + if (!errno && !*s) return i; - i = estrtol(pidstr, &s, 10); - if (!errno && !*s) return i; + // Skip leading "SIG". + strcasestart(&pidstr, "sig"); - if (!strncasecmp(pidstr, "sig", 3)) pidstr+=3; - } + // Named signal? for (i=0; i<ARRAY_LEN(signames); i++) - if (!pidstr) xputs(signames[i].name); - else if (!strcasecmp(pidstr, signames[i].name)) return signames[i].num; + if (!strcasecmp(pidstr, signames[i].name)) return signames[i].num; + + // Real-time signal? + if (strcasestart(&pidstr, "rtmin")) i = SIGRTMIN; + else if (strcasestart(&pidstr, "rtmax")) i = SIGRTMAX; + else return -1; + // No offset? + if (!*pidstr) return i; + // We allow any offset that's still a real-time signal: SIGRTMIN+20 is fine. + // Others are more restrictive, only accepting what they show with -l. + offset = estrtol(pidstr, &s, 10); + if (errno || *s) return -1; + i += offset; + if (i >= SIGRTMIN && i <= SIGRTMAX) return i; return -1; } @@ -922,11 +946,36 @@ char *num_to_sig(int sig) { int i; + // A named signal? for (i=0; i<ARRAY_LEN(signames); i++) if (signames[i].num == sig) return signames[i].name; + + // A real-time signal? + if (sig == SIGRTMIN) return "RTMIN"; + if (sig == SIGRTMAX) return "RTMAX"; + if (sig > SIGRTMIN && sig < SIGRTMAX) { + if (sig-SIGRTMIN <= SIGRTMAX-sig) sprintf(libbuf, "RTMIN+%d", sig-SIGRTMIN); + else sprintf(libbuf, "RTMAX-%d", SIGRTMAX-sig); + return libbuf; + } return NULL; } +// Output a nicely formatted 80-column table of all the signals. +void list_signals() +{ + int i = 0, count = 0; + char *name; + + for (; i<=SIGRTMAX; i++) { + if ((name = num_to_sig(i))) { + printf("%2d) SIG%-9s", i, name); + if (++count % 5 == 0) putchar('\n'); + } + } + putchar('\n'); +} + // premute mode bits based on posix mode strings. mode_t string_to_mode(char *modestr, mode_t mode) { @@ -229,6 +229,7 @@ char *chomp(char *s); int unescape(char c); char *strend(char *str, char *suffix); int strstart(char **a, char *b); +int strcasestart(char **a, char *b); off_t fdlength(int fd); void loopfiles_rw(char **argv, int flags, int permissions, void (*function)(int fd, char *name)); @@ -388,6 +389,7 @@ void generic_signal(int signal); void exit_signal(int signal); void sigatexit(void *handler); int sig_to_num(char *pidstr); +void list_signals(); char *num_to_sig(int sig); mode_t string_to_mode(char *mode_str, mode_t base); diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c index 8870618b..119e01fa 100644 --- a/toys/lsb/killall.c +++ b/toys/lsb/killall.c @@ -68,7 +68,7 @@ void killall_main(void) TT.signum = SIGTERM; if (toys.optflags & FLAG_l) { - sig_to_num(NULL); + list_signals(); return; } diff --git a/toys/posix/kill.c b/toys/posix/kill.c index f8e86b67..ee68980b 100644 --- a/toys/posix/kill.c +++ b/toys/posix/kill.c @@ -67,8 +67,9 @@ void kill_main(void) char *s = NULL; if (signum>=0) s = num_to_sig(signum&127); - puts(s ? s : "UNKNOWN"); - } else sig_to_num(NULL); + if (isdigit(**args)) puts(s ? s : "UNKNOWN"); + else printf("%d\n", signum); + } else list_signals(); return; } |