summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2017-07-26 16:56:23 +0100
committerPeter Stephenson <pws@zsh.org>2017-07-27 09:22:04 +0100
commitd4b94b5e8388c744a1d879fecb5af957b170c4c1 (patch)
tree56352f47635ef1436e0669aa85f2f570d9d3aec7
parent18c3c12bf0dc0fdbfb9ff79ebf90475a1dadc606 (diff)
downloadzsh-d4b94b5e8388c744a1d879fecb5af957b170c4c1.tar.gz
zsh-d4b94b5e8388c744a1d879fecb5af957b170c4c1.tar.xz
zsh-d4b94b5e8388c744a1d879fecb5af957b170c4c1.zip
41464, 41466: With POSIX_BUILTINS, exec only executes sexternal commands.
Document the default behaviour and add a test.
-rw-r--r--ChangeLog5
-rw-r--r--Doc/Zsh/builtins.yo8
-rw-r--r--Doc/Zsh/options.yo4
-rw-r--r--Src/exec.c14
-rw-r--r--Test/E01options.ztst14
5 files changed, 42 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index b885ac05d..b0dcb7e44 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2017-07-26  Peter Stephenson  <p.stephenson@samsung.com>
 
+	* 41464, 41466 (modified): Doc/Zsh/builtins.yo,
+	Doc/Zsh/options.yo, Src/exec.c, Test/E01options.ztst:
+	POSIX_BUILTINS stops "exec" finding builtins or shell
+	functions.  Document existing behaviour.
+
 	* Jim: 41461: Doc/Zsh/seealso.yo: complete list of zsh manual
 	pages in introduction.
 
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 333db1c2c..99b1dd45b 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -667,7 +667,10 @@ if there are no var(args) or they contain no commands (i.e. are
 an empty string or whitespace) the return status is zero.
 )
 item(tt(exec) [ tt(-cl) ] [ tt(-a) var(argv0) ] [ var(command) [ var(arg) ... ] ])(
-Replace the current shell with an external var(command) rather than forking.
+Replace the current shell with var(command) rather than forking.
+If var(command) is a shell builtin command or a shell function,
+the shell executes it, then immediately exits.
+
 With tt(-c) clear the environment; with tt(-l) prepend tt(-) to the
 tt(argv[0]) string of the command executed (to simulate a login shell);
 with tt(-a) var(argv0) set the tt(argv[0]) string of the command
@@ -675,6 +678,9 @@ executed.
 See ifzman(the section `Precommand Modifiers' in zmanref(zshmisc))\
 ifnzman(noderef(Precommand Modifiers)).
 
+If the option tt(POSIX_BUILTINS) is set, var(command) is never
+interpreted as a shell builtin command or shell function.
+
 cindex(redirection, current shell's I/O)
 If var(command) is omitted but any redirections are specified,
 then the redirections will take effect in the current shell.
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index cc6ae2a47..70092d681 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -2140,6 +2140,10 @@ In addition, various error conditions associated with the above builtins
 or tt(exec) cause a non-interactive shell to exit and an interactive
 shell to return to its top-level processing.
 
+Furthermore, functions and shell builtins are not executed after
+an tt(exec) prefix; the command to be executed must be an external
+command found in the path.
+
 Furthermore, the tt(getopts) builtin behaves in a POSIX-compatible
 fashion in that the associated variable tt(OPTIND) is not made
 local to functions.
diff --git a/Src/exec.c b/Src/exec.c
index 0a9687998..f339dd6d0 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -2778,6 +2778,12 @@ execcmd_exec(Estate state, Execcmd_params eparams,
 		 * Reserved words take precedence over shell functions.
 		 */
 		checked = 1;
+	    } else if (isset(POSIXBUILTINS) && (cflags & BINF_EXEC)) {
+		/*
+		 * POSIX doesn't allow "exec" to operate on builtins
+		 * or shell functions.
+		 */
+		break;
 	    } else {
 		if (!(cflags & (BINF_BUILTIN | BINF_COMMAND)) &&
 		    (hn = shfunctab->getnode(shfunctab, cmdarg))) {
@@ -3123,10 +3129,14 @@ execcmd_exec(Estate state, Execcmd_params eparams,
 	     *   - we have determined there are options which would
 	     *     require us to use the "command" builtin); or
 	     * - we aren't using POSIX and so BINF_COMMAND indicates a zsh
-	     *   precommand modifier is being used in place of the builtin
+	     *   precommand modifier is being used in place of the
+	     *   builtin
+	     * - we are using POSIX and this is an EXEC, so we can't
+	     *   execute a builtin or function.
 	     */
 	    if (errflag || checked || is_builtin ||
-		(unset(POSIXBUILTINS) && (cflags & BINF_COMMAND)))
+		(isset(POSIXBUILTINS) ?
+		 (cflags & BINF_EXEC) : (cflags & BINF_COMMAND)))
 		break;
 
 	    cmdarg = (char *) peekfirst(args);
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
index dac9430cc..f01d83567 100644
--- a/Test/E01options.ztst
+++ b/Test/E01options.ztst
@@ -831,6 +831,20 @@
 >val2
 >val2
 
+  print "Contents of file" >cat_arg
+  (
+     cat() { print Function with argument $1 }
+     print Without
+     (exec cat cat_arg; print Not reached)
+     print With
+     (setopt posixbuiltins; exec cat cat_arg; print Not reached)
+  )
+0:POSIX_BUILTINS and exec
+>Without
+>Function with argument cat_arg
+>With
+>Contents of file
+
 # PRINTEXITVALUE only works if shell input is coming from standard input.
 # Goodness only knows why.
   $ZTST_testdir/../Src/zsh -f <<<'