diff options
author | Ron Yorston <rmy@pobox.com> | 2012-03-22 14:11:12 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-03-22 14:11:12 +0000 |
commit | 67758035a4fe040c6ac69b39d61bcd6bddd7b827 (patch) | |
tree | a4a1db7f54c16d12fabe2626b8f1e235cd694e9e /shell | |
parent | 811c449748d5bd0505f8510e5582892f94ac0cda (diff) | |
parent | b83c9704128dd106071184e4b00335a3b8486857 (diff) | |
download | busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.gz busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.bz2 busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.zip |
Merge commit 'b83c9704128dd106071184e4b00335a3b8486857' into merge
Diffstat (limited to 'shell')
-rw-r--r-- | shell/Config.src | 10 | ||||
-rw-r--r-- | shell/ash.c | 18 | ||||
-rw-r--r-- | shell/hush.c | 72 | ||||
-rw-r--r-- | shell/shell_common.c | 12 |
4 files changed, 76 insertions, 36 deletions
diff --git a/shell/Config.src b/shell/Config.src index e96c21620..b31e62dda 100644 --- a/shell/Config.src +++ b/shell/Config.src | |||
@@ -136,4 +136,14 @@ config FEATURE_SH_NOFORK | |||
136 | This feature is relatively new. Use with care. Report bugs | 136 | This feature is relatively new. Use with care. Report bugs |
137 | to project mailing list. | 137 | to project mailing list. |
138 | 138 | ||
139 | config FEATURE_SH_HISTFILESIZE | ||
140 | bool "Use $HISTFILESIZE" | ||
141 | default y | ||
142 | depends on HUSH || ASH | ||
143 | help | ||
144 | This option makes busybox shells to use $HISTFILESIZE variable | ||
145 | to set shell history size. Note that its max value is capped | ||
146 | by "History size" setting in library tuning section. | ||
147 | |||
148 | |||
139 | endmenu | 149 | endmenu |
diff --git a/shell/ash.c b/shell/ash.c index d12a483a3..eaaa71967 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3658,13 +3658,18 @@ setsignal(int signo) | |||
3658 | switch (new_act) { | 3658 | switch (new_act) { |
3659 | case S_CATCH: | 3659 | case S_CATCH: |
3660 | act.sa_handler = signal_handler; | 3660 | act.sa_handler = signal_handler; |
3661 | act.sa_flags = 0; /* matters only if !DFL and !IGN */ | ||
3662 | sigfillset(&act.sa_mask); /* ditto */ | ||
3663 | break; | 3661 | break; |
3664 | case S_IGN: | 3662 | case S_IGN: |
3665 | act.sa_handler = SIG_IGN; | 3663 | act.sa_handler = SIG_IGN; |
3666 | break; | 3664 | break; |
3667 | } | 3665 | } |
3666 | |||
3667 | /* flags and mask matter only if !DFL and !IGN, but we do it | ||
3668 | * for all cases for more deterministic behavior: | ||
3669 | */ | ||
3670 | act.sa_flags = 0; | ||
3671 | sigfillset(&act.sa_mask); | ||
3672 | |||
3668 | sigaction_set(signo, &act); | 3673 | sigaction_set(signo, &act); |
3669 | 3674 | ||
3670 | *t = new_act; | 3675 | *t = new_act; |
@@ -13765,10 +13770,9 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13765 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY | 13770 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY |
13766 | if (iflag) { | 13771 | if (iflag) { |
13767 | const char *hp = lookupvar("HISTFILE"); | 13772 | const char *hp = lookupvar("HISTFILE"); |
13768 | 13773 | if (!hp) { | |
13769 | if (hp == NULL) { | ||
13770 | hp = lookupvar("HOME"); | 13774 | hp = lookupvar("HOME"); |
13771 | if (hp != NULL) { | 13775 | if (hp) { |
13772 | char *defhp = concat_path_file(hp, ".ash_history"); | 13776 | char *defhp = concat_path_file(hp, ".ash_history"); |
13773 | setvar("HISTFILE", defhp, 0); | 13777 | setvar("HISTFILE", defhp, 0); |
13774 | free(defhp); | 13778 | free(defhp); |
@@ -13817,6 +13821,10 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13817 | const char *hp = lookupvar("HISTFILE"); | 13821 | const char *hp = lookupvar("HISTFILE"); |
13818 | if (hp) | 13822 | if (hp) |
13819 | line_input_state->hist_file = hp; | 13823 | line_input_state->hist_file = hp; |
13824 | # if ENABLE_FEATURE_SH_HISTFILESIZE | ||
13825 | hp = lookupvar("HISTFILESIZE"); | ||
13826 | line_input_state->max_history = size_from_HISTFILESIZE(hp); | ||
13827 | # endif | ||
13820 | } | 13828 | } |
13821 | #endif | 13829 | #endif |
13822 | state4: /* XXX ??? - why isn't this before the "if" statement */ | 13830 | state4: /* XXX ??? - why isn't this before the "if" statement */ |
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? */ | ||
450 | typedef struct in_str { | 448 | typedef 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 | ||
1080 | static void syntax_error(unsigned lineno, const char *msg) | 1079 | static 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 | ||
1088 | static void syntax_error_at(unsigned lineno, const char *msg) | 1087 | static 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 | ||
1093 | static void syntax_error_unterm_str(unsigned lineno, const char *s) | 1092 | static 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 | ||
1098 | static void syntax_error_unterm_ch(unsigned lineno, char ch) | 1097 | static 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 | ||
1104 | static void syntax_error_unexpected_ch(unsigned lineno, int ch) | 1103 | static 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 | ||
diff --git a/shell/shell_common.c b/shell/shell_common.c index c7b5b6122..75f4b3e54 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -286,6 +286,12 @@ static const struct limits limits_tbl[] = { | |||
286 | #ifdef RLIMIT_LOCKS | 286 | #ifdef RLIMIT_LOCKS |
287 | { RLIMIT_LOCKS, 0, 'w', "locks" }, | 287 | { RLIMIT_LOCKS, 0, 'w', "locks" }, |
288 | #endif | 288 | #endif |
289 | #ifdef RLIMIT_NICE | ||
290 | { RLIMIT_NICE, 0, 'e', "scheduling priority" }, | ||
291 | #endif | ||
292 | #ifdef RLIMIT_RTPRIO | ||
293 | { RLIMIT_RTPRIO, 0, 'r', "real-time priority" }, | ||
294 | #endif | ||
289 | }; | 295 | }; |
290 | 296 | ||
291 | enum { | 297 | enum { |
@@ -328,6 +334,12 @@ static const char ulimit_opt_string[] = "-HSa" | |||
328 | #ifdef RLIMIT_LOCKS | 334 | #ifdef RLIMIT_LOCKS |
329 | "w::" | 335 | "w::" |
330 | #endif | 336 | #endif |
337 | #ifdef RLIMIT_NICE | ||
338 | "e::" | ||
339 | #endif | ||
340 | #ifdef RLIMIT_RTPRIO | ||
341 | "r::" | ||
342 | #endif | ||
331 | ; | 343 | ; |
332 | 344 | ||
333 | #if ENABLE_PLATFORM_MINGW32 | 345 | #if ENABLE_PLATFORM_MINGW32 |