aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-03-24 05:25:59 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2011-03-24 05:25:59 +0100
commit3eab24e64a65746ed9fcc5bed3e9a19a489b0573 (patch)
treed22ebcecadb99fcb4ec94f1b461b39e3910a014c /shell
parent68d5cb5dacbc80347119ac9cff365e5f04105ef1 (diff)
downloadbusybox-w32-3eab24e64a65746ed9fcc5bed3e9a19a489b0573.tar.gz
busybox-w32-3eab24e64a65746ed9fcc5bed3e9a19a489b0573.tar.bz2
busybox-w32-3eab24e64a65746ed9fcc5bed3e9a19a489b0573.zip
hush: make parse errors in sourced file non-fatal in interactive script
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c97
1 files changed, 52 insertions, 45 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 8154ac47b..e4c3a7d77 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1095,17 +1095,10 @@ static void syntax_error_unterm_str(unsigned lineno, const char *s)
1095 die_if_script(lineno, "syntax error: unterminated %s", s); 1095 die_if_script(lineno, "syntax error: unterminated %s", s);
1096} 1096}
1097 1097
1098/* It so happens that all such cases are totally fatal
1099 * even if shell is interactive: EOF while looking for closing
1100 * delimiter. There is nowhere to read stuff from after that,
1101 * it's EOF! The only choice is to terminate.
1102 */
1103static void syntax_error_unterm_ch(unsigned lineno, char ch) NORETURN;
1104static void syntax_error_unterm_ch(unsigned lineno, char ch) 1098static void syntax_error_unterm_ch(unsigned lineno, char ch)
1105{ 1099{
1106 char msg[2] = { ch, '\0' }; 1100 char msg[2] = { ch, '\0' };
1107 syntax_error_unterm_str(lineno, msg); 1101 syntax_error_unterm_str(lineno, msg);
1108 xfunc_die();
1109} 1102}
1110 1103
1111static void syntax_error_unexpected_ch(unsigned lineno, int ch) 1104static void syntax_error_unexpected_ch(unsigned lineno, int ch)
@@ -3539,39 +3532,40 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
3539 3532
3540#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS 3533#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS
3541/* Subroutines for copying $(...) and `...` things */ 3534/* Subroutines for copying $(...) and `...` things */
3542static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); 3535static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
3543/* '...' */ 3536/* '...' */
3544static void add_till_single_quote(o_string *dest, struct in_str *input) 3537static int add_till_single_quote(o_string *dest, struct in_str *input)
3545{ 3538{
3546 while (1) { 3539 while (1) {
3547 int ch = i_getch(input); 3540 int ch = i_getch(input);
3548 if (ch == EOF) { 3541 if (ch == EOF) {
3549 syntax_error_unterm_ch('\''); 3542 syntax_error_unterm_ch('\'');
3550 /*xfunc_die(); - redundant */ 3543 return 0;
3551 } 3544 }
3552 if (ch == '\'') 3545 if (ch == '\'')
3553 return; 3546 return 1;
3554 o_addchr(dest, ch); 3547 o_addchr(dest, ch);
3555 } 3548 }
3556} 3549}
3557/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ 3550/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
3558static void add_till_double_quote(o_string *dest, struct in_str *input) 3551static int add_till_double_quote(o_string *dest, struct in_str *input)
3559{ 3552{
3560 while (1) { 3553 while (1) {
3561 int ch = i_getch(input); 3554 int ch = i_getch(input);
3562 if (ch == EOF) { 3555 if (ch == EOF) {
3563 syntax_error_unterm_ch('"'); 3556 syntax_error_unterm_ch('"');
3564 /*xfunc_die(); - redundant */ 3557 return 0;
3565 } 3558 }
3566 if (ch == '"') 3559 if (ch == '"')
3567 return; 3560 return 1;
3568 if (ch == '\\') { /* \x. Copy both chars. */ 3561 if (ch == '\\') { /* \x. Copy both chars. */
3569 o_addchr(dest, ch); 3562 o_addchr(dest, ch);
3570 ch = i_getch(input); 3563 ch = i_getch(input);
3571 } 3564 }
3572 o_addchr(dest, ch); 3565 o_addchr(dest, ch);
3573 if (ch == '`') { 3566 if (ch == '`') {
3574 add_till_backquote(dest, input, /*in_dquote:*/ 1); 3567 if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
3568 return 0;
3575 o_addchr(dest, ch); 3569 o_addchr(dest, ch);
3576 continue; 3570 continue;
3577 } 3571 }
@@ -3592,12 +3586,12 @@ static void add_till_double_quote(o_string *dest, struct in_str *input)
3592 * Example Output 3586 * Example Output
3593 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST 3587 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST
3594 */ 3588 */
3595static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote) 3589static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
3596{ 3590{
3597 while (1) { 3591 while (1) {
3598 int ch = i_getch(input); 3592 int ch = i_getch(input);
3599 if (ch == '`') 3593 if (ch == '`')
3600 return; 3594 return 1;
3601 if (ch == '\\') { 3595 if (ch == '\\') {
3602 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */ 3596 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
3603 ch = i_getch(input); 3597 ch = i_getch(input);
@@ -3611,7 +3605,7 @@ static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquo
3611 } 3605 }
3612 if (ch == EOF) { 3606 if (ch == EOF) {
3613 syntax_error_unterm_ch('`'); 3607 syntax_error_unterm_ch('`');
3614 /*xfunc_die(); - redundant */ 3608 return 0;
3615 } 3609 }
3616 o_addchr(dest, ch); 3610 o_addchr(dest, ch);
3617 } 3611 }
@@ -3647,7 +3641,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
3647 ch = i_getch(input); 3641 ch = i_getch(input);
3648 if (ch == EOF) { 3642 if (ch == EOF) {
3649 syntax_error_unterm_ch(end_ch); 3643 syntax_error_unterm_ch(end_ch);
3650 /*xfunc_die(); - redundant */ 3644 return 0;
3651 } 3645 }
3652 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) { 3646 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) {
3653 if (!dbl) 3647 if (!dbl)
@@ -3661,22 +3655,26 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
3661 o_addchr(dest, ch); 3655 o_addchr(dest, ch);
3662 if (ch == '(' || ch == '{') { 3656 if (ch == '(' || ch == '{') {
3663 ch = (ch == '(' ? ')' : '}'); 3657 ch = (ch == '(' ? ')' : '}');
3664 add_till_closing_bracket(dest, input, ch); 3658 if (!add_till_closing_bracket(dest, input, ch))
3659 return 0;
3665 o_addchr(dest, ch); 3660 o_addchr(dest, ch);
3666 continue; 3661 continue;
3667 } 3662 }
3668 if (ch == '\'') { 3663 if (ch == '\'') {
3669 add_till_single_quote(dest, input); 3664 if (!add_till_single_quote(dest, input))
3665 return 0;
3670 o_addchr(dest, ch); 3666 o_addchr(dest, ch);
3671 continue; 3667 continue;
3672 } 3668 }
3673 if (ch == '"') { 3669 if (ch == '"') {
3674 add_till_double_quote(dest, input); 3670 if (!add_till_double_quote(dest, input))
3671 return 0;
3675 o_addchr(dest, ch); 3672 o_addchr(dest, ch);
3676 continue; 3673 continue;
3677 } 3674 }
3678 if (ch == '`') { 3675 if (ch == '`') {
3679 add_till_backquote(dest, input, /*in_dquote:*/ 0); 3676 if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
3677 return 0;
3680 o_addchr(dest, ch); 3678 o_addchr(dest, ch);
3681 continue; 3679 continue;
3682 } 3680 }
@@ -3685,7 +3683,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
3685 ch = i_getch(input); 3683 ch = i_getch(input);
3686 if (ch == EOF) { 3684 if (ch == EOF) {
3687 syntax_error_unterm_ch(')'); 3685 syntax_error_unterm_ch(')');
3688 /*xfunc_die(); - redundant */ 3686 return 0;
3689 } 3687 }
3690 o_addchr(dest, ch); 3688 o_addchr(dest, ch);
3691 continue; 3689 continue;
@@ -3756,8 +3754,8 @@ static int parse_dollar(o_string *as_string,
3756 ) { 3754 ) {
3757 bad_dollar_syntax: 3755 bad_dollar_syntax:
3758 syntax_error_unterm_str("${name}"); 3756 syntax_error_unterm_str("${name}");
3759 debug_printf_parse("parse_dollar return 1: unterminated ${name}\n"); 3757 debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
3760 return 1; 3758 return 0;
3761 } 3759 }
3762 nommu_addchr(as_string, ch); 3760 nommu_addchr(as_string, ch);
3763 ch |= quote_mask; 3761 ch |= quote_mask;
@@ -3813,6 +3811,8 @@ static int parse_dollar(o_string *as_string,
3813 pos = dest->length; 3811 pos = dest->length;
3814#if ENABLE_HUSH_DOLLAR_OPS 3812#if ENABLE_HUSH_DOLLAR_OPS
3815 last_ch = add_till_closing_bracket(dest, input, end_ch); 3813 last_ch = add_till_closing_bracket(dest, input, end_ch);
3814 if (last_ch == 0) /* error? */
3815 return 0;
3816#else 3816#else
3817#error Simple code to only allow ${var} is not implemented 3817#error Simple code to only allow ${var} is not implemented
3818#endif 3818#endif
@@ -3857,7 +3857,8 @@ static int parse_dollar(o_string *as_string,
3857 o_addchr(dest, /*quote_mask |*/ '+'); 3857 o_addchr(dest, /*quote_mask |*/ '+');
3858 if (!BB_MMU) 3858 if (!BB_MMU)
3859 pos = dest->length; 3859 pos = dest->length;
3860 add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG); 3860 if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
3861 return 0; /* error */
3861 if (as_string) { 3862 if (as_string) {
3862 o_addstr(as_string, dest->data + pos); 3863 o_addstr(as_string, dest->data + pos);
3863 o_addchr(as_string, ')'); 3864 o_addchr(as_string, ')');
@@ -3872,7 +3873,8 @@ static int parse_dollar(o_string *as_string,
3872 o_addchr(dest, quote_mask | '`'); 3873 o_addchr(dest, quote_mask | '`');
3873 if (!BB_MMU) 3874 if (!BB_MMU)
3874 pos = dest->length; 3875 pos = dest->length;
3875 add_till_closing_bracket(dest, input, ')'); 3876 if (!add_till_closing_bracket(dest, input, ')'))
3877 return 0; /* error */
3876 if (as_string) { 3878 if (as_string) {
3877 o_addstr(as_string, dest->data + pos); 3879 o_addstr(as_string, dest->data + pos);
3878 o_addchr(as_string, ')'); 3880 o_addchr(as_string, ')');
@@ -3899,8 +3901,8 @@ static int parse_dollar(o_string *as_string,
3899 default: 3901 default:
3900 o_addQchr(dest, '$'); 3902 o_addQchr(dest, '$');
3901 } 3903 }
3902 debug_printf_parse("parse_dollar return 0\n"); 3904 debug_printf_parse("parse_dollar return 1 (ok)\n");
3903 return 0; 3905 return 1;
3904#undef as_string 3906#undef as_string
3905} 3907}
3906 3908
@@ -3941,13 +3943,13 @@ static int encode_string(o_string *as_string,
3941 if (ch != EOF) 3943 if (ch != EOF)
3942 nommu_addchr(as_string, ch); 3944 nommu_addchr(as_string, ch);
3943 if (ch == dquote_end) { /* may be only '"' or EOF */ 3945 if (ch == dquote_end) { /* may be only '"' or EOF */
3944 debug_printf_parse("encode_string return 0\n"); 3946 debug_printf_parse("encode_string return 1 (ok)\n");
3945 return 0; 3947 return 1;
3946 } 3948 }
3947 /* note: can't move it above ch == dquote_end check! */ 3949 /* note: can't move it above ch == dquote_end check! */
3948 if (ch == EOF) { 3950 if (ch == EOF) {
3949 syntax_error_unterm_ch('"'); 3951 syntax_error_unterm_ch('"');
3950 /*xfunc_die(); - redundant */ 3952 return 0; /* error */
3951 } 3953 }
3952 next = '\0'; 3954 next = '\0';
3953 if (ch != '\n') { 3955 if (ch != '\n') {
@@ -3978,10 +3980,10 @@ static int encode_string(o_string *as_string,
3978 goto again; 3980 goto again;
3979 } 3981 }
3980 if (ch == '$') { 3982 if (ch == '$') {
3981 if (parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80) != 0) { 3983 if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
3982 debug_printf_parse("encode_string return 1: " 3984 debug_printf_parse("encode_string return 0: "
3983 "parse_dollar returned non-0\n"); 3985 "parse_dollar returned 0 (error)\n");
3984 return 1; 3986 return 0;
3985 } 3987 }
3986 goto again; 3988 goto again;
3987 } 3989 }
@@ -3990,7 +3992,8 @@ static int encode_string(o_string *as_string,
3990 //unsigned pos = dest->length; 3992 //unsigned pos = dest->length;
3991 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3993 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3992 o_addchr(dest, 0x80 | '`'); 3994 o_addchr(dest, 0x80 | '`');
3993 add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'); 3995 if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
3996 return 0; /* error */
3994 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3997 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3995 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); 3998 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
3996 goto again; 3999 goto again;
@@ -4061,8 +4064,8 @@ static struct pipe *parse_stream(char **pstring,
4061 /* end_trigger == '}' case errors out earlier, 4064 /* end_trigger == '}' case errors out earlier,
4062 * checking only ')' */ 4065 * checking only ')' */
4063 if (end_trigger == ')') { 4066 if (end_trigger == ')') {
4064 syntax_error_unterm_ch('('); /* exits */ 4067 syntax_error_unterm_ch('(');
4065 /* goto parse_error; */ 4068 goto parse_error;
4066 } 4069 }
4067 4070
4068 if (done_word(&dest, &ctx)) { 4071 if (done_word(&dest, &ctx)) {
@@ -4353,9 +4356,9 @@ static struct pipe *parse_stream(char **pstring,
4353 dest.has_quoted_part = 1; 4356 dest.has_quoted_part = 1;
4354 break; 4357 break;
4355 case '$': 4358 case '$':
4356 if (parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0) != 0) { 4359 if (!parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0)) {
4357 debug_printf_parse("parse_stream parse error: " 4360 debug_printf_parse("parse_stream parse error: "
4358 "parse_dollar returned non-0\n"); 4361 "parse_dollar returned 0 (error)\n");
4359 goto parse_error; 4362 goto parse_error;
4360 } 4363 }
4361 break; 4364 break;
@@ -4365,7 +4368,7 @@ static struct pipe *parse_stream(char **pstring,
4365 ch = i_getch(input); 4368 ch = i_getch(input);
4366 if (ch == EOF) { 4369 if (ch == EOF) {
4367 syntax_error_unterm_ch('\''); 4370 syntax_error_unterm_ch('\'');
4368 /*xfunc_die(); - redundant */ 4371 goto parse_error;
4369 } 4372 }
4370 nommu_addchr(&ctx.as_string, ch); 4373 nommu_addchr(&ctx.as_string, ch);
4371 if (ch == '\'') 4374 if (ch == '\'')
@@ -4377,7 +4380,7 @@ static struct pipe *parse_stream(char **pstring,
4377 dest.has_quoted_part = 1; 4380 dest.has_quoted_part = 1;
4378 if (dest.o_assignment == NOT_ASSIGNMENT) 4381 if (dest.o_assignment == NOT_ASSIGNMENT)
4379 dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; 4382 dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
4380 if (encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1)) 4383 if (!encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1))
4381 goto parse_error; 4384 goto parse_error;
4382 dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; 4385 dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
4383 break; 4386 break;
@@ -4388,7 +4391,8 @@ static struct pipe *parse_stream(char **pstring,
4388 o_addchr(&dest, SPECIAL_VAR_SYMBOL); 4391 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
4389 o_addchr(&dest, '`'); 4392 o_addchr(&dest, '`');
4390 pos = dest.length; 4393 pos = dest.length;
4391 add_till_backquote(&dest, input, /*in_dquote:*/ 0); 4394 if (!add_till_backquote(&dest, input, /*in_dquote:*/ 0))
4395 goto parse_error;
4392# if !BB_MMU 4396# if !BB_MMU
4393 o_addstr(&ctx.as_string, dest.data + pos); 4397 o_addstr(&ctx.as_string, dest.data + pos);
4394 o_addchr(&ctx.as_string, '`'); 4398 o_addchr(&ctx.as_string, '`');
@@ -4664,6 +4668,7 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int
4664 */ 4668 */
4665 setup_string_in_str(&input, str); 4669 setup_string_in_str(&input, str);
4666 encode_string(NULL, &dest, &input, EOF, process_bkslash); 4670 encode_string(NULL, &dest, &input, EOF, process_bkslash);
4671//TODO: error check (encode_string returns 0 on error)?
4667 //bb_error_msg("'%s' -> '%s'", str, dest.data); 4672 //bb_error_msg("'%s' -> '%s'", str, dest.data);
4668 exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash); 4673 exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash);
4669 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); 4674 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
@@ -8625,6 +8630,8 @@ static int FAST_FUNC builtin_source(char **argv)
8625#endif 8630#endif
8626 save_and_replace_G_args(&sv, argv); 8631 save_and_replace_G_args(&sv, argv);
8627 8632
8633//TODO: syntax errors in sourced file should never abort the "calling" script.
8634//Try: bash -c '. ./bad_file; echo YES'
8628 parse_and_run_file(input); 8635 parse_and_run_file(input);
8629 fclose(input); 8636 fclose(input);
8630 8637