Imported from ../bash-2.01.1.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 "config.h"
22
23 #if defined (HISTORY)
24
25 #if defined (HAVE_UNISTD_H)
26 #  include <unistd.h>
27 #endif
28
29 #include "bashtypes.h"
30 #include <stdio.h>
31 #include <errno.h>
32 #include "bashansi.h"
33 #include "posixstat.h"
34 #include "filecntl.h"
35
36 #include "shell.h"
37 #include "flags.h"
38 #include "input.h"
39 #include "parser.h"     /* for the struct dstack stuff. */
40 #include "pathexp.h"    /* for the struct ignorevar stuff */
41 #include "builtins/common.h"
42
43 #include <readline/history.h>
44 #include <glob/fnmatch.h>
45
46 #if defined (READLINE)
47 #  include "bashline.h"
48 #endif
49
50 #if !defined (errno)
51 extern int errno;
52 #endif
53
54 extern int glob_pattern_p ();
55
56 static int histignore_item_func ();
57
58 static struct ignorevar histignore =
59 {
60   "HISTIGNORE",
61   (struct ign *)0,
62   0,
63   (char *)0,
64   (Function *)histignore_item_func,
65 };
66
67 #define HIGN_EXPAND 0x01
68
69 /* Declarations of bash history variables. */
70 /* Non-zero means to remember lines typed to the shell on the history
71    list.  This is different than the user-controlled behaviour; this
72    becomes zero when we read lines from a file, for example. */
73 int remember_on_history = 1;
74
75 /* The number of lines that Bash has added to this history session. */
76 int history_lines_this_session;
77
78 /* The number of lines that Bash has read from the history file. */
79 int history_lines_in_file;
80
81 #if defined (BANG_HISTORY)
82 /* Non-zero means do no history expansion on this line, regardless
83    of what history_expansion says. */
84 int history_expansion_inhibited;
85 #endif
86
87 /* By default, every line is saved in the history individually.  I.e.,
88    if the user enters:
89         bash$ for i in a b c
90         > do
91         > echo $i
92         > done
93    Each line will be individually saved in the history.
94         bash$ history
95         10  for i in a b c
96         11  do
97         12  echo $i
98         13  done
99         14  history
100    If the variable command_oriented_history is set, multiple lines
101    which form one command will be saved as one history entry.
102         bash$ for i in a b c
103         > do
104         > echo $i
105         > done
106         bash$ history
107         10  for i in a b c
108     do
109     echo $i
110     done
111         11  history
112    The user can then recall the whole command all at once instead
113    of just being able to recall one line at a time.
114    */
115 int command_oriented_history = 1;
116
117 /* Non-zero means to store newlines in the history list when using
118    command_oriented_history rather than trying to use semicolons. */
119 int literal_history;
120
121 /* Non-zero means to append the history to the history file at shell
122    exit, even if the history has been stifled. */
123 int force_append_history;
124
125 /* A nit for picking at history saving.
126    Value of 0 means save all lines parsed by the shell on the history.
127    Value of 1 means save all lines that do not start with a space.
128    Value of 2 means save all lines that do not match the last line saved. */
129 int history_control;
130
131 /* Set to 1 if the last command was added to the history list successfully
132    as a separate history entry; set to 0 if the line was ignored or added
133    to a previous entry as part of command-oriented-history processing. */
134 int hist_last_line_added;
135
136 #if defined (READLINE)
137 /* If non-zero, and readline is being used, the user is offered the
138    chance to re-edit a failed history expansion. */
139 int history_reediting;
140
141 /* If non-zero, and readline is being used, don't directly execute a
142    line with history substitution.  Reload it into the editing buffer
143    instead and let the user further edit and confirm with a newline. */
144 int hist_verify;
145
146 #endif /* READLINE */
147
148 /* Variables declared in other files used here. */
149 extern int interactive;
150 extern int current_command_line_count;
151
152 extern struct dstack dstack;
153
154 extern char *extract_colon_unit ();
155 extern char *history_delimiting_chars ();
156 extern void maybe_add_history ();       /* forward declaration */
157 extern void bash_add_history ();        /* forward declaration */
158
159 static int history_should_ignore ();
160
161 /* Is the history expansion starting at string[i] one that should not
162    be expanded? */
163 static int
164 bash_history_inhibit_expansion (string, i)
165      char *string;
166      int i;
167 {
168   /* The shell uses ! as a pattern negation character in globbing [...]
169      expressions, so let those pass without expansion. */
170   if (i > 0 && (string[i - 1] == '[') && member (']', string + i + 1))
171     return (1);
172   /* The shell uses ! as the indirect expansion character, so let those
173      expansions pass as well. */
174   else if (i > 1 && string[i - 1] == '{' && string[i - 2] == '$' &&
175              member ('}', string + i + 1))
176     return (1);
177   else
178     return (0);
179 }
180
181 void
182 bash_initialize_history ()
183 {
184   history_quotes_inhibit_expansion = 1;
185   history_search_delimiter_chars = ";&()|<>";
186   history_inhibit_expansion_function = bash_history_inhibit_expansion;
187 }
188
189 void
190 bash_history_reinit (interact)
191      int interact;
192 {
193 #if defined (BANG_HISTORY)
194   history_expansion = interact != 0;
195   history_expansion_inhibited = 1;
196 #endif
197   remember_on_history = interact != 0;
198   history_inhibit_expansion_function = bash_history_inhibit_expansion;
199 }
200
201 void
202 bash_history_disable ()
203 {
204   remember_on_history = 0;
205 #if defined (BANG_HISTORY)
206   history_expansion_inhibited = 1;
207 #endif
208 }
209
210 void
211 bash_history_enable ()
212 {
213   remember_on_history = 1;
214 #if defined (BANG_HISTORY)
215   history_expansion_inhibited = 0;
216 #endif
217   history_inhibit_expansion_function = bash_history_inhibit_expansion;
218   sv_history_control ("HISTCONTROL");
219   sv_histignore ("HISTIGNORE");
220 }
221
222 /* Load the history list from the history file. */
223 void
224 load_history ()
225 {
226   char *hf;
227   struct stat buf;
228
229   /* Truncate history file for interactive shells which desire it.
230      Note that the history file is automatically truncated to the
231      size of HISTSIZE if the user does not explicitly set the size
232      differently. */
233   set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
234   sv_histsize ("HISTFILESIZE");
235
236   /* Read the history in HISTFILE into the history list. */
237   hf = get_string_value ("HISTFILE");
238
239   if (hf && *hf && stat (hf, &buf) == 0)
240     {
241       read_history (hf);
242       using_history ();
243       history_lines_in_file = where_history ();
244     }
245 }
246
247 #ifdef INCLUDE_UNUSED
248 /* Write the existing history out to the history file. */
249 void
250 save_history ()
251 {
252   char *hf;
253   struct stat buf;
254
255   hf = get_string_value ("HISTFILE");
256   if (hf && *hf && stat (hf, &buf) == 0)
257     {
258       /* Append only the lines that occurred this session to
259          the history file. */
260       using_history ();
261
262       if (history_lines_this_session < where_history () || force_append_history)
263         append_history (history_lines_this_session, hf);
264       else
265         write_history (hf);
266
267       sv_histsize ("HISTFILESIZE");
268     }
269 }
270 #endif
271
272 int
273 maybe_append_history (filename)
274      char *filename;
275 {
276   int fd, result;
277   struct stat buf;
278
279   result = EXECUTION_SUCCESS;
280   if (history_lines_this_session && (history_lines_this_session < where_history ()))
281     {
282       /* If the filename was supplied, then create it if necessary. */
283       if (stat (filename, &buf) == -1 && errno == ENOENT)
284         {
285           fd = open (filename, O_WRONLY|O_CREAT, 0666);
286           if (fd < 0)
287             {
288               builtin_error ("%s: cannot create: %s", filename, strerror (errno));
289               return (EXECUTION_FAILURE);
290             }
291           close (fd);
292         }
293       result = append_history (history_lines_this_session, filename);
294       history_lines_in_file += history_lines_this_session;
295       history_lines_this_session = 0;
296     }
297   return (result);
298 }
299
300 /* If this is an interactive shell, then append the lines executed
301    this session to the history file. */
302 int
303 maybe_save_shell_history ()
304 {
305   int result;
306   char *hf;
307   struct stat buf;
308
309   result = 0;
310   if (history_lines_this_session)
311     {
312       hf = get_string_value ("HISTFILE");
313
314       if (hf && *hf)
315         {
316           /* If the file doesn't exist, then create it. */
317           if (stat (hf, &buf) == -1)
318             {
319               int file;
320               file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0666);
321               if (file != -1)
322                 close (file);
323             }
324
325           /* Now actually append the lines if the history hasn't been
326              stifled.  If the history has been stifled, rewrite the
327              history file. */
328           using_history ();
329           if (history_lines_this_session <= where_history () || force_append_history)
330             {
331               result = append_history (history_lines_this_session, hf);
332               history_lines_in_file += history_lines_this_session;
333             }
334           else
335             {
336               result = write_history (hf);
337               history_lines_in_file = history_lines_this_session;
338             }
339           history_lines_this_session = 0;
340
341           sv_histsize ("HISTFILESIZE");
342         }
343     }
344   return (result);
345 }
346
347 #if defined (READLINE)
348 /* Tell readline () that we have some text for it to edit. */
349 static void
350 re_edit (text)
351      char *text;
352 {
353   if (bash_input.type == st_stdin)
354     bash_re_edit (text);
355 }
356 #endif /* READLINE */
357
358 /* Return 1 if this line needs history expansion. */
359 static int
360 history_expansion_p (line)
361      char *line;
362 {
363   register char *s;
364
365   for (s = line; *s; s++)
366     if (*s == history_expansion_char || *s == history_subst_char)
367       return 1;
368   return 0;
369 }
370
371 /* Do pre-processing on LINE.  If PRINT_CHANGES is non-zero, then
372    print the results of expanding the line if there were any changes.
373    If there is an error, return NULL, otherwise the expanded line is
374    returned.  If ADDIT is non-zero the line is added to the history
375    list after history expansion.  ADDIT is just a suggestion;
376    REMEMBER_ON_HISTORY can veto, and does.
377    Right now this does history expansion. */
378 char *
379 pre_process_line (line, print_changes, addit)
380      char *line;
381      int print_changes, addit;
382 {
383   char *history_value;
384   char *return_value;
385   int expanded;
386
387   return_value = line;
388   expanded = 0;
389
390 #  if defined (BANG_HISTORY)
391   /* History expand the line.  If this results in no errors, then
392      add that line to the history if ADDIT is non-zero. */
393   if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
394     {
395       expanded = history_expand (line, &history_value);
396
397       if (expanded)
398         {
399           if (print_changes)
400             {
401               if (expanded < 0)
402                 internal_error (history_value);
403 #if defined (READLINE)
404               else if (hist_verify == 0)
405 #else
406               else
407 #endif
408                 fprintf (stderr, "%s\n", history_value);
409             }
410
411           /* If there was an error, return NULL. */
412           if (expanded < 0 || expanded == 2)    /* 2 == print only */
413             {
414               free (history_value);
415
416 #    if defined (READLINE)
417               /* New hack.  We can allow the user to edit the
418                  failed history expansion. */
419               if (history_reediting && expanded < 0)
420                 re_edit (line);
421 #    endif /* READLINE */
422               return ((char *)NULL);
423             }
424
425 #    if defined (READLINE)
426           if (hist_verify && expanded == 1)
427             {
428               re_edit (history_value);
429               return ((char *)NULL);
430             }
431 #    endif
432         }
433
434       /* Let other expansions know that return_value can be free'ed,
435          and that a line has been added to the history list.  Note
436          that we only add lines that have something in them. */
437       expanded = 1;
438       return_value = history_value;
439     }
440 #  endif /* BANG_HISTORY */
441
442   if (addit && remember_on_history && *return_value)
443     maybe_add_history (return_value);
444
445 #if 0
446   if (expanded == 0)
447     return_value = savestring (line);
448 #endif
449
450   return (return_value);
451 }
452
453 /* Add LINE to the history list depending on the value of HISTORY_CONTROL. */
454 void
455 maybe_add_history (line)
456      char *line;
457 {
458   int should_add;
459   HIST_ENTRY *temp;
460
461   should_add = hist_last_line_added = 0;
462
463   /* Don't use the value of history_control to affect the second
464      and subsequent lines of a multi-line command when
465      command_oriented_history is enabled. */
466   if (command_oriented_history && current_command_line_count > 1)
467     {
468       bash_add_history (line);
469       return;
470     }
471
472   switch (history_control)
473     {
474     case 0:
475       should_add = 1;
476       break;
477     case 1:
478       if (*line != ' ')
479         should_add = 1;
480       break;
481     case 3:
482       if (*line == ' ')
483         break;
484       /* FALLTHROUGH if case == 3 (`ignoreboth') */
485     case 2:
486       using_history ();
487       temp = previous_history ();
488
489       if (temp == 0 || STREQ (temp->line, line) == 0)
490         should_add = 1;
491
492       using_history ();
493       break;
494     }
495
496   if (should_add && history_should_ignore (line) == 0)
497     bash_add_history (line);
498 }
499
500 /* Add a line to the history list.
501    The variable COMMAND_ORIENTED_HISTORY controls the style of history
502    remembering;  when non-zero, and LINE is not the first line of a
503    complete parser construct, append LINE to the last history line instead
504    of adding it as a new line. */
505 void
506 bash_add_history (line)
507      char *line;
508 {
509   int add_it, offset, curlen;
510   HIST_ENTRY *current, *old;
511   char *chars_to_add, *new_line;
512
513   add_it = 1;
514   if (command_oriented_history && current_command_line_count > 1)
515     {
516       chars_to_add = literal_history ? "\n" : history_delimiting_chars ();
517
518       using_history ();
519       current = previous_history ();
520
521       if (current)
522         {
523           /* If the previous line ended with an escaped newline (escaped
524              with backslash, but otherwise unquoted), then remove the quoted
525              newline, since that is what happens when the line is parsed. */
526           curlen = strlen (current->line);
527
528           if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
529               current->line[curlen - 2] != '\\')
530             {
531               current->line[curlen - 1] = '\0';
532               curlen--;
533               chars_to_add = "";
534             }
535
536           new_line = (char *) xmalloc (1
537                                        + curlen
538                                        + strlen (line)
539                                        + strlen (chars_to_add));
540           sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
541           offset = where_history ();
542           old = replace_history_entry (offset, new_line, current->data);
543           free (new_line);
544
545           if (old)
546             {
547               FREE (old->line);
548               free (old);
549             }
550           add_it = 0;
551         }
552     }
553
554   if (add_it)
555     {
556       hist_last_line_added = 1;
557       add_history (line);
558       history_lines_this_session++;
559     }
560   using_history ();
561 }
562
563 int
564 history_number ()
565 {
566   using_history ();
567   return (get_string_value ("HISTSIZE") ? history_base + where_history () : 1);
568 }
569
570 static int
571 should_expand (s)
572      char *s;
573 {
574   char *p;
575
576   for (p = s; p && *p; p++)
577     {
578       if (*p == '\\')
579         p++;
580       else if (*p == '&')
581         return 1;
582     }
583   return 0;
584 }
585
586 static int
587 histignore_item_func (ign)
588      struct ign *ign;
589 {
590   if (should_expand (ign->val))
591     ign->flags |= HIGN_EXPAND;
592   return (0);
593 }
594
595 void
596 setup_history_ignore (varname)
597      char *varname;
598 {
599   setup_ignore_patterns (&histignore);
600 }
601
602 static HIST_ENTRY *
603 last_history_entry ()
604 {
605   HIST_ENTRY *he;
606
607   using_history ();
608   he = previous_history ();
609   using_history ();
610   return he;
611 }
612
613 char *
614 last_history_line ()
615 {
616   HIST_ENTRY *he;
617
618   he = last_history_entry ();
619   if (he == 0)
620     return ((char *)NULL);
621   return he->line;
622 }
623
624 static char *
625 expand_histignore_pattern (pat)
626      char *pat;
627 {
628   HIST_ENTRY *phe;
629   char *ret, *p, *r, *t;
630   int len, rlen, ind, tlen;
631
632   phe = last_history_entry ();
633
634   if (phe == (HIST_ENTRY *)0)
635     return (savestring (pat));
636
637   len = strlen (phe->line);
638   rlen = len + strlen (pat) + 2;
639   ret = xmalloc (rlen);
640
641   for (p = pat, r = ret; p && *p; )
642     {
643       if (*p == '&')
644         {
645           ind = r - ret;
646           if (glob_pattern_p (phe->line) || strchr (phe->line, '\\'))
647             {
648               t = quote_globbing_chars (phe->line);
649               tlen = strlen (t);
650               RESIZE_MALLOCED_BUFFER (ret, ind, tlen, rlen, rlen);
651               r = ret + ind;    /* in case reallocated */
652               strcpy (r, t);
653               r += tlen;
654               free (t);
655             }
656           else
657             {
658               tlen = strlen (phe->line);
659               RESIZE_MALLOCED_BUFFER (ret, ind, tlen, rlen, rlen);
660               r = ret + ind;    /* in case reallocated */
661               strcpy (r, phe->line);
662               r += len;
663             }
664           p++;
665           continue;
666         }
667
668       if (*p == '\\' && p[1] == '&')
669         p++;
670
671       *r++ = *p++;
672     }
673   *r = '\0';
674   return ret;
675 }
676
677 /* Return 1 if we should not put LINE into the history according to the
678    patterns in HISTIGNORE. */
679 static int
680 history_should_ignore (line)
681      char *line;
682 {
683   register int i, match;
684   char *npat;
685
686   if (histignore.num_ignores == 0)
687     return 0;
688
689   for (i = match = 0; i < histignore.num_ignores; i++)
690     {
691       if (histignore.ignores[i].flags & HIGN_EXPAND)
692         npat = expand_histignore_pattern (histignore.ignores[i].val);
693       else
694         npat = histignore.ignores[i].val;
695
696       match = fnmatch (npat, line, 0) != FNM_NOMATCH;
697
698       if (histignore.ignores[i].flags & HIGN_EXPAND)
699         free (npat);
700
701       if (match)
702         break;
703     }
704
705   return match;
706 }
707 #endif /* HISTORY */