diff options
author | Ron Yorston <rmy@pobox.com> | 2021-10-13 14:37:51 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-10-13 14:37:51 +0100 |
commit | 0ecf1aea459571b48dc68ddc2b7b9265740fa960 (patch) | |
tree | 491d6184a44b8b525a4ca35759d622aecd7f6344 /shell/ash.c | |
parent | 4859ddcb20616718efbea12c6bf8b27c469b68de (diff) | |
parent | aaf3d5ba74c5da97ff80b61f30cb8dd225d39096 (diff) | |
download | busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.gz busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.bz2 busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 68 |
1 files changed, 31 insertions, 37 deletions
diff --git a/shell/ash.c b/shell/ash.c index 9214982c1..98da20f8a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -351,19 +351,6 @@ typedef long arith_t; | |||
351 | # error "Do not even bother, ash will not run on NOMMU machine" | 351 | # error "Do not even bother, ash will not run on NOMMU machine" |
352 | #endif | 352 | #endif |
353 | 353 | ||
354 | /* We use a trick to have more optimized code (fewer pointer reloads): | ||
355 | * ash.c: extern struct globals *const ash_ptr_to_globals; | ||
356 | * ash_ptr_hack.c: struct globals *ash_ptr_to_globals; | ||
357 | * This way, compiler in ash.c knows the pointer can not change. | ||
358 | * | ||
359 | * However, this may break on weird arches or toolchains. In this case, | ||
360 | * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable | ||
361 | * this optimization. | ||
362 | */ | ||
363 | #ifndef BB_GLOBAL_CONST | ||
364 | # define BB_GLOBAL_CONST const | ||
365 | #endif | ||
366 | |||
367 | #if ENABLE_PLATFORM_MINGW32 | 354 | #if ENABLE_PLATFORM_MINGW32 |
368 | # define FORKSHELL_DEBUG 0 | 355 | # define FORKSHELL_DEBUG 0 |
369 | 356 | ||
@@ -693,8 +680,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
693 | #endif | 680 | #endif |
694 | 681 | ||
695 | #define INIT_G_misc() do { \ | 682 | #define INIT_G_misc() do { \ |
696 | (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ | 683 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \ |
697 | barrier(); \ | ||
698 | savestatus = -1; \ | 684 | savestatus = -1; \ |
699 | curdir = nullstr; \ | 685 | curdir = nullstr; \ |
700 | physdir = nullstr; \ | 686 | physdir = nullstr; \ |
@@ -1783,8 +1769,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack; | |||
1783 | #define g_stacknleft (G_memstack.g_stacknleft) | 1769 | #define g_stacknleft (G_memstack.g_stacknleft) |
1784 | #define stackbase (G_memstack.stackbase ) | 1770 | #define stackbase (G_memstack.stackbase ) |
1785 | #define INIT_G_memstack() do { \ | 1771 | #define INIT_G_memstack() do { \ |
1786 | (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \ | 1772 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \ |
1787 | barrier(); \ | ||
1788 | g_stackp = &stackbase; \ | 1773 | g_stackp = &stackbase; \ |
1789 | g_stacknxt = stackbase.space; \ | 1774 | g_stacknxt = stackbase.space; \ |
1790 | g_stacknleft = MINSIZE; \ | 1775 | g_stacknleft = MINSIZE; \ |
@@ -2445,8 +2430,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; | |||
2445 | #endif | 2430 | #endif |
2446 | #define INIT_G_var() do { \ | 2431 | #define INIT_G_var() do { \ |
2447 | unsigned i; \ | 2432 | unsigned i; \ |
2448 | (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \ | 2433 | XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \ |
2449 | barrier(); \ | ||
2450 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ | 2434 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ |
2451 | varinit[i].flags = varinit_data[i].flags; \ | 2435 | varinit[i].flags = varinit_data[i].flags; \ |
2452 | varinit[i].var_text = varinit_data[i].var_text; \ | 2436 | varinit[i].var_text = varinit_data[i].var_text; \ |
@@ -7840,14 +7824,19 @@ subevalvar(char *start, char *str, int strloc, | |||
7840 | if ((unsigned)len > (orig_len - pos)) | 7824 | if ((unsigned)len > (orig_len - pos)) |
7841 | len = orig_len - pos; | 7825 | len = orig_len - pos; |
7842 | 7826 | ||
7843 | for (vstr = startp; pos; vstr++, pos--) { | 7827 | if (!quotes) { |
7844 | if (quotes && (unsigned char)*vstr == CTLESC) | 7828 | loc = mempcpy(startp, startp + pos, len); |
7829 | } else { | ||
7830 | for (vstr = startp; pos != 0; pos--) { | ||
7831 | if ((unsigned char)*vstr == CTLESC) | ||
7832 | vstr++; | ||
7845 | vstr++; | 7833 | vstr++; |
7846 | } | 7834 | } |
7847 | for (loc = startp; len; len--) { | 7835 | for (loc = startp; len != 0; len--) { |
7848 | if (quotes && (unsigned char)*vstr == CTLESC) | 7836 | if ((unsigned char)*vstr == CTLESC) |
7837 | *loc++ = *vstr++; | ||
7849 | *loc++ = *vstr++; | 7838 | *loc++ = *vstr++; |
7850 | *loc++ = *vstr++; | 7839 | } |
7851 | } | 7840 | } |
7852 | *loc = '\0'; | 7841 | *loc = '\0'; |
7853 | goto out; | 7842 | goto out; |
@@ -7901,7 +7890,7 @@ subevalvar(char *start, char *str, int strloc, | |||
7901 | #if BASH_PATTERN_SUBST | 7890 | #if BASH_PATTERN_SUBST |
7902 | workloc = expdest - (char *)stackblock(); | 7891 | workloc = expdest - (char *)stackblock(); |
7903 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 7892 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
7904 | size_t no_meta_len; | 7893 | size_t no_meta_len, first_escaped; |
7905 | int len; | 7894 | int len; |
7906 | char *idx, *end; | 7895 | char *idx, *end; |
7907 | 7896 | ||
@@ -7919,28 +7908,34 @@ subevalvar(char *start, char *str, int strloc, | |||
7919 | if (str[0] == '\0') | 7908 | if (str[0] == '\0') |
7920 | goto out1; | 7909 | goto out1; |
7921 | 7910 | ||
7922 | no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str); | 7911 | first_escaped = (str[0] == '\\' && str[1]); |
7912 | /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" | ||
7913 | * as literal too (as it is semi-common, and easy to accomodate | ||
7914 | * by just using str + 1). | ||
7915 | */ | ||
7916 | no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str); | ||
7923 | len = 0; | 7917 | len = 0; |
7924 | idx = startp; | 7918 | idx = startp; |
7925 | end = str - 1; | 7919 | end = str - 1; |
7926 | while (idx <= end) { | 7920 | while (idx <= end) { |
7927 | try_to_match: | 7921 | try_to_match: |
7928 | if (no_meta_len == 0) { | 7922 | if (no_meta_len == 0) { |
7929 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ | 7923 | /* pattern has meta chars, have to glob */ |
7930 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); | 7924 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); |
7931 | } else { | 7925 | } else { |
7932 | /* Testcase for very slow replace (performs about 22k replaces): | 7926 | /* Testcase for very slow replace (performs about 22k replaces): |
7933 | * x=:::::::::::::::::::::: | 7927 | * x=:::::::::::::::::::::: |
7934 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 7928 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
7935 | * echo "${x//:/|}" | 7929 | * echo "${x//:/|}" |
7930 | * To test "first_escaped" logic, replace : with *. | ||
7936 | */ | 7931 | */ |
7937 | if (strncmp(rmesc, str, no_meta_len) != 0) | 7932 | if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0) |
7938 | goto no_match; | 7933 | goto no_match; |
7939 | loc = idx; | 7934 | loc = idx; |
7940 | if (!quotes) { | 7935 | if (!quotes) { |
7941 | loc += no_meta_len; | 7936 | loc += no_meta_len - first_escaped; |
7942 | } else { | 7937 | } else { |
7943 | size_t n = no_meta_len; | 7938 | size_t n = no_meta_len - first_escaped; |
7944 | do { | 7939 | do { |
7945 | if ((unsigned char)*loc == CTLESC) | 7940 | if ((unsigned char)*loc == CTLESC) |
7946 | loc++; | 7941 | loc++; |
@@ -11811,14 +11806,14 @@ static void freestrings(struct strpush *sp) | |||
11811 | INT_OFF; | 11806 | INT_OFF; |
11812 | do { | 11807 | do { |
11813 | struct strpush *psp; | 11808 | struct strpush *psp; |
11814 | 11809 | #if ENABLE_ASH_ALIAS | |
11815 | if (sp->ap) { | 11810 | if (sp->ap) { |
11816 | sp->ap->flag &= ~ALIASINUSE; | 11811 | sp->ap->flag &= ~ALIASINUSE; |
11817 | if (sp->ap->flag & ALIASDEAD) { | 11812 | if (sp->ap->flag & ALIASDEAD) { |
11818 | unalias(sp->ap->name); | 11813 | unalias(sp->ap->name); |
11819 | } | 11814 | } |
11820 | } | 11815 | } |
11821 | 11816 | #endif | |
11822 | psp = sp; | 11817 | psp = sp; |
11823 | sp = sp->spfree; | 11818 | sp = sp->spfree; |
11824 | 11819 | ||
@@ -15497,7 +15492,7 @@ init(void) | |||
15497 | 15492 | ||
15498 | 15493 | ||
15499 | //usage:#define ash_trivial_usage | 15494 | //usage:#define ash_trivial_usage |
15500 | //usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" | 15495 | //usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]" |
15501 | //////// comes from ^^^^^^^^^^optletters | 15496 | //////// comes from ^^^^^^^^^^optletters |
15502 | //usage:#define ash_full_usage "\n\n" | 15497 | //usage:#define ash_full_usage "\n\n" |
15503 | //usage: "Unix shell interpreter" | 15498 | //usage: "Unix shell interpreter" |
@@ -15764,13 +15759,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15764 | } | 15759 | } |
15765 | state2: | 15760 | state2: |
15766 | state = 3; | 15761 | state = 3; |
15767 | if ( | 15762 | if (iflag |
15768 | #if ENABLE_PLATFORM_POSIX | 15763 | #if ENABLE_PLATFORM_POSIX |
15769 | #ifndef linux | 15764 | #ifndef linux |
15770 | getuid() == geteuid() && getgid() == getegid() && | 15765 | && getuid() == geteuid() && getgid() == getegid() |
15771 | #endif | 15766 | #endif |
15772 | #endif | 15767 | #endif |
15773 | iflag | ||
15774 | ) { | 15768 | ) { |
15775 | const char *shinit = lookupvar("ENV"); | 15769 | const char *shinit = lookupvar("ENV"); |
15776 | if (shinit != NULL && *shinit != '\0') | 15770 | if (shinit != NULL && *shinit != '\0') |