diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-18 09:20:35 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-18 09:20:35 +0000 |
commit | c1c63b622dfc863798e0873feba6ccd1677394aa (patch) | |
tree | 08196e8b604f1335ff1784e6913c88b40aadbb6e | |
parent | 4954d47ab01624855fdf4bcf0a86fb86f6381638 (diff) | |
download | busybox-w32-c1c63b622dfc863798e0873feba6ccd1677394aa.tar.gz busybox-w32-c1c63b622dfc863798e0873feba6ccd1677394aa.tar.bz2 busybox-w32-c1c63b622dfc863798e0873feba6ccd1677394aa.zip |
hush: fix last hush-bugs testcase (disappearing "", $empty"" etc)
-rw-r--r-- | shell/hush.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/shell/hush.c b/shell/hush.c index e49e6e9b2..cb289769e 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -2354,7 +2354,6 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2354 | switch (first_ch & 0x7f) { | 2354 | switch (first_ch & 0x7f) { |
2355 | /* Highest bit in first_ch indicates that var is double-quoted */ | 2355 | /* Highest bit in first_ch indicates that var is double-quoted */ |
2356 | case '$': /* pid */ | 2356 | case '$': /* pid */ |
2357 | /* FIXME: (echo $$) should still print pid of main shell */ | ||
2358 | val = utoa(root_pid); | 2357 | val = utoa(root_pid); |
2359 | break; | 2358 | break; |
2360 | case '!': /* bg pid */ | 2359 | case '!': /* bg pid */ |
@@ -2406,8 +2405,13 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2406 | } | 2405 | } |
2407 | } | 2406 | } |
2408 | break; | 2407 | break; |
2408 | case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ | ||
2409 | /* "Empty variable", used to make "" etc to not disappear */ | ||
2410 | arg++; | ||
2411 | ored_ch = 0x80; | ||
2412 | break; | ||
2409 | #if ENABLE_HUSH_TICK | 2413 | #if ENABLE_HUSH_TICK |
2410 | case '`': { | 2414 | case '`': { /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */ |
2411 | struct in_str input; | 2415 | struct in_str input; |
2412 | *p = '\0'; | 2416 | *p = '\0'; |
2413 | arg++; | 2417 | arg++; |
@@ -2420,7 +2424,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2420 | goto store_val; | 2424 | goto store_val; |
2421 | } | 2425 | } |
2422 | #endif | 2426 | #endif |
2423 | default: | 2427 | default: /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */ |
2424 | *p = '\0'; | 2428 | *p = '\0'; |
2425 | arg[0] = first_ch & 0x7f; | 2429 | arg[0] = first_ch & 0x7f; |
2426 | if (isdigit(arg[0])) { | 2430 | if (isdigit(arg[0])) { |
@@ -2856,9 +2860,11 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2856 | char ***glob_target; | 2860 | char ***glob_target; |
2857 | 2861 | ||
2858 | debug_printf_parse("done_word entered: '%s' %p\n", word->data, child); | 2862 | debug_printf_parse("done_word entered: '%s' %p\n", word->data, child); |
2859 | if (word->length == 0 && !word->nonnull) { | 2863 | if (word->length == 0) { |
2860 | debug_printf_parse("done_word return 0: true null, ignored\n"); | 2864 | if (!word->nonnull) { |
2861 | return 0; | 2865 | debug_printf_parse("done_word return 0: true null, ignored\n"); |
2866 | return 0; | ||
2867 | } | ||
2862 | } | 2868 | } |
2863 | if (ctx->pending_redirect) { | 2869 | if (ctx->pending_redirect) { |
2864 | glob_target = &ctx->pending_redirect->glob_word; | 2870 | glob_target = &ctx->pending_redirect->glob_word; |
@@ -2868,7 +2874,7 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2868 | debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); | 2874 | debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); |
2869 | return 1; | 2875 | return 1; |
2870 | } | 2876 | } |
2871 | if (!child->argv) { | 2877 | if (!child->argv) { /* if it's the first word... */ |
2872 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); | 2878 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); |
2873 | if (reserved_word(word, ctx)) { | 2879 | if (reserved_word(word, ctx)) { |
2874 | o_reset(word); | 2880 | o_reset(word); |
@@ -2876,10 +2882,18 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2876 | return (ctx->res_w == RES_SNTX); | 2882 | return (ctx->res_w == RES_SNTX); |
2877 | } | 2883 | } |
2878 | } | 2884 | } |
2885 | if (word->nonnull) { | ||
2886 | /* Insert "empty variable" reference, this makes e.g. "", '', | ||
2887 | * $empty"" etc to not disappear */ | ||
2888 | o_addchr(word, SPECIAL_VAR_SYMBOL); | ||
2889 | o_addchr(word, SPECIAL_VAR_SYMBOL); | ||
2890 | } | ||
2879 | glob_target = &child->argv; | 2891 | glob_target = &child->argv; |
2880 | } | 2892 | } |
2881 | 2893 | ||
2882 | if (word->length || word->nonnull) { | 2894 | //FIXME: we had globbing here, but now it's moved! Do we glob in e.g. ">*.tmp" now!? |
2895 | |||
2896 | /*if (word->length || word->nonnull) - true */ { | ||
2883 | *glob_target = add_malloced_string_to_strings(*glob_target, xstrdup(word->data)); | 2897 | *glob_target = add_malloced_string_to_strings(*glob_target, xstrdup(word->data)); |
2884 | debug_print_strings("glob_target appended", *glob_target); | 2898 | debug_print_strings("glob_target appended", *glob_target); |
2885 | } | 2899 | } |
@@ -3026,11 +3040,10 @@ static int redirect_opt_num(o_string *o) | |||
3026 | if (o->length == 0) | 3040 | if (o->length == 0) |
3027 | return -1; | 3041 | return -1; |
3028 | for (num = 0; num < o->length; num++) { | 3042 | for (num = 0; num < o->length; num++) { |
3029 | if (!isdigit(*(o->data + num))) { | 3043 | if (!isdigit(o->data[num])) { |
3030 | return -1; | 3044 | return -1; |
3031 | } | 3045 | } |
3032 | } | 3046 | } |
3033 | /* reuse num (and save an int) */ | ||
3034 | num = atoi(o->data); | 3047 | num = atoi(o->data); |
3035 | o_reset(o); | 3048 | o_reset(o); |
3036 | return num; | 3049 | return num; |
@@ -3668,8 +3681,8 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3668 | free(ctx.stack); | 3681 | free(ctx.stack); |
3669 | o_reset(&temp); | 3682 | o_reset(&temp); |
3670 | } | 3683 | } |
3671 | temp.nonnull = 0; | 3684 | /*temp.nonnull = 0; - o_free does it below */ |
3672 | temp.o_quote = 0; | 3685 | /*temp.o_quote = 0; - o_free does it below */ |
3673 | free_pipe_list(ctx.list_head, /* indent: */ 0); | 3686 | free_pipe_list(ctx.list_head, /* indent: */ 0); |
3674 | /* Discard all unprocessed line input, force prompt on */ | 3687 | /* Discard all unprocessed line input, force prompt on */ |
3675 | inp->p = NULL; | 3688 | inp->p = NULL; |