Subject: Re: bin/17870: /bin/sh bug on expanding $? in here-documents
To: None <netbsd-bugs@netbsd.org>
From: David Laight <david@l8s.co.uk>
List: netbsd-bugs
Date: 08/08/2002 10:06:13
Test case is:

    ! :
    cat <<EOF
    $?
    EOF

Which is expeced to output '1' (not '0').

I had a look at this.  I think:
- the status of every command is written to 'exitstatus'
- $? substitutes in 'oexitstatus'
- some commands don't necessarily write to 'exitstatus' so there
  is an assignment 'exitstatus = 0' to ensure 'success' is set.
- $? may be substitued for after 'exitstatus = 0' has been set.
- expandarg() is normally preceeded by 'oexitstatus = exitstatus'
  to ensure that the correct status is substituted.

Now 'evalcommand' sets 'oexitstatus = exitstatus' before its
loop through (what looks like) the arguments calling expandarg()
for each one.  However it also sets 'exitstatus = 0' for this
command.  This means that expredir() copies the 0 into oexitstatus
before calling expandarg().

Now deferring the 'extstatus = 0' in evalcommand until after the
call to expredir seems to work - until you try:

    ! :
    cat >`echo /dev/tty` <<EOF
    $?
    EOF

Also using:
    cat >`echo /dev/tty; ! :` <<EOF
    $?
    EOF
outputs the failure from the embedded command.
    cat `echo -; ! :` <<EOF
is fine...

I think the correct solution is to move the 'oexitstatus = exitstatus'
from inside the loop in expredir() to before each call to it.
(Except the one in evalcommand - where it is already set.)

Anyone care to comment?

	David

-- 
David Laight: david@l8s.co.uk