b1e3ab391d643f1c2e678a0743ccc6708db5ff80
[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, 1989, 1991 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 it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING.  If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 $PRODUCES history.c
23
24 $BUILTIN history
25 $FUNCTION history_builtin
26 $DEPENDS_ON HISTORY
27 $SHORT_DOC history [-c] [n] or history -awrn [filename] or history -ps arg [arg...]
28 Display the history list with line numbers.  Lines listed with
29 with a `*' have been modified.  Argument of N says to list only
30 the last N lines.  The -c option causes the history list to be
31 cleared by deleting all of the entries.  The `-w' option writes out the
32 current history to the history file;  `-r' means to read the file and
33 append the contents to the history list instead.  `-a' means
34 to append history lines from this session to the history file.
35 Argument `-n' means to read all history lines not already read
36 from the history file and append them to the history list.  If
37 FILENAME is given, then that is used as the history file else
38 if $HISTFILE has a value, that is used, else ~/.bash_history.
39 If the -s option is supplied, the non-option ARGs are appended to
40 the history list as a single entry.  The -p option means to perform
41 history expansion on each ARG and display the result, without storing
42 anything in the history list.
43 $END
44
45 #include <config.h>
46
47 #if defined (HISTORY)
48 #include "../bashtypes.h"
49 #include <sys/file.h>
50 #include "../posixstat.h"
51 #include "../filecntl.h"
52 #include <errno.h>
53 #include <stdio.h>
54 #if defined (HAVE_UNISTD_H)
55 #  include <unistd.h>
56 #endif
57
58 #include "../bashansi.h"
59
60 #include "../shell.h"
61 #include "../bashhist.h"
62 #include <readline/history.h>
63 #include "bashgetopt.h"
64 #include "common.h"
65
66 #if !defined (errno)
67 extern int errno;
68 #endif
69
70 static void display_history ();
71 static void push_history ();
72 static int expand_and_print_history ();
73
74 #define AFLAG   0x01
75 #define RFLAG   0x02
76 #define WFLAG   0x04
77 #define NFLAG   0x08
78 #define SFLAG   0x10
79 #define PFLAG   0x20
80 #define CFLAG   0x40
81
82 int
83 history_builtin (list)
84      WORD_LIST *list;
85 {
86   int flags, opt, result;
87   char *filename;
88
89   flags = 0;
90   reset_internal_getopt ();
91   while ((opt = internal_getopt (list, "acnpsrw")) != -1)
92     {
93       switch (opt)
94         {
95         case 'a':
96           flags |= AFLAG;
97           break;
98         case 'c':
99           flags |= CFLAG;
100           break;
101         case 'n':
102           flags |= NFLAG;
103           break;
104         case 'r':
105           flags |= RFLAG;
106           break;
107         case 'w':
108           flags |= WFLAG;
109           break;
110         case 's':
111           flags |= SFLAG;
112           break;
113         case 'p':
114 #if defined (BANG_HISTORY)
115           flags |= PFLAG;
116 #endif
117           break;
118         default:
119           builtin_usage ();
120           return (EX_USAGE);
121         }
122     }
123   list = loptend;
124
125   opt = flags & (AFLAG|RFLAG|WFLAG|NFLAG);
126   if (opt && opt != AFLAG && opt != RFLAG && opt != WFLAG && opt != NFLAG)
127     {
128       builtin_error ("cannot use more than one of -anrw");
129       return (EXECUTION_FAILURE);
130     }
131
132   /* clear the history, but allow other arguments to add to it again. */
133   if (flags & CFLAG)
134     {
135       clear_history ();
136       if (list == 0)
137         return (EXECUTION_SUCCESS);
138     }
139
140   if (flags & SFLAG)
141     {
142       if (list)
143         push_history (list);
144       return (EXECUTION_SUCCESS);
145     }
146 #if defined (BANG_HISTORY)
147   else if (flags & PFLAG)
148     {
149       if (list)
150         return (expand_and_print_history (list));
151       return (EXECUTION_SUCCESS);
152     }
153 #endif
154   else if ((flags & (AFLAG|RFLAG|NFLAG|WFLAG|CFLAG)) == 0)
155     {
156       display_history (list);
157       return (EXECUTION_SUCCESS);
158     }
159
160   filename = list ? list->word->word : get_string_value ("HISTFILE");
161   result = EXECUTION_SUCCESS;
162
163   if (flags & AFLAG)            /* Append session's history to file. */
164     result = maybe_append_history (filename);
165   else if (flags & WFLAG)       /* Write entire history. */
166     result = write_history (filename);
167   else if (flags & RFLAG)       /* Read entire file. */
168     result = read_history (filename);
169   else if (flags & NFLAG)       /* Read `new' history from file. */
170     {
171       /* Read all of the lines in the file that we haven't already read. */
172       using_history ();
173       result = read_history_range (filename, history_lines_in_file, -1);
174       using_history ();
175       history_lines_in_file = where_history ();
176     }
177
178   return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
179 }
180
181 /* Accessors for HIST_ENTRY lists that are called HLIST. */
182 #define histline(i) (hlist[(i)]->line)
183 #define histdata(i) (hlist[(i)]->data)
184
185 static void
186 display_history (list)
187      WORD_LIST *list;
188 {
189   register int i;
190   int limited, limit;
191   HIST_ENTRY **hlist;
192
193   if (list)
194     {
195       limited = 1;
196       limit = get_numeric_arg (list, 0);
197     }
198   else
199     limited = limit = 0;
200
201   hlist = history_list ();
202
203   if (hlist)
204     {
205       for (i = 0;  hlist[i]; i++)
206         ;
207
208       if (limit < 0)
209         limit = -limit;
210
211       if ((limited == 0)  || ((i -= limit) < 0))
212         i = 0;
213
214       while (hlist[i])
215         {
216           QUIT;
217           printf ("%5d%c %s\n", i + history_base,
218                   histdata(i) ? '*' : ' ',
219                   histline(i));
220           i++;
221         }
222     }
223 }
224
225 static int
226 delete_last_history ()
227 {
228   register int i;
229   HIST_ENTRY **hlist, *histent, *discard;
230
231   hlist = history_list ();
232   if (hlist == NULL)
233     return 0;
234
235   for (i = 0; hlist[i]; i++)
236     ;
237   i--;
238
239   /* History_get () takes a parameter that must be offset by history_base. */
240   histent = history_get (history_base + i);     /* Don't free this */
241   if (histent == NULL)
242     return 0;
243
244   discard = remove_history (i);
245   if (discard)
246     {
247       if (discard->line)
248         free (discard->line);
249       free ((char *) discard);
250     }
251   return (1);
252 }
253
254 /* Remove the last entry in the history list and add each argument in
255    LIST to the history. */
256 static void
257 push_history (list)
258      WORD_LIST *list;
259 {
260   char *s;
261
262   if (hist_last_line_added && delete_last_history () == 0)
263     return;
264   s = string_list (list);
265   maybe_add_history (s);        /* Obeys HISTCONTROL setting. */
266   free (s);
267 }
268
269 #if defined (BANG_HISTORY)
270 static int
271 expand_and_print_history (list)
272      WORD_LIST *list;
273 {
274   char *s;
275   int r, result;
276
277   if (hist_last_line_added && delete_last_history () == 0)
278     return EXECUTION_FAILURE;
279   result = EXECUTION_SUCCESS;
280   while (list)
281     {
282       r = history_expand (list->word->word, &s);
283       if (r < 0)
284         {
285           builtin_error ("%s: history expansion failed", list->word->word);
286           result = EXECUTION_FAILURE;
287         }
288       else
289         {
290           fputs (s, stdout);
291           putchar ('\n');
292         }
293       FREE (s);
294       list = list->next;
295     }
296   fflush (stdout);
297   return result;
298 }
299 #endif /* BANG_HISTORY */
300 #endif /* HISTORY */