]> git.ipfire.org Git - thirdparty/bash.git/blob - bashhist.c
Imported from ../bash-2.0.tar.gz.
[thirdparty/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 */