From d0d341e4e179d0ec3ce1f5a2bebe2aba7183a04e Mon Sep 17 00:00:00 2001
From: Harald Hoyer <harald@redhat.com>
Date: Fri, 19 Apr 2013 07:41:59 +0200
Subject: [PATCH] Obsolete SIGRTMAX-n signal names

Never ever address signals with SIGRTMAX-n. Signals should always be
addressed with SIGRTMIN+n.

http://man7.org/linux/man-pages/man7/signal.7.html
[...]
programs should never refer to real-time signals using hard-coded numbers, but
instead should always refer to real-time signals using the notation SIGRTMIN+n
[...]
---
 pcomplete.c          | 18 ++++++++++++++++++
 support/mksignames.c | 12 ++++++++++++
 support/signames.c   | 20 +++++++++-----------
 trap.c               | 32 ++++++++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/pcomplete.c b/pcomplete.c
index e4f2059..625ffb9 100644
--- a/pcomplete.c
+++ b/pcomplete.c
@@ -82,6 +82,7 @@ extern char *strpbrk __P((char *, char *));
 extern int array_needs_making;
 extern STRING_INT_ALIST word_token_alist[];
 extern char *signal_names[];
+extern char *signal_names_compat[];
 
 #if defined (DEBUG)
 #if defined (PREFER_STDARG)
@@ -105,6 +106,7 @@ static int it_init_running __P((ITEMLIST *));
 static int it_init_stopped __P((ITEMLIST *));
 static int it_init_keywords __P((ITEMLIST *));
 static int it_init_signals __P((ITEMLIST *));
+static int it_init_signals_compat __P((ITEMLIST *));
 static int it_init_variables __P((ITEMLIST *));
 static int it_init_setopts __P((ITEMLIST *));
 static int it_init_shopts __P((ITEMLIST *));
@@ -166,6 +168,7 @@ ITEMLIST it_services = { LIST_DYNAMIC };	/* unused */
 ITEMLIST it_setopts = { 0, it_init_setopts, (STRINGLIST *)0 };
 ITEMLIST it_shopts = { 0, it_init_shopts, (STRINGLIST *)0 };
 ITEMLIST it_signals = { 0, it_init_signals, (STRINGLIST *)0 };
+ITEMLIST it_signals_compat = { 0, it_init_signals_compat, (STRINGLIST *)0 };
 ITEMLIST it_stopped = { LIST_DYNAMIC, it_init_stopped, (STRINGLIST *)0 };
 ITEMLIST it_users = { LIST_DYNAMIC };		/* unused */
 ITEMLIST it_variables = { LIST_DYNAMIC, it_init_variables, (STRINGLIST *)0 };
@@ -608,6 +611,20 @@ it_init_signals (itp)
 }
 
 static int
+it_init_signals_compat (itp)
+     ITEMLIST *itp;
+{
+  STRINGLIST *sl;
+
+  sl = strlist_create (0);
+  sl->list = signal_names_compat;
+  sl->list_len = strvec_len (sl->list);
+  itp->flags |= LIST_DONTFREE;
+  itp->slist = sl;
+  return 0;
+}
+
+static int
 it_init_variables (itp)
      ITEMLIST *itp;
 {
@@ -771,6 +788,7 @@ gen_action_completions (cs, text)
   GEN_COMPS (flags, CA_SETOPT, &it_setopts, text, ret, tmatches);
   GEN_COMPS (flags, CA_SHOPT, &it_shopts, text, ret, tmatches);
   GEN_COMPS (flags, CA_SIGNAL, &it_signals, text, ret, tmatches);
+  GEN_COMPS (flags, CA_SIGNAL, &it_signals_compat, text, ret, tmatches);
   GEN_COMPS (flags, CA_STOPPED, &it_stopped, text, ret, tmatches);
   GEN_COMPS (flags, CA_VARIABLE, &it_variables, text, ret, tmatches);
 
diff --git a/support/mksignames.c b/support/mksignames.c
index 5618879..27db609 100644
--- a/support/mksignames.c
+++ b/support/mksignames.c
@@ -41,6 +41,7 @@
 /* Imported from signames.c */
 extern void initialize_signames ();
 extern char *signal_names[];
+extern char *signal_names_compat[];
 
 char *progname;
 
@@ -57,6 +58,7 @@ write_signames (stream)
 	   "/* A translation list so we can be polite to our users. */\n");
 #if defined (CROSS_COMPILING)
   fprintf (stream, "extern char *signal_names[];\n\n");
