synchronize history patches with busybox git
[busybox-power] / debian / patches / git-backports / 0002-lineedit-add-support-for-history-saving-on-exit.patch
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
5
6 Based on the patch by Dennis Groenen <tj.groenen@gmail.com>
7
8 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
9 ---
10  include/libbb.h  |    9 +++++++
11  libbb/Config.src |    7 +++++
12  libbb/lineedit.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++++----
13  shell/ash.c      |    4 +++
14  shell/hush.c     |    4 +++
15  5 files changed, 86 insertions(+), 6 deletions(-)
16
17 diff --git a/include/libbb.h b/include/libbb.h
18 index 63d0419..91343a9 100644
19 --- a/include/libbb.h
20 +++ b/include/libbb.h
21 @@ -1421,6 +1421,12 @@ typedef struct line_input_t {
22         int cur_history;
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)"
30 +        */
31         unsigned cnt_history_in_file;
32         const char *hist_file;
33  #  endif
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'
36   */
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);
40 +# endif
41  #else
42  #define MAX_HISTORY 0
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
49         help
50           Enable history saving in shells.
51  
52 +config FEATURE_EDITING_SAVE_ON_EXIT
53 +       bool "Save history on shell exit, not after every command"
54 +       default n
55 +       depends on FEATURE_EDITING_SAVEHISTORY
56 +       help
57 +         Save history on shell exit, not after every command.
58 +
59  config FEATURE_REVERSE_SEARCH
60         bool "Reverse history search"
61         default y
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)
67  
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;
71 +               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') {
76                                 free(line);
77 @@ -1359,7 +1361,8 @@ static void load_history(line_input_t *st_parm)
78                         }
79                         free(temp_h[idx]);
80                         temp_h[idx] = line;
81 -                       st_parm->cnt_history_in_file++;
82 +                       if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
83 +                               st_parm->cnt_history_in_file++;
84                         idx++;
85                         if (idx == st_parm->max_history)
86                                 idx = 0;
87 @@ -1389,15 +1392,66 @@ static void load_history(line_input_t *st_parm)
88                         st_parm->history[i++] = line;
89                 }
90                 st_parm->cnt_history = i;
91 +               if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
92 +                       st_parm->cnt_history_in_file = i;
93         }
94  }
95  
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)
99 +{
100 +       FILE *fp;
101 +
102 +       if (!(st->flags & SAVE_HISTORY))
103 +               return;
104 +       if (!st->hist_file)
105 +               return;
106 +       if (st->cnt_history <= st->cnt_history_in_file)
107 +               return;
108 +
109 +       fp = fopen(st->hist_file, "a");
110 +       if (fp) {
111 +               int i, fd;
112 +               char *new_name;
113 +               line_input_t *st_temp;
114 +
115 +               for (i = st->cnt_history_in_file; i < st->cnt_history; i++)
116 +                       fprintf(fp, "%s\n", st->history[i]);
117 +               fclose(fp);
118 +
119 +               /* we may have concurrently written entries from others.
120 +                * load them */
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);
125 +
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);
129 +               if (fd >= 0) {
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]);
133 +                       fclose(fp);
134 +                       if (rename(new_name, st->hist_file) == 0)
135 +                               st->cnt_history_in_file = st_temp->cnt_history;
136 +               }
137 +               free(new_name);
138 +               free_line_input_t(st_temp);
139 +       }
140 +}
141 +#  else
142  static void save_history(char *str)
143  {
144         int fd;
145         int len, len2;
146  
147 +       if (!(state->flags & SAVE_HISTORY))
148 +               return;
149 +       if (!state->hist_file)
150 +               return;
151 +
152         fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600);
153         if (fd < 0)
154                 return;
155 @@ -1441,6 +1495,7 @@ static void save_history(char *str)
156                 free_line_input_t(st_temp);
157         }
158  }
159 +#  endif
160  # else
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--;
169         }
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)
177 -               save_history(str);
178 +# if ENABLE_FEATURE_EDITING_SAVEHISTORY && !ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
179 +       save_history(str);
180  # endif
181         IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
182  }
183 diff --git a/shell/ash.c b/shell/ash.c
184 index bf376bd..14472cb 100644
185 --- a/shell/ash.c
186 +++ b/shell/ash.c
187 @@ -12888,6 +12888,10 @@ exitshell(void)
188         char *p;
189         int status;
190  
191 +#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
192 +       save_history(line_input_state);
193 +#endif
194 +
195         status = exitstatus;
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
200 --- a/shell/hush.c
201 +++ b/shell/hush.c
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)
205  {
206 +#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
207 +       save_history(G.line_input_state);
208 +#endif
209 +
210         fflush_all();
211         if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) {
212                 char *argv[3];
213 -- 
214 1.7.6.1
215