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