]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/history.def
Imported from ../bash-2.05.tar.gz.
[thirdparty/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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22 $PRODUCES history.c
23
24 $BUILTIN history
25 $FUNCTION history_builtin
26 $DEPENDS_ON HISTORY
27 $SHORT_DOC history [-c] [-d offset] [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 `-d' option deletes
32 the history entry at offset OFFSET. The `-w' option writes out the
33 current history to the history file; `-r' means to read the file and
34 append the contents to the history list instead. `-a' means
35 to append history lines from this session to the history file.
36 Argument `-n' means to read all history lines not already read
37 from the history file and append them to the history list. If
38 FILENAME is given, then that is used as the history file else
39 if $HISTFILE has a value, that is used, else ~/.bash_history.
40 If the -s option is supplied, the non-option ARGs are appended to
41 the history list as a single entry. The -p option means to perform
42 history expansion on each ARG and display the result, without storing
43 anything in the history list.
44 $END
45
46 #include <config.h>
47
48 #if defined (HISTORY)
49 #include "../bashtypes.h"
50 #ifndef _MINIX
51 # include <sys/file.h>
52 #endif
53 #include "posixstat.h"
54 #include "filecntl.h"
55 #include <errno.h>
56 #include <stdio.h>
57 #if defined (HAVE_UNISTD_H)
58 # include <unistd.h>
59 #endif
60
61 #include "../bashansi.h"
62
63 #include "../shell.h"
64 #include "../bashhist.h"
65 #include <readline/history.h>
66 #include "bashgetopt.h"
67 #include "common.h"
68
69 #if !defined (errno)
70 extern int errno;
71 #endif
72
73 static void display_history ();
74 static void push_history ();
75 static int expand_and_print_history ();
76 static int delete_histent ();
77
78 #define AFLAG 0x01
79 #define RFLAG 0x02
80 #define WFLAG 0x04
81 #define NFLAG 0x08
82 #define SFLAG 0x10
83 #define PFLAG 0x20
84 #define CFLAG 0x40
85 #define DFLAG 0x80
86
87 int
88 history_builtin (list)
89 WORD_LIST *list;
90 {
91 int flags, opt, result;
92 char *filename, *delete_arg;
93 long delete_offset;
94
95 flags = 0;
96 reset_internal_getopt ();
97 while ((opt = internal_getopt (list, "acd:npsrw")) != -1)
98 {
99 switch (opt)
100 {
101 case 'a':
102 flags |= AFLAG;
103 break;
104 case 'c':
105 flags |= CFLAG;
106 break;
107 case 'n':
108 flags |= NFLAG;
109 break;
110 case 'r':
111 flags |= RFLAG;
112 break;
113 case 'w':
114 flags |= WFLAG;
115 break;
116 case 's':
117 flags |= SFLAG;
118 break;
119 case 'd':
120 flags |= DFLAG;
121 delete_arg = list_optarg;
122 break;
123 case 'p':
124 #if defined (BANG_HISTORY)
125 flags |= PFLAG;
126 #endif
127 break;
128 default:
129 builtin_usage ();
130 return (EX_USAGE);
131 }
132 }
133 list = loptend;
134
135 opt = flags & (AFLAG|RFLAG|WFLAG|NFLAG);
136 if (opt && opt != AFLAG && opt != RFLAG && opt != WFLAG && opt != NFLAG)
137 {
138 builtin_error ("cannot use more than one of -anrw");
139 return (EXECUTION_FAILURE);
140 }
141
142 /* clear the history, but allow other arguments to add to it again. */
143 if (flags & CFLAG)
144 {
145 clear_history ();
146 if (list == 0)
147 return (EXECUTION_SUCCESS);
148 }
149
150 if (flags & SFLAG)
151 {
152 if (list)
153 push_history (list);
154 return (EXECUTION_SUCCESS);
155 }
156 #if defined (BANG_HISTORY)
157 else if (flags & PFLAG)
158 {
159 if (list)
160 return (expand_and_print_history (list));
161 return (EXECUTION_SUCCESS);
162 }
163 #endif
164 else if (flags & DFLAG)
165 {
166 if (legal_number (delete_arg, &delete_offset) == 0)
167 {
168 builtin_error ("%s: not a valid history position", delete_arg);
169 return (EXECUTION_FAILURE);
170 }
171 opt = delete_offset;
172 if (opt < history_base || opt < 0 || opt > (history_base + history_length))
173 {
174 builtin_error ("%d: not a valid history position", opt);
175 return (EXECUTION_FAILURE);
176 }
177 result = delete_histent (opt - history_base);
178 /* Since remove_history changes history_length, this can happen if
179 we delete the last history entry. */
180 if (where_history () > history_length)
181 history_set_pos (history_length);
182 return (result ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
183 }
184 else if ((flags & (AFLAG|RFLAG|NFLAG|WFLAG|CFLAG)) == 0)
185 {
186 display_history (list);
187 return (EXECUTION_SUCCESS);
188 }
189
190 filename = list ? list->word->word : get_string_value ("HISTFILE");
191 result = EXECUTION_SUCCESS;
192
193 if (flags & AFLAG) /* Append session's history to file. */
194 result = maybe_append_history (filename);
195 else if (flags & WFLAG) /* Write entire history. */
196 result = write_history (filename);
197 else if (flags & RFLAG) /* Read entire file. */
198 result = read_history (filename);
199 else if (flags & NFLAG) /* Read `new' history from file. */
200 {
201 /* Read all of the lines in the file that we haven't already read. */
202 using_history ();
203 result = read_history_range (filename, history_lines_in_file, -1);
204 using_history ();
205 history_lines_in_file = where_history ();
206 }
207
208 return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
209 }
210
211 /* Accessors for HIST_ENTRY lists that are called HLIST. */
212 #define histline(i) (hlist[(i)]->line)
213 #define histdata(i) (hlist[(i)]->data)
214
215 static void
216 display_history (list)
217 WORD_LIST *list;
218 {
219 register int i;
220 int limited, limit;
221 HIST_ENTRY **hlist;
222
223 if (list)
224 {
225 limited = 1;
226 limit = get_numeric_arg (list, 0);
227 }
228 else
229 limited = limit = 0;
230
231 hlist = history_list ();
232
233 if (hlist)
234 {
235 for (i = 0; hlist[i]; i++)
236 ;
237
238 if (limit < 0)
239 limit = -limit;
240
241 if ((limited == 0) || ((i -= limit) < 0))
242 i = 0;
243
244 while (hlist[i])
245 {
246 QUIT;
247 printf ("%5d%c %s\n", i + history_base,
248 histdata(i) ? '*' : ' ',
249 histline(i));
250 i++;
251 }
252 }
253 }
254
255 /* Delete and free the history list entry at offset I. */
256 static int
257 delete_histent (i)
258 int i;
259 {
260 HIST_ENTRY *discard;
261
262 discard = remove_history (i);
263 if (discard)
264 {
265 if (discard->line)
266 free (discard->line);
267 free ((char *) discard);
268 }
269 return 1;
270 }
271
272 static int
273 delete_last_history ()
274 {
275 register int i;
276 HIST_ENTRY **hlist, *histent;
277
278 hlist = history_list ();
279 if (hlist == NULL)
280 return 0;
281
282 for (i = 0; hlist[i]; i++)
283 ;
284 i--;
285
286 /* History_get () takes a parameter that must be offset by history_base. */
287 histent = history_get (history_base + i); /* Don't free this */
288 if (histent == NULL)
289 return 0;
290
291 return (delete_histent (i));
292 }
293
294 /* Remove the last entry in the history list and add each argument in
295 LIST to the history. */
296 static void
297 push_history (list)
298 WORD_LIST *list;
299 {
300 char *s;
301
302 if (hist_last_line_added && delete_last_history () == 0)
303 return;
304 s = string_list (list);
305 maybe_add_history (s); /* Obeys HISTCONTROL setting. */
306 free (s);
307 }
308
309 #if defined (BANG_HISTORY)
310 static int
311 expand_and_print_history (list)
312 WORD_LIST *list;
313 {
314 char *s;
315 int r, result;
316
317 if (hist_last_line_added && delete_last_history () == 0)
318 return EXECUTION_FAILURE;
319 result = EXECUTION_SUCCESS;
320 while (list)
321 {
322 r = history_expand (list->word->word, &s);
323 if (r < 0)
324 {
325 builtin_error ("%s: history expansion failed", list->word->word);
326 result = EXECUTION_FAILURE;
327 }
328 else
329 {
330 fputs (s, stdout);
331 putchar ('\n');
332 }
333 FREE (s);
334 list = list->next;
335 }
336 fflush (stdout);
337 return result;
338 }
339 #endif /* BANG_HISTORY */
340 #endif /* HISTORY */