diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-24 13:22:47 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-24 13:22:47 +0000 |
commit | 5a1437d8355f44702d9ff85311cfd11f2625217c (patch) | |
tree | b14078bad2688b4857df720a3766b0f6c0d3ed61 | |
parent | cd7f4d27a2ccda62c3cd41c980a75a1aa59d8534 (diff) | |
download | busybox-w32-5a1437d8355f44702d9ff85311cfd11f2625217c.tar.gz busybox-w32-5a1437d8355f44702d9ff85311cfd11f2625217c.tar.bz2 busybox-w32-5a1437d8355f44702d9ff85311cfd11f2625217c.zip |
hush: fix segfaulting syntax error in interactive hush
-rw-r--r-- | shell/hush.c | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/shell/hush.c b/shell/hush.c index 1ff7b0df6..d96615d54 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -305,8 +305,8 @@ struct in_str { | |||
305 | char eof_flag; /* meaningless if ->p == NULL */ | 305 | char eof_flag; /* meaningless if ->p == NULL */ |
306 | char peek_buf[2]; | 306 | char peek_buf[2]; |
307 | #if ENABLE_HUSH_INTERACTIVE | 307 | #if ENABLE_HUSH_INTERACTIVE |
308 | int __promptme; | 308 | smallint promptme; |
309 | int promptmode; | 309 | smallint promptmode; /* 0: PS1, 1: PS2 */ |
310 | #endif | 310 | #endif |
311 | FILE *file; | 311 | FILE *file; |
312 | int (*get) (struct in_str *); | 312 | int (*get) (struct in_str *); |
@@ -427,15 +427,23 @@ enum { run_list_level = 0 }; | |||
427 | /* Normal */ | 427 | /* Normal */ |
428 | static void syntax(const char *msg) | 428 | static void syntax(const char *msg) |
429 | { | 429 | { |
430 | (interactive_fd ? bb_error_msg : bb_error_msg_and_die) | 430 | /* Was using fancy stuff: |
431 | (msg ? "%s: %s" : "syntax error", "syntax error", msg); | 431 | * (interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...) |
432 | * but it SEGVs. ?! Oh well... explicit temp ptr works around that */ | ||
433 | void (*fp)(const char *s, ...); | ||
434 | |||
435 | fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die); | ||
436 | fp(msg ? "%s: %s" : "syntax error", "syntax error", msg); | ||
432 | } | 437 | } |
438 | |||
433 | #else | 439 | #else |
434 | /* Debug */ | 440 | /* Debug */ |
435 | static void syntax_lineno(int line) | 441 | static void syntax_lineno(int line) |
436 | { | 442 | { |
437 | (interactive_fd ? bb_error_msg : bb_error_msg_and_die) | 443 | void (*fp)(const char *s, ...); |
438 | ("syntax error hush.c:%d", line); | 444 | |
445 | fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die); | ||
446 | fp("syntax error hush.c:%d", line); | ||
439 | } | 447 | } |
440 | #define syntax(str) syntax_lineno(__LINE__) | 448 | #define syntax(str) syntax_lineno(__LINE__) |
441 | #endif | 449 | #endif |
@@ -1136,20 +1144,17 @@ static const char* setup_prompt_string(int promptmode) | |||
1136 | debug_printf("setup_prompt_string %d ", promptmode); | 1144 | debug_printf("setup_prompt_string %d ", promptmode); |
1137 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT | 1145 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT |
1138 | /* Set up the prompt */ | 1146 | /* Set up the prompt */ |
1139 | if (promptmode == 1) { | 1147 | if (promptmode == 0) { /* PS1 */ |
1140 | char *ns; | ||
1141 | free((char*)PS1); | 1148 | free((char*)PS1); |
1142 | ns = xmalloc(strlen(cwd)+4); | 1149 | PS1 = xasprintf("%s %c ", cwd, (geteuid() != 0) ? '$' : '#'); |
1143 | sprintf(ns, "%s %s", cwd, (geteuid() != 0) ? "$ " : "# "); | 1150 | prompt_str = PS1; |
1144 | prompt_str = ns; | ||
1145 | PS1 = ns; | ||
1146 | } else { | 1151 | } else { |
1147 | prompt_str = PS2; | 1152 | prompt_str = PS2; |
1148 | } | 1153 | } |
1149 | #else | 1154 | #else |
1150 | prompt_str = (promptmode == 1) ? PS1 : PS2; | 1155 | prompt_str = (promptmode == 0) ? PS1 : PS2; |
1151 | #endif | 1156 | #endif |
1152 | debug_printf("result %s\n", prompt_str); | 1157 | debug_printf("result '%s'\n", prompt_str); |
1153 | return prompt_str; | 1158 | return prompt_str; |
1154 | } | 1159 | } |
1155 | 1160 | ||
@@ -1199,12 +1204,12 @@ static int file_get(struct in_str *i) | |||
1199 | /* need to double check i->file because we might be doing something | 1204 | /* need to double check i->file because we might be doing something |
1200 | * more complicated by now, like sourcing or substituting. */ | 1205 | * more complicated by now, like sourcing or substituting. */ |
1201 | #if ENABLE_HUSH_INTERACTIVE | 1206 | #if ENABLE_HUSH_INTERACTIVE |
1202 | if (interactive_fd && i->__promptme && i->file == stdin) { | 1207 | if (interactive_fd && i->promptme && i->file == stdin) { |
1203 | do { | 1208 | do { |
1204 | get_user_input(i); | 1209 | get_user_input(i); |
1205 | } while (!*i->p); /* need non-empty line */ | 1210 | } while (!*i->p); /* need non-empty line */ |
1206 | i->promptmode = 2; | 1211 | i->promptmode = 1; /* PS2 */ |
1207 | i->__promptme = 0; | 1212 | i->promptme = 0; |
1208 | goto take_cached; | 1213 | goto take_cached; |
1209 | } | 1214 | } |
1210 | #endif | 1215 | #endif |
@@ -1213,7 +1218,7 @@ static int file_get(struct in_str *i) | |||
1213 | debug_printf("file_get: got a '%c' %d\n", ch, ch); | 1218 | debug_printf("file_get: got a '%c' %d\n", ch, ch); |
1214 | #if ENABLE_HUSH_INTERACTIVE | 1219 | #if ENABLE_HUSH_INTERACTIVE |
1215 | if (ch == '\n') | 1220 | if (ch == '\n') |
1216 | i->__promptme = 1; | 1221 | i->promptme = 1; |
1217 | #endif | 1222 | #endif |
1218 | return ch; | 1223 | return ch; |
1219 | } | 1224 | } |
@@ -1243,8 +1248,8 @@ static void setup_file_in_str(struct in_str *i, FILE *f) | |||
1243 | i->peek = file_peek; | 1248 | i->peek = file_peek; |
1244 | i->get = file_get; | 1249 | i->get = file_get; |
1245 | #if ENABLE_HUSH_INTERACTIVE | 1250 | #if ENABLE_HUSH_INTERACTIVE |
1246 | i->__promptme = 1; | 1251 | i->promptme = 1; |
1247 | i->promptmode = 1; | 1252 | i->promptmode = 0; /* PS1 */ |
1248 | #endif | 1253 | #endif |
1249 | i->file = f; | 1254 | i->file = f; |
1250 | i->p = NULL; | 1255 | i->p = NULL; |
@@ -1255,8 +1260,8 @@ static void setup_string_in_str(struct in_str *i, const char *s) | |||
1255 | i->peek = static_peek; | 1260 | i->peek = static_peek; |
1256 | i->get = static_get; | 1261 | i->get = static_get; |
1257 | #if ENABLE_HUSH_INTERACTIVE | 1262 | #if ENABLE_HUSH_INTERACTIVE |
1258 | i->__promptme = 1; | 1263 | i->promptme = 1; |
1259 | i->promptmode = 1; | 1264 | i->promptmode = 0; /* PS1 */ |
1260 | #endif | 1265 | #endif |
1261 | i->p = s; | 1266 | i->p = s; |
1262 | i->eof_flag = 0; | 1267 | i->eof_flag = 0; |
@@ -3246,6 +3251,7 @@ static int parse_group(o_string *dest, struct p_context *ctx, | |||
3246 | child->subshell = 1; | 3251 | child->subshell = 1; |
3247 | } | 3252 | } |
3248 | rcode = parse_stream(dest, &sub, input, endch); | 3253 | rcode = parse_stream(dest, &sub, input, endch); |
3254 | //vda: err chk? | ||
3249 | done_word(dest, &sub); /* finish off the final word in the subcontext */ | 3255 | done_word(dest, &sub); /* finish off the final word in the subcontext */ |
3250 | done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ | 3256 | done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ |
3251 | child->group = sub.list_head; | 3257 | child->group = sub.list_head; |
@@ -3588,7 +3594,7 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3588 | if (!(parse_flag & PARSEFLAG_SEMICOLON) || (parse_flag & PARSEFLAG_REPARSING)) | 3594 | if (!(parse_flag & PARSEFLAG_SEMICOLON) || (parse_flag & PARSEFLAG_REPARSING)) |
3589 | set_in_charmap(";$&|", CHAR_ORDINARY); | 3595 | set_in_charmap(";$&|", CHAR_ORDINARY); |
3590 | #if ENABLE_HUSH_INTERACTIVE | 3596 | #if ENABLE_HUSH_INTERACTIVE |
3591 | inp->promptmode = 1; | 3597 | inp->promptmode = 0; /* PS1 */ |
3592 | #endif | 3598 | #endif |
3593 | /* We will stop & execute after each ';' or '\n'. | 3599 | /* We will stop & execute after each ';' or '\n'. |
3594 | * Example: "sleep 9999; echo TEST" + ctrl-C: | 3600 | * Example: "sleep 9999; echo TEST" + ctrl-C: |