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.
---
 lib/lib.c          | 81 +++++++++++++++++++++++++++++++++++++---------
 lib/lib.h          |  2 ++
 toys/lsb/killall.c |  2 +-
 toys/posix/kill.c  |  5 +--
 4 files changed, 71 insertions(+), 19 deletions(-)
From 7ea0f1ac9846a61724620848e88e570175ba0680 Mon Sep 17 00:00:00 2001
From: Elliott Hughes <[email protected]>
Date: Fri, 7 Jun 2019 22:52:38 -0700
Subject: [PATCH] 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.
---
 lib/lib.c          | 81 +++++++++++++++++++++++++++++++++++++---------
 lib/lib.h          |  2 ++
 toys/lsb/killall.c |  2 +-
 toys/posix/kill.c  |  5 +--
 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;
   }
 
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to