diff options
author | Ron Yorston <rmy@pobox.com> | 2019-03-31 08:55:48 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2019-03-31 09:51:00 +0100 |
commit | 61e0e3160a8be3ed8488b09200a5dca1bd1b21b4 (patch) | |
tree | d55341d875d1dd0d77445960723a47418efd14e5 /shell/ash.c | |
parent | be2949717934c19890879cf2a8fc74c5da55d1c7 (diff) | |
parent | 35082fc2c17369223669e099f422acc0982ee4ff (diff) | |
download | busybox-w32-61e0e3160a8be3ed8488b09200a5dca1bd1b21b4.tar.gz busybox-w32-61e0e3160a8be3ed8488b09200a5dca1bd1b21b4.tar.bz2 busybox-w32-61e0e3160a8be3ed8488b09200a5dca1bd1b21b4.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell/ash.c')
-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 5f64bebe3..8a3c3ae35 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3866,7 +3866,7 @@ struct procstat { | |||
3866 | 3866 | ||
3867 | struct job { | 3867 | struct job { |
3868 | struct procstat ps0; /* status of process */ | 3868 | struct procstat ps0; /* status of process */ |
3869 | struct procstat *ps; /* status or processes when more than one */ | 3869 | struct procstat *ps; /* status of processes when more than one */ |
3870 | #if JOBS | 3870 | #if JOBS |
3871 | int stopstatus; /* status of a stopped job */ | 3871 | int stopstatus; /* status of a stopped job */ |
3872 | #endif | 3872 | #endif |
@@ -4703,6 +4703,9 @@ wait_block_or_sig(int *status) | |||
4703 | #define DOWAIT_NONBLOCK 0 | 4703 | #define DOWAIT_NONBLOCK 0 |
4704 | #define DOWAIT_BLOCK 1 | 4704 | #define DOWAIT_BLOCK 1 |
4705 | #define DOWAIT_BLOCK_OR_SIG 2 | 4705 | #define DOWAIT_BLOCK_OR_SIG 2 |
4706 | #if ENABLE_ASH_BASH_COMPAT | ||
4707 | # define DOWAIT_JOBSTATUS 0x10 /* OR this to get job's exitstatus instead of pid */ | ||
4708 | #endif | ||
4706 | 4709 | ||
4707 | static int | 4710 | static int |
4708 | dowait(int block, struct job *job) | 4711 | dowait(int block, struct job *job) |
@@ -4710,7 +4713,11 @@ dowait(int block, struct job *job) | |||
4710 | int pid; | 4713 | int pid; |
4711 | int status; | 4714 | int status; |
4712 | struct job *jp; | 4715 | struct job *jp; |
4713 | struct job *thisjob = NULL; | 4716 | struct job *thisjob; |
4717 | #if ENABLE_ASH_BASH_COMPAT | ||
4718 | bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS); | ||
4719 | block = (block & ~DOWAIT_JOBSTATUS); | ||
4720 | #endif | ||
4714 | 4721 | ||
4715 | TRACE(("dowait(0x%x) called\n", block)); | 4722 | TRACE(("dowait(0x%x) called\n", block)); |
4716 | 4723 | ||
@@ -4747,10 +4754,10 @@ dowait(int block, struct job *job) | |||
4747 | } | 4754 | } |
4748 | TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", | 4755 | TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", |
4749 | pid, status, errno, strerror(errno))); | 4756 | pid, status, errno, strerror(errno))); |
4757 | thisjob = NULL; | ||
4750 | if (pid <= 0) | 4758 | if (pid <= 0) |
4751 | goto out; | 4759 | goto out; |
4752 | 4760 | ||
4753 | thisjob = NULL; | ||
4754 | for (jp = curjob; jp; jp = jp->prev_job) { | 4761 | for (jp = curjob; jp; jp = jp->prev_job) { |
4755 | int jobstate; | 4762 | int jobstate; |
4756 | struct procstat *ps; | 4763 | struct procstat *ps; |
@@ -4814,6 +4821,13 @@ dowait(int block, struct job *job) | |||
4814 | out: | 4821 | out: |
4815 | INT_ON; | 4822 | INT_ON; |
4816 | 4823 | ||
4824 | #if ENABLE_ASH_BASH_COMPAT | ||
4825 | if (want_jobexitstatus) { | ||
4826 | pid = -1; | ||
4827 | if (thisjob && thisjob->state == JOBDONE) | ||
4828 | pid = thisjob->ps[thisjob->nprocs - 1].ps_status; | ||
4829 | } | ||
4830 | #endif | ||
4817 | if (thisjob && thisjob == job) { | 4831 | if (thisjob && thisjob == job) { |
4818 | char s[48 + 1]; | 4832 | char s[48 + 1]; |
4819 | int len; | 4833 | int len; |
@@ -4996,15 +5010,24 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
4996 | struct job *job; | 5010 | struct job *job; |
4997 | int retval; | 5011 | int retval; |
4998 | struct job *jp; | 5012 | struct job *jp; |
4999 | 5013 | #if ENABLE_ASH_BASH_COMPAT | |
5014 | int status; | ||
5015 | char one = nextopt("n"); | ||
5016 | #else | ||
5000 | nextopt(nullstr); | 5017 | nextopt(nullstr); |
5018 | #endif | ||
5001 | retval = 0; | 5019 | retval = 0; |
5002 | 5020 | ||
5003 | argv = argptr; | 5021 | argv = argptr; |
5004 | if (!*argv) { | 5022 | if (!argv[0]) { |
5005 | /* wait for all jobs */ | 5023 | /* wait for all jobs / one job if -n */ |
5006 | for (;;) { | 5024 | for (;;) { |
5007 | jp = curjob; | 5025 | jp = curjob; |
5026 | #if ENABLE_ASH_BASH_COMPAT | ||
5027 | if (one && !jp) | ||
5028 | /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */ | ||
5029 | retval = 127; | ||
5030 | #endif | ||
5008 | while (1) { | 5031 | while (1) { |
5009 | if (!jp) /* no running procs */ | 5032 | if (!jp) /* no running procs */ |
5010 | goto ret; | 5033 | goto ret; |
@@ -5020,13 +5043,31 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
5020 | * with an exit status greater than 128, immediately after which | 5043 | * with an exit status greater than 128, immediately after which |
5021 | * the trap is executed." | 5044 | * the trap is executed." |
5022 | */ | 5045 | */ |
5046 | #if ENABLE_ASH_BASH_COMPAT | ||
5047 | status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL); | ||
5048 | #else | ||
5023 | dowait(DOWAIT_BLOCK_OR_SIG, NULL); | 5049 | dowait(DOWAIT_BLOCK_OR_SIG, NULL); |
5050 | #endif | ||
5024 | /* if child sends us a signal *and immediately exits*, | 5051 | /* if child sends us a signal *and immediately exits*, |
5025 | * dowait() returns pid > 0. Check this case, | 5052 | * dowait() returns pid > 0. Check this case, |
5026 | * not "if (dowait() < 0)"! | 5053 | * not "if (dowait() < 0)"! |
5027 | */ | 5054 | */ |
5028 | if (pending_sig) | 5055 | if (pending_sig) |
5029 | goto sigout; | 5056 | goto sigout; |
5057 | #if ENABLE_ASH_BASH_COMPAT | ||
5058 | if (one) { | ||
5059 | /* wait -n waits for one _job_, not one _process_. | ||
5060 | * date; sleep 3 & sleep 2 | sleep 1 & wait -n; date | ||
5061 | * should wait for 2 seconds. Not 1 or 3. | ||
5062 | */ | ||
5063 | if (status != -1 && !WIFSTOPPED(status)) { | ||
5064 | retval = WEXITSTATUS(status); | ||
5065 | if (WIFSIGNALED(status)) | ||
5066 | retval = WTERMSIG(status) + 128; | ||
5067 | goto ret; | ||
5068 | } | ||
5069 | } | ||
5070 | #endif | ||
5030 | } | 5071 | } |
5031 | } | 5072 | } |
5032 | 5073 | ||