Fix `set -e' handling from mksh (see bugs #71256, #546332, closes: #387755). Index: pdksh-5.2.14/exec.c =================================================================== --- pdksh-5.2.14.orig/exec.c 2009-09-19 11:54:58.000000000 +0200 +++ pdksh-5.2.14/exec.c 2009-09-19 11:55:01.000000000 +0200 @@ -15,7 +15,7 @@ #endif /* KSH */ static int comexec ARGS((struct op *t, struct tbl *volatile tp, char **ap, - int volatile flags)); + int volatile flags, volatile int * volatile xerrok)); static void scriptexec ARGS((struct op *tp, char **ap)); static int call_builtin ARGS((struct tbl *tp, char **wp)); static int iosetup ARGS((struct ioword *iop, struct tbl *tp)); @@ -70,12 +70,13 @@ * execute command tree */ int -execute(t, flags) +execute(t, flags, xerrok) struct op * volatile t; volatile int flags; /* if XEXEC don't fork */ + volatile int * volatile xerrok; { int i; - volatile int rv = 0; + volatile int rv = 0, dummy = 0; int pv[2]; char ** volatile ap; char *s, *cp; @@ -85,6 +86,10 @@ 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_t eval_done = FALSE; @@ -94,7 +99,7 @@ } */ 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) @@ -152,11 +157,11 @@ 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: @@ -173,7 +178,7 @@ * (: ; 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; @@ -182,17 +187,17 @@ 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; #ifdef KSH @@ -257,7 +262,7 @@ */ flags &= ~XEXEC; exchild(t->left, flags|XBGND|XFORK|XCOPROC|XCCLOSE, - coproc.readw); + NULL, coproc.readw); break; } #endif /* KSH */ @@ -267,20 +272,24 @@ * 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; #ifdef KSH @@ -328,7 +337,7 @@ 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); } } #ifdef KSH @@ -340,7 +349,7 @@ } is_first = FALSE; setstr(global(t->str), cp, KSH_UNWIND_ERROR); - rv = execute(t->left, flags & XERROK); + rv = execute(t->left, flags & XERROK, xerrok); } } } @@ -365,17 +374,17 @@ } } 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: @@ -387,11 +396,11 @@ 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: @@ -402,7 +411,7 @@ /* 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 */ @@ -430,7 +439,8 @@ quitenv(); /* restores IO */ if ((flags&XEXEC)) unwind(LEXIT); /* exit child */ - if (rv != 0 && !(flags & XERROK)) { + if (rv != 0 && !(flags & XERROK) + && (xerrok == NULL || !*xerrok)) { if (Flag(FERREXIT)) unwind(LERROR); trapsig(SIGERR_); @@ -443,11 +453,12 @@ */ static int -comexec(t, tp, ap, flags) +comexec(t, tp, ap, flags, xerrok) struct op *t; struct tbl *volatile tp; register char **ap; int volatile flags; + volatile int * volatile xerrok; { int i; volatile int rv = 0; @@ -660,7 +671,7 @@ i = ksh_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; @@ -737,7 +748,7 @@ 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: Index: pdksh-5.2.14/c_sh.c =================================================================== --- pdksh-5.2.14.orig/c_sh.c 2009-09-19 11:54:58.000000000 +0200 +++ pdksh-5.2.14/c_sh.c 2009-09-19 11:55:01.000000000 +0200 @@ -725,9 +725,10 @@ * time pipeline (really a statement, not a built-in command) */ int -timex(t, f) +timex(t, f, xerrok) struct op *t; int f; + volatile int * xerrok; { #define TF_NOARGS BIT(0) #define TF_NOREAL BIT(1) /* don't report real time */ @@ -753,7 +754,7 @@ if (t->left->type == TCOM) t->left->str = opts; opts[0] = 0; - rv = execute(t->left, f | XTIME); + rv = execute(t->left, f | XTIME, xerrok); tf |= opts[0]; t1t = ksh_times(&t1); } else Index: pdksh-5.2.14/eval.c =================================================================== --- pdksh-5.2.14.orig/eval.c 2009-09-19 11:54:58.000000000 +0200 +++ pdksh-5.2.14/eval.c 2009-09-19 11:55:01.000000000 +0200 @@ -877,7 +877,7 @@ close(pv[1]); } - execute(t, XFORK|XXCOM|XPIPEO); + execute(t, XFORK|XXCOM|XPIPEO, NULL); restfd(1, ofd1); startlast(); xp->split = 1; /* waitlast() */ Index: pdksh-5.2.14/jobs.c =================================================================== --- pdksh-5.2.14.orig/jobs.c 2009-09-19 11:54:58.000000000 +0200 +++ pdksh-5.2.14/jobs.c 2009-09-19 11:55:01.000000000 +0200 @@ -443,9 +443,10 @@ /* execute tree in child subprocess */ int -exchild(t, flags, close_fd) +exchild(t, flags, xerrok, close_fd) struct op *t; int flags; + volatile int *xerrok; int close_fd; /* used if XPCLOSE or XCCLOSE */ { static Proc *last_proc; /* for pipelines */ @@ -464,7 +465,7 @@ /* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND * (also done in another execute() below) */ - return execute(t, flags & (XEXEC | XERROK)); + return execute(t, flags & (XEXEC | XERROK), xerrok); #ifdef JOB_SIGS /* no SIGCHLD's while messing with job and process lists */ @@ -659,7 +660,7 @@ #endif /* OS2 */ tty_close(); cleartraps(); - execute(t, (flags & XERROK) | XEXEC); /* no return */ + execute(t, (flags & XERROK) | XEXEC, xerrok); /* no return */ internal_errorf(0, "exchild: execute() returned"); unwind(LLEAVE); /* NOTREACHED */ Index: pdksh-5.2.14/main.c =================================================================== --- pdksh-5.2.14.orig/main.c 2009-09-19 11:54:58.000000000 +0200 +++ pdksh-5.2.14/main.c 2009-09-19 11:55:01.000000000 +0200 @@ -634,7 +634,7 @@ } if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY))) - exstat = execute(t, 0); + exstat = execute(t, 0, NULL); if (t != NULL && t->type != TEOF && interactive && really_exit) really_exit = 0; Index: pdksh-5.2.14/proto.h =================================================================== --- pdksh-5.2.14.orig/proto.h 2009-09-19 11:54:58.000000000 +0200 +++ pdksh-5.2.14/proto.h 2009-09-19 11:55:01.000000000 +0200 @@ -42,7 +42,7 @@ int c_unset ARGS((char **wp)); int c_ulimit ARGS((char **wp)); int c_times ARGS((char **wp)); -int timex ARGS((struct op *t, int f)); +int timex ARGS((struct op *t, int f, volatile int *xerrok)); void timex_hook ARGS((struct op *t, char ** volatile *app)); int c_exec ARGS((char **wp)); int c_builtin ARGS((char **wp)); @@ -65,7 +65,7 @@ int glob_str ARGS((char *cp, XPtrV *wp, int markdirs)); /* exec.c */ int fd_clexec ARGS((int fd)); -int execute ARGS((struct op * volatile t, volatile int flags)); +int execute ARGS((struct op * volatile t, volatile int flags, volatile int * volatile xerrok)); int shcomexec ARGS((char **wp)); struct tbl * findfunc ARGS((const char *name, unsigned int h, int create)); int define ARGS((const char *name, struct op *t)); @@ -138,7 +138,7 @@ void j_init ARGS((int mflagset)); void j_exit ARGS((void)); void j_change ARGS((void)); -int exchild ARGS((struct op *t, int flags, int close_fd)); +int exchild ARGS((struct op *t, int flags, volatile int * xerrok, int close_fd)); void startlast ARGS((void)); int waitlast ARGS((void)); int waitfor ARGS((const char *cp, int *sigp)); Index: pdksh-5.2.14/tests/debian-111.t =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ pdksh-5.2.14/tests/debian-111.t 2009-09-19 12:02:51.000000000 +0200 @@ -0,0 +1,60 @@ +name: debian-111-1 +description: + Check set -e regression +stdin: + set -e; true; false && true; echo OK +expected-stdout: + OK +--- +name: debian-111-2 +description: + Regression for #387755 +stdin: + set -e + ! true + ! false + echo OK +expected-stdout: + OK +--- +name: debian-111-3 +description: + Regression for #387755 +stdin: + set -e; (false); echo here +expected-stdout: +expected-fail: yes +--- +name: debian-111-4 +description: + Regression for #387755 +stdin: + set +e; (false); echo here +expected-stdout: + here +--- +name: debian-111-5 +description: + Regression for #71256 +stdin: + set -e + if true; then + false && echo something + fi + echo OK +expected-stdout: + OK +--- +name: debian-111-6 +description: + Regression for #71256 +stdin: + set +e + if true; then + false && echo something + fi + echo OK +expected-stdout: + OK +--- +