Module Name:    src
Committed By:   kre
Date:           Mon Nov 26 13:47:39 UTC 2018

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

Log Message:
Make it be that an empty command is treated as a regular builtin
for the purposes of any redirects it might have -- ie: as posix
requires, make the redirects appear to have been executed in a subshell
environment, so if one fails, aside from a diagnositc msg, all the
running script sees is a command that failed ($? != 0), rather
that having the shell exit which used to happen (the empty command was
being treated as a special builtin).

Continue to treat the empty command as special for the purposes of
var assigns it might contain (those are not executed in a sub-shell
and persist) - an error there (eg: assigning to a readonly var) will
continue to cause the shell (non-interactive shell) to exit.

This makes the NetBSD shell behave like all other (reasonably modern)
shells - fix method (not the implementation, details differ) taken from
FreeBSD who fixed this back in early 2010.    Problem pointed out
in (non-list) mail by Martijn Dekker.


To generate a diff of this commit:
cvs rdiff -u -r1.163 -r1.164 src/bin/sh/eval.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.163 src/bin/sh/eval.c:1.164
--- src/bin/sh/eval.c:1.163	Fri Nov 23 23:37:22 2018
+++ src/bin/sh/eval.c	Mon Nov 26 13:47:39 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: eval.c,v 1.163 2018/11/23 23:37:22 kre Exp $	*/
+/*	$NetBSD: eval.c,v 1.164 2018/11/26 13:47:39 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.163 2018/11/23 23:37:22 kre Exp $");
+__RCSID("$NetBSD: eval.c,v 1.164 2018/11/26 13:47:39 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -873,6 +873,7 @@ evalcommand(union node *cmd, int flgs, s
 	volatile int temp_path;
 	const int savefuncline = funclinebase;
 	const int savefuncabs = funclineabs;
+	volatile int cmd_flags = 0;
 
 	vforked = 0;
 	/* First expand the arguments. */
@@ -979,11 +980,16 @@ evalcommand(union node *cmd, int flgs, s
 
 	/* Now locate the command. */
 	if (argc == 0) {
-		cmdentry.cmdtype = CMDSPLBLTIN;
+		/*
+		 * the empty command begins as a normal builtin, and
+		 * remains that way while redirects are processed, then
+		 * will become special before we get to doing the
+		 * var assigns.
+		 */
+		cmdentry.cmdtype = CMDBUILTIN;
 		cmdentry.u.bltin = bltincmd;
 	} else {
 		static const char PATH[] = "PATH=";
-		int cmd_flags = 0;
 
 		/*
 		 * Modify the command lookup path, if a PATH= assignment
@@ -1224,9 +1230,11 @@ evalcommand(union node *cmd, int flgs, s
 			exitshell(exitstatus);
 		break;
 
-	case CMDBUILTIN:
 	case CMDSPLBLTIN:
-		VXTRACE(DBG_EVAL, ("builtin command%s:  ",vforked?" VF":""), trargs(argv));
+		VTRACE(DBG_EVAL, ("special "));
+	case CMDBUILTIN:
+		VXTRACE(DBG_EVAL, ("builtin command [%d]%s:  ", argc,
+		    vforked ? " VF" : ""), trargs(argv));
 		mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;
 		if (flags == EV_BACKCMD) {
 			memout.nleft = 0;
@@ -1254,6 +1262,15 @@ evalcommand(union node *cmd, int flgs, s
 			}
 			redirect(cmd->ncmd.redirect, mode);
 
+			/*
+			 * the empty command is regarded as a normal
+			 * builtin for the purposes of redirects, but
+			 * is a special builtin for var assigns.
+			 * (unless we are the "command" command.)
+			 */
+			if (argc == 0 && !(cmd_flags & DO_NOFUNC))
+				cmdentry.cmdtype = CMDSPLBLTIN;
+
 			/* exec is a special builtin, but needs this list... */
 			cmdenviron = varlist.list;
 			/* we must check 'readonly' flag for all builtins */

Reply via email to