summaryrefslogtreecommitdiffstats
path: root/bin/sh/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sh/eval.c')
-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