mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-22 05:17:59 +02:00
554 lines
17 KiB
Plaintext
554 lines
17 KiB
Plaintext
*** ../bash-3.0-patched/execute_cmd.c Sun Jul 4 14:12:58 2004
|
|
--- execute_cmd.c Wed Dec 1 16:50:48 2004
|
|
***************
|
|
*** 1,5 ****
|
|
/* execute_command.c -- Execute a COMMAND structure. */
|
|
|
|
! /* Copyright (C) 1987-2003 Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Bash, the Bourne Again SHell.
|
|
--- 1,5 ----
|
|
/* execute_command.c -- Execute a COMMAND structure. */
|
|
|
|
! /* Copyright (C) 1987-2004 Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Bash, the Bourne Again SHell.
|
|
***************
|
|
*** 161,165 ****
|
|
static int execute_while_or_until __P((WHILE_COM *, int));
|
|
static int execute_if_command __P((IF_COM *));
|
|
! static int execute_null_command __P((REDIRECT *, int, int, int, pid_t));
|
|
static void fix_assignment_words __P((WORD_LIST *));
|
|
static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
|
|
--- 161,165 ----
|
|
static int execute_while_or_until __P((WHILE_COM *, int));
|
|
static int execute_if_command __P((IF_COM *));
|
|
! static int execute_null_command __P((REDIRECT *, int, int, int));
|
|
static void fix_assignment_words __P((WORD_LIST *));
|
|
static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
|
|
***************
|
|
*** 492,496 ****
|
|
int exec_result, invert, ignore_return, was_error_trap;
|
|
REDIRECT *my_undo_list, *exec_undo_list;
|
|
- volatile pid_t last_pid;
|
|
volatile int save_line_number;
|
|
|
|
--- 492,495 ----
|
|
***************
|
|
*** 649,653 ****
|
|
call to execute_simple_command if a longjmp occurs as the
|
|
result of a `return' builtin. This is true for sure with gcc. */
|
|
! last_pid = last_made_pid;
|
|
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
|
|
|
|
--- 648,652 ----
|
|
call to execute_simple_command if a longjmp occurs as the
|
|
result of a `return' builtin. This is true for sure with gcc. */
|
|
! last_made_pid = NO_PID;
|
|
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
|
|
|
|
***************
|
|
*** 679,683 ****
|
|
when the shell is compiled without job control. */
|
|
if (already_making_children && pipe_out == NO_PIPE &&
|
|
! last_pid != last_made_pid)
|
|
{
|
|
stop_pipeline (asynchronous, (COMMAND *)NULL);
|
|
--- 678,682 ----
|
|
when the shell is compiled without job control. */
|
|
if (already_making_children && pipe_out == NO_PIPE &&
|
|
! last_made_pid != NO_PID)
|
|
{
|
|
stop_pipeline (asynchronous, (COMMAND *)NULL);
|
|
***************
|
|
*** 699,710 ****
|
|
pipelines) to be waited for twice. */
|
|
exec_result = wait_for (last_made_pid);
|
|
- #if defined (RECYCLES_PIDS)
|
|
- /* LynxOS, for one, recycles pids very quickly -- so quickly
|
|
- that a new process may have the same pid as the last one
|
|
- created. This has been reported to fix the problem on that
|
|
- OS, and a similar problem on Cygwin. */
|
|
- if (exec_result == 0)
|
|
- last_made_pid = NO_PID;
|
|
- #endif
|
|
}
|
|
}
|
|
--- 698,701 ----
|
|
***************
|
|
*** 1275,1278 ****
|
|
--- 1266,1274 ----
|
|
tcom = (command->type == cm_subshell) ? command->value.Subshell->command : command;
|
|
|
|
+ if (command->flags & CMD_TIME_PIPELINE)
|
|
+ tcom->flags |= CMD_TIME_PIPELINE;
|
|
+ if (command->flags & CMD_TIME_POSIX)
|
|
+ tcom->flags |= CMD_TIME_POSIX;
|
|
+
|
|
/* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */
|
|
if ((command->flags & CMD_IGNORE_RETURN) && tcom != command)
|
|
***************
|
|
*** 1356,1359 ****
|
|
--- 1352,1356 ----
|
|
terminate_current_pipeline ();
|
|
kill_current_pipeline ();
|
|
+ UNBLOCK_CHILD (oset);
|
|
#endif /* JOB_CONTROL */
|
|
last_command_exit_value = EXECUTION_FAILURE;
|
|
***************
|
|
*** 1623,1628 ****
|
|
xtrace_print_for_command_head (for_command);
|
|
|
|
! /* Save this command unless it's a trap command. */
|
|
! if (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))
|
|
{
|
|
FREE (the_printed_command_except_trap);
|
|
--- 1620,1626 ----
|
|
xtrace_print_for_command_head (for_command);
|
|
|
|
! /* Save this command unless it's a trap command and we're not running
|
|
! a debug trap. */
|
|
! if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
|
|
{
|
|
FREE (the_printed_command_except_trap);
|
|
***************
|
|
*** 1639,1643 ****
|
|
|
|
this_command_name = (char *)NULL;
|
|
! v = bind_variable (identifier, list->word->word);
|
|
if (readonly_p (v) || noassign_p (v))
|
|
{
|
|
--- 1637,1641 ----
|
|
|
|
this_command_name = (char *)NULL;
|
|
! v = bind_variable (identifier, list->word->word, 0);
|
|
if (readonly_p (v) || noassign_p (v))
|
|
{
|
|
***************
|
|
*** 1686,1690 ****
|
|
SHELL_VAR *new_value;
|
|
|
|
! new_value = bind_variable (identifier, value_cell(old_value));
|
|
new_value->attributes = old_value->attributes;
|
|
dispose_variable (old_value);
|
|
--- 1684,1688 ----
|
|
SHELL_VAR *new_value;
|
|
|
|
! new_value = bind_variable (identifier, value_cell(old_value), 0);
|
|
new_value->attributes = old_value->attributes;
|
|
dispose_variable (old_value);
|
|
***************
|
|
*** 1732,1737 ****
|
|
command_string_index = 0;
|
|
print_arith_command (new);
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
|
|
r = run_debug_trap ();
|
|
--- 1730,1738 ----
|
|
command_string_index = 0;
|
|
print_arith_command (new);
|
|
! if (signal_in_progress (DEBUG_TRAP) == 0)
|
|
! {
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
! }
|
|
|
|
r = run_debug_trap ();
|
|
***************
|
|
*** 2040,2045 ****
|
|
xtrace_print_select_command_head (select_command);
|
|
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
|
|
retval = run_debug_trap ();
|
|
--- 2041,2049 ----
|
|
xtrace_print_select_command_head (select_command);
|
|
|
|
! if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
|
|
! {
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
! }
|
|
|
|
retval = run_debug_trap ();
|
|
***************
|
|
*** 2093,2097 ****
|
|
}
|
|
|
|
! v = bind_variable (identifier, selection);
|
|
if (readonly_p (v) || noassign_p (v))
|
|
{
|
|
--- 2097,2101 ----
|
|
}
|
|
|
|
! v = bind_variable (identifier, selection, 0);
|
|
if (readonly_p (v) || noassign_p (v))
|
|
{
|
|
***************
|
|
*** 2169,2173 ****
|
|
xtrace_print_case_command_head (case_command);
|
|
|
|
! if (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))
|
|
{
|
|
FREE (the_printed_command_except_trap);
|
|
--- 2173,2177 ----
|
|
xtrace_print_case_command_head (case_command);
|
|
|
|
! if (signal_in_progress (DEBUG_TRAP == 0) && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
|
|
{
|
|
FREE (the_printed_command_except_trap);
|
|
***************
|
|
*** 2186,2197 ****
|
|
#endif
|
|
|
|
- /* Posix.2 specifies that the WORD is tilde expanded. */
|
|
- if (member ('~', case_command->word->word))
|
|
- {
|
|
- word = bash_tilde_expand (case_command->word->word, 0);
|
|
- free (case_command->word->word);
|
|
- case_command->word->word = word;
|
|
- }
|
|
-
|
|
wlist = expand_word_unsplit (case_command->word, 0);
|
|
word = wlist ? string_list (wlist) : savestring ("");
|
|
--- 2190,2193 ----
|
|
***************
|
|
*** 2211,2223 ****
|
|
for (list = clauses->patterns; list; list = list->next)
|
|
{
|
|
- /* Posix.2 specifies to tilde expand each member of the pattern
|
|
- list. */
|
|
- if (member ('~', list->word->word))
|
|
- {
|
|
- pattern = bash_tilde_expand (list->word->word, 0);
|
|
- free (list->word->word);
|
|
- list->word->word = pattern;
|
|
- }
|
|
-
|
|
es = expand_word_leave_quoted (list->word, 0);
|
|
|
|
--- 2207,2210 ----
|
|
***************
|
|
*** 2396,2401 ****
|
|
command_string_index = 0;
|
|
print_arith_command (arith_command->exp);
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
|
|
/* Run the debug trap before each arithmetic command, but do it after we
|
|
--- 2383,2392 ----
|
|
command_string_index = 0;
|
|
print_arith_command (arith_command->exp);
|
|
!
|
|
! if (signal_in_progress (DEBUG_TRAP) == 0)
|
|
! {
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
! }
|
|
|
|
/* Run the debug trap before each arithmetic command, but do it after we
|
|
***************
|
|
*** 2509,2515 ****
|
|
else
|
|
#endif /* COND_REGEXP */
|
|
! result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP)
|
|
! ? EXECUTION_SUCCESS
|
|
! : EXECUTION_FAILURE;
|
|
if (arg1 != nullstr)
|
|
free (arg1);
|
|
--- 2500,2512 ----
|
|
else
|
|
#endif /* COND_REGEXP */
|
|
! {
|
|
! int oe;
|
|
! oe = extended_glob;
|
|
! extended_glob = 1;
|
|
! result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP)
|
|
! ? EXECUTION_SUCCESS
|
|
! : EXECUTION_FAILURE;
|
|
! extended_glob = oe;
|
|
! }
|
|
if (arg1 != nullstr)
|
|
free (arg1);
|
|
***************
|
|
*** 2547,2552 ****
|
|
command_string_index = 0;
|
|
print_cond_command (cond_command);
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
|
|
/* Run the debug trap before each conditional command, but do it after we
|
|
--- 2544,2553 ----
|
|
command_string_index = 0;
|
|
print_cond_command (cond_command);
|
|
!
|
|
! if (signal_in_progress (DEBUG_TRAP) == 0)
|
|
! {
|
|
! FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
! }
|
|
|
|
/* Run the debug trap before each conditional command, but do it after we
|
|
***************
|
|
*** 2581,2585 ****
|
|
if (arg == 0)
|
|
arg = "";
|
|
! var = bind_variable ("_", arg);
|
|
VUNSETATTR (var, att_exported);
|
|
}
|
|
--- 2582,2586 ----
|
|
if (arg == 0)
|
|
arg = "";
|
|
! var = bind_variable ("_", arg, 0);
|
|
VUNSETATTR (var, att_exported);
|
|
}
|
|
***************
|
|
*** 2589,2596 ****
|
|
supposed to take place. */
|
|
static int
|
|
! execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subst_pid)
|
|
REDIRECT *redirects;
|
|
int pipe_in, pipe_out, async;
|
|
- pid_t old_last_command_subst_pid;
|
|
{
|
|
int r;
|
|
--- 2590,2596 ----
|
|
supposed to take place. */
|
|
static int
|
|
! execute_null_command (redirects, pipe_in, pipe_out, async)
|
|
REDIRECT *redirects;
|
|
int pipe_in, pipe_out, async;
|
|
{
|
|
int r;
|
|
***************
|
|
*** 2638,2642 ****
|
|
if (r != 0)
|
|
return (EXECUTION_FAILURE);
|
|
! else if (old_last_command_subst_pid != last_command_subst_pid)
|
|
return (last_command_exit_value);
|
|
else
|
|
--- 2638,2642 ----
|
|
if (r != 0)
|
|
return (EXECUTION_FAILURE);
|
|
! else if (last_command_subst_pid != NO_PID)
|
|
return (last_command_exit_value);
|
|
else
|
|
***************
|
|
*** 2667,2672 ****
|
|
if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
|
|
return;
|
|
}
|
|
! w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP);
|
|
}
|
|
}
|
|
--- 2667,2674 ----
|
|
if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
|
|
return;
|
|
+ else if (b && (b->flags & ASSIGNMENT_BUILTIN))
|
|
+ words->word->flags |= W_ASSNBLTIN;
|
|
}
|
|
! w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
|
|
}
|
|
}
|
|
***************
|
|
*** 2684,2688 ****
|
|
char *command_line, *lastarg, *temp;
|
|
int first_word_quoted, result, builtin_is_special, already_forked, dofork;
|
|
! pid_t old_last_command_subst_pid, old_last_async_pid;
|
|
sh_builtin_func_t *builtin;
|
|
SHELL_VAR *func;
|
|
--- 2686,2690 ----
|
|
char *command_line, *lastarg, *temp;
|
|
int first_word_quoted, result, builtin_is_special, already_forked, dofork;
|
|
! pid_t old_last_async_pid;
|
|
sh_builtin_func_t *builtin;
|
|
SHELL_VAR *func;
|
|
***************
|
|
*** 2700,2707 ****
|
|
print_simple_command (simple_command);
|
|
|
|
! if (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))
|
|
{
|
|
FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = savestring (the_printed_command);
|
|
}
|
|
|
|
--- 2702,2709 ----
|
|
print_simple_command (simple_command);
|
|
|
|
! if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
|
|
{
|
|
FREE (the_printed_command_except_trap);
|
|
! the_printed_command_except_trap = the_printed_command ? savestring (the_printed_command) : (char *)0;
|
|
}
|
|
|
|
***************
|
|
*** 2719,2723 ****
|
|
simple_command->words ? (simple_command->words->word->flags & W_QUOTED): 0;
|
|
|
|
! old_last_command_subst_pid = last_command_subst_pid;
|
|
old_last_async_pid = last_asynchronous_pid;
|
|
|
|
--- 2721,2725 ----
|
|
simple_command->words ? (simple_command->words->word->flags & W_QUOTED): 0;
|
|
|
|
! last_command_subst_pid = NO_PID;
|
|
old_last_async_pid = last_asynchronous_pid;
|
|
|
|
***************
|
|
*** 2740,2764 ****
|
|
if (dofork)
|
|
{
|
|
- #if 0
|
|
- /* XXX memory leak if expand_words() error causes a jump_to_top_level */
|
|
- command_line = savestring (the_printed_command);
|
|
- #endif
|
|
-
|
|
/* Do this now, because execute_disk_command will do it anyway in the
|
|
vast majority of cases. */
|
|
maybe_make_export_env ();
|
|
|
|
- #if 0
|
|
- if (make_child (command_line, async) == 0)
|
|
- #else
|
|
if (make_child (savestring (the_printed_command), async) == 0)
|
|
- #endif
|
|
{
|
|
already_forked = 1;
|
|
simple_command->flags |= CMD_NO_FORK;
|
|
|
|
! subshell_environment = (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
|
|
! ? (SUBSHELL_PIPE|SUBSHELL_FORK)
|
|
! : (SUBSHELL_ASYNC|SUBSHELL_FORK);
|
|
|
|
/* We need to do this before piping to handle some really
|
|
--- 2742,2759 ----
|
|
if (dofork)
|
|
{
|
|
/* Do this now, because execute_disk_command will do it anyway in the
|
|
vast majority of cases. */
|
|
maybe_make_export_env ();
|
|
|
|
if (make_child (savestring (the_printed_command), async) == 0)
|
|
{
|
|
already_forked = 1;
|
|
simple_command->flags |= CMD_NO_FORK;
|
|
|
|
! subshell_environment = SUBSHELL_FORK;
|
|
! if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
|
|
! subshell_environment |= SUBSHELL_PIPE;
|
|
! if (async)
|
|
! subshell_environment |= SUBSHELL_ASYNC;
|
|
|
|
/* We need to do this before piping to handle some really
|
|
***************
|
|
*** 2805,2810 ****
|
|
result = execute_null_command (simple_command->redirects,
|
|
pipe_in, pipe_out,
|
|
! already_forked ? 0 : async,
|
|
! old_last_command_subst_pid);
|
|
if (already_forked)
|
|
exit (result);
|
|
--- 2800,2804 ----
|
|
result = execute_null_command (simple_command->redirects,
|
|
pipe_in, pipe_out,
|
|
! already_forked ? 0 : async);
|
|
if (already_forked)
|
|
exit (result);
|
|
***************
|
|
*** 3060,3064 ****
|
|
push_scope (VC_BLTNENV, temporary_env);
|
|
if (subshell == 0)
|
|
! add_unwind_protect (pop_scope, "1");
|
|
temporary_env = (HASH_TABLE *)NULL;
|
|
}
|
|
--- 3054,3058 ----
|
|
push_scope (VC_BLTNENV, temporary_env);
|
|
if (subshell == 0)
|
|
! add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1");
|
|
temporary_env = (HASH_TABLE *)NULL;
|
|
}
|
|
***************
|
|
*** 3106,3110 ****
|
|
char *debug_trap, *error_trap, *return_trap;
|
|
#if defined (ARRAY_VARS)
|
|
! SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v;
|
|
ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
|
|
#endif
|
|
--- 3100,3104 ----
|
|
char *debug_trap, *error_trap, *return_trap;
|
|
#if defined (ARRAY_VARS)
|
|
! SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
|
|
ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
|
|
#endif
|
|
***************
|
|
*** 3179,3183 ****
|
|
--- 3173,3183 ----
|
|
}
|
|
|
|
+ /* Shell functions inherit the RETURN trap if function tracing is on
|
|
+ globally or on individually for this function. */
|
|
+ #if 0
|
|
if (return_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
|
|
+ #else
|
|
+ if (return_trap && (signal_in_progress (DEBUG_TRAP) || ((trace_p (var) == 0) && function_trace_mode == 0)))
|
|
+ #endif
|
|
{
|
|
if (subshell == 0)
|
|
***************
|
|
*** 3232,3236 ****
|
|
|
|
if (return_val)
|
|
! result = return_catch_value;
|
|
else
|
|
{
|
|
--- 3232,3242 ----
|
|
|
|
if (return_val)
|
|
! {
|
|
! result = return_catch_value;
|
|
! /* Run the RETURN trap in the function's context. */
|
|
! save_current = currently_executing_command;
|
|
! run_return_trap ();
|
|
! currently_executing_command = save_current;
|
|
! }
|
|
else
|
|
{
|
|
***************
|
|
*** 3256,3259 ****
|
|
--- 3262,3269 ----
|
|
#else
|
|
result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
|
|
+
|
|
+ save_current = currently_executing_command;
|
|
+ run_return_trap ();
|
|
+ currently_executing_command = save_current;
|
|
#endif
|
|
showing_function_line = 0;
|
|
***************
|
|
*** 3269,3275 ****
|
|
funcnest--;
|
|
#if defined (ARRAY_VARS)
|
|
array_pop (bash_source_a);
|
|
- array_pop (funcname_a);
|
|
array_pop (bash_lineno_a);
|
|
#endif
|
|
|
|
--- 3279,3292 ----
|
|
funcnest--;
|
|
#if defined (ARRAY_VARS)
|
|
+ /* These two variables cannot be unset, and cannot be affected by the
|
|
+ function. */
|
|
array_pop (bash_source_a);
|
|
array_pop (bash_lineno_a);
|
|
+
|
|
+ /* FUNCNAME can be unset, and so can potentially be changed by the
|
|
+ function. */
|
|
+ GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
|
|
+ if (nfv == funcname_v)
|
|
+ array_pop (funcname_a);
|
|
#endif
|
|
|