diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-03-27 15:51:42 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-03-27 15:52:17 +0100 |
commit | 966f087ab41e555fb40a158e7feae7603b31d450 (patch) | |
tree | 02b8a9452f62a7c0d614776345b0290d60870e4a | |
parent | da996c5d2ace026506eb82d3b04ac48bb7aca3fb (diff) | |
download | busybox-w32-966f087ab41e555fb40a158e7feae7603b31d450.tar.gz busybox-w32-966f087ab41e555fb40a158e7feae7603b31d450.tar.bz2 busybox-w32-966f087ab41e555fb40a158e7feae7603b31d450.zip |
ash: add "wait -n" bashism
function old new delta
waitcmd 205 288 +83
dowait 405 444 +39
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 122/0) Total: 122 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c index a4394d756..b1499b037 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3522,7 +3522,7 @@ struct procstat { | |||
3522 | 3522 | ||
3523 | struct job { | 3523 | struct job { |
3524 | struct procstat ps0; /* status of process */ | 3524 | struct procstat ps0; /* status of process */ |
3525 | struct procstat *ps; /* status or processes when more than one */ | 3525 | struct procstat *ps; /* status of processes when more than one */ |
3526 | #if JOBS | 3526 | #if JOBS |
3527 | int stopstatus; /* status of a stopped job */ | 3527 | int stopstatus; /* status of a stopped job */ |
3528 | #endif | 3528 | #endif |
@@ -4235,6 +4235,9 @@ wait_block_or_sig(int *status) | |||
4235 | #define DOWAIT_NONBLOCK 0 | 4235 | #define DOWAIT_NONBLOCK 0 |
4236 | #define DOWAIT_BLOCK 1 | 4236 | #define DOWAIT_BLOCK 1 |
4237 | #define DOWAIT_BLOCK_OR_SIG 2 | 4237 | #define DOWAIT_BLOCK_OR_SIG 2 |
4238 | #if ENABLE_ASH_BASH_COMPAT | ||
4239 | # define DOWAIT_JOBSTATUS 0x10 /* OR this to get job's exitstatus instead of pid */ | ||
4240 | #endif | ||
4238 | 4241 | ||
4239 | static int | 4242 | static int |
4240 | dowait(int block, struct job *job) | 4243 | dowait(int block, struct job *job) |
@@ -4242,7 +4245,11 @@ dowait(int block, struct job *job) | |||
4242 | int pid; | 4245 | int pid; |
4243 | int status; | 4246 | int status; |
4244 | struct job *jp; | 4247 | struct job *jp; |
4245 | struct job *thisjob = NULL; | 4248 | struct job *thisjob; |
4249 | #if ENABLE_ASH_BASH_COMPAT | ||
4250 | bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS); | ||
4251 | block = (block & ~DOWAIT_JOBSTATUS); | ||
4252 | #endif | ||
4246 | 4253 | ||
4247 | TRACE(("dowait(0x%x) called\n", block)); | 4254 | TRACE(("dowait(0x%x) called\n", block)); |
4248 | 4255 | ||
@@ -4279,10 +4286,10 @@ dowait(int block, struct job *job) | |||
4279 | } | 4286 | } |
4280 | TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", | 4287 | TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", |
4281 | pid, status, errno, strerror(errno))); | 4288 | pid, status, errno, strerror(errno))); |
4289 | thisjob = NULL; | ||
4282 | if (pid <= 0) | 4290 | if (pid <= 0) |
4283 | goto out; | 4291 | goto out; |
4284 | 4292 | ||
4285 | thisjob = NULL; | ||
4286 | for (jp = curjob; jp; jp = jp->prev_job) { | 4293 | for (jp = curjob; jp; jp = jp->prev_job) { |
4287 | int jobstate; | 4294 | int jobstate; |
4288 | struct procstat *ps; | 4295 | struct procstat *ps; |
@@ -4341,6 +4348,13 @@ dowait(int block, struct job *job) | |||
4341 | out: | 4348 | out: |
4342 | INT_ON; | 4349 | INT_ON; |
4343 | 4350 | ||
4351 | #if ENABLE_ASH_BASH_COMPAT | ||
4352 | if (want_jobexitstatus) { | ||
4353 | pid = -1; | ||
4354 | if (thisjob && thisjob->state == JOBDONE) | ||
4355 | pid = thisjob->ps[thisjob->nprocs - 1].ps_status; | ||
4356 | } | ||
4357 | #endif | ||
4344 | if (thisjob && thisjob == job) { | 4358 | if (thisjob && thisjob == job) { |
4345 | char s[48 + 1]; | 4359 | char s[48 + 1]; |
4346 | int len; | 4360 | int len; |
@@ -4523,15 +4537,24 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
4523 | struct job *job; | 4537 | struct job *job; |
4524 | int retval; | 4538 | int retval; |
4525 | struct job *jp; | 4539 | struct job *jp; |
4526 | 4540 | #if ENABLE_ASH_BASH_COMPAT | |
4541 | int status; | ||
4542 | char one = nextopt("n"); | ||
4543 | #else | ||
4527 | nextopt(nullstr); | 4544 | nextopt(nullstr); |
4545 | #endif | ||
4528 | retval = 0; | 4546 | retval = 0; |
4529 | 4547 | ||
4530 | argv = argptr; | 4548 | argv = argptr; |
4531 | if (!*argv) { | 4549 | if (!argv[0]) { |
4532 | /* wait for all jobs */ | 4550 | /* wait for all jobs / one job if -n */ |
4533 | for (;;) { | 4551 | for (;;) { |
4534 | jp = curjob; | 4552 | jp = curjob; |
4553 | #if ENABLE_ASH_BASH_COMPAT | ||
4554 | if (one && !jp) | ||
4555 | /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */ | ||
4556 | retval = 127; | ||
4557 | #endif | ||
4535 | while (1) { | 4558 | while (1) { |
4536 | if (!jp) /* no running procs */ | 4559 | if (!jp) /* no running procs */ |
4537 | goto ret; | 4560 | goto ret; |
@@ -4547,13 +4570,31 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
4547 | * with an exit status greater than 128, immediately after which | 4570 | * with an exit status greater than 128, immediately after which |
4548 | * the trap is executed." | 4571 | * the trap is executed." |
4549 | */ | 4572 | */ |
4573 | #if ENABLE_ASH_BASH_COMPAT | ||
4574 | status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL); | ||
4575 | #else | ||
4550 | dowait(DOWAIT_BLOCK_OR_SIG, NULL); | 4576 | dowait(DOWAIT_BLOCK_OR_SIG, NULL); |
4577 | #endif | ||
4551 | /* if child sends us a signal *and immediately exits*, | 4578 | /* if child sends us a signal *and immediately exits*, |
4552 | * dowait() returns pid > 0. Check this case, | 4579 | * dowait() returns pid > 0. Check this case, |
4553 | * not "if (dowait() < 0)"! | 4580 | * not "if (dowait() < 0)"! |
4554 | */ | 4581 | */ |
4555 | if (pending_sig) | 4582 | if (pending_sig) |
4556 | goto sigout; | 4583 | goto sigout; |
4584 | #if ENABLE_ASH_BASH_COMPAT | ||
4585 | if (one) { | ||
4586 | /* wait -n waits for one _job_, not one _process_. | ||
4587 | * date; sleep 3 & sleep 2 | sleep 1 & wait -n; date | ||
4588 | * should wait for 2 seconds. Not 1 or 3. | ||
4589 | */ | ||
4590 | if (status != -1 && !WIFSTOPPED(status)) { | ||
4591 | retval = WEXITSTATUS(status); | ||
4592 | if (WIFSIGNALED(status)) | ||
4593 | retval = WTERMSIG(status) + 128; | ||
4594 | goto ret; | ||
4595 | } | ||
4596 | } | ||
4597 | #endif | ||
4557 | } | 4598 | } |
4558 | } | 4599 | } |
4559 | 4600 | ||