aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-09-08 13:44:34 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-09-08 13:44:34 +0200
commit5b686cb8e6db85c0080ff8747c0fef7cb326dc20 (patch)
tree95f104213fcfbf70d48e7b59492eaf83b26edf95
parent9b78255dcaf79c99d337641a4135e402e00ee3a1 (diff)
downloadbusybox-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.c76
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
383enum {
384 EXP_FLAG_GLOB = 0x200,
385 EXP_FLAG_ESC_GLOB_CHARS = 0x100,
386 EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */
387};
388
383typedef struct o_string { 389typedef 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)
2035static void o_addQchr(o_string *o, int ch) 2040static 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
2077static void o_addQblock(o_string *o, const char *str, int len) 2084static 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 */
2450static int o_save_ptr(o_string *o, int n) 2460static 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
4963enum {
4964 EXPVAR_FLAG_GLOB = 0x200,
4965 EXPVAR_FLAG_ESCAPE_VARS = 0x100,
4966 EXPVAR_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */
4967};
4968static char **expand_variables(char **argv, unsigned or_mask) 4975static 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
4992static char **expand_strvec_to_strvec(char **argv) 4996static 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
4998static char **expand_strvec_to_strvec_singleword_noglob(char **argv) 5002static 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;