Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / builtins / history.def
1 This file is history.def, from which is created history.c.
2 It implements the builtin "history" in Bash.
3
4 Copyright (C) 1987-2009 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash.  If not, see <http://www.gnu.org/licenses/>.
20
21 $PRODUCES history.c
22
23 $BUILTIN history
24 $FUNCTION history_builtin
25 $DEPENDS_ON HISTORY
26 $SHORT_DOC history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]
27 Display or manipulate the history list.
28
29 Display the history list with line numbers, prefixing each modified
30 entry with a `*'.  An argument of N lists only the last N entries.
31
32 Options:
33   -c    clear the history list by deleting all of the entries
34   -d offset     delete the history entry at offset OFFSET.
35
36   -a    append history lines from this session to the history file
37   -n    read all history lines not already read from the history file
38   -r    read the history file and append the contents to the history
39         list
40   -w    write the current history to the history file
41         and append them to the history list
42
43   -p    perform history expansion on each ARG and display the result
44         without storing it in the history list
45   -s    append the ARGs to the history list as a single entry
46
47 If FILENAME is given, it is used as the history file.  Otherwise,
48 if $HISTFILE has a value, that is used, else ~/.bash_history.
49
50 If the $HISTTIMEFORMAT variable is set and not null, its value is used
51 as a format string for strftime(3) to print the time stamp associated
52 with each displayed history entry.  No time stamps are printed otherwise.
53
54 Exit Status:
55 Returns success unless an invalid option is given or an error occurs.
56 $END
57
58 #include <config.h>
59
60 #if defined (HISTORY)
61 #include "../bashtypes.h"
62 #if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
63 #  include <sys/file.h>
64 #endif
65 #include "posixstat.h"
66 #include "filecntl.h"
67 #include <errno.h>
68 #include <stdio.h>
69 #if defined (HAVE_UNISTD_H)
70 #  include <unistd.h>
71 #endif
72
73 #include "../bashansi.h"
74 #include "../bashintl.h"
75
76 #include "../shell.h"
77 #include "../bashhist.h"
78 #include <readline/history.h>
79 #include "bashgetopt.h"
80 #include "common.h"
81
82 #if !defined (errno)
83 extern int errno;
84 #endif
85
86 extern int current_command_line_count;
87 extern int force_append_history;        /* shopt -s histappend */
88
89 static char *histtime __P((HIST_ENTRY *, const char *));
90 static int display_history __P((WORD_LIST *));
91 static void push_history __P((WORD_LIST *));
92 static int expand_and_print_history __P((WORD_LIST *));
93
94 #define AFLAG   0x01
95 #define RFLAG   0x02
96 #define WFLAG   0x04
97 #define NFLAG   0x08
98 #define SFLAG   0x10
99 #define PFLAG   0x20
100 #define CFLAG   0x40
101 #define DFLAG   0x80
102
103 int
104 history_builtin (list)
105      WORD_LIST *list;
106 {
107   int flags, opt, result, old_history_lines, obase;
108   char *filename, *delete_arg;
109   intmax_t delete_offset;
110
111   flags = 0;
112   reset_internal_getopt ();
113   while ((opt = internal_getopt (list, "acd:npsrw")) != -1)
114     {
115       switch (opt)
116         {
117         case 'a':
118           flags |= AFLAG;
119           break;
120         case 'c':
121           flags |= CFLAG;
122           break;
123         case 'n':
124           flags |= NFLAG;
125           break;
126         case 'r':
127           flags |= RFLAG;
128           break;
129         case 'w':
130           flags |= WFLAG;
131           break;
132         case 's':
133           flags |= SFLAG;
134           break;
135         case 'd':
136           flags |= DFLAG;
137           delete_arg = list_optarg;
138           break;
139         case 'p':
140 #if defined (BANG_HISTORY)
141           flags |= PFLAG;
142 #endif
143           break;
144         default:
145           builtin_usage ();
146           return (EX_USAGE);
147         }
148     }
149   list = loptend;
150
151   opt = flags & (AFLAG|RFLAG|WFLAG|NFLAG);
152   if (opt && opt != AFLAG && opt != RFLAG && opt != WFLAG && opt != NFLAG)
153     {
154       builtin_error (_("cannot use more than one of -anrw"));
155       return (EXECUTION_FAILURE);
156     }
157
158   /* clear the history, but allow other arguments to add to it again. */
159   if (flags & CFLAG)
160     {
161       bash_clear_history ();
162       if (list == 0)
163         return (EXECUTION_SUCCESS);
164     }
165
166   if (flags & SFLAG)
167     {
168       if (list)
169         push_history (list);
170       return (EXECUTION_SUCCESS);
171     }
172 #if defined (BANG_HISTORY)
173   else if (flags & PFLAG)
174     {
175       if (list)
176         return (expand_and_print_history (list));
177       return (sh_chkwrite (EXECUTION_SUCCESS));
178     }
179 #endif
180   else if (flags & DFLAG)
181     {
182       if ((legal_number (delete_arg, &delete_offset) == 0)
183           || (delete_offset < history_base)
184           || (delete_offset > (history_base + history_length)))
185         {
186           sh_erange (delete_arg, _("history position"));
187           return (EXECUTION_FAILURE);
188         }
189       opt = delete_offset;
190       result = bash_delete_histent (opt - history_base);
191       /* Since remove_history changes history_length, this can happen if
192          we delete the last history entry. */
193       if (where_history () > history_length)
194         history_set_pos (history_length);
195       return (result ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
196     }
197   else if ((flags & (AFLAG|RFLAG|NFLAG|WFLAG|CFLAG)) == 0)
198     {
199       result = display_history (list);
200       return (sh_chkwrite (result));
201     }
202
203   filename = list ? list->word->word : get_string_value ("HISTFILE");
204   result = EXECUTION_SUCCESS;
205
206   if (flags & AFLAG)            /* Append session's history to file. */
207     result = maybe_append_history (filename);
208   else if (flags & WFLAG)       /* Write entire history. */
209     result = write_history (filename);
210   else if (flags & RFLAG)       /* Read entire file. */
211     result = read_history (filename);
212   else if (flags & NFLAG)       /* Read `new' history from file. */
213     {
214       /* Read all of the lines in the file that we haven't already read. */
215       old_history_lines = history_lines_in_file;
216       obase = history_base;
217
218       using_history ();
219       result = read_history_range (filename, history_lines_in_file, -1);
220       using_history ();
221
222       history_lines_in_file = where_history ();
223
224       /* If we're rewriting the history file at shell exit rather than just
225          appending the lines from this session to it, the question is whether
226          we reset history_lines_this_session to 0, losing any history entries
227          we had before we read the new entries from the history file, or
228          whether we count the new entries we just read from the file as
229          history lines added during this session.
230          Right now, we do the latter.  This will cause these history entries
231          to be written to the history file along with any intermediate entries
232          we add when we do a `history -a', but the alternative is losing
233          them altogether. */
234       if (force_append_history == 0)
235         history_lines_this_session += history_lines_in_file - old_history_lines +
236                                     history_base - obase;
237     }
238
239   return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
240 }
241
242 /* Accessors for HIST_ENTRY lists that are called HLIST. */
243 #define histline(i) (hlist[(i)]->line)
244 #define histdata(i) (hlist[(i)]->data)
245
246 static char *
247 histtime (hlist, histtimefmt)
248      HIST_ENTRY *hlist;
249      const char *histtimefmt;
250 {
251   static char timestr[128];
252   time_t t;
253
254   t = history_get_time (hlist);
255   if (t)
256     strftime (timestr, sizeof (timestr), histtimefmt, localtime (&t));
257   else
258     strcpy (timestr, "??");
259   return timestr;
260 }
261
262 static int
263 display_history (list)
264      WORD_LIST *list;
265 {
266   register int i;
267   intmax_t limit;
268   HIST_ENTRY **hlist;
269   char *histtimefmt, *timestr;
270
271   if (list)
272     {
273       if (get_numeric_arg (list, 0, &limit) == 0)
274         return (EXECUTION_FAILURE);
275
276       if (limit < 0)
277         limit = -limit;
278     }
279   else
280     limit = -1;
281
282   hlist = history_list ();
283
284   if (hlist)
285     {
286       for (i = 0;  hlist[i]; i++)
287         ;
288
289       if (0 <= limit && limit < i)
290         i -= limit;
291       else
292         i = 0;
293
294       histtimefmt = get_string_value ("HISTTIMEFORMAT");
295
296       while (hlist[i])
297         {
298           QUIT;
299
300           timestr = (histtimefmt && *histtimefmt) ? histtime (hlist[i], histtimefmt) : (char *)NULL;
301           printf ("%5d%c %s%s\n", i + history_base,
302                   histdata(i) ? '*' : ' ',
303                   ((timestr && *timestr) ? timestr : ""),
304                   histline(i));
305           i++;
306         }
307     }
308
309   return (EXECUTION_SUCCESS);
310 }
311
312 /* Remove the last entry in the history list and add each argument in
313    LIST to the history. */
314 static void
315 push_history (list)
316      WORD_LIST *list;
317 {
318   char *s;
319
320   /* Delete the last history entry if it was a single entry added to the
321      history list (generally the `history -s' itself), or if `history -s'
322      is being used in a compound command and the compound command was
323      added to the history as a single element (command-oriented history).
324      If you don't want history -s to remove the compound command from the
325      history, change #if 0 to #if 1 below. */
326 #if 0
327   if (hist_last_line_pushed == 0 && hist_last_line_added && bash_delete_last_history () == 0)
328 #else
329   if (hist_last_line_pushed == 0 &&
330         (hist_last_line_added ||
331           (current_command_line_count > 0 && current_command_first_line_saved && command_oriented_history))
332       && bash_delete_last_history () == 0)
333 #endif
334       return;
335
336   s = string_list (list);
337   /* Call check_add_history with FORCE set to 1 to skip the check against
338      current_command_line_count.  If history -s is used in a compound
339      command, the above code will delete the compound command's history
340      entry and this call will add the line to the history as a separate
341      entry.  Without FORCE=1, if current_command_line_count were > 1, the
342      line would be appended to the entry before the just-deleted entry. */
343   check_add_history (s, 1);     /* obeys HISTCONTROL, HISTIGNORE */
344
345   hist_last_line_pushed = 1;    /* XXX */
346   free (s);
347 }
348
349 #if defined (BANG_HISTORY)
350 static int
351 expand_and_print_history (list)
352      WORD_LIST *list;
353 {
354   char *s;
355   int r, result;
356
357   if (hist_last_line_pushed == 0 && hist_last_line_added && bash_delete_last_history () == 0)
358     return EXECUTION_FAILURE;
359   result = EXECUTION_SUCCESS;
360   while (list)
361     {
362       r = history_expand (list->word->word, &s);
363       if (r < 0)
364         {
365           builtin_error (_("%s: history expansion failed"), list->word->word);
366           result = EXECUTION_FAILURE;
367         }
368       else
369         {
370           fputs (s, stdout);
371           putchar ('\n');
372         }
373       FREE (s);
374       list = list->next;
375     }
376   fflush (stdout);
377   return result;
378 }
379 #endif /* BANG_HISTORY */
380 #endif /* HISTORY */