Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 Mar 2010 14:24:35 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r205154 - in head: bin/sh tools/regression/bin/sh/builtins tools/regression/bin/sh/errors
Message-ID:  <201003141424.o2EEOZCP065456@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Sun Mar 14 14:24:35 2010
New Revision: 205154
URL: http://svn.freebsd.org/changeset/base/205154

Log:
  sh: Do not abort on a redirection error on a compound command.
  
  Redirection errors on subshells already did not abort the shell because
  the redirection is executed in the subshell.
  
  Other shells seem to agree that these redirection errors should not abort
  the shell.
  
  Also ensure that the redirections will be cleaned up properly in cases like
    command eval '{ shift x; } 2>/dev/null'
  
  Example:
    { echo bad; } </var/empty/x; echo good

Added:
  head/tools/regression/bin/sh/builtins/command11.0   (contents, props changed)
  head/tools/regression/bin/sh/errors/redirection-error6.0   (contents, props changed)
Modified:
  head/bin/sh/eval.c

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c	Sun Mar 14 13:51:12 2010	(r205153)
+++ head/bin/sh/eval.c	Sun Mar 14 14:24:35 2010	(r205154)
@@ -91,6 +91,7 @@ STATIC void evalloop(union node *, int);
 STATIC void evalfor(union node *, int);
 STATIC void evalcase(union node *, int);
 STATIC void evalsubshell(union node *, int);
+STATIC void evalredir(union node *, int);
 STATIC void expredir(union node *);
 STATIC void evalpipe(union node *);
 STATIC void evalcommand(union node *, int, struct backcmd *);
@@ -221,10 +222,7 @@ evaltree(union node *n, int flags)
 		evaltree(n->nbinary.ch2, flags);
 		break;
 	case NREDIR:
-		expredir(n->nredir.redirect);
-		redirect(n->nredir.redirect, REDIR_PUSH);
-		evaltree(n->nredir.n, flags);
-		popredir();
+		evalredir(n, flags);
 		break;
 	case NSUBSHELL:
 		evalsubshell(n, flags);
@@ -415,6 +413,46 @@ evalsubshell(union node *n, int flags)
 }
 
 
+/*
+ * Evaluate a redirected compound command.
+ */
+
+STATIC void
+evalredir(union node *n, int flags)
+{
+	struct jmploc jmploc;
+	struct jmploc *savehandler;
+	volatile int in_redirect = 1;
+
+	expredir(n->nredir.redirect);
+	savehandler = handler;
+	if (setjmp(jmploc.loc)) {
+		int e;
+
+		handler = savehandler;
+		e = exception;
+		if (e == EXERROR || e == EXEXEC) {
+			popredir();
+			if (in_redirect) {
+				exitstatus = 2;
+				return;
+			}
+		}
+		longjmp(handler->loc, 1);
+	} else {
+		INTOFF;
+		handler = &jmploc;
+		redirect(n->nredir.redirect, REDIR_PUSH);
+		in_redirect = 0;
+		INTON;
+		evaltree(n->nredir.n, flags);
+	}
+	INTOFF;
+	handler = savehandler;
+	popredir();
+	INTON;
+}
+
 
 /*
  * Compute the names of the files in a redirection list.

Added: head/tools/regression/bin/sh/builtins/command11.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/builtins/command11.0	Sun Mar 14 14:24:35 2010	(r205154)
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+failures=0
+
+check() {
+	if ! eval "[ $* ]"; then
+		echo "Failed: $*"
+		: $((failures += 1))
+	fi
+}
+
+check '"$({ command eval \{ shift x\; \} 2\>/dev/null; } >/dev/null; echo hi)" = hi'
+
+exit $((failures > 0))

Added: head/tools/regression/bin/sh/errors/redirection-error6.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/errors/redirection-error6.0	Sun Mar 14 14:24:35 2010	(r205154)
@@ -0,0 +1,12 @@
+# $FreeBSD$
+# A redirection error on a compound command should not abort the shell.
+exec 2>/dev/null
+{ echo bad; } </var/empty/x
+if :; then echo bad; fi </var/empty/x
+for i in 1; do echo bad; done </var/empty/x
+i=0
+while [ $i = 0 ]; do echo bad; i=1; done </var/empty/x
+i=0
+until [ $i != 0 ]; do echo bad; i=1; done </var/empty/x
+case i in *) echo bad ;; esac </var/empty/x
+exit 0



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003141424.o2EEOZCP065456>