diff options
-rw-r--r-- | shell/hush.c | 73 | ||||
-rw-r--r-- | shell/hush_test/hush-bugs/glob_and_assign.right | 8 | ||||
-rwxr-xr-x | shell/hush_test/hush-bugs/glob_and_assign.tests | 26 | ||||
-rwxr-xr-x | shell/hush_test/run-all | 9 |
4 files changed, 65 insertions, 51 deletions
diff --git a/shell/hush.c b/shell/hush.c index e64cc476d..ae12ebec4 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -106,6 +106,7 @@ #define debug_printf_expand(...) do {} while (0) #define debug_printf_glob(...) do {} while (0) #define debug_printf_list(...) do {} while (0) +#define debug_printf_subst(...) do {} while (0) #define debug_printf_clean(...) do {} while (0) #ifndef debug_printf @@ -145,6 +146,10 @@ #define debug_printf_list(...) fprintf(stderr, __VA_ARGS__) #endif +#ifndef debug_printf_subst +#define debug_printf_subst(...) fprintf(stderr, __VA_ARGS__) +#endif + /* Keep unconditionally on for now */ #define ENABLE_HUSH_DEBUG 1 @@ -516,8 +521,6 @@ static int run_list(struct pipe *pi); static void pseudo_exec_argv(char **ptrs2free, char **argv) ATTRIBUTE_NORETURN; static void pseudo_exec(char **ptrs2free, struct child_prog *child) ATTRIBUTE_NORETURN; static int run_pipe(struct pipe *pi); -/* variable assignment: */ -static int is_assignment(const char *s); /* data structure manipulation: */ static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); static void initialize_context(struct p_context *ctx); @@ -573,6 +576,16 @@ static int glob_needed(const char *s) return 0; } +static int is_assignment(const char *s) +{ + if (!s || !isalpha(*s)) + return 0; + s++; + while (isalnum(*s) || *s == '_') + s++; + return *s == '='; +} + static char **add_malloced_strings_to_strings(char **strings, char **add) { int i; @@ -938,7 +951,7 @@ static void o_addQstr(o_string *o, const char *str, int len) if (ordinary_cnt == len) return; str += ordinary_cnt; - len -= ordinary_cnt - 1; /* we are processing + 1 char below */ + len -= ordinary_cnt + 1; /* we are processing + 1 char below */ ch = *str++; sz = 1; @@ -1000,7 +1013,7 @@ static int o_save_ptr_helper(o_string *o, int n) string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); string_len = o->length - string_start; if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */ - debug_printf_list("list[%d]=%d string_start=%d (growing)", n, string_len, string_start); + debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start); /* list[n] points to string_start, make space for 16 more pointers */ o->maxlen += 0x10 * sizeof(list[0]); o->data = xrealloc(o->data, o->maxlen + 1); @@ -1008,12 +1021,12 @@ static int o_save_ptr_helper(o_string *o, int n) memmove(list + n + 0x10, list + n, string_len); o->length += 0x10 * sizeof(list[0]); } else - debug_printf_list("list[%d]=%d string_start=%d", n, string_len, string_start); + debug_printf_list("list[%d]=%d string_start=%d\n", n, string_len, string_start); } else { /* We have empty slot at list[n], reuse without growth */ string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */ string_len = o->length - string_start; - debug_printf_list("list[%d]=%d string_start=%d (empty slot)", n, string_len, string_start); + debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n", n, string_len, string_start); o->has_empty_slot = 0; } list[n] = (char*)string_len; @@ -1048,15 +1061,15 @@ static int o_glob(o_string *o, int n) int gr; char *pattern; - debug_printf_glob("start o_glob: n:%d o->data:%p", n, o->data); + debug_printf_glob("start o_glob: n:%d o->data:%p\n", n, o->data); if (!o->data) return o_save_ptr_helper(o, n); pattern = o->data + o_get_last_ptr(o, n); - debug_printf_glob("glob pattern '%s'", pattern); + debug_printf_glob("glob pattern '%s'\n", pattern); if (!glob_needed(pattern)) { literal: o->length = unbackslash(pattern) - o->data; - debug_printf_glob("glob pattern '%s' is literal", pattern); + debug_printf_glob("glob pattern '%s' is literal\n", pattern); return o_save_ptr_helper(o, n); } @@ -1108,7 +1121,7 @@ static char **o_finalize_list(o_string *o, int n) n = o_save_ptr(o, n); /* force growth for list[n] if necessary */ if (DEBUG_EXPAND) debug_print_list("finalized", o, n); - debug_printf_expand("finalized n:%d", n); + debug_printf_expand("finalized n:%d\n", n); list = (char**)o->data; string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); list[--n] = NULL; @@ -2285,7 +2298,7 @@ static int expand_on_ifs(o_string *output, int n, const char *str) while (1) { int word_len = strcspn(str, ifs); if (word_len) { - o_addQstr(output, str, word_len); + o_addstr(output, str, word_len); str += word_len; } if (!*str) /* EOL - do not finalize word */ @@ -2328,7 +2341,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) o_string subst_result = NULL_O_STRING; #endif - o_addQstr(output, arg, p - arg); + o_addstr(output, arg, p - arg); debug_print_list("expand_vars_to_list[1]", output, n); arg = ++p; p = strchr(p, SPECIAL_VAR_SYMBOL); @@ -2374,7 +2387,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) * and in this case should treat it like '$*' - see 'else...' below */ if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */ while (1) { - o_addQstr(output, global_argv[i], strlen(global_argv[i])); + o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q? if (++i >= global_argc) break; o_addchr(output, '\0'); @@ -2383,7 +2396,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) } } else { /* quoted $*: add as one word */ while (1) { - o_addQstr(output, global_argv[i], strlen(global_argv[i])); + o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q? if (!global_argv[++i]) break; if (ifs[0]) @@ -2397,10 +2410,10 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) *p = '\0'; arg++; //TODO: can we just stuff it into "output" directly? - //bb_error_msg("SUBST '%s' first_ch %x", arg, first_ch); + debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch); setup_string_in_str(&input, arg); process_command_subs(&subst_result, &input, NULL); - //bb_error_msg("RES '%s'", subst_result.data); + debug_printf_subst("SUBST RES '%s'\n", subst_result.data); val = subst_result.data; goto store_val; } @@ -2421,14 +2434,16 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) #endif *p = SPECIAL_VAR_SYMBOL; if (!(first_ch & 0x80)) { /* unquoted $VAR */ + debug_printf_expand("unquoted '%s', output->o_quote:%d\n", val, output->o_quote); if (val) { n = expand_on_ifs(output, n, val); val = NULL; } - } /* else: quoted $VAR, val will be appended below */ + } else /* quoted $VAR, val will be appended below */ + debug_printf_expand("quoted '%s', output->o_quote:%d\n", val, output->o_quote); } if (val) { - o_addQstr(output, val, strlen(val)); + o_addQstr(output, val, strlen(val)); ///maybe q? } #if ENABLE_HUSH_TICK @@ -2439,7 +2454,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) if (arg[0]) { debug_print_list("expand_vars_to_list[a]", output, n); - o_addQstr(output, arg, strlen(arg) + 1); + /* this part is literal, and it was already pre-quoted + * if needed (much earlier), do not use o_addQstr here! */ + o_addstr(output, arg, strlen(arg) + 1); debug_print_list("expand_vars_to_list[b]", output, n); } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ && !(ored_ch & 0x80) /* and all vars were not quoted. */ @@ -2460,8 +2477,10 @@ static char **expand_variables(char **argv, int or_mask) char **v; o_string output = NULL_O_STRING; - if (or_mask & 0x100) + if (or_mask & 0x100) { + output.o_quote = 1; output.o_glob = 1; + } n = 0; v = argv; @@ -2637,16 +2656,6 @@ static void unset_local_var(const char *name) } } -static int is_assignment(const char *s) -{ - if (!s || !isalpha(*s)) - return 0; - s++; - while (isalnum(*s) || *s == '_') - s++; - return *s == '='; -} - /* the src parameter allows us to peek forward to a possible &n syntax * for file descriptor duplication, e.g., "2>&1". * Return code is 0 normally, 1 if a syntax error is detected in src. @@ -3341,7 +3350,7 @@ static int handle_dollar(o_string *dest, struct in_str *input) o_addchr(dest, SPECIAL_VAR_SYMBOL); o_addchr(dest, quote_mask | '`'); add_till_closing_curly_brace(dest, input); - //bb_error_msg("RES '%s'", dest->data + pos); + //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos); o_addchr(dest, SPECIAL_VAR_SYMBOL); break; } @@ -3496,7 +3505,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx, o_addchr(dest, dest->o_quote ? 0x80 | '`' : '`'); add_till_backquote(dest, input); o_addchr(dest, SPECIAL_VAR_SYMBOL); - //bb_error_msg("RES '%s'", dest->data + pos); + //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); break; } #endif diff --git a/shell/hush_test/hush-bugs/glob_and_assign.right b/shell/hush_test/hush-bugs/glob_and_assign.right index dae832361..d46e44363 100644 --- a/shell/hush_test/hush-bugs/glob_and_assign.right +++ b/shell/hush_test/hush-bugs/glob_and_assign.right @@ -1,2 +1,6 @@ -ZVAR=z.map -*.map +ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp +ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp +*.tmp +ZVAR=z.tmp z.tmp +ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp +ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp diff --git a/shell/hush_test/hush-bugs/glob_and_assign.tests b/shell/hush_test/hush-bugs/glob_and_assign.tests index ea11e364b..0b158f20f 100755 --- a/shell/hush_test/hush-bugs/glob_and_assign.tests +++ b/shell/hush_test/hush-bugs/glob_and_assign.tests @@ -1,18 +1,10 @@ -## # bash zbad2 -## ZVAR=z.map -## *.map -## # hush zbad2 -## ZVAR=z.map -## z.map <====== !!! - -## hush does globbing for "VAR=val" too! -## it should do it only for non-assignments. -## even if word looks like assignment, it can be non-assignment: -## ZVAR=*.map /bin/echo ZVAR=*.map -## ^dont_glob ^glob - ->ZVAR=z.map -ZVAR=*.map /bin/echo ZVAR=*.map -ZVAR=*.map +>ZVAR=z.tmp +>z.tmp +ZVAR=*.tmp echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp" +ZVAR=*.tmp /bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp" +ZVAR=*.tmp echo "$ZVAR" -rm ZVAR=z.map +echo $ZVAR +echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp" +/bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp" +rm ZVAR=z.tmp z.tmp diff --git a/shell/hush_test/run-all b/shell/hush_test/run-all index 5cec85af6..b79af2f67 100755 --- a/shell/hush_test/run-all +++ b/shell/hush_test/run-all @@ -1,5 +1,14 @@ #!/bin/sh +unset LANG LANGUAGE +unset LC_COLLATE +unset LC_CTYPE +unset LC_MONETARY +unset LC_MESSAGES +unset LC_NUMERIC +unset LC_TIME +unset LC_ALL + test -x hush || { echo "No ./hush - creating a link to ../../busybox" ln -s ../../busybox hush |