summaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-11-02 10:19:18 +0000
committerRon Yorston <rmy@pobox.com>2016-11-02 10:19:18 +0000
commite45ff573dc9707b1ea71f490ef16cd9d08feaaf2 (patch)
tree09980b02b9c8efc8d772c7379abdcd4eef4ddad8 /shell/ash.c
parent7bc3efa4f0c7608723d301bda5ee006a0f6141fe (diff)
parent2e6af549715f5d7b4c2ab204e46c8b8f6f057045 (diff)
downloadbusybox-w32-e45ff573dc9707b1ea71f490ef16cd9d08feaaf2.tar.gz
busybox-w32-e45ff573dc9707b1ea71f490ef16cd9d08feaaf2.tar.bz2
busybox-w32-e45ff573dc9707b1ea71f490ef16cd9d08feaaf2.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c122
1 files changed, 81 insertions, 41 deletions
diff --git a/shell/ash.c b/shell/ash.c
index dd320355e..a709c3602 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -362,8 +362,7 @@ struct globals_misc {
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 volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
365 /* last pending signal */ 365 volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
366 volatile /*sig_atomic_t*/ smallint pending_sig;
367 smallint exception_type; /* kind of exception (0..5) */ 366 smallint exception_type; /* kind of exception (0..5) */
368 /* exceptions */ 367 /* exceptions */
369#define EXINT 0 /* SIGINT received */ 368#define EXINT 0 /* SIGINT received */
@@ -915,13 +914,8 @@ trace_vprintf(const char *fmt, va_list va)
915{ 914{
916 if (debug != 1) 915 if (debug != 1)
917 return; 916 return;
918 if (DEBUG_TIME)
919 fprintf(tracefile, "%u ", (int) time(NULL));
920 if (DEBUG_PID)
921 fprintf(tracefile, "[%u] ", (int) getpid());
922 if (DEBUG_SIG)
923 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
924 vfprintf(tracefile, fmt, va); 917 vfprintf(tracefile, fmt, va);
918 fprintf(tracefile, "\n");
925} 919}
926 920
927static void 921static void
@@ -1314,11 +1308,10 @@ ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1314{ 1308{
1315#if DEBUG 1309#if DEBUG
1316 if (msg) { 1310 if (msg) {
1317 TRACE(("ash_vmsg_and_raise(%d, \"", cond)); 1311 TRACE(("ash_vmsg_and_raise(%d):", cond));
1318 TRACEV((msg, ap)); 1312 TRACEV((msg, ap));
1319 TRACE(("\") pid=%d\n", getpid()));
1320 } else 1313 } else
1321 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid())); 1314 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1322 if (msg) 1315 if (msg)
1323#endif 1316#endif
1324 ash_vmsg(msg, ap); 1317 ash_vmsg(msg, ap);
@@ -2250,6 +2243,7 @@ setvareq(char *s, int flags)
2250 if (flags & VNOSAVE) 2243 if (flags & VNOSAVE)
2251 free(s); 2244 free(s);
2252 n = vp->var_text; 2245 n = vp->var_text;
2246 exitstatus = 1;
2253 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n); 2247 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2254 } 2248 }
2255 2249
@@ -3715,11 +3709,6 @@ setsignal(int signo)
3715#define CUR_RUNNING 1 3709#define CUR_RUNNING 1
3716#define CUR_STOPPED 0 3710#define CUR_STOPPED 0
3717 3711
3718/* mode flags for dowait */
3719#define DOWAIT_NONBLOCK 0
3720#define DOWAIT_BLOCK 1
3721#define DOWAIT_BLOCK_OR_SIG 2
3722
3723#if JOBS 3712#if JOBS
3724/* pgrp of shell on invocation */ 3713/* pgrp of shell on invocation */
3725static int initialpgrp; //references:2 3714static int initialpgrp; //references:2
@@ -4231,24 +4220,30 @@ waitpid_child(int *status, int wait_flags)
4231#else 4220#else
4232 4221
4233static int 4222static int
4234wait_block_or_sig(int *status, int wait_flags) 4223wait_block_or_sig(int *status)
4235{ 4224{
4236 sigset_t mask;
4237 int pid; 4225 int pid;
4238 4226
4239 do { 4227 do {
4240 /* Poll all children for changes in their state */ 4228 /* Poll all children for changes in their state */
4241 got_sigchld = 0; 4229 got_sigchld = 0;
4242 pid = waitpid(-1, status, wait_flags | WNOHANG); 4230 /* if job control is active, accept stopped processes too */
4231 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4243 if (pid != 0) 4232 if (pid != 0)
4244 break; /* Error (e.g. EINTR) or pid */ 4233 break; /* Error (e.g. EINTR, ECHILD) or pid */
4245 4234
4246 /* No child is ready. Sleep until interesting signal is received */ 4235 /* Children exist, but none are ready. Sleep until interesting signal */
4236#if 0 /* dash does this */
4237 sigset_t mask;
4247 sigfillset(&mask); 4238 sigfillset(&mask);
4248 sigprocmask(SIG_SETMASK, &mask, &mask); 4239 sigprocmask(SIG_SETMASK, &mask, &mask);
4249 while (!got_sigchld && !pending_sig) 4240 while (!got_sigchld && !pending_sig)
4250 sigsuspend(&mask); 4241 sigsuspend(&mask);
4251 sigprocmask(SIG_SETMASK, &mask, NULL); 4242 sigprocmask(SIG_SETMASK, &mask, NULL);
4243#else
4244 while (!got_sigchld && !pending_sig)
4245 pause();
4246#endif
4252 4247
4253 /* If it was SIGCHLD, poll children again */ 4248 /* If it was SIGCHLD, poll children again */
4254 } while (got_sigchld); 4249 } while (got_sigchld);
@@ -4257,11 +4252,13 @@ wait_block_or_sig(int *status, int wait_flags)
4257} 4252}
4258#endif 4253#endif
4259 4254
4255#define DOWAIT_NONBLOCK 0
4256#define DOWAIT_BLOCK 1
4257#define DOWAIT_BLOCK_OR_SIG 2
4260 4258
4261static int 4259static int
4262dowait(int block, struct job *job) 4260dowait(int block, struct job *job)
4263{ 4261{
4264 int wait_flags;
4265 int pid; 4262 int pid;
4266 int status; 4263 int status;
4267 struct job *jp; 4264 struct job *jp;
@@ -4269,13 +4266,6 @@ dowait(int block, struct job *job)
4269 4266
4270 TRACE(("dowait(0x%x) called\n", block)); 4267 TRACE(("dowait(0x%x) called\n", block));
4271 4268
4272 wait_flags = 0;
4273 if (block == DOWAIT_NONBLOCK)
4274 wait_flags = WNOHANG;
4275 /* If job control is compiled in, we accept stopped processes too. */
4276 if (doing_jobctl)
4277 wait_flags |= WUNTRACED;
4278
4279 /* It's wrong to call waitpid() outside of INT_OFF region: 4269 /* It's wrong to call waitpid() outside of INT_OFF region:
4280 * signal can arrive just after syscall return and handler can 4270 * signal can arrive just after syscall return and handler can
4281 * longjmp away, losing stop/exit notification processing. 4271 * longjmp away, losing stop/exit notification processing.
@@ -4286,17 +4276,27 @@ dowait(int block, struct job *job)
4286 * in INT_OFF region: "wait" needs to wait for any running job 4276 * in INT_OFF region: "wait" needs to wait for any running job
4287 * to change state, but should exit on any trap too. 4277 * to change state, but should exit on any trap too.
4288 * In INT_OFF region, a signal just before syscall entry can set 4278 * In INT_OFF region, a signal just before syscall entry can set
4289 * pending_sig valiables, but we can't check them, and we would 4279 * pending_sig variables, but we can't check them, and we would
4290 * either enter a sleeping waitpid() (BUG), or need to busy-loop. 4280 * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4281 *
4291 * Because of this, we run inside INT_OFF, but use a special routine 4282 * Because of this, we run inside INT_OFF, but use a special routine
4292 * which combines waitpid() and sigsuspend(). 4283 * which combines waitpid() and pause().
4284 * This is the reason why we need to have a handler for SIGCHLD:
4285 * SIG_DFL handler does not wake pause().
4293 */ 4286 */
4294 INT_OFF; 4287 INT_OFF;
4295 if (block == DOWAIT_BLOCK_OR_SIG) 4288 if (block == DOWAIT_BLOCK_OR_SIG) {
4296 pid = wait_block_or_sig(&status, wait_flags); 4289 pid = wait_block_or_sig(&status);
4297 else 4290 } else {
4298 /* NB: _not_ safe_waitpid, we need to detect EINTR. */ 4291 int wait_flags = 0;
4292 if (block == DOWAIT_NONBLOCK)
4293 wait_flags = WNOHANG;
4294 /* if job control is active, accept stopped processes too */
4295 if (doing_jobctl)
4296 wait_flags |= WUNTRACED;
4297 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4299 pid = waitpid(-1, &status, wait_flags); 4298 pid = waitpid(-1, &status, wait_flags);
4299 }
4300 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", 4300 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4301 pid, status, errno, strerror(errno))); 4301 pid, status, errno, strerror(errno)));
4302 if (pid <= 0) 4302 if (pid <= 0)
@@ -7410,6 +7410,21 @@ expandmeta(struct strlist *str /*, int flag*/)
7410 7410
7411 if (fflag) 7411 if (fflag)
7412 goto nometa; 7412 goto nometa;
7413
7414 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7415 p = str->text;
7416 while (*p) {
7417 if (*p == '*')
7418 goto need_glob;
7419 if (*p == '?')
7420 goto need_glob;
7421 if (*p == '[')
7422 goto need_glob;
7423 p++;
7424 }
7425 goto nometa;
7426
7427 need_glob:
7413 INT_OFF; 7428 INT_OFF;
7414 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); 7429 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7415// GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match 7430// GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
@@ -10064,7 +10079,7 @@ evalcommand(union node *cmd, int flags)
10064 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { 10079 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10065 if (exception_type == EXERROR && spclbltin <= 0) { 10080 if (exception_type == EXERROR && spclbltin <= 0) {
10066 FORCE_INT_ON; 10081 FORCE_INT_ON;
10067 break; 10082 goto readstatus;
10068 } 10083 }
10069 raise: 10084 raise:
10070 longjmp(exception_handler->loc, 1); 10085 longjmp(exception_handler->loc, 1);
@@ -10584,6 +10599,9 @@ popfile(void)
10584{ 10599{
10585 struct parsefile *pf = g_parsefile; 10600 struct parsefile *pf = g_parsefile;
10586 10601
10602 if (pf == &basepf)
10603 return;
10604
10587 INT_OFF; 10605 INT_OFF;
10588 if (pf->pf_fd >= 0) 10606 if (pf->pf_fd >= 0)
10589 close(pf->pf_fd); 10607 close(pf->pf_fd);
@@ -12747,6 +12765,10 @@ expandstr(const char *ps)
12747static int 12765static int
12748evalstring(char *s, int flags) 12766evalstring(char *s, int flags)
12749{ 12767{
12768 struct jmploc *volatile savehandler;
12769 struct jmploc jmploc;
12770 int ex;
12771
12750 union node *n; 12772 union node *n;
12751 struct stackmark smark; 12773 struct stackmark smark;
12752 int status; 12774 int status;
@@ -12756,6 +12778,19 @@ evalstring(char *s, int flags)
12756 setstackmark(&smark); 12778 setstackmark(&smark);
12757 12779
12758 status = 0; 12780 status = 0;
12781 /* On exception inside execution loop, we must popfile().
12782 * Try interactively:
12783 * readonly a=a
12784 * command eval "a=b" # throws "is read only" error
12785 * "command BLTIN" is not supposed to abort (even in non-interactive use).
12786 * But if we skip popfile(), we hit EOF in eval's string, and exit.
12787 */
12788 savehandler = exception_handler;
12789 ex = setjmp(jmploc.loc);
12790 if (ex)
12791 goto out;
12792 exception_handler = &jmploc;
12793
12759 while ((n = parsecmd(0)) != NODE_EOF) { 12794 while ((n = parsecmd(0)) != NODE_EOF) {
12760 int i; 12795 int i;
12761 12796
@@ -12766,10 +12801,15 @@ evalstring(char *s, int flags)
12766 if (evalskip) 12801 if (evalskip)
12767 break; 12802 break;
12768 } 12803 }
12804 out:
12769 popstackmark(&smark); 12805 popstackmark(&smark);
12770 popfile(); 12806 popfile();
12771 stunalloc(s); 12807 stunalloc(s);
12772 12808
12809 exception_handler = savehandler;
12810 if (ex)
12811 longjmp(exception_handler->loc, ex);
12812
12773 return status; 12813 return status;
12774} 12814}
12775 12815
@@ -13982,11 +14022,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13982 goto state4; 14022 goto state4;
13983 } 14023 }
13984 exception_handler = &jmploc; 14024 exception_handler = &jmploc;
13985#if DEBUG
13986 opentrace();
13987 TRACE(("Shell args: "));
13988 trace_puts_args(argv);
13989#endif
13990 rootpid = getpid(); 14025 rootpid = getpid();
13991 14026
13992 init(IF_PLATFORM_MINGW32(argc >= 2 && strcmp(argv[1], "-X") == 0)); 14027 init(IF_PLATFORM_MINGW32(argc >= 2 && strcmp(argv[1], "-X") == 0));
@@ -14003,6 +14038,11 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
14003 } 14038 }
14004#endif 14039#endif
14005 procargs(argv); 14040 procargs(argv);
14041#if DEBUG
14042 TRACE(("Shell args: "));
14043 trace_puts_args(argv);
14044#endif
14045
14006#if ENABLE_PLATFORM_MINGW32 14046#if ENABLE_PLATFORM_MINGW32
14007 if ( noconsole ) { 14047 if ( noconsole ) {
14008 DWORD dummy; 14048 DWORD dummy;