summaryrefslogtreecommitdiff
path: root/execute_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'execute_cmd.c')
-rw-r--r--execute_cmd.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/execute_cmd.c b/execute_cmd.c
index e3da9bfb..8f9d9a7e 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -2276,7 +2276,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
{
WORD_LIST *words, *lastword;
char *command_line, *lastarg, *temp;
- int first_word_quoted, result, builtin_is_special, already_forked;
+ int first_word_quoted, result, builtin_is_special, already_forked, dofork;
pid_t old_last_command_subst_pid;
Function *builtin;
SHELL_VAR *func;
@@ -2298,8 +2298,23 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
old_last_command_subst_pid = last_command_subst_pid;
- already_forked = 0;
- if (pipe_in != NO_PIPE || pipe_out != NO_PIPE || async)
+ already_forked = dofork = 0;
+
+ /* If we're in a pipeline or run in the background, set DOFORK so we
+ make the child early, before word expansion. This keeps assignment
+ statements from affecting the parent shell's environment when they
+ should not. */
+ dofork = pipe_in != NO_PIPE || pipe_out != NO_PIPE || async;
+
+ /* Something like `%2 &' should restart job 2 in the background, not cause
+ the shell to fork here. */
+ if (dofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE &&
+ simple_command->words && simple_command->words->word &&
+ simple_command->words->word->word &&
+ (simple_command->words->word->word[0] == '%'))
+ dofork = 0;
+
+ if (dofork)
{
/* XXX memory leak if expand_words() error causes a jump_to_top_level */
command_line = savestring (the_printed_command);
@@ -2312,7 +2327,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
do_piping (pipe_in, pipe_out);
pipe_in = pipe_out = -1;
- subshell_environment = SUBSHELL_ASYNC;
+ subshell_environment = async ? SUBSHELL_ASYNC : SUBSHELL_FORK;
}
else
{