summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--src/eval.c31
-rw-r--r--src/eval.h2
-rw-r--r--src/histedit.c6
-rw-r--r--src/main.c2
-rw-r--r--src/trap.c27
-rw-r--r--src/trap.h2
7 files changed, 49 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index a6ba252..a01503a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,9 @@
 	* Generalise setinputfile for use in read_profile/readcmdfile.
 	* Handle SKIPEVAL in read_profile by exiting.
 	* Let evaltree handle traps from cmdloop.
+	* Reset evalskip after minusc is executed.
+	* Stop executing traps once SKIPEVAL is seen.
+	* Only handle each signal once in dotrap.
 
 2005-03-25  Gerrit Pape <pape@smarden.org>
 
diff --git a/src/eval.c b/src/eval.c
index 31272da..ac4425c 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -163,7 +163,8 @@ evalcmd(int argc, char **argv)
                         STPUTC('\0', concat);
                         p = grabstackstr(concat);
                 }
-                evalstring(p);
+                evalstring(p, ~SKIPEVAL);
+                
         }
         return exitstatus;
 }
@@ -173,23 +174,29 @@ evalcmd(int argc, char **argv)
  * Execute a command or commands contained in a string.
  */
 
-void
-evalstring(char *s)
+int
+evalstring(char *s, int mask)
 {
 	union node *n;
 	struct stackmark smark;
+	int skip;
 
-	setstackmark(&smark);
 	setinputstring(s);
+	setstackmark(&smark);
 
+	skip = 0;
 	while ((n = parsecmd(0)) != NEOF) {
 		evaltree(n, 0);
 		popstackmark(&smark);
-		if (evalskip)
+		skip = evalskip;
+		if (skip)
 			break;
 	}
 	popfile();
-	popstackmark(&smark);
+
+	skip &= mask;
+	evalskip = skip;
+	return skip;
 }
 
 
@@ -319,12 +326,15 @@ setstatus:
 		break;
 	}
 out:
-	if (pendingsigs)
-		dotrap();
-	if (flags & EV_EXIT)
-		exraise(EXEXIT);
 	if ((checkexit & exitstatus))
 		evalskip |= SKIPEVAL;
+	else if (pendingsigs && dotrap())
+		goto exexit;
+
+	if (flags & EV_EXIT) {
+exexit:
+		exraise(EXEXIT);
+	}
 }
 
 
@@ -930,7 +940,6 @@ cmddone:
 	commandname = savecmdname;
 	exsig = 0;
 	handler = savehandler;
-	evalskip &= ~SKIPEVAL;
 
 	return i;
 }
diff --git a/src/eval.h b/src/eval.h
index 3d0a9a6..bd2cee0 100644
--- a/src/eval.h
+++ b/src/eval.h
@@ -51,7 +51,7 @@ struct backcmd {		/* result of evalbackcmd */
 	struct job *jp;		/* job structure for command */
 };
 
-void evalstring(char *);
+int evalstring(char *, int);
 union node;	/* BLETCH for ansi C */
 void evaltree(union node *, int);
 void evalbackcmd(union node *, struct backcmd *);
diff --git a/src/histedit.c b/src/histedit.c
index 0d435cd..9c5656b 100644
--- a/src/histedit.c
+++ b/src/histedit.c
@@ -383,7 +383,8 @@ histcmd(int argc, char **argv)
 					out2str(s);
 				}
 
-				evalstring(strcpy(stalloc(strlen(s) + 1), s));
+				evalstring(strcpy(stalloc(strlen(s) + 1), s),
+					   ~0);
 				if (displayhist && hist) {
 					/*
 					 *  XXX what about recursive and
@@ -407,7 +408,8 @@ histcmd(int argc, char **argv)
 		fclose(efp);
 		editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
 		sprintf(editcmd, "%s %s", editor, editfile);
-		evalstring(editcmd, 0);	/* XXX - should use no JC command */
+		/* XXX - should use no JC command */
+		evalstring(editcmd, ~0);
 		INTON;
 		readcmdfile(editfile);	/* XXX - should read back - quick tst */
 		unlink(editfile);
diff --git a/src/main.c b/src/main.c
index fd13ab2..317447c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -189,7 +189,7 @@ state2:
 state3:
 	state = 4;
 	if (minusc)
-		evalstring(minusc);
+		evalstring(minusc, 0);
 
 	if (sflag || minusc == NULL) {
 state4:	/* XXX ??? - why isn't this before the "if" statement */
diff --git a/src/trap.c b/src/trap.c
index 15ff49a..6264b5c 100644
--- a/src/trap.c
+++ b/src/trap.c
@@ -301,23 +301,34 @@ onsig(int signo)
  * handlers while we are executing a trap handler.
  */
 
-void
+int
 dotrap(void)
 {
 	char *p;
 	char *q;
+	int i;
 	int savestatus;
+	int skip = 0;
 
 	savestatus = exitstatus;
-	q = gotsig;
-	while (pendingsigs = 0, barrier(), (p = memchr(q, 1, NSIG - 1))) {
-		*p = 0;
-		p = trap[p - q + 1];
+	pendingsigs = 0;
+	barrier();
+
+	for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
+		if (!*q)
+			continue;
+		*q = 0;
+
+		p = trap[i + 1];
 		if (!p)
 			continue;
-		evalstring(p);
+		skip = evalstring(p, SKIPEVAL);
 		exitstatus = savestatus;
+		if (skip)
+			break;
 	}
+
+	return skip;
 }
 
 
@@ -364,9 +375,9 @@ exitshell(void)
 		goto out;
 	}
 	handler = &loc;
-	if ((p = trap[0]) != NULL && *p != '\0') {
+	if ((p = trap[0])) {
 		trap[0] = NULL;
-		evalstring(p);
+		evalstring(p, 0);
 	}
 	flushall();
 out:
diff --git a/src/trap.h b/src/trap.h
index fd164a8..380651b 100644
--- a/src/trap.h
+++ b/src/trap.h
@@ -49,7 +49,7 @@ void clear_traps(void);
 void setsignal(int);
 void ignoresig(int);
 void onsig(int);
-void dotrap(void);
+int dotrap(void);
 void setinteractive(int);
 void exitshell(void) __attribute__((__noreturn__));
 int decode_signal(const char *, int);