Bourne Shell bug? Have a look..

Chet Ramey chet at odin.INS.CWRU.Edu
Fri Feb 1 03:18:17 AEST 1991


In article <1067 at mwtech.UUCP> martin at mwtech.UUCP (Martin Weitzel) writes:

>You further know (or again you just learn it), that there can be more
>than one redirection per line:
>
>	echo hello >file foo >baz
>
>Now: Which redirection is the one that is finally in effect when the
>programm (the `echo' in the above example) runs, if you combine both
>of the above "strange" ways to do I/O-direction? (What I want is not
>the answer to a specific example, but the general rule!) I'll post the
>answer in a week or so if noone solves this).

That command will leave `baz' empty and "hello foo" in `file', but this is
wrong. 

I claim that the general rule that Martin is asking for is in fact a bug
in sh, and a long-standing one at that.  Consider that

	echo hello foo > file > baz

leaves `file' empty and "hello foo" in `baz'.  According to the sh
`grammar', and the claim that redirections may appear anywhere in a
command, this command and Martin's should produce identical results. 

I'll bet that the presence of the word `foo' between the redirections in
Martin's example somehow causes sh not to reverse the chain of redirections
that it builds, so that `file' is active when the command is run. 

Here is an example of what I consider correct behavior.  When bash
processes the command line that Martin gave, to use an example I'm familiar
with, it separates the redirections from the command words right away, in
the yacc grammar actions.  Bash incrementally builds a chain of
redirections by processing left to right.  (This is what Posix specifies,
though the language in the 1003.2 draft is `beginning to end'.)  Bash builds
the chain in a rather inefficient manner, appending each redirection to
the chain already built.  If bash simply appended the chain to the
redirection, the chain would need to be reversed to have redirections
processed in the proper order, and bash would have to do this before
processing any of them when it is time to exec the command.

This is the piece of the yacc grammar that accomplishes that (lots and lots
of essential support code and other rules omitted):

redirections:   redirection
                        {
                          $$ = $1;
                        }
        |       redirections redirection
                        {
                          register REDIRECT *t = $1;

                          while (t->next)
                            t = t->next;
                          t->next = $2;
                          $$ = $1;
                        }
        ;


Sh obviously wants to do something like this, as evidenced by the supposed
equivalent command I wrote above, but does not when presented with the
command Martin used.  I say it's a bug.  Bash, ash, ksh-86, and ksh-88
agree with me.  All AT&T versions of sh up to and including V.3.2 do not. 

Another thing: sh allows redirections anywhere in the command only for a 
simple command.  For example:

slc2$ sh
slc2$  > foo for i in 1 2 3
for: not found
slc2$ >foo echo hello
slc2$ cat foo
hello
slc2$

Chet

-- 
Chet Ramey				``There's just no surf in
Network Services Group			  Cleveland, U.S.A. ...''
Case Western Reserve University
chet at ins.CWRU.Edu		My opinions are just those, and mine alone.



More information about the Comp.unix.shell mailing list