From 816cd16a4ce81ec8d2989a356256f813fc91475d Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Wed, 13 Jul 2011 09:29:55 -0700 Subject: cttyhack: remove the trailing newline when reading console name from sysfs Signed-off-by: Kevin Cernekee Signed-off-by: Denys Vlasenko --- shell/cttyhack.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'shell') diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 4261289b4..37ea13723 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -122,10 +122,12 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) do { #ifdef __linux__ int s = open_read_close("/sys/class/tty/console/active", - console + 5, sizeof(console) - 5 - 1); + console + 5, sizeof(console) - 5); if (s > 0) { - /* found active console via sysfs (Linux 2.6.38+) */ - console[5 + s] = '\0'; + /* found active console via sysfs (Linux 2.6.38+) + * sysfs string looks like "ttyS0\n" so zap the newline: + */ + console[4 + s] = '\0'; break; } -- cgit v1.2.3-55-g6feb From 4619802a5f399119345ca339886b7b060f2c15aa Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Sun, 14 Aug 2011 13:35:25 -0700 Subject: cttyhack: trivial spelling/spacing fixes Signed-off-by: Kevin Cernekee Signed-off-by: Denys Vlasenko --- shell/cttyhack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shell') diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 37ea13723..6241c76a9 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -139,7 +139,7 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) #endif #ifdef TIOCGSERIAL if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { - /* this is a serial console, asuming it is named /dev/ttySn */ + /* this is a serial console; assuming it is named /dev/ttySn */ sprintf(console + 8, "S%d", u.sr.line); break; } -- cgit v1.2.3-55-g6feb From 4840ae8a06298e987374fa3cc6d7e4969fd19344 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Sep 2011 15:28:03 +0200 Subject: lineedit: fix atomic replace of history file; hush: fix $HISTFILE handling Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 4 ++-- shell/ash.c | 2 +- shell/hush.c | 40 +++++++++++++++++++++++----------------- 3 files changed, 26 insertions(+), 20 deletions(-) (limited to 'shell') diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 10265192e..5d139043a 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1425,7 +1425,7 @@ static void save_history(char *str) /* write out temp file and replace hist_file atomically */ new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid()); - fd = open(state->hist_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fd = open(new_name, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd >= 0) { FILE *fp; int i; @@ -1475,7 +1475,7 @@ static void remember_in_history(char *str) /* i <= state->max_history */ state->cur_history = i; state->cnt_history = i; -# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY +# if ENABLE_FEATURE_EDITING_SAVEHISTORY if ((state->flags & SAVE_HISTORY) && state->hist_file) save_history(str); # endif diff --git a/shell/ash.c b/shell/ash.c index d48cd016f..bf376bd0d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -13194,7 +13194,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } if (sflag || minusc == NULL) { -#if defined MAX_HISTORY && MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY +#if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY if (iflag) { const char *hp = lookupvar("HISTFILE"); if (hp) diff --git a/shell/hush.c b/shell/hush.c index e4138adf7..42143fd9e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7816,23 +7816,7 @@ int hush_main(int argc, char **argv) */ #if ENABLE_FEATURE_EDITING - G.line_input_state = new_line_input_t(FOR_SHELL); -# if defined MAX_HISTORY && MAX_HISTORY > 0 && ENABLE_HUSH_SAVEHISTORY - { - const char *hp = get_local_var_value("HISTFILE"); - if (!hp) { - hp = get_local_var_value("HOME"); - if (hp) { - G.line_input_state->hist_file = concat_path_file(hp, ".hush_history"); - //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 + G.line_input_state = new_line_input_t(FOR_SHELL & ~SAVE_HISTORY); #endif /* Initialize some more globals to non-zero values */ @@ -8104,6 +8088,28 @@ int hush_main(int argc, char **argv) /* -1 is special - makes xfuncs longjmp, not exit * (we reset die_sleep = 0 whereever we [v]fork) */ enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */ + +# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 + { + const char *hp = get_local_var_value("HISTFILE"); + if (!hp) { + hp = get_local_var_value("HOME"); + if (hp) + hp = concat_path_file(hp, ".hush_history"); + } else { + hp = xstrdup(hp); + } + if (hp) { + G.line_input_state->hist_file = hp; + G.line_input_state->flags |= SAVE_HISTORY; + //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 } else { install_special_sighandlers(); } -- cgit v1.2.3-55-g6feb From bede215cf105377a1127532d2d710924cb58cc39 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Sep 2011 16:12:33 +0200 Subject: lineedit: add support for history saving on exit Based on the patch by Dennis Groenen Signed-off-by: Denys Vlasenko --- include/libbb.h | 9 ++++++++ libbb/Config.src | 7 ++++++ libbb/lineedit.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++----- shell/ash.c | 4 ++++ shell/hush.c | 4 ++++ 5 files changed, 86 insertions(+), 6 deletions(-) (limited to 'shell') diff --git a/include/libbb.h b/include/libbb.h index 63d041957..91343a95e 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1421,6 +1421,12 @@ typedef struct line_input_t { int cur_history; int max_history; /* must never be <= 0 */ # if ENABLE_FEATURE_EDITING_SAVEHISTORY + /* meaning of this field depends on FEATURE_EDITING_SAVE_ON_EXIT: + * if !FEATURE_EDITING_SAVE_ON_EXIT: "how many lines are + * in on-disk history" + * if FEATURE_EDITING_SAVE_ON_EXIT: "how many in-memory lines are + * also in on-disk history (and thus need to be skipped on save)" + */ unsigned cnt_history_in_file; const char *hist_file; # endif @@ -1446,6 +1452,9 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC; * >0 length of input string, including terminating '\n' */ int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; +# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT +void save_history(line_input_t *st); +# endif #else #define MAX_HISTORY 0 int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC; diff --git a/libbb/Config.src b/libbb/Config.src index aa442365a..f6f88b9ce 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -94,6 +94,13 @@ config FEATURE_EDITING_SAVEHISTORY help Enable history saving in shells. +config FEATURE_EDITING_SAVE_ON_EXIT + bool "Save history on shell exit, not after every command" + default n + depends on FEATURE_EDITING_SAVEHISTORY + help + Save history on shell exit, not after every command. + config FEATURE_REVERSE_SEARCH bool "Reverse history search" default y diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 5d139043a..0786f9ae6 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1351,7 +1351,9 @@ static void load_history(line_input_t *st_parm) /* fill temp_h[], retaining only last MAX_HISTORY lines */ memset(temp_h, 0, sizeof(temp_h)); - st_parm->cnt_history_in_file = idx = 0; + idx = 0; + if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) + st_parm->cnt_history_in_file = 0; while ((line = xmalloc_fgetline(fp)) != NULL) { if (line[0] == '\0') { free(line); @@ -1359,7 +1361,8 @@ static void load_history(line_input_t *st_parm) } free(temp_h[idx]); temp_h[idx] = line; - st_parm->cnt_history_in_file++; + if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) + st_parm->cnt_history_in_file++; idx++; if (idx == st_parm->max_history) idx = 0; @@ -1389,15 +1392,66 @@ static void load_history(line_input_t *st_parm) st_parm->history[i++] = line; } st_parm->cnt_history = i; + if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) + st_parm->cnt_history_in_file = i; } } -/* state->flags is already checked to be nonzero */ +# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT +void save_history(line_input_t *st) +{ + FILE *fp; + + if (!(st->flags & SAVE_HISTORY)) + return; + if (!st->hist_file) + return; + if (st->cnt_history <= st->cnt_history_in_file) + return; + + fp = fopen(st->hist_file, "a"); + if (fp) { + int i, fd; + char *new_name; + line_input_t *st_temp; + + for (i = st->cnt_history_in_file; i < st->cnt_history; i++) + fprintf(fp, "%s\n", st->history[i]); + fclose(fp); + + /* we may have concurrently written entries from others. + * load them */ + st_temp = new_line_input_t(st->flags); + st_temp->hist_file = st->hist_file; + st_temp->max_history = st->max_history; + load_history(st_temp); + + /* write out temp file and replace hist_file atomically */ + new_name = xasprintf("%s.%u.new", st->hist_file, (int) getpid()); + fd = open(new_name, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd >= 0) { + fp = xfdopen_for_write(fd); + for (i = 0; i < st_temp->cnt_history; i++) + fprintf(fp, "%s\n", st_temp->history[i]); + fclose(fp); + if (rename(new_name, st->hist_file) == 0) + st->cnt_history_in_file = st_temp->cnt_history; + } + free(new_name); + free_line_input_t(st_temp); + } +} +# else static void save_history(char *str) { int fd; int len, len2; + if (!(state->flags & SAVE_HISTORY)) + return; + if (!state->hist_file) + return; + fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600); if (fd < 0) return; @@ -1441,6 +1495,7 @@ static void save_history(char *str) free_line_input_t(st_temp); } } +# endif # else # define load_history(a) ((void)0) # define save_history(a) ((void)0) @@ -1469,15 +1524,16 @@ static void remember_in_history(char *str) for (i = 0; i < state->max_history-1; i++) state->history[i] = state->history[i+1]; /* i == state->max_history-1 */ + if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT && state->cnt_history_in_file) + state->cnt_history_in_file--; } /* i <= state->max_history-1 */ state->history[i++] = xstrdup(str); /* i <= state->max_history */ state->cur_history = i; state->cnt_history = i; -# if ENABLE_FEATURE_EDITING_SAVEHISTORY - if ((state->flags & SAVE_HISTORY) && state->hist_file) - save_history(str); +# if ENABLE_FEATURE_EDITING_SAVEHISTORY && !ENABLE_FEATURE_EDITING_SAVE_ON_EXIT + save_history(str); # endif IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;) } diff --git a/shell/ash.c b/shell/ash.c index bf376bd0d..14472cb61 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12888,6 +12888,10 @@ exitshell(void) char *p; int status; +#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT + save_history(line_input_state); +#endif + status = exitstatus; TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); if (setjmp(loc.loc)) { diff --git a/shell/hush.c b/shell/hush.c index 42143fd9e..a9e2dd311 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1541,6 +1541,10 @@ static sighandler_t pick_sighandler(unsigned sig) static void hush_exit(int exitcode) NORETURN; static void hush_exit(int exitcode) { +#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT + save_history(G.line_input_state); +#endif + fflush_all(); if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) { char *argv[3]; -- cgit v1.2.3-55-g6feb From e45af7ad17c3f0ecaec1d761aa89cb4fd83afbc2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Sep 2011 16:15:24 +0200 Subject: lineedit: remove SAVE_HISTORY bit, ->hist_file can be used as indicator Signed-off-by: Denys Vlasenko --- include/libbb.h | 13 ++++++------- libbb/lineedit.c | 6 +----- shell/hush.c | 3 +-- 3 files changed, 8 insertions(+), 14 deletions(-) (limited to 'shell') diff --git a/include/libbb.h b/include/libbb.h index 91343a95e..1ca448930 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1434,13 +1434,12 @@ typedef struct line_input_t { # endif } line_input_t; enum { - DO_HISTORY = 1 * (MAX_HISTORY > 0), - SAVE_HISTORY = 2 * (MAX_HISTORY > 0) * ENABLE_FEATURE_EDITING_SAVEHISTORY, - TAB_COMPLETION = 4 * ENABLE_FEATURE_TAB_COMPLETION, - USERNAME_COMPLETION = 8 * ENABLE_FEATURE_USERNAME_COMPLETION, - VI_MODE = 0x10 * ENABLE_FEATURE_EDITING_VI, - WITH_PATH_LOOKUP = 0x20, - FOR_SHELL = DO_HISTORY | SAVE_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION, + DO_HISTORY = 1 * (MAX_HISTORY > 0), + TAB_COMPLETION = 2 * ENABLE_FEATURE_TAB_COMPLETION, + USERNAME_COMPLETION = 4 * ENABLE_FEATURE_USERNAME_COMPLETION, + VI_MODE = 8 * ENABLE_FEATURE_EDITING_VI, + WITH_PATH_LOOKUP = 0x10, + FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION, }; line_input_t *new_line_input_t(int flags) FAST_FUNC; /* So far static: void free_line_input_t(line_input_t *n) FAST_FUNC; */ diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 0786f9ae6..603bbfcae 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1402,8 +1402,6 @@ void save_history(line_input_t *st) { FILE *fp; - if (!(st->flags & SAVE_HISTORY)) - return; if (!st->hist_file) return; if (st->cnt_history <= st->cnt_history_in_file) @@ -1447,8 +1445,6 @@ static void save_history(char *str) int fd; int len, len2; - if (!(state->flags & SAVE_HISTORY)) - return; if (!state->hist_file) return; @@ -2188,7 +2184,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman state = st ? st : (line_input_t*) &const_int_0; #if MAX_HISTORY > 0 # if ENABLE_FEATURE_EDITING_SAVEHISTORY - if ((state->flags & SAVE_HISTORY) && state->hist_file) + if (state->hist_file) if (state->cnt_history == 0) load_history(state); # endif diff --git a/shell/hush.c b/shell/hush.c index a9e2dd311..7a34f59ae 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7820,7 +7820,7 @@ int hush_main(int argc, char **argv) */ #if ENABLE_FEATURE_EDITING - G.line_input_state = new_line_input_t(FOR_SHELL & ~SAVE_HISTORY); + G.line_input_state = new_line_input_t(FOR_SHELL); #endif /* Initialize some more globals to non-zero values */ @@ -8105,7 +8105,6 @@ int hush_main(int argc, char **argv) } if (hp) { G.line_input_state->hist_file = hp; - G.line_input_state->flags |= SAVE_HISTORY; //set_local_var(xasprintf("HISTFILE=%s", ...)); } # if ENABLE_FEATURE_SH_HISTFILESIZE -- cgit v1.2.3-55-g6feb From 156840c249ddf761d9e60b06ca6d8aaa1bf88402 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Mon, 31 Oct 2011 13:18:44 +0100 Subject: cttyhack: print detected ctty name when called without parameters Sometimes there's a need to figure out the controlling tty from a shell script, for example, to obtain a line for getty. In this case it's easier to call cttyhack than trying to repeat some of the cttyhack's logic. function old new delta cttyhack_main 283 327 +44 packed_usage 28911 28915 +4 Signed-off-by: Alexander Shishkin Signed-off-by: Denys Vlasenko --- shell/cttyhack.c | 76 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 34 deletions(-) (limited to 'shell') diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 6241c76a9..640f5b1fb 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -50,9 +50,12 @@ //config: //config: # exec setsid sh -c 'exec sh /dev/tty1 2>&1' //config: +//config: Starting getty on a controlling tty from a shell script: +//config: +//config: # getty 115200 $(cttyhack) //usage:#define cttyhack_trivial_usage -//usage: "PROG ARGS" +//usage: "[PROG ARGS]" //usage:#define cttyhack_full_usage "\n\n" //usage: "Give PROG a controlling tty if possible." //usage: "\nExample for /etc/inittab (for busybox init):" @@ -108,61 +111,66 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) char paranoia[sizeof(struct serial_struct) * 3]; } u; - if (!*++argv) { - bb_show_usage(); - } - strcpy(console, "/dev/tty"); fd = open(console, O_RDWR); - if (fd >= 0) { - /* We already have ctty, nothing to do */ - close(fd); - } else { + if (fd < 0) { /* We don't have ctty (or don't have "/dev/tty" node...) */ do { #ifdef __linux__ - int s = open_read_close("/sys/class/tty/console/active", - console + 5, sizeof(console) - 5); - if (s > 0) { - /* found active console via sysfs (Linux 2.6.38+) - * sysfs string looks like "ttyS0\n" so zap the newline: - */ - console[4 + s] = '\0'; - break; - } - + int s; if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { /* this is linux virtual tty */ - sprintf(console + 8, "S%d" + 1, u.vt.v_active); + sprintf(console + 8, "S%u" + 1, (int)u.vt.v_active); break; } #endif #ifdef TIOCGSERIAL if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) { /* this is a serial console; assuming it is named /dev/ttySn */ - sprintf(console + 8, "S%d", u.sr.line); + sprintf(console + 8, "S%u", (int)u.sr.line); + break; + } +#endif +#ifdef __linux__ + /* Note that this method is not related to _stdin_ */ + s = open_read_close("/sys/class/tty/console/active", + console + 5, sizeof(console) - 5); + if (s > 0) { + /* found active console via sysfs (Linux 2.6.38+) + * sysfs string looks like "ttyS0\n" so zap the newline: + */ + console[4 + s] = '\0'; break; } #endif /* nope, could not find it */ - goto ret; + console[0] = '\0'; } while (0); + } + argv++; + if (!argv[0]) { + if (!console[0]) + return EXIT_FAILURE; + puts(console); + return EXIT_SUCCESS; + } + + if (fd < 0) { fd = open_or_warn(console, O_RDWR); if (fd < 0) goto ret; - //bb_error_msg("switching to '%s'", console); - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - while (fd > 2) - close(fd--); - /* Some other session may have it as ctty, - * steal it from them: - */ - ioctl(0, TIOCSCTTY, 1); } - -ret: + //bb_error_msg("switching to '%s'", console); + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + while (fd > 2) + close(fd--); + /* Some other session may have it as ctty, + * try to steal it from them: + */ + ioctl(0, TIOCSCTTY, 1); + ret: BB_EXECVP_or_die(argv); } -- cgit v1.2.3-55-g6feb From f8a5b792ba3cb0d11531902a04600fc274dff69e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 31 Oct 2011 16:57:04 +0100 Subject: cttyhack: move /sys/class/tty/console/active check to the front Signed-off-by: Denys Vlasenko --- shell/cttyhack.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'shell') diff --git a/shell/cttyhack.c b/shell/cttyhack.c index 640f5b1fb..6ff867413 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -117,7 +117,24 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) /* We don't have ctty (or don't have "/dev/tty" node...) */ do { #ifdef __linux__ - int s; + /* Note that this method does not use _stdin_. + * Thus, "cttyhack 0) { + /* found active console via sysfs (Linux 2.6.38+) + * sysfs string looks like "ttyS0\n" so zap the newline: + */ + console[4 + s] = '\0'; + break; + } + if (ioctl(0, VT_GETSTATE, &u.vt) == 0) { /* this is linux virtual tty */ sprintf(console + 8, "S%u" + 1, (int)u.vt.v_active); @@ -130,18 +147,6 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv) sprintf(console + 8, "S%u", (int)u.sr.line); break; } -#endif -#ifdef __linux__ - /* Note that this method is not related to _stdin_ */ - s = open_read_close("/sys/class/tty/console/active", - console + 5, sizeof(console) - 5); - if (s > 0) { - /* found active console via sysfs (Linux 2.6.38+) - * sysfs string looks like "ttyS0\n" so zap the newline: - */ - console[4 + s] = '\0'; - break; - } #endif /* nope, could not find it */ console[0] = '\0'; -- cgit v1.2.3-55-g6feb