aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-03-31 08:55:48 +0100
committerRon Yorston <rmy@pobox.com>2019-03-31 09:51:00 +0100
commit61e0e3160a8be3ed8488b09200a5dca1bd1b21b4 (patch)
treed55341d875d1dd0d77445960723a47418efd14e5 /shell/ash.c
parentbe2949717934c19890879cf2a8fc74c5da55d1c7 (diff)
parent35082fc2c17369223669e099f422acc0982ee4ff (diff)
downloadbusybox-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.c53
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
3867struct job { 3867struct 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
4707static int 4710static int
4708dowait(int block, struct job *job) 4711dowait(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