summaryrefslogtreecommitdiff
path: root/bin/ksh/exec.c
diff options
context:
space:
mode:
authorJared Yanovich <jaredy@cvs.openbsd.org>2009-01-29 23:27:27 +0000
committerJared Yanovich <jaredy@cvs.openbsd.org>2009-01-29 23:27:27 +0000
commit13f12bb1515bba7e136f815e45e8748acee9e3db (patch)
tree9b4c95d9db59bd0eb01abd04d0ccbc676e5db9a2 /bin/ksh/exec.c
parent90be8e08639f88e86f264a0ef15ee046ee6b9877 (diff)
pass "xerrok" status across the execution call stack to more closely
match what both POSIX and ksh.1 already describe in regards to set -e/errexit's behavior in determining when to exit from nonzero return values. specifically, the truth values tested as operands to `&&' and `||', as well as the resulting compound expression itself, along with the truth value resulting from a negated command (i.e. a pipeline prefixed `!'), should not make the shell exit when -e is in effect. issue reported by matthieu. testing matthieu, naddy. ok miod (earlier version), otto. man page ok jmc.
Diffstat (limited to 'bin/ksh/exec.c')
-rw-r--r--bin/ksh/exec.c76
1 files changed, 43 insertions, 33 deletions
diff --git a/bin/ksh/exec.c b/bin/ksh/exec.c
index 1eb65c02989..1c144fa9c19 100644
--- a/bin/ksh/exec.c
+++ b/bin/ksh/exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec.c,v 1.48 2007/09/05 19:02:01 otto Exp $ */
+/* $OpenBSD: exec.c,v 1.49 2009/01/29 23:27:26 jaredy Exp $ */
/*
* execute command tree
@@ -13,7 +13,7 @@
# define PS4_SUBSTITUTE(s) substitute((s), 0)
static int comexec(struct op *, struct tbl *volatile, char **,
- int volatile);
+ int volatile, volatile int *);
static void scriptexec(struct op *, char **);
static int call_builtin(struct tbl *, char **);
static int iosetup(struct ioword *, struct tbl *);
@@ -31,9 +31,9 @@ static void dbteste_error(Test_env *, int, const char *);
*/
int
execute(struct op *volatile t,
- volatile int flags) /* if XEXEC don't fork */
+ volatile int flags, volatile int *xerrok) /* if XEXEC don't fork */
{
- int i;
+ int i, dummy = 0;
volatile int rv = 0;
int pv[2];
char ** volatile ap;
@@ -44,6 +44,10 @@ execute(struct op *volatile t,
if (t == NULL)
return 0;
+ /* Caller doesn't care if XERROK should propagate. */
+ if (xerrok == NULL)
+ xerrok = &dummy;
+
/* Is this the end of a pipeline? If so, we want to evaluate the
* command arguments
bool eval_done = false;
@@ -53,7 +57,7 @@ execute(struct op *volatile t,
}
*/
if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE)
- return exchild(t, flags & ~XTIME, -1); /* run in sub-process */
+ return exchild(t, flags & ~XTIME, xerrok, -1); /* run in sub-process */
newenv(E_EXEC);
if (trap)
@@ -111,11 +115,11 @@ execute(struct op *volatile t,
switch (t->type) {
case TCOM:
- rv = comexec(t, tp, ap, flags);
+ rv = comexec(t, tp, ap, flags, xerrok);
break;
case TPAREN:
- rv = execute(t->left, flags|XFORK);
+ rv = execute(t->left, flags|XFORK, xerrok);
break;
case TPIPE:
@@ -131,7 +135,7 @@ execute(struct op *volatile t,
* (: ; cat /etc/termcap) | sleep 1
* will hang forever).
*/
- exchild(t->left, flags|XPIPEO|XCCLOSE, pv[0]);
+ exchild(t->left, flags|XPIPEO|XCCLOSE, NULL, pv[0]);
(void) ksh_dup2(pv[0], 0, false); /* stdin of next */
closepipe(pv);
flags |= XPIPEI;
@@ -140,17 +144,17 @@ execute(struct op *volatile t,
restfd(1, e->savefd[1]); /* stdout of last */
e->savefd[1] = 0; /* no need to re-restore this */
/* Let exchild() close 0 in parent, after fork, before wait */
- i = exchild(t, flags|XPCLOSE, 0);
+ i = exchild(t, flags|XPCLOSE, xerrok, 0);
if (!(flags&XBGND) && !(flags&XXCOM))
rv = i;
break;
case TLIST:
while (t->type == TLIST) {
- execute(t->left, flags & XERROK);
+ execute(t->left, flags & XERROK, NULL);
t = t->right;
}
- rv = execute(t, flags & XERROK);
+ rv = execute(t, flags & XERROK, xerrok);
break;
case TCOPROC:
@@ -208,7 +212,7 @@ execute(struct op *volatile t,
*/
flags &= ~XEXEC;
exchild(t->left, flags|XBGND|XFORK|XCOPROC|XCCLOSE,
- coproc.readw);
+ NULL, coproc.readw);
break;
}
@@ -217,20 +221,24 @@ execute(struct op *volatile t,
* forks again for async... parent should optimize
* this to "foo &"...
*/
- rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK);
+ rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok);
break;
case TOR:
case TAND:
- rv = execute(t->left, XERROK);
- if (t->right != NULL && (rv == 0) == (t->type == TAND))
- rv = execute(t->right, flags & XERROK);
- else
- flags |= XERROK;
+ rv = execute(t->left, XERROK, xerrok);
+ if ((rv == 0) == (t->type == TAND))
+ rv = execute(t->right, XERROK, xerrok);
+ flags |= XERROK;
+ if (xerrok)
+ *xerrok = 1;
break;
case TBANG:
- rv = !execute(t->right, XERROK);
+ rv = !execute(t->right, XERROK, xerrok);
+ flags |= XERROK;
+ if (xerrok)
+ *xerrok = 1;
break;
case TDBRACKET:
@@ -272,7 +280,7 @@ execute(struct op *volatile t,
if (t->type == TFOR) {
while (*ap != NULL) {
setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
- rv = execute(t->left, flags & XERROK);
+ rv = execute(t->left, flags & XERROK, xerrok);
}
} else { /* TSELECT */
for (;;) {
@@ -282,7 +290,7 @@ execute(struct op *volatile t,
}
is_first = false;
setstr(global(t->str), cp, KSH_UNWIND_ERROR);
- rv = execute(t->left, flags & XERROK);
+ rv = execute(t->left, flags & XERROK, xerrok);
}
}
}
@@ -305,17 +313,17 @@ execute(struct op *volatile t,
}
}
rv = 0; /* in case of a continue */
- while ((execute(t->left, XERROK) == 0) == (t->type == TWHILE))
- rv = execute(t->right, flags & XERROK);
+ while ((execute(t->left, XERROK, NULL) == 0) == (t->type == TWHILE))
+ rv = execute(t->right, flags & XERROK, xerrok);
break;
case TIF:
case TELIF:
if (t->right == NULL)
break; /* should be error */
- rv = execute(t->left, XERROK) == 0 ?
- execute(t->right->left, flags & XERROK) :
- execute(t->right->right, flags & XERROK);
+ rv = execute(t->left, XERROK, NULL) == 0 ?
+ execute(t->right->left, flags & XERROK, xerrok) :
+ execute(t->right->right, flags & XERROK, xerrok);
break;
case TCASE:
@@ -327,11 +335,11 @@ execute(struct op *volatile t,
goto Found;
break;
Found:
- rv = execute(t->left, flags & XERROK);
+ rv = execute(t->left, flags & XERROK, xerrok);
break;
case TBRACE:
- rv = execute(t->left, flags & XERROK);
+ rv = execute(t->left, flags & XERROK, xerrok);
break;
case TFUNCT:
@@ -342,7 +350,7 @@ execute(struct op *volatile t,
/* Clear XEXEC so nested execute() call doesn't exit
* (allows "ls -l | time grep foo").
*/
- rv = timex(t, flags & ~XEXEC);
+ rv = timex(t, flags & ~XEXEC, xerrok);
break;
case TEXEC: /* an eval'd TCOM */
@@ -362,7 +370,8 @@ execute(struct op *volatile t,
quitenv(NULL); /* restores IO */
if ((flags&XEXEC))
unwind(LEXIT); /* exit child */
- if (rv != 0 && !(flags & XERROK)) {
+ if (rv != 0 && !(flags & XERROK) &&
+ (xerrok == NULL || !*xerrok)) {
trapsig(SIGERR_);
if (Flag(FERREXIT))
unwind(LERROR);
@@ -375,7 +384,8 @@ execute(struct op *volatile t,
*/
static int
-comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags)
+comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags,
+ volatile int *xerrok)
{
int i;
volatile int rv = 0;
@@ -586,7 +596,7 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags)
i = sigsetjmp(e->jbuf, 0);
if (i == 0) {
/* seems odd to pass XERROK here, but at&t ksh does */
- exstat = execute(tp->val.t, flags & XERROK);
+ exstat = execute(tp->val.t, flags & XERROK, xerrok);
i = LRETURN;
}
kshname = old_kshname;
@@ -661,7 +671,7 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags)
texec.left = t; /* for tprint */
texec.str = tp->val.s;
texec.args = ap;
- rv = exchild(&texec, flags, -1);
+ rv = exchild(&texec, flags, xerrok, -1);
break;
}
Leave: