diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-08 13:44:34 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-08 13:44:34 +0200 |
commit | 5b686cb8e6db85c0080ff8747c0fef7cb326dc20 (patch) | |
tree | 95f104213fcfbf70d48e7b59492eaf83b26edf95 | |
parent | 9b78255dcaf79c99d337641a4135e402e00ee3a1 (diff) | |
download | busybox-w32-5b686cb8e6db85c0080ff8747c0fef7cb326dc20.tar.gz busybox-w32-5b686cb8e6db85c0080ff8747c0fef7cb326dc20.tar.bz2 busybox-w32-5b686cb8e6db85c0080ff8747c0fef7cb326dc20.zip |
hush: replace flag bytes in struct o_string with bit flags
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | shell/hush.c | 76 |
1 files changed, 40 insertions, 36 deletions
diff --git a/shell/hush.c b/shell/hush.c index e6cb34859..05ac4096f 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -380,14 +380,19 @@ enum { | |||
380 | RES_SNTX | 380 | RES_SNTX |
381 | }; | 381 | }; |
382 | 382 | ||
383 | enum { | ||
384 | EXP_FLAG_GLOB = 0x200, | ||
385 | EXP_FLAG_ESC_GLOB_CHARS = 0x100, | ||
386 | EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ | ||
387 | }; | ||
388 | |||
383 | typedef struct o_string { | 389 | typedef struct o_string { |
384 | char *data; | 390 | char *data; |
385 | int length; /* position where data is appended */ | 391 | int length; /* position where data is appended */ |
386 | int maxlen; | 392 | int maxlen; |
387 | /* Protect newly added chars against globbing | 393 | /* Protect newly added chars against globbing |
388 | * (by prepending \ to *, ?, [, \) */ | 394 | * (by prepending \ to *, ?, [, \) */ |
389 | smallint o_escape; | 395 | int o_expflags; |
390 | smallint o_glob; | ||
391 | /* At least some part of the string was inside '' or "", | 396 | /* At least some part of the string was inside '' or "", |
392 | * possibly empty one: word"", wo''rd etc. */ | 397 | * possibly empty one: word"", wo''rd etc. */ |
393 | smallint has_quoted_part; | 398 | smallint has_quoted_part; |
@@ -2035,7 +2040,9 @@ static void o_addqchr(o_string *o, int ch) | |||
2035 | static void o_addQchr(o_string *o, int ch) | 2040 | static void o_addQchr(o_string *o, int ch) |
2036 | { | 2041 | { |
2037 | int sz = 1; | 2042 | int sz = 1; |
2038 | if (o->o_escape && strchr("*?[\\" MAYBE_BRACES, ch)) { | 2043 | if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) |
2044 | && strchr("*?[\\" MAYBE_BRACES, ch) | ||
2045 | ) { | ||
2039 | sz++; | 2046 | sz++; |
2040 | o->data[o->length] = '\\'; | 2047 | o->data[o->length] = '\\'; |
2041 | o->length++; | 2048 | o->length++; |
@@ -2076,7 +2083,7 @@ static void o_addqblock(o_string *o, const char *str, int len) | |||
2076 | 2083 | ||
2077 | static void o_addQblock(o_string *o, const char *str, int len) | 2084 | static void o_addQblock(o_string *o, const char *str, int len) |
2078 | { | 2085 | { |
2079 | if (!o->o_escape) { | 2086 | if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) { |
2080 | o_addblock(o, str, len); | 2087 | o_addblock(o, str, len); |
2081 | return; | 2088 | return; |
2082 | } | 2089 | } |
@@ -2107,7 +2114,10 @@ static void debug_print_list(const char *prefix, o_string *o, int n) | |||
2107 | 2114 | ||
2108 | indent(); | 2115 | indent(); |
2109 | fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", | 2116 | fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", |
2110 | prefix, list, n, string_start, o->length, o->maxlen, o->o_glob, o->has_quoted_part, o->o_escape); | 2117 | prefix, list, n, string_start, o->length, o->maxlen, |
2118 | !!(o->o_expflags & EXP_FLAG_GLOB), | ||
2119 | o->has_quoted_part, | ||
2120 | !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | ||
2111 | while (i < n) { | 2121 | while (i < n) { |
2112 | indent(); | 2122 | indent(); |
2113 | fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i], | 2123 | fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i], |
@@ -2445,11 +2455,11 @@ static int perform_glob(o_string *o, int n) | |||
2445 | 2455 | ||
2446 | #endif /* !HUSH_BRACE_EXP */ | 2456 | #endif /* !HUSH_BRACE_EXP */ |
2447 | 2457 | ||
2448 | /* If o->o_glob == 1, glob the string so far remembered. | 2458 | /* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered. |
2449 | * Otherwise, just finish current list[] and start new */ | 2459 | * Otherwise, just finish current list[] and start new */ |
2450 | static int o_save_ptr(o_string *o, int n) | 2460 | static int o_save_ptr(o_string *o, int n) |
2451 | { | 2461 | { |
2452 | if (o->o_glob) { /* if globbing is requested */ | 2462 | if (o->o_expflags & EXP_FLAG_GLOB) { |
2453 | /* If o->has_empty_slot, list[n] was already globbed | 2463 | /* If o->has_empty_slot, list[n] was already globbed |
2454 | * (if it was requested back then when it was filled) | 2464 | * (if it was requested back then when it was filled) |
2455 | * so don't do that again! */ | 2465 | * so don't do that again! */ |
@@ -3523,7 +3533,7 @@ static int parse_dollar(o_string *as_string, | |||
3523 | struct in_str *input) | 3533 | struct in_str *input) |
3524 | { | 3534 | { |
3525 | int ch = i_peek(input); /* first character after the $ */ | 3535 | int ch = i_peek(input); /* first character after the $ */ |
3526 | unsigned char quote_mask = dest->o_escape ? 0x80 : 0; | 3536 | unsigned char quote_mask = (dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) ? 0x80 : 0; |
3527 | 3537 | ||
3528 | debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); | 3538 | debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); |
3529 | if (isalpha(ch)) { | 3539 | if (isalpha(ch)) { |
@@ -3739,7 +3749,7 @@ static int parse_stream_dquoted(o_string *as_string, | |||
3739 | nommu_addchr(as_string, ch); | 3749 | nommu_addchr(as_string, ch); |
3740 | if (ch == dquote_end) { /* may be only '"' or EOF */ | 3750 | if (ch == dquote_end) { /* may be only '"' or EOF */ |
3741 | if (dest->o_assignment == NOT_ASSIGNMENT) | 3751 | if (dest->o_assignment == NOT_ASSIGNMENT) |
3742 | dest->o_escape ^= 1; | 3752 | dest->o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; |
3743 | debug_printf_parse("parse_stream_dquoted return 0\n"); | 3753 | debug_printf_parse("parse_stream_dquoted return 0\n"); |
3744 | return 0; | 3754 | return 0; |
3745 | } | 3755 | } |
@@ -3753,7 +3763,7 @@ static int parse_stream_dquoted(o_string *as_string, | |||
3753 | next = i_peek(input); | 3763 | next = i_peek(input); |
3754 | } | 3764 | } |
3755 | debug_printf_parse("\" ch=%c (%d) escape=%d\n", | 3765 | debug_printf_parse("\" ch=%c (%d) escape=%d\n", |
3756 | ch, ch, dest->o_escape); | 3766 | ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
3757 | if (ch == '\\') { | 3767 | if (ch == '\\') { |
3758 | if (next == EOF) { | 3768 | if (next == EOF) { |
3759 | syntax_error("\\<eof>"); | 3769 | syntax_error("\\<eof>"); |
@@ -3828,7 +3838,7 @@ static struct pipe *parse_stream(char **pstring, | |||
3828 | 3838 | ||
3829 | /* Double-quote state is handled in the state variable is_in_dquote. | 3839 | /* Double-quote state is handled in the state variable is_in_dquote. |
3830 | * A single-quote triggers a bypass of the main loop until its mate is | 3840 | * A single-quote triggers a bypass of the main loop until its mate is |
3831 | * found. When recursing, quote state is passed in via dest->o_escape. | 3841 | * found. When recursing, quote state is passed in via dest->o_expflags. |
3832 | */ | 3842 | */ |
3833 | debug_printf_parse("parse_stream entered, end_trigger='%c'\n", | 3843 | debug_printf_parse("parse_stream entered, end_trigger='%c'\n", |
3834 | end_trigger ? end_trigger : 'X'); | 3844 | end_trigger ? end_trigger : 'X'); |
@@ -3869,7 +3879,7 @@ static struct pipe *parse_stream(char **pstring, | |||
3869 | } | 3879 | } |
3870 | ch = i_getch(input); | 3880 | ch = i_getch(input); |
3871 | debug_printf_parse(": ch=%c (%d) escape=%d\n", | 3881 | debug_printf_parse(": ch=%c (%d) escape=%d\n", |
3872 | ch, ch, dest.o_escape); | 3882 | ch, ch, !!(dest.o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
3873 | if (ch == EOF) { | 3883 | if (ch == EOF) { |
3874 | struct pipe *pi; | 3884 | struct pipe *pi; |
3875 | 3885 | ||
@@ -4168,7 +4178,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4168 | dest.has_quoted_part = 1; | 4178 | dest.has_quoted_part = 1; |
4169 | is_in_dquote ^= 1; /* invert */ | 4179 | is_in_dquote ^= 1; /* invert */ |
4170 | if (dest.o_assignment == NOT_ASSIGNMENT) | 4180 | if (dest.o_assignment == NOT_ASSIGNMENT) |
4171 | dest.o_escape ^= 1; | 4181 | dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; |
4172 | break; | 4182 | break; |
4173 | #if ENABLE_HUSH_TICK | 4183 | #if ENABLE_HUSH_TICK |
4174 | case '`': { | 4184 | case '`': { |
@@ -4359,9 +4369,9 @@ static int expand_on_ifs(o_string *output, int n, const char *str) | |||
4359 | while (1) { | 4369 | while (1) { |
4360 | int word_len = strcspn(str, G.ifs); | 4370 | int word_len = strcspn(str, G.ifs); |
4361 | if (word_len) { | 4371 | if (word_len) { |
4362 | if (output->o_escape) | 4372 | if (output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) |
4363 | o_addqblock(output, str, word_len); | 4373 | o_addqblock(output, str, word_len); |
4364 | else if (!output->o_glob) | 4374 | else if (!(output->o_expflags & EXP_FLAG_GLOB)) |
4365 | o_addblock(output, str, word_len); | 4375 | o_addblock(output, str, word_len); |
4366 | else /* if (!escape && glob) */ { | 4376 | else /* if (!escape && glob) */ { |
4367 | /* Protect backslashes against globbing up :) | 4377 | /* Protect backslashes against globbing up :) |
@@ -4819,9 +4829,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char | |||
4819 | i = 1; | 4829 | i = 1; |
4820 | ored_ch |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ | 4830 | ored_ch |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ |
4821 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ | 4831 | if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ |
4822 | smallint sv = output->o_escape; | 4832 | int sv = output->o_expflags; |
4823 | /* unquoted var's contents should be globbed, so don't escape */ | 4833 | /* unquoted var's contents should be globbed, so don't escape */ |
4824 | output->o_escape = 0; | 4834 | output->o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; |
4825 | while (G.global_argv[i]) { | 4835 | while (G.global_argv[i]) { |
4826 | n = expand_on_ifs(output, n, G.global_argv[i]); | 4836 | n = expand_on_ifs(output, n, G.global_argv[i]); |
4827 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); | 4837 | debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); |
@@ -4834,7 +4844,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char | |||
4834 | debug_print_list("expand_vars_to_list[3]", output, n); | 4844 | debug_print_list("expand_vars_to_list[3]", output, n); |
4835 | } | 4845 | } |
4836 | } | 4846 | } |
4837 | output->o_escape = sv; | 4847 | output->o_expflags = sv; |
4838 | } else | 4848 | } else |
4839 | /* If or_mask is nonzero, we handle assignment 'a=....$@.....' | 4849 | /* If or_mask is nonzero, we handle assignment 'a=....$@.....' |
4840 | * and in this case should treat it like '$*' - see 'else...' below */ | 4850 | * and in this case should treat it like '$*' - see 'else...' below */ |
@@ -4911,17 +4921,19 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char | |||
4911 | val = expand_one_var(&to_be_freed, arg, &p, first_ch); | 4921 | val = expand_one_var(&to_be_freed, arg, &p, first_ch); |
4912 | IF_HUSH_TICK(store_val:) | 4922 | IF_HUSH_TICK(store_val:) |
4913 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ | 4923 | if (!(first_ch & 0x80)) { /* unquoted $VAR */ |
4914 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, output->o_escape); | 4924 | debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, |
4925 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | ||
4915 | if (val && val[0]) { | 4926 | if (val && val[0]) { |
4916 | /* unquoted var's contents should be globbed, so don't escape */ | 4927 | /* unquoted var's contents should be globbed, so don't escape */ |
4917 | smallint sv = output->o_escape; | 4928 | int sv = output->o_expflags; |
4918 | output->o_escape = 0; | 4929 | output->o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; |
4919 | n = expand_on_ifs(output, n, val); | 4930 | n = expand_on_ifs(output, n, val); |
4920 | val = NULL; | 4931 | val = NULL; |
4921 | output->o_escape = sv; | 4932 | output->o_expflags = sv; |
4922 | } | 4933 | } |
4923 | } else { /* quoted $VAR, val will be appended below */ | 4934 | } else { /* quoted $VAR, val will be appended below */ |
4924 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, output->o_escape); | 4935 | debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, |
4936 | !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | ||
4925 | } | 4937 | } |
4926 | break; | 4938 | break; |
4927 | 4939 | ||
@@ -4960,21 +4972,13 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char | |||
4960 | return n; | 4972 | return n; |
4961 | } | 4973 | } |
4962 | 4974 | ||
4963 | enum { | ||
4964 | EXPVAR_FLAG_GLOB = 0x200, | ||
4965 | EXPVAR_FLAG_ESCAPE_VARS = 0x100, | ||
4966 | EXPVAR_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ | ||
4967 | }; | ||
4968 | static char **expand_variables(char **argv, unsigned or_mask) | 4975 | static char **expand_variables(char **argv, unsigned or_mask) |
4969 | { | 4976 | { |
4970 | int n; | 4977 | int n; |
4971 | char **list; | 4978 | char **list; |
4972 | o_string output = NULL_O_STRING; | 4979 | o_string output = NULL_O_STRING; |
4973 | 4980 | ||
4974 | /* protect against globbing for "$var"? */ | 4981 | output.o_expflags = or_mask; |
4975 | /* (unquoted $var will temporarily switch it off) */ | ||
4976 | output.o_escape = 1 & (or_mask / EXPVAR_FLAG_ESCAPE_VARS); | ||
4977 | output.o_glob = 1 & (or_mask / EXPVAR_FLAG_GLOB); | ||
4978 | 4982 | ||
4979 | n = 0; | 4983 | n = 0; |
4980 | while (*argv) { | 4984 | while (*argv) { |
@@ -4991,13 +4995,13 @@ static char **expand_variables(char **argv, unsigned or_mask) | |||
4991 | 4995 | ||
4992 | static char **expand_strvec_to_strvec(char **argv) | 4996 | static char **expand_strvec_to_strvec(char **argv) |
4993 | { | 4997 | { |
4994 | return expand_variables(argv, EXPVAR_FLAG_GLOB | EXPVAR_FLAG_ESCAPE_VARS); | 4998 | return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); |
4995 | } | 4999 | } |
4996 | 5000 | ||
4997 | #if ENABLE_HUSH_BASH_COMPAT | 5001 | #if ENABLE_HUSH_BASH_COMPAT |
4998 | static char **expand_strvec_to_strvec_singleword_noglob(char **argv) | 5002 | static char **expand_strvec_to_strvec_singleword_noglob(char **argv) |
4999 | { | 5003 | { |
5000 | return expand_variables(argv, EXPVAR_FLAG_SINGLEWORD); | 5004 | return expand_variables(argv, EXP_FLAG_SINGLEWORD); |
5001 | } | 5005 | } |
5002 | #endif | 5006 | #endif |
5003 | 5007 | ||
@@ -5023,7 +5027,7 @@ static char *expand_string_to_string(const char *str) | |||
5023 | 5027 | ||
5024 | argv[0] = (char*)str; | 5028 | argv[0] = (char*)str; |
5025 | argv[1] = NULL; | 5029 | argv[1] = NULL; |
5026 | list = expand_variables(argv, EXPVAR_FLAG_ESCAPE_VARS | EXPVAR_FLAG_SINGLEWORD); | 5030 | list = expand_variables(argv, EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD); |
5027 | if (HUSH_DEBUG) | 5031 | if (HUSH_DEBUG) |
5028 | if (!list[0] || list[1]) | 5032 | if (!list[0] || list[1]) |
5029 | bb_error_msg_and_die("BUG in varexp2"); | 5033 | bb_error_msg_and_die("BUG in varexp2"); |
@@ -5039,7 +5043,7 @@ static char* expand_strvec_to_string(char **argv) | |||
5039 | { | 5043 | { |
5040 | char **list; | 5044 | char **list; |
5041 | 5045 | ||
5042 | list = expand_variables(argv, EXPVAR_FLAG_SINGLEWORD); | 5046 | list = expand_variables(argv, EXP_FLAG_SINGLEWORD); |
5043 | /* Convert all NULs to spaces */ | 5047 | /* Convert all NULs to spaces */ |
5044 | if (list[0]) { | 5048 | if (list[0]) { |
5045 | int n = 1; | 5049 | int n = 1; |