summaryrefslogtreecommitdiffstats
path: root/system/pdksh/patches/111_mksh-set-e.patch
blob: ca6f42b18f25e8bb275162107f16bdc969e42945 (plain)
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
+---
+