Bug 12806

Summary: `sh -e' doesn't parse multi-command lines correctly
Product: Base System Reporter: Andrew Arensburger <arensb>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 3.2-RELEASE   
Hardware: Any   
OS: Any   

Description Andrew Arensburger 1999-07-25 16:00:00 UTC
        sh(1) says,

:    -e errexit
:            If not interactive, exit immediately if any untested command
:            fails.  The exit status of a command is considered to be explic-
:            itly tested if the command is used to control an if, elif, while,
:            or until; or if the command is the left hand operand of an ``&&''
:            or ``||'' operator.

This works fine if the script is of the form 
        cmd1
        cmd2 && cmd3
but not if it is of the form
        cmd1; cmd2 && cmd3

        One practical upshot is that if you have a Makefile built with
GNU automake, "make clean" does not work.

Fix: 

Don't know. If I come up with one, I'll let you know.
How-To-Repeat: 
        The following two scripts should behave identically:

#!/bin/sh -e
echo before
test foo = bar && echo blah
echo after

#!/bin/sh -e
echo before; test foo = bar && echo blah
echo after

        The first one prints

        before
        after

as expected. The second one, however, prints

        before

and exits.
Comment 1 Danny J. Zerkel 1999-08-06 04:20:12 UTC
I confirmed that ksh works as expected and the sh on Solaris works as
expected,
so I poked around and I have included a patch below.  What it looks like
is that
for a semicolon node, evaltree() calls evaltree() for both sides of the
node and
then retests the eflag, even though it has already been tested on each
side of
the node.  There is no reason, that I can see, for the semicolon node to
check
the eflag, so I just made it do the other tests and return.

--- /usr/src/bin/sh/eval.c.orig Thu Aug  5 23:08:44 1999
+++ /usr/src/bin/sh/eval.c      Thu Aug  5 23:13:31 1999
@@ -200,10 +200,14 @@
        switch (n->type) {
        case NSEMI:
                evaltree(n->nbinary.ch1, 0);
-               if (evalskip)
-                       goto out;
-               evaltree(n->nbinary.ch2, flags);
-               break;
+               if (!evalskip) {
+                       evaltree(n->nbinary.ch2, flags);
+               }
+               if (pendingsigs)
+                       dotrap();
+               if (flags & EV_EXIT)
+                       exitshell(exitstatus);
+               return;
        case NAND:
                evaltree(n->nbinary.ch1, EV_TESTED);
                if (evalskip || exitstatus != 0) {

-- Danny J. Zerkel
dzerkel@columbus.rr.com
Comment 2 arensb 1999-08-06 15:43:33 UTC
On Thu, 05 Aug 1999 23:20:12 EDT, "Danny J. Zerkel" wrote:
> What it looks like
> is that
> for a semicolon node, evaltree() calls evaltree() for both sides of the
> node and
> then retests the eflag, even though it has already been tested on each
> side of
> the node.  There is no reason, that I can see, for the semicolon node to
> check
> the eflag, so I just made it do the other tests and return.

	This patch works for me. While it's not as elegant as I would
have liked (but I tend to be anal), I haven't been able to come up
with a better solution.
	Theoretically, this patch might change the behavior of /bin/sh
if you ever wound up with a tree of the form

	        NAND
	       /    \
	   NSEMI    stmt
	    / \
	stmt   stmt

but this can't happen, can it?

-- 
Andrew Arensburger, Systems guy		Center for Automation Research
arensb@cfar.umd.edu			University of Maryland
     Now we dolly back, now we fade to black... and roll credits!
Comment 3 Danny J. Zerkel 2001-07-16 04:20:45 UTC
Some other fix has been applied, which also fixes this problem.

This PR can be closed

------------------
dzerkel@columbus.rr.com
Comment 4 Steve Price freebsd_committer freebsd_triage 2001-07-16 10:19:35 UTC
State Changed
From-To: open->closed

As "Danny J. Zerkel" <dzerkel@columbus.rr.com> points out this has been 
fixed.  Thanks.