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