diff options
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/shell/ash.c b/shell/ash.c index 2cee0c42f..308cc0273 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -193,6 +193,7 @@ | |||
193 | //config: "PS#" may contain volatile content, such as backquote commands. | 193 | //config: "PS#" may contain volatile content, such as backquote commands. |
194 | //config: This option recreates the prompt string from the environment | 194 | //config: This option recreates the prompt string from the environment |
195 | //config: variable each time it is displayed. | 195 | //config: variable each time it is displayed. |
196 | //config: | ||
196 | 197 | ||
197 | //usage:#define ash_trivial_usage NOUSAGE_STR | 198 | //usage:#define ash_trivial_usage NOUSAGE_STR |
198 | //usage:#define ash_full_usage "" | 199 | //usage:#define ash_full_usage "" |
@@ -4844,6 +4845,7 @@ clear_traps(void) | |||
4844 | INT_ON; | 4845 | INT_ON; |
4845 | } | 4846 | } |
4846 | } | 4847 | } |
4848 | may_have_traps = 0; | ||
4847 | } | 4849 | } |
4848 | 4850 | ||
4849 | /* Lives far away from here, needed for forkchild */ | 4851 | /* Lives far away from here, needed for forkchild */ |
@@ -6615,13 +6617,14 @@ parse_sub_pattern(char *arg, int inquotes) | |||
6615 | #endif /* ENABLE_ASH_BASH_COMPAT */ | 6617 | #endif /* ENABLE_ASH_BASH_COMPAT */ |
6616 | 6618 | ||
6617 | static const char * | 6619 | static const char * |
6618 | subevalvar(char *p, char *str, int strloc, int subtype, | 6620 | subevalvar(char *p, char *varname, int strloc, int subtype, |
6619 | int startloc, int varflags, int quotes, struct strlist *var_str_list) | 6621 | int startloc, int varflags, int quotes, struct strlist *var_str_list) |
6620 | { | 6622 | { |
6621 | struct nodelist *saveargbackq = argbackq; | 6623 | struct nodelist *saveargbackq = argbackq; |
6622 | char *startp; | 6624 | char *startp; |
6623 | char *loc; | 6625 | char *loc; |
6624 | char *rmesc, *rmescend; | 6626 | char *rmesc, *rmescend; |
6627 | char *str; | ||
6625 | IF_ASH_BASH_COMPAT(const char *repl = NULL;) | 6628 | IF_ASH_BASH_COMPAT(const char *repl = NULL;) |
6626 | IF_ASH_BASH_COMPAT(int pos, len, orig_len;) | 6629 | IF_ASH_BASH_COMPAT(int pos, len, orig_len;) |
6627 | int saveherefd = herefd; | 6630 | int saveherefd = herefd; |
@@ -6629,6 +6632,9 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6629 | int zero; | 6632 | int zero; |
6630 | char *(*scan)(char*, char*, char*, char*, int, int); | 6633 | char *(*scan)(char*, char*, char*, char*, int, int); |
6631 | 6634 | ||
6635 | //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d", | ||
6636 | // p, varname, strloc, subtype, startloc, varflags, quotes); | ||
6637 | |||
6632 | herefd = -1; | 6638 | herefd = -1; |
6633 | argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0, | 6639 | argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0, |
6634 | var_str_list); | 6640 | var_str_list); |
@@ -6639,11 +6645,15 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6639 | 6645 | ||
6640 | switch (subtype) { | 6646 | switch (subtype) { |
6641 | case VSASSIGN: | 6647 | case VSASSIGN: |
6642 | setvar(str, startp, 0); | 6648 | setvar(varname, startp, 0); |
6643 | amount = startp - expdest; | 6649 | amount = startp - expdest; |
6644 | STADJUST(amount, expdest); | 6650 | STADJUST(amount, expdest); |
6645 | return startp; | 6651 | return startp; |
6646 | 6652 | ||
6653 | case VSQUESTION: | ||
6654 | varunset(p, varname, startp, varflags); | ||
6655 | /* NOTREACHED */ | ||
6656 | |||
6647 | #if ENABLE_ASH_BASH_COMPAT | 6657 | #if ENABLE_ASH_BASH_COMPAT |
6648 | case VSSUBSTR: | 6658 | case VSSUBSTR: |
6649 | loc = str = stackblock() + strloc; | 6659 | loc = str = stackblock() + strloc; |
@@ -6704,11 +6714,8 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6704 | STADJUST(amount, expdest); | 6714 | STADJUST(amount, expdest); |
6705 | return loc; | 6715 | return loc; |
6706 | #endif | 6716 | #endif |
6707 | |||
6708 | case VSQUESTION: | ||
6709 | varunset(p, str, startp, varflags); | ||
6710 | /* NOTREACHED */ | ||
6711 | } | 6717 | } |
6718 | |||
6712 | resetloc = expdest - (char *)stackblock(); | 6719 | resetloc = expdest - (char *)stackblock(); |
6713 | 6720 | ||
6714 | /* We'll comeback here if we grow the stack while handling | 6721 | /* We'll comeback here if we grow the stack while handling |
@@ -6742,13 +6749,14 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6742 | 6749 | ||
6743 | if (!repl) { | 6750 | if (!repl) { |
6744 | repl = parse_sub_pattern(str, varflags & VSQUOTE); | 6751 | repl = parse_sub_pattern(str, varflags & VSQUOTE); |
6752 | //bb_error_msg("repl:'%s'", repl); | ||
6745 | if (!repl) | 6753 | if (!repl) |
6746 | repl = nullstr; | 6754 | repl = nullstr; |
6747 | } | 6755 | } |
6748 | 6756 | ||
6749 | /* If there's no pattern to match, return the expansion unmolested */ | 6757 | /* If there's no pattern to match, return the expansion unmolested */ |
6750 | if (str[0] == '\0') | 6758 | if (str[0] == '\0') |
6751 | return 0; | 6759 | return NULL; |
6752 | 6760 | ||
6753 | len = 0; | 6761 | len = 0; |
6754 | idx = startp; | 6762 | idx = startp; |
@@ -6756,6 +6764,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6756 | while (idx < end) { | 6764 | while (idx < end) { |
6757 | try_to_match: | 6765 | try_to_match: |
6758 | loc = scanright(idx, rmesc, rmescend, str, quotes, 1); | 6766 | loc = scanright(idx, rmesc, rmescend, str, quotes, 1); |
6767 | //bb_error_msg("scanright('%s'):'%s'", str, loc); | ||
6759 | if (!loc) { | 6768 | if (!loc) { |
6760 | /* No match, advance */ | 6769 | /* No match, advance */ |
6761 | char *restart_detect = stackblock(); | 6770 | char *restart_detect = stackblock(); |
@@ -6794,6 +6803,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6794 | idx = loc; | 6803 | idx = loc; |
6795 | } | 6804 | } |
6796 | 6805 | ||
6806 | //bb_error_msg("repl:'%s'", repl); | ||
6797 | for (loc = (char*)repl; *loc; loc++) { | 6807 | for (loc = (char*)repl; *loc; loc++) { |
6798 | char *restart_detect = stackblock(); | 6808 | char *restart_detect = stackblock(); |
6799 | if (quotes && *loc == '\\') { | 6809 | if (quotes && *loc == '\\') { |
@@ -6829,6 +6839,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6829 | STPUTC('\0', expdest); | 6839 | STPUTC('\0', expdest); |
6830 | startp = (char *)stackblock() + startloc; | 6840 | startp = (char *)stackblock() + startloc; |
6831 | memmove(startp, (char *)stackblock() + workloc, len + 1); | 6841 | memmove(startp, (char *)stackblock() + workloc, len + 1); |
6842 | //bb_error_msg("startp:'%s'", startp); | ||
6832 | amount = expdest - (startp + len); | 6843 | amount = expdest - (startp + len); |
6833 | STADJUST(-amount, expdest); | 6844 | STADJUST(-amount, expdest); |
6834 | return startp; | 6845 | return startp; |
@@ -7129,7 +7140,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) | |||
7129 | */ | 7140 | */ |
7130 | STPUTC('\0', expdest); | 7141 | STPUTC('\0', expdest); |
7131 | patloc = expdest - (char *)stackblock(); | 7142 | patloc = expdest - (char *)stackblock(); |
7132 | if (NULL == subevalvar(p, /* str: */ NULL, patloc, subtype, | 7143 | if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, |
7133 | startloc, varflags, | 7144 | startloc, varflags, |
7134 | //TODO: | EXP_REDIR too? All other such places do it too | 7145 | //TODO: | EXP_REDIR too? All other such places do it too |
7135 | /* quotes: */ flags & (EXP_FULL | EXP_CASE), | 7146 | /* quotes: */ flags & (EXP_FULL | EXP_CASE), |
@@ -11577,8 +11588,11 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11577 | USTPUTC('\\', out); | 11588 | USTPUTC('\\', out); |
11578 | } | 11589 | } |
11579 | #endif | 11590 | #endif |
11580 | if (dblquote && c != '\\' | 11591 | /* Backslash is retained if we are in "str" and next char isn't special */ |
11581 | && c != '`' && c != '$' | 11592 | if (dblquote |
11593 | && c != '\\' | ||
11594 | && c != '`' | ||
11595 | && c != '$' | ||
11582 | && (c != '"' || eofmark != NULL) | 11596 | && (c != '"' || eofmark != NULL) |
11583 | ) { | 11597 | ) { |
11584 | USTPUTC(CTLESC, out); | 11598 | USTPUTC(CTLESC, out); |
@@ -11650,7 +11664,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11650 | } else { | 11664 | } else { |
11651 | /* | 11665 | /* |
11652 | * unbalanced parens | 11666 | * unbalanced parens |
11653 | * (don't 2nd guess - no error) | 11667 | * (don't 2nd guess - no error) |
11654 | */ | 11668 | */ |
11655 | pungetc(); | 11669 | pungetc(); |
11656 | USTPUTC(')', out); | 11670 | USTPUTC(')', out); |
@@ -11678,7 +11692,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11678 | } | 11692 | } |
11679 | IF_ASH_ALIAS(if (c != PEOA)) | 11693 | IF_ASH_ALIAS(if (c != PEOA)) |
11680 | USTPUTC(c, out); | 11694 | USTPUTC(c, out); |
11681 | |||
11682 | } | 11695 | } |
11683 | c = pgetc_fast(); | 11696 | c = pgetc_fast(); |
11684 | } /* for (;;) */ | 11697 | } /* for (;;) */ |
@@ -11844,8 +11857,6 @@ parsesub: { | |||
11844 | unsigned char subtype; | 11857 | unsigned char subtype; |
11845 | int typeloc; | 11858 | int typeloc; |
11846 | int flags; | 11859 | int flags; |
11847 | char *p; | ||
11848 | static const char types[] ALIGN1 = "}-+?="; | ||
11849 | 11860 | ||
11850 | c = pgetc(); | 11861 | c = pgetc(); |
11851 | if (c > 255 /* PEOA or PEOF */ | 11862 | if (c > 255 /* PEOA or PEOF */ |
@@ -11858,7 +11869,8 @@ parsesub: { | |||
11858 | #endif | 11869 | #endif |
11859 | USTPUTC('$', out); | 11870 | USTPUTC('$', out); |
11860 | pungetc(); | 11871 | pungetc(); |
11861 | } else if (c == '(') { /* $(command) or $((arith)) */ | 11872 | } else if (c == '(') { |
11873 | /* $(command) or $((arith)) */ | ||
11862 | if (pgetc() == '(') { | 11874 | if (pgetc() == '(') { |
11863 | #if ENABLE_SH_MATH_SUPPORT | 11875 | #if ENABLE_SH_MATH_SUPPORT |
11864 | PARSEARITH(); | 11876 | PARSEARITH(); |
@@ -11870,6 +11882,7 @@ parsesub: { | |||
11870 | PARSEBACKQNEW(); | 11882 | PARSEBACKQNEW(); |
11871 | } | 11883 | } |
11872 | } else { | 11884 | } else { |
11885 | /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */ | ||
11873 | USTPUTC(CTLVAR, out); | 11886 | USTPUTC(CTLVAR, out); |
11874 | typeloc = out - (char *)stackblock(); | 11887 | typeloc = out - (char *)stackblock(); |
11875 | USTPUTC(VSNORMAL, out); | 11888 | USTPUTC(VSNORMAL, out); |
@@ -11879,76 +11892,85 @@ parsesub: { | |||
11879 | if (c == '#') { | 11892 | if (c == '#') { |
11880 | c = pgetc(); | 11893 | c = pgetc(); |
11881 | if (c == '}') | 11894 | if (c == '}') |
11882 | c = '#'; | 11895 | c = '#'; /* ${#} - same as $# */ |
11883 | else | 11896 | else |
11884 | subtype = VSLENGTH; | 11897 | subtype = VSLENGTH; /* ${#VAR} */ |
11885 | } else | 11898 | } else { |
11886 | subtype = 0; | 11899 | subtype = 0; |
11900 | } | ||
11887 | } | 11901 | } |
11888 | if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) { | 11902 | if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) { |
11903 | /* $[{[#]]NAME[}] */ | ||
11889 | do { | 11904 | do { |
11890 | STPUTC(c, out); | 11905 | STPUTC(c, out); |
11891 | c = pgetc(); | 11906 | c = pgetc(); |
11892 | } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c)); | 11907 | } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c)); |
11893 | } else if (isdigit(c)) { | 11908 | } else if (isdigit(c)) { |
11909 | /* $[{[#]]NUM[}] */ | ||
11894 | do { | 11910 | do { |
11895 | STPUTC(c, out); | 11911 | STPUTC(c, out); |
11896 | c = pgetc(); | 11912 | c = pgetc(); |
11897 | } while (isdigit(c)); | 11913 | } while (isdigit(c)); |
11898 | } else if (is_special(c)) { | 11914 | } else if (is_special(c)) { |
11915 | /* $[{[#]]<specialchar>[}] */ | ||
11899 | USTPUTC(c, out); | 11916 | USTPUTC(c, out); |
11900 | c = pgetc(); | 11917 | c = pgetc(); |
11901 | } else { | 11918 | } else { |
11902 | badsub: | 11919 | badsub: |
11903 | raise_error_syntax("bad substitution"); | 11920 | raise_error_syntax("bad substitution"); |
11904 | } | 11921 | } |
11905 | if (c != '}' && subtype == VSLENGTH) | 11922 | if (c != '}' && subtype == VSLENGTH) { |
11923 | /* ${#VAR didn't end with } */ | ||
11906 | goto badsub; | 11924 | goto badsub; |
11925 | } | ||
11907 | 11926 | ||
11908 | STPUTC('=', out); | 11927 | STPUTC('=', out); |
11909 | flags = 0; | 11928 | flags = 0; |
11910 | if (subtype == 0) { | 11929 | if (subtype == 0) { |
11930 | /* ${VAR...} but not $VAR or ${#VAR} */ | ||
11931 | /* c == first char after VAR */ | ||
11911 | switch (c) { | 11932 | switch (c) { |
11912 | case ':': | 11933 | case ':': |
11913 | c = pgetc(); | 11934 | c = pgetc(); |
11914 | #if ENABLE_ASH_BASH_COMPAT | 11935 | #if ENABLE_ASH_BASH_COMPAT |
11915 | if (c == ':' || c == '$' || isdigit(c)) { | 11936 | if (c == ':' || c == '$' || isdigit(c)) { |
11916 | pungetc(); | ||
11917 | subtype = VSSUBSTR; | 11937 | subtype = VSSUBSTR; |
11918 | break; | 11938 | pungetc(); |
11939 | break; /* "goto do_pungetc" is bigger (!) */ | ||
11919 | } | 11940 | } |
11920 | #endif | 11941 | #endif |
11921 | flags = VSNUL; | 11942 | flags = VSNUL; |
11922 | /*FALLTHROUGH*/ | 11943 | /*FALLTHROUGH*/ |
11923 | default: | 11944 | default: { |
11924 | p = strchr(types, c); | 11945 | static const char types[] ALIGN1 = "}-+?="; |
11946 | const char *p = strchr(types, c); | ||
11925 | if (p == NULL) | 11947 | if (p == NULL) |
11926 | goto badsub; | 11948 | goto badsub; |
11927 | subtype = p - types + VSNORMAL; | 11949 | subtype = p - types + VSNORMAL; |
11928 | break; | 11950 | break; |
11951 | } | ||
11929 | case '%': | 11952 | case '%': |
11930 | case '#': { | 11953 | case '#': { |
11931 | int cc = c; | 11954 | int cc = c; |
11932 | subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT; | 11955 | subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT); |
11933 | c = pgetc(); | 11956 | c = pgetc(); |
11934 | if (c == cc) | 11957 | if (c != cc) |
11935 | subtype++; | 11958 | goto do_pungetc; |
11936 | else | 11959 | subtype++; |
11937 | pungetc(); | ||
11938 | break; | 11960 | break; |
11939 | } | 11961 | } |
11940 | #if ENABLE_ASH_BASH_COMPAT | 11962 | #if ENABLE_ASH_BASH_COMPAT |
11941 | case '/': | 11963 | case '/': |
11942 | subtype = VSREPLACE; | 11964 | subtype = VSREPLACE; |
11943 | c = pgetc(); | 11965 | c = pgetc(); |
11944 | if (c == '/') | 11966 | if (c != '/') |
11945 | subtype++; /* VSREPLACEALL */ | 11967 | goto do_pungetc; |
11946 | else | 11968 | subtype++; /* VSREPLACEALL */ |
11947 | pungetc(); | ||
11948 | break; | 11969 | break; |
11949 | #endif | 11970 | #endif |
11950 | } | 11971 | } |
11951 | } else { | 11972 | } else { |
11973 | do_pungetc: | ||
11952 | pungetc(); | 11974 | pungetc(); |
11953 | } | 11975 | } |
11954 | if (dblquote || arinest) | 11976 | if (dblquote || arinest) |
@@ -12518,7 +12540,6 @@ evalcmd(int argc UNUSED_PARAM, char **argv) | |||
12518 | p = grabstackstr(concat); | 12540 | p = grabstackstr(concat); |
12519 | } | 12541 | } |
12520 | evalstring(p, ~SKIPEVAL); | 12542 | evalstring(p, ~SKIPEVAL); |
12521 | |||
12522 | } | 12543 | } |
12523 | return exitstatus; | 12544 | return exitstatus; |
12524 | } | 12545 | } |