[gnu.bash.bug] function redirection problem

accwai@WATMATH.WATERLOO.EDU (Andy Wai) (07/15/89)

The following was discovered by one of the users around here:

   Script started on Fri Jul 14 13:23:21 1989
   % bash			<== invoke bash here
   watmath[1]$ function CAT	<== define function CAT
   bash>{
   bash>/bin/cat $@
   bash>}
   watmath[2]$ CAT hi
   Hi!				<== this one is fine
   watmath[3]$ CAT hi >log	<== did an "ls" and "exit" here, not echoed
   % cat log			<== back to csh, look at the log file
   Hi!
   watmath[4]$ ls		<== "ls" and "exit" shows up in the log file!
   hi
   log
   typescript
   watmath[5]$ exit
   % exit
   script done on Fri Jul 14 13:25:36 1989

Once the output of a function is redirected, it stays redirected after
the function is completed.  This happens on all architectures we have.
It was discovered in version 1.01 and still exist in 1.02.

Thanks.

Andy Wai
Math. Faculty Computing Facility
U. of Waterloo

chet@kiwi.CWRU.EDU (Chet Ramey) (07/20/89)

In article <8907141748.AA14752@watmath.waterloo.edu> accwai@WATMATH.WATERLOO.EDU (Andy Wai) writes:

>Once the output of a function is redirected, it stays redirected after
>the function is completed.  This happens on all architectures we have.
>It was discovered in version 1.01 and still exist in 1.02.

This is kind of a weird problem.  Here is a trail of what happens:

1.  execute_command gets called with the function as the command and 
    an output redirection spec.

2.  it calls do_redirections to do the redirections and create the 
    redirection_undo_list, then copies that to my_undo_list

3.  execute_simple_command gets called, and after deciding that the command
    is a function, calls execute_command again on the list of commands that
    make up the function body.

4.  execute_command calls do_redirections again and overwrites 
    redirection_undo_list and my_undo_list.  Bang.  When the function
    completes, there is nothing to undo, so nothing is undone.

The fix is to save and restore the undo list around the call to the function,
so that execute_command can zero out redirection_undo_list and not
have to worry about it.  This seems to work for multiple functions redirecting
output to multiple places as well:

kiwi$ type CAT
CAT is a function
CAT () {
/bin/cat $@			<--- just let inputs pass through
}
kiwi$ type CAT2
CAT2 is a function
CAT2 () {
CAT $@ ; CAT $@ >log2		<---- cat to screen and to log file
}
kiwi$ CAT hi
thththththththththt
kiwi$ CAT2 hi hi hi > log       <---- same stuff should end up in log and log2
kiwi$ cat log
thththththththththt
thththththththththt
thththththththththt
kiwi$ CAT log2
thththththththththt
thththththththththt
thththththththththt

These diffs seem to work, but they may depend on when the compiler allocates
storage for func_redirection_undo_list (gcc does it OK for me).

*** bash-1.02/execute_cmd.c	Wed Jul 19 17:26:45 1989
--- execute_cmd.c	Wed Jul 19 18:30:23 1989
***************
*** 621,624 ****
--- 622,626 ----
  	  {
  	    int result = EXECUTION_FAILURE;
+ 	    REDIRECT *func_redirection_undo_list = (REDIRECT *) NULL;
  	    if (do_redirections (simple_command->redirects, 1, 1) == 0)
  	      {
***************
*** 641,645 ****
--- 643,649 ----
  		      {
  			COMMAND *tc = (COMMAND *)copy_command (var->value);
+ 			extern int dispose_command(), pop_context();
  
+ 			func_redirection_undo_list = (REDIRECT *) copy_redirects (redirection_undo_list);
  			push_context ();
  
***************
*** 658,662 ****
  	      {
  	      }
! 	    do_redirections (reverse_list (redirection_undo_list), 1, 0);
  	    return (result);
  	  }
--- 666,670 ----
  	      {
  	      }
! 	    do_redirections (reverse_list (func_redirection_undo_list), 1, 0);
  	    return (result);
  	  }







Chet Ramey			"We are preparing to think about contemplating 
Network Services Group, CWRU	 preliminary work on plans to develop a
chet@cwjcc.INS.CWRU.Edu		 schedule for producing the 10th Edition of 
				 the Unix Programmers Manual." -- Andrew Hume