aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c72
1 files changed, 41 insertions, 31 deletions
diff --git a/shell/hush.c b/shell/hush.c
index e4c3a7d77..d3e957c2f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -445,8 +445,6 @@ enum {
445/* Used for initialization: o_string foo = NULL_O_STRING; */ 445/* Used for initialization: o_string foo = NULL_O_STRING; */
446#define NULL_O_STRING { NULL } 446#define NULL_O_STRING { NULL }
447 447
448/* I can almost use ordinary FILE*. Is open_memstream() universally
449 * available? Where is it documented? */
450typedef struct in_str { 448typedef struct in_str {
451 const char *p; 449 const char *p;
452 /* eof_flag=1: last char in ->p is really an EOF */ 450 /* eof_flag=1: last char in ->p is really an EOF */
@@ -455,6 +453,7 @@ typedef struct in_str {
455#if ENABLE_HUSH_INTERACTIVE 453#if ENABLE_HUSH_INTERACTIVE
456 smallint promptmode; /* 0: PS1, 1: PS2 */ 454 smallint promptmode; /* 0: PS1, 1: PS2 */
457#endif 455#endif
456 int last_char;
458 FILE *file; 457 FILE *file;
459 int (*get) (struct in_str *) FAST_FUNC; 458 int (*get) (struct in_str *) FAST_FUNC;
460 int (*peek) (struct in_str *) FAST_FUNC; 459 int (*peek) (struct in_str *) FAST_FUNC;
@@ -1077,22 +1076,22 @@ static void die_if_script(unsigned lineno, const char *fmt, ...)
1077 xfunc_die(); 1076 xfunc_die();
1078} 1077}
1079 1078
1080static void syntax_error(unsigned lineno, const char *msg) 1079static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
1081{ 1080{
1082 if (msg) 1081 if (msg)
1083 die_if_script(lineno, "syntax error: %s", msg); 1082 bb_error_msg("syntax error: %s", msg);
1084 else 1083 else
1085 die_if_script(lineno, "syntax error", NULL); 1084 bb_error_msg("syntax error");
1086} 1085}
1087 1086
1088static void syntax_error_at(unsigned lineno, const char *msg) 1087static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
1089{ 1088{
1090 die_if_script(lineno, "syntax error at '%s'", msg); 1089 bb_error_msg("syntax error at '%s'", msg);
1091} 1090}
1092 1091
1093static void syntax_error_unterm_str(unsigned lineno, const char *s) 1092static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
1094{ 1093{
1095 die_if_script(lineno, "syntax error: unterminated %s", s); 1094 bb_error_msg("syntax error: unterminated %s", s);
1096} 1095}
1097 1096
1098static void syntax_error_unterm_ch(unsigned lineno, char ch) 1097static void syntax_error_unterm_ch(unsigned lineno, char ch)
@@ -1101,12 +1100,12 @@ static void syntax_error_unterm_ch(unsigned lineno, char ch)
1101 syntax_error_unterm_str(lineno, msg); 1100 syntax_error_unterm_str(lineno, msg);
1102} 1101}
1103 1102
1104static void syntax_error_unexpected_ch(unsigned lineno, int ch) 1103static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
1105{ 1104{
1106 char msg[2]; 1105 char msg[2];
1107 msg[0] = ch; 1106 msg[0] = ch;
1108 msg[1] = '\0'; 1107 msg[1] = '\0';
1109 die_if_script(lineno, "syntax error: unexpected %s", ch == EOF ? "EOF" : msg); 1108 bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
1110} 1109}
1111 1110
1112#if HUSH_DEBUG < 2 1111#if HUSH_DEBUG < 2
@@ -1843,6 +1842,7 @@ static int FAST_FUNC static_get(struct in_str *i)
1843 int ch = *i->p; 1842 int ch = *i->p;
1844 if (ch != '\0') { 1843 if (ch != '\0') {
1845 i->p++; 1844 i->p++;
1845 i->last_char = ch;
1846 return ch; 1846 return ch;
1847 } 1847 }
1848 return EOF; 1848 return EOF;
@@ -1964,6 +1964,7 @@ static int FAST_FUNC file_get(struct in_str *i)
1964 do ch = fgetc(i->file); while (ch == '\0'); 1964 do ch = fgetc(i->file); while (ch == '\0');
1965 } 1965 }
1966 debug_printf("file_get: got '%c' %d\n", ch, ch); 1966 debug_printf("file_get: got '%c' %d\n", ch, ch);
1967 i->last_char = ch;
1967 return ch; 1968 return ch;
1968} 1969}
1969 1970
@@ -4008,7 +4009,7 @@ static int encode_string(o_string *as_string,
4008 * Scan input until EOF or end_trigger char. 4009 * Scan input until EOF or end_trigger char.
4009 * Return a list of pipes to execute, or NULL on EOF 4010 * Return a list of pipes to execute, or NULL on EOF
4010 * or if end_trigger character is met. 4011 * or if end_trigger character is met.
4011 * On syntax error, exit is shell is not interactive, 4012 * On syntax error, exit if shell is not interactive,
4012 * reset parsing machinery and start parsing anew, 4013 * reset parsing machinery and start parsing anew,
4013 * or return ERR_PTR. 4014 * or return ERR_PTR.
4014 */ 4015 */
@@ -4037,8 +4038,6 @@ static struct pipe *parse_stream(char **pstring,
4037 * here we should use blank chars as separators, not $IFS 4038 * here we should use blank chars as separators, not $IFS
4038 */ 4039 */
4039 4040
4040 reset: /* we come back here only on syntax errors in interactive shell */
4041
4042 if (MAYBE_ASSIGNMENT != 0) 4041 if (MAYBE_ASSIGNMENT != 0)
4043 dest.o_assignment = MAYBE_ASSIGNMENT; 4042 dest.o_assignment = MAYBE_ASSIGNMENT;
4044 initialize_context(&ctx); 4043 initialize_context(&ctx);
@@ -4530,22 +4529,15 @@ static struct pipe *parse_stream(char **pstring,
4530 } 4529 }
4531 IF_HAS_KEYWORDS(pctx = p2;) 4530 IF_HAS_KEYWORDS(pctx = p2;)
4532 } while (HAS_KEYWORDS && pctx); 4531 } while (HAS_KEYWORDS && pctx);
4533 /* Free text, clear all dest fields */ 4532
4534 o_free(&dest); 4533 o_free(&dest);
4535 /* If we are not in top-level parse, we return, 4534 G.last_exitcode = 1;
4536 * our caller will propagate error.
4537 */
4538 if (end_trigger != ';') {
4539#if !BB_MMU 4535#if !BB_MMU
4540 if (pstring) 4536 if (pstring)
4541 *pstring = NULL; 4537 *pstring = NULL;
4542#endif 4538#endif
4543 debug_leave(); 4539 debug_leave();
4544 return ERR_PTR; 4540 return ERR_PTR;
4545 }
4546 /* Discard cached input, force prompt */
4547 input->p = NULL;
4548 goto reset;
4549 } 4541 }
4550} 4542}
4551 4543
@@ -5550,8 +5542,24 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger)
5550 inp->promptmode = 0; /* PS1 */ 5542 inp->promptmode = 0; /* PS1 */
5551#endif 5543#endif
5552 pipe_list = parse_stream(NULL, inp, end_trigger); 5544 pipe_list = parse_stream(NULL, inp, end_trigger);
5553 if (!pipe_list) { /* EOF */ 5545 if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */
5554 if (empty) 5546 /* If we are in "big" script
5547 * (not in `cmd` or something similar)...
5548 */
5549 if (pipe_list == ERR_PTR && end_trigger == ';') {
5550 /* Discard cached input (rest of line) */
5551 int ch = inp->last_char;
5552 while (ch != EOF && ch != '\n') {
5553 //bb_error_msg("Discarded:'%c'", ch);
5554 ch = i_getch(inp);
5555 }
5556 /* Force prompt */
5557 inp->p = NULL;
5558 /* This stream isn't empty */
5559 empty = 0;
5560 continue;
5561 }
5562 if (!pipe_list && empty)
5555 G.last_exitcode = 0; 5563 G.last_exitcode = 0;
5556 break; 5564 break;
5557 } 5565 }
@@ -7606,6 +7614,10 @@ int hush_main(int argc, char **argv)
7606 //set_local_var(xasprintf("HISTFILE=%s", ...)); 7614 //set_local_var(xasprintf("HISTFILE=%s", ...));
7607 } 7615 }
7608 } 7616 }
7617# if ENABLE_FEATURE_SH_HISTFILESIZE
7618 hp = get_local_var_value("HISTFILESIZE");
7619 G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
7620# endif
7609 } 7621 }
7610# endif 7622# endif
7611#endif 7623#endif
@@ -8630,8 +8642,6 @@ static int FAST_FUNC builtin_source(char **argv)
8630#endif 8642#endif
8631 save_and_replace_G_args(&sv, argv); 8643 save_and_replace_G_args(&sv, argv);
8632 8644
8633//TODO: syntax errors in sourced file should never abort the "calling" script.
8634//Try: bash -c '. ./bad_file; echo YES'
8635 parse_and_run_file(input); 8645 parse_and_run_file(input);
8636 fclose(input); 8646 fclose(input);
8637 8647