Imported from ../bash-1.14.7.tar.gz.
[platform/upstream/bash.git] / bashhist.c
1 /* bashhist.c -- bash interface to the GNU history library. */
2
3 /* Copyright (C) 1993 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
7    Bash is free software; you can redistribute it and/or modify it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 2, or (at your option) any later
10    version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17    You should have received a copy of the GNU General Public License along
18    with Bash; see the file COPYING.  If not, write to the Free Software
19    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include <sys/types.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include "bashansi.h"
25 #include "posixstat.h"
26 #include "filecntl.h"
27 #include "shell.h"
28 #include "flags.h"
29 #include <readline/history.h>
30
31 /* Declarations of bash history variables. */
32 /* Non-zero means to remember lines typed to the shell on the history
33    list.  This is different than the user-controlled behaviour; this
34    becomes zero when we read lines from a file, for example. */
35 int remember_on_history = 1;
36
37 /* The number of lines that Bash has added to this history session. */
38 int history_lines_this_session = 0;
39
40 /* The number of lines that Bash has read from the history file. */
41 int history_lines_in_file = 0;
42
43 /* Non-zero means do no history expansion on this line, regardless
44    of what history_expansion says. */
45 int history_expansion_inhibited = 0;
46
47 /* By default, every line is saved in the history individually.  I.e.,
48    if the user enters:
49         bash$ for i in a b c
50         > do
51         > echo $i
52         > done
53    Each line will be individually saved in the history.
54         bash$ history
55         10  for i in a b c
56         11  do
57         12  echo $i
58         13  done
59         14  history
60    If the variable command_oriented_history is set, multiple lines
61    which form one command will be saved as one history entry.
62         bash$ for i in a b c
63         > do
64         > echo $i
65         > done
66         bash$ history
67         10  for i in a b c
68     do
69     echo $i
70     done
71         11  history
72    The user can then recall the whole command all at once instead
73    of just being able to recall one line at a time.
74    */
75 int command_oriented_history = 0;
76
77 /* A nit for picking at history saving.
78    Value of 0 means save all lines parsed by the shell on the history.
79    Value of 1 means save all lines that do not start with a space.
80    Value of 2 means save all lines that do not match the last line saved. */
81 int history_control = 0;
82
83 /* Variables declared in other files used here. */
84 extern int interactive;
85 extern int current_command_line_count;
86 extern int delimiter_depth;
87
88 extern char *history_delimiting_chars ();
89 extern void maybe_add_history ();       /* forward declaration */
90
91 static void bash_add_history ();
92
93 /* Load the history list from the history file. */
94 void
95 load_history ()
96 {
97   char *hf;
98
99   /* Truncate history file for interactive shells which desire it.
100      Note that the history file is automatically truncated to the
101      size of HISTSIZE if the user does not explicitly set the size
102      differently. */
103   set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
104   stupidly_hack_special_variables ("HISTFILESIZE");
105
106   /* Read the history in HISTFILE into the history list. */
107   hf = get_string_value ("HISTFILE");
108
109   if (hf && *hf)
110     {
111       struct stat buf;
112
113       if (stat (hf, &buf) == 0)
114         {
115           read_history (hf);
116           using_history ();
117           history_lines_in_file = where_history ();
118         }
119     }
120 }
121
122 /* Write the existing history out to the history file. */
123 void
124 save_history ()
125 {
126   char *hf = get_string_value ("HISTFILE");
127
128   if (hf && *hf)
129     {
130       struct stat buf;
131
132       if (stat (hf, &buf) == 0)
133         {
134           /* Append only the lines that occurred this session to
135              the history file. */
136           using_history ();
137
138           if (history_lines_this_session < where_history ())
139             append_history (history_lines_this_session, hf);
140           else
141             write_history (hf);
142         }
143     }
144 }
145
146 /* If this is an interactive shell, then append the lines executed
147    this session to the history file. */
148 int
149 maybe_save_shell_history ()
150 {
151   int result = 0;
152
153   if (history_lines_this_session)
154     {
155       char *hf = get_string_value ("HISTFILE");
156
157       if (hf && *hf)
158         {
159           struct stat buf;
160
161           /* If the file doesn't exist, then create it. */
162           if (stat (hf, &buf) == -1)
163             {
164               int file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0666);
165               if (file != -1)
166                 close (file);
167             }
168
169           /* Now actually append the lines if the history hasn't been
170              stifled.  If the history has been stifled, rewrite the
171              history file. */
172           using_history ();
173           if (history_lines_this_session <= where_history ())
174             {
175               result = append_history (history_lines_this_session, hf);
176               history_lines_in_file += history_lines_this_session;
177             }
178           else
179             {
180               result = write_history (hf);
181               history_lines_in_file = history_lines_this_session;
182             }
183           history_lines_this_session = 0;
184         }
185     }
186   return (result);
187 }
188
189 #if defined (HISTORY_REEDITING)
190 /* Tell readline () that we have some text for it to edit. */
191 static void
192 re_edit (text)
193      char *text;
194 {
195 #if defined (READLINE)
196   if (strcmp (bash_input.name, "readline stdin") == 0)
197     bash_re_edit (text);
198 #endif /* READLINE */
199 }
200 #endif /* HISTORY_REEDITING */
201
202 /* Do pre-processing on LINE.  If PRINT_CHANGES is non-zero, then
203    print the results of expanding the line if there were any changes.
204    If there is an error, return NULL, otherwise the expanded line is
205    returned.  If ADDIT is non-zero the line is added to the history
206    list after history expansion.  ADDIT is just a suggestion;
207    REMEMBER_ON_HISTORY can veto, and does.
208    Right now this does history expansion. */
209 char *
210 pre_process_line (line, print_changes, addit)
211      char *line;
212      int print_changes, addit;
213 {
214   char *history_value;
215   char *return_value;
216   int expanded = 0;
217
218   return_value = line;
219
220 #  if defined (BANG_HISTORY)
221   /* History expand the line.  If this results in no errors, then
222      add that line to the history if ADDIT is non-zero. */
223   if (!history_expansion_inhibited && history_expansion)
224     {
225       expanded = history_expand (line, &history_value);
226
227       if (expanded)
228         {
229           if (print_changes)
230             {
231               if (expanded < 0)
232                 internal_error (history_value);
233               else
234                 fprintf (stderr, "%s\n", history_value);
235             }
236
237           /* If there was an error, return NULL. */
238           if (expanded < 0 || expanded == 2)    /* 2 == print only */
239             {
240               free (history_value);
241
242 #    if defined (HISTORY_REEDITING)
243               /* New hack.  We can allow the user to edit the
244                  failed history expansion. */
245               re_edit (line);
246 #    endif /* HISTORY_REEDITING */
247               return ((char *)NULL);
248             }
249         }
250
251       /* Let other expansions know that return_value can be free'ed,
252          and that a line has been added to the history list.  Note
253          that we only add lines that have something in them. */
254       expanded = 1;
255       return_value = history_value;
256     }
257 #  endif /* BANG_HISTORY */
258
259   if (addit && remember_on_history && *return_value)
260     maybe_add_history (return_value);
261
262   if (!expanded)
263     return_value = savestring (line);
264
265   return (return_value);
266 }
267
268 /* Add LINE to the history list depending on the value of HISTORY_CONTROL. */
269 void
270 maybe_add_history (line)
271      char *line;
272 {
273   int h;
274
275   /* Don't use the value of history_control to affect the second
276      and subsequent lines of a multi-line command when
277      command_oriented_history is enabled. */
278   if (command_oriented_history && current_command_line_count > 1)
279     h = 0;
280   else
281     h = history_control;
282
283   switch (h)
284     {
285     case 0:
286       bash_add_history (line);
287       break;
288     case 1:
289       if (*line != ' ')
290         bash_add_history (line);
291       break;
292     case 3:
293       if (*line == ' ')
294         break;
295       /* FALLTHROUGH if case == 3 (`ignoreboth') */
296     case 2:
297       {
298         HIST_ENTRY *temp;
299
300         using_history ();
301         temp = previous_history ();
302
303         if (!temp || (STREQ (temp->line, line) == 0))
304           bash_add_history (line);
305
306         using_history ();
307       }
308       break;
309     }
310 }
311
312 /* Add a line to the history list.
313    The variable COMMAND_ORIENTED_HISTORY controls the style of history
314    remembering;  when non-zero, and LINE is not the first line of a
315    complete parser construct, append LINE to the last history line instead
316    of adding it as a new line. */
317 static void
318 bash_add_history (line)
319      char *line;
320 {
321   int add_it = 1;
322
323   if (command_oriented_history && current_command_line_count > 1)
324     {
325       register int offset;
326       register HIST_ENTRY *current, *old;
327       char *chars_to_add, *new_line;
328
329       chars_to_add = history_delimiting_chars ();
330
331       using_history ();
332
333       current = previous_history ();
334
335       if (current)
336         {
337           /* If the previous line ended with an escaped newline (escaped
338              with backslash, but otherwise unquoted), then remove the quoted
339              newline, since that is what happens when the line is parsed. */
340           int curlen;
341
342           curlen = strlen (current->line);
343
344           if (!delimiter_depth && current->line[curlen - 1] == '\\' &&
345               current->line[curlen - 2] != '\\')
346             {
347               current->line[curlen - 1] = '\0';
348               curlen--;
349               chars_to_add = "";
350             }
351
352           offset = where_history ();
353           new_line = (char *) xmalloc (1
354                                        + curlen
355                                        + strlen (line)
356                                        + strlen (chars_to_add));
357           sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
358           old = replace_history_entry (offset, new_line, current->data);
359           free (new_line);
360
361           if (old)
362             {
363               /* Note that the old data is not freed, since it was simply
364                  copied to the new history entry. */
365               if (old->line)
366                 free (old->line);
367
368               free (old);
369             }
370           add_it = 0;
371         }
372     }
373
374   if (add_it)
375     {
376       add_history (line);
377       history_lines_this_session++;
378     }
379   using_history ();
380 }
381
382 int
383 history_number ()
384 {
385   using_history ();
386   if (get_string_value ("HISTSIZE"))
387     return (history_base + where_history ());
388   else
389     return (1);         /* default to command number 1 */
390 }