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