Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: real-time signals support



This adds support for POSIX real-time signals, covering kill, trap,
$signals and TRAP...() functions.

For consistency with ksh and bash, the naming is RTMIN, RTMIN+1 ...
RTMAX-1, RTMAX. This means that each signal has an alternate name
so on my system, RTMIN+31 is an alternate name for RTMAX-30. NetBSD's
sh uses RT0, RT1...

The patch also adds a -L option to kill similar to bash and ksh which
prints signals with their numbers as a table. On many systems, the
real-time signals are not numbered contiguously with the earlier
signals. Where they are (NetBSD and Solaris), zsh was already including
RTMIN.

Prior to this patch, kill -l uses the WIFSIGNALED and WTERMSIG
macros to convert a return status to the corresponding signal. But
zsh simply ORs the status with 0200 (128). So surely we need to
look for that instead? This alteration makes the behaviour more
consistent with bash. To test, try kill -l {0..260}

In the POSIX spec, SIGRTMIN/MAX are permitted to not be fixed constants, and
this is indeed the case on Linux. As far as I can tell this is because glibc
steals a couple of them for threading support. They don't appear to be
dynamically configurable. However, this does prevent the sigtrapped and
siglists arrays from having their size determined at compile-time. Where
numbers are not contiguous, I've not left a gap so some of the patch is
renaming to make the distinction between signal numbers and trap table indices
clear.

Oliver

diff --git a/Completion/Zsh/Command/_kill b/Completion/Zsh/Command/_kill
index 084cf42c8..3b5c02151 100644
--- a/Completion/Zsh/Command/_kill
+++ b/Completion/Zsh/Command/_kill
@@ -4,10 +4,11 @@ local curcontext="$curcontext" line state ret=1
 typeset -A opt_args
 
 _arguments -C \
-  '(-s -l 1)-n[specify signal number]:signal number' \
-  '(-l)-q[send the specified integer with the signal using sigqueue]:value' \
-  '(-n -l 1)-s[specify signal name]:signal:_signals -s' \
-  '(-n -s)-l[list signal names or numbers of specified signals]:*:signal:_signals' \
+  '(-s -l -L 1)-n[specify signal number]:signal number' \
+  '(-l -L)-q[send the specified integer with the signal using sigqueue]:value' \
+  '(-n -l -L 1)-s[specify signal name]:signal:_signals -s' \
+  '-l[list signal names or numbers of specified signals]:*:signal:_signals' \
+  '(- *)-L[list each signal and corresponding number]' \
   '(-n -s -l)1::signal:_signals -p -s' \
   '*:processes:->processes' && ret=0
   
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 784089594..6318053d8 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -1144,7 +1144,8 @@ cindex(killing jobs)
 cindex(jobs, killing)
 xitem(tt(kill) [ tt(-s) var(signal_name) | tt(-n) var(signal_number) | \
 tt(-)var(sig) ] [ tt(-q) var(value) ] var(job) ...)
