diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-10 12:03:20 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-10 12:03:20 +0000 |
commit | 1fd1ea4395e520694bd9f8b1dc9e60af6442946d (patch) | |
tree | ffe931a1e9254789ac119321f88b17767176c73c | |
parent | 551bdfecb7cfb4df0f127d34884e0a9502324acd (diff) | |
download | busybox-w32-1fd1ea4395e520694bd9f8b1dc9e60af6442946d.tar.gz busybox-w32-1fd1ea4395e520694bd9f8b1dc9e60af6442946d.tar.bz2 busybox-w32-1fd1ea4395e520694bd9f8b1dc9e60af6442946d.zip |
hush: tighten up "for" variable name check.
Add TODOs.
Disable redir4.right part where we differ from bash.
It is not a bug per standards.
Add a few tests, one is in hush-bugs section:
and_or_and_backgrounding.right. It will likely bite users
in real world usage.
-rw-r--r-- | shell/hush.c | 29 | ||||
-rw-r--r-- | shell/hush_test/hush-bugs/and_or_and_backgrounding.right | 4 | ||||
-rwxr-xr-x | shell/hush_test/hush-bugs/and_or_and_backgrounding.tests | 31 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/for_with_bslashes.right | 8 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/for_with_bslashes.tests | 10 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/redir1.tests | 2 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/redir4.right | 11 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/redir4.tests | 7 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/param_subshell.tests | 4 |
9 files changed, 82 insertions, 24 deletions
diff --git a/shell/hush.c b/shell/hush.c index bb4fdc295..422fc63f6 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -344,8 +344,7 @@ typedef enum redir_type { | |||
344 | 344 | ||
345 | REDIRFD_CLOSE = -3, | 345 | REDIRFD_CLOSE = -3, |
346 | REDIRFD_SYNTAX_ERR = -2, | 346 | REDIRFD_SYNTAX_ERR = -2, |
347 | REDIRFD_TO_FILE = -1, | 347 | REDIRFD_TO_FILE = -1, /* otherwise, rd_fd if redirected to rd_dup */ |
348 | /* otherwise, rd_fd is redirected to rd_dup */ | ||
349 | 348 | ||
350 | HEREDOC_SKIPTABS = 1, | 349 | HEREDOC_SKIPTABS = 1, |
351 | HEREDOC_QUOTED = 2, | 350 | HEREDOC_QUOTED = 2, |
@@ -3999,6 +3998,7 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
3999 | ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED; | 3998 | ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED; |
4000 | } | 3999 | } |
4001 | debug_printf_parse("word stored in rd_filename: '%s'\n", word->data); | 4000 | debug_printf_parse("word stored in rd_filename: '%s'\n", word->data); |
4001 | ctx->pending_redirect = NULL; | ||
4002 | } else { | 4002 | } else { |
4003 | /* If this word wasn't an assignment, next ones definitely | 4003 | /* If this word wasn't an assignment, next ones definitely |
4004 | * can't be assignments. Even if they look like ones. */ | 4004 | * can't be assignments. Even if they look like ones. */ |
@@ -4076,19 +4076,19 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
4076 | debug_print_strings("word appended to argv", command->argv); | 4076 | debug_print_strings("word appended to argv", command->argv); |
4077 | } | 4077 | } |
4078 | 4078 | ||
4079 | o_reset(word); | ||
4080 | ctx->pending_redirect = NULL; | ||
4081 | |||
4082 | #if ENABLE_HUSH_LOOPS | 4079 | #if ENABLE_HUSH_LOOPS |
4083 | /* Force FOR to have just one word (variable name) */ | ||
4084 | /* NB: basically, this makes hush see "for v in ..." syntax as if | ||
4085 | * as it is "for v; in ...". FOR and IN become two pipe structs | ||
4086 | * in parse tree. */ | ||
4087 | if (ctx->ctx_res_w == RES_FOR) { | 4080 | if (ctx->ctx_res_w == RES_FOR) { |
4088 | if (!is_well_formed_var_name(command->argv[0], '\0')) { | 4081 | if (word->o_quoted |
4089 | syntax_error("malformed variable name in for"); | 4082 | || !is_well_formed_var_name(command->argv[0], '\0') |
4083 | ) { | ||
4084 | /* bash says "not a valid identifier" */ | ||
4085 | syntax_error("not a valid identifier in for"); | ||
4090 | return 1; | 4086 | return 1; |
4091 | } | 4087 | } |
4088 | /* Force FOR to have just one word (variable name) */ | ||
4089 | /* NB: basically, this makes hush see "for v in ..." | ||
4090 | * syntax as if it is "for v; in ...". FOR and IN become | ||
4091 | * two pipe structs in parse tree. */ | ||
4092 | done_pipe(ctx, PIPE_SEQ); | 4092 | done_pipe(ctx, PIPE_SEQ); |
4093 | } | 4093 | } |
4094 | #endif | 4094 | #endif |
@@ -4098,6 +4098,9 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
4098 | done_pipe(ctx, PIPE_SEQ); | 4098 | done_pipe(ctx, PIPE_SEQ); |
4099 | } | 4099 | } |
4100 | #endif | 4100 | #endif |
4101 | |||
4102 | o_reset(word); | ||
4103 | |||
4101 | debug_printf_parse("done_word return 0\n"); | 4104 | debug_printf_parse("done_word return 0\n"); |
4102 | return 0; | 4105 | return 0; |
4103 | } | 4106 | } |
@@ -6197,6 +6200,8 @@ static int builtin_read(char **argv) | |||
6197 | 6200 | ||
6198 | if (argv[1]) { | 6201 | if (argv[1]) { |
6199 | name = argv[1]; | 6202 | name = argv[1]; |
6203 | /* bash (3.2.33(1)) bug: "read 0abcd" will execute, | ||
6204 | * and _after_ that_ it will complain */ | ||
6200 | if (!is_well_formed_var_name(name, '\0')) { | 6205 | if (!is_well_formed_var_name(name, '\0')) { |
6201 | /* Mimic bash message */ | 6206 | /* Mimic bash message */ |
6202 | bb_error_msg("read: '%s': not a valid identifier", name); | 6207 | bb_error_msg("read: '%s': not a valid identifier", name); |
@@ -6204,6 +6209,8 @@ static int builtin_read(char **argv) | |||
6204 | } | 6209 | } |
6205 | } | 6210 | } |
6206 | 6211 | ||
6212 | //TODO: bash unbackslashes input, splits words and puts them in argv[i] | ||
6213 | |||
6207 | string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name), NULL); | 6214 | string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name), NULL); |
6208 | return set_local_var(string, 0, 0); | 6215 | return set_local_var(string, 0, 0); |
6209 | } | 6216 | } |
diff --git a/shell/hush_test/hush-bugs/and_or_and_backgrounding.right b/shell/hush_test/hush-bugs/and_or_and_backgrounding.right new file mode 100644 index 000000000..90ce63e01 --- /dev/null +++ b/shell/hush_test/hush-bugs/and_or_and_backgrounding.right | |||
@@ -0,0 +1,4 @@ | |||
1 | First | ||
2 | Second | ||
3 | Third | ||
4 | Done | ||
diff --git a/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests b/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests new file mode 100755 index 000000000..05acfb863 --- /dev/null +++ b/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests | |||
@@ -0,0 +1,31 @@ | |||
1 | # UNFIXED BUG: hush thinks that ; && || & have the same precedence. | ||
2 | # According to this doc, && || have higher precedence than ; &. | ||
3 | # See example below. | ||
4 | # Precedence of ; is not a problem in practice. Precedence of & is. | ||
5 | # | ||
6 | #http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html | ||
7 | # | ||
8 | #2.9.3 Lists | ||
9 | # | ||
10 | #An AND-OR list is a sequence of one or more pipelines separated by | ||
11 | #the operators "&&" and "||" . | ||
12 | # | ||
13 | #A list is a sequence of one or more AND-OR lists separated by the operators | ||
14 | #';' and '&' and optionally terminated by ';', '&', or <newline>. | ||
15 | # | ||
16 | #The operators "&&" and "||" shall have equal precedence and shall be | ||
17 | #evaluated with left associativity. For example, both of the following | ||
18 | #commands write solely bar to standard output: | ||
19 | # | ||
20 | # false && echo foo || echo bar | ||
21 | # true || echo foo && echo bar | ||
22 | # | ||
23 | #A ';' or <newline> terminator shall cause the preceding AND-OR list | ||
24 | #to be executed sequentially; an '&' shall cause asynchronous execution | ||
25 | #of the preceding AND-OR list. | ||
26 | |||
27 | echo First && sleep 0.2 && echo Third & | ||
28 | sleep 0.1 | ||
29 | echo Second | ||
30 | wait | ||
31 | echo Done | ||
diff --git a/shell/hush_test/hush-misc/for_with_bslashes.right b/shell/hush_test/hush-misc/for_with_bslashes.right new file mode 100644 index 000000000..02d96692c --- /dev/null +++ b/shell/hush_test/hush-misc/for_with_bslashes.right | |||
@@ -0,0 +1,8 @@ | |||
1 | a | ||
2 | b\c | ||
3 | b\\c | ||
4 | b"c | ||
5 | b'c | ||
6 | b$c | ||
7 | b`true`c | ||
8 | Zero:0 | ||
diff --git a/shell/hush_test/hush-misc/for_with_bslashes.tests b/shell/hush_test/hush-misc/for_with_bslashes.tests new file mode 100755 index 000000000..363f3d85b --- /dev/null +++ b/shell/hush_test/hush-misc/for_with_bslashes.tests | |||
@@ -0,0 +1,10 @@ | |||
1 | # UNFIXED BUG. | ||
2 | # commented-out words contain ^C character. | ||
3 | # It's a SPECIAL_VAR_SYMBOL, for now hush does not escape it. | ||
4 | # When it is fixed, update this test. | ||
5 | |||
6 | for a in 'a' 'b\c' 'b\\c' 'b"c' "b'c" 'b$c' 'b`true`c' ### 'b#c' | ||
7 | do | ||
8 | echo $a | ||
9 | done | ||
10 | echo Zero:$? | ||
diff --git a/shell/hush_test/hush-misc/redir1.tests b/shell/hush_test/hush-misc/redir1.tests index 70e9e17f0..ef2fbfb77 100755 --- a/shell/hush_test/hush-misc/redir1.tests +++ b/shell/hush_test/hush-misc/redir1.tests | |||
@@ -27,7 +27,7 @@ var=ok | |||
27 | { var=bad >shell_test_$$; } & | 27 | { var=bad >shell_test_$$; } & |
28 | # cant use usleep as it isnt standard in $PATH -- | 28 | # cant use usleep as it isnt standard in $PATH -- |
29 | # we fail when testing busybox compiled solely as "hush" | 29 | # we fail when testing busybox compiled solely as "hush" |
30 | sleep 1 | 30 | wait |
31 | echo "Test 4: var:$var" | 31 | echo "Test 4: var:$var" |
32 | test -f shell_test_$$ && echo "File created:ok" | 32 | test -f shell_test_$$ && echo "File created:ok" |
33 | 33 | ||
diff --git a/shell/hush_test/hush-misc/redir4.right b/shell/hush_test/hush-misc/redir4.right index ada6c2d85..ead25f603 100644 --- a/shell/hush_test/hush-misc/redir4.right +++ b/shell/hush_test/hush-misc/redir4.right | |||
@@ -10,16 +10,9 @@ Here3 | |||
10 | Ok3 | 10 | Ok3 |
11 | Here4 | 11 | Here4 |
12 | Ok4 | 12 | Ok4 |
13 | How with variable refs | 13 | Now with variable refs |
14 | shell_test_1 | 14 | shell_test_1 |
15 | \shell_test_1 | 15 | \shell_test_1 |
16 | \shell_test_1 | 16 | \shell_test_1 |
17 | \shell_test_1 | 17 | \shell_test_1 |
18 | Here1 | 18 | Done |
19 | Ok1 | ||
20 | Here2 | ||
21 | Ok2 | ||
22 | Here3 | ||
23 | Ok3 | ||
24 | Here4 | ||
25 | Ok4 | ||
diff --git a/shell/hush_test/hush-misc/redir4.tests b/shell/hush_test/hush-misc/redir4.tests index ac2a44166..c50b8cedf 100755 --- a/shell/hush_test/hush-misc/redir4.tests +++ b/shell/hush_test/hush-misc/redir4.tests | |||
@@ -38,7 +38,7 @@ Here4 | |||
38 | echo Ok4 | 38 | echo Ok4 |
39 | 39 | ||
40 | 40 | ||
41 | echo How with variable refs | 41 | echo Now with variable refs |
42 | i=1 | 42 | i=1 |
43 | 43 | ||
44 | 44 | ||
@@ -58,6 +58,11 @@ rm *shell_test* | |||
58 | echo *shell_test* | 58 | echo *shell_test* |
59 | rm *shell_test* | 59 | rm *shell_test* |
60 | 60 | ||
61 | echo Done;exit | ||
62 | # UNFIXED BUG. bash apparently will expand $i even in terminating delimiter. | ||
63 | # http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html | ||
64 | # does not mandate this behavior. | ||
65 | # This is not likely to be used much in real-world. | ||
61 | 66 | ||
62 | cat <<\shell_test_$i | 67 | cat <<\shell_test_$i |
63 | Here1 | 68 | Here1 |
diff --git a/shell/hush_test/hush-vars/param_subshell.tests b/shell/hush_test/hush-vars/param_subshell.tests index 565a84589..27fdc5b9b 100755 --- a/shell/hush_test/hush-vars/param_subshell.tests +++ b/shell/hush_test/hush-vars/param_subshell.tests | |||
@@ -7,9 +7,9 @@ echo 1=$1 | |||
7 | { echo 3=$3; } & | 7 | { echo 3=$3; } & |
8 | # cant use usleep as it isnt standard in $PATH -- | 8 | # cant use usleep as it isnt standard in $PATH -- |
9 | # we fail when testing busybox compiled solely as "hush" | 9 | # we fail when testing busybox compiled solely as "hush" |
10 | sleep 1 | 10 | wait |
11 | ( echo 4=$4 ) | 11 | ( echo 4=$4 ) |
12 | ( echo 5=$5 ) & | 12 | ( echo 5=$5 ) & |
13 | sleep 1 | 13 | wait |
14 | true | echo 6=$6 | cat | 14 | true | echo 6=$6 | cat |
15 | true | { echo 7=$7; } | cat | 15 | true | { echo 7=$7; } | cat |