aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-06-07 22:52:38 -0700
committerRob Landley <rob@landley.net>2019-06-10 15:08:08 -0500
commit1e229a235d9e011c4f64169e51be7ac4fa78bbde (patch)
treee68712c60331b51dfeff685916bc4c00ff3c7d6b
parente2551dbf740941572607f6eb50cab2cc23e59548 (diff)
downloadtoybox-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.c81
-rw-r--r--lib/lib.h2
-rw-r--r--toys/lsb/killall.c2
-rw-r--r--toys/posix/kill.c5
4 files changed, 71 insertions, 19 deletions
diff --git a/lib/lib.c b/lib/lib.c
index ffb24f65..17af3c35 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -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)
{
diff --git a/lib/lib.h b/lib/lib.h
index 080c533f..7f79bdb8 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -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;
}