diff options
author | Denis Vlasenko | 2008-06-14 17:13:20 +0000 |
---|---|---|
committer | Denis Vlasenko | 2008-06-14 17:13:20 +0000 |
commit | f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43 (patch) | |
tree | 3389ceea2b3b8db090cad74507acfa1c061c6a75 | |
parent | dd316dd283704b9adb588c3fb7cdec6ba5fbceb8 (diff) | |
download | busybox-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.zip busybox-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.tar.gz |
hush: fix a bug where we were requiring semicolon here: (cmd;)
also fix a bug where after error prompt is not shown.
function old new delta
parse_stream 1612 1638 +26
parse_and_run_stream 361 375 +14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 40/0) Total: 40 bytes
-rw-r--r-- | shell/hush.c | 53 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/colon.tests | 3 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/while_in_subshell.right (renamed from shell/hush_test/hush-bugs/while_in_subshell.right) | 0 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/while_in_subshell.tests (renamed from shell/hush_test/hush-bugs/while_in_subshell.tests) | 0 |
4 files changed, 34 insertions, 22 deletions
diff --git a/shell/hush.c b/shell/hush.c index a84bb92..f4c1701 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -3437,11 +3437,11 @@ static int parse_group(o_string *dest, struct p_context *ctx, child->subshell = 1; } rcode = parse_stream(dest, &sub, input, endch); -//vda: err chk? - done_word(dest, &sub); /* finish off the final word in the subcontext */ - done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ - child->group = sub.list_head; - + if (rcode == 0) { + done_word(dest, &sub); /* finish off the final word in the subcontext */ + done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ + child->group = sub.list_head; + } debug_printf_parse("parse_group return %d\n", rcode); return rcode; /* child remains "open", available for possible redirects */ @@ -3700,11 +3700,19 @@ static int parse_stream(o_string *dest, struct p_context *ctx, done_pipe(ctx, PIPE_SEQ); } } - if ((end_trigger && strchr(end_trigger, ch)) - && !dest->o_quote && ctx->res_w == RES_NONE - ) { - debug_printf_parse("parse_stream return 0: end_trigger char found\n"); - return 0; + if (end_trigger) { + if (!dest->o_quote && strchr(end_trigger, ch)) { + /* Special case: (...word) makes last word terminate, + * as if ';' is seen */ + if (ch == ')') { + done_word(dest, ctx); + done_pipe(ctx, PIPE_SEQ); + } + if (ctx->res_w == RES_NONE) { + debug_printf_parse("parse_stream return 0: end_trigger char found\n"); + return 0; + } + } } if (m == CHAR_IFS) continue; @@ -3757,15 +3765,15 @@ static int parse_stream(o_string *dest, struct p_context *ctx, dest->nonnull = 1; while (1) { ch = i_getch(input); - if (ch == EOF || ch == '\'') + if (ch == EOF) { + syntax("unterminated '"); + debug_printf_parse("parse_stream return 1: unterminated '\n"); + return 1; + } + if (ch == '\'') break; o_addqchr(dest, ch); } - if (ch == EOF) { - syntax("unterminated '"); - debug_printf_parse("parse_stream return 1: unterminated '\n"); - return 1; - } break; case '"': dest->nonnull = 1; @@ -3861,7 +3869,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx, if (ENABLE_HUSH_DEBUG) bb_error_msg_and_die("BUG: unexpected %c\n", ch); } - } + } /* while (1) */ /* Complain if quote? No, maybe we just finished a command substitution * that was quoted. Example: * $ echo "`cat foo` plus more" @@ -3913,8 +3921,9 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) struct p_context ctx; o_string temp = NULL_O_STRING; int rcode; + do { -// It always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit? +// parse_type always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit? // After that, the whole parse_type fiels is not needed. ctx.parse_type = parse_flag; initialize_context(&ctx); @@ -3938,17 +3947,21 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) debug_printf_exec("parse_stream_outer: run_and_free_list\n"); run_and_free_list(ctx.list_head); } else { + /* We arrive here also if rcode == 1 (error in parse_stream) */ if (ctx.old_flag != 0) { free(ctx.stack); o_reset(&temp); } temp.nonnull = 0; temp.o_quote = 0; - inp->p = NULL; free_pipe_list(ctx.list_head, /* indent: */ 0); + /* Discard all unprocessed line input, force prompt on */ + inp->p = NULL; + inp->promptme = 1; } o_free(&temp); - } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ + /* loop on syntax errors, return on EOF: */ + } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); return 0; } diff --git a/shell/hush_test/hush-misc/colon.tests b/shell/hush_test/hush-misc/colon.tests index ea3b4d5..cb8ab53 100755 --- a/shell/hush_test/hush-misc/colon.tests +++ b/shell/hush_test/hush-misc/colon.tests @@ -1,6 +1,5 @@ false : echo $? -# Extra ; after done is due to a bug -(while :; do exit; done;) +(while :; do exit; done) echo OK: $? diff --git a/shell/hush_test/hush-bugs/while_in_subshell.right b/shell/hush_test/hush-misc/while_in_subshell.right index 290d39b..290d39b 100644 --- a/shell/hush_test/hush-bugs/while_in_subshell.right +++ b/shell/hush_test/hush-misc/while_in_subshell.right diff --git a/shell/hush_test/hush-bugs/while_in_subshell.tests b/shell/hush_test/hush-misc/while_in_subshell.tests index def8e09..def8e09 100755 --- a/shell/hush_test/hush-bugs/while_in_subshell.tests +++ b/shell/hush_test/hush-misc/while_in_subshell.tests |