diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-17 12:09:21 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-17 12:09:21 +0000 |
commit | 6eaf8deddd3c2cd747b09fb038f9e56f18250714 (patch) | |
tree | 44cd58a2415de3951bd5d694a78139633f605fcf | |
parent | b6926109b70cd6989384ea6ac1dc9dd9f842efc4 (diff) | |
download | busybox-w32-6eaf8deddd3c2cd747b09fb038f9e56f18250714.tar.gz busybox-w32-6eaf8deddd3c2cd747b09fb038f9e56f18250714.tar.bz2 busybox-w32-6eaf8deddd3c2cd747b09fb038f9e56f18250714.zip |
hush: fix "for a in; do echo 'I should never run'; done" bug
-rw-r--r-- | shell/hush.c | 18 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/empty_for.right (renamed from shell/hush_test/hush-bugs/empty_for.right) | 0 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/empty_for.tests (renamed from shell/hush_test/hush-bugs/empty_for.tests) | 0 |
3 files changed, 10 insertions, 8 deletions
diff --git a/shell/hush.c b/shell/hush.c index ae12ebec4..45448c5f3 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -2004,7 +2004,7 @@ static int run_list(struct pipe *pi) | |||
2004 | || (rpipe->res_word == RES_FOR && rpipe->next->res_word != RES_IN) | 2004 | || (rpipe->res_word == RES_FOR && rpipe->next->res_word != RES_IN) |
2005 | ) { | 2005 | ) { |
2006 | /* TODO: what is tested in the first condition? */ | 2006 | /* TODO: what is tested in the first condition? */ |
2007 | syntax("malformed for"); /* 2nd condition: not followed by IN */ | 2007 | syntax("malformed for"); /* 2nd condition: FOR not followed by IN */ |
2008 | debug_printf_exec("run_list lvl %d return 1\n", run_list_level); | 2008 | debug_printf_exec("run_list lvl %d return 1\n", run_list_level); |
2009 | return 1; | 2009 | return 1; |
2010 | } | 2010 | } |
@@ -2898,7 +2898,8 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2898 | ctx->pending_redirect = NULL; | 2898 | ctx->pending_redirect = NULL; |
2899 | } | 2899 | } |
2900 | #if ENABLE_HUSH_LOOPS | 2900 | #if ENABLE_HUSH_LOOPS |
2901 | if (ctx->res_w == RES_FOR) { /* comment? */ | 2901 | /* comment? is it forcing "for" to have just one word (variable name)? */ |
2902 | if (ctx->res_w == RES_FOR) { | ||
2902 | //TESTING | 2903 | //TESTING |
2903 | //looks like (word->length == 0 && !word->nonnull) is true here, always | 2904 | //looks like (word->length == 0 && !word->nonnull) is true here, always |
2904 | //(due to o_reset). done_word would return at once. Why then? | 2905 | //(due to o_reset). done_word would return at once. Why then? |
@@ -2910,8 +2911,8 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2910 | return 0; | 2911 | return 0; |
2911 | } | 2912 | } |
2912 | 2913 | ||
2913 | /* The only possible error here is out of memory, in which case | 2914 | /* Command (member of a pipe) is complete. The only possible error here |
2914 | * xmalloc exits. */ | 2915 | * is out of memory, in which case xmalloc exits. */ |
2915 | static int done_command(struct p_context *ctx) | 2916 | static int done_command(struct p_context *ctx) |
2916 | { | 2917 | { |
2917 | /* The child is really already in the pipe structure, so | 2918 | /* The child is really already in the pipe structure, so |
@@ -2949,7 +2950,6 @@ static int done_command(struct p_context *ctx) | |||
2949 | 2950 | ||
2950 | static void done_pipe(struct p_context *ctx, pipe_style type) | 2951 | static void done_pipe(struct p_context *ctx, pipe_style type) |
2951 | { | 2952 | { |
2952 | struct pipe *new_p; | ||
2953 | int not_null; | 2953 | int not_null; |
2954 | 2954 | ||
2955 | debug_printf_parse("done_pipe entered, followup %d\n", type); | 2955 | debug_printf_parse("done_pipe entered, followup %d\n", type); |
@@ -2960,9 +2960,11 @@ static void done_pipe(struct p_context *ctx, pipe_style type) | |||
2960 | ctx->ctx_inverted = 0; | 2960 | ctx->ctx_inverted = 0; |
2961 | /* Without this check, even just <enter> on command line generates | 2961 | /* Without this check, even just <enter> on command line generates |
2962 | * tree of three NOPs (!). Which is harmless but annoying. | 2962 | * tree of three NOPs (!). Which is harmless but annoying. |
2963 | * IOW: it is safe to do it unconditionally. */ | 2963 | * IOW: it is safe to do it unconditionally. |
2964 | if (not_null) { | 2964 | * RES_IN case is for "for a in; do ..." (empty IN set) |
2965 | new_p = new_pipe(); | 2965 | * to work. */ |
2966 | if (not_null || ctx->pipe->res_word == RES_IN) { | ||
2967 | struct pipe *new_p = new_pipe(); | ||
2966 | ctx->pipe->next = new_p; | 2968 | ctx->pipe->next = new_p; |
2967 | ctx->pipe = new_p; | 2969 | ctx->pipe = new_p; |
2968 | ctx->child = NULL; /* needed! */ | 2970 | ctx->child = NULL; /* needed! */ |
diff --git a/shell/hush_test/hush-bugs/empty_for.right b/shell/hush_test/hush-misc/empty_for.right index 290d39b7e..290d39b7e 100644 --- a/shell/hush_test/hush-bugs/empty_for.right +++ b/shell/hush_test/hush-misc/empty_for.right | |||
diff --git a/shell/hush_test/hush-bugs/empty_for.tests b/shell/hush_test/hush-misc/empty_for.tests index 0cb52e849..0cb52e849 100755 --- a/shell/hush_test/hush-bugs/empty_for.tests +++ b/shell/hush_test/hush-misc/empty_for.tests | |||