about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2004-11-22 10:33:03 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2004-11-22 10:33:03 +0000
commit5141e68daa20caa8523361d5dff63e9384c30191 (patch)
tree7521410b050a3f152e5dd902c209ff12477bd455
parentf1846d402bed119a74409c3b417484661e100e27 (diff)
downloadzsh-5141e68daa20caa8523361d5dff63e9384c30191.tar.gz
zsh-5141e68daa20caa8523361d5dff63e9384c30191.tar.xz
zsh-5141e68daa20caa8523361d5dff63e9384c30191.zip
20572: Allow alternative signal names
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/builtins.yo13
-rw-r--r--Src/builtin.c18
-rw-r--r--Src/exec.c6
-rw-r--r--Src/jobs.c129
-rw-r--r--Src/signals.c15
-rw-r--r--Src/utils.c21
7 files changed, 172 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index 13d4c5731..9b69e96ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-11-22  Peter Stephenson  <pws@csr.com>
+
+	* 20572: Doc/Zsh/builtins.yo, Src/builtin.c, Src/exec.c,
+	Src/jobs.c, Src/signals.c, Src/utils.c: Allow -CLD and -IO
+	as alternatives to -CHLD and -POLL where they are the same signal.
+
 2004-11-20  Doug Kearns  <djkea2@mugca.its.monash.edu.au>
 
 	* 20571: Completion/Unix/Command/_java: update javac completion for
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 51802f1d6..a1e9df79a 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -626,6 +626,14 @@ 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.
+
+On some systems, alternative signal names are allowed for a few signals.
+Typical examples are tt(SIGCHLD) and tt(SIGCLD) or tt(SIGPOLL) and
+tt(SIGIO), assuming they correspond to the same signal number.  tt(kill
+-l) will only list the preferred form, however tt(kill -l) var(alt) will
+show if the alternative form corresponds to a signal number.  For example,
+under Linux tt(kill -l IO) and tt(kill -l POLL) both output 29, hence
+tt(kill -IO) and tt(kill -POLL) have the same effect.
 )
 findex(let)
 item(tt(let) var(arg) ...)(
@@ -1179,6 +1187,11 @@ will print the line number of a command executed after it has run, while
 example(TRAPDEBUG() { print $LINENO; })
 
 will always print the number zero.
+
+Alternative signal names are allowed as described under tt(kill) above.
+Defining a trap under either name causes any trap under an alternative
+name to be removed.  However, it is recommended that for consistency
+users stick exclusively to one name or another.
 )
 findex(true)
 cindex(doing nothing, successfully)
