1 Patch to only update history upon shell exit.
2 Should prevent unnecessary wear on the flash and save some power.
3 By Alexander Shishkin <ext-alexander.shishkin@nokia.com>
5 Ported to BusyBox 1.18.4 by Dennis Groenen <dennis_groenen@hotmail.com> - 2011-04-29
10 @@ -1275,130 +1275,52 @@ static int get_next_history(void)
13 # if ENABLE_FEATURE_EDITING_SAVEHISTORY
14 -/* We try to ensure that concurrent additions to the history
15 - * do not overwrite each other.
16 - * Otherwise shell users get unhappy.
18 - * History file is trimmed lazily, when it grows several times longer
19 - * than configured MAX_HISTORY lines.
22 -static void free_line_input_t(line_input_t *n)
24 - int i = n->cnt_history;
26 - free(n->history[--i]);
30 /* state->flags is already checked to be nonzero */
31 -static void load_history(line_input_t *st_parm)
32 +static void load_history(const char *fromfile)
34 - char *temp_h[MAX_HISTORY];
37 - unsigned idx, i, line_len;
40 - /* NB: do not trash old history if file can't be opened */
41 + if (!state->cnt_history) {
42 + fp = fopen(fromfile, "r");
44 + for (hi = 0; hi < MAX_HISTORY;) {
45 + char *hl = xmalloc_fgetline(fp);
48 - fp = fopen_for_read(st_parm->hist_file);
50 - /* clean up old history */
51 - for (idx = st_parm->cnt_history; idx > 0;) {
53 - free(st_parm->history[idx]);
54 - st_parm->history[idx] = NULL;
57 - /* fill temp_h[], retaining only last MAX_HISTORY lines */
58 - memset(temp_h, 0, sizeof(temp_h));
59 - st_parm->cnt_history_in_file = idx = 0;
60 - while ((line = xmalloc_fgetline(fp)) != NULL) {
61 - if (line[0] == '\0') {
67 - st_parm->cnt_history_in_file++;
69 - if (idx == MAX_HISTORY)
74 - /* find first non-NULL temp_h[], if any */
75 - if (st_parm->cnt_history_in_file) {
76 - while (temp_h[idx] == NULL) {
78 - if (idx == MAX_HISTORY)
83 + if (l >= MAX_LINELEN)
84 + hl[MAX_LINELEN-1] = '\0';
85 + if (l == 0 || hl[0] == ' ') {
89 + state->history[hi++] = hl;
94 - /* copy temp_h[] to st_parm->history[] */
95 - for (i = 0; i < MAX_HISTORY;) {
100 - if (idx == MAX_HISTORY)
102 - line_len = strlen(line);
103 - if (line_len >= MAX_LINELEN)
104 - line[MAX_LINELEN-1] = '\0';
105 - st_parm->history[i++] = line;
107 - st_parm->cnt_history = i;
108 + state->cur_history = state->cnt_history = hi;
112 /* state->flags is already checked to be nonzero */
113 -static void save_history(char *str)
114 +void save_history(line_input_t *);
115 +void save_history(line_input_t *st)
121 - fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600);
124 - xlseek(fd, 0, SEEK_END); /* paranoia */
126 - str[len] = '\n'; /* we (try to) do atomic write */
127 - len2 = full_write(fd, str, len + 1);
130 - if (len2 != len + 1)
131 - return; /* "wtf?" */
133 - /* did we write so much that history file needs trimming? */
134 - state->cnt_history_in_file++;
135 - if (state->cnt_history_in_file > MAX_HISTORY * 4) {
137 - line_input_t *st_temp;
139 - /* we may have concurrently written entries from others.
141 - st_temp = new_line_input_t(state->flags);
142 - st_temp->hist_file = state->hist_file;
143 - load_history(st_temp);
145 - /* write out temp file and replace hist_file atomically */
146 - new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid());
147 - fd = open(state->hist_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
150 + if (st->cnt_history) {
151 + fp = fopen(st->hist_file, "w");
155 - fp = xfdopen_for_write(fd);
156 - for (i = 0; i < st_temp->cnt_history; i++)
157 - fprintf(fp, "%s\n", st_temp->history[i]);
158 + for (i = 0; i < st->cnt_history; i++) {
159 + fprintf(fp, "%s\n", st->history[i]);
162 - if (rename(new_name, state->hist_file) == 0)
163 - state->cnt_history_in_file = st_temp->cnt_history;
166 - free_line_input_t(st_temp);
170 @@ -1435,10 +1357,6 @@ static void remember_in_history(char *st
171 /* i <= MAX_HISTORY */
172 state->cur_history = i;
173 state->cnt_history = i;
174 -# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
175 - if ((state->flags & SAVE_HISTORY) && state->hist_file)
178 IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
181 @@ -1960,7 +1878,7 @@ int FAST_FUNC read_line_input(const char
182 # if ENABLE_FEATURE_EDITING_SAVEHISTORY
183 if ((state->flags & SAVE_HISTORY) && state->hist_file)
184 if (state->cnt_history == 0)
185 - load_history(state);
186 + load_history(state->hist_file);
188 if (state->flags & DO_HISTORY)
189 state->cur_history = state->cnt_history;
190 diff -urpN a/shell/ash.c b/shell/ash.c
195 # define CLEAR_RANDOM_T(rnd) ((void)0)
197 +#if ENABLE_FEATURE_EDITING_SAVEHISTORY
198 +void save_history(line_input_t *);
201 #include "NUM_APPLETS.h"
203 @@ -12810,6 +12813,10 @@ exitshell(void)
207 + if (iflag && (line_input_state->flags & SAVE_HISTORY)
208 + && line_input_state->hist_file && !shlvl) {
209 + save_history(line_input_state);
212 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
213 if (setjmp(loc.loc)) {