aboutsummaryrefslogtreecommitdiff
path: root/shell
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
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')
-rw-r--r--shell/ash.c53
-rw-r--r--shell/hush.c35
2 files changed, 79 insertions, 9 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
diff --git a/shell/hush.c b/shell/hush.c
index 920a85299..fa9afa38e 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -923,7 +923,7 @@ struct globals {
923# define G_flag_return_in_progress 0 923# define G_flag_return_in_progress 0
924#endif 924#endif
925 smallint exiting; /* used to prevent EXIT trap recursion */ 925 smallint exiting; /* used to prevent EXIT trap recursion */
926 /* These support $?, $#, and $1 */ 926 /* These support $? */
927 smalluint last_exitcode; 927 smalluint last_exitcode;
928 smalluint expand_exitcode; 928 smalluint expand_exitcode;
929 smalluint last_bg_pid_exitcode; 929 smalluint last_bg_pid_exitcode;
@@ -934,6 +934,9 @@ struct globals {
934#else 934#else
935# define G_global_args_malloced 0 935# define G_global_args_malloced 0
936#endif 936#endif
937#if ENABLE_HUSH_BASH_COMPAT
938 int dead_job_exitcode; /* for "wait -n" */
939#endif
937 /* how many non-NULL argv's we have. NB: $# + 1 */ 940 /* how many non-NULL argv's we have. NB: $# + 1 */
938 int global_argc; 941 int global_argc;
939 char **global_argv; 942 char **global_argv;
@@ -8657,6 +8660,9 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
8657 pi->cmds[i].pid = 0; 8660 pi->cmds[i].pid = 0;
8658 pi->alive_cmds--; 8661 pi->alive_cmds--;
8659 if (!pi->alive_cmds) { 8662 if (!pi->alive_cmds) {
8663#if ENABLE_HUSH_BASH_COMPAT
8664 G.dead_job_exitcode = job_exited_or_stopped(pi);
8665#endif
8660 if (G_interactive_fd) { 8666 if (G_interactive_fd) {
8661 printf(JOB_STATUS_FORMAT, pi->jobid, 8667 printf(JOB_STATUS_FORMAT, pi->jobid,
8662 "Done", pi->cmdtext); 8668 "Done", pi->cmdtext);
@@ -8763,7 +8769,7 @@ static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid)
8763 /* fg_pipe exited or stopped */ 8769 /* fg_pipe exited or stopped */
8764 break; 8770 break;
8765 } 8771 }
8766 if (childpid == waitfor_pid) { 8772 if (childpid == waitfor_pid) { /* "wait PID" */
8767 debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status); 8773 debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status);
8768 rcode = WEXITSTATUS(status); 8774 rcode = WEXITSTATUS(status);
8769 if (WIFSIGNALED(status)) 8775 if (WIFSIGNALED(status))
@@ -8774,6 +8780,15 @@ static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid)
8774 rcode++; 8780 rcode++;
8775 break; /* "wait PID" called us, give it exitcode+1 */ 8781 break; /* "wait PID" called us, give it exitcode+1 */
8776 } 8782 }
8783#if ENABLE_HUSH_BASH_COMPAT
8784 if (-1 == waitfor_pid /* "wait -n" (wait for any one job) */
8785 && G.dead_job_exitcode >= 0 /* some job did finish */
8786 ) {
8787 debug_printf_exec("waitfor_pid:-1\n");
8788 rcode = G.dead_job_exitcode + 1;
8789 break;
8790 }
8791#endif
8777 /* This wasn't one of our processes, or */ 8792 /* This wasn't one of our processes, or */
8778 /* fg_pipe still has running processes, do waitpid again */ 8793 /* fg_pipe still has running processes, do waitpid again */
8779 } /* while (waitpid succeeds)... */ 8794 } /* while (waitpid succeeds)... */
@@ -11471,6 +11486,12 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid
11471 ret--; 11486 ret--;
11472 if (ret < 0) /* if ECHILD, may need to fix "ret" */ 11487 if (ret < 0) /* if ECHILD, may need to fix "ret" */
11473 ret = 0; 11488 ret = 0;
11489#if ENABLE_HUSH_BASH_COMPAT
11490 if (waitfor_pid == -1 && errno == ECHILD) {
11491 /* exitcode of "wait -n" with no children is 127, not 0 */
11492 ret = 127;
11493 }
11494#endif
11474 sigprocmask(SIG_SETMASK, &oldset, NULL); 11495 sigprocmask(SIG_SETMASK, &oldset, NULL);
11475 break; 11496 break;
11476 } 11497 }
@@ -11499,6 +11520,14 @@ static int FAST_FUNC builtin_wait(char **argv)
11499 int status; 11520 int status;
11500 11521
11501 argv = skip_dash_dash(argv); 11522 argv = skip_dash_dash(argv);
11523#if ENABLE_HUSH_BASH_COMPAT
11524 if (argv[0] && strcmp(argv[0], "-n") == 0) {
11525 /* wait -n */
11526 /* (bash accepts "wait -n PID" too and ignores PID) */
11527 G.dead_job_exitcode = -1;
11528 return wait_for_child_or_signal(NULL, -1 /*no job, wait for one job*/);
11529 }
11530#endif
11502 if (argv[0] == NULL) { 11531 if (argv[0] == NULL) {
11503 /* Don't care about wait results */ 11532 /* Don't care about wait results */
11504 /* Note 1: must wait until there are no more children */ 11533 /* Note 1: must wait until there are no more children */
@@ -11516,7 +11545,7 @@ static int FAST_FUNC builtin_wait(char **argv)
11516 * ^C <-- after ~4 sec from keyboard 11545 * ^C <-- after ~4 sec from keyboard
11517 * $ 11546 * $
11518 */ 11547 */
11519 return wait_for_child_or_signal(NULL, 0 /*(no job and no pid to wait for)*/); 11548 return wait_for_child_or_signal(NULL, 0 /*no job and no pid to wait for*/);
11520 } 11549 }
11521 11550
11522 do { 11551 do {