aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-03-27 15:51:42 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2019-03-27 15:52:17 +0100
commit966f087ab41e555fb40a158e7feae7603b31d450 (patch)
tree02b8a9452f62a7c0d614776345b0290d60870e4a
parentda996c5d2ace026506eb82d3b04ac48bb7aca3fb (diff)
downloadbusybox-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.c53
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
3523struct job { 3523struct 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
4239static int 4242static int
4240dowait(int block, struct job *job) 4243dowait(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