diff --git a/Src/builtin.c b/Src/builtin.c
index bc21fa9e2..3a471760a 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2543,7 +2543,16 @@ bin_functions(char *name, char **argv, Options ops, int func)
 		/* no flags, so just print */
 		shfunctab->printnode((HashNode) shf, pflags);
 	} else if (on & PM_UNDEFINED) {
-	    int signum, ok = 1;
+	    int signum = -1, ok = 1;
+
+	    if (!strncmp(*argv, "TRAP", 4) &&
+		(signum = getsignum(*argv + 4)) != -1) {
+		/*
+		 * Because of the possibility of alternative names,
+		 * we must remove the trap explicitly.
+		 */
+		removetrapnode(signum);
+	    }
 
 	    /* Add a new undefined (autoloaded) function to the *
 	     * hash table with the corresponding flags set.     */
@@ -2552,8 +2561,7 @@ bin_functions(char *name, char **argv, Options ops, int func)
 	    shf->funcdef = mkautofn(shf);
 	    shfunctab->addnode(shfunctab, ztrdup(*argv), shf);
 
-	    if (!strncmp(*argv, "TRAP", 4) &&
-		(signum = getsignum(*argv + 4)) != -1) {
+	    if (signum != -1) {
 		if (settrap(signum, shf->funcdef)) {
 		    shfunctab->removenode(shfunctab, *argv);
 		    shfunctab->freenode((HashNode)shf);
@@ -4898,11 +4906,9 @@ bin_trap(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
 	queue_signals();
 	for (sig = 0; sig < VSIGCOUNT; sig++) {
 	    if (sigtrapped[sig] & ZSIG_FUNC) {
-		char fname[20];
 		HashNode hn;
 
-		sprintf(fname, "TRAP%s", sigs[sig]);
-		if ((hn = shfunctab->getnode(shfunctab, fname)))
+		if ((hn = gettrapnode(sig, 0)))
 		    shfunctab->printnode(hn, 0);
 		DPUTS(!hn, "BUG: I did not find any trap functions!");
 	    } else if (sigtrapped[sig]) {
diff --git a/Src/exec.c b/Src/exec.c
index c5fac2fc9..49503db0f 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3345,6 +3345,12 @@ execfuncdef(Estate state, UNUSED(int do_exec))
 		return 1;
 	    }
 	    sigtrapped[signum] |= ZSIG_FUNC;
+
+	    /*
+	     * Remove the old node explicitly in case it has
+	     * an alternative name
+	     */
+	    removetrapnode(signum);
 	}
 	shfunctab->addnode(shfunctab, ztrdup(s), shf);
     }
diff --git a/Src/jobs.c b/Src/jobs.c
index dc5bc10b6..cb9e5422c 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -1819,6 +1819,36 @@ bin_fg(char *name, char **argv, Options ops, int func)
     return retval;
 }
 
+#if defined(SIGCHLD) && defined(SIGCLD)
+#if SIGCHLD == SIGCLD
+#define ALT_SIGS 1
+#endif
+#endif
+#if defined(SIGPOLL) && defined(SIGIO)
+#if SIGPOLL == SIGIO
+#define ALT_SIGS 1
+#endif
+#endif
+
+#ifdef ALT_SIGS
+const struct {
+    const char *name;
+    int num;
+} alt_sigs[] = {
+#if defined(SIGCHLD) && defined(SIGCLD)
+#if SIGCHLD == SIGCLD
+    { "CLD", SIGCLD },
+#endif
+#endif
+#if defined(SIGPOLL) && defined(SIGIO)
+#if SIGPOLL == SIGIO
+    { "IO", SIGIO },
+#endif
+#endif
+    { NULL, 0 }
+};
+#endif
+
 /* kill: send a signal to a process.  The process(es) may be specified *
  * by job specifier (see above) or pid.  A signal, defaulting to       *
  * SIGTERM, may be specified by name or number, preceded by a dash.    */
@@ -1847,6 +1877,18 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 			    for (sig = 1; sig <= SIGCOUNT; sig++)
 				if (!cstrpcmp(sigs + sig, &signame))
 				    break;
+#ifdef ALT_SIGS
+			    if (sig > SIGCOUNT) {
+				int i;
+
+				for (i = 0; alt_sigs[i].name; i++)
+				    if (!cstrpcmp(&alt_sigs[i].name, &signame))
+				    {
+					sig = alt_sigs[i].num;
+					break;
+				    }
+			    }
+#endif
 			    if (sig > SIGCOUNT) {
 				zwarnnam(nam, "unknown signal: SIG%s",
 					 signame, 0);
@@ -1908,6 +1950,18 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 			break;
 		if (*signame == '0' && !signame[1])
 		    sig = 0;
+#ifdef ALT_SIGS
+		if (sig > SIGCOUNT) {
+		    int i;
+
+		    for (i = 0; alt_sigs[i].name; i++)
+			if (!strcmp(alt_sigs[i].name, signame))
+			{
+			    sig = alt_sigs[i].num;
+			    break;
+			}
+		}
+#endif
 		if (sig > SIGCOUNT) {
 		    zwarnnam(nam, "unknown signal: SIG%s", signame, 0);
 		    zwarnnam(nam, "type kill -l for a List of signals", NULL, 0);
@@ -1964,6 +2018,81 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 
     return returnval < 126 ? returnval : 1;
 }
+/* Get a signal number from a string */
+
+/**/
+mod_export int
+getsignum(char *s)
+{
+    int x, i;
+
+    /* check for a signal specified by number */
+    x = atoi(s);
+    if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
+	return x;
+
+    /* search for signal by name */
+    for (i = 0; i < VSIGCOUNT; i++)
+	if (!strcmp(s, sigs[i]))
+	    return i;
+
+#ifdef ALT_SIGS
+    for (i = 0; alt_sigs[i].name; i++)
+    {
+	if (!strcmp(s, alt_sigs[i].name))
+	    return alt_sigs[i].num;
+    }
+#endif
+
+    /* no matching signal */
+    return -1;
+}
+
+/* Get the function node for a trap, taking care about alternative names */
+/**/
+HashNode
+gettrapnode(int sig, int ignoredisable)
+{
+    char fname[20];
+    HashNode hn;
+    HashNode (*getptr)(HashTable ht, char *name);
+#ifdef ALT_SIGS
+    int i;
+#endif
+    if (ignoredisable)
+	getptr = shfunctab->getnode2;
+    else
+	getptr = shfunctab->getnode;
+
+    sprintf(fname, "TRAP%s", sigs[sig]);
+    if ((hn = getptr(shfunctab, fname)))
+	return hn;
+
+#ifdef ALT_SIGS
+    for (i = 0; alt_sigs[i].name; i++) {
+	if (alt_sigs[i].num == sig) {
+	    sprintf(fname, "TRAP%s", alt_sigs[i].name);
+	    if ((hn = getptr(shfunctab, fname)))
+		return hn;
+	}
+    }
+#endif
+
+    return NULL;
+}
+
+/* Remove a TRAP function under any name for the signal */
+
+/**/
+void
+removetrapnode(int sig)
+{
+    HashNode hn = gettrapnode(sig, 1);
+    if (hn) {
+	shfunctab->removenode(shfunctab, hn->nam);
+	shfunctab->freenode(hn);
+    }
+}
 
 /* Suspend this shell */
 
diff --git a/Src/signals.c b/Src/signals.c
index fd5d47e71..9959d3c31 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -697,10 +697,8 @@ dosavetrap(int sig, int level)
 	 * Get the old function: this assumes we haven't added
 	 * the new one yet.
 	 */
-	char func[20];
 	Shfunc shf, newshf = NULL;
-	sprintf(func, "TRAP%s", sigs[sig]);
-	if ((shf = (Shfunc)shfunctab->getnode2(shfunctab, func))) {
+	if ((shf = (Shfunc)gettrapnode(sig, 1))) {
 	    /* Copy the node for saving */
 	    newshf = (Shfunc) zalloc(sizeof(*newshf));
 	    newshf->nam = ztrdup(shf->nam);
@@ -837,16 +835,15 @@ removetrap(int sig)
      * That causes a little inefficiency, but a good deal more reliability.
      */
     if (trapped & ZSIG_FUNC) {
-	char func[20];
-	HashNode node;
+	HashNode node = gettrapnode(sig, 1);
 
-	sprintf(func, "TRAP%s", sigs[sig]);
 	/*
 	 * As in dosavetrap(), don't call removeshfuncnode() because
 	 * that calls back into unsettrap();
 	 */
 	sigfuncs[sig] = NULL;
-	node = removehashnode(shfunctab, func);
+	if (node)
+	    removehashnode(shfunctab, node->nam);
 	unqueue_signals();
 
 	return node;
@@ -1010,10 +1007,10 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
     runhookdef(BEFORETRAPHOOK, NULL);
     if (*sigtr & ZSIG_FUNC) {
 	int osc = sfcontext;
+	HashNode hn = gettrapnode(sig, 0);
 
 	args = znewlinklist();
-	name = (char *) zalloc(5 + strlen(sigs[sig]));
-	sprintf(name, "TRAP%s", sigs[sig]);
+	name = ztrdup(hn->nam);
 	zaddlinknode(args, name);
 	sprintf(num, "%d", sig);
 	zaddlinknode(args, num);
diff --git a/Src/utils.c b/Src/utils.c
index 047aa2644..20eef2ac6 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3969,27 +3969,6 @@ restoredir(struct dirsav *d)
     return err;
 }
 
-/* Get a signal number from a string */
-
-/**/
-mod_export int
-getsignum(char *s)
-{
-    int x, i;
-
-    /* check for a signal specified by number */
-    x = atoi(s);
-    if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
-	return x;
-
-    /* search for signal by name */
-    for (i = 0; i < VSIGCOUNT; i++)
-	if (!strcmp(s, sigs[i]))
-	    return i;
-
-    /* no matching signal */
-    return -1;
-}
 
 /* Check whether the shell is running with privileges in effect.  *
  * This is the case if EITHER the euid is zero, OR (if the system *