summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Doc/Zsh/options.yo6
-rw-r--r--Src/builtin.c10
-rw-r--r--Src/exec.c22
-rw-r--r--Test/A04redirect.ztst49
5 files changed, 82 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index bcaab5c63..cb9dcfd71 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-02-22  Peter Stephenson  <p.w.stephenson@ntlworld.com>
+
+	* 28791: Doc/Zsh/options.yo, Src/builtin.c, Src/exec.c,
+	Test/A04redirect.ztst: exit on errors in special builtins
+	with POSIXBUILTINS.
+
 2011-02-21  Peter Stephenson  <pws@csr.com>
 
 	* 28783: Doc/Zsh/options.yo, Src/lex.c, Test/A01grammar.ztst:
@@ -14242,5 +14248,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.5205 $
+* $Revision: 1.5206 $
 *****************************************************
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index 4ecf8f831..892378469 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1871,9 +1871,9 @@ tt(times),
 tt(trap) and
 tt(unset).
 
-In addition, a failed redirection after tt(exec) causes a non-interactive
-shell to exit and an interactive shell to return to its top-level
-processing.
+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.
 )
 pindex(POSIX_IDENTIFIERS)
 pindex(NO_POSIX_IDENTIFIERS)
diff --git a/Src/builtin.c b/Src/builtin.c
index a85a49a20..aa87dfb7d 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4821,8 +4821,14 @@ bin_dot(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
 	freearray(pparams);
 	pparams = old;
     }
-    if (ret == SOURCE_NOT_FOUND)
-	zwarnnam(name, "%e: %s", errno, enam);
+    if (ret == SOURCE_NOT_FOUND) {
+	if (isset(POSIXBUILTINS)) {
+	    /* hard error in POSIX (we'll exit later) */
+	    zerrnam(name, "%e: %s", errno, enam);
+	} else {
+	    zwarnnam(name, "%e: %s", errno, enam);
+	}
+    }
     zsfree(arg0);
     if (old0) {
 	zsfree(argzero);
diff --git a/Src/exec.c b/Src/exec.c
index da67465d8..25a2eee38 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -2416,6 +2416,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
 		checked = !(cflags & BINF_BUILTIN);
 		break;
 	    }
+	    cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
+	    cflags |= hn->flags;
 	    if (!(hn->flags & BINF_PREFIX)) {
 		is_builtin = 1;
 
@@ -2425,8 +2427,6 @@ execcmd(Estate state, int input, int output, int how, int last1)
 		assign = (hn->flags & BINF_MAGICEQUALS);
 		break;
 	    }
-	    cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
-	    cflags |= hn->flags;
 	    checked = 0;
 	    if ((cflags & BINF_COMMAND) && nextnode(firstnode(args))) {
 		/* check for options to command builtin */
@@ -3297,12 +3297,20 @@ execcmd(Estate state, int input, int output, int how, int last1)
     fixfds(save);
 
  done:
-    if (redir_err && isset(POSIXBUILTINS)) {
-	if (!isset(INTERACTIVE)) {
-	    /* We've already _exit'ed if forked */
-	    exit(1);
+    if (isset(POSIXBUILTINS) &&
+	(cflags & (BINF_PSPECIAL|BINF_EXEC))) {
+	/*
+	 * For POSIX-compatibile behaviour with special
+	 * builtins (including exec which we don't usually
+	 * classify as a builtin, we treat all errors as fatal.
+	 */
+	if (redir_err || errflag) {
+	    if (!isset(INTERACTIVE)) {
+		/* We've already _exit'ed if forked */
+		exit(1);
+	    }
+	    errflag = 1;
 	}
-	errflag = 1;
     }
     if (newxtrerr) {
 	fil = fileno(newxtrerr);
diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst
index c35977c66..9340b71f0 100644
--- a/Test/A04redirect.ztst
+++ b/Test/A04redirect.ztst
@@ -378,3 +378,52 @@
   echo output'
 1:failed exec redir, POSIX_BUILTINS
 ?zsh:2: no such file or directory: /nonexistent/nonexistent
+
+  $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
+  set >/nonexistent/nonexistent
+  echo output'
+1:failed special builtin redir, POSIX_BUILTINS
+?zsh:2: no such file or directory: /nonexistent/nonexistent
+
+  $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
+  echo >/nonexistent/nonexistent
+  echo output'
+0:failed unspecial builtin redir, POSIX_BUILTINS
+>output
+?zsh:2: no such file or directory: /nonexistent/nonexistent
+
+  $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS -c '
+  . /nonexistent/nonexistent
+  echo output'
+1:failed dot, POSIX_BUILTINS
+?zsh:.:2: no such file or directory: /nonexistent/nonexistent
+
+  $ZTST_testdir/../Src/zsh -f -c '
+  . /nonexistent/nonexistent
+  echo output'
+0:failed dot, NO_POSIX_BUILTINS
+>output
+?zsh:.:2: no such file or directory: /nonexistent/nonexistent
+
+  $ZTST_testdir/../Src/zsh -f <<<'
+  readonly foo
+  foo=bar set output
+  echo output'
+0:failed assignment on posix special, NO_POSIX_BUILTINS
+>output
+?zsh: read-only variable: foo
+
+  $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS <<<'
+  readonly foo
+  foo=bar set output
+  echo output'
+1:failed assignment on posix special, POSIX_BUILTINS
+?zsh: read-only variable: foo
+
+  $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS <<<'
+  readonly foo
+  foo=bar echo output
+  echo output'
+0:failed assignment on non-posix-special, POSIX_BUILTINS
+>output
+?zsh: read-only variable: foo