aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c109
1 files changed, 71 insertions, 38 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 5debd82f2..6cc29d25e 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2566,12 +2566,8 @@ putprompt(const char *s)
2566} 2566}
2567#endif 2567#endif
2568 2568
2569#if ENABLE_ASH_EXPAND_PRMT
2570/* expandstr() needs parsing machinery, so it is far away ahead... */ 2569/* expandstr() needs parsing machinery, so it is far away ahead... */
2571static const char *expandstr(const char *ps); 2570static const char *expandstr(const char *ps);
2572#else
2573#define expandstr(s) s
2574#endif
2575 2571
2576static void 2572static void
2577setprompt_if(smallint do_set, int whichprompt) 2573setprompt_if(smallint do_set, int whichprompt)
@@ -2596,10 +2592,10 @@ setprompt_if(smallint do_set, int whichprompt)
2596 } 2592 }
2597#if ENABLE_ASH_EXPAND_PRMT 2593#if ENABLE_ASH_EXPAND_PRMT
2598 pushstackmark(&smark, stackblocksize()); 2594 pushstackmark(&smark, stackblocksize());
2599#endif
2600 putprompt(expandstr(prompt)); 2595 putprompt(expandstr(prompt));
2601#if ENABLE_ASH_EXPAND_PRMT
2602 popstackmark(&smark); 2596 popstackmark(&smark);
2597#else
2598 putprompt(prompt);
2603#endif 2599#endif
2604} 2600}
2605 2601
@@ -4244,15 +4240,19 @@ sprint_status48(char *s, int status, int sigonly)
4244 4240
4245 col = 0; 4241 col = 0;
4246 if (!WIFEXITED(status)) { 4242 if (!WIFEXITED(status)) {
4247 if (JOBS && WIFSTOPPED(status)) 4243#if JOBS
4244 if (WIFSTOPPED(status))
4248 st = WSTOPSIG(status); 4245 st = WSTOPSIG(status);
4249 else 4246 else
4247#endif
4250 st = WTERMSIG(status); 4248 st = WTERMSIG(status);
4251 if (sigonly) { 4249 if (sigonly) {
4252 if (st == SIGINT || st == SIGPIPE) 4250 if (st == SIGINT || st == SIGPIPE)
4253 goto out; 4251 goto out;
4254 if (JOBS && WIFSTOPPED(status)) 4252#if JOBS
4253 if (WIFSTOPPED(status))
4255 goto out; 4254 goto out;
4255#endif
4256 } 4256 }
4257 st &= 0x7f; 4257 st &= 0x7f;
4258//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata 4258//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
@@ -4501,8 +4501,10 @@ dowait(int block, struct job *job)
4501 goto out; 4501 goto out;
4502 } 4502 }
4503 /* The process wasn't found in job list */ 4503 /* The process wasn't found in job list */
4504 if (JOBS && !WIFSTOPPED(status)) 4504#if JOBS
4505 if (!WIFSTOPPED(status))
4505 jobless--; 4506 jobless--;
4507#endif
4506 out: 4508 out:
4507 INT_ON; 4509 INT_ON;
4508 4510
@@ -6285,6 +6287,7 @@ rmescapes(char *str, int flag)
6285 while (*p) { 6287 while (*p) {
6286 if ((unsigned char)*p == CTLQUOTEMARK) { 6288 if ((unsigned char)*p == CTLQUOTEMARK) {
6287// Note: both inquotes and protect_against_glob only affect whether 6289// Note: both inquotes and protect_against_glob only affect whether
6290// CTLESC,<ch> gets converted to <ch> or to \<ch>
6288 inquotes = ~inquotes; 6291 inquotes = ~inquotes;
6289 p++; 6292 p++;
6290 protect_against_glob = globbing; 6293 protect_against_glob = globbing;
@@ -6297,7 +6300,33 @@ rmescapes(char *str, int flag)
6297 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)"); 6300 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6298#endif 6301#endif
6299 if (protect_against_glob) { 6302 if (protect_against_glob) {
6300 *q++ = '\\'; 6303 /*
6304 * We used to trust glob() and fnmatch() to eat
6305 * superfluous escapes (\z where z has no
6306 * special meaning anyway). But this causes
6307 * bugs such as string of one greek letter rho
6308 * (unicode-encoded as two bytes "cf,81")
6309 * getting encoded as "cf,CTLESC,81"
6310 * and here, converted to "cf,\,81" -
6311 * which does not go well with some flavors
6312 * of fnmatch() in unicode locales
6313 * (for example, glibc <= 2.22).
6314 *
6315 * Lets add "\" only on the chars which need it.
6316 * Testcases for less obvious chars are shown.
6317 */
6318 if (*p == '*'
6319 || *p == '?'
6320 || *p == '['
6321 || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6322 || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6323 || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6324 || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6325 /* Some libc support [^negate], that's why "^" also needs love */
6326 || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6327 ) {
6328 *q++ = '\\';
6329 }
6301 } 6330 }
6302 } else if (*p == '\\' && !inquotes) { 6331 } else if (*p == '\\' && !inquotes) {
6303 /* naked back slash */ 6332 /* naked back slash */
@@ -6963,7 +6992,6 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6963 char *loc; 6992 char *loc;
6964 char *rmesc, *rmescend; 6993 char *rmesc, *rmescend;
6965 char *str; 6994 char *str;
6966 IF_BASH_SUBSTR(int pos, len, orig_len;)
6967 int amount, resetloc; 6995 int amount, resetloc;
6968 IF_BASH_PATTERN_SUBST(int workloc;) 6996 IF_BASH_PATTERN_SUBST(int workloc;)
6969 IF_BASH_PATTERN_SUBST(char *repl = NULL;) 6997 IF_BASH_PATTERN_SUBST(char *repl = NULL;)
@@ -6992,14 +7020,23 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6992 /* NOTREACHED */ 7020 /* NOTREACHED */
6993 7021
6994#if BASH_SUBSTR 7022#if BASH_SUBSTR
6995 case VSSUBSTR: 7023 case VSSUBSTR: {
6996//TODO: support more general format ${v:EXPR:EXPR}, 7024 int pos, len, orig_len;
6997// where EXPR follows $(()) rules 7025 char *colon;
7026
6998 loc = str = stackblock() + strloc; 7027 loc = str = stackblock() + strloc;
7028
7029# if !ENABLE_FEATURE_SH_MATH
7030# define ash_arith number
7031# endif
6999 /* Read POS in ${var:POS:LEN} */ 7032 /* Read POS in ${var:POS:LEN} */
7000 pos = atoi(loc); /* number(loc) errors out on "1:4" */ 7033 colon = strchr(loc, ':');
7001 len = str - startp - 1; 7034 if (colon) *colon = '\0';
7035 pos = ash_arith(loc);
7036 if (colon) *colon = ':';
7002 7037
7038 /* Read LEN in ${var:POS:LEN} */
7039 len = str - startp - 1;
7003 /* *loc != '\0', guaranteed by parser */ 7040 /* *loc != '\0', guaranteed by parser */
7004 if (quotes) { 7041 if (quotes) {
7005 char *ptr; 7042 char *ptr;
@@ -7013,25 +7050,21 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7013 } 7050 }
7014 } 7051 }
7015 orig_len = len; 7052 orig_len = len;
7016
7017 if (*loc++ == ':') { 7053 if (*loc++ == ':') {
7018 /* ${var::LEN} */ 7054 /* ${var::LEN} */
7019 len = number(loc); 7055 len = ash_arith(loc);
7020 } else { 7056 } else {
7021 /* Skip POS in ${var:POS:LEN} */ 7057 /* Skip POS in ${var:POS:LEN} */
7022 len = orig_len; 7058 len = orig_len;
7023 while (*loc && *loc != ':') { 7059 while (*loc && *loc != ':') {
7024 /* TODO?
7025 * bash complains on: var=qwe; echo ${var:1a:123}
7026 if (!isdigit(*loc))
7027 ash_msg_and_raise_error(msg_illnum, str);
7028 */
7029 loc++; 7060 loc++;
7030 } 7061 }
7031 if (*loc++ == ':') { 7062 if (*loc++ == ':') {
7032 len = number(loc); 7063 len = ash_arith(loc);
7033 } 7064 }
7034 } 7065 }
7066# undef ash_arith
7067
7035 if (pos < 0) { 7068 if (pos < 0) {
7036 /* ${VAR:$((-n)):l} starts n chars from the end */ 7069 /* ${VAR:$((-n)):l} starts n chars from the end */
7037 pos = orig_len + pos; 7070 pos = orig_len + pos;
@@ -7039,12 +7072,16 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7039 if ((unsigned)pos >= orig_len) { 7072 if ((unsigned)pos >= orig_len) {
7040 /* apart from obvious ${VAR:999999:l}, 7073 /* apart from obvious ${VAR:999999:l},
7041 * covers ${VAR:$((-9999999)):l} - result is "" 7074 * covers ${VAR:$((-9999999)):l} - result is ""
7042 * (bash-compat) 7075 * (bash compat)
7043 */ 7076 */
7044 pos = 0; 7077 pos = 0;
7045 len = 0; 7078 len = 0;
7046 } 7079 }
7047 if (len > (orig_len - pos)) 7080 if (len < 0) {
7081 /* ${VAR:N:-M} sets LEN to strlen()-M */
7082 len = (orig_len - pos) + len;
7083 }
7084 if ((unsigned)len > (orig_len - pos))
7048 len = orig_len - pos; 7085 len = orig_len - pos;
7049 7086
7050 for (str = startp; pos; str++, pos--) { 7087 for (str = startp; pos; str++, pos--) {
@@ -7060,6 +7097,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7060 amount = loc - expdest; 7097 amount = loc - expdest;
7061 STADJUST(amount, expdest); 7098 STADJUST(amount, expdest);
7062 return loc; 7099 return loc;
7100 }
7063#endif /* BASH_SUBSTR */ 7101#endif /* BASH_SUBSTR */
7064 } 7102 }
7065 7103
@@ -7104,6 +7142,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7104#if BASH_PATTERN_SUBST 7142#if BASH_PATTERN_SUBST
7105 workloc = expdest - (char *)stackblock(); 7143 workloc = expdest - (char *)stackblock();
7106 if (subtype == VSREPLACE || subtype == VSREPLACEALL) { 7144 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7145 int len;
7107 char *idx, *end; 7146 char *idx, *end;
7108 7147
7109 if (!repl) { 7148 if (!repl) {
@@ -7970,7 +8009,9 @@ expandhere(union node *arg, int fd)
7970static int 8009static int
7971patmatch(char *pattern, const char *string) 8010patmatch(char *pattern, const char *string)
7972{ 8011{
7973 return pmatch(preglob(pattern, 0), string); 8012 char *p = preglob(pattern, 0);
8013 //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
8014 return pmatch(p, string);
7974} 8015}
7975 8016
7976/* 8017/*
@@ -8072,7 +8113,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **
8072 clearenv(); 8113 clearenv();
8073 while (*envp) 8114 while (*envp)
8074 putenv(*envp++); 8115 putenv(*envp++);
8075 run_applet_no_and_exit(applet_no, argv); 8116 run_applet_no_and_exit(applet_no, cmd, argv);
8076 } 8117 }
8077 /* re-exec ourselves with the new arguments */ 8118 /* re-exec ourselves with the new arguments */
8078 execve(bb_busybox_exec_path, argv, envp); 8119 execve(bb_busybox_exec_path, argv, envp);
@@ -12022,9 +12063,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12022 smallint dblquote; 12063 smallint dblquote;
12023 smallint oldstyle; 12064 smallint oldstyle;
12024 IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */ 12065 IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
12025#if ENABLE_ASH_EXPAND_PRMT
12026 smallint pssyntax; /* we are expanding a prompt string */ 12066 smallint pssyntax; /* we are expanding a prompt string */
12027#endif
12028 int varnest; /* levels of variables expansion */ 12067 int varnest; /* levels of variables expansion */
12029 IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */ 12068 IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */
12030 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ 12069 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
@@ -12036,11 +12075,9 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12036 bqlist = NULL; 12075 bqlist = NULL;
12037 quotef = 0; 12076 quotef = 0;
12038 IF_FEATURE_SH_MATH(prevsyntax = 0;) 12077 IF_FEATURE_SH_MATH(prevsyntax = 0;)
12039#if ENABLE_ASH_EXPAND_PRMT
12040 pssyntax = (syntax == PSSYNTAX); 12078 pssyntax = (syntax == PSSYNTAX);
12041 if (pssyntax) 12079 if (pssyntax)
12042 syntax = DQSYNTAX; 12080 syntax = DQSYNTAX;
12043#endif
12044 dblquote = (syntax == DQSYNTAX); 12081 dblquote = (syntax == DQSYNTAX);
12045 varnest = 0; 12082 varnest = 0;
12046 IF_FEATURE_SH_MATH(arinest = 0;) 12083 IF_FEATURE_SH_MATH(arinest = 0;)
@@ -12094,12 +12131,10 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12094 } else if (c == '\n') { 12131 } else if (c == '\n') {
12095 nlprompt(); 12132 nlprompt();
12096 } else { 12133 } else {
12097#if ENABLE_ASH_EXPAND_PRMT
12098 if (c == '$' && pssyntax) { 12134 if (c == '$' && pssyntax) {
12099 USTPUTC(CTLESC, out); 12135 USTPUTC(CTLESC, out);
12100 USTPUTC('\\', out); 12136 USTPUTC('\\', out);
12101 } 12137 }
12102#endif
12103 /* Backslash is retained if we are in "str" and next char isn't special */ 12138 /* Backslash is retained if we are in "str" and next char isn't special */
12104 if (dblquote 12139 if (dblquote
12105 && c != '\\' 12140 && c != '\\'
@@ -12384,7 +12419,7 @@ parsesub: {
12384#if ENABLE_FEATURE_SH_MATH 12419#if ENABLE_FEATURE_SH_MATH
12385 PARSEARITH(); 12420 PARSEARITH();
12386#else 12421#else
12387 raise_error_syntax("you disabled math support for $((arith)) syntax"); 12422 raise_error_syntax("support for $((arith)) is disabled");
12388#endif 12423#endif
12389 } else { 12424 } else {
12390 pungetc(); 12425 pungetc();
@@ -12933,7 +12968,6 @@ parseheredoc(void)
12933/* 12968/*
12934 * called by editline -- any expansions to the prompt should be added here. 12969 * called by editline -- any expansions to the prompt should be added here.
12935 */ 12970 */
12936#if ENABLE_ASH_EXPAND_PRMT
12937static const char * 12971static const char *
12938expandstr(const char *ps) 12972expandstr(const char *ps)
12939{ 12973{
@@ -12959,7 +12993,6 @@ expandstr(const char *ps)
12959 expandarg(&n, NULL, EXP_QUOTED); 12993 expandarg(&n, NULL, EXP_QUOTED);
12960 return stackblock(); 12994 return stackblock();
12961} 12995}
12962#endif
12963 12996
12964/* 12997/*
12965 * Execute a command or commands contained in a string. 12998 * Execute a command or commands contained in a string.
@@ -13497,7 +13530,7 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13497 exitcode = 0; 13530 exitcode = 0;
13498 while (*ap) { 13531 while (*ap) {
13499 signo = get_signum(*ap); 13532 signo = get_signum(*ap);
13500 if (signo < 0) { 13533 if (signo < 0 || signo >= NSIG) {
13501 /* Mimic bash message exactly */ 13534 /* Mimic bash message exactly */
13502 ash_msg("%s: invalid signal specification", *ap); 13535 ash_msg("%s: invalid signal specification", *ap);
13503 exitcode = 1; 13536 exitcode = 1;