*** ../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