aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 3184249f5..e2b4eee95 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5435,33 +5435,13 @@ redirect(union node *redir, int flags)
int newfd;
int copied_fd2 = -1;
- if (!redir) {
+ if (!redir)
return;
- }
-
sv = NULL;
- sv_pos = 0;
INT_OFF;
- if (flags & REDIR_PUSH) {
- union node *tmp = redir;
- do {
- sv_pos++;
-#if BASH_REDIR_OUTPUT
- if (tmp->nfile.type == NTO2)
- sv_pos++;
-#endif
- tmp = tmp->nfile.next;
- } while (tmp);
- sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
- sv->next = redirlist;
- sv->pair_count = sv_pos;
- redirlist = sv;
- while (sv_pos > 0) {
- sv_pos--;
- sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
- }
- }
-
+ if (flags & REDIR_PUSH)
+ sv = redirlist;
+ sv_pos = 0;
do {
int right_fd = -1;
fd = redir->nfile.fd;
@@ -5583,6 +5563,34 @@ redirectsafe(union node *redir, int flags)
return err;
}
+static struct redirtab*
+pushredir(union node *redir)
+{
+ struct redirtab *sv;
+ int i;
+
+ if (!redir)
+ return redirlist;
+
+ i = 0;
+ do {
+ i++;
+#if BASH_REDIR_OUTPUT
+ if (redir->nfile.type == NTO2)
+ i++;
+#endif
+ redir = redir->nfile.next;
+ } while (redir);
+
+ sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
+ sv->pair_count = i;
+ while (--i >= 0)
+ sv->two_fd[i].orig = sv->two_fd[i].copy = EMPTY;
+ sv->next = redirlist;
+ redirlist = sv;
+ return sv->next;
+}
+
/*
* Undo the effects of the last redirection.
*/
@@ -5618,6 +5626,13 @@ popredir(int drop, int restore)
INT_ON;
}
+static void
+unwindredir(struct redirtab *stop)
+{
+ while (redirlist != stop)
+ popredir(/*drop:*/ 0, /*restore:*/ 0);
+}
+
/* ============ Routines to expand arguments to commands
*
@@ -8727,6 +8742,7 @@ evaltree(union node *n, int flags)
goto setstatus;
case NREDIR:
expredir(n->nredir.redirect);
+ pushredir(n->nredir.redirect);
status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
if (!status) {
status = evaltree(n->nredir.n, flags & EV_TESTED);
@@ -9622,6 +9638,7 @@ evalcommand(union node *cmd, int flags)
"\0\0", bltincmd /* why three NULs? */
};
struct localvar_list *localvar_stop;
+ struct redirtab *redir_stop;
struct stackmark smark;
union node *argp;
struct arglist arglist;
@@ -9687,6 +9704,7 @@ evalcommand(union node *cmd, int flags)
preverrout_fd = 2;
expredir(cmd->ncmd.redirect);
+ redir_stop = pushredir(cmd->ncmd.redirect);
status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
path = vpath.var_text;
@@ -9878,6 +9896,7 @@ evalcommand(union node *cmd, int flags)
out:
if (cmd->ncmd.redirect)
popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
+ unwindredir(redir_stop);
unwindlocalvars(localvar_stop);
if (lastarg) {
/* dsl: I think this is intended to be used to support
@@ -13584,8 +13603,7 @@ reset(void)
popallfiles();
/* from redir.c: */
- while (redirlist)
- popredir(/*drop:*/ 0, /*restore:*/ 0);
+ unwindredir(NULL);
/* from var.c: */
unwindlocalvars(NULL);