source: trunk/essentials/app-shells/bash/bashhist.c@ 3247

Last change on this file since 3247 was 3233, checked in by bird, 19 years ago

Applied bash-3.1-bash-logger.patch (gentoo)

  • 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 */