summaryrefslogtreecommitdiff
path: root/execute_cmd.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-04-09 16:13:32 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2010-04-09 16:15:01 -0700
commit2d698b6e42d8dca191ac795ef5dba3bf62496eec (patch)
treeac5e0b67043c50f49160e9fe407435706cf30444 /execute_cmd.c
parentf1250933e4a2ac09a3d0b25b3877068e12f44da5 (diff)
downloadvyatta-bash-2d698b6e42d8dca191ac795ef5dba3bf62496eec.tar.gz
vyatta-bash-2d698b6e42d8dca191ac795ef5dba3bf62496eec.zip
Integrate bash 3.2 version
This is merge of current Debian stable (Lenny) version of Bash with Vyatta changes.
Diffstat (limited to 'execute_cmd.c')
-rw-r--r--execute_cmd.c104
1 files changed, 90 insertions, 14 deletions
diff --git a/execute_cmd.c b/execute_cmd.c
index 9162f3e..662889a 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1,4 +1,4 @@
-/* execute_command.c -- Execute a COMMAND structure. */
+/* execute_cmd.c -- Execute a COMMAND structure. */
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
@@ -214,6 +214,8 @@ static int special_builtin_failed;
report the correct line number. Kind of a hack. */
static int showing_function_line;
+static int line_number_for_err_trap;
+
/* For catching RETURN in a function. */
int return_catch_flag;
int return_catch_value;
@@ -359,6 +361,7 @@ execute_command (command)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
+ QUIT;
return (result);
}
@@ -501,6 +504,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
if (command == 0 || breaking || continuing || read_but_dont_execute)
return (EXECUTION_SUCCESS);
+ QUIT;
run_pending_traps ();
#if 0
@@ -663,7 +667,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
if (command->flags & CMD_STDIN_REDIR)
command->value.Simple->flags |= CMD_STDIN_REDIR;
- line_number = command->value.Simple->line;
+ line_number_for_err_trap = line_number = command->value.Simple->line;
exec_result =
execute_simple_command (command->value.Simple, pipe_in, pipe_out,
asynchronous, fds_to_close);
@@ -865,6 +869,24 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
? EXECUTION_FAILURE
: EXECUTION_SUCCESS;
+#if defined (DPAREN_ARITHMETIC) || defined (COND_COMMAND)
+ /* This is where we set PIPESTATUS from the exit status of the appropriate
+ compound commands (the ones that look enough like simple commands to
+ cause confusion). We might be able to optimize by not doing this if
+ subshell_environment != 0. */
+ switch (command->type)
+ {
+# if defined (DPAREN_ARITHMETIC)
+ case cm_arith:
+# endif
+# if defined (COND_COMMAND)
+ case cm_cond:
+# endif
+ set_pipestatus_from_exit (exec_result);
+ break;
+ }
+#endif
+
last_command_exit_value = exec_result;
run_pending_traps ();
#if 0
@@ -1187,6 +1209,10 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
the special case of an asynchronous GROUP command where the
the subshell bit is turned on down in case cm_group: below),
turn off `asynchronous', so that two subshells aren't spawned.
+ XXX - asynchronous used to be set to 0 in this block, but that
+ means that setup_async_signals was never run. Now it's set to
+ 0 after subshell_environment is set appropriately and setup_async_signals
+ is run.
This seems semantically correct to me. For example,
( foo ) & seems to say ``do the command `foo' in a subshell
@@ -1214,19 +1240,35 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
aliases. */
if (ois != interactive_shell)
expand_aliases = 0;
- asynchronous = 0;
}
/* Subshells are neither login nor interactive. */
login_shell = interactive = 0;
- subshell_environment = user_subshell ? SUBSHELL_PAREN : SUBSHELL_ASYNC;
+ if (user_subshell)
+ subshell_environment = SUBSHELL_PAREN;
+ else
+ {
+ subshell_environment = 0; /* XXX */
+ if (asynchronous)
+ subshell_environment |= SUBSHELL_ASYNC;
+ if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+ subshell_environment |= SUBSHELL_PIPE;
+ }
reset_terminating_signals (); /* in sig.c */
/* Cancel traps, in trap.c. */
restore_original_signals ();
+
+ /* Make sure restore_original_signals doesn't undo the work done by
+ make_child to ensure that asynchronous children are immune to SIGINT
+ and SIGQUIT. Turn off asynchronous to make sure more subshells are
+ not spawned. */
if (asynchronous)
- setup_async_signals ();
+ {
+ setup_async_signals ();
+ asynchronous = 0;
+ }
#if defined (JOB_CONTROL)
set_sigchld_handler ();
@@ -1308,8 +1350,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
if (function_value)
return_code = return_catch_value;
else
- return_code = execute_command_internal
- (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close);
+ return_code = execute_command_internal (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close);
/* If we are asked to, invert the return value. */
if (invert)
@@ -1629,7 +1670,11 @@ execute_for_command (for_command)
/* Save this command unless it's a trap command and we're not running
a debug trap. */
+#if 0
if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#else
+ if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+#endif
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = savestring (the_printed_command);
@@ -2048,7 +2093,11 @@ execute_select_command (select_command)
if (echo_command_at_execute)
xtrace_print_select_command_head (select_command);
+#if 0
if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#else
+ if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+#endif
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = savestring (the_printed_command);
@@ -2180,7 +2229,11 @@ execute_case_command (case_command)
if (echo_command_at_execute)
xtrace_print_case_command_head (case_command);
- if (signal_in_progress (DEBUG_TRAP == 0) && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#if 0
+ if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#else
+ if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+#endif
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = savestring (the_printed_command);
@@ -2378,6 +2431,7 @@ execute_arith_command (arith_command)
int expok, save_line_number, retval;
intmax_t expresult;
WORD_LIST *new;
+ char *exp;
expresult = 0;
@@ -2420,8 +2474,11 @@ execute_arith_command (arith_command)
if (new)
{
- expresult = evalexp (new->word->word, &expok);
+ exp = new->next ? string_list (new) : new->word->word;
+ expresult = evalexp (exp, &expok);
line_number = save_line_number;
+ if (exp != new->word->word)
+ free (exp);
dispose_words (new);
}
else
@@ -2477,6 +2534,7 @@ execute_cond_node (cond)
}
else if (cond->type == COND_BINARY)
{
+ rmatch = 0;
patmatch = ((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') &&
(cond->op->word[0] == '!' || cond->op->word[0] == '=') ||
(cond->op->word[0] == '=' && cond->op->word[1] == '\0'));
@@ -2488,7 +2546,7 @@ execute_cond_node (cond)
arg1 = cond_expand_word (cond->left->op, 0);
if (arg1 == 0)
arg1 = nullstr;
- arg2 = cond_expand_word (cond->right->op, patmatch);
+ arg2 = cond_expand_word (cond->right->op, patmatch||rmatch);
if (arg2 == 0)
arg2 = nullstr;
@@ -2614,7 +2672,10 @@ execute_null_command (redirects, pipe_in, pipe_out, async)
do_piping (pipe_in, pipe_out);
- subshell_environment = SUBSHELL_ASYNC;
+ if (async)
+ subshell_environment |= SUBSHELL_ASYNC;
+ if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+ subshell_environment |= SUBSHELL_PIPE;
if (do_redirections (redirects, RX_ACTIVE) == 0)
exit (EXECUTION_SUCCESS);
@@ -2709,7 +2770,11 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
command_string_index = 0;
print_simple_command (simple_command);
+#if 0
if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
+#else
+ if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
+#endif
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = the_printed_command ? savestring (the_printed_command) : (char *)0;
@@ -2983,7 +3048,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
}
if (command_line == 0)
- command_line = savestring (the_printed_command);
+ command_line = savestring (the_printed_command_except_trap);
execute_disk_command (words, simple_command->redirects, command_line,
pipe_in, pipe_out, async, fds_to_close,
@@ -3342,7 +3407,7 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var,
struct fd_bitmap *fds_to_close;
int flags;
{
- int result, r;
+ int result, r, funcvalue;
#if defined (JOB_CONTROL)
int jobs_hack;
@@ -3353,7 +3418,10 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var,
/* A subshell is neither a login shell nor interactive. */
login_shell = interactive = 0;
- subshell_environment = SUBSHELL_ASYNC;
+ if (async)
+ subshell_environment |= SUBSHELL_ASYNC;
+ if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
+ subshell_environment |= SUBSHELL_PIPE;
maybe_make_export_env (); /* XXX - is this needed? */
@@ -3387,10 +3455,18 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var,
so we don't go back up to main(). */
result = setjmp (top_level);
+ /* Give the return builtin a place to jump to when executed in a subshell
+ or pipeline */
+ funcvalue = 0;
+ if (return_catch_flag && builtin == return_builtin)
+ funcvalue = setjmp (return_catch);
+
if (result == EXITPROG)
exit (last_command_exit_value);
else if (result)
exit (EXECUTION_FAILURE);
+ else if (funcvalue)
+ exit (return_catch_value);
else
{
r = execute_builtin (builtin, words, flags, 1);