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

Re: Bug#310872: zsh can't be a ksh replacement (can't trap ERR).



Bart Schaefer wrote:
> I note in passing that "trap" in zsh doesn't understand all the same
> signals that "kill" does.  For example, when the OS defines both, "kill"
> understands SIGIO as a synonym for SIGPOLL and SIGCLD for SIGCHLD, but
> "trap" only knows CHLD and POLL.

How did you work this out?

% grep SIGIO /usr/include/asm/signal.h
#define SIGIOT           6
#define SIGIO           29
#define SIGPOLL         SIGIO
% trap 'echo foo' POLL
% trap
trap -- 'echo foo' POLL
% trap 'echo bar' IO
% trap
trap -- 'echo bar' POLL

Currently SIGPOLL is always the basic signal because there isn't an easy
way of deciding, although the form of the header suggests SIGIO is more
basic here.  With the existing code this causes the trap always to be
listed as POLL.  I've fixed this in the patch below.  It doesn't help
with the $signals array, however.  (Function traps always showed up
under the original name.)

Adding SIGERR as an alias where there's no system signal is trivial.
Now it should show up in the trap lists under ERR, too.  I've removed
the ALT_SIGS definition because there isn't really any justification for
making the mechanism optional now.

Index: Doc/Zsh/func.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/func.yo,v
retrieving revision 1.9
diff -u -r1.9 func.yo
--- Doc/Zsh/func.yo	1 Apr 2005 12:04:22 -0000	1.9
+++ Doc/Zsh/func.yo	1 Jun 2005 10:25:59 -0000
@@ -222,11 +222,14 @@
 or when the current function exits if defined inside a function.
 )
 findex(TRAPZERR)
+findex(TRAPERR)
 item(tt(TRAPZERR))(
 Executed whenever a command has a non-zero exit status.  However, the
 function is not executed if the command occurred in a sublist followed by
 `tt(&&)' or `tt(||)'; only the final command in a sublist of this type
-causes the trap to be executed.
+causes the trap to be executed.  The function tt(TRAPERR) acts the same as
+tt(TRAPZERR) on systems where there is no tt(SIGERR) (this is the usual
+case).
 )
 enditem()
 
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.137
diff -u -r1.137 builtin.c
--- Src/builtin.c	25 Apr 2005 10:18:33 -0000	1.137
+++ Src/builtin.c	1 Jun 2005 10:26:00 -0000
@@ -4978,13 +4978,14 @@
 		    shfunctab->printnode(hn, 0);
 		DPUTS(!hn, "BUG: I did not find any trap functions!");
 	    } else if (sigtrapped[sig]) {
+		char *name = getsigname(sig);
 		if (!siglists[sig])
-		    printf("trap -- '' %s\n", sigs[sig]);
+		    printf("trap -- '' %s\n", name);
 		else {
 		    s = getpermtext(siglists[sig], NULL);
 		    printf("trap -- ");
 		    quotedzputs(s, stdout);
-		    printf(" %s\n", sigs[sig]);
+		    printf(" %s\n", name);
 		    zsfree(s);
 		}
 	    }
@@ -5017,14 +5018,25 @@
     /* set traps */
     for (; *argv; argv++) {
 	Eprog t;
+	int flags;
 
 	sig = getsignum(*argv);
 	if (sig == -1) {
 	    zwarnnam(name, "undefined signal: %s", *argv, 0);
 	    break;
 	}
+	if (!strcmp(sigs[sig], *argv))
+	    flags = 0;
+	else {
+	    /*
+	     * Record that the signal is used under an assumed name.
+	     * If we ever have more than one alias per signal this
+	     * will need improving.
+	     */
+	    flags = ZSIG_ALIAS;
+	}
 	t = dupeprog(prog, 0);
-	if (settrap(sig, t, 0))
+	if (settrap(sig, t, flags))
 	    freeeprog(t);
     }
     return *argv != NULL;
Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.38
diff -u -r1.38 jobs.c
--- Src/jobs.c	28 Feb 2005 14:29:12 -0000	1.38
+++ Src/jobs.c	1 Jun 2005 10:26:00 -0000
@@ -1819,18 +1819,6 @@
     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;
@@ -1845,9 +1833,15 @@
     { "IO", SIGIO },
 #endif
 #endif
+#if !defined(SIGERR)
+    /*
+     * If SIGERR is not defined by the operating system, use it
+     * as an alias for SIGZERR.
+     */
+    { "ERR", SIGZERR },
+#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       *
@@ -1879,7 +1873,6 @@
 			    for (sig = 1; sig <= SIGCOUNT; sig++)
 				if (!cstrpcmp(sigs + sig, &signame))
 				    break;
-#ifdef ALT_SIGS
 			    if (sig > SIGCOUNT) {
 				int i;
 
@@ -1890,7 +1883,6 @@
 					break;
 				    }
 			    }
-#endif
 			    if (sig > SIGCOUNT) {
 				zwarnnam(nam, "unknown signal: SIG%s",
 					 signame, 0);
@@ -1953,7 +1945,6 @@
 			break;
 		if (*signame == '0' && !signame[1])
 		    sig = 0;
-#ifdef ALT_SIGS
 		if (sig > SIGCOUNT) {
 		    int i;
 
@@ -1964,7 +1955,6 @@
 			    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);
@@ -2042,18 +2032,40 @@
 	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 name for a signal. */
+
+/**/
+mod_export const char *
+getsigname(int sig)
+{
+    if (sigtrapped[sig] & ZSIG_ALIAS)
+    {
+	int i;
+	for (i = 0; alt_sigs[i].name; i++)
+	    if (sig == alt_sigs[i].num)
+		return alt_sigs[i].name;
+    }
+    else
+	return sigs[sig];
+
+    /* shouldn't reach here */
+#ifdef DEBUG
+    dputs("Bad alias flag for signal");
+#endif
+    return "";
+}
+
+
 /* Get the function node for a trap, taking care about alternative names */
 /**/
 HashNode
@@ -2062,9 +2074,7 @@
     char fname[20];
     HashNode hn;
     HashNode (*getptr)(HashTable ht, char *name);
-#ifdef ALT_SIGS
     int i;
-#endif
     if (ignoredisable)
 	getptr = shfunctab->getnode2;
     else
@@ -2074,7 +2084,6 @@
     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);
@@ -2082,7 +2091,6 @@
 		return hn;
 	}
     }
-#endif
 
     return NULL;
 }
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.73
diff -u -r1.73 zsh.h
--- Src/zsh.h	12 Apr 2005 15:11:12 -0000	1.73
+++ Src/zsh.h	1 Jun 2005 10:26:00 -0000
@@ -1852,7 +1852,8 @@
 /* Mask to get the above flags */
 #define ZSIG_MASK	(ZSIG_TRAPPED|ZSIG_IGNORED|ZSIG_FUNC)
 /* No. of bits to shift local level when storing in sigtrapped */
-#define ZSIG_SHIFT	3
+#define ZSIG_ALIAS	(1<<3)  /* Trap is stored under an alias */
+#define ZSIG_SHIFT	4
 
 /**********************************/
 /* Flags to third argument of zle */


-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

**********************************************************************



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