aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c459
1 files changed, 219 insertions, 240 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 28b522d7c..6aaeecfac 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -241,6 +241,9 @@
241#include "shell_common.h" 241#include "shell_common.h"
242#if ENABLE_FEATURE_SH_MATH 242#if ENABLE_FEATURE_SH_MATH
243# include "math.h" 243# include "math.h"
244#else
245typedef long arith_t;
246# define ARITH_FMT "%ld"
244#endif 247#endif
245#if ENABLE_ASH_RANDOM_SUPPORT 248#if ENABLE_ASH_RANDOM_SUPPORT
246# include "random.h" 249# include "random.h"
@@ -708,8 +711,8 @@ fmtstr(char *outbuf, size_t length, const char *fmt, ...)
708 va_list ap; 711 va_list ap;
709 int ret; 712 int ret;
710 713
711 va_start(ap, fmt);
712 INT_OFF; 714 INT_OFF;
715 va_start(ap, fmt);
713 ret = vsnprintf(outbuf, length, fmt, ap); 716 ret = vsnprintf(outbuf, length, fmt, ap);
714 va_end(ap); 717 va_end(ap);
715 INT_ON; 718 INT_ON;
@@ -1334,7 +1337,6 @@ static struct parsefile basepf; /* top level input file */
1334static struct parsefile *g_parsefile = &basepf; /* current input file */ 1337static struct parsefile *g_parsefile = &basepf; /* current input file */
1335static int startlinno; /* line # where last token started */ 1338static int startlinno; /* line # where last token started */
1336static char *commandname; /* currently executing command */ 1339static char *commandname; /* currently executing command */
1337static struct strlist *cmdenviron; /* environment for builtin command */
1338 1340
1339 1341
1340/* ============ Message printing */ 1342/* ============ Message printing */
@@ -1391,6 +1393,18 @@ ash_msg_and_raise_error(const char *msg, ...)
1391 va_end(ap); 1393 va_end(ap);
1392} 1394}
1393 1395
1396/*
1397 * Use '%m' to append error string on platforms that support it, '%s' and
1398 * strerror() on those that don't.
1399 *
1400 * 'fmt' must be a string literal.
1401 */
1402#ifdef HAVE_PRINTF_PERCENTM
1403#define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1404#else
1405#define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1406#endif
1407
1394static void raise_error_syntax(const char *) NORETURN; 1408static void raise_error_syntax(const char *) NORETURN;
1395static void 1409static void
1396raise_error_syntax(const char *msg) 1410raise_error_syntax(const char *msg)
@@ -1875,9 +1889,6 @@ single_quote(const char *s)
1875 1889
1876/* 1890/*
1877 * Produce a possibly single quoted string suitable as input to the shell. 1891 * Produce a possibly single quoted string suitable as input to the shell.
1878 * If 'conditional' is nonzero, quoting is only done if the string contains
1879 * non-shellsafe characters, or is identical to a shell keyword (reserved
1880 * word); if it is zero, quoting is always done.
1881 * If quoting was done, the return string is allocated on the stack, 1892 * If quoting was done, the return string is allocated on the stack,
1882 * otherwise a pointer to the original string is returned. 1893 * otherwise a pointer to the original string is returned.
1883 */ 1894 */
@@ -2312,15 +2323,9 @@ reinit_unicode_for_ash(void)
2312/* 2323/*
2313 * Search the environment of a builtin command. 2324 * Search the environment of a builtin command.
2314 */ 2325 */
2315static const char * 2326static ALWAYS_INLINE const char *
2316bltinlookup(const char *name) 2327bltinlookup(const char *name)
2317{ 2328{
2318 struct strlist *sp;
2319
2320 for (sp = cmdenviron; sp; sp = sp->next) {
2321 if (varcmp(sp->text, name) == 0)
2322 return var_end(sp->text);
2323 }
2324 return lookupvar(name); 2329 return lookupvar(name);
2325} 2330}
2326 2331
@@ -2331,14 +2336,15 @@ bltinlookup(const char *name)
2331 * will go away. 2336 * will go away.
2332 * Called with interrupts off. 2337 * Called with interrupts off.
2333 */ 2338 */
2334static void 2339static struct var *
2335setvareq(char *s, int flags) 2340setvareq(char *s, int flags)
2336{ 2341{
2337 struct var *vp, **vpp; 2342 struct var *vp, **vpp;
2338 2343
2339 vpp = hashvar(s); 2344 vpp = hashvar(s);
2340 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); 2345 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2341 vp = *findvar(vpp, s); 2346 vpp = findvar(vpp, s);
2347 vp = *vpp;
2342 if (vp) { 2348 if (vp) {
2343 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) { 2349 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2344 const char *n; 2350 const char *n;
@@ -2351,7 +2357,7 @@ setvareq(char *s, int flags)
2351 } 2357 }
2352 2358
2353 if (flags & VNOSET) 2359 if (flags & VNOSET)
2354 return; 2360 goto out;
2355 2361
2356 if (vp->var_func && !(flags & VNOFUNC)) 2362 if (vp->var_func && !(flags & VNOFUNC))
2357 vp->var_func(var_end(s)); 2363 vp->var_func(var_end(s));
@@ -2359,11 +2365,22 @@ setvareq(char *s, int flags)
2359 if (!(vp->flags & (VTEXTFIXED|VSTACK))) 2365 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2360 free((char*)vp->var_text); 2366 free((char*)vp->var_text);
2361 2367
2368 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2369 *vpp = vp->next;
2370 free(vp);
2371 out_free:
2372 if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2373 free(s);
2374 goto out;
2375 }
2376
2362 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET); 2377 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2363 } else { 2378 } else {
2364 /* variable s is not found */ 2379 /* variable s is not found */
2365 if (flags & VNOSET) 2380 if (flags & VNOSET)
2366 return; 2381 goto out;
2382 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2383 goto out_free;
2367 vp = ckzalloc(sizeof(*vp)); 2384 vp = ckzalloc(sizeof(*vp));
2368 vp->next = *vpp; 2385 vp->next = *vpp;
2369 /*vp->func = NULL; - ckzalloc did it */ 2386 /*vp->func = NULL; - ckzalloc did it */
@@ -2373,13 +2390,16 @@ setvareq(char *s, int flags)
2373 s = ckstrdup(s); 2390 s = ckstrdup(s);
2374 vp->var_text = s; 2391 vp->var_text = s;
2375 vp->flags = flags; 2392 vp->flags = flags;
2393
2394 out:
2395 return vp;
2376} 2396}
2377 2397
2378/* 2398/*
2379 * Set the value of a variable. The flags argument is ored with the 2399 * Set the value of a variable. The flags argument is ored with the
2380 * flags of the variable. If val is NULL, the variable is unset. 2400 * flags of the variable. If val is NULL, the variable is unset.
2381 */ 2401 */
2382static void 2402static struct var *
2383setvar(const char *name, const char *val, int flags) 2403setvar(const char *name, const char *val, int flags)
2384{ 2404{
2385 const char *q; 2405 const char *q;
@@ -2387,6 +2407,7 @@ setvar(const char *name, const char *val, int flags)
2387 char *nameeq; 2407 char *nameeq;
2388 size_t namelen; 2408 size_t namelen;
2389 size_t vallen; 2409 size_t vallen;
2410 struct var *vp;
2390 2411
2391 q = endofname(name); 2412 q = endofname(name);
2392 p = strchrnul(q, '='); 2413 p = strchrnul(q, '=');
@@ -2408,8 +2429,10 @@ setvar(const char *name, const char *val, int flags)
2408 p = mempcpy(p, val, vallen); 2429 p = mempcpy(p, val, vallen);
2409 } 2430 }
2410 *p = '\0'; 2431 *p = '\0';
2411 setvareq(nameeq, flags | VNOSAVE); 2432 vp = setvareq(nameeq, flags | VNOSAVE);
2412 INT_ON; 2433 INT_ON;
2434
2435 return vp;
2413} 2436}
2414 2437
2415static void FAST_FUNC 2438static void FAST_FUNC
@@ -2421,43 +2444,10 @@ setvar0(const char *name, const char *val)
2421/* 2444/*
2422 * Unset the specified variable. 2445 * Unset the specified variable.
2423 */ 2446 */
2424static int 2447static void
2425unsetvar(const char *s) 2448unsetvar(const char *s)
2426{ 2449{
2427 struct var **vpp; 2450 setvar(s, NULL, 0);
2428 struct var *vp;
2429 int retval;
2430
2431 vpp = findvar(hashvar(s), s);
2432 vp = *vpp;
2433 retval = 2;
2434 if (vp) {
2435 int flags = vp->flags;
2436
2437 retval = 1;
2438 if (flags & VREADONLY)
2439 goto out;
2440#if ENABLE_ASH_RANDOM_SUPPORT
2441 vp->flags &= ~VDYNAMIC;
2442#endif
2443 if (flags & VUNSET)
2444 goto ok;
2445 if ((flags & VSTRFIXED) == 0) {
2446 INT_OFF;
2447 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2448 free((char*)vp->var_text);
2449 *vpp = vp->next;
2450 free(vp);
2451 INT_ON;
2452 } else {
2453 setvar0(s, NULL);
2454 vp->flags &= ~VEXPORT;
2455 }
2456 ok:
2457 retval = 0;
2458 }
2459 out:
2460 return retval;
2461} 2451}
2462 2452
2463/* 2453/*
@@ -4067,7 +4057,7 @@ static void
4067xtcsetpgrp(int fd, pid_t pgrp) 4057xtcsetpgrp(int fd, pid_t pgrp)
4068{ 4058{
4069 if (tcsetpgrp(fd, pgrp)) 4059 if (tcsetpgrp(fd, pgrp))
4070 ash_msg_and_raise_error("can't set tty process group (%m)"); 4060 ash_msg_and_raise_perror("can't set tty process group");
4071} 4061}
4072 4062
4073/* 4063/*
@@ -5529,68 +5519,6 @@ stoppedjobs(void)
5529#define CLOSED -3 /* marks a slot of previously-closed fd */ 5519#define CLOSED -3 /* marks a slot of previously-closed fd */
5530 5520
5531/* 5521/*
5532 * Open a file in noclobber mode.
5533 * The code was copied from bash.
5534 */
5535static int
5536noclobberopen(const char *fname)
5537{
5538 int r, fd;
5539 struct stat finfo, finfo2;
5540
5541 /*
5542 * If the file exists and is a regular file, return an error
5543 * immediately.
5544 */
5545 r = stat(fname, &finfo);
5546 if (r == 0 && S_ISREG(finfo.st_mode)) {
5547 errno = EEXIST;
5548 return -1;
5549 }
5550
5551 /*
5552 * If the file was not present (r != 0), make sure we open it
5553 * exclusively so that if it is created before we open it, our open
5554 * will fail. Make sure that we do not truncate an existing file.
5555 * Note that we don't turn on O_EXCL unless the stat failed -- if the
5556 * file was not a regular file, we leave O_EXCL off.
5557 */
5558 if (r != 0)
5559 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5560 fd = open(fname, O_WRONLY|O_CREAT, 0666);
5561
5562 /* If the open failed, return the file descriptor right away. */
5563 if (fd < 0)
5564 return fd;
5565
5566 /*
5567 * OK, the open succeeded, but the file may have been changed from a
5568 * non-regular file to a regular file between the stat and the open.
5569 * We are assuming that the O_EXCL open handles the case where FILENAME
5570 * did not exist and is symlinked to an existing file between the stat
5571 * and open.
5572 */
5573
5574 /*
5575 * If we can open it and fstat the file descriptor, and neither check
5576 * revealed that it was a regular file, and the file has not been
5577 * replaced, return the file descriptor.
5578 */
5579 if (fstat(fd, &finfo2) == 0
5580 && !S_ISREG(finfo2.st_mode)
5581 && finfo.st_dev == finfo2.st_dev
5582 && finfo.st_ino == finfo2.st_ino
5583 ) {
5584 return fd;
5585 }
5586
5587 /* The file has been replaced. badness. */
5588 close(fd);
5589 errno = EEXIST;
5590 return -1;
5591}
5592
5593/*
5594 * Handle here documents. Normally we fork off a process to write the 5522 * Handle here documents. Normally we fork off a process to write the
5595 * data to a pipe. If the document is short, we can stuff the data in 5523 * data to a pipe. If the document is short, we can stuff the data in
5596 * the pipe without forking. 5524 * the pipe without forking.
@@ -5645,6 +5573,7 @@ openhere(union node *redir)
5645static int 5573static int
5646openredirect(union node *redir) 5574openredirect(union node *redir)
5647{ 5575{
5576 struct stat sb;
5648 char *fname; 5577 char *fname;
5649 int f; 5578 int f;
5650 5579
@@ -5709,9 +5638,23 @@ openredirect(union node *redir)
5709#endif 5638#endif
5710 /* Take care of noclobber mode. */ 5639 /* Take care of noclobber mode. */
5711 if (Cflag) { 5640 if (Cflag) {
5712 f = noclobberopen(fname); 5641 if (stat(fname, &sb) < 0) {
5713 if (f < 0) 5642 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5643 if (f < 0)
5644 goto ecreate;
5645 } else if (!S_ISREG(sb.st_mode)) {
5646 f = open(fname, O_WRONLY, 0666);
5647 if (f < 0)
5648 goto ecreate;
5649 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5650 close(f);
5651 errno = EEXIST;
5652 goto ecreate;
5653 }
5654 } else {
5655 errno = EEXIST;
5714 goto ecreate; 5656 goto ecreate;
5657 }
5715 break; 5658 break;
5716 } 5659 }
5717 /* FALLTHROUGH */ 5660 /* FALLTHROUGH */
@@ -5750,7 +5693,7 @@ savefd(int from)
5750 err = newfd < 0 ? errno : 0; 5693 err = newfd < 0 ? errno : 0;
5751 if (err != EBADF) { 5694 if (err != EBADF) {
5752 if (err) 5695 if (err)
5753 ash_msg_and_raise_error("%d: %m", from); 5696 ash_msg_and_raise_perror("%d", from);
5754 close(from); 5697 close(from);
5755 fcntl(newfd, F_SETFD, FD_CLOEXEC); 5698 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5756 } 5699 }
@@ -5765,7 +5708,7 @@ dup2_or_raise(int from, int to)
5765 newfd = (from != to) ? dup2(from, to) : to; 5708 newfd = (from != to) ? dup2(from, to) : to;
5766 if (newfd < 0) { 5709 if (newfd < 0) {
5767 /* Happens when source fd is not open: try "echo >&99" */ 5710 /* Happens when source fd is not open: try "echo >&99" */
5768 ash_msg_and_raise_error("%d: %m", from); 5711 ash_msg_and_raise_perror("%d", from);
5769 } 5712 }
5770 return newfd; 5713 return newfd;
5771} 5714}
@@ -5896,7 +5839,7 @@ redirect(union node *redir, int flags)
5896 /* "echo >&10" and 10 is a fd opened to a sh script? */ 5839 /* "echo >&10" and 10 is a fd opened to a sh script? */
5897 if (is_hidden_fd(sv, right_fd)) { 5840 if (is_hidden_fd(sv, right_fd)) {
5898 errno = EBADF; /* as if it is closed */ 5841 errno = EBADF; /* as if it is closed */
5899 ash_msg_and_raise_error("%d: %m", right_fd); 5842 ash_msg_and_raise_perror("%d", right_fd);
5900 } 5843 }
5901 newfd = -1; 5844 newfd = -1;
5902 } else { 5845 } else {
@@ -5930,7 +5873,7 @@ redirect(union node *redir, int flags)
5930 if (newfd >= 0) 5873 if (newfd >= 0)
5931 close(newfd); 5874 close(newfd);
5932 errno = i; 5875 errno = i;
5933 ash_msg_and_raise_error("%d: %m", fd); 5876 ash_msg_and_raise_perror("%d", fd);
5934 /* NOTREACHED */ 5877 /* NOTREACHED */
5935 } 5878 }
5936 /* EBADF: it is not open - good, remember to close it */ 5879 /* EBADF: it is not open - good, remember to close it */
@@ -6104,7 +6047,7 @@ ash_arith(const char *s)
6104#define RMESCAPE_SLASH 0x20 /* Stop globbing after slash */ 6047#define RMESCAPE_SLASH 0x20 /* Stop globbing after slash */
6105 6048
6106/* Add CTLESC when necessary. */ 6049/* Add CTLESC when necessary. */
6107#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR) 6050#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT)
6108/* Do not skip NUL characters. */ 6051/* Do not skip NUL characters. */
6109#define QUOTES_KEEPNUL EXP_TILDE 6052#define QUOTES_KEEPNUL EXP_TILDE
6110 6053
@@ -6137,19 +6080,20 @@ static struct arglist exparg;
6137 6080
6138/* 6081/*
6139 * Our own itoa(). 6082 * Our own itoa().
6083 * cvtnum() is used even if math support is off (to prepare $? values and such).
6140 */ 6084 */
6141#if !ENABLE_FEATURE_SH_MATH
6142/* cvtnum() is used even if math support is off (to prepare $? values and such) */
6143typedef long arith_t;
6144# define ARITH_FMT "%ld"
6145#endif
6146static int 6085static int
6147cvtnum(arith_t num) 6086cvtnum(arith_t num)
6148{ 6087{
6149 int len; 6088 int len;
6150 6089
6151 expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest); 6090 /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6152 len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num); 6091 len = sizeof(arith_t) * 3;
6092 /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6093 if (sizeof(arith_t) < 4) len += 2;
6094
6095 expdest = makestrspace(len, expdest);
6096 len = fmtstr(expdest, len, ARITH_FMT, num);
6153 STADJUST(len, expdest); 6097 STADJUST(len, expdest);
6154 return len; 6098 return len;
6155} 6099}
@@ -6569,9 +6513,24 @@ struct backcmd { /* result of evalbackcmd */
6569}; 6513};
6570 6514
6571/* These forward decls are needed to use "eval" code for backticks handling: */ 6515/* These forward decls are needed to use "eval" code for backticks handling: */
6572#define EV_EXIT 01 /* exit after evaluating tree */ 6516/* flags in argument to evaltree */
6517#define EV_EXIT 01 /* exit after evaluating tree */
6518#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
6573static int evaltree(union node *, int); 6519static int evaltree(union node *, int);
6574 6520
6521/* An evaltree() which is known to never return.
6522 * Used to use an alias:
6523 * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6524 * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6525 */
6526static ALWAYS_INLINE NORETURN void
6527evaltreenr(union node *n, int flags)
6528{
6529 evaltree(n, flags);
6530 bb_unreachable(abort());
6531 /* NOTREACHED */
6532}
6533
6575static void FAST_FUNC 6534static void FAST_FUNC
6576evalbackcmd(union node *n, struct backcmd *result) 6535evalbackcmd(union node *n, struct backcmd *result)
6577{ 6536{
@@ -6617,7 +6576,7 @@ evalbackcmd(union node *n, struct backcmd *result)
6617 */ 6576 */
6618 eflag = 0; 6577 eflag = 0;
6619 ifsfree(); 6578 ifsfree();
6620 evaltree(n, EV_EXIT); /* actually evaltreenr... */ 6579 evaltreenr(n, EV_EXIT);
6621 /* NOTREACHED */ 6580 /* NOTREACHED */
6622 } 6581 }
6623#endif 6582#endif
@@ -6750,19 +6709,15 @@ expari(int flag)
6750#endif 6709#endif
6751 6710
6752/* argstr needs it */ 6711/* argstr needs it */
6753static char *evalvar(char *p, int flags, struct strlist *var_str_list); 6712static char *evalvar(char *p, int flags);
6754 6713
6755/* 6714/*
6756 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC 6715 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
6757 * characters to allow for further processing. Otherwise treat 6716 * characters to allow for further processing. Otherwise treat
6758 * $@ like $* since no splitting will be performed. 6717 * $@ like $* since no splitting will be performed.
6759 *
6760 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6761 * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6762 * for correct expansion of "B=$A" word.
6763 */ 6718 */
6764static void 6719static void
6765argstr(char *p, int flags, struct strlist *var_str_list) 6720argstr(char *p, int flags)
6766{ 6721{
6767 static const char spclchars[] ALIGN1 = { 6722 static const char spclchars[] ALIGN1 = {
6768 '=', 6723 '=',
@@ -6855,7 +6810,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6855 inquotes ^= EXP_QUOTED; 6810 inquotes ^= EXP_QUOTED;
6856 /* "$@" syntax adherence hack */ 6811 /* "$@" syntax adherence hack */
6857 if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) { 6812 if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6858 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1; 6813 p = evalvar(p + 1, flags | inquotes) + 1;
6859 goto start; 6814 goto start;
6860 } 6815 }
6861 addquote: 6816 addquote:
@@ -6881,7 +6836,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
6881 goto addquote; 6836 goto addquote;
6882 case CTLVAR: 6837 case CTLVAR:
6883 TRACE(("argstr: evalvar('%s')\n", p)); 6838 TRACE(("argstr: evalvar('%s')\n", p));
6884 p = evalvar(p, flags | inquotes, var_str_list); 6839 p = evalvar(p, flags | inquotes);
6885 TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock())); 6840 TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6886 goto start; 6841 goto start;
6887 case CTLBACKQ: 6842 case CTLBACKQ:
@@ -7023,7 +6978,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags)
7023 6978
7024static const char * 6979static const char *
7025subevalvar(char *p, char *varname, int strloc, int subtype, 6980subevalvar(char *p, char *varname, int strloc, int subtype,
7026 int startloc, int varflags, int flag, struct strlist *var_str_list) 6981 int startloc, int varflags, int flag)
7027{ 6982{
7028 struct nodelist *saveargbackq = argbackq; 6983 struct nodelist *saveargbackq = argbackq;
7029 int quotes = flag & QUOTES_ESC; 6984 int quotes = flag & QUOTES_ESC;
@@ -7041,8 +6996,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7041 // p, varname, strloc, subtype, startloc, varflags, quotes); 6996 // p, varname, strloc, subtype, startloc, varflags, quotes);
7042 6997
7043 argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? 6998 argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
7044 (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0), 6999 (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
7045 var_str_list); 7000 );
7046 STPUTC('\0', expdest); 7001 STPUTC('\0', expdest);
7047 argbackq = saveargbackq; 7002 argbackq = saveargbackq;
7048 startp = (char *)stackblock() + startloc; 7003 startp = (char *)stackblock() + startloc;
@@ -7319,7 +7274,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7319 * ash -c 'echo ${#1#}' name:'1=#' 7274 * ash -c 'echo ${#1#}' name:'1=#'
7320 */ 7275 */
7321static NOINLINE ssize_t 7276static NOINLINE ssize_t
7322varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp) 7277varvalue(char *name, int varflags, int flags, int *quotedp)
7323{ 7278{
7324 const char *p; 7279 const char *p;
7325 int num; 7280 int num;
@@ -7411,31 +7366,6 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int
7411 goto value; 7366 goto value;
7412 default: 7367 default:
7413 /* NB: name has form "VAR=..." */ 7368 /* NB: name has form "VAR=..." */
7414
7415 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
7416 * which should be considered before we check variables. */
7417 if (var_str_list) {
7418 unsigned name_len = (strchrnul(name, '=') - name) + 1;
7419 p = NULL;
7420 do {
7421 char *str, *eq;
7422 str = var_str_list->text;
7423 eq = strchr(str, '=');
7424 if (!eq) /* stop at first non-assignment */
7425 break;
7426 eq++;
7427 if (name_len == (unsigned)(eq - str)
7428 && strncmp(str, name, name_len) == 0
7429 ) {
7430 p = eq;
7431 /* goto value; - WRONG! */
7432 /* think "A=1 A=2 B=$A" */
7433 }
7434 var_str_list = var_str_list->next;
7435 } while (var_str_list);
7436 if (p)
7437 goto value;
7438 }
7439 p = lookupvar(name); 7369 p = lookupvar(name);
7440 value: 7370 value:
7441 if (!p) 7371 if (!p)
@@ -7465,7 +7395,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int
7465 * input string. 7395 * input string.
7466 */ 7396 */
7467static char * 7397static char *
7468evalvar(char *p, int flag, struct strlist *var_str_list) 7398evalvar(char *p, int flag)
7469{ 7399{
7470 char varflags; 7400 char varflags;
7471 char subtype; 7401 char subtype;
@@ -7489,7 +7419,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
7489 p = strchr(p, '=') + 1; //TODO: use var_end(p)? 7419 p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7490 7420
7491 again: 7421 again:
7492 varlen = varvalue(var, varflags, flag, var_str_list, &quoted); 7422 varlen = varvalue(var, varflags, flag, &quoted);
7493 if (varflags & VSNUL) 7423 if (varflags & VSNUL)
7494 varlen--; 7424 varlen--;
7495 7425
@@ -7503,8 +7433,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
7503 if (varlen < 0) { 7433 if (varlen < 0) {
7504 argstr( 7434 argstr(
7505 p, 7435 p,
7506 flag | EXP_TILDE | EXP_WORD, 7436 flag | EXP_TILDE | EXP_WORD
7507 var_str_list
7508 ); 7437 );
7509 goto end; 7438 goto end;
7510 } 7439 }
@@ -7516,7 +7445,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
7516 goto record; 7445 goto record;
7517 7446
7518 subevalvar(p, var, 0, subtype, startloc, varflags, 7447 subevalvar(p, var, 0, subtype, startloc, varflags,
7519 flag & ~QUOTES_ESC, var_str_list); 7448 flag & ~QUOTES_ESC);
7520 varflags &= ~VSNUL; 7449 varflags &= ~VSNUL;
7521 /* 7450 /*
7522 * Remove any recorded regions beyond 7451 * Remove any recorded regions beyond
@@ -7569,7 +7498,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
7569 STPUTC('\0', expdest); 7498 STPUTC('\0', expdest);
7570 patloc = expdest - (char *)stackblock(); 7499 patloc = expdest - (char *)stackblock();
7571 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, 7500 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7572 startloc, varflags, flag, var_str_list)) { 7501 startloc, varflags, flag)) {
7573 int amount = expdest - ( 7502 int amount = expdest - (
7574 (char *)stackblock() + patloc - 1 7503 (char *)stackblock() + patloc - 1
7575 ); 7504 );
@@ -7993,8 +7922,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
7993 argbackq = arg->narg.backquote; 7922 argbackq = arg->narg.backquote;
7994 STARTSTACKSTR(expdest); 7923 STARTSTACKSTR(expdest);
7995 TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag)); 7924 TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7996 argstr(arg->narg.text, flag, 7925 argstr(arg->narg.text, flag);
7997 /* var_str_list: */ arglist ? arglist->list : NULL);
7998 p = _STPUTC('\0', expdest); 7926 p = _STPUTC('\0', expdest);
7999 expdest = p - 1; 7927 expdest = p - 1;
8000 if (arglist == NULL) { 7928 if (arglist == NULL) {
@@ -8013,10 +7941,6 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
8013 exparg.lastp = &exparg.list; 7941 exparg.lastp = &exparg.list;
8014 expandmeta(exparg.list /*, flag*/); 7942 expandmeta(exparg.list /*, flag*/);
8015 } else { 7943 } else {
8016 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
8017 rmescapes(p, 0);
8018 TRACE(("expandarg: rmescapes:'%s'\n", p));
8019 }
8020 sp = stzalloc(sizeof(*sp)); 7944 sp = stzalloc(sizeof(*sp));
8021 sp->text = p; 7945 sp->text = p;
8022 *exparg.lastp = sp; 7946 *exparg.lastp = sp;
@@ -8065,8 +7989,7 @@ casematch(union node *pattern, char *val)
8065 setstackmark(&smark); 7989 setstackmark(&smark);
8066 argbackq = pattern->narg.backquote; 7990 argbackq = pattern->narg.backquote;
8067 STARTSTACKSTR(expdest); 7991 STARTSTACKSTR(expdest);
8068 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE, 7992 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
8069 /* var_str_list: */ NULL);
8070 STACKSTRNUL(expdest); 7993 STACKSTRNUL(expdest);
8071 ifsfree(); 7994 ifsfree();
8072 result = patmatch(stackblock(), val); 7995 result = patmatch(stackblock(), val);
@@ -8144,7 +8067,7 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */
8144 8067
8145 8068
8146static void 8069static void
8147tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) 8070tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8148{ 8071{
8149#if ENABLE_FEATURE_SH_STANDALONE 8072#if ENABLE_FEATURE_SH_STANDALONE
8150 if (applet_no >= 0) { 8073 if (applet_no >= 0) {
@@ -8152,6 +8075,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **
8152 clearenv(); 8075 clearenv();
8153 while (*envp) 8076 while (*envp)
8154 putenv(*envp++); 8077 putenv(*envp++);
8078 popredir(/*drop:*/ 1, /*restore:*/ 0);
8155 run_applet_no_and_exit(applet_no, cmd, argv); 8079 run_applet_no_and_exit(applet_no, cmd, argv);
8156 } 8080 }
8157 /* re-exec ourselves with the new arguments */ 8081 /* re-exec ourselves with the new arguments */
@@ -8169,7 +8093,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **
8169#else 8093#else
8170 execve(cmd, argv, envp); 8094 execve(cmd, argv, envp);
8171#endif 8095#endif
8172 if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) { 8096 if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8173 /* Run "cmd" as a shell script: 8097 /* Run "cmd" as a shell script:
8174 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html 8098 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8175 * "If the execve() function fails with ENOEXEC, the shell 8099 * "If the execve() function fails with ENOEXEC, the shell
@@ -8186,8 +8110,8 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **
8186 * message and exit code 126. For one, this prevents attempts 8110 * message and exit code 126. For one, this prevents attempts
8187 * to interpret foreign ELF binaries as shell scripts. 8111 * to interpret foreign ELF binaries as shell scripts.
8188 */ 8112 */
8189 argv[0] = cmd; 8113 argv[0] = (char*) cmd;
8190 cmd = (char*) bb_busybox_exec_path; 8114 cmd = bb_busybox_exec_path;
8191 /* NB: this is only possible because all callers of shellexec() 8115 /* NB: this is only possible because all callers of shellexec()
8192 * ensure that the argv[-1] slot exists! 8116 * ensure that the argv[-1] slot exists!
8193 */ 8117 */
@@ -8810,10 +8734,6 @@ static int nodeptrsize;
8810static char **nodeptr; 8734static char **nodeptr;
8811#endif 8735#endif
8812 8736
8813/* flags in argument to evaltree */
8814#define EV_EXIT 01 /* exit after evaluating tree */
8815#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
8816
8817static const uint8_t nodesize[N_NUMBER] ALIGN1 = { 8737static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8818 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)), 8738 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
8819 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)), 8739 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
@@ -9336,11 +9256,6 @@ evaltree(union node *n, int flags)
9336 return exitstatus; 9256 return exitstatus;
9337} 9257}
9338 9258
9339#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
9340static
9341#endif
9342int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
9343
9344static int 9259static int
9345skiploop(void) 9260skiploop(void)
9346{ 9261{
@@ -9699,27 +9614,57 @@ optschanged(void)
9699#endif 9614#endif
9700} 9615}
9701 9616
9702static struct localvar *localvars; 9617struct localvar_list {
9618 struct localvar_list *next;
9619 struct localvar *lv;
9620};
9621
9622static struct localvar_list *localvar_stack;
9703 9623
9704/* 9624/*
9705 * Called after a function returns. 9625 * Called after a function returns.
9706 * Interrupts must be off. 9626 * Interrupts must be off.
9707 */ 9627 */
9708static void 9628static void
9709poplocalvars(void) 9629poplocalvars(int keep)
9710{ 9630{
9711 struct localvar *lvp; 9631 struct localvar_list *ll;
9632 struct localvar *lvp, *next;
9712 struct var *vp; 9633 struct var *vp;
9713 9634
9714 while ((lvp = localvars) != NULL) { 9635 INT_OFF;
9715 localvars = lvp->next; 9636 ll = localvar_stack;
9637 localvar_stack = ll->next;
9638
9639 next = ll->lv;
9640 free(ll);
9641
9642 while ((lvp = next) != NULL) {
9643 next = lvp->next;
9716 vp = lvp->vp; 9644 vp = lvp->vp;
9717 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-")); 9645 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9718 if (vp == NULL) { /* $- saved */ 9646 if (keep) {
9647 int bits = VSTRFIXED;
9648
9649 if (lvp->flags != VUNSET) {
9650 if (vp->var_text == lvp->text)
9651 bits |= VTEXTFIXED;
9652 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9653 free((char*)lvp->text);
9654 }
9655
9656 vp->flags &= ~bits;
9657 vp->flags |= (lvp->flags & bits);
9658
9659 if ((vp->flags &
9660 (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9661 unsetvar(vp->var_text);
9662 } else if (vp == NULL) { /* $- saved */
9719 memcpy(optlist, lvp->text, sizeof(optlist)); 9663 memcpy(optlist, lvp->text, sizeof(optlist));
9720 free((char*)lvp->text); 9664 free((char*)lvp->text);
9721 optschanged(); 9665 optschanged();
9722 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 9666 } else if (lvp->flags == VUNSET) {
9667 vp->flags &= ~(VSTRFIXED|VREADONLY);
9723 unsetvar(vp->var_text); 9668 unsetvar(vp->var_text);
9724 } else { 9669 } else {
9725 if (vp->var_func) 9670 if (vp->var_func)
@@ -9731,19 +9676,43 @@ poplocalvars(void)
9731 } 9676 }
9732 free(lvp); 9677 free(lvp);
9733 } 9678 }
9679 INT_ON;
9680}
9681
9682/*
9683 * Create a new localvar environment.
9684 */
9685static struct localvar_list *
9686pushlocalvars(void)
9687{
9688 struct localvar_list *ll;
9689
9690 INT_OFF;
9691 ll = ckzalloc(sizeof(*ll));
9692 /*ll->lv = NULL; - zalloc did it */
9693 ll->next = localvar_stack;
9694 localvar_stack = ll;
9695 INT_ON;
9696
9697 return ll->next;
9698}
9699
9700static void
9701unwindlocalvars(struct localvar_list *stop)
9702{
9703 while (localvar_stack != stop)
9704 poplocalvars(0);
9734} 9705}
9735 9706
9736static int 9707static int
9737evalfun(struct funcnode *func, int argc, char **argv, int flags) 9708evalfun(struct funcnode *func, int argc, char **argv, int flags)
9738{ 9709{
9739 volatile struct shparam saveparam; 9710 volatile struct shparam saveparam;
9740 struct localvar *volatile savelocalvars;
9741 struct jmploc *volatile savehandler; 9711 struct jmploc *volatile savehandler;
9742 struct jmploc jmploc; 9712 struct jmploc jmploc;
9743 int e; 9713 int e;
9744 9714
9745 saveparam = shellparam; 9715 saveparam = shellparam;
9746 savelocalvars = localvars;
9747 savehandler = exception_handler; 9716 savehandler = exception_handler;
9748 e = setjmp(jmploc.loc); 9717 e = setjmp(jmploc.loc);
9749 if (e) { 9718 if (e) {
@@ -9751,7 +9720,6 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
9751 } 9720 }
9752 INT_OFF; 9721 INT_OFF;
9753 exception_handler = &jmploc; 9722 exception_handler = &jmploc;
9754 localvars = NULL;
9755 shellparam.malloced = 0; 9723 shellparam.malloced = 0;
9756 func->count++; 9724 func->count++;
9757 funcnest++; 9725 funcnest++;
@@ -9762,13 +9730,13 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
9762 shellparam.optind = 1; 9730 shellparam.optind = 1;
9763 shellparam.optoff = -1; 9731 shellparam.optoff = -1;
9764#endif 9732#endif
9733 pushlocalvars();
9765 evaltree(func->n.narg.next, flags & EV_TESTED); 9734 evaltree(func->n.narg.next, flags & EV_TESTED);
9735 poplocalvars(0);
9766 funcdone: 9736 funcdone:
9767 INT_OFF; 9737 INT_OFF;
9768 funcnest--; 9738 funcnest--;
9769 freefunc(func); 9739 freefunc(func);
9770 poplocalvars();
9771 localvars = savelocalvars;
9772 freeparam(&shellparam); 9740 freeparam(&shellparam);
9773 shellparam = saveparam; 9741 shellparam = saveparam;
9774 exception_handler = savehandler; 9742 exception_handler = savehandler;
@@ -9797,7 +9765,7 @@ mklocal(char *name)
9797 * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x 9765 * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9798 * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x 9766 * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9799 */ 9767 */
9800 lvp = localvars; 9768 lvp = localvar_stack->lv;
9801 while (lvp) { 9769 while (lvp) {
9802 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) { 9770 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9803 if (eq) 9771 if (eq)
@@ -9822,10 +9790,9 @@ mklocal(char *name)
9822 if (vp == NULL) { 9790 if (vp == NULL) {
9823 /* variable did not exist yet */ 9791 /* variable did not exist yet */
9824 if (eq) 9792 if (eq)
9825 setvareq(name, VSTRFIXED); 9793 vp = setvareq(name, VSTRFIXED);
9826 else 9794 else
9827 setvar(name, NULL, VSTRFIXED); 9795 vp = setvar(name, NULL, VSTRFIXED);
9828 vp = *vpp; /* the new variable */
9829 lvp->flags = VUNSET; 9796 lvp->flags = VUNSET;
9830 } else { 9797 } else {
9831 lvp->text = vp->var_text; 9798 lvp->text = vp->var_text;
@@ -9842,8 +9809,8 @@ mklocal(char *name)
9842 } 9809 }
9843 } 9810 }
9844 lvp->vp = vp; 9811 lvp->vp = vp;
9845 lvp->next = localvars; 9812 lvp->next = localvar_stack->lv;
9846 localvars = lvp; 9813 localvar_stack->lv = lvp;
9847 ret: 9814 ret:
9848 INT_ON; 9815 INT_ON;
9849} 9816}
@@ -9856,7 +9823,7 @@ localcmd(int argc UNUSED_PARAM, char **argv)
9856{ 9823{
9857 char *name; 9824 char *name;
9858 9825
9859 if (!funcnest) 9826 if (!localvar_stack)
9860 ash_msg_and_raise_error("not in a function"); 9827 ash_msg_and_raise_error("not in a function");
9861 9828
9862 argv = argptr; 9829 argv = argptr;
@@ -10025,7 +9992,7 @@ static const struct builtincmd builtintab[] = {
10025#if ENABLE_FEATURE_SH_MATH 9992#if ENABLE_FEATURE_SH_MATH
10026 { BUILTIN_NOSPEC "let" , letcmd }, 9993 { BUILTIN_NOSPEC "let" , letcmd },
10027#endif 9994#endif
10028 { BUILTIN_ASSIGN "local" , localcmd }, 9995 { BUILTIN_SPEC_REG_ASSG "local" , localcmd },
10029#if ENABLE_ASH_PRINTF 9996#if ENABLE_ASH_PRINTF
10030 { BUILTIN_REGULAR "printf" , printfcmd }, 9997 { BUILTIN_REGULAR "printf" , printfcmd },
10031#endif 9998#endif
@@ -10115,6 +10082,7 @@ evalcommand(union node *cmd, int flags)
10115 static const struct builtincmd null_bltin = { 10082 static const struct builtincmd null_bltin = {
10116 "\0\0", bltincmd /* why three NULs? */ 10083 "\0\0", bltincmd /* why three NULs? */
10117 }; 10084 };
10085 struct localvar_list *localvar_stop;
10118 struct stackmark smark; 10086 struct stackmark smark;
10119 union node *argp; 10087 union node *argp;
10120 struct arglist arglist; 10088 struct arglist arglist;
@@ -10136,6 +10104,7 @@ evalcommand(union node *cmd, int flags)
10136 /* First expand the arguments. */ 10104 /* First expand the arguments. */
10137 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); 10105 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10138 setstackmark(&smark); 10106 setstackmark(&smark);
10107 localvar_stop = pushlocalvars();
10139 back_exitstatus = 0; 10108 back_exitstatus = 0;
10140 10109
10141 cmdentry.cmdtype = CMDBUILTIN; 10110 cmdentry.cmdtype = CMDBUILTIN;
@@ -10189,6 +10158,8 @@ evalcommand(union node *cmd, int flags)
10189 spp = varlist.lastp; 10158 spp = varlist.lastp;
10190 expandarg(argp, &varlist, EXP_VARTILDE); 10159 expandarg(argp, &varlist, EXP_VARTILDE);
10191 10160
10161 mklocal((*spp)->text);
10162
10192 /* 10163 /*
10193 * Modify the command lookup path, if a PATH= assignment 10164 * Modify the command lookup path, if a PATH= assignment
10194 * is present 10165 * is present
@@ -10354,17 +10325,12 @@ evalcommand(union node *cmd, int flags)
10354 /* NOTREACHED */ 10325 /* NOTREACHED */
10355 } /* default */ 10326 } /* default */
10356 case CMDBUILTIN: 10327 case CMDBUILTIN:
10357 cmdenviron = varlist.list; 10328 if (spclbltin > 0 || argc == 0) {
10358 if (cmdenviron) { 10329 poplocalvars(1);
10359 struct strlist *list = cmdenviron; 10330 if (cmd_is_exec && argc > 1)
10360 int i = VNOSET; 10331 listsetvar(varlist.list, VEXPORT);
10361 if (spclbltin > 0 || argc == 0) {
10362 i = 0;
10363 if (cmd_is_exec && argc > 1)
10364 i = VEXPORT;
10365 }
10366 listsetvar(list, i);
10367 } 10332 }
10333
10368 /* Tight loop with builtins only: 10334 /* Tight loop with builtins only:
10369 * "while kill -0 $child; do true; done" 10335 * "while kill -0 $child; do true; done"
10370 * will never exit even if $child died, unless we do this 10336 * will never exit even if $child died, unless we do this
@@ -10382,7 +10348,7 @@ evalcommand(union node *cmd, int flags)
10382 goto readstatus; 10348 goto readstatus;
10383 10349
10384 case CMDFUNCTION: 10350 case CMDFUNCTION:
10385 listsetvar(varlist.list, 0); 10351 poplocalvars(1);
10386 /* See above for the rationale */ 10352 /* See above for the rationale */
10387 dowait(DOWAIT_NONBLOCK, NULL); 10353 dowait(DOWAIT_NONBLOCK, NULL);
10388 if (evalfun(cmdentry.u.func, argc, argv, flags)) 10354 if (evalfun(cmdentry.u.func, argc, argv, flags))
@@ -10395,6 +10361,7 @@ evalcommand(union node *cmd, int flags)
10395 out: 10361 out:
10396 if (cmd->ncmd.redirect) 10362 if (cmd->ncmd.redirect)
10397 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec); 10363 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
10364 unwindlocalvars(localvar_stop);
10398 if (lastarg) { 10365 if (lastarg) {
10399 /* dsl: I think this is intended to be used to support 10366 /* dsl: I think this is intended to be used to support
10400 * '_' in 'vi' command mode during line editing... 10367 * '_' in 'vi' command mode during line editing...
@@ -13051,6 +13018,12 @@ expandstr(const char *ps)
13051 return stackblock(); 13018 return stackblock();
13052} 13019}
13053 13020
13021static inline int
13022parser_eof(void)
13023{
13024 return tokpushback && lasttoken == TEOF;
13025}
13026
13054/* 13027/*
13055 * Execute a command or commands contained in a string. 13028 * Execute a command or commands contained in a string.
13056 */ 13029 */
@@ -13086,7 +13059,7 @@ evalstring(char *s, int flags)
13086 while ((n = parsecmd(0)) != NODE_EOF) { 13059 while ((n = parsecmd(0)) != NODE_EOF) {
13087 int i; 13060 int i;
13088 13061
13089 i = evaltree(n, flags); 13062 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13090 if (n) 13063 if (n)
13091 status = i; 13064 status = i;
13092 popstackmark(&smark); 13065 popstackmark(&smark);
@@ -13237,11 +13210,12 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13237 char *fullname; 13210 char *fullname;
13238 char **argv; 13211 char **argv;
13239 char *args_need_save; 13212 char *args_need_save;
13240 struct strlist *sp;
13241 volatile struct shparam saveparam; 13213 volatile struct shparam saveparam;
13242 13214
13243 for (sp = cmdenviron; sp; sp = sp->next) 13215//???
13244 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED); 13216// struct strlist *sp;
13217// for (sp = cmdenviron; sp; sp = sp->next)
13218// setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13245 13219
13246 nextopt(nullstr); /* handle possible "--" */ 13220 nextopt(nullstr); /* handle possible "--" */
13247 argv = argptr; 13221 argv = argptr;
@@ -13588,13 +13562,18 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13588 return 0; 13562 return 0;
13589 } 13563 }
13590 13564
13565 /* Why the second check?
13566 * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13567 * In this case, NUM is signal no, not an action.
13568 */
13591 action = NULL; 13569 action = NULL;
13592 if (ap[1]) 13570 if (ap[1] && !is_number(ap[0]))
13593 action = *ap++; 13571 action = *ap++;
13572
13594 exitcode = 0; 13573 exitcode = 0;
13595 while (*ap) { 13574 while (*ap) {
13596 signo = get_signum(*ap); 13575 signo = get_signum(*ap);
13597 if (signo < 0 || signo >= NSIG) { 13576 if (signo < 0) {
13598 /* Mimic bash message exactly */ 13577 /* Mimic bash message exactly */
13599 ash_msg("%s: invalid signal specification", *ap); 13578 ash_msg("%s: invalid signal specification", *ap);
13600 exitcode = 1; 13579 exitcode = 1;
@@ -13752,7 +13731,6 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13752 char **ap; 13731 char **ap;
13753 int i; 13732 int i;
13754 int flag = 0; 13733 int flag = 0;
13755 int ret = 0;
13756 13734
13757 while ((i = nextopt("vf")) != 0) { 13735 while ((i = nextopt("vf")) != 0) {
13758 flag = i; 13736 flag = i;
@@ -13760,15 +13738,13 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13760 13738
13761 for (ap = argptr; *ap; ap++) { 13739 for (ap = argptr; *ap; ap++) {
13762 if (flag != 'f') { 13740 if (flag != 'f') {
13763 i = unsetvar(*ap); 13741 unsetvar(*ap);
13764 ret |= i; 13742 continue;
13765 if (!(i & 2))
13766 continue;
13767 } 13743 }
13768 if (flag != 'v') 13744 if (flag != 'v')
13769 unsetfunc(*ap); 13745 unsetfunc(*ap);
13770 } 13746 }
13771 return ret & 1; 13747 return 0;
13772} 13748}
13773 13749
13774static const unsigned char timescmd_str[] ALIGN1 = { 13750static const unsigned char timescmd_str[] ALIGN1 = {
@@ -14250,6 +14226,9 @@ reset(void)
14250 /* from redir.c: */ 14226 /* from redir.c: */
14251 while (redirlist) 14227 while (redirlist)
14252 popredir(/*drop:*/ 0, /*restore:*/ 0); 14228 popredir(/*drop:*/ 0, /*restore:*/ 0);
14229
14230 /* from var.c: */
14231 unwindlocalvars(NULL);
14253} 14232}
14254 14233
14255#if PROFILE 14234#if PROFILE
@@ -14386,7 +14365,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
14386 // if (!sflag) g_parsefile->pf_fd = -1; 14365 // if (!sflag) g_parsefile->pf_fd = -1;
14387 // ^^ not necessary since now we special-case fd 0 14366 // ^^ not necessary since now we special-case fd 0
14388 // in is_hidden_fd() to not be considered "hidden fd" 14367 // in is_hidden_fd() to not be considered "hidden fd"
14389 evalstring(minusc, 0); 14368 evalstring(minusc, sflag ? 0 : EV_EXIT);
14390 } 14369 }
14391 14370
14392 if (sflag || minusc == NULL) { 14371 if (sflag || minusc == NULL) {