Module Name:    src
Committed By:   kre
Date:           Thu Aug 20 23:09:56 UTC 2020

Modified Files:
        src/bin/sh: eval.c trap.c

Log Message:
Be less conservative about when we do clear_traps() when we have
traps_invalid (that is, when we actually nuke the parent shell's
caught traps in a subshell).  This allows more reasonable use of
"trap -p" (and similar) in subshells than existed before (and in
particular, that command can be in a function now - there can also
be several related commands like
        traps=$(trap -p INT; trap -p QUIT; trap -p HUP)
A side effect of all of this is that
        (eval "$(trap -p)"; ...)
now allows copying caught traps into a subshell environment, if desired.

Also att the ksh93 variant (the one not picked by POSIX as it isn't
generally as useful) of "trap -p" (but call it "trap -P" which extracts
just the trap action for named signals (giving more than one is usually
undesirable).   This allows
        eval "$(trap -P INT)"
to run the action for SIGINT traps, without needing to attempt to parse
the "trap -p" output.


To generate a diff of this commit:
cvs rdiff -u -r1.180 -r1.181 src/bin/sh/eval.c
cvs rdiff -u -r1.54 -r1.55 src/bin/sh/trap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/eval.c
diff -u src/bin/sh/eval.c:1.180 src/bin/sh/eval.c:1.181
--- src/bin/sh/eval.c:1.180	Thu May 14 08:34:17 2020
+++ src/bin/sh/eval.c	Thu Aug 20 23:09:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: eval.c,v 1.180 2020/05/14 08:34:17 msaitoh Exp $	*/
+/*	$NetBSD: eval.c,v 1.181 2020/08/20 23:09:56 kre Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
 #else
-__RCSID("$NetBSD: eval.c,v 1.180 2020/05/14 08:34:17 msaitoh Exp $");
+__RCSID("$NetBSD: eval.c,v 1.181 2020/08/20 23:09:56 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -280,8 +280,10 @@ evaltree(union node *n, int flags)
 		next = NULL;
 		CTRACE(DBG_EVAL, ("pid %d, evaltree(%p: %s(%d), %#x) called\n",
 		    getpid(), n, NODETYPENAME(n->type), n->type, flags));
+	/*
 		if (n->type != NCMD && traps_invalid)
 			free_traps();
+	*/
 		switch (n->type) {
 		case NSEMI:
 			evaltree(n->nbinary.ch1, sflags);
@@ -302,6 +304,8 @@ evaltree(union node *n, int flags)
 			next = n->nbinary.ch2;
 			break;
 		case NREDIR:
+			if (traps_invalid)
+				free_traps();
 			evalredir(n, flags);
 			break;
 		case NSUBSHELL:
@@ -309,9 +313,13 @@ evaltree(union node *n, int flags)
 			do_etest = !(flags & EV_TESTED);
 			break;
 		case NBACKGND:
+			if (traps_invalid)
+				free_traps();
 			evalsubshell(n, flags);
 			break;
 		case NIF: {
+			if (traps_invalid)
+				free_traps();
 			evaltree(n->nif.test, EV_TESTED);
 			if (nflag || evalskip)
 				goto out1;
@@ -325,15 +333,23 @@ evaltree(union node *n, int flags)
 		}
 		case NWHILE:
 		case NUNTIL:
+			if (traps_invalid)
+				free_traps();
 			evalloop(n, sflags);
 			break;
 		case NFOR:
+			if (traps_invalid)
+				free_traps();
 			evalfor(n, sflags);
 			break;
 		case NCASE:
+			if (traps_invalid)
+				free_traps();
 			evalcase(n, sflags);
 			break;
 		case NDEFUN:
+			if (traps_invalid)
+				free_traps();
 			CTRACE(DBG_EVAL, ("Defining fn %s @%d%s\n",
 			    n->narg.text, n->narg.lineno,
 			    fnline1 ? " LINENO=1" : ""));
@@ -350,6 +366,8 @@ evaltree(union node *n, int flags)
 				exitstatus = 1;
 			break;
 		case NPIPE:
+			if (traps_invalid)
+				free_traps();
 			evalpipe(n);
 			do_etest = !(flags & EV_TESTED);
 			break;
@@ -1043,6 +1061,10 @@ evalcommand(union node *cmd, int flgs, s
 	 *	command eval trap
 	 *	eval command trap
 	 * without zapping the traps completely, in all other cases we do.
+	 * Function calls also do not zap the traps (but commands they execute
+	 * probably will) - this allows a function like
+	 *	trapstate() { trap -p; }
+	 * called as save_traps=$(trapstate).
 	 *
 	 * The test here permits eval "anything" but when evalstring() comes
 	 * back here again, the "anything" will be validated.
@@ -1055,6 +1077,7 @@ evalcommand(union node *cmd, int flgs, s
 	 * trapcmd() takes care of doing free_traps() if it is needed there.
 	 */
 	if (traps_invalid &&
+	    cmdentry.cmdtype != CMDFUNCTION &&
 	    ((cmdentry.cmdtype!=CMDSPLBLTIN && cmdentry.cmdtype!=CMDBUILTIN) ||
 	     (cmdentry.u.bltin != trapcmd && cmdentry.u.bltin != evalcmd)))
 		free_traps();

Index: src/bin/sh/trap.c
diff -u src/bin/sh/trap.c:1.54 src/bin/sh/trap.c:1.55
--- src/bin/sh/trap.c:1.54	Thu Aug 20 16:15:50 2020
+++ src/bin/sh/trap.c	Thu Aug 20 23:09:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.54 2020/08/20 16:15:50 kre Exp $	*/
+/*	$NetBSD: trap.c,v 1.55 2020/08/20 23:09:56 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)trap.c	8.5 (Berkeley) 6/5/95";
 #else
-__RCSID("$NetBSD: trap.c,v 1.54 2020/08/20 16:15:50 kre Exp $");
+__RCSID("$NetBSD: trap.c,v 1.55 2020/08/20 23:09:56 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -232,6 +232,8 @@ trapcmd(int argc, char **argv)
 	ap = argv + 1;
 
 	CTRACE(DBG_TRAP, ("trapcmd: "));
+	if (argc == 3 && strcmp(ap[1], "--") == 0)
+		argc--;
 	if (argc == 2 && strcmp(*ap, "-l") == 0) {
 		CTRACE(DBG_TRAP, ("-l\n"));
 		out1str("EXIT");
@@ -253,9 +255,9 @@ trapcmd(int argc, char **argv)
 		traps_invalid = 0;
 		return 0;
 	}
-	if (argc >= 2 && strcmp(*ap, "-p") == 0) {
-		CTRACE(DBG_TRAP, ("-p "));
-		printonly = 1;
+	if (argc >= 2 && (strcmp(*ap, "-p") == 0 || strcmp(*ap, "-P") == 0)) {
+		CTRACE(DBG_TRAP, ("%s ", *ap));
+		printonly = 1 + (ap[0][1] == 'p');
 		ap++;
 		argc--;
 	}
@@ -265,6 +267,9 @@ trapcmd(int argc, char **argv)
 		ap++;
 	}
 
+	if (printonly == 1 && argc < 2)
+		goto usage;
+
 	if (argc <= 1) {
 		int count;
 
@@ -339,8 +344,10 @@ trapcmd(int argc, char **argv)
 	}
 
 	if (argc < 2) {		/* there must be at least 1 condition */
+ usage:
 		out2str("Usage: trap [-l]\n"
 			"       trap -p [condition ...]\n"
+			"       trap -P  condition ...\n"
 			"       trap action condition ...\n"
 			"       trap N condition ...\n");
 		return 2;
@@ -365,12 +372,17 @@ trapcmd(int argc, char **argv)
 			 * (action will always be "-") here, if someone
 			 * really wants to get that particular output
 			 */
-			out1str("trap -- ");
-			if (trap[signo] == NULL)
-				out1str("-");
-			else
-				print_quoted(trap[signo]);
-			out1fmt(" %s\n", trap_signame(signo));
+			if (printonly == 1) {
+				if (trap[signo] != NULL)
+					out1fmt("%s\n", trap[signo]);
+			} else {
+				out1str("trap -- ");
+				if (trap[signo] == NULL)
+					out1str("-");
+				else
+					print_quoted(trap[signo]);
+				out1fmt(" %s\n", trap_signame(signo));
+			}
 			continue;
 		}
 

Reply via email to