# CONFIG_FEATURE_EDITING_VI is not set
CONFIG_FEATURE_EDITING_HISTORY=100
CONFIG_FEATURE_EDITING_SAVEHISTORY=y
+CONFIG_FEATURE_EDITING_DELAYEDHISTORY=y
CONFIG_FEATURE_REVERSE_SEARCH=y
CONFIG_FEATURE_TAB_COMPLETION=y
# CONFIG_FEATURE_USERNAME_COMPLETION is not set
CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
CONFIG_ASH_RANDOM_SUPPORT=y
CONFIG_ASH_EXPAND_PRMT=y
-CONFIG_ASH_HIST_BUFFER=y
-CONFIG_ASH_HIST_BUFFER_PATH="/tmp"
CONFIG_CTTYHACK=y
CONFIG_HUSH=y
CONFIG_HUSH_BASH_COMPAT=y
--- /dev/null
+From 772cc01d3739d50ae43858fed8ec733c0c7bf00c Mon Sep 17 00:00:00 2001
+From: Dennis Groenen <tj.groenen@gmail.com>
+Date: Sun, 21 Aug 2011 13:28:34 +0200
+Subject: [PATCH] add support for delayed history saving
+
+---
+ include/libbb.h | 3 +++
+ libbb/Config.src | 8 ++++++++
+ libbb/lineedit.c | 24 +++++++++++++++++++++++-
+ shell/ash.c | 5 +++++
+ shell/hush.c | 5 +++++
+ 5 files changed, 44 insertions(+), 1 deletions(-)
+
+diff --git a/include/libbb.h b/include/libbb.h
+index 63d0419..233b674 100644
+--- a/include/libbb.h
++++ b/include/libbb.h
+@@ -1446,6 +1446,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_DELAYEDHISTORY
++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 aa44236..deee15f 100644
+--- a/libbb/Config.src
++++ b/libbb/Config.src
+@@ -94,6 +94,14 @@ config FEATURE_EDITING_SAVEHISTORY
+ help
+ Enable history saving in shells.
+
++config FEATURE_EDITING_DELAYEDHISTORY
++ bool "Delayed history saving"
++ default n
++ depends on FEATURE_EDITING_SAVEHISTORY
++ help
++ Disable saving history to disk after every command. Write out
++ history only upon shell closure instead.
++
+ config FEATURE_REVERSE_SEARCH
+ bool "Reverse history search"
+ default y
+diff --git a/libbb/lineedit.c b/libbb/lineedit.c
+index 1026519..48ac509 100644
+--- a/libbb/lineedit.c
++++ b/libbb/lineedit.c
+@@ -1392,10 +1392,29 @@ static void load_history(line_input_t *st_parm)
+ }
+ }
+
+-/* state->flags is already checked to be nonzero */
++# if ENABLE_FEATURE_EDITING_DELAYEDHISTORY
++void save_history(line_input_t *st)
++# else
+ static void save_history(char *str)
++# endif
+ {
+ int fd;
++# if ENABLE_FEATURE_EDITING_DELAYEDHISTORY
++# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
++ FILE *f_hist_file;
++ state = st ? st : (line_input_t*) &const_int_0;
++ f_hist_file = fopen(state->hist_file,"a");
++ if (f_hist_file) {
++ int i;
++ for (i = state->cnt_history_in_file; i < state->cnt_history; i++)
++ fprintf(f_hist_file, "%s\n", state->history[i]);
++ }
++ fclose(f_hist_file);
++# else
++ return;
++# endif
++# else
++ /* state->flags is already checked to be nonzero */
+ int len, len2;
+
+ fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600);
+@@ -1409,6 +1428,7 @@ static void save_history(char *str)
+ close(fd);
+ if (len2 != len + 1)
+ return; /* "wtf?" */
++# endif /* FEATURE_EDITING_DELAYEDHISTORY */
+
+ /* did we write so much that history file needs trimming? */
+ state->cnt_history_in_file++;
+@@ -1475,10 +1495,12 @@ static void remember_in_history(char *str)
+ /* i <= state->max_history */
+ state->cur_history = i;
+ state->cnt_history = i;
++#if !ENABLE_FEATURE_EDITING_DELAYEDHISTORY /* save_history() will be called by exit_shell() */
+ # if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
+ if ((state->flags & SAVE_HISTORY) && state->hist_file)
+ save_history(str);
+ # endif
++#endif
+ IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
+ }
+
+diff --git a/shell/ash.c b/shell/ash.c
+index d48cd01..08d4e92 100644
+--- a/shell/ash.c
++++ b/shell/ash.c
+@@ -12888,6 +12888,11 @@ exitshell(void)
+ char *p;
+ int status;
+
++#if ENABLE_FEATURE_EDITING_DELAYEDHISTORY
++ if ((line_input_state->flags & SAVE_HISTORY) && line_input_state->hist_file)
++ 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 e4138ad..a7428d6 100644
+--- a/shell/hush.c
++++ b/shell/hush.c
+@@ -1541,6 +1541,11 @@ static sighandler_t pick_sighandler(unsigned sig)
+ static void hush_exit(int exitcode) NORETURN;
+ static void hush_exit(int exitcode)
+ {
++#if ENABLE_FEATURE_EDITING_DELAYEDHISTORY
++ if ((G.line_input_state->flags & SAVE_HISTORY) && G.line_input_state->hist_file)
++ 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];
+--
+1.7.6
+
--- /dev/null
+From 03b2e51fbe2d69823cea54e6b3ecb7db7d981879 Mon Sep 17 00:00:00 2001
+From: Dennis Groenen <tj.groenen@gmail.com>
+Date: Sun, 21 Aug 2011 13:31:41 +0200
+Subject: [PATCH] hush: don't save history when non-interactive
+
+---
+ shell/hush.c | 7 +++++++
+ 1 files changed, 7 insertions(+), 0 deletions(-)
+
+diff --git a/shell/hush.c b/shell/hush.c
+index a7428d6..4ea641b 100644
+--- a/shell/hush.c
++++ b/shell/hush.c
+@@ -7832,6 +7832,7 @@ int hush_main(int argc, char **argv)
+ //set_local_var(xasprintf("HISTFILE=%s", ...));
+ }
+ }
++ G.line_input_state->flags &= ~SAVE_HISTORY; /* hush is non-interactive at this point */
+ # if ENABLE_FEATURE_SH_HISTFILESIZE
+ hp = get_local_var_value("HISTFILESIZE");
+ G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
+@@ -8053,6 +8054,12 @@ int hush_main(int argc, char **argv)
+ * standard output is a terminal
+ * Refer to Posix.2, the description of the 'sh' utility.
+ */
++#if ENABLE_FEATURE_EDITING
++# if defined MAX_HISTORY && MAX_HISTORY > 0 && ENABLE_HUSH_SAVEHISTORY
++ G.line_input_state->flags |= SAVE_HISTORY;
++# endif
++#endif
++
+ #if ENABLE_HUSH_JOB
+ if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
+ G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
+--
+1.7.6
+
+++ /dev/null
-Allows the user to specify a location at compile time for temporarily storing ash's history file until the shell is closed.
-NB This is only useful if ASH_HIST_BUFFER_PATH points to an in-memory filesystem.
-By Dennis Groenen <tj.groenen@gmail.com> - 2011-08-20
----
-
---- a/shell/ash.c
-+++ b/shell/ash.c
-@@ -184,6 +184,24 @@
- //config: This option recreates the prompt string from the environment
- //config: variable each time it is displayed.
- //config:
-+//config:config ASH_HIST_BUFFER
-+//config: bool "History buffer"
-+//config: default n
-+//config: depends on ASH && FEATURE_EDITING_SAVEHISTORY
-+//config: help
-+//config: Allows you to set a temporary location for .ash_history.
-+//config: History is saved to this custom location, and written out to
-+//config: its default location (~/.ash_history) upon shell exit.
-+//config: Useful to prevent wear on flash-based storage devices.
-+//config:
-+//config:config ASH_HIST_BUFFER_PATH
-+//config: string "History buffer location"
-+//config: default "/tmp"
-+//config: depends on ASH && ASH_HIST_BUFFER
-+//config: help
-+//config: Directory which will be used to save the shell history until
-+//config: ash is exited.
-+//config:
-
- //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
- //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
-@@ -12888,6 +12906,14 @@ exitshell(void)
- char *p;
- int status;
-
-+#if ENABLE_ASH_HIST_BUFFER
-+ const char *tmphistory = lookupvar("HISTFILE");
-+ const char *storedhistory = lookupvar("STOREDHISTFILE");
-+
-+ if (storedhistory) /* is NULL when setting up the history buffer failed; check for this before copying */
-+ copy_file(tmphistory, storedhistory, FILEUTILS_FORCE | FILEUTILS_DEREFERENCE | FILEUTILS_PRESERVE_STATUS);
-+#endif
-+
- status = exitstatus;
- TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
- if (setjmp(loc.loc)) {
-@@ -13151,9 +13177,59 @@ int ash_main(int argc UNUSED_PARAM, char
- if (!hp) {
- hp = lookupvar("HOME");
- if (hp) {
-+#if ENABLE_ASH_HIST_BUFFER
-+ char *tmppath;
-+ char *tmphistory;
-+ char *storedhistory;
-+ const char *user = lookupvar("USER");
-+
-+ tmppath = concat_path_file(CONFIG_ASH_HIST_BUFFER_PATH, user);
-+ tmphistory = concat_path_file(tmppath, ".ash_history");
-+ storedhistory = concat_path_file(hp, ".ash_history");
-+
-+ if (access(CONFIG_ASH_HIST_BUFFER_PATH, R_OK == -1)) {
-+ bb_simple_perror_msg("could not access history buffer path");
-+ goto bail;
-+ }
-+
-+ if (bb_make_directory(tmppath, S_IRWXU, FILEUTILS_RECUR)) {
-+ /* bb_make_directory is noisy, no need for an additional error message */
-+ goto bail;
-+ } else {
-+ struct stat stat_tmppath;
-+ stat(tmppath, &stat_tmppath);
-+ if (stat_tmppath.st_uid != geteuid() || stat_tmppath.st_mode & (S_IRWXG | S_IRWXO)) {
-+ errno = 0;
-+ bb_simple_perror_msg("history buffer is not exclusive to the shell user");
-+ goto bail;
-+ }
-+ }
-+
-+ if (access(tmphistory, R_OK | W_OK) == -1) {
-+ if (access(storedhistory, R_OK) != -1) {
-+ if (copy_file(storedhistory, tmphistory, FILEUTILS_FORCE | FILEUTILS_DEREFERENCE | FILEUTILS_PRESERVE_STATUS) == -1) {
-+ /* copy_file is noisy too, no need for an additional error message */
-+ goto bail;
-+ }
-+ }
-+ }
-+ setvar("STOREDHISTFILE", storedhistory, 0);
-+ goto out;
-+
-+ bail:
-+ errno = 0;
-+ bb_simple_perror_msg("shell history will not be saved");
-+ tmphistory = xasprintf("/dev/null");
-+ out:
-+ setvar("HISTFILE", tmphistory, 0);
-+ free(storedhistory);
-+ free(tmphistory);
-+ free(tmppath);
-+#else
- char *defhp = concat_path_file(hp, ".ash_history");
- setvar("HISTFILE", defhp, 0);
- free(defhp);
-+#endif
- }
- }
- }
--- /dev/null
+Allows the user to specify a location at compile time for temporarily storing ash's history file until the shell is closed.
+NB This is only useful if ASH_HIST_BUFFER_PATH points to an in-memory filesystem.
+By Dennis Groenen <tj.groenen@gmail.com> - 2011-08-20
+---
+
+--- a/shell/ash.c
++++ b/shell/ash.c
+@@ -184,6 +184,24 @@
+ //config: This option recreates the prompt string from the environment
+ //config: variable each time it is displayed.
+ //config:
++//config:config ASH_HIST_BUFFER
++//config: bool "History buffer"
++//config: default n
++//config: depends on ASH && FEATURE_EDITING_SAVEHISTORY
++//config: help
++//config: Allows you to set a temporary location for .ash_history.
++//config: History is saved to this custom location, and written out to
++//config: its default location (~/.ash_history) upon shell exit.
++//config: Useful to prevent wear on flash-based storage devices.
++//config:
++//config:config ASH_HIST_BUFFER_PATH
++//config: string "History buffer location"
++//config: default "/tmp"
++//config: depends on ASH && ASH_HIST_BUFFER
++//config: help
++//config: Directory which will be used to save the shell history until
++//config: ash is exited.
++//config:
+
+ //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
+ //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
+@@ -12888,6 +12906,14 @@ exitshell(void)
+ char *p;
+ int status;
+
++#if ENABLE_ASH_HIST_BUFFER
++ const char *tmphistory = lookupvar("HISTFILE");
++ const char *storedhistory = lookupvar("STOREDHISTFILE");
++
++ if (storedhistory) /* is NULL when setting up the history buffer failed; check for this before copying */
++ copy_file(tmphistory, storedhistory, FILEUTILS_FORCE | FILEUTILS_DEREFERENCE | FILEUTILS_PRESERVE_STATUS);
++#endif
++
+ status = exitstatus;
+ TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
+ if (setjmp(loc.loc)) {
+@@ -13151,9 +13177,59 @@ int ash_main(int argc UNUSED_PARAM, char
+ if (!hp) {
+ hp = lookupvar("HOME");
+ if (hp) {
++#if ENABLE_ASH_HIST_BUFFER
++ char *tmppath;
++ char *tmphistory;
++ char *storedhistory;
++ const char *user = lookupvar("USER");
++
++ tmppath = concat_path_file(CONFIG_ASH_HIST_BUFFER_PATH, user);
++ tmphistory = concat_path_file(tmppath, ".ash_history");
++ storedhistory = concat_path_file(hp, ".ash_history");
++
++ if (access(CONFIG_ASH_HIST_BUFFER_PATH, R_OK == -1)) {
++ bb_simple_perror_msg("could not access history buffer path");
++ goto bail;
++ }
++
++ if (bb_make_directory(tmppath, S_IRWXU, FILEUTILS_RECUR)) {
++ /* bb_make_directory is noisy, no need for an additional error message */
++ goto bail;
++ } else {
++ struct stat stat_tmppath;
++ stat(tmppath, &stat_tmppath);
++ if (stat_tmppath.st_uid != geteuid() || stat_tmppath.st_mode & (S_IRWXG | S_IRWXO)) {
++ errno = 0;
++ bb_simple_perror_msg("history buffer is not exclusive to the shell user");
++ goto bail;
++ }
++ }
++
++ if (access(tmphistory, R_OK | W_OK) == -1) {
++ if (access(storedhistory, R_OK) != -1) {
++ if (copy_file(storedhistory, tmphistory, FILEUTILS_FORCE | FILEUTILS_DEREFERENCE | FILEUTILS_PRESERVE_STATUS) == -1) {
++ /* copy_file is noisy too, no need for an additional error message */
++ goto bail;
++ }
++ }
++ }
++ setvar("STOREDHISTFILE", storedhistory, 0);
++ goto out;
++
++ bail:
++ errno = 0;
++ bb_simple_perror_msg("shell history will not be saved");
++ tmphistory = xasprintf("/dev/null");
++ out:
++ setvar("HISTFILE", tmphistory, 0);
++ free(storedhistory);
++ free(tmphistory);
++ free(tmppath);
++#else
+ char *defhp = concat_path_file(hp, ".ash_history");
+ setvar("HISTFILE", defhp, 0);
+ free(defhp);
++#endif
+ }
+ }
+ }
#New patches as per reported issues by users
showkey-default-option.patch
ps-accept-and-ignore-missing-options.patch
-ash-history-buffer.patch
+0001-add-support-for-delayed-history-saving.patch
+0002-hush-don-t-save-history-when-non-interactive.patch