summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-03-14 14:24:35 +0000
committerjilles <jilles@FreeBSD.org>2010-03-14 14:24:35 +0000
commitd88c6b27847cfb6d2e02b9178df93eba8f67a461 (patch)
tree60d32e3f85931ad6ed822e0fcbfb662f567e83f9 /bin
parentb9152e6b95f7273c5f4ab0f40fb6270c9220d2eb (diff)
downloadFreeBSD-src-d88c6b27847cfb6d2e02b9178df93eba8f67a461.zip
FreeBSD-src-d88c6b27847cfb6d2e02b9178df93eba8f67a461.tar.gz
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
Diffstat (limited to 'bin')
-rw-r--r--bin/sh/eval.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 199ec1e..e93fb14 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -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.
OpenPOWER on IntegriCloud