diff options
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/shell/hush.c b/shell/hush.c index b76351f..2a734f3 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -3373,12 +3373,47 @@ static void done_pipe(struct parse_context *ctx, pipe_style type) debug_printf_parse("done_pipe entered, followup %d\n", type); /* Close previous command */ not_null = done_command(ctx); - ctx->pipe->followup = type; #if HAS_KEYWORDS ctx->pipe->pi_inverted = ctx->ctx_inverted; ctx->ctx_inverted = 0; ctx->pipe->res_word = ctx->ctx_res_w; #endif + if (type != PIPE_BG || ctx->list_head == ctx->pipe) { + no_conv: + ctx->pipe->followup = type; + } else { + /* Necessary since && and || have more precedence than &: + * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2, + * in a backgrounded subshell. + */ + struct pipe *pi; + struct command *command; + + /* Is this actually the case? */ + pi = ctx->list_head; + while (pi != ctx->pipe) { + if (pi->followup != PIPE_AND && pi->followup != PIPE_OR) + goto no_conv; + pi = pi->next; + } + + debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n"); + pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */ + pi = xzalloc(sizeof(*pi)); + pi->followup = PIPE_BG; + pi->num_cmds = 1; + pi->cmds = xzalloc(sizeof(pi->cmds[0])); + command = &pi->cmds[0]; + if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */ + command->cmd_type = CMD_NORMAL; + command->group = ctx->list_head; +#if !BB_MMU +//TODO: is this correct?! + command->group_as_string = xstrdup(ctx->as_string.data); +#endif + /* Replace all pipes in ctx with one newly created */ + ctx->list_head = ctx->pipe = pi; + } /* Without this check, even just <enter> on command line generates * tree of three NOPs (!). Which is harmless but annoying. |