aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-10-28 12:42:38 +0100
committerRon Yorston <rmy@pobox.com>2016-10-28 12:42:38 +0100
commitd3b0f5df93a7955ff1b9a56d2d5ebd7bc2ef5708 (patch)
tree6b5e1eee412b8980d714f16c2aa70e399be07ff7
parent687f98b0ba79aeb85b73c4ab06b661fb17bf4e23 (diff)
parent458c1f218bb6a6bd0325f0b0cedea5ab0980dbc3 (diff)
downloadbusybox-w32-d3b0f5df93a7955ff1b9a56d2d5ebd7bc2ef5708.tar.gz
busybox-w32-d3b0f5df93a7955ff1b9a56d2d5ebd7bc2ef5708.tar.bz2
busybox-w32-d3b0f5df93a7955ff1b9a56d2d5ebd7bc2ef5708.zip
Merge branch 'busybox' into merge
-rw-r--r--shell/ash.c467
-rw-r--r--shell/hush.c1
2 files changed, 242 insertions, 226 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 9c73760f0..abbc0cd78 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -361,6 +361,7 @@ struct globals_misc {
361 361
362 volatile int suppress_int; /* counter */ 362 volatile int suppress_int; /* counter */
363 volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */ 363 volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
364 volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
364 /* last pending signal */ 365 /* last pending signal */
365 volatile /*sig_atomic_t*/ smallint pending_sig; 366 volatile /*sig_atomic_t*/ smallint pending_sig;
366 smallint exception_type; /* kind of exception (0..5) */ 367 smallint exception_type; /* kind of exception (0..5) */
@@ -368,7 +369,6 @@ struct globals_misc {
368#define EXINT 0 /* SIGINT received */ 369#define EXINT 0 /* SIGINT received */
369#define EXERROR 1 /* a generic error */ 370#define EXERROR 1 /* a generic error */
370#define EXEXIT 4 /* exit the shell */ 371#define EXEXIT 4 /* exit the shell */
371#define EXSIG 5 /* trapped signal in wait(1) */
372 372
373 smallint isloginsh; 373 smallint isloginsh;
374 char nullstr[1]; /* zero length string */ 374 char nullstr[1]; /* zero length string */
@@ -441,6 +441,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
441#define exception_type (G_misc.exception_type ) 441#define exception_type (G_misc.exception_type )
442#define suppress_int (G_misc.suppress_int ) 442#define suppress_int (G_misc.suppress_int )
443#define pending_int (G_misc.pending_int ) 443#define pending_int (G_misc.pending_int )
444#define got_sigchld (G_misc.got_sigchld )
444#define pending_sig (G_misc.pending_sig ) 445#define pending_sig (G_misc.pending_sig )
445#define isloginsh (G_misc.isloginsh ) 446#define isloginsh (G_misc.isloginsh )
446#define nullstr (G_misc.nullstr ) 447#define nullstr (G_misc.nullstr )
@@ -552,26 +553,20 @@ static void raise_interrupt(void) NORETURN;
552static void 553static void
553raise_interrupt(void) 554raise_interrupt(void)
554{ 555{
555 int ex_type;
556
557 pending_int = 0; 556 pending_int = 0;
558 /* Signal is not automatically unmasked after it is raised, 557 /* Signal is not automatically unmasked after it is raised,
559 * do it ourself - unmask all signals */ 558 * do it ourself - unmask all signals */
560 sigprocmask_allsigs(SIG_UNBLOCK); 559 sigprocmask_allsigs(SIG_UNBLOCK);
561 /* pending_sig = 0; - now done in signal_handler() */ 560 /* pending_sig = 0; - now done in signal_handler() */
562 561
563 ex_type = EXSIG; 562 if (!(rootshell && iflag)) {
564 if (gotsig[SIGINT - 1] && !trap[SIGINT]) { 563 /* Kill ourself with SIGINT */
565 if (!(rootshell && iflag)) { 564 signal(SIGINT, SIG_DFL);
566 /* Kill ourself with SIGINT */ 565 raise(SIGINT);
567 signal(SIGINT, SIG_DFL);
568 raise(SIGINT);
569 }
570 ex_type = EXINT;
571 } 566 }
572 /* bash: ^C even on empty command line sets $? */ 567 /* bash: ^C even on empty command line sets $? */
573 exitstatus = SIGINT + 128; 568 exitstatus = SIGINT + 128;
574 raise_exception(ex_type); 569 raise_exception(EXINT);
575 /* NOTREACHED */ 570 /* NOTREACHED */
576} 571}
577#if DEBUG 572#if DEBUG
@@ -3592,7 +3587,14 @@ ignoresig(int signo)
3592static void 3587static void
3593signal_handler(int signo) 3588signal_handler(int signo)
3594{ 3589{
3590 if (signo == SIGCHLD) {
3591 got_sigchld = 1;
3592 if (!trap[SIGCHLD])
3593 return;
3594 }
3595
3595 gotsig[signo - 1] = 1; 3596 gotsig[signo - 1] = 1;
3597 pending_sig = signo;
3596 3598
3597 if (signo == SIGINT && !trap[SIGINT]) { 3599 if (signo == SIGINT && !trap[SIGINT]) {
3598 if (!suppress_int) { 3600 if (!suppress_int) {
@@ -3600,8 +3602,6 @@ signal_handler(int signo)
3600 raise_interrupt(); /* does not return */ 3602 raise_interrupt(); /* does not return */
3601 } 3603 }
3602 pending_int = 1; 3604 pending_int = 1;
3603 } else {
3604 pending_sig = signo;
3605 } 3605 }
3606} 3606}
3607 3607
@@ -3661,6 +3661,9 @@ setsignal(int signo)
3661//whereas we have to restore it to what shell got on entry 3661//whereas we have to restore it to what shell got on entry
3662//from the parent. See comment above 3662//from the parent. See comment above
3663 3663
3664 if (signo == SIGCHLD)
3665 new_act = S_CATCH;
3666
3664 t = &sigmode[signo - 1]; 3667 t = &sigmode[signo - 1];
3665 cur_act = *t; 3668 cur_act = *t;
3666 if (cur_act == 0) { 3669 if (cur_act == 0) {
@@ -3711,8 +3714,9 @@ setsignal(int signo)
3711#define CUR_STOPPED 0 3714#define CUR_STOPPED 0
3712 3715
3713/* mode flags for dowait */ 3716/* mode flags for dowait */
3714#define DOWAIT_NONBLOCK WNOHANG 3717#define DOWAIT_NONBLOCK 0
3715#define DOWAIT_BLOCK 0 3718#define DOWAIT_BLOCK 1
3719#define DOWAIT_BLOCK_OR_SIG 2
3716 3720
3717#if JOBS 3721#if JOBS
3718/* pgrp of shell on invocation */ 3722/* pgrp of shell on invocation */
@@ -4223,27 +4227,76 @@ waitpid_child(int *status, int wait_flags)
4223#endif 4227#endif
4224 4228
4225static int 4229static int
4226dowait(int wait_flags, struct job *job) 4230wait_block_or_sig(int *status, int wait_flags)
4227{ 4231{
4232 sigset_t mask;
4233 int pid;
4234
4235 do {
4236 /* Poll all children for changes in their state */
4237 got_sigchld = 0;
4238 pid = waitpid(-1, status, wait_flags | WNOHANG);
4239 if (pid != 0)
4240 break; /* Error (e.g. EINTR) or pid */
4241
4242 /* No child is ready. Sleep until interesting signal is received */
4243 sigfillset(&mask);
4244 sigprocmask(SIG_SETMASK, &mask, &mask);
4245 while (!got_sigchld && !pending_sig)
4246 sigsuspend(&mask);
4247 sigprocmask(SIG_SETMASK, &mask, NULL);
4248
4249 /* If it was SIGCHLD, poll children again */
4250 } while (got_sigchld);
4251
4252 return pid;
4253}
4254
4255
4256static int
4257dowait(int block, struct job *job)
4258{
4259 int wait_flags;
4228 int pid; 4260 int pid;
4229 int status; 4261 int status;
4230 struct job *jp; 4262 struct job *jp;
4231 struct job *thisjob; 4263 struct job *thisjob = NULL;
4232 4264
4233 TRACE(("dowait(0x%x) called\n", wait_flags)); 4265 TRACE(("dowait(0x%x) called\n", block));
4234 4266
4235 /* Do a wait system call. If job control is compiled in, we accept 4267 wait_flags = 0;
4236 * stopped processes. wait_flags may have WNOHANG, preventing blocking. 4268 if (block == DOWAIT_NONBLOCK)
4237 * NB: _not_ safe_waitpid, we need to detect EINTR */ 4269 wait_flags = WNOHANG;
4270 /* If job control is compiled in, we accept stopped processes too. */
4238 if (doing_jobctl) 4271 if (doing_jobctl)
4239 wait_flags |= WUNTRACED; 4272 wait_flags |= WUNTRACED;
4240 pid = waitpid(-1, &status, wait_flags); 4273
4274 /* It's wrong to call waitpid() outside of INT_OFF region:
4275 * signal can arrive just after syscall return and handler can
4276 * longjmp away, losing stop/exit notification processing.
4277 * Thus, for "jobs" builtin, and for waiting for a fg job,
4278 * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4279 *
4280 * However, for "wait" builtin it is wrong to simply call waitpid()
4281 * in INT_OFF region: "wait" needs to wait for any running job
4282 * to change state, but should exit on any trap too.
4283 * In INT_OFF region, a signal just before syscall entry can set
4284 * pending_sig valiables, but we can't check them, and we would
4285 * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4286 * Because of this, we run inside INT_OFF, but use a special routine
4287 * which combines waitpid() and sigsuspend().
4288 */
4289 INT_OFF;
4290 if (block == DOWAIT_BLOCK_OR_SIG)
4291 pid = wait_block_or_sig(&status, wait_flags);
4292 else
4293 /* NB: _not_ safe_waitpid, we need to detect EINTR. */
4294 pid = waitpid(-1, &status, wait_flags);
4241 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", 4295 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4242 pid, status, errno, strerror(errno))); 4296 pid, status, errno, strerror(errno)));
4243 if (pid <= 0) 4297 if (pid <= 0)
4244 return pid; 4298 goto out;
4245 4299
4246 INT_OFF;
4247 thisjob = NULL; 4300 thisjob = NULL;
4248 for (jp = curjob; jp; jp = jp->prev_job) { 4301 for (jp = curjob; jp; jp = jp->prev_job) {
4249 int jobstate; 4302 int jobstate;
@@ -4320,15 +4373,6 @@ dowait(int wait_flags, struct job *job)
4320 return pid; 4373 return pid;
4321} 4374}
4322 4375
4323static int
4324blocking_wait_with_raise_on_sig(void)
4325{
4326 pid_t pid = dowait(DOWAIT_BLOCK, NULL);
4327 if (pid <= 0 && pending_sig)
4328 raise_exception(EXSIG);
4329 return pid;
4330}
4331
4332#if JOBS 4376#if JOBS
4333static void 4377static void
4334showjob(struct job *jp, int mode) 4378showjob(struct job *jp, int mode)
@@ -4498,9 +4542,6 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4498 int retval; 4542 int retval;
4499 struct job *jp; 4543 struct job *jp;
4500 4544
4501 if (pending_sig)
4502 raise_exception(EXSIG);
4503
4504 nextopt(nullstr); 4545 nextopt(nullstr);
4505 retval = 0; 4546 retval = 0;
4506 4547
@@ -4517,21 +4558,20 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4517 jp->waited = 1; 4558 jp->waited = 1;
4518 jp = jp->prev_job; 4559 jp = jp->prev_job;
4519 } 4560 }
4520 blocking_wait_with_raise_on_sig();
4521 /* man bash: 4561 /* man bash:
4522 * "When bash is waiting for an asynchronous command via 4562 * "When bash is waiting for an asynchronous command via
4523 * the wait builtin, the reception of a signal for which a trap 4563 * the wait builtin, the reception of a signal for which a trap
4524 * has been set will cause the wait builtin to return immediately 4564 * has been set will cause the wait builtin to return immediately
4525 * with an exit status greater than 128, immediately after which 4565 * with an exit status greater than 128, immediately after which
4526 * the trap is executed." 4566 * the trap is executed."
4527 * 4567 */
4528 * blocking_wait_with_raise_on_sig raises signal handlers 4568 dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4529 * if it gets no pid (pid < 0). However, 4569 /* if child sends us a signal *and immediately exits*,
4530 * if child sends us a signal *and immediately exits*, 4570 * dowait() returns pid > 0. Check this case,
4531 * blocking_wait_with_raise_on_sig gets pid > 0 4571 * not "if (dowait() < 0)"!
4532 * and does not handle pending_sig. Check this case: */ 4572 */
4533 if (pending_sig) 4573 if (pending_sig)
4534 raise_exception(EXSIG); 4574 goto sigout;
4535 } 4575 }
4536 } 4576 }
4537 4577
@@ -4551,8 +4591,11 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4551 job = getjob(*argv, 0); 4591 job = getjob(*argv, 0);
4552 } 4592 }
4553 /* loop until process terminated or stopped */ 4593 /* loop until process terminated or stopped */
4554 while (job->state == JOBRUNNING) 4594 while (job->state == JOBRUNNING) {
4555 blocking_wait_with_raise_on_sig(); 4595 dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4596 if (pending_sig)
4597 goto sigout;
4598 }
4556 job->waited = 1; 4599 job->waited = 1;
4557 retval = getstatus(job); 4600 retval = getstatus(job);
4558 repeat: ; 4601 repeat: ;
@@ -4560,6 +4603,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4560 4603
4561 ret: 4604 ret:
4562 return retval; 4605 return retval;
4606 sigout:
4607 retval = 128 + pending_sig;
4608 return retval;
4563} 4609}
4564 4610
4565static struct job * 4611static struct job *
@@ -4954,19 +5000,19 @@ clear_traps(void)
4954{ 5000{
4955 char **tp; 5001 char **tp;
4956 5002
5003 INT_OFF;
4957 for (tp = trap; tp < &trap[NSIG]; tp++) { 5004 for (tp = trap; tp < &trap[NSIG]; tp++) {
4958 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */ 5005 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4959 INT_OFF;
4960 if (trap_ptr == trap) 5006 if (trap_ptr == trap)
4961 free(*tp); 5007 free(*tp);
4962 /* else: it "belongs" to trap_ptr vector, don't free */ 5008 /* else: it "belongs" to trap_ptr vector, don't free */
4963 *tp = NULL; 5009 *tp = NULL;
4964 if ((tp - trap) != 0) 5010 if ((tp - trap) != 0)
4965 setsignal(tp - trap); 5011 setsignal(tp - trap);
4966 INT_ON;
4967 } 5012 }
4968 } 5013 }
4969 may_have_traps = 0; 5014 may_have_traps = 0;
5015 INT_ON;
4970} 5016}
4971 5017
4972/* Lives far away from here, needed for forkchild */ 5018/* Lives far away from here, needed for forkchild */
@@ -5914,6 +5960,119 @@ cvtnum(arith_t num)
5914 return len; 5960 return len;
5915} 5961}
5916 5962
5963/*
5964 * Break the argument string into pieces based upon IFS and add the
5965 * strings to the argument list. The regions of the string to be
5966 * searched for IFS characters have been stored by recordregion.
5967 */
5968static void
5969ifsbreakup(char *string, struct arglist *arglist)
5970{
5971 struct ifsregion *ifsp;
5972 struct strlist *sp;
5973 char *start;
5974 char *p;
5975 char *q;
5976 const char *ifs, *realifs;
5977 int ifsspc;
5978 int nulonly;
5979
5980 start = string;
5981 if (ifslastp != NULL) {
5982 ifsspc = 0;
5983 nulonly = 0;
5984 realifs = ifsset() ? ifsval() : defifs;
5985 ifsp = &ifsfirst;
5986 do {
5987 p = string + ifsp->begoff;
5988 nulonly = ifsp->nulonly;
5989 ifs = nulonly ? nullstr : realifs;
5990 ifsspc = 0;
5991 while (p < string + ifsp->endoff) {
5992 q = p;
5993 if ((unsigned char)*p == CTLESC)
5994 p++;
5995 if (!strchr(ifs, *p)) {
5996 p++;
5997 continue;
5998 }
5999 if (!nulonly)
6000 ifsspc = (strchr(defifs, *p) != NULL);
6001 /* Ignore IFS whitespace at start */
6002 if (q == start && ifsspc) {
6003 p++;
6004 start = p;
6005 continue;
6006 }
6007 *q = '\0';
6008 sp = stzalloc(sizeof(*sp));
6009 sp->text = start;
6010 *arglist->lastp = sp;
6011 arglist->lastp = &sp->next;
6012 p++;
6013 if (!nulonly) {
6014 for (;;) {
6015 if (p >= string + ifsp->endoff) {
6016 break;
6017 }
6018 q = p;
6019 if ((unsigned char)*p == CTLESC)
6020 p++;
6021 if (strchr(ifs, *p) == NULL) {
6022 p = q;
6023 break;
6024 }
6025 if (strchr(defifs, *p) == NULL) {
6026 if (ifsspc) {
6027 p++;
6028 ifsspc = 0;
6029 } else {
6030 p = q;
6031 break;
6032 }
6033 } else
6034 p++;
6035 }
6036 }
6037 start = p;
6038 } /* while */
6039 ifsp = ifsp->next;
6040 } while (ifsp != NULL);
6041 if (nulonly)
6042 goto add;
6043 }
6044
6045 if (!*start)
6046 return;
6047
6048 add:
6049 sp = stzalloc(sizeof(*sp));
6050 sp->text = start;
6051 *arglist->lastp = sp;
6052 arglist->lastp = &sp->next;
6053}
6054
6055static void
6056ifsfree(void)
6057{
6058 struct ifsregion *p = ifsfirst.next;
6059
6060 if (!p)
6061 goto out;
6062
6063 INT_OFF;
6064 do {
6065 struct ifsregion *ifsp;
6066 ifsp = p->next;
6067 free(p);
6068 p = ifsp;
6069 } while (p);
6070 ifsfirst.next = NULL;
6071 INT_ON;
6072 out:
6073 ifslastp = NULL;
6074}
6075
5917static size_t 6076static size_t
5918esclen(const char *start, const char *p) 6077esclen(const char *start, const char *p)
5919{ 6078{
@@ -6235,6 +6394,7 @@ evalbackcmd(union node *n, struct backcmd *result)
6235 * For now, preserve bash-like behavior, it seems to be somewhat more useful: 6394 * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6236 */ 6395 */
6237 eflag = 0; 6396 eflag = 0;
6397 ifsfree();
6238 evaltree(n, EV_EXIT); /* actually evaltreenr... */ 6398 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6239 /* NOTREACHED */ 6399 /* NOTREACHED */
6240 } 6400 }
@@ -7207,116 +7367,6 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
7207} 7367}
7208 7368
7209/* 7369/*
7210 * Break the argument string into pieces based upon IFS and add the
7211 * strings to the argument list. The regions of the string to be
7212 * searched for IFS characters have been stored by recordregion.
7213 */
7214static void
7215ifsbreakup(char *string, struct arglist *arglist)
7216{
7217 struct ifsregion *ifsp;
7218 struct strlist *sp;
7219 char *start;
7220 char *p;
7221 char *q;
7222 const char *ifs, *realifs;
7223 int ifsspc;
7224 int nulonly;
7225
7226 start = string;
7227 if (ifslastp != NULL) {
7228 ifsspc = 0;
7229 nulonly = 0;
7230 realifs = ifsset() ? ifsval() : defifs;
7231 ifsp = &ifsfirst;
7232 do {
7233 p = string + ifsp->begoff;
7234 nulonly = ifsp->nulonly;
7235 ifs = nulonly ? nullstr : realifs;
7236 ifsspc = 0;
7237 while (p < string + ifsp->endoff) {
7238 q = p;
7239 if ((unsigned char)*p == CTLESC)
7240 p++;
7241 if (!strchr(ifs, *p)) {
7242 p++;
7243 continue;
7244 }
7245 if (!nulonly)
7246 ifsspc = (strchr(defifs, *p) != NULL);
7247 /* Ignore IFS whitespace at start */
7248 if (q == start && ifsspc) {
7249 p++;
7250 start = p;
7251 continue;
7252 }
7253 *q = '\0';
7254 sp = stzalloc(sizeof(*sp));
7255 sp->text = start;
7256 *arglist->lastp = sp;
7257 arglist->lastp = &sp->next;
7258 p++;
7259 if (!nulonly) {
7260 for (;;) {
7261 if (p >= string + ifsp->endoff) {
7262 break;
7263 }
7264 q = p;
7265 if ((unsigned char)*p == CTLESC)
7266 p++;
7267 if (strchr(ifs, *p) == NULL) {
7268 p = q;
7269 break;
7270 }
7271 if (strchr(defifs, *p) == NULL) {
7272 if (ifsspc) {
7273 p++;
7274 ifsspc = 0;
7275 } else {
7276 p = q;
7277 break;
7278 }
7279 } else
7280 p++;
7281 }
7282 }
7283 start = p;
7284 } /* while */
7285 ifsp = ifsp->next;
7286 } while (ifsp != NULL);
7287 if (nulonly)
7288 goto add;
7289 }
7290
7291 if (!*start)
7292 return;
7293
7294 add:
7295 sp = stzalloc(sizeof(*sp));
7296 sp->text = start;
7297 *arglist->lastp = sp;
7298 arglist->lastp = &sp->next;
7299}
7300
7301static void
7302ifsfree(void)
7303{
7304 struct ifsregion *p;
7305
7306 INT_OFF;
7307 p = ifsfirst.next;
7308 do {
7309 struct ifsregion *ifsp;
7310 ifsp = p->next;
7311 free(p);
7312 p = ifsp;
7313 } while (p);
7314 ifslastp = NULL;
7315 ifsfirst.next = NULL;
7316 INT_ON;
7317}
7318
7319/*
7320 * Add a file name to the list. 7370 * Add a file name to the list.
7321 */ 7371 */
7322static void 7372static void
@@ -7654,15 +7704,14 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
7654 7704
7655 argbackq = arg->narg.backquote; 7705 argbackq = arg->narg.backquote;
7656 STARTSTACKSTR(expdest); 7706 STARTSTACKSTR(expdest);
7657 ifsfirst.next = NULL;
7658 ifslastp = NULL;
7659 TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag)); 7707 TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7660 argstr(arg->narg.text, flag, 7708 argstr(arg->narg.text, flag,
7661 /* var_str_list: */ arglist ? arglist->list : NULL); 7709 /* var_str_list: */ arglist ? arglist->list : NULL);
7662 p = _STPUTC('\0', expdest); 7710 p = _STPUTC('\0', expdest);
7663 expdest = p - 1; 7711 expdest = p - 1;
7664 if (arglist == NULL) { 7712 if (arglist == NULL) {
7665 return; /* here document expanded */ 7713 /* here document expanded */
7714 goto out;
7666 } 7715 }
7667 p = grabstackstr(p); 7716 p = grabstackstr(p);
7668 TRACE(("expandarg: p:'%s'\n", p)); 7717 TRACE(("expandarg: p:'%s'\n", p));
@@ -7685,13 +7734,14 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
7685 *exparg.lastp = sp; 7734 *exparg.lastp = sp;
7686 exparg.lastp = &sp->next; 7735 exparg.lastp = &sp->next;
7687 } 7736 }
7688 if (ifsfirst.next)
7689 ifsfree();
7690 *exparg.lastp = NULL; 7737 *exparg.lastp = NULL;
7691 if (exparg.list) { 7738 if (exparg.list) {
7692 *arglist->lastp = exparg.list; 7739 *arglist->lastp = exparg.list;
7693 arglist->lastp = exparg.lastp; 7740 arglist->lastp = exparg.lastp;
7694 } 7741 }
7742
7743 out:
7744 ifsfree();
7695} 7745}
7696 7746
7697/* 7747/*
@@ -7725,10 +7775,10 @@ casematch(union node *pattern, char *val)
7725 setstackmark(&smark); 7775 setstackmark(&smark);
7726 argbackq = pattern->narg.backquote; 7776 argbackq = pattern->narg.backquote;
7727 STARTSTACKSTR(expdest); 7777 STARTSTACKSTR(expdest);
7728 ifslastp = NULL;
7729 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE, 7778 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7730 /* var_str_list: */ NULL); 7779 /* var_str_list: */ NULL);
7731 STACKSTRNUL(expdest); 7780 STACKSTRNUL(expdest);
7781 ifsfree();
7732 result = patmatch(stackblock(), val); 7782 result = patmatch(stackblock(), val);
7733 popstackmark(&smark); 7783 popstackmark(&smark);
7734 return result; 7784 return result;
@@ -8890,41 +8940,18 @@ static void prehash(union node *);
8890static int 8940static int
8891evaltree(union node *n, int flags) 8941evaltree(union node *n, int flags)
8892{ 8942{
8893 struct jmploc *volatile savehandler = exception_handler;
8894 struct jmploc jmploc;
8895 int checkexit = 0; 8943 int checkexit = 0;
8896 int (*evalfn)(union node *, int); 8944 int (*evalfn)(union node *, int);
8897 int status = 0; 8945 int status = 0;
8898 int int_level;
8899
8900 SAVE_INT(int_level);
8901 8946
8902 if (n == NULL) { 8947 if (n == NULL) {
8903 TRACE(("evaltree(NULL) called\n")); 8948 TRACE(("evaltree(NULL) called\n"));
8904 goto out1; 8949 goto out;
8905 } 8950 }
8906 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags)); 8951 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8907 8952
8908 dotrap(); 8953 dotrap();
8909 8954
8910 exception_handler = &jmploc;
8911 {
8912 int err = setjmp(jmploc.loc);
8913 if (err) {
8914 /* if it was a signal, check for trap handlers */
8915 if (exception_type == EXSIG) {
8916 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8917 exception_type, err));
8918 goto out;
8919 }
8920 /* continue on the way out */
8921 TRACE(("exception %d in evaltree, propagating err=%d\n",
8922 exception_type, err));
8923 exception_handler = savehandler;
8924 longjmp(exception_handler->loc, err);
8925 }
8926 }
8927
8928 switch (n->type) { 8955 switch (n->type) {
8929 default: 8956 default:
8930#if DEBUG 8957#if DEBUG
@@ -9015,11 +9042,7 @@ evaltree(union node *n, int flags)
9015 exitstatus = status; 9042 exitstatus = status;
9016 break; 9043 break;
9017 } 9044 }
9018
9019 out: 9045 out:
9020 exception_handler = savehandler;
9021
9022 out1:
9023 /* Order of checks below is important: 9046 /* Order of checks below is important:
9024 * signal handlers trigger before exit caused by "set -e". 9047 * signal handlers trigger before exit caused by "set -e".
9025 */ 9048 */
@@ -9030,9 +9053,7 @@ evaltree(union node *n, int flags)
9030 if (flags & EV_EXIT) 9053 if (flags & EV_EXIT)
9031 raise_exception(EXEXIT); 9054 raise_exception(EXEXIT);
9032 9055
9033 RESTORE_INT(int_level);
9034 TRACE(("leaving evaltree (no interrupts)\n")); 9056 TRACE(("leaving evaltree (no interrupts)\n"));
9035
9036 return exitstatus; 9057 return exitstatus;
9037} 9058}
9038 9059
@@ -10036,21 +10057,12 @@ evalcommand(union node *cmd, int flags)
10036 dowait(DOWAIT_NONBLOCK, NULL); 10057 dowait(DOWAIT_NONBLOCK, NULL);
10037 10058
10038 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { 10059 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10039 int exit_status; 10060 if (exception_type == EXERROR && spclbltin <= 0) {
10040 int i = exception_type; 10061 FORCE_INT_ON;
10041 if (i == EXEXIT) 10062 break;
10042 goto raise;
10043 exit_status = 2;
10044 if (i == EXINT)
10045 exit_status = 128 + SIGINT;
10046 if (i == EXSIG)
10047 exit_status = 128 + pending_sig;
10048 exitstatus = exit_status;
10049 if (i == EXINT || spclbltin > 0) {
10050 raise:
10051 longjmp(exception_handler->loc, 1);
10052 } 10063 }
10053 FORCE_INT_ON; 10064 raise:
10065 longjmp(exception_handler->loc, 1);
10054 } 10066 }
10055 goto readstatus; 10067 goto readstatus;
10056 10068
@@ -13255,12 +13267,13 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13255 if (action) { 13267 if (action) {
13256 if (LONE_DASH(action)) 13268 if (LONE_DASH(action))
13257 action = NULL; 13269 action = NULL;
13258 else 13270 else {
13271 if (action[0]) /* not NULL and not "" and not "-" */
13272 may_have_traps = 1;
13259 action = ckstrdup(action); 13273 action = ckstrdup(action);
13274 }
13260 } 13275 }
13261 free(trap[signo]); 13276 free(trap[signo]);
13262 if (action)
13263 may_have_traps = 1;
13264 trap[signo] = action; 13277 trap[signo] = action;
13265 if (signo != 0) 13278 if (signo != 0)
13266 setsignal(signo); 13279 setsignal(signo);
@@ -13661,7 +13674,9 @@ init(void)
13661 /* we will never free this */ 13674 /* we will never free this */
13662 basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ); 13675 basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13663 13676
13664 signal(SIGCHLD, SIG_DFL); 13677 sigmode[SIGCHLD - 1] = S_DFL;
13678 setsignal(SIGCHLD);
13679
13665 /* bash re-enables SIGHUP which is SIG_IGNed on entry. 13680 /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13666 * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$" 13681 * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13667 */ 13682 */
@@ -13863,11 +13878,12 @@ procargs(char **argv)
13863} 13878}
13864 13879
13865/* 13880/*
13866 * Read /etc/profile or .profile. 13881 * Read /etc/profile, ~/.profile, $ENV.
13867 */ 13882 */
13868static void 13883static void
13869read_profile(const char *name) 13884read_profile(const char *name)
13870{ 13885{
13886 name = expandstr(name);
13871 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0) 13887 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13872 return; 13888 return;
13873 cmdloop(0); 13889 cmdloop(0);
@@ -13877,6 +13893,7 @@ read_profile(const char *name)
13877/* 13893/*
13878 * This routine is called when an error or an interrupt occurs in an 13894 * This routine is called when an error or an interrupt occurs in an
13879 * interactive shell and control is returned to the main command loop. 13895 * interactive shell and control is returned to the main command loop.
13896 * (In dash, this function is auto-generated by build machinery).
13880 */ 13897 */
13881static void 13898static void
13882reset(void) 13899reset(void)
@@ -13884,13 +13901,15 @@ reset(void)
13884 /* from eval.c: */ 13901 /* from eval.c: */
13885 evalskip = 0; 13902 evalskip = 0;
13886 loopnest = 0; 13903 loopnest = 0;
13904
13905 /* from expand.c: */
13906 ifsfree();
13907
13887 /* from input.c: */ 13908 /* from input.c: */
13888 g_parsefile->left_in_buffer = 0; 13909 g_parsefile->left_in_buffer = 0;
13889 g_parsefile->left_in_line = 0; /* clear input buffer */ 13910 g_parsefile->left_in_line = 0; /* clear input buffer */
13890 popallfiles(); 13911 popallfiles();
13891 /* from parser.c: */ 13912
13892 tokpushback = 0;
13893 checkkwd = 0;
13894 /* from redir.c: */ 13913 /* from redir.c: */
13895 while (redirlist) 13914 while (redirlist)
13896 popredir(/*drop:*/ 0, /*restore:*/ 0); 13915 popredir(/*drop:*/ 0, /*restore:*/ 0);
@@ -13911,7 +13930,6 @@ extern int etext();
13911int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 13930int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13912int ash_main(int argc UNUSED_PARAM, char **argv) 13931int ash_main(int argc UNUSED_PARAM, char **argv)
13913{ 13932{
13914 const char *shinit;
13915 volatile smallint state; 13933 volatile smallint state;
13916 struct jmploc jmploc; 13934 struct jmploc jmploc;
13917 struct stackmark smark; 13935 struct stackmark smark;
@@ -14005,11 +14023,8 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
14005 state1: 14023 state1:
14006 state = 2; 14024 state = 2;
14007 hp = lookupvar("HOME"); 14025 hp = lookupvar("HOME");
14008 if (hp) { 14026 if (hp)
14009 hp = concat_path_file(hp, ".profile"); 14027 read_profile("$HOME/.profile");
14010 read_profile(hp);
14011 free((char*)hp);
14012 }
14013 } 14028 }
14014 state2: 14029 state2:
14015 state = 3; 14030 state = 3;
@@ -14019,11 +14034,11 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
14019#endif 14034#endif
14020 iflag 14035 iflag
14021 ) { 14036 ) {
14022 shinit = lookupvar("ENV"); 14037 const char *shinit = lookupvar("ENV");
14023 if (shinit != NULL && *shinit != '\0') { 14038 if (shinit != NULL && *shinit != '\0')
14024 read_profile(shinit); 14039 read_profile(shinit);
14025 }
14026 } 14040 }
14041 popstackmark(&smark);
14027 state3: 14042 state3:
14028 state = 4; 14043 state = 4;
14029 if (minusc) { 14044 if (minusc) {
diff --git a/shell/hush.c b/shell/hush.c
index d7a0d761e..c80429d5c 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -8405,6 +8405,7 @@ int hush_main(int argc, char **argv)
8405 * "bash <script>" (which is never interactive (unless -i?)) 8405 * "bash <script>" (which is never interactive (unless -i?))
8406 * sources $BASH_ENV here (without scanning $PATH). 8406 * sources $BASH_ENV here (without scanning $PATH).
8407 * If called as sh, does the same but with $ENV. 8407 * If called as sh, does the same but with $ENV.
8408 * Also NB, per POSIX, $ENV should undergo parameter expansion.
8408 */ 8409 */
8409 G.global_argc--; 8410 G.global_argc--;
8410 G.global_argv++; 8411 G.global_argv++;