source: vendor/bash/3.1-p17/bashhist.c@ 3276

Last change on this file since 3276 was 3276, checked in by bird, 18 years ago

Backed out bash-3.1-gentoo.patch, bash-3.1-fix-dash-login-shell.patch and bash-3.1-bash-logger.patch (gentoo patches).

  • Property svn:eol-style set to native
File size: 20.6 KB
Line 
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"
55extern int rl_done, rl_dispatching; /* should really include readline.h */
56#endif
57
58#if !defined (errno)
59extern int errno;
60#endif
61
62static int histignore_item_func __P((struct ign *));
63static int check_history_control __P((char *));
64static void hc_erasedups __P((char *));
65static void really_add_history __P((char *));
66
67static 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. */
82int 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. */
88int history_lines_this_session;
89
90/* The number of lines that Bash has read from the history file. */
91int 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. */
96int 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 */
129int 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. */
134int 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. */
138int 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. */
142int 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. */
152int 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. */
157int hist_last_line_added;
158
159/* Set to 1 if builtins/history.def:push_history added the last history
160 entry. */
161int 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. */
166int 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. */
171int hist_verify;
172
173#endif /* READLINE */
174
175/* Non-zero means to not save function definitions in the history list. */
176int dont_save_function_defs;
177
178/* Variables declared in other files used here. */
179extern int current_command_line_count;
180
181extern struct dstack dstack;
182
183static int bash_history_inhibit_expansion __P((char *, int));
184#if defined (READLINE)
185static void re_edit __P((char *));
186#endif
187static int history_expansion_p __P((char *));
188static int shell_comment __P((char *));
189static int should_expand __P((char *));
190static HIST_ENTRY *last_history_entry __P((void));
191static char *expand_histignore_pattern __P((char *));
192static int history_should_ignore __P((char *));
193
194/* Is the history expansion starting at string[i] one that should not
195 be expanded? */
196static int
197bash_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
218void
219bash_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
229void
230bash_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
241void
242bash_history_disable ()
243{
244 remember_on_history = 0;
245#if defined (BANG_HISTORY)
246 history_expansion_inhibited = 1;
247#endif
248}
249
250void
251bash_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. */
263void
264load_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 ("HISTFILESIZE", get_string_value ("HISTSIZE"));
274 sv_histsize ("HISTFILESIZE");
275
276 /* Read the history in HISTFILE into the history list. */
277 hf = get_string_value ("HISTFILE");
278
279 if (hf && *hf && stat (hf, &buf) == 0)
280 {
281 read_history (hf);
282 using_history ();
283 history_lines_in_file = where_history ();
284 }
285}
286
287#ifdef INCLUDE_UNUSED
288/* Write the existing history out to the history file. */
289void
290save_history ()
291{
292 char *hf;
293 struct stat buf;
294
295 hf = get_string_value ("HISTFILE");
296 if (hf && *hf && stat (hf, &buf) == 0)
297 {
298 /* Append only the lines that occurred this session to
299 the history file. */
300 using_history ();
301
302 if (history_lines_this_session < where_history () || force_append_history)
303 append_history (history_lines_this_session, hf);
304 else
305 write_history (hf);
306
307 sv_histsize ("HISTFILESIZE");
308 }
309}
310#endif
311
312int
313maybe_append_history (filename)
314 char *filename;
315{
316 int fd, result;
317 struct stat buf;
318
319 result = EXECUTION_SUCCESS;
320 if (history_lines_this_session && (history_lines_this_session < where_history ()))
321 {
322 /* If the filename was supplied, then create it if necessary. */
323 if (stat (filename, &buf) == -1 && errno == ENOENT)
324 {
325 fd = open (filename, O_WRONLY|O_CREAT, 0600);
326 if (fd < 0)
327 {
328 builtin_error (_("%s: cannot create: %s"), filename, strerror (errno));
329 return (EXECUTION_FAILURE);
330 }
331 close (fd);
332 }
333 result = append_history (history_lines_this_session, filename);
334 history_lines_in_file += history_lines_this_session;
335 history_lines_this_session = 0;
336 }
337 return (result);
338}
339
340/* If this is an interactive shell, then append the lines executed
341 this session to the history file. */
342int
343maybe_save_shell_history ()
344{
345 int result;
346 char *hf;
347 struct stat buf;
348
349 result = 0;
350 if (history_lines_this_session)
351 {
352 hf = get_string_value ("HISTFILE");
353
354 if (hf && *hf)
355 {
356 /* If the file doesn't exist, then create it. */
357 if (stat (hf, &buf) == -1)
358 {
359 int file;
360 file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0600);
361 if (file != -1)
362 close (file);
363 }
364
365 /* Now actually append the lines if the history hasn't been
366 stifled. If the history has been stifled, rewrite the
367 history file. */
368 using_history ();
369 if (history_lines_this_session <= where_history () || force_append_history)
370 {
371 result = append_history (history_lines_this_session, hf);
372 history_lines_in_file += history_lines_this_session;
373 }
374 else
375 {
376 result = write_history (hf);
377 history_lines_in_file = history_lines_this_session;
378 }
379 history_lines_this_session = 0;
380
381 sv_histsize ("HISTFILESIZE");
382 }
383 }
384 return (result);
385}
386
387#if defined (READLINE)
388/* Tell readline () that we have some text for it to edit. */
389static void
390re_edit (text)
391 char *text;
392{
393 if (bash_input.type == st_stdin)
394 bash_re_edit (text);
395}
396#endif /* READLINE */
397
398/* Return 1 if this line needs history expansion. */
399static int
400history_expansion_p (line)
401 char *line;
402{
403 register char *s;
404
405 for (s = line; *s; s++)
406 if (*s == history_expansion_char || *s == history_subst_char)
407 return 1;
408 return 0;
409}
410
411/* Do pre-processing on LINE. If PRINT_CHANGES is non-zero, then
412 print the results of expanding the line if there were any changes.
413 If there is an error, return NULL, otherwise the expanded line is
414 returned. If ADDIT is non-zero the line is added to the history
415 list after history expansion. ADDIT is just a suggestion;
416 REMEMBER_ON_HISTORY can veto, and does.
417 Right now this does history expansion. */
418char *
419pre_process_line (line, print_changes, addit)
420 char *line;
421 int print_changes, addit;
422{
423 char *history_value;
424 char *return_value;
425 int expanded;
426
427 return_value = line;
428 expanded = 0;
429
430# if defined (BANG_HISTORY)
431 /* History expand the line. If this results in no errors, then
432 add that line to the history if ADDIT is non-zero. */
433 if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
434 {
435 expanded = history_expand (line, &history_value);
436
437 if (expanded)
438 {
439 if (print_changes)
440 {
441 if (expanded < 0)
442 internal_error ("%s", history_value);
443#if defined (READLINE)
444 else if (hist_verify == 0 || expanded == 2)
445#else
446 else
447#endif
448 fprintf (stderr, "%s\n", history_value);
449 }
450
451 /* If there was an error, return NULL. */
452 if (expanded < 0 || expanded == 2) /* 2 == print only */
453 {
454# if defined (READLINE)
455 if (expanded == 2 && rl_dispatching == 0 && *history_value)
456# else
457 if (expanded == 2 && *history_value)
458# endif /* !READLINE */
459 maybe_add_history (history_value);
460
461 free (history_value);
462
463# if defined (READLINE)
464 /* New hack. We can allow the user to edit the
465 failed history expansion. */
466 if (history_reediting && expanded < 0 && rl_done)
467 re_edit (line);
468# endif /* READLINE */
469 return ((char *)NULL);
470 }
471
472# if defined (READLINE)
473 if (hist_verify && expanded == 1)
474 {
475 re_edit (history_value);
476 return ((char *)NULL);
477 }
478# endif
479 }
480
481 /* Let other expansions know that return_value can be free'ed,
482 and that a line has been added to the history list. Note
483 that we only add lines that have something in them. */
484 expanded = 1;
485 return_value = history_value;
486 }
487# endif /* BANG_HISTORY */
488
489 if (addit && remember_on_history && *return_value)
490 maybe_add_history (return_value);
491
492#if 0
493 if (expanded == 0)
494 return_value = savestring (line);
495#endif
496
497 return (return_value);
498}
499
500/* Return 1 if the first non-whitespace character in LINE is a `#', indicating
501 * that the line is a shell comment. */
502static int
503shell_comment (line)
504 char *line;
505{
506 char *p;
507
508 for (p = line; p && *p && whitespace (*p); p++)
509 ;
510 return (p && *p == '#');
511}
512
513#ifdef INCLUDE_UNUSED
514/* Remove shell comments from LINE. A `#' and anything after it is a comment.
515 This isn't really useful yet, since it doesn't handle quoting. */
516static char *
517filter_comments (line)
518 char *line;
519{
520 char *p;
521
522 for (p = line; p && *p && *p != '#'; p++)
523 ;
524 if (p && *p == '#')
525 *p = '\0';
526 return (line);
527}
528#endif
529
530/* Check LINE against what HISTCONTROL says to do. Returns 1 if the line
531 should be saved; 0 if it should be discarded. */
532static int
533check_history_control (line)
534 char *line;
535{
536 HIST_ENTRY *temp;
537 int r;
538
539 if (history_control == 0)
540 return 1;
541
542 /* ignorespace or ignoreboth */
543 if ((history_control & HC_IGNSPACE) && *line == ' ')
544 return 0;
545
546 /* ignoredups or ignoreboth */
547 if (history_control & HC_IGNDUPS)
548 {
549 using_history ();
550 temp = previous_history ();
551
552 r = (temp == 0 || STREQ (temp->line, line) == 0);
553
554 using_history ();
555
556 if (r == 0)
557 return r;
558 }
559
560 return 1;
561}
562
563/* Remove all entries matching LINE from the history list. Triggered when
564 HISTCONTROL includes `erasedups'. */
565static void
566hc_erasedups (line)
567 char *line;
568{
569 HIST_ENTRY *temp;
570 int r;
571
572 using_history ();
573 while (temp = previous_history ())
574 {
575 if (STREQ (temp->line, line))
576 {
577 r = where_history ();
578 remove_history (r);
579 }
580 }
581 using_history ();
582}
583
584/* Add LINE to the history list, handling possibly multi-line compound
585 commands. We note whether or not we save the first line of each command
586 (which is usually the entire command and history entry), and don't add
587 the second and subsequent lines of a multi-line compound command if we
588 didn't save the first line. We don't usually save shell comment lines in
589 compound commands in the history, because they could have the effect of
590 commenting out the rest of the command when the entire command is saved as
591 a single history entry (when COMMAND_ORIENTED_HISTORY is enabled). If
592 LITERAL_HISTORY is set, we're saving lines in the history with embedded
593 newlines, so it's OK to save comment lines. We also make sure to save
594 multiple-line quoted strings or other constructs. */
595void
596maybe_add_history (line)
597 char *line;
598{
599 hist_last_line_added = 0;
600
601 /* Don't use the value of history_control to affect the second
602 and subsequent lines of a multi-line command (old code did
603 this only when command_oriented_history is enabled). */
604 if (current_command_line_count > 1)
605 {
606 if (current_command_first_line_saved &&
607 (literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
608 bash_add_history (line);
609 return;
610 }
611
612 /* This is the first line of a (possible multi-line) command. Note whether
613 or not we should save the first line and remember it. */
614 current_command_first_line_saved = check_add_history (line, 0);
615}
616
617/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the
618 history if it's OK. Used by `history -s' as well as maybe_add_history().
619 Returns 1 if the line was saved in the history, 0 otherwise. */
620int
621check_add_history (line, force)
622 char *line;
623 int force;
624{
625 if (check_history_control (line) && history_should_ignore (line) == 0)
626 {
627 /* We're committed to saving the line. If the user has requested it,
628 remove other matching lines from the history. */
629 if (history_control & HC_ERASEDUPS)
630 hc_erasedups (line);
631
632 if (force)
633 {
634 really_add_history (line);
635 using_history ();
636 }
637 else
638 bash_add_history (line);
639 return 1;
640 }
641 return 0;
642}
643
644/* Add a line to the history list.
645 The variable COMMAND_ORIENTED_HISTORY controls the style of history
646 remembering; when non-zero, and LINE is not the first line of a
647 complete parser construct, append LINE to the last history line instead
648 of adding it as a new line. */
649void
650bash_add_history (line)
651 char *line;
652{
653 int add_it, offset, curlen;
654 HIST_ENTRY *current, *old;
655 char *chars_to_add, *new_line;
656
657 add_it = 1;
658 if (command_oriented_history && current_command_line_count > 1)
659 {
660 chars_to_add = literal_history ? "\n" : history_delimiting_chars ();
661
662 using_history ();
663 current = previous_history ();
664
665 if (current)
666 {
667 /* If the previous line ended with an escaped newline (escaped
668 with backslash, but otherwise unquoted), then remove the quoted
669 newline, since that is what happens when the line is parsed. */
670 curlen = strlen (current->line);
671
672 if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
673 current->line[curlen - 2] != '\\')
674 {
675 current->line[curlen - 1] = '\0';
676 curlen--;
677 chars_to_add = "";
678 }
679
680 new_line = (char *)xmalloc (1
681 + curlen
682 + strlen (line)
683 + strlen (chars_to_add));
684 sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
685 offset = where_history ();
686 old = replace_history_entry (offset, new_line, current->data);
687 free (new_line);
688
689 if (old)
690 free_history_entry (old);
691
692 add_it = 0;
693 }
694 }
695
696 if (add_it)
697 really_add_history (line);
698
699 using_history ();
700}
701
702static void
703really_add_history (line)
704 char *line;
705{
706 hist_last_line_added = 1;
707 hist_last_line_pushed = 0;
708 add_history (line);
709 history_lines_this_session++;
710}
711
712int
713history_number ()
714{
715 using_history ();
716 return (remember_on_history ? history_base + where_history () : 1);
717}
718
719static int
720should_expand (s)
721 char *s;
722{
723 char *p;
724
725 for (p = s; p && *p; p++)
726 {
727 if (*p == '\\')
728 p++;
729 else if (*p == '&')
730 return 1;
731 }
732 return 0;
733}
734
735static int
736histignore_item_func (ign)
737 struct ign *ign;
738{
739 if (should_expand (ign->val))
740 ign->flags |= HIGN_EXPAND;
741 return (0);
742}
743
744void
745setup_history_ignore (varname)
746 char *varname;
747{
748 setup_ignore_patterns (&histignore);
749}
750
751static HIST_ENTRY *
752last_history_entry ()
753{
754 HIST_ENTRY *he;
755
756 using_history ();
757 he = previous_history ();
758 using_history ();
759 return he;
760}
761
762char *
763last_history_line ()
764{
765 HIST_ENTRY *he;
766
767 he = last_history_entry ();
768 if (he == 0)
769 return ((char *)NULL);
770 return he->line;
771}
772
773static char *
774expand_histignore_pattern (pat)
775 char *pat;
776{
777 HIST_ENTRY *phe;
778 char *ret;
779
780 phe = last_history_entry ();
781
782 if (phe == (HIST_ENTRY *)0)
783 return (savestring (pat));
784
785 ret = strcreplace (pat, '&', phe->line, 1);
786
787 return ret;
788}
789
790/* Return 1 if we should not put LINE into the history according to the
791 patterns in HISTIGNORE. */
792static int
793history_should_ignore (line)
794 char *line;
795{
796 register int i, match;
797 char *npat;
798
799 if (histignore.num_ignores == 0)
800 return 0;
801
802 for (i = match = 0; i < histignore.num_ignores; i++)
803 {
804 if (histignore.ignores[i].flags & HIGN_EXPAND)
805 npat = expand_histignore_pattern (histignore.ignores[i].val);
806 else
807 npat = histignore.ignores[i].val;
808
809 match = strmatch (npat, line, FNMATCH_EXTFLAG) != FNM_NOMATCH;
810
811 if (histignore.ignores[i].flags & HIGN_EXPAND)
812 free (npat);
813
814 if (match)
815 break;
816 }
817
818 return match;
819}
820#endif /* HISTORY */
Note: See TracBrowser for help on using the repository browser.