diff options
-rw-r--r-- | shell/ash.c | 87 |
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; | |||
482 | static void | 481 | static void |
483 | raise_interrupt(void) | 482 | raise_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 | ||
4266 | static struct job * | 4263 | static struct job * |
@@ -8475,41 +8472,18 @@ static void prehash(union node *); | |||
8475 | static int | 8472 | static int |
8476 | evaltree(union node *n, int flags) | 8473 | evaltree(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 | ||