aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-17 07:24:29 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-17 07:24:29 +0000
commit30c9cc5b178932bc417846919eaa2fc1bf8e5996 (patch)
tree57e6d113f605411ee3fe272fdc0746d7f189f71c
parentc7985b76c5174c4c224b67e29dd554443f80f47e (diff)
downloadbusybox-w32-30c9cc5b178932bc417846919eaa2fc1bf8e5996.tar.gz
busybox-w32-30c9cc5b178932bc417846919eaa2fc1bf8e5996.tar.bz2
busybox-w32-30c9cc5b178932bc417846919eaa2fc1bf8e5996.zip
hush: continue fixing quoting and subst: fix glob_and_assign.tests.
-rw-r--r--shell/hush.c73
-rw-r--r--shell/hush_test/hush-bugs/glob_and_assign.right8
-rwxr-xr-xshell/hush_test/hush-bugs/glob_and_assign.tests26
-rwxr-xr-xshell/hush_test/run-all9
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 @@
106#define debug_printf_expand(...) do {} while (0) 106#define debug_printf_expand(...) do {} while (0)
107#define debug_printf_glob(...) do {} while (0) 107#define debug_printf_glob(...) do {} while (0)
108#define debug_printf_list(...) do {} while (0) 108#define debug_printf_list(...) do {} while (0)
109#define debug_printf_subst(...) do {} while (0)
109#define debug_printf_clean(...) do {} while (0) 110#define debug_printf_clean(...) do {} while (0)
110 111
111#ifndef debug_printf 112#ifndef debug_printf
@@ -145,6 +146,10 @@
145#define debug_printf_list(...) fprintf(stderr, __VA_ARGS__) 146#define debug_printf_list(...) fprintf(stderr, __VA_ARGS__)
146#endif 147#endif
147 148
149#ifndef debug_printf_subst
150#define debug_printf_subst(...) fprintf(stderr, __VA_ARGS__)
151#endif
152
148/* Keep unconditionally on for now */ 153/* Keep unconditionally on for now */
149#define ENABLE_HUSH_DEBUG 1 154#define ENABLE_HUSH_DEBUG 1
150 155
@@ -516,8 +521,6 @@ static int run_list(struct pipe *pi);
516static void pseudo_exec_argv(char **ptrs2free, char **argv) ATTRIBUTE_NORETURN; 521static void pseudo_exec_argv(char **ptrs2free, char **argv) ATTRIBUTE_NORETURN;
517static void pseudo_exec(char **ptrs2free, struct child_prog *child) ATTRIBUTE_NORETURN; 522static void pseudo_exec(char **ptrs2free, struct child_prog *child) ATTRIBUTE_NORETURN;
518static int run_pipe(struct pipe *pi); 523static int run_pipe(struct pipe *pi);
519/* variable assignment: */
520static int is_assignment(const char *s);
521/* data structure manipulation: */ 524/* data structure manipulation: */
522static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); 525static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
523static void initialize_context(struct p_context *ctx); 526static void initialize_context(struct p_context *ctx);
@@ -573,6 +576,16 @@ static int glob_needed(const char *s)
573 return 0; 576 return 0;
574} 577}
575 578
579static int is_assignment(const char *s)
580{
581 if (!s || !isalpha(*s))
582 return 0;
583 s++;
584 while (isalnum(*s) || *s == '_')
585 s++;
586 return *s == '=';
587}
588
576static char **add_malloced_strings_to_strings(char **strings, char **add) 589static char **add_malloced_strings_to_strings(char **strings, char **add)
577{ 590{
578 int i; 591 int i;
@@ -938,7 +951,7 @@ static void o_addQstr(o_string *o, const char *str, int len)
938 if (ordinary_cnt == len) 951 if (ordinary_cnt == len)
939 return; 952 return;
940 str += ordinary_cnt; 953 str += ordinary_cnt;
941 len -= ordinary_cnt - 1; /* we are processing + 1 char below */ 954 len -= ordinary_cnt + 1; /* we are processing + 1 char below */
942 955
943 ch = *str++; 956 ch = *str++;
944 sz = 1; 957 sz = 1;
@@ -1000,7 +1013,7 @@ static int o_save_ptr_helper(o_string *o, int n)
1000 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); 1013 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
1001 string_len = o->length - string_start; 1014 string_len = o->length - string_start;
1002 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */ 1015 if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
1003 debug_printf_list("list[%d]=%d string_start=%d (growing)", n, string_len, string_start); 1016 debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
1004 /* list[n] points to string_start, make space for 16 more pointers */ 1017 /* list[n] points to string_start, make space for 16 more pointers */
1005 o->maxlen += 0x10 * sizeof(list[0]); 1018 o->maxlen += 0x10 * sizeof(list[0]);
1006 o->data = xrealloc(o->data, o->maxlen + 1); 1019 o->data = xrealloc(o->data, o->maxlen + 1);
@@ -1008,12 +1021,12 @@ static int o_save_ptr_helper(o_string *o, int n)
1008 memmove(list + n + 0x10, list + n, string_len); 1021 memmove(list + n + 0x10, list + n, string_len);
1009 o->length += 0x10 * sizeof(list[0]); 1022 o->length += 0x10 * sizeof(list[0]);
1010 } else 1023 } else
1011 debug_printf_list("list[%d]=%d string_start=%d", n, string_len, string_start); 1024 debug_printf_list("list[%d]=%d string_start=%d\n", n, string_len, string_start);
1012 } else { 1025 } else {
1013 /* We have empty slot at list[n], reuse without growth */ 1026 /* We have empty slot at list[n], reuse without growth */
1014 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */ 1027 string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
1015 string_len = o->length - string_start; 1028 string_len = o->length - string_start;
1016 debug_printf_list("list[%d]=%d string_start=%d (empty slot)", n, string_len, string_start); 1029 debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n", n, string_len, string_start);
1017 o->has_empty_slot = 0; 1030 o->has_empty_slot = 0;
1018 } 1031 }
1019 list[n] = (char*)string_len; 1032 list[n] = (char*)string_len;
@@ -1048,15 +1061,15 @@ static int o_glob(o_string *o, int n)
1048 int gr; 1061 int gr;
1049 char *pattern; 1062 char *pattern;
1050 1063
1051 debug_printf_glob("start o_glob: n:%d o->data:%p", n, o->data); 1064 debug_printf_glob("start o_glob: n:%d o->data:%p\n", n, o->data);
1052 if (!o->data) 1065 if (!o->data)
1053 return o_save_ptr_helper(o, n); 1066 return o_save_ptr_helper(o, n);
1054 pattern = o->data + o_get_last_ptr(o, n); 1067 pattern = o->data + o_get_last_ptr(o, n);
1055 debug_printf_glob("glob pattern '%s'", pattern); 1068 debug_printf_glob("glob pattern '%s'\n", pattern);
1056 if (!glob_needed(pattern)) { 1069 if (!glob_needed(pattern)) {
1057 literal: 1070 literal:
1058 o->length = unbackslash(pattern) - o->data; 1071 o->length = unbackslash(pattern) - o->data;
1059 debug_printf_glob("glob pattern '%s' is literal", pattern); 1072 debug_printf_glob("glob pattern '%s' is literal\n", pattern);
1060 return o_save_ptr_helper(o, n); 1073 return o_save_ptr_helper(o, n);
1061 } 1074 }
1062 1075
@@ -1108,7 +1121,7 @@ static char **o_finalize_list(o_string *o, int n)
1108 n = o_save_ptr(o, n); /* force growth for list[n] if necessary */ 1121 n = o_save_ptr(o, n); /* force growth for list[n] if necessary */
1109 if (DEBUG_EXPAND) 1122 if (DEBUG_EXPAND)
1110 debug_print_list("finalized", o, n); 1123 debug_print_list("finalized", o, n);
1111 debug_printf_expand("finalized n:%d", n); 1124 debug_printf_expand("finalized n:%d\n", n);
1112 list = (char**)o->data; 1125 list = (char**)o->data;
1113 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]); 1126 string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
1114 list[--n] = NULL; 1127 list[--n] = NULL;
@@ -2285,7 +2298,7 @@ static int expand_on_ifs(o_string *output, int n, const char *str)
2285 while (1) { 2298 while (1) {
2286 int word_len = strcspn(str, ifs); 2299 int word_len = strcspn(str, ifs);
2287 if (word_len) { 2300 if (word_len) {
2288 o_addQstr(output, str, word_len); 2301 o_addstr(output, str, word_len);
2289 str += word_len; 2302 str += word_len;
2290 } 2303 }
2291 if (!*str) /* EOL - do not finalize word */ 2304 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)
2328 o_string subst_result = NULL_O_STRING; 2341 o_string subst_result = NULL_O_STRING;
2329#endif 2342#endif
2330 2343
2331 o_addQstr(output, arg, p - arg); 2344 o_addstr(output, arg, p - arg);
2332 debug_print_list("expand_vars_to_list[1]", output, n); 2345 debug_print_list("expand_vars_to_list[1]", output, n);
2333 arg = ++p; 2346 arg = ++p;
2334 p = strchr(p, SPECIAL_VAR_SYMBOL); 2347 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)
2374 * and in this case should treat it like '$*' - see 'else...' below */ 2387 * and in this case should treat it like '$*' - see 'else...' below */
2375 if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */ 2388 if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */
2376 while (1) { 2389 while (1) {
2377 o_addQstr(output, global_argv[i], strlen(global_argv[i])); 2390 o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q?
2378 if (++i >= global_argc) 2391 if (++i >= global_argc)
2379 break; 2392 break;
2380 o_addchr(output, '\0'); 2393 o_addchr(output, '\0');
@@ -2383,7 +2396,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2383 } 2396 }
2384 } else { /* quoted $*: add as one word */ 2397 } else { /* quoted $*: add as one word */
2385 while (1) { 2398 while (1) {
2386 o_addQstr(output, global_argv[i], strlen(global_argv[i])); 2399 o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q?
2387 if (!global_argv[++i]) 2400 if (!global_argv[++i])
2388 break; 2401 break;
2389 if (ifs[0]) 2402 if (ifs[0])
@@ -2397,10 +2410,10 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2397 *p = '\0'; 2410 *p = '\0';
2398 arg++; 2411 arg++;
2399//TODO: can we just stuff it into "output" directly? 2412//TODO: can we just stuff it into "output" directly?
2400 //bb_error_msg("SUBST '%s' first_ch %x", arg, first_ch); 2413 debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
2401 setup_string_in_str(&input, arg); 2414 setup_string_in_str(&input, arg);
2402 process_command_subs(&subst_result, &input, NULL); 2415 process_command_subs(&subst_result, &input, NULL);
2403 //bb_error_msg("RES '%s'", subst_result.data); 2416 debug_printf_subst("SUBST RES '%s'\n", subst_result.data);
2404 val = subst_result.data; 2417 val = subst_result.data;
2405 goto store_val; 2418 goto store_val;
2406 } 2419 }
@@ -2421,14 +2434,16 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2421#endif 2434#endif
2422 *p = SPECIAL_VAR_SYMBOL; 2435 *p = SPECIAL_VAR_SYMBOL;
2423 if (!(first_ch & 0x80)) { /* unquoted $VAR */ 2436 if (!(first_ch & 0x80)) { /* unquoted $VAR */
2437 debug_printf_expand("unquoted '%s', output->o_quote:%d\n", val, output->o_quote);
2424 if (val) { 2438 if (val) {
2425 n = expand_on_ifs(output, n, val); 2439 n = expand_on_ifs(output, n, val);
2426 val = NULL; 2440 val = NULL;
2427 } 2441 }
2428 } /* else: quoted $VAR, val will be appended below */ 2442 } else /* quoted $VAR, val will be appended below */
2443 debug_printf_expand("quoted '%s', output->o_quote:%d\n", val, output->o_quote);
2429 } 2444 }
2430 if (val) { 2445 if (val) {
2431 o_addQstr(output, val, strlen(val)); 2446 o_addQstr(output, val, strlen(val)); ///maybe q?
2432 } 2447 }
2433 2448
2434#if ENABLE_HUSH_TICK 2449#if ENABLE_HUSH_TICK
@@ -2439,7 +2454,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2439 2454
2440 if (arg[0]) { 2455 if (arg[0]) {
2441 debug_print_list("expand_vars_to_list[a]", output, n); 2456 debug_print_list("expand_vars_to_list[a]", output, n);
2442 o_addQstr(output, arg, strlen(arg) + 1); 2457 /* this part is literal, and it was already pre-quoted
2458 * if needed (much earlier), do not use o_addQstr here! */
2459 o_addstr(output, arg, strlen(arg) + 1);
2443 debug_print_list("expand_vars_to_list[b]", output, n); 2460 debug_print_list("expand_vars_to_list[b]", output, n);
2444 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ 2461 } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
2445 && !(ored_ch & 0x80) /* and all vars were not quoted. */ 2462 && !(ored_ch & 0x80) /* and all vars were not quoted. */
@@ -2460,8 +2477,10 @@ static char **expand_variables(char **argv, int or_mask)
2460 char **v; 2477 char **v;
2461 o_string output = NULL_O_STRING; 2478 o_string output = NULL_O_STRING;
2462 2479
2463 if (or_mask & 0x100) 2480 if (or_mask & 0x100) {
2481 output.o_quote = 1;
2464 output.o_glob = 1; 2482 output.o_glob = 1;
2483 }
2465 2484
2466 n = 0; 2485 n = 0;
2467 v = argv; 2486 v = argv;
@@ -2637,16 +2656,6 @@ static void unset_local_var(const char *name)
2637 } 2656 }
2638} 2657}
2639 2658
2640static int is_assignment(const char *s)
2641{
2642 if (!s || !isalpha(*s))
2643 return 0;
2644 s++;
2645 while (isalnum(*s) || *s == '_')
2646 s++;
2647 return *s == '=';
2648}
2649
2650/* the src parameter allows us to peek forward to a possible &n syntax 2659/* the src parameter allows us to peek forward to a possible &n syntax
2651 * for file descriptor duplication, e.g., "2>&1". 2660 * for file descriptor duplication, e.g., "2>&1".
2652 * Return code is 0 normally, 1 if a syntax error is detected in src. 2661 * 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)
3341 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3350 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3342 o_addchr(dest, quote_mask | '`'); 3351 o_addchr(dest, quote_mask | '`');
3343 add_till_closing_curly_brace(dest, input); 3352 add_till_closing_curly_brace(dest, input);
3344 //bb_error_msg("RES '%s'", dest->data + pos); 3353 //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
3345 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3354 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3346 break; 3355 break;
3347 } 3356 }
@@ -3496,7 +3505,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3496 o_addchr(dest, dest->o_quote ? 0x80 | '`' : '`'); 3505 o_addchr(dest, dest->o_quote ? 0x80 | '`' : '`');
3497 add_till_backquote(dest, input); 3506 add_till_backquote(dest, input);
3498 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3507 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3499 //bb_error_msg("RES '%s'", dest->data + pos); 3508 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
3500 break; 3509 break;
3501 } 3510 }
3502#endif 3511#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 @@
1ZVAR=z.map 1ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
2*.map 2ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
3*.tmp
4ZVAR=z.tmp z.tmp
5ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
6ZVAR=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 @@
1## # bash zbad2 1>ZVAR=z.tmp
2## ZVAR=z.map 2>z.tmp
3## *.map 3ZVAR=*.tmp echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
4## # hush zbad2 4ZVAR=*.tmp /bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
5## ZVAR=z.map 5ZVAR=*.tmp
6## z.map <====== !!!
7
8## hush does globbing for "VAR=val" too!
9## it should do it only for non-assignments.
10## even if word looks like assignment, it can be non-assignment:
11## ZVAR=*.map /bin/echo ZVAR=*.map
12## ^dont_glob ^glob
13
14>ZVAR=z.map
15ZVAR=*.map /bin/echo ZVAR=*.map
16ZVAR=*.map
17echo "$ZVAR" 6echo "$ZVAR"
18rm ZVAR=z.map 7echo $ZVAR
8echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
9/bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
10rm 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 @@
1#!/bin/sh 1#!/bin/sh
2 2
3unset LANG LANGUAGE
4unset LC_COLLATE
5unset LC_CTYPE
6unset LC_MONETARY
7unset LC_MESSAGES
8unset LC_NUMERIC
9unset LC_TIME
10unset LC_ALL
11
3test -x hush || { 12test -x hush || {
4 echo "No ./hush - creating a link to ../../busybox" 13 echo "No ./hush - creating a link to ../../busybox"
5 ln -s ../../busybox hush 14 ln -s ../../busybox hush