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