From cecbc986112cdd5ce95d15221979edf4281f5f7f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 30 Mar 2011 18:54:52 +0200 Subject: hush: fix source1.tests function old new delta parse_and_run_stream 95 139 +44 static_get 22 25 +3 file_get 260 263 +3 builtin_umask 133 132 -1 parse_stream 2442 2425 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/2 up/down: 50/-18) Total: 32 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 64 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 27 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index e4c3a7d77..a47652470 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -445,8 +445,6 @@ enum { /* Used for initialization: o_string foo = NULL_O_STRING; */ #define NULL_O_STRING { NULL } -/* I can almost use ordinary FILE*. Is open_memstream() universally - * available? Where is it documented? */ typedef struct in_str { const char *p; /* eof_flag=1: last char in ->p is really an EOF */ @@ -455,6 +453,7 @@ typedef struct in_str { #if ENABLE_HUSH_INTERACTIVE smallint promptmode; /* 0: PS1, 1: PS2 */ #endif + int last_char; FILE *file; int (*get) (struct in_str *) FAST_FUNC; int (*peek) (struct in_str *) FAST_FUNC; @@ -1077,22 +1076,22 @@ static void die_if_script(unsigned lineno, const char *fmt, ...) xfunc_die(); } -static void syntax_error(unsigned lineno, const char *msg) +static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg) { if (msg) - die_if_script(lineno, "syntax error: %s", msg); + bb_error_msg("syntax error: %s", msg); else - die_if_script(lineno, "syntax error", NULL); + bb_error_msg("syntax error"); } -static void syntax_error_at(unsigned lineno, const char *msg) +static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg) { - die_if_script(lineno, "syntax error at '%s'", msg); + bb_error_msg("syntax error at '%s'", msg); } -static void syntax_error_unterm_str(unsigned lineno, const char *s) +static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s) { - die_if_script(lineno, "syntax error: unterminated %s", s); + bb_error_msg("syntax error: unterminated %s", s); } static void syntax_error_unterm_ch(unsigned lineno, char ch) @@ -1101,12 +1100,12 @@ static void syntax_error_unterm_ch(unsigned lineno, char ch) syntax_error_unterm_str(lineno, msg); } -static void syntax_error_unexpected_ch(unsigned lineno, int ch) +static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch) { char msg[2]; msg[0] = ch; msg[1] = '\0'; - die_if_script(lineno, "syntax error: unexpected %s", ch == EOF ? "EOF" : msg); + bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg); } #if HUSH_DEBUG < 2 @@ -1843,6 +1842,7 @@ static int FAST_FUNC static_get(struct in_str *i) int ch = *i->p; if (ch != '\0') { i->p++; + i->last_char = ch; return ch; } return EOF; @@ -1964,6 +1964,7 @@ static int FAST_FUNC file_get(struct in_str *i) do ch = fgetc(i->file); while (ch == '\0'); } debug_printf("file_get: got '%c' %d\n", ch, ch); + i->last_char = ch; return ch; } @@ -4008,7 +4009,7 @@ static int encode_string(o_string *as_string, * Scan input until EOF or end_trigger char. * Return a list of pipes to execute, or NULL on EOF * or if end_trigger character is met. - * On syntax error, exit is shell is not interactive, + * On syntax error, exit if shell is not interactive, * reset parsing machinery and start parsing anew, * or return ERR_PTR. */ @@ -4037,8 +4038,6 @@ static struct pipe *parse_stream(char **pstring, * here we should use blank chars as separators, not $IFS */ - reset: /* we come back here only on syntax errors in interactive shell */ - if (MAYBE_ASSIGNMENT != 0) dest.o_assignment = MAYBE_ASSIGNMENT; initialize_context(&ctx); @@ -4532,20 +4531,17 @@ static struct pipe *parse_stream(char **pstring, } while (HAS_KEYWORDS && pctx); /* Free text, clear all dest fields */ o_free(&dest); + + G.last_exitcode = 1; /* If we are not in top-level parse, we return, * our caller will propagate error. */ - if (end_trigger != ';') { #if !BB_MMU - if (pstring) - *pstring = NULL; + if (pstring) + *pstring = NULL; #endif - debug_leave(); - return ERR_PTR; - } - /* Discard cached input, force prompt */ - input->p = NULL; - goto reset; + debug_leave(); + return ERR_PTR; } } @@ -5550,8 +5546,24 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger) inp->promptmode = 0; /* PS1 */ #endif pipe_list = parse_stream(NULL, inp, end_trigger); - if (!pipe_list) { /* EOF */ - if (empty) + if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */ + /* If we are in "big" script + * (not in `cmd` or something similar)... + */ + if (pipe_list == ERR_PTR && end_trigger == ';') { + /* Discard cached input (rest of line) */ + int ch = inp->last_char; + while (ch != EOF && ch != '\n') { + //bb_error_msg("Discarded:'%c'", ch); + ch = i_getch(inp); + } + /* Force prompt */ + inp->p = NULL; + /* This stream isn't empty */ + empty = 0; + continue; + } + if (!pipe_list && empty) G.last_exitcode = 0; break; } @@ -8630,8 +8642,6 @@ static int FAST_FUNC builtin_source(char **argv) #endif save_and_replace_G_args(&sv, argv); -//TODO: syntax errors in sourced file should never abort the "calling" script. -//Try: bash -c '. ./bad_file; echo YES' parse_and_run_file(input); fclose(input); -- cgit v1.2.3-55-g6feb From a439fa93f64e6eb34f0633d00d203b4267d58521 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 30 Mar 2011 19:11:46 +0200 Subject: hush: remove outdated comments Signed-off-by: Denys Vlasenko --- shell/hush.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'shell') diff --git a/shell/hush.c b/shell/hush.c index a47652470..e698e6c52 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4529,13 +4529,9 @@ static struct pipe *parse_stream(char **pstring, } IF_HAS_KEYWORDS(pctx = p2;) } while (HAS_KEYWORDS && pctx); - /* Free text, clear all dest fields */ - o_free(&dest); + o_free(&dest); G.last_exitcode = 1; - /* If we are not in top-level parse, we return, - * our caller will propagate error. - */ #if !BB_MMU if (pstring) *pstring = NULL; -- cgit v1.2.3-55-g6feb From 2c4de5b045a79db73052d5b865474a00c9a87e99 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 31 Mar 2011 13:16:52 +0200 Subject: ash,hush: optional support for $HISTFILESIZE. Based on patch from Alexey Fomenko (ext-alexey.fomenko AT nokia.com) function old new delta size_from_HISTFILESIZE - 44 +44 hush_main 998 1025 +27 ash_main 1348 1374 +26 read_line_input 3361 3372 +11 new_line_input_t 17 24 +7 Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 +++- libbb/Config.src | 5 +++-- libbb/lineedit.c | 44 +++++++++++++++++++++++++++++--------------- shell/Config.src | 10 ++++++++++ shell/ash.c | 9 ++++++--- shell/hush.c | 4 ++++ 6 files changed, 55 insertions(+), 21 deletions(-) (limited to 'shell') diff --git a/include/libbb.h b/include/libbb.h index c371e35f2..f2f3313b4 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1373,8 +1373,9 @@ void read_key_ungets(char *buffer, const char *str, unsigned len) FAST_FUNC; #if ENABLE_FEATURE_EDITING /* It's NOT just ENABLEd or disabled. It's a number: */ -# ifdef CONFIG_FEATURE_EDITING_HISTORY +# if defined CONFIG_FEATURE_EDITING_HISTORY && CONFIG_FEATURE_EDITING_HISTORY > 0 # define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0) +unsigned size_from_HISTFILESIZE(const char *hp); # else # define MAX_HISTORY 0 # endif @@ -1384,6 +1385,7 @@ typedef struct line_input_t { # if MAX_HISTORY int cnt_history; int cur_history; + int max_history; /* must never be <= 0 */ # if ENABLE_FEATURE_EDITING_SAVEHISTORY unsigned cnt_history_in_file; const char *hist_file; diff --git a/libbb/Config.src b/libbb/Config.src index a25af23b4..0ea8f43ab 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -80,11 +80,12 @@ config FEATURE_EDITING_VI config FEATURE_EDITING_HISTORY int "History size" - range 0 99999 + # Don't allow way too big values here, code uses fixed "char *history[N]" struct member + range 0 9999 default 255 depends on FEATURE_EDITING help - Specify command history size. + Specify command history size (0 - disable). config FEATURE_EDITING_SAVEHISTORY bool "History saving" diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b7a2b31dc..095ccfbef 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1243,12 +1243,26 @@ line_input_t* FAST_FUNC new_line_input_t(int flags) { line_input_t *n = xzalloc(sizeof(*n)); n->flags = flags; + n->max_history = MAX_HISTORY; return n; } #if MAX_HISTORY > 0 +unsigned size_from_HISTFILESIZE(const char *hp) +{ + int size = MAX_HISTORY; + if (hp) { + size = atoi(hp); + if (size <= 0) + return 1; + if (size > MAX_HISTORY) + return MAX_HISTORY; + } + return size; +} + static void save_command_ps_at_cur_history(void) { if (command_ps[0] != BB_NUL) { @@ -1339,7 +1353,7 @@ static void load_history(line_input_t *st_parm) temp_h[idx] = line; st_parm->cnt_history_in_file++; idx++; - if (idx == MAX_HISTORY) + if (idx == st_parm->max_history) idx = 0; } fclose(fp); @@ -1348,18 +1362,18 @@ static void load_history(line_input_t *st_parm) if (st_parm->cnt_history_in_file) { while (temp_h[idx] == NULL) { idx++; - if (idx == MAX_HISTORY) + if (idx == st_parm->max_history) idx = 0; } } /* copy temp_h[] to st_parm->history[] */ - for (i = 0; i < MAX_HISTORY;) { + for (i = 0; i < st_parm->max_history;) { line = temp_h[idx]; if (!line) break; idx++; - if (idx == MAX_HISTORY) + if (idx == st_parm->max_history) idx = 0; line_len = strlen(line); if (line_len >= MAX_LINELEN) @@ -1390,7 +1404,7 @@ static void save_history(char *str) /* did we write so much that history file needs trimming? */ state->cnt_history_in_file++; - if (state->cnt_history_in_file > MAX_HISTORY * 4) { + if (state->cnt_history_in_file > state->max_history * 4) { char *new_name; line_input_t *st_temp; @@ -1436,20 +1450,20 @@ static void remember_in_history(char *str) if (i && strcmp(state->history[i-1], str) == 0) return; - free(state->history[MAX_HISTORY]); /* redundant, paranoia */ - state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */ + free(state->history[state->max_history]); /* redundant, paranoia */ + state->history[state->max_history] = NULL; /* redundant, paranoia */ /* If history[] is full, remove the oldest command */ - /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */ - if (i >= MAX_HISTORY) { + /* we need to keep history[state->max_history] empty, hence >=, not > */ + if (i >= state->max_history) { free(state->history[0]); - for (i = 0; i < MAX_HISTORY-1; i++) + for (i = 0; i < state->max_history-1; i++) state->history[i] = state->history[i+1]; - /* i == MAX_HISTORY-1 */ + /* i == state->max_history-1 */ } - /* i <= MAX_HISTORY-1 */ + /* i <= state->max_history-1 */ state->history[i++] = xstrdup(str); - /* i <= MAX_HISTORY */ + /* i <= state->max_history */ state->cur_history = i; state->cnt_history = i; # if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY @@ -1970,7 +1984,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman maxsize = MAX_LINELEN; S.maxsize = maxsize; - /* With null flags, no other fields are ever used */ + /* With zero flags, no other fields are ever used */ state = st ? st : (line_input_t*) &const_int_0; #if MAX_HISTORY > 0 # if ENABLE_FEATURE_EDITING_SAVEHISTORY @@ -2022,7 +2036,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman #endif #if 0 - for (i = 0; i <= MAX_HISTORY; i++) + for (i = 0; i <= state->max_history; i++) bb_error_msg("history[%d]:'%s'", i, state->history[i]); bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history); #endif 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 This feature is relatively new. Use with care. Report bugs to project mailing list. +config FEATURE_SH_HISTFILESIZE + bool "Use $HISTFILESIZE" + default y + depends on HUSH || ASH + help + This option makes busybox shells to use $HISTFILESIZE variable + to set shell history size. Note that its max value is capped + by "History size" setting in library tuning section. + + endmenu diff --git a/shell/ash.c b/shell/ash.c index 1520c5ae5..11ba9774a 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13143,10 +13143,9 @@ int ash_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_EDITING_SAVEHISTORY if (iflag) { const char *hp = lookupvar("HISTFILE"); - - if (hp == NULL) { + if (!hp) { hp = lookupvar("HOME"); - if (hp != NULL) { + if (hp) { char *defhp = concat_path_file(hp, ".ash_history"); setvar("HISTFILE", defhp, 0); free(defhp); @@ -13195,6 +13194,10 @@ int ash_main(int argc UNUSED_PARAM, char **argv) const char *hp = lookupvar("HISTFILE"); if (hp) line_input_state->hist_file = hp; +# if ENABLE_FEATURE_SH_HISTFILESIZE + hp = lookupvar("HISTFILESIZE"); + line_input_state->max_history = size_from_HISTFILESIZE(hp); +# endif } #endif state4: /* XXX ??? - why isn't this before the "if" statement */ diff --git a/shell/hush.c b/shell/hush.c index e698e6c52..d3e957c2f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7614,6 +7614,10 @@ int hush_main(int argc, char **argv) //set_local_var(xasprintf("HISTFILE=%s", ...)); } } +# if ENABLE_FEATURE_SH_HISTFILESIZE + hp = get_local_var_value("HISTFILESIZE"); + G.line_input_state->max_history = size_from_HISTFILESIZE(hp); +# endif } # endif #endif -- cgit v1.2.3-55-g6feb From e32d05b708a31716e0a788c43f81990436535140 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 4 Apr 2011 02:12:14 +0200 Subject: ash,hush: add ulimit -e -r (RLIMIT_NICE, RLIMIT_RTPRIO) Signed-off-by: Denys Vlasenko --- shell/shell_common.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'shell') diff --git a/shell/shell_common.c b/shell/shell_common.c index f02ed81ea..68659abd3 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -286,6 +286,12 @@ static const struct limits limits_tbl[] = { #ifdef RLIMIT_LOCKS { RLIMIT_LOCKS, 0, 'w', "locks" }, #endif +#ifdef RLIMIT_NICE + { RLIMIT_NICE, 0, 'e', "scheduling priority" }, +#endif +#ifdef RLIMIT_RTPRIO + { RLIMIT_RTPRIO, 0, 'r', "real-time priority" }, +#endif }; enum { @@ -327,6 +333,12 @@ static const char ulimit_opt_string[] = "-HSa" #endif #ifdef RLIMIT_LOCKS "w::" +#endif +#ifdef RLIMIT_NICE + "e::" +#endif +#ifdef RLIMIT_RTPRIO + "r::" #endif ; -- cgit v1.2.3-55-g6feb From 89b3cbaa97d715ac27e9558ea73a1221925f589b Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Sat, 16 Apr 2011 20:05:14 +0200 Subject: ash: clear sa_flags always Signed-off-by: Ian Wienand Signed-off-by: Denys Vlasenko --- shell/ash.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 11ba9774a..b50e0952e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3491,13 +3491,18 @@ setsignal(int signo) switch (new_act) { case S_CATCH: act.sa_handler = signal_handler; - act.sa_flags = 0; /* matters only if !DFL and !IGN */ - sigfillset(&act.sa_mask); /* ditto */ break; case S_IGN: act.sa_handler = SIG_IGN; break; } + + /* flags and mask matter only if !DFL and !IGN, but we do it + * for all cases for more deterministic behavior: + */ + act.sa_flags = 0; + sigfillset(&act.sa_mask); + sigaction_set(signo, &act); *t = new_act; -- cgit v1.2.3-55-g6feb