1 From bede215cf105377a1127532d2d710924cb58cc39 Mon Sep 17 00:00:00 2001
2 From: Denys Vlasenko <vda.linux@googlemail.com>
3 Date: Sun, 4 Sep 2011 16:12:33 +0200
4 Subject: [PATCH 2/3] lineedit: add support for history saving on exit
6 Based on the patch by Dennis Groenen <tj.groenen@gmail.com>
8 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
10 include/libbb.h | 9 +++++++
11 libbb/Config.src | 7 +++++
12 libbb/lineedit.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++----
15 5 files changed, 86 insertions(+), 6 deletions(-)
17 diff --git a/include/libbb.h b/include/libbb.h
18 index 63d0419..91343a9 100644
21 @@ -1421,6 +1421,12 @@ typedef struct line_input_t {
23 int max_history; /* must never be <= 0 */
24 # if ENABLE_FEATURE_EDITING_SAVEHISTORY
25 + /* meaning of this field depends on FEATURE_EDITING_SAVE_ON_EXIT:
26 + * if !FEATURE_EDITING_SAVE_ON_EXIT: "how many lines are
27 + * in on-disk history"
28 + * if FEATURE_EDITING_SAVE_ON_EXIT: "how many in-memory lines are
29 + * also in on-disk history (and thus need to be skipped on save)"
31 unsigned cnt_history_in_file;
32 const char *hist_file;
34 @@ -1446,6 +1452,9 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC;
35 * >0 length of input string, including terminating '\n'
37 int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC;
38 +# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
39 +void save_history(line_input_t *st);
43 int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
44 diff --git a/libbb/Config.src b/libbb/Config.src
45 index aa44236..f6f88b9 100644
46 --- a/libbb/Config.src
47 +++ b/libbb/Config.src
48 @@ -94,6 +94,13 @@ config FEATURE_EDITING_SAVEHISTORY
50 Enable history saving in shells.
52 +config FEATURE_EDITING_SAVE_ON_EXIT
53 + bool "Save history on shell exit, not after every command"
55 + depends on FEATURE_EDITING_SAVEHISTORY
57 + Save history on shell exit, not after every command.
59 config FEATURE_REVERSE_SEARCH
60 bool "Reverse history search"
62 diff --git a/libbb/lineedit.c b/libbb/lineedit.c
63 index 5d13904..0786f9a 100644
64 --- a/libbb/lineedit.c
65 +++ b/libbb/lineedit.c
66 @@ -1351,7 +1351,9 @@ static void load_history(line_input_t *st_parm)
68 /* fill temp_h[], retaining only last MAX_HISTORY lines */
69 memset(temp_h, 0, sizeof(temp_h));
70 - st_parm->cnt_history_in_file = idx = 0;
72 + if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
73 + st_parm->cnt_history_in_file = 0;
74 while ((line = xmalloc_fgetline(fp)) != NULL) {
75 if (line[0] == '\0') {
77 @@ -1359,7 +1361,8 @@ static void load_history(line_input_t *st_parm)
81 - st_parm->cnt_history_in_file++;
82 + if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
83 + st_parm->cnt_history_in_file++;
85 if (idx == st_parm->max_history)
87 @@ -1389,15 +1392,66 @@ static void load_history(line_input_t *st_parm)
88 st_parm->history[i++] = line;
90 st_parm->cnt_history = i;
91 + if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
92 + st_parm->cnt_history_in_file = i;
96 -/* state->flags is already checked to be nonzero */
97 +# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
98 +void save_history(line_input_t *st)
102 + if (!(st->flags & SAVE_HISTORY))
104 + if (!st->hist_file)
106 + if (st->cnt_history <= st->cnt_history_in_file)
109 + fp = fopen(st->hist_file, "a");
113 + line_input_t *st_temp;
115 + for (i = st->cnt_history_in_file; i < st->cnt_history; i++)
116 + fprintf(fp, "%s\n", st->history[i]);
119 + /* we may have concurrently written entries from others.
121 + st_temp = new_line_input_t(st->flags);
122 + st_temp->hist_file = st->hist_file;
123 + st_temp->max_history = st->max_history;
124 + load_history(st_temp);
126 + /* write out temp file and replace hist_file atomically */
127 + new_name = xasprintf("%s.%u.new", st->hist_file, (int) getpid());
128 + fd = open(new_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
130 + fp = xfdopen_for_write(fd);
131 + for (i = 0; i < st_temp->cnt_history; i++)
132 + fprintf(fp, "%s\n", st_temp->history[i]);
134 + if (rename(new_name, st->hist_file) == 0)
135 + st->cnt_history_in_file = st_temp->cnt_history;
138 + free_line_input_t(st_temp);
142 static void save_history(char *str)
147 + if (!(state->flags & SAVE_HISTORY))
149 + if (!state->hist_file)
152 fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600);
155 @@ -1441,6 +1495,7 @@ static void save_history(char *str)
156 free_line_input_t(st_temp);
161 # define load_history(a) ((void)0)
162 # define save_history(a) ((void)0)
163 @@ -1469,15 +1524,16 @@ static void remember_in_history(char *str)
164 for (i = 0; i < state->max_history-1; i++)
165 state->history[i] = state->history[i+1];
166 /* i == state->max_history-1 */
167 + if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT && state->cnt_history_in_file)
168 + state->cnt_history_in_file--;
170 /* i <= state->max_history-1 */
171 state->history[i++] = xstrdup(str);
172 /* i <= state->max_history */
173 state->cur_history = i;
174 state->cnt_history = i;
175 -# if ENABLE_FEATURE_EDITING_SAVEHISTORY
176 - if ((state->flags & SAVE_HISTORY) && state->hist_file)
178 +# if ENABLE_FEATURE_EDITING_SAVEHISTORY && !ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
181 IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
183 diff --git a/shell/ash.c b/shell/ash.c
184 index bf376bd..14472cb 100644
187 @@ -12888,6 +12888,10 @@ exitshell(void)
191 +#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
192 + save_history(line_input_state);
196 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
197 if (setjmp(loc.loc)) {
198 diff --git a/shell/hush.c b/shell/hush.c
199 index 42143fd..a9e2dd3 100644
202 @@ -1541,6 +1541,10 @@ static sighandler_t pick_sighandler(unsigned sig)
203 static void hush_exit(int exitcode) NORETURN;
204 static void hush_exit(int exitcode)
206 +#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
207 + save_history(G.line_input_state);
211 if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) {