+  fprintf (stream, "extern char *signal_names_compat[];\n\n");
   fprintf (stream, "extern void initialize_signames __P((void));\n\n");
 #else
   fprintf (stream, "char *signal_names[NSIG + 4] = {\n");
@@ -66,6 +68,16 @@ write_signames (stream)
 
   fprintf (stream, "    (char *)0x0\n");
   fprintf (stream, "};\n\n");
+  fprintf (stream, "char *signal_names_compat[NSIG + 4] = {\n");
+
+  for (i = 0; i <= LASTSIG; i++)
+    if (signal_names_compat[i])
+        fprintf (stream, "    \"%s\",\n", signal_names_compat[i]);
+    else
+        fprintf (stream, "    \"%s\",\n", signal_names[i]);
+
+  fprintf (stream, "    (char *)0x0\n");
+  fprintf (stream, "};\n\n");
   fprintf (stream, "#define initialize_signames()\n\n");
 #endif
 }
diff --git a/support/signames.c b/support/signames.c
index abbcd1e..3ee14a5 100644
--- a/support/signames.c
+++ b/support/signames.c
@@ -45,6 +45,7 @@
 #define LASTSIG NSIG+2
 
 char *signal_names[2 * (LASTSIG)];
+char *signal_names_compat[2 * (LASTSIG)];
 
 #define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0]))
 
@@ -102,16 +103,17 @@ initialize_signames ()
 #if defined (SIGRTMAX)
   rtmax = SIGRTMAX;
   signal_names[rtmax] = "SIGRTMAX";
+  signal_names_compat[rtmax] = "SIGRTMAX";
 #endif
 
 #if defined (SIGRTMAX) && defined (SIGRTMIN)
   if (rtmax > rtmin)
     {
-      rtcnt = (rtmax - rtmin - 1) / 2;
+      rtcnt = rtmax - rtmin;
       /* croak if there are too many RT signals */
-      if (rtcnt >= RTLIM/2)
+      if (rtcnt >= RTLIM)
 	{
-	  rtcnt = RTLIM/2-1;
+	  rtcnt = RTLIM;
 #ifdef BUILDTOOL
 	  fprintf(stderr, "%s: error: more than %d real time signals, fix `%s'\n",
 		  progname, RTLIM, progname);
@@ -123,17 +125,13 @@ initialize_signames ()
 	  signal_names[rtmin+i] = (char *)malloc(RTLEN);
 	  if (signal_names[rtmin+i])
 	    sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i);
-	  signal_names[rtmax-i] = (char *)malloc(RTLEN);
-	  if (signal_names[rtmax-i])
-	    sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i);
 	}
 
-      if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
+      for (i = 1; i <= (rtcnt - 1) / 2; i++)
 	{
-	  /* Need an extra RTMIN signal */
-	  signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
-	  if (signal_names[rtmin+rtcnt+1])
-	    sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1);
+	  signal_names_compat[rtmax-i] = (char *)malloc(RTLEN);
+	  if (signal_names_compat[rtmax-i])
+	    sprintf (signal_names_compat[rtmax-i], "SIGRTMAX-%d", i);
 	}
     }
 #endif /* SIGRTMIN && SIGRTMAX */
diff --git a/trap.c b/trap.c
index 86665e7..6af9c65 100644
--- a/trap.c
+++ b/trap.c
@@ -257,6 +257,38 @@ decode_signal (string, flags)
 	return ((int)sig);
     }
 
+  /* A leading `SIG' may be omitted. */
+  for (sig = 0; sig < BASH_NSIG; sig++)
+    {
+      name = signal_names_compat[sig];
+      if (name == 0 || name[0] == '\0')
+	continue;
+
+      /* Check name without the SIG prefix first case sensitivly or
+	 insensitively depending on whether flags includes DSIG_NOCASE */
+      if (STREQN (name, "SIG", 3))
+	{
+	  name += 3;
+
+	  if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
+	    return ((int)sig);
+	  else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
+	    return ((int)sig);
+	  /* If we can't use the `SIG' prefix to match, punt on this
+	     name now. */
+	  else if ((flags & DSIG_SIGPREFIX) == 0)
+	    continue;
+	}
+
+      /* Check name with SIG prefix case sensitively or insensitively
+	 depending on whether flags includes DSIG_NOCASE */
+      name = signal_names_compat[sig];
+      if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
+	return ((int)sig);
+      else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
+	return ((int)sig);
+    }
+
   return (NO_SIG);
 }
 
-- 
1.8.2