-item(tt(kill) tt(-l) [ var(sig) ... ])(
+xitem(tt(kill) tt(-l) [ var(sig) ... ])
+item(tt(kill) tt(-L))(
 Sends either tt(SIGTERM) or the specified signal to the given
 jobs or processes.
 Signals are given by number or by names, with or without the `tt(SIG)'
@@ -1158,7 +1159,8 @@ specified the signal names are listed.  Otherwise, for each
 var(sig) that is a name, the corresponding signal number is
 listed.  For each var(sig) that is a signal number or a number
 representing the exit status of a process which was terminated or
-stopped by a signal the name of the signal is printed.
+stopped by a signal the name of the signal is printed.  The final
+form with tt(-L) lists each signal name with its corresponding number.
 
 On some systems, alternative signal names are allowed for a few signals.
 Typical examples are tt(SIGCHLD) and tt(SIGCLD) or tt(SIGPOLL) and
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index a6fbe6723..8c5e67e70 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -953,7 +953,10 @@ has index 1, the signals are offset by 1 from the signal number
 used by the operating system.  For example, on typical Unix-like systems
 tt(HUP) is signal number 1, but is referred to as tt($signals[2]).  This
 is because of tt(EXIT) at position 1 in the array, which is used
-internally by zsh but is not known to the operating system.
+internally by zsh but is not known to the operating system. On many systems
+there is a block of reserved or unused signal numbers before the POSIX
+real-time signals so the array index can't be used as an accurate indicator
+of their signal number. Use, for example, tt(kill -l SIGRTMIN) instead.
 )
 vindex(TRY_BLOCK_ERROR)
 item(tt(TRY_BLOCK_ERROR) <S>)(
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index a05ea2fe4..7441c30b8 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -309,7 +309,7 @@ setfunction(char *name, char *val, int dis)
     shfunc_set_sticky(shf);
 
     if (!strncmp(name, "TRAP", 4) &&
-	(sn = getsignum(name + 4)) != -1) {
+	(sn = getsigidx(name + 4)) != -1) {
 	if (settrap(sn, NULL, ZSIG_FUNC)) {
 	    freeeprog(shf->funcdef);
 	    zfree(shf, sizeof(*shf));
diff --git a/Src/builtin.c b/Src/builtin.c
index dd352c146..7a851936c 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -3425,16 +3425,16 @@ bin_functions(char *name, char **argv, Options ops, int func)
 	    newsh->sticky = sticky_emulation_dup(shf->sticky, 0);
 	/* is newsh a signal trap? (adapted from exec.c) */
 	if (!strncmp(s, "TRAP", 4)) {
-	    int signum = getsignum(s + 4);
-	    if (signum != -1) {
-		if (settrap(signum, NULL, ZSIG_FUNC)) {
+	    int sigidx = getsigidx(s + 4);
+	    if (sigidx != -1) {
+		if (settrap(sigidx, NULL, ZSIG_FUNC)) {
 		    freeeprog(newsh->funcdef);
 		    dircache_set(&newsh->filename, NULL);
 		    zfree(newsh, sizeof(*newsh));
 		    return 1;
 		}
 		/* Remove any old node explicitly */
-		removetrapnode(signum);
+		removetrapnode(sigidx);
 	    }
 	}
 	shfunctab->addnode(shfunctab, ztrdup(s), &newsh->node);
@@ -3713,15 +3713,15 @@ bin_functions(char *name, char **argv, Options ops, int func)
 		/* no flags, so just print */
 		printshfuncexpand(&shf->node, pflags, expand);
 	} else if (on & PM_UNDEFINED) {
-	    int signum = -1, ok = 1;
+	    int sigidx = -1, ok = 1;
 
 	    if (!strncmp(*argv, "TRAP", 4) &&
-		(signum = getsignum(*argv + 4)) != -1) {
+		(sigidx = getsigidx(*argv + 4)) != -1) {
 		/*
 		 * Because of the possibility of alternative names,
 		 * we must remove the trap explicitly.
 		 */
-		removetrapnode(signum);
+		removetrapnode(sigidx);
 	    }
 
 	    if (**argv == '/') {
@@ -3757,8 +3757,8 @@ bin_functions(char *name, char **argv, Options ops, int func)
 	    shfunc_set_sticky(shf);
 	    add_autoload_function(shf, *argv);
 
-	    if (signum != -1) {
-		if (settrap(signum, NULL, ZSIG_FUNC)) {
+	    if (sigidx != -1) {
+		if (settrap(sigidx, NULL, ZSIG_FUNC)) {
 		    shfunctab->removenode(shfunctab, *argv);
 		    shfunctab->freenode(&shf->node);
 		    returnval = 1;
@@ -7344,7 +7344,7 @@ bin_trap(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
     /* If given no arguments, list all currently-set traps */
     if (!*argv) {
 	queue_signals();
-	for (sig = 0; sig < VSIGCOUNT; sig++) {
+	for (sig = 0; sig < TRAPCOUNT; sig++) {
 	    if (sigtrapped[sig] & ZSIG_FUNC) {
 		HashNode hn;
 
@@ -7370,13 +7370,13 @@ bin_trap(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
 
     /* If we have a signal number, unset the specified *
      * signals.  With only -, remove all traps.        */
-    if ((getsignum(*argv) != -1) || (!strcmp(*argv, "-") && argv++)) {
+    if ((getsigidx(*argv) != -1) || (!strcmp(*argv, "-") && argv++)) {
 	if (!*argv) {
-	    for (sig = 0; sig < VSIGCOUNT; sig++)
+	    for (sig = 0; sig < TRAPCOUNT; sig++)
 		unsettrap(sig);
 	} else {
 	    for (; *argv; argv++) {
-		sig = getsignum(*argv);
+		sig = getsigidx(*argv);
 		if (sig == -1) {
 		    zwarnnam(name, "undefined signal: %s", *argv);
 		    break;
@@ -7401,12 +7401,12 @@ bin_trap(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
 	Eprog t;
 	int flags;
 
-	sig = getsignum(*argv);
+	sig = getsigidx(*argv);
 	if (sig == -1) {
 	    zwarnnam(name, "undefined signal: %s", *argv);
 	    break;
 	}
-	if (idigit(**argv) ||
+	if (idigit(**argv) || (sig >= VSIGCOUNT) ||
 	    !strcmp(sigs[sig], *argv) ||
 	    (!strncmp("SIG", *argv, 3) && !strcmp(sigs[sig], *argv+3))) {
 	    /* The signal was specified by number or by canonical name (with
diff --git a/Src/exec.c b/Src/exec.c
index 1565cb13e..f6ccbefe5 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -5427,7 +5427,7 @@ execfuncdef(Estate state, Eprog redir_prog)
 	} else {
 	    /* is this shell function a signal trap? */
 	    if (!strncmp(s, "TRAP", 4) &&
-		(signum = getsignum(s + 4)) != -1) {
+		(signum = getsigidx(s + 4)) != -1) {
 		if (settrap(signum, NULL, ZSIG_FUNC)) {
 		    freeeprog(shf->funcdef);
 		    dircache_set(&shf->filename, NULL);
diff --git a/Src/hashtable.c b/Src/hashtable.c
index bb165505e..75b06c4ad 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -836,10 +836,10 @@ static HashNode
 removeshfuncnode(UNUSED(HashTable ht), const char *nam)
 {
     HashNode hn;
-    int signum;
+    int sigidx;
 
-    if (!strncmp(nam, "TRAP", 4) && (signum = getsignum(nam + 4)) != -1)
-	hn = removetrap(signum);
+    if (!strncmp(nam, "TRAP", 4) && (sigidx = getsigidx(nam + 4)) != -1)
+	hn = removetrap(sigidx);
     else
 	hn = removehashnode(shfunctab, nam);
 
@@ -856,10 +856,10 @@ disableshfuncnode(HashNode hn, UNUSED(int flags))
 {
     hn->flags |= DISABLED;
     if (!strncmp(hn->nam, "TRAP", 4)) {
-	int signum = getsignum(hn->nam + 4);
-	if (signum != -1) {
-	    sigtrapped[signum] &= ~ZSIG_FUNC;
-	    unsettrap(signum);
+	int sigidx = getsigidx(hn->nam + 4);
+	if (sigidx != -1) {
+	    sigtrapped[sigidx] &= ~ZSIG_FUNC;
+	    unsettrap(sigidx);
 	}
     }
 }
@@ -876,9 +876,9 @@ enableshfuncnode(HashNode hn, UNUSED(int flags))
 
     shf->node.flags &= ~DISABLED;
     if (!strncmp(shf->node.nam, "TRAP", 4)) {
-	int signum = getsignum(shf->node.nam + 4);
-	if (signum != -1) {
-	    settrap(signum, NULL, ZSIG_FUNC);
+	int sigidx = getsigidx(shf->node.nam + 4);
+	if (sigidx != -1) {
+	    settrap(sigidx, NULL, ZSIG_FUNC);
 	}
     }
 }
diff --git a/Src/init.c b/Src/init.c
index 83b79d3d4..ec21521b1 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1382,6 +1382,9 @@ setupshin(char *runscript)
 void
 init_signals(void)
 {
+    sigtrapped = (int *) hcalloc(TRAPCOUNT * sizeof(int));
+    siglists = (Eprog *) hcalloc(TRAPCOUNT * sizeof(Eprog));
+
     if (interact) {
 	int i;
 	signal_setmask(signal_mask(0));
diff --git a/Src/jobs.c b/Src/jobs.c
index 118c5e61b..49decc661 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -1073,6 +1073,21 @@ should_report_time(Job j)
     return 0;
 }
 
+/**/
+char *
+sigmsg(int sig)
+{
+    static char *unknown = "unknown signal";
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+    static char rtmsg[] = "real-time event XXX";
+    if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
+	sprintf(rtmsg + sizeof(rtmsg) - 4, "%u", sig - SIGRTMIN + 1);
+	return rtmsg;
+    }
+#endif
+    return sig <= SIGCOUNT ? sig_msg[sig] : unknown;
+}
+
 /* !(lng & 3) means jobs    *
  *  (lng & 1) means jobs -l *
  *  (lng & 2) means jobs -p
@@ -2694,7 +2709,7 @@ static const struct {
 int
 bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 {
-    int sig = SIGTERM;
+    int status, sig = SIGTERM;
     int returnval = 0;
 #ifdef HAVE_SIGQUEUE
     union sigval sigqueue_info;
@@ -2740,23 +2755,29 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 	    if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
 		if (argv[1]) {
 		    while (*++argv) {
-			sig = zstrtol(*argv, &signame, 10);
+			status = zstrtol(*argv, &signame, 10);
 			if (signame == *argv) {
+			    signame = casemodify(signame, CASMOD_UPPER);
 			    if (!strncmp(signame, "SIG", 3))
 				signame += 3;
 			    for (sig = 1; sig <= SIGCOUNT; sig++)
-				if (!strcasecmp(sigs[sig], signame))
+				if (!strcmp(sigs[sig], signame))
 				    break;
 			    if (sig > SIGCOUNT) {
 				int i;
 
 				for (i = 0; alt_sigs[i].name; i++)
-				    if (!strcasecmp(alt_sigs[i].name, signame))
+				    if (!strcmp(alt_sigs[i].name, signame))
 				    {
 					sig = alt_sigs[i].num;
 					break;
 				    }
 			    }
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+			    if (sig > SIGCOUNT && (sig = rtsigno(signame))) {
+				printf("%d\n", sig);
+			    } else
+#endif
 			    if (sig > SIGCOUNT) {
 				zwarnnam(nam, "unknown signal: SIG%s",
 					 signame);
@@ -2769,14 +2790,15 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 					 signame);
 				returnval++;
 			    } else {
-				if (WIFSIGNALED(sig))
-				    sig = WTERMSIG(sig);
-				else if (WIFSTOPPED(sig))
-				    sig = WSTOPSIG(sig);
+				sig = status & ~0200;
 				if (1 <= sig && sig <= SIGCOUNT)
 				    printf("%s\n", sigs[sig]);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+				else if ((signame = rtsigname(sig, 0)))
+				    printf("%s\n", signame);
+#endif
 				else
-				    printf("%d\n", sig);
+				    printf("%d\n", status);
 			    }
 			}
 		    }
@@ -2785,10 +2807,42 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 		printf("%s", sigs[1]);
 		for (sig = 2; sig <= SIGCOUNT; sig++)
 		    printf(" %s", sigs[sig]);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+		for (sig = SIGRTMIN; sig <= SIGRTMAX; sig++)
+		    printf(" %s", rtsigname(sig, 0));
+#endif
 		putchar('\n');
 		return 0;
 	    }
 
+	    /* with argument "-L" list signals with their numbers in a table */
+	    if ((*argv)[1] == 'L' && (*argv)[2] == '\0') {
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+		const int width = SIGRTMAX >= 100 ? 3 : 2;
+#else
+		const int width = SIGCOUNT >= 100 ? 3 : 2;
+#endif
+		for (sig = 1; sig < SIGCOUNT
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+			+ 1
+#endif
+			; sig++)
+		{
+		    printf("%*d) %-10s%c", width, sig, sigs[sig],
+			    sig % 5 ? ' ' : '\n');
+		}
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+		for (sig = SIGRTMIN; sig < SIGRTMAX; sig++) {
+		    printf("%*d) %-10s%c", width, sig, rtsigname(sig, 0),
+			    (sig - SIGRTMIN + SIGCOUNT + 1) % 5 ? ' ' : '\n');
+		}
+		printf("%*d) RTMAX\n", width, sig);
+#else
+		printf("%*d) %s\n", width, sig, sigs[sig]);
+#endif
+		return 0;
+	    }
+
     	    if ((*argv)[1] == 'n' && (*argv)[2] == '\0') {
 	    	char *endp;
 
@@ -2833,9 +2887,13 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 			    break;
 			}
 		}
-		if (sig > SIGCOUNT) {
+		if (sig > SIGCOUNT
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+			&& !(sig = rtsigno(signame))
+#endif
+			) {
 		    zwarnnam(nam, "unknown signal: SIG%s", signame);
-		    zwarnnam(nam, "type kill -l for a list of signals");
+		    zwarnnam(nam, "type kill -L for a list of signals");
 		    return 1;
 		}
 	    }
@@ -2916,18 +2974,19 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 
     return returnval < 126 ? returnval : 1;
 }
-/* Get a signal number from a string */
+
+/* Get index into table of traps from a string describing a signal */
 
 /**/
 mod_export int
-getsignum(const char *s)
+getsigidx(const char *s)
 {
     int x, i;
 
     /* check for a signal specified by number */
     x = atoi(s);
-    if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
-	return x;
+    if (idigit(*s) && x >= 0)
+	return SIGIDX(x);
 
     /* search for signal by name */
     if (!strncmp(s, "SIG", 3))
@@ -2943,11 +3002,16 @@ getsignum(const char *s)
 	    return alt_sigs[i].num;
     }
 
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+    if ((x = rtsigno(s)))
+	return SIGIDX(x);
+#endif
+
     /* no matching signal */
     return -1;
 }
 
-/* Get the name for a signal. */
+/* Get the name for a signal given the index into the traps table. */
 
 /**/
 mod_export const char *
@@ -2961,6 +3025,11 @@ getsigname(int sig)
 		return alt_sigs[i].name;
     }
     else
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+    if (sig >= VSIGCOUNT)
+	return rtsigname(SIGNUM(sig), 0);
+    else
+#endif
 	return sigs[sig];
 
     /* shouldn't reach here */
@@ -2985,10 +3054,22 @@ gettrapnode(int sig, int ignoredisable)
     else
 	getptr = shfunctab->getnode;
 
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+    if (sig >= VSIGCOUNT)
+	sprintf(fname, "TRAP%s", rtsigname(SIGNUM(sig), 0));
+    else
+#endif
     sprintf(fname, "TRAP%s", sigs[sig]);
     if ((hn = getptr(shfunctab, fname)))
 	return hn;
 
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+    if (sig >= VSIGCOUNT) {
+	sprintf(fname, "TRAP%s", rtsigname(SIGNUM(sig), 1));
+	return getptr(shfunctab, fname);
+    }
+#endif
+
     for (i = 0; alt_sigs[i].name; i++) {
 	if (alt_sigs[i].num == sig) {
 	    sprintf(fname, "TRAP%s", alt_sigs[i].name);
diff --git a/Src/params.c b/Src/params.c
index 225acb8a1..7c5e9d8ff 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -946,8 +946,18 @@ createparamtable(void)
     setsparam("ZSH_ARGZERO", ztrdup(posixzero));
     setsparam("ZSH_VERSION", ztrdup_metafy(ZSH_VERSION));
     setsparam("ZSH_PATCHLEVEL", ztrdup_metafy(ZSH_PATCHLEVEL));
-    setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *)));
-    for (t = sigs; (*sigptr++ = ztrdup_metafy(*t++)); );
+    setaparam("signals", sigptr = zalloc((TRAPCOUNT + 1) * sizeof(char *)));
+    t = sigs;
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+    while (t - sigs <= SIGCOUNT)
+	*sigptr++ = ztrdup_metafy(*t++);
+    {
+	int sig;
+	for (sig = SIGRTMIN; sig <= SIGRTMAX; sig++)
+	    *sigptr++ = ztrdup_metafy(rtsigname(sig, 0));
+    }
+#endif
+    while ((*sigptr++ = ztrdup_metafy(*t++))) /* empty */ ;
 
     noerrs = 0;
 }
diff --git a/Src/signals.c b/Src/signals.c
index b1a843e2c..d28853ea6 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -31,10 +31,12 @@
 #include "signals.pro"
  
 /* Array describing the state of each signal: an element contains *
- * 0 for the default action or some ZSIG_* flags ored together.   */
+ * 0 for the default action or some ZSIG_* flags ored together.   *
+ * Contains TRAPCOUNT elements but can't be allocated statically  *
+ * because that's a dynamic value on Linux                        */
 
 /**/
-mod_export int sigtrapped[VSIGCOUNT];
+mod_export int *sigtrapped;
 
 /*
  * Trap programme lists for each signal.
@@ -48,7 +50,7 @@ mod_export int sigtrapped[VSIGCOUNT];
  */
 
 /**/
-mod_export Eprog siglists[VSIGCOUNT];
+mod_export Eprog *siglists;
 
 /* Total count of trapped signals */
 
@@ -892,7 +894,7 @@ dosavetrap(int sig, int level)
  * Set a trap:  note this does not handle manipulation of
  * the function table for TRAPNAL functions.
  *
- * sig is the signal number.
+ * sig is index into the table of trapped signals.
  *
  * l is the list to be eval'd for a trap defined with the "trap"
  * builtin and should be NULL for a function trap.
@@ -931,6 +933,10 @@ settrap(int sig, Eprog l, int flags)
 #endif
             sig != SIGCHLD)
             signal_ignore(sig);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+	else if (sig >= VSIGCOUNT && sig < TRAPCOUNT)
+	    signal_ignore(SIGNUM(sig));
+#endif
     } else {
 	nsigtrapped++;
         sigtrapped[sig] = ZSIG_TRAPPED;
@@ -940,6 +946,10 @@ settrap(int sig, Eprog l, int flags)
 #endif
             sig != SIGCHLD)
             install_handler(sig);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+	if (sig >= VSIGCOUNT && sig < TRAPCOUNT)
+	    install_handler(SIGNUM(sig));
+#endif
     }
     sigtrapped[sig] |= flags;
     /*
@@ -1019,6 +1029,11 @@ removetrap(int sig)
 #endif
              sig != SIGCHLD)
         signal_default(sig);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+    else if (sig >= VSIGCOUNT && sig < TRAPCOUNT)
+	    signal_default(SIGNUM(sig));
+#endif
+
     if (sig == SIGEXIT)
 	exit_trap_posix = 0;
 
@@ -1172,7 +1187,7 @@ endtrapscope(void)
 static int
 handletrap(int sig)
 {
-    if (!sigtrapped[sig])
+    if (!sigtrapped[SIGIDX(sig)])
 	return 0;
 
     if (trap_queueing_enabled)
@@ -1189,7 +1204,7 @@ handletrap(int sig)
 	return 1;
     }
 
-    dotrap(sig);
+    dotrap(SIGIDX(sig));
 
     if (sig == SIGALRM)
     {
@@ -1481,3 +1496,60 @@ dotrap(int sig)
 
     restore_queue_signals(q);
 }
+
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+
+/* Realtime signals, these are a contiguous block that can
+ * be separated from the other signals with an unused gap. */
+
+/**/
+int
+rtsigno(const char* signame)
+{
+    const int maxofs = SIGRTMAX - SIGRTMIN;
+    const char *end = signame + 5;
+    int offset;
+    struct rtdir { int sig; int dir; char op; } x = { 0, 0, 0 };
+    if (!strncmp(signame, "RTMIN", 5)) {
+	x = (struct rtdir) { SIGRTMIN, 1, '+' };
+    } else if (!strncmp(signame, "RTMAX", 5)) {
+	x = (struct rtdir) { SIGRTMAX, -1, '-' };
+    } else
+	return 0;
+
+    if (signame[5] == x.op) {
+	if ((offset = strtol(signame + 6, (char **) &end, 10)) > maxofs)
+	    return 0;
+	x.sig += offset * x.dir;
+    }
+    if (*end)
+	return 0;
+
+    return x.sig;
+}
+
+/**/
+char *
+rtsigname(int signo, int alt)
+{
+    char* buf = (char *) zhalloc(10);
+    int minofs = signo - SIGRTMIN;
+    int maxofs = SIGRTMAX - signo;
+    int offset;
+    int form = alt ^ (maxofs < minofs);
+
+    if (signo < SIGRTMIN || signo > SIGRTMAX)
+	return NULL;
+
+    strcpy(buf, "RT");
+    strcpy(buf+2, form ? "MAX-" : "MIN+");
+    offset = form ? maxofs : minofs;
+    if (offset) {
+	snprintf(buf + 6, 4, "%d", offset);
+    } else {
+	buf[5] = '\0';
+    }
+    return buf;
+}
+
+#endif
diff --git a/Src/signals.h b/Src/signals.h
index 41ac88cce..391f11fed 100644
--- a/Src/signals.h
+++ b/Src/signals.h
@@ -36,6 +36,15 @@
 #define SIGZERR   (SIGCOUNT+1)
 #define SIGDEBUG  (SIGCOUNT+2)
 #define VSIGCOUNT (SIGCOUNT+3)
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+# define TRAPCOUNT (VSIGCOUNT + SIGRTMAX - SIGRTMIN + 1)
+# define SIGNUM(x) ((x) >= VSIGCOUNT ? (x) - VSIGCOUNT + SIGRTMIN : (x))
+# define SIGIDX(x) ((x) >= SIGRTMIN && (x) <= SIGRTMAX ? (x) - SIGRTMIN + VSIGCOUNT : (x))
+#else
+# define TRAPCOUNT VSIGCOUNT
+# define SIGNUM(x) (x)
+# define SIGIDX(x) (x)
+#endif
 #define SIGEXIT    0
 
 #ifdef SV_BSDSIG
diff --git a/Src/signames2.awk b/Src/signames2.awk
index 4d1557cd8..5738030c6 100644
--- a/Src/signames2.awk
+++ b/Src/signames2.awk
@@ -15,7 +15,7 @@
     if (signam == "CHLD" && sig[signum] == "CLD")  sig[signum] = ""
     if (signam == "POLL" && sig[signum] == "IO")   sig[signum] = ""
     if (signam == "ABRT" && sig[signum] == "IOT")  sig[signum] = ""
-    if (sig[signum] == "") {
+    if (signam !~ /RTM(IN|AX)/ && sig[signum] == "") {
 	sig[signum] = signam
 	if (0 + max < 0 + signum && signum < 60)
 	    max = signum
@@ -66,10 +66,6 @@ END {
     printf "#include %czsh.mdh%c\n", 34, 34
     printf "\n"
     printf "/**/\n"
-    printf "#define sigmsg(sig) ((sig) <= SIGCOUNT ? sig_msg[sig]"
-    printf " : %c%s%c)", 34, "unknown signal", 34
-    printf "\n"
-    printf "/**/\n"
     printf "mod_export char *sig_msg[SIGCOUNT+2] = {\n"
     printf "\t%c%s%c,\n", 34, "done", 34
 




Messages sorted by: Reverse Date, Date, Thread, Author