This mail is a follow up to "[PATCH] ash: add support for history buffer"
On 08/09/2011 05:05 AM, Denys Vlasenko wrote:
All you need is to create a CONFIG_ option which disables
"save history to disk after every command" behavior in remember_in_history()
function, makes save_history() non-static and calls it on shell exit
in both ash and hush.
Pardon the late reply, I was outside the country last week. I gave what
you said a shot. Attached is the resulting patch that implements bash
like history saving in BusyBox.
All introduced code resides behind the new
FEATURE_EDITING_DELAYEDHISTORY config option. When a shell gets closed,
its history will get appended to its respective history file. This is
modeled after how bash handles (parallel) shells with regards to shell
history. There are no signs of history contamination when using parallel
shells.
There is, however, one (major) blocker with my patch. For some reason,
both the conditions "G.line_input_state->flags & SAVE_HISTORY" and
"G.line_input_state->hist_file" are true in hush when hush is not being
ran as an interactive shell (e.g. hush -c "echo hello"). Saving shell
history upon shell exit then will of course cause hush to segfault. Is
there a bug in hush causing those conditions to be true, or am I
overlooking something (in hush_exit())? This problem does not occur in
ash, which shares most of its history handling code with hush. Any input
on this is highly appreciated.
--Dennis
>From c7f39e550a60976f4de4cb4ddc93b53d55be5acc Mon Sep 17 00:00:00 2001
From: Dennis Groenen <[email protected]>
Date: Thu, 18 Aug 2011 15:02:01 +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 | 9 ++++++++-
5 files changed, 47 insertions(+), 2 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..6c68bfe 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1158,7 +1158,6 @@ static void cmdedit_update_prompt(void);
# define cmdedit_update_prompt() ((void)0)
#endif
-
/* Utility functions
*/
/* Replace each \x with x in place, return ptr past NUL. */
@@ -1541,6 +1540,14 @@ static sighandler_t pick_sighandler(unsigned sig)
static void hush_exit(int exitcode) NORETURN;
static void hush_exit(int exitcode)
{
+
+/* The following if statement always returns true?
+ * Therefore, hush will segfault when being ran with -c "command" */
+#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
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox