ad94b9aaeee6f5f42b40a123ef4f51033019073e
[busybox-power] / debian / patches / obselete / shell-hist.patch
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>
4
5 Ported to BusyBox 1.18.4 by Dennis Groenen <dennis_groenen@hotmail.com> - 2011-04-29  
6 ---
7
8 --- a/libbb/lineedit.c
9 +++ b/libbb/lineedit.c
10 @@ -1275,130 +1275,52 @@ static int get_next_history(void)
11  }
12  
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.
17 - *
18 - * History file is trimmed lazily, when it grows several times longer
19 - * than configured MAX_HISTORY lines.
20 - */
21 -
22 -static void free_line_input_t(line_input_t *n)
23 -{
24 -       int i = n->cnt_history;
25 -       while (i > 0)
26 -               free(n->history[--i]);
27 -       free(n);
28 -}
29 -
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)
33  {
34 -       char *temp_h[MAX_HISTORY];
35 -       char *line;
36         FILE *fp;
37 -       unsigned idx, i, line_len;
38 +       int hi = 0;
39  
40 -       /* NB: do not trash old history if file can't be opened */
41 +       if (!state->cnt_history) {
42 +               fp = fopen(fromfile, "r");
43 +               if (fp) {
44 +                       for (hi = 0; hi < MAX_HISTORY;) {
45 +                               char *hl = xmalloc_fgetline(fp);
46 +                               int l;
47  
48 -       fp = fopen_for_read(st_parm->hist_file);
49 -       if (fp) {
50 -               /* clean up old history */
51 -               for (idx = st_parm->cnt_history; idx > 0;) {
52 -                       idx--;
53 -                       free(st_parm->history[idx]);
54 -                       st_parm->history[idx] = NULL;
55 -               }
56 -
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') {
62 -                               free(line);
63 -                               continue;
64 -                       }
65 -                       free(temp_h[idx]);
66 -                       temp_h[idx] = line;
67 -                       st_parm->cnt_history_in_file++;
68 -                       idx++;
69 -                       if (idx == MAX_HISTORY)
70 -                               idx = 0;
71 -               }
72 -               fclose(fp);
73 -
74 -               /* find first non-NULL temp_h[], if any */
75 -               if (st_parm->cnt_history_in_file) {
76 -                       while (temp_h[idx] == NULL) {
77 -                               idx++;
78 -                               if (idx == MAX_HISTORY)
79 -                                       idx = 0;
80 +                               if (!hl)
81 +                                       break;
82 +                               l = strlen(hl);
83 +                               if (l >= MAX_LINELEN)
84 +                                       hl[MAX_LINELEN-1] = '\0';
85 +                               if (l == 0 || hl[0] == ' ') {
86 +                                       free(hl);
87 +                                       continue;
88 +                               }
89 +                               state->history[hi++] = hl;
90                         }
91 +                       fclose(fp);
92                 }
93 -
94 -               /* copy temp_h[] to st_parm->history[] */
95 -               for (i = 0; i < MAX_HISTORY;) {
96 -                       line = temp_h[idx];
97 -                       if (!line)
98 -                               break;
99 -                       idx++;
100 -                       if (idx == MAX_HISTORY)
101 -                               idx = 0;
102 -                       line_len = strlen(line);
103 -                       if (line_len >= MAX_LINELEN)
104 -                               line[MAX_LINELEN-1] = '\0';
105 -                       st_parm->history[i++] = line;
106 -               }
107 -               st_parm->cnt_history = i;
108 +               state->cur_history = state->cnt_history = hi;
109         }
110  }
111  
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)
116  {
117 -       int fd;
118 -       int len, len2;
119 +       FILE *fp;
120  
121 -       fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600);
122 -       if (fd < 0)
123 -               return;
124 -       xlseek(fd, 0, SEEK_END); /* paranoia */
125 -       len = strlen(str);
126 -       str[len] = '\n'; /* we (try to) do atomic write */
127 -       len2 = full_write(fd, str, len + 1);
128 -       str[len] = '\0';
129 -       close(fd);
130 -       if (len2 != len + 1)
131 -               return; /* "wtf?" */
132 -
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) {
136 -               char *new_name;
137 -               line_input_t *st_temp;
138 -
139 -               /* we may have concurrently written entries from others.
140 -                * load them */
141 -               st_temp = new_line_input_t(state->flags);
142 -               st_temp->hist_file = state->hist_file;
143 -               load_history(st_temp);
144 -
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);
148 -               if (fd >= 0) {
149 -                       FILE *fp;
150 +       if (st->cnt_history) {
151 +               fp = fopen(st->hist_file, "w");
152 +               if (fp) {
153                         int i;
154  
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]);
160 +                       }
161                         fclose(fp);
162 -                       if (rename(new_name, state->hist_file) == 0)
163 -                               state->cnt_history_in_file = st_temp->cnt_history;
164                 }
165 -               free(new_name);
166 -               free_line_input_t(st_temp);
167         }
168  }
169  # else
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)
176 -               save_history(str);
177 -# endif
178         IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
179  }
180  
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);
187  # endif
188         if (state->flags & DO_HISTORY)
189                 state->cur_history = state->cnt_history;
190 diff -urpN a/shell/ash.c b/shell/ash.c
191 --- a/shell/ash.c
192 +++ b/shell/ash.c
193 @@ -51,6 +51,9 @@
194  #else
195  # define CLEAR_RANDOM_T(rnd) ((void)0)
196  #endif
197 +#if ENABLE_FEATURE_EDITING_SAVEHISTORY
198 +void save_history(line_input_t *);
199 +#endif
200  
201  #include "NUM_APPLETS.h"
202  #if NUM_APPLETS == 1
203 @@ -12810,6 +12813,10 @@ exitshell(void)
204         char *p;
205         int status;
206  
207 +       if (iflag && (line_input_state->flags & SAVE_HISTORY)
208 +           && line_input_state->hist_file && !shlvl) {
209 +               save_history(line_input_state);
210 +       }
211         status = exitstatus;
212         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
213         if (setjmp(loc.loc)) {