aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c87
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
6617static const char * 6619static const char *
6618subevalvar(char *p, char *str, int strloc, int subtype, 6620subevalvar(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}