aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c87
1 files changed, 23 insertions, 64 deletions
diff --git a/shell/ash.c b/shell/ash.c
index e21df3291..b060d227a 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -302,7 +302,6 @@ struct globals_misc {
302#define EXINT 0 /* SIGINT received */ 302#define EXINT 0 /* SIGINT received */
303#define EXERROR 1 /* a generic error */ 303#define EXERROR 1 /* a generic error */
304#define EXEXIT 4 /* exit the shell */ 304#define EXEXIT 4 /* exit the shell */
305#define EXSIG 5 /* trapped signal in wait(1) */
306 305
307 smallint isloginsh; 306 smallint isloginsh;
308 char nullstr[1]; /* zero length string */ 307 char nullstr[1]; /* zero length string */
@@ -482,26 +481,20 @@ static void raise_interrupt(void) NORETURN;
482static void 481static void
483raise_interrupt(void) 482raise_interrupt(void)
484{ 483{
485 int ex_type;
486
487 pending_int = 0; 484 pending_int = 0;
488 /* Signal is not automatically unmasked after it is raised, 485 /* Signal is not automatically unmasked after it is raised,
489 * do it ourself - unmask all signals */ 486 * do it ourself - unmask all signals */
490 sigprocmask_allsigs(SIG_UNBLOCK); 487 sigprocmask_allsigs(SIG_UNBLOCK);
491 /* pending_sig = 0; - now done in signal_handler() */ 488 /* pending_sig = 0; - now done in signal_handler() */
492 489
493 ex_type = EXSIG; 490 if (!(rootshell && iflag)) {
494 if (gotsig[SIGINT - 1] && !trap[SIGINT]) { 491 /* Kill ourself with SIGINT */
495 if (!(rootshell && iflag)) { 492 signal(SIGINT, SIG_DFL);
496 /* Kill ourself with SIGINT */ 493 raise(SIGINT);
497 signal(SIGINT, SIG_DFL);
498 raise(SIGINT);
499 }
500 ex_type = EXINT;
501 } 494 }
502 /* bash: ^C even on empty command line sets $? */ 495 /* bash: ^C even on empty command line sets $? */
503 exitstatus = SIGINT + 128; 496 exitstatus = SIGINT + 128;
504 raise_exception(ex_type); 497 raise_exception(EXINT);
505 /* NOTREACHED */ 498 /* NOTREACHED */
506} 499}
507#if DEBUG 500#if DEBUG
@@ -4201,9 +4194,6 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4201 int retval; 4194 int retval;
4202 struct job *jp; 4195 struct job *jp;
4203 4196
4204 if (pending_sig)
4205 raise_exception(EXSIG);
4206
4207 nextopt(nullstr); 4197 nextopt(nullstr);
4208 retval = 0; 4198 retval = 0;
4209 4199
@@ -4220,7 +4210,6 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4220 jp->waited = 1; 4210 jp->waited = 1;
4221 jp = jp->prev_job; 4211 jp = jp->prev_job;
4222 } 4212 }
4223 dowait(DOWAIT_BLOCK, NULL);
4224 /* man bash: 4213 /* man bash:
4225 * "When bash is waiting for an asynchronous command via 4214 * "When bash is waiting for an asynchronous command via
4226 * the wait builtin, the reception of a signal for which a trap 4215 * the wait builtin, the reception of a signal for which a trap
@@ -4228,8 +4217,13 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4228 * with an exit status greater than 128, immediately after which 4217 * with an exit status greater than 128, immediately after which
4229 * the trap is executed." 4218 * the trap is executed."
4230 */ 4219 */
4220 dowait(DOWAIT_BLOCK, NULL); ///DOWAIT_WAITCMD
4221 /* if child sends us a signal *and immediately exits*,
4222 * dowait() returns pid > 0. Check this case,
4223 * not "if (dowait() < 0)"!
4224 */
4231 if (pending_sig) 4225 if (pending_sig)
4232 raise_exception(EXSIG); 4226 goto sigout;
4233 } 4227 }
4234 } 4228 }
4235 4229
@@ -4250,9 +4244,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4250 } 4244 }
4251 /* loop until process terminated or stopped */ 4245 /* loop until process terminated or stopped */
4252 while (job->state == JOBRUNNING) { 4246 while (job->state == JOBRUNNING) {
4253 pid_t pid = dowait(DOWAIT_BLOCK, NULL); 4247 dowait(DOWAIT_BLOCK, NULL); ///DOWAIT_WAITCMD
4254 if (pid <= 0 && pending_sig) 4248 if (pending_sig)
4255 raise_exception(EXSIG); 4249 goto sigout;
4256 } 4250 }
4257 job->waited = 1; 4251 job->waited = 1;
4258 retval = getstatus(job); 4252 retval = getstatus(job);
@@ -4261,6 +4255,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4261 4255
4262 ret: 4256 ret:
4263 return retval; 4257 return retval;
4258 sigout:
4259 retval = 128 + pending_sig;
4260 return retval;
4264} 4261}
4265 4262
4266static struct job * 4263static struct job *
@@ -8475,41 +8472,18 @@ static void prehash(union node *);
8475static int 8472static int
8476evaltree(union node *n, int flags) 8473evaltree(union node *n, int flags)
8477{ 8474{
8478 struct jmploc *volatile savehandler = exception_handler;
8479 struct jmploc jmploc;
8480 int checkexit = 0; 8475 int checkexit = 0;
8481 int (*evalfn)(union node *, int); 8476 int (*evalfn)(union node *, int);
8482 int status = 0; 8477 int status = 0;
8483 int int_level;
8484
8485 SAVE_INT(int_level);
8486 8478
8487 if (n == NULL) { 8479 if (n == NULL) {
8488 TRACE(("evaltree(NULL) called\n")); 8480 TRACE(("evaltree(NULL) called\n"));
8489 goto out1; 8481 goto out;
8490 } 8482 }
8491 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags)); 8483 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8492 8484
8493 dotrap(); 8485 dotrap();
8494 8486
8495 exception_handler = &jmploc;
8496 {
8497 int err = setjmp(jmploc.loc);
8498 if (err) {
8499 /* if it was a signal, check for trap handlers */
8500 if (exception_type == EXSIG) {
8501 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8502 exception_type, err));
8503 goto out;
8504 }
8505 /* continue on the way out */
8506 TRACE(("exception %d in evaltree, propagating err=%d\n",
8507 exception_type, err));
8508 exception_handler = savehandler;
8509 longjmp(exception_handler->loc, err);
8510 }
8511 }
8512
8513 switch (n->type) { 8487 switch (n->type) {
8514 default: 8488 default:
8515#if DEBUG 8489#if DEBUG
@@ -8600,11 +8574,7 @@ evaltree(union node *n, int flags)
8600 exitstatus = status; 8574 exitstatus = status;
8601 break; 8575 break;
8602 } 8576 }
8603
8604 out: 8577 out:
8605 exception_handler = savehandler;
8606
8607 out1:
8608 /* Order of checks below is important: 8578 /* Order of checks below is important:
8609 * signal handlers trigger before exit caused by "set -e". 8579 * signal handlers trigger before exit caused by "set -e".
8610 */ 8580 */
@@ -8615,9 +8585,7 @@ evaltree(union node *n, int flags)
8615 if (flags & EV_EXIT) 8585 if (flags & EV_EXIT)
8616 raise_exception(EXEXIT); 8586 raise_exception(EXEXIT);
8617 8587
8618 RESTORE_INT(int_level);
8619 TRACE(("leaving evaltree (no interrupts)\n")); 8588 TRACE(("leaving evaltree (no interrupts)\n"));
8620
8621 return exitstatus; 8589 return exitstatus;
8622} 8590}
8623 8591
@@ -9574,21 +9542,12 @@ evalcommand(union node *cmd, int flags)
9574 dowait(DOWAIT_NONBLOCK, NULL); 9542 dowait(DOWAIT_NONBLOCK, NULL);
9575 9543
9576 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { 9544 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9577 int exit_status; 9545 if (exception_type == EXERROR && spclbltin <= 0) {
9578 int i = exception_type; 9546 FORCE_INT_ON;
9579 if (i == EXEXIT) 9547 break;
9580 goto raise;
9581 exit_status = 2;
9582 if (i == EXINT)
9583 exit_status = 128 + SIGINT;
9584 if (i == EXSIG)
9585 exit_status = 128 + pending_sig;
9586 exitstatus = exit_status;
9587 if (i == EXINT || spclbltin > 0) {
9588 raise:
9589 longjmp(exception_handler->loc, 1);
9590 } 9548 }
9591 FORCE_INT_ON; 9549 raise:
9550 longjmp(exception_handler->loc, 1);
9592 } 9551 }
9593 goto readstatus; 9552 goto readstatus;
9594 9553