hush: fix segfaulting syntax error in interactive hush

This commit is contained in:
Denis Vlasenko 2007-05-24 13:22:47 +00:00
parent cd7f4d27a2
commit 5a1437d835

View File

@ -305,8 +305,8 @@ struct in_str {
char eof_flag; /* meaningless if ->p == NULL */ char eof_flag; /* meaningless if ->p == NULL */
char peek_buf[2]; char peek_buf[2];
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE
int __promptme; smallint promptme;
int promptmode; smallint promptmode; /* 0: PS1, 1: PS2 */
#endif #endif
FILE *file; FILE *file;
int (*get) (struct in_str *); int (*get) (struct in_str *);
@ -427,15 +427,23 @@ enum { run_list_level = 0 };
/* Normal */ /* Normal */
static void syntax(const char *msg) static void syntax(const char *msg)
{ {
(interactive_fd ? bb_error_msg : bb_error_msg_and_die) /* Was using fancy stuff:
(msg ? "%s: %s" : "syntax error", "syntax error", msg); * (interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...)
* but it SEGVs. ?! Oh well... explicit temp ptr works around that */
void (*fp)(const char *s, ...);
fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die);
fp(msg ? "%s: %s" : "syntax error", "syntax error", msg);
} }
#else #else
/* Debug */ /* Debug */
static void syntax_lineno(int line) static void syntax_lineno(int line)
{ {
(interactive_fd ? bb_error_msg : bb_error_msg_and_die) void (*fp)(const char *s, ...);
("syntax error hush.c:%d", line);
fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die);
fp("syntax error hush.c:%d", line);
} }
#define syntax(str) syntax_lineno(__LINE__) #define syntax(str) syntax_lineno(__LINE__)
#endif #endif
@ -1136,20 +1144,17 @@ static const char* setup_prompt_string(int promptmode)
debug_printf("setup_prompt_string %d ", promptmode); debug_printf("setup_prompt_string %d ", promptmode);
#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
/* Set up the prompt */ /* Set up the prompt */
if (promptmode == 1) { if (promptmode == 0) { /* PS1 */
char *ns;
free((char*)PS1); free((char*)PS1);
ns = xmalloc(strlen(cwd)+4); PS1 = xasprintf("%s %c ", cwd, (geteuid() != 0) ? '$' : '#');
sprintf(ns, "%s %s", cwd, (geteuid() != 0) ? "$ " : "# "); prompt_str = PS1;
prompt_str = ns;
PS1 = ns;
} else { } else {
prompt_str = PS2; prompt_str = PS2;
} }
#else #else
prompt_str = (promptmode == 1) ? PS1 : PS2; prompt_str = (promptmode == 0) ? PS1 : PS2;
#endif #endif
debug_printf("result %s\n", prompt_str); debug_printf("result '%s'\n", prompt_str);
return prompt_str; return prompt_str;
} }
@ -1199,12 +1204,12 @@ static int file_get(struct in_str *i)
/* need to double check i->file because we might be doing something /* need to double check i->file because we might be doing something
* more complicated by now, like sourcing or substituting. */ * more complicated by now, like sourcing or substituting. */
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE
if (interactive_fd && i->__promptme && i->file == stdin) { if (interactive_fd && i->promptme && i->file == stdin) {
do { do {
get_user_input(i); get_user_input(i);
} while (!*i->p); /* need non-empty line */ } while (!*i->p); /* need non-empty line */
i->promptmode = 2; i->promptmode = 1; /* PS2 */
i->__promptme = 0; i->promptme = 0;
goto take_cached; goto take_cached;
} }
#endif #endif
@ -1213,7 +1218,7 @@ static int file_get(struct in_str *i)
debug_printf("file_get: got a '%c' %d\n", ch, ch); debug_printf("file_get: got a '%c' %d\n", ch, ch);
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE
if (ch == '\n') if (ch == '\n')
i->__promptme = 1; i->promptme = 1;
#endif #endif
return ch; return ch;
} }
@ -1243,8 +1248,8 @@ static void setup_file_in_str(struct in_str *i, FILE *f)
i->peek = file_peek; i->peek = file_peek;
i->get = file_get; i->get = file_get;
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE
i->__promptme = 1; i->promptme = 1;
i->promptmode = 1; i->promptmode = 0; /* PS1 */
#endif #endif
i->file = f; i->file = f;
i->p = NULL; i->p = NULL;
@ -1255,8 +1260,8 @@ static void setup_string_in_str(struct in_str *i, const char *s)
i->peek = static_peek; i->peek = static_peek;
i->get = static_get; i->get = static_get;
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE
i->__promptme = 1; i->promptme = 1;
i->promptmode = 1; i->promptmode = 0; /* PS1 */
#endif #endif
i->p = s; i->p = s;
i->eof_flag = 0; i->eof_flag = 0;
@ -3246,6 +3251,7 @@ static int parse_group(o_string *dest, struct p_context *ctx,
child->subshell = 1; child->subshell = 1;
} }
rcode = parse_stream(dest, &sub, input, endch); rcode = parse_stream(dest, &sub, input, endch);
//vda: err chk?
done_word(dest, &sub); /* finish off the final word in the subcontext */ done_word(dest, &sub); /* finish off the final word in the subcontext */
done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */
child->group = sub.list_head; child->group = sub.list_head;
@ -3588,7 +3594,7 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
if (!(parse_flag & PARSEFLAG_SEMICOLON) || (parse_flag & PARSEFLAG_REPARSING)) if (!(parse_flag & PARSEFLAG_SEMICOLON) || (parse_flag & PARSEFLAG_REPARSING))
set_in_charmap(";$&|", CHAR_ORDINARY); set_in_charmap(";$&|", CHAR_ORDINARY);
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE
inp->promptmode = 1; inp->promptmode = 0; /* PS1 */
#endif #endif
/* We will stop & execute after each ';' or '\n'. /* We will stop & execute after each ';' or '\n'.
* Example: "sleep 9999; echo TEST" + ctrl-C: * Example: "sleep 9999; echo TEST" + ctrl-C: