aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-14 17:13:20 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-14 17:13:20 +0000
commitf8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43 (patch)
tree3389ceea2b3b8db090cad74507acfa1c061c6a75 /shell
parentdd316dd283704b9adb588c3fb7cdec6ba5fbceb8 (diff)
downloadbusybox-w32-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.tar.gz
busybox-w32-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.tar.bz2
busybox-w32-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.zip
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
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c53
-rwxr-xr-xshell/hush_test/hush-misc/colon.tests3
-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-xshell/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 a84bb92dc..f4c170117 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -3437,11 +3437,11 @@ static int parse_group(o_string *dest, struct p_context *ctx,
3437 child->subshell = 1; 3437 child->subshell = 1;
3438 } 3438 }
3439 rcode = parse_stream(dest, &sub, input, endch); 3439 rcode = parse_stream(dest, &sub, input, endch);
3440//vda: err chk? 3440 if (rcode == 0) {
3441 done_word(dest, &sub); /* finish off the final word in the subcontext */ 3441 done_word(dest, &sub); /* finish off the final word in the subcontext */
3442 done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ 3442 done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */
3443 child->group = sub.list_head; 3443 child->group = sub.list_head;
3444 3444 }
3445 debug_printf_parse("parse_group return %d\n", rcode); 3445 debug_printf_parse("parse_group return %d\n", rcode);
3446 return rcode; 3446 return rcode;
3447 /* child remains "open", available for possible redirects */ 3447 /* child remains "open", available for possible redirects */
@@ -3700,11 +3700,19 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3700 done_pipe(ctx, PIPE_SEQ); 3700 done_pipe(ctx, PIPE_SEQ);
3701 } 3701 }
3702 } 3702 }
3703 if ((end_trigger && strchr(end_trigger, ch)) 3703 if (end_trigger) {
3704 && !dest->o_quote && ctx->res_w == RES_NONE 3704 if (!dest->o_quote && strchr(end_trigger, ch)) {
3705 ) { 3705 /* Special case: (...word) makes last word terminate,
3706 debug_printf_parse("parse_stream return 0: end_trigger char found\n"); 3706 * as if ';' is seen */
3707 return 0; 3707 if (ch == ')') {
3708 done_word(dest, ctx);
3709 done_pipe(ctx, PIPE_SEQ);
3710 }
3711 if (ctx->res_w == RES_NONE) {
3712 debug_printf_parse("parse_stream return 0: end_trigger char found\n");
3713 return 0;
3714 }
3715 }
3708 } 3716 }
3709 if (m == CHAR_IFS) 3717 if (m == CHAR_IFS)
3710 continue; 3718 continue;
@@ -3757,15 +3765,15 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3757 dest->nonnull = 1; 3765 dest->nonnull = 1;
3758 while (1) { 3766 while (1) {
3759 ch = i_getch(input); 3767 ch = i_getch(input);
3760 if (ch == EOF || ch == '\'') 3768 if (ch == EOF) {
3769 syntax("unterminated '");
3770 debug_printf_parse("parse_stream return 1: unterminated '\n");
3771 return 1;
3772 }
3773 if (ch == '\'')
3761 break; 3774 break;
3762 o_addqchr(dest, ch); 3775 o_addqchr(dest, ch);
3763 } 3776 }
3764 if (ch == EOF) {
3765 syntax("unterminated '");
3766 debug_printf_parse("parse_stream return 1: unterminated '\n");
3767 return 1;
3768 }
3769 break; 3777 break;
3770 case '"': 3778 case '"':
3771 dest->nonnull = 1; 3779 dest->nonnull = 1;
@@ -3861,7 +3869,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3861 if (ENABLE_HUSH_DEBUG) 3869 if (ENABLE_HUSH_DEBUG)
3862 bb_error_msg_and_die("BUG: unexpected %c\n", ch); 3870 bb_error_msg_and_die("BUG: unexpected %c\n", ch);
3863 } 3871 }
3864 } 3872 } /* while (1) */
3865 /* Complain if quote? No, maybe we just finished a command substitution 3873 /* Complain if quote? No, maybe we just finished a command substitution
3866 * that was quoted. Example: 3874 * that was quoted. Example:
3867 * $ echo "`cat foo` plus more" 3875 * $ echo "`cat foo` plus more"
@@ -3913,8 +3921,9 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
3913 struct p_context ctx; 3921 struct p_context ctx;
3914 o_string temp = NULL_O_STRING; 3922 o_string temp = NULL_O_STRING;
3915 int rcode; 3923 int rcode;
3924
3916 do { 3925 do {
3917// It always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit? 3926// parse_type always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit?
3918// After that, the whole parse_type fiels is not needed. 3927// After that, the whole parse_type fiels is not needed.
3919 ctx.parse_type = parse_flag; 3928 ctx.parse_type = parse_flag;
3920 initialize_context(&ctx); 3929 initialize_context(&ctx);
@@ -3938,17 +3947,21 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
3938 debug_printf_exec("parse_stream_outer: run_and_free_list\n"); 3947 debug_printf_exec("parse_stream_outer: run_and_free_list\n");
3939 run_and_free_list(ctx.list_head); 3948 run_and_free_list(ctx.list_head);
3940 } else { 3949 } else {
3950 /* We arrive here also if rcode == 1 (error in parse_stream) */
3941 if (ctx.old_flag != 0) { 3951 if (ctx.old_flag != 0) {
3942 free(ctx.stack); 3952 free(ctx.stack);
3943 o_reset(&temp); 3953 o_reset(&temp);
3944 } 3954 }
3945 temp.nonnull = 0; 3955 temp.nonnull = 0;
3946 temp.o_quote = 0; 3956 temp.o_quote = 0;
3947 inp->p = NULL;
3948 free_pipe_list(ctx.list_head, /* indent: */ 0); 3957 free_pipe_list(ctx.list_head, /* indent: */ 0);
3958 /* Discard all unprocessed line input, force prompt on */
3959 inp->p = NULL;
3960 inp->promptme = 1;
3949 } 3961 }
3950 o_free(&temp); 3962 o_free(&temp);
3951 } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ 3963 /* loop on syntax errors, return on EOF: */
3964 } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP));
3952 return 0; 3965 return 0;
3953} 3966}
3954 3967
diff --git a/shell/hush_test/hush-misc/colon.tests b/shell/hush_test/hush-misc/colon.tests
index ea3b4d5f3..cb8ab5306 100755
--- a/shell/hush_test/hush-misc/colon.tests
+++ b/shell/hush_test/hush-misc/colon.tests
@@ -1,6 +1,5 @@
1false 1false
2: 2:
3echo $? 3echo $?
4# Extra ; after done is due to a bug 4(while :; do exit; done)
5(while :; do exit; done;)
6echo OK: $? 5echo OK: $?
diff --git a/shell/hush_test/hush-bugs/while_in_subshell.right b/shell/hush_test/hush-misc/while_in_subshell.right
index 290d39b7e..290d39b7e 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 def8e092b..def8e092b 100755
--- a/shell/hush_test/hush-bugs/while_in_subshell.tests
+++ b/shell/hush_test/hush-misc/while_in_subshell.tests