about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2015-04-15 09:44:19 +0100
committerPeter Stephenson <pws@zsh.org>2015-04-15 09:44:19 +0100
commita2c579050fbf40eb9192f043e901e6b2eff3ab50 (patch)
tree320c38cb5e98627b020da1f1ca9be387641d7ee2
parent741b0bd97f6ddbd69fb2fa1dbbf6604a51488d82 (diff)
downloadzsh-a2c579050fbf40eb9192f043e901e6b2eff3ab50.tar.gz
zsh-a2c579050fbf40eb9192f043e901e6b2eff3ab50.tar.xz
zsh-a2c579050fbf40eb9192f043e901e6b2eff3ab50.zip
34887: Fix POSIX_BUILTINS with assignment.
In the form
  var=val command special-builtin-or-func
the var is restored after execution, unlike the case where "command"
is absent.

Clear up case in code that handles this.

Add tests.
-rw-r--r--ChangeLog6
-rw-r--r--Src/exec.c28
-rw-r--r--Test/E01options.ztst13
3 files changed, 40 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index da61364d5..a5d8d7e85 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-04-15  Peter Stephenson  <p.stephenson@samsung.com>
+
+	* 34887: Src/exec, Test/E01options.ztst: assignments before
+	"command special-builtin/func" in POSIX_BUILTINS mode behave as
+	normal command. Tidy up case handling in code and add test.
+
 2015-04-13  Daniel Shahaf  <d.s@daniel.shahaf.name>
 
 	* users/20159: Completion/Zsh/Command/_zstyle: completion: zstyle:
diff --git a/Src/exec.c b/Src/exec.c
index 1a6149ad7..2ee37d09f 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3384,14 +3384,28 @@ execcmd(Estate state, int input, int output, int how, int last1)
 	    LinkList restorelist = 0, removelist = 0;
 	    /* builtin or shell function */
 
-	    if (!forked && ((cflags & BINF_COMMAND) ||
-			    (unset(POSIXBUILTINS) && !assign) ||
-			    (isset(POSIXBUILTINS) && !is_shfunc &&
-			     !(hn->flags & BINF_PSPECIAL)))) {
-		if (varspc)
+	    if (!forked && varspc) {
+		int do_save = 0;
+		if (isset(POSIXBUILTINS)) {
+		    /*
+		     * If it's a function or special builtin --- save
+		     * if it's got "command" in front.
+		     * If it's a normal command --- save.
+		     */
+		    if (is_shfunc || (hn->flags & BINF_PSPECIAL))
+			do_save = (orig_cflags & BINF_COMMAND);
+		    else
+			do_save = 1;
+		} else {
+		    /*
+		     * Save if it's got "command" in front or it's
+		     * not a magic-equals assignment.
+		     */
+		    if ((cflags & BINF_COMMAND) || !assign)
+			do_save = 1;
+		}
+		if (do_save)
 		    save_params(state, varspc, &restorelist, &removelist);
-		else
-		    restorelist = removelist = NULL;
 	    }
 	    if (varspc) {
 		/* Export this if the command is a shell function,
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
index 32135344f..5c453c80b 100644
--- a/Test/E01options.ztst
+++ b/Test/E01options.ztst
@@ -783,6 +783,19 @@
 >print is a shell builtin
 ?(eval):8: command not found: print
 
+  # With non-special command: original value restored
+  # With special builtin: new value kept
+  # With special builtin preceeded by "command": original value restored.
+  (setopt posixbuiltins
+  FOO=val0
+  FOO=val1 true; echo $FOO
+  FOO=val2 times 1>/dev/null 2>&1; echo $FOO
+  FOO=val3 command times 1>/dev/null 2>&1; echo $FOO)
+0:POSIX_BUILTINS and restoring variables
+>val0
+>val2
+>val2
+
 # PRINTEXITVALUE only works if shell input is coming from standard input.
 # Goodness only knows why.
   $ZTST_testdir/../Src/zsh -f <<<'