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 */