[gnu.bash.bug] YA Bash functions incompatibility with sh?

brian@radio.astro.utoronto.ca (Brian Glendenning) (06/28/89)

I believe I may have found another incompatibility between sh and
bash (maybe I should get brave and call it a bug :-).

sh:
$ del() { /bin/rm -i $* ; }
$ touch junk
$ del junk
rm: remove junk? ^C
$ echo $*

$

bash:
$ del() { /bin/rm -i $* ; }
$ touch junk
$ del junk
rm: remove junk? ^C
$ echo $*
junk
$ 


This would not be so bad, except that it appears that if $* is set it
is not reset properly upon entry to other shell functions (at least),
e.g.:

bash:
$ del() { /bin/rm -i $* ; }
$ lf() { /bin/ls -F $* ; }
$ touch junk
$ del junk
rm: remove junk? ^C
$ mv junk trash
$ lf
junk not found
$ 

--
	  Brian Glendenning - Radio astronomy, University of Toronto
brian@radio.astro.utoronto.ca uunet!utai!radio!brian  glendenn@utorphys.bitnet
-- 
	  Brian Glendenning - Radio astronomy, University of Toronto
brian@radio.astro.utoronto.ca uunet!utai!radio!brian  glendenn@utorphys.bitnet

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

In article <BRIAN.89Jun27235835@radio.astro.utoronto.ca> brian@radio.astro.utoronto.ca (Brian Glendenning) writes:
>
>I believe I may have found another incompatibility between sh and
>bash (maybe I should get brave and call it a bug :-).

Be brave; it is a bug.

>bash:
>$ del() { /bin/rm -i $* ; }
>$ lf() { /bin/ls -F $* ; }
>$ touch junk
>$ del junk
>rm: remove junk? ^C
>$ mv junk trash
>$ lf
>junk not found
>$ 

What is happening is that a context is getting pushed, but not popped (a
bash context consists of the `dollar variables' and any local variables, as
well as a particular value of variable_context, cf.  push_context() and
pop_context() in builtins.c).  Ordinarily, during command execution, this
is not a problem; the appropriate context is restored when the child forked
to execute the command exits.  However, bash executes functions and
builtins with no redirections directly in the main shell, and fails to add
unwind protects to restore the proper state if interrupted.

Once you digest that :-), a fix is easy (though it might not be the Officially
Blessed fix).

With the following diffs applied, here is what happens to Brian's example:

cwns6$ del() { /bin/rm -i $* ; }
cwns6$ lf() { /bin/ls -F $* ; }
cwns6$ touch foo
cwns6$ del foo
/bin/rm: remove foo? ^C
cwns6$ mv foo bar
cwns6$ lf
bar
cwns6$ 

Here are the diffs to execute_cmd.c:

*** bash-1.01/execute_cmd.c	Fri Jun 23 12:55:22 1989
--- src-1.01/execute_cmd.c	Fri Jun 30 14:08:37 1989
***************
*** 633,641 ****
--- 633,646 ----
  		    else
  		      {
+ 			extern int pop_context(), dispose_command();
  			COMMAND *tc = (COMMAND *)copy_command (var->value);
  
  			push_context ();
+ 			add_unwind_protect(dispose_command, (char *)tc);
+ 			add_unwind_protect(pop_context, (char *) NULL);
  			remember_args (words->next, 0);
  			result = execute_command (tc);
  			pop_context ();
  			dispose_command (tc);
+ 			remove_unwind_protect();
+ 			remove_unwind_protect();

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