blob: 182082684c6ac9c9606b7634d0a836398e911609 [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001This file is fc.def, from which is created fc.c.
2It implements the builtin "fc" in Bash.
3
Chet Rameyac50fba2014-02-26 09:36:43 -05004Copyright (C) 1987-2011 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
Jari Aalto31859422009-01-12 13:36:28 +00008Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
Jari Aalto726f6381996-08-26 18:22:31 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
Jari Aalto726f6381996-08-26 18:22:31 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
Jari Aalto726f6381996-08-26 18:22:31 +000020
21$PRODUCES fc.c
22
23$BUILTIN fc
24$FUNCTION fc_builtin
25$DEPENDS_ON HISTORY
Jari Aalto31859422009-01-12 13:36:28 +000026$SHORT_DOC fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]
27Display or execute commands from the history list.
28
Jari Aaltob72432f1999-02-19 17:11:39 +000029fc is used to list or edit and re-execute commands from the history list.
Jari Aalto726f6381996-08-26 18:22:31 +000030FIRST and LAST can be numbers specifying the range, or FIRST can be a
31string, which means the most recent command beginning with that
32string.
33
Jari Aalto31859422009-01-12 13:36:28 +000034Options:
35 -e ENAME select which editor to use. Default is FCEDIT, then EDITOR,
36 then vi
37 -l list lines instead of editing
38 -n omit line numbers when listing
39 -r reverse the order of the lines (newest listed first)
Jari Aalto726f6381996-08-26 18:22:31 +000040
Jari Aalto31859422009-01-12 13:36:28 +000041With the `fc -s [pat=rep ...] [command]' format, COMMAND is
Jari Aalto726f6381996-08-26 18:22:31 +000042re-executed after the substitution OLD=NEW is performed.
43
44A useful alias to use with this is r='fc -s', so that typing `r cc'
45runs the last command beginning with `cc' and typing `r' re-executes
46the last command.
Jari Aalto31859422009-01-12 13:36:28 +000047
48Exit Status:
49Returns success or status of executed command; non-zero if an error occurs.
Jari Aalto726f6381996-08-26 18:22:31 +000050$END
51
Jari Aaltoccc6cda1996-12-23 17:02:34 +000052#include <config.h>
53
Jari Aalto726f6381996-08-26 18:22:31 +000054#if defined (HISTORY)
Chet Rameyac50fba2014-02-26 09:36:43 -050055#if defined (HAVE_SYS_PARAM_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000056# include <sys/param.h>
57#endif
Jari Aaltod166f041997-06-05 14:59:13 +000058#include "../bashtypes.h"
Jari Aaltobb706242000-03-17 21:46:59 +000059#include "posixstat.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000060#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000061# include <sys/file.h>
62#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000063
64#if defined (HAVE_UNISTD_H)
65# include <unistd.h>
66#endif
67
68#include <stdio.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000069#include <chartypes.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000070
71#include "../bashansi.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000072#include "../bashintl.h"
Jari Aalto726f6381996-08-26 18:22:31 +000073#include <errno.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000074
75#include "../shell.h"
Jari Aalto726f6381996-08-26 18:22:31 +000076#include "../builtins.h"
77#include "../flags.h"
Jari Aalto726f6381996-08-26 18:22:31 +000078#include "../bashhist.h"
Jari Aaltobb706242000-03-17 21:46:59 +000079#include "maxpath.h"
Jari Aalto726f6381996-08-26 18:22:31 +000080#include <readline/history.h>
81#include "bashgetopt.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000082#include "common.h"
Jari Aalto726f6381996-08-26 18:22:31 +000083
Jari Aalto726f6381996-08-26 18:22:31 +000084#if !defined (errno)
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +010085#include <errno.h>
Jari Aalto726f6381996-08-26 18:22:31 +000086#endif /* !errno */
87
Chet Rameyac50fba2014-02-26 09:36:43 -050088extern int current_command_line_count;
Jari Aaltod166f041997-06-05 14:59:13 +000089extern int literal_history;
Jari Aalto95732b42005-12-07 14:08:12 +000090extern int posixly_correct;
Chet Ramey89a92862011-11-21 20:49:12 -050091extern int subshell_environment, interactive_shell;
Jari Aalto726f6381996-08-26 18:22:31 +000092
Jari Aaltof73dda02001-11-13 17:56:06 +000093extern int unlink __P((const char *));
Jari Aalto726f6381996-08-26 18:22:31 +000094
Jari Aalto28ef6c32001-04-06 19:14:31 +000095extern FILE *sh_mktmpfp __P((char *, int, char **));
Jari Aaltod166f041997-06-05 14:59:13 +000096
Jari Aalto726f6381996-08-26 18:22:31 +000097/* **************************************************************** */
98/* */
99/* The K*rn shell style fc command (Fix Command) */
100/* */
101/* **************************************************************** */
102
103/* fc builtin command (fix command) for Bash for those who
104 like K*rn-style history better than csh-style.
105
106 fc [-e ename] [-nlr] [first] [last]
107
108 FIRST and LAST can be numbers specifying the range, or FIRST can be
109 a string, which means the most recent command beginning with that
110 string.
111
112 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
113 then the editor which corresponds to the current readline editing
114 mode, then vi.
115
116 -l means list lines instead of editing.
117 -n means no line numbers listed.
118 -r means reverse the order of the lines (making it newest listed first).
119
120 fc -e - [pat=rep ...] [command]
121 fc -s [pat=rep ...] [command]
122
123 Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
124*/
125
Jari Aalto726f6381996-08-26 18:22:31 +0000126/* Data structure describing a list of global replacements to perform. */
127typedef struct repl {
128 struct repl *next;
129 char *pat;
130 char *rep;
131} REPL;
132
Jari Aalto726f6381996-08-26 18:22:31 +0000133/* Accessors for HIST_ENTRY lists that are called HLIST. */
134#define histline(i) (hlist[(i)]->line)
135#define histdata(i) (hlist[(i)]->data)
136
137#define FREE_RLIST() \
138 do { \
139 for (rl = rlist; rl; ) { \
140 REPL *r; \
141 r = rl->next; \
142 if (rl->pat) \
143 free (rl->pat); \
144 if (rl->rep) \
145 free (rl->rep); \
146 free (rl); \
147 rl = r; \
148 } \
149 } while (0)
150
Jari Aaltof73dda02001-11-13 17:56:06 +0000151static char *fc_dosubs __P((char *, REPL *));
152static char *fc_gethist __P((char *, HIST_ENTRY **));
153static int fc_gethnum __P((char *, HIST_ENTRY **));
154static int fc_number __P((WORD_LIST *));
155static void fc_replhist __P((char *));
156#ifdef INCLUDE_UNUSED
157static char *fc_readline __P((FILE *));
158static void fc_addhist __P((char *));
159#endif
160
Jari Aalto726f6381996-08-26 18:22:31 +0000161/* String to execute on a file that we want to edit. */
162#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
Jari Aalto95732b42005-12-07 14:08:12 +0000163#if defined (STRICT_POSIX)
164# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
165#else
166# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
167#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000168
169int
170fc_builtin (list)
171 WORD_LIST *list;
172{
173 register int i;
174 register char *sep;
175 int numbering, reverse, listing, execute;
Chet Rameyac50fba2014-02-26 09:36:43 -0500176 int histbeg, histend, last_hist, retval, opt, rh, real_last;
Jari Aalto726f6381996-08-26 18:22:31 +0000177 FILE *stream;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000178 REPL *rlist, *rl;
Jari Aalto95732b42005-12-07 14:08:12 +0000179 char *ename, *command, *newcom, *fcedit;
Jari Aalto726f6381996-08-26 18:22:31 +0000180 HIST_ENTRY **hlist;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000181 char *fn;
Jari Aalto726f6381996-08-26 18:22:31 +0000182
183 numbering = 1;
184 reverse = listing = execute = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000185 ename = (char *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +0000186
187 /* Parse out the options and set which of the two forms we're in. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000188 reset_internal_getopt ();
189 lcurrent = list; /* XXX */
190 while (fc_number (loptend = lcurrent) == 0 &&
191 (opt = internal_getopt (list, ":e:lnrs")) != -1)
Jari Aalto726f6381996-08-26 18:22:31 +0000192 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000193 switch (opt)
Jari Aalto726f6381996-08-26 18:22:31 +0000194 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000195 case 'n':
196 numbering = 0;
197 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000198
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000199 case 'l':
200 listing = 1;
201 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000202
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000203 case 'r':
204 reverse = 1;
205 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000206
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000207 case 's':
208 execute = 1;
209 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000210
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000211 case 'e':
212 ename = list_optarg;
213 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000214
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000215 default:
216 builtin_usage ();
217 return (EX_USAGE);
Jari Aalto726f6381996-08-26 18:22:31 +0000218 }
Jari Aalto726f6381996-08-26 18:22:31 +0000219 }
220
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000221 list = loptend;
222
Jari Aalto726f6381996-08-26 18:22:31 +0000223 if (ename && (*ename == '-') && (ename[1] == '\0'))
224 execute = 1;
225
226 /* The "execute" form of the command (re-run, with possible string
227 substitutions). */
228 if (execute)
229 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000230 rlist = (REPL *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +0000231 while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
232 {
233 *sep++ = '\0';
234 rl = (REPL *)xmalloc (sizeof (REPL));
235 rl->next = (REPL *)NULL;
236 rl->pat = savestring (list->word->word);
237 rl->rep = savestring (sep);
238
239 if (rlist == NULL)
240 rlist = rl;
241 else
242 {
243 rl->next = rlist;
244 rlist = rl;
245 }
246 list = list->next;
247 }
248
249 /* If we have a list of substitutions to do, then reverse it
250 to get the replacements in the proper order. */
251
Jari Aalto7117c2d2002-07-17 14:10:11 +0000252 rlist = REVERSE_LIST (rlist, REPL *);
Jari Aalto726f6381996-08-26 18:22:31 +0000253
254 hlist = history_list ();
255
256 /* If we still have something in list, it is a command spec.
257 Otherwise, we use the most recent command in time. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000258 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
Jari Aalto726f6381996-08-26 18:22:31 +0000259
260 if (command == NULL)
261 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000262 builtin_error (_("no command found"));
Jari Aalto726f6381996-08-26 18:22:31 +0000263 if (rlist)
264 FREE_RLIST ();
265
266 return (EXECUTION_FAILURE);
267 }
268
269 if (rlist)
270 {
271 newcom = fc_dosubs (command, rlist);
272 free (command);
273 FREE_RLIST ();
274 command = newcom;
275 }
276
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000277 fprintf (stderr, "%s\n", command);
278 fc_replhist (command); /* replace `fc -s' with command */
Chet Ramey89a92862011-11-21 20:49:12 -0500279 /* Posix says that the re-executed commands should be entered into the
280 history. */
Jari Aaltod166f041997-06-05 14:59:13 +0000281 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
Jari Aalto726f6381996-08-26 18:22:31 +0000282 }
283
284 /* This is the second form of the command (the list-or-edit-and-rerun
285 form). */
286 hlist = history_list ();
287 if (hlist == 0)
288 return (EXECUTION_SUCCESS);
289 for (i = 0; hlist[i]; i++);
290
291 /* With the Bash implementation of history, the current command line
292 ("fc blah..." and so on) is already part of the history list by
293 the time we get to this point. This just skips over that command
294 and makes the last command that this deals with be the last command
Jari Aaltod166f041997-06-05 14:59:13 +0000295 the user entered before the fc. We need to check whether the
296 line was actually added (HISTIGNORE may have caused it to not be),
297 so we check hist_last_line_added. */
Jari Aalto726f6381996-08-26 18:22:31 +0000298
Chet Ramey89a92862011-11-21 20:49:12 -0500299 /* Even though command substitution through parse_and_execute turns off
300 remember_on_history, command substitution in a shell when set -o history
301 has been enabled (interactive or not) should use it in the last_hist
302 calculation as if it were on. */
303 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
304 last_hist = i - rh - hist_last_line_added;
Jari Aalto726f6381996-08-26 18:22:31 +0000305
Chet Rameyac50fba2014-02-26 09:36:43 -0500306 /* Make sure that real_last is calculated the same way here and in
307 fc_gethnum. The return value from fc_gethnum is treated specially if
308 it is == real_last and we are listing commands. */
309 real_last = i;
310 /* back up from the end to the last non-null history entry */
311 while (hlist[real_last] == 0 && real_last > 0)
312 real_last--;
313
Chet Ramey30d188c2011-11-21 20:57:16 -0500314 /* XXX */
Chet Ramey7aaa6612011-11-22 20:00:53 -0500315 if (i == last_hist && hlist[last_hist] == 0)
Chet Ramey30d188c2011-11-21 20:57:16 -0500316 while (last_hist >= 0 && hlist[last_hist] == 0)
317 last_hist--;
318 if (last_hist < 0)
319 {
320 sh_erange ((char *)NULL, _("history specification"));
321 return (EXECUTION_FAILURE);
322 }
323
Jari Aalto726f6381996-08-26 18:22:31 +0000324 if (list)
325 {
326 histbeg = fc_gethnum (list->word->word, hlist);
327 list = list->next;
328
329 if (list)
330 histend = fc_gethnum (list->word->word, hlist);
Chet Rameyac50fba2014-02-26 09:36:43 -0500331 else if (histbeg == real_last)
332 histend = listing ? real_last : histbeg;
Jari Aalto726f6381996-08-26 18:22:31 +0000333 else
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000334 histend = listing ? last_hist : histbeg;
Jari Aalto726f6381996-08-26 18:22:31 +0000335 }
336 else
337 {
338 /* The default for listing is the last 16 history items. */
339 if (listing)
340 {
341 histend = last_hist;
Jari Aalto95732b42005-12-07 14:08:12 +0000342 histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
Jari Aalto726f6381996-08-26 18:22:31 +0000343 if (histbeg < 0)
344 histbeg = 0;
345 }
346 else
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000347 /* For editing, it is the last history command. */
348 histbeg = histend = last_hist;
Jari Aalto726f6381996-08-26 18:22:31 +0000349 }
350
Jari Aalto31859422009-01-12 13:36:28 +0000351 /* "When not listing, the fc command that caused the editing shall not be
352 entered into the history list." */
353 if (listing == 0 && hist_last_line_added)
354 {
355 bash_delete_last_history ();
356 /* If we're editing a single command -- the last command in the
357 history -- and we just removed the dummy command added by
358 edit_and_execute_command (), we need to check whether or not we
359 just removed the last command in the history and need to back
360 the pointer up. remember_on_history is off because we're running
361 in parse_and_execute(). */
362 if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
363 last_hist = histbeg = --histend;
364 }
365
Jari Aalto726f6381996-08-26 18:22:31 +0000366 /* We print error messages for line specifications out of range. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000367 if ((histbeg < 0) || (histend < 0))
Jari Aalto726f6381996-08-26 18:22:31 +0000368 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000369 sh_erange ((char *)NULL, _("history specification"));
Jari Aalto726f6381996-08-26 18:22:31 +0000370 return (EXECUTION_FAILURE);
371 }
372
373 if (histend < histbeg)
374 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000375 i = histend;
Jari Aalto726f6381996-08-26 18:22:31 +0000376 histend = histbeg;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000377 histbeg = i;
378
Jari Aalto726f6381996-08-26 18:22:31 +0000379 reverse = 1;
380 }
381
382 if (listing)
383 stream = stdout;
384 else
385 {
386 numbering = 0;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000387 stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000388 if (stream == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000389 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000390 builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
Jari Aalto28ef6c32001-04-06 19:14:31 +0000391 FREE (fn);
Jari Aalto726f6381996-08-26 18:22:31 +0000392 return (EXECUTION_FAILURE);
393 }
394 }
395
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000396 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
Jari Aalto726f6381996-08-26 18:22:31 +0000397 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000398 QUIT;
399 if (numbering)
400 fprintf (stream, "%d", i + history_base);
401 if (listing)
Jari Aalto95732b42005-12-07 14:08:12 +0000402 {
403 if (posixly_correct)
404 fputs ("\t", stream);
405 else
406 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
407 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000408 fprintf (stream, "%s\n", histline (i));
Jari Aalto726f6381996-08-26 18:22:31 +0000409 }
410
411 if (listing)
Jari Aalto31859422009-01-12 13:36:28 +0000412 return (sh_chkwrite (EXECUTION_SUCCESS));
Jari Aalto726f6381996-08-26 18:22:31 +0000413
Jari Aalto31859422009-01-12 13:36:28 +0000414 fflush (stream);
415 if (ferror (stream))
416 {
417 sh_wrerror ();
418 fclose (stream);
419 return (EXECUTION_FAILURE);
420 }
Jari Aalto726f6381996-08-26 18:22:31 +0000421 fclose (stream);
422
423 /* Now edit the file of commands. */
424 if (ename)
425 {
426 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
427 sprintf (command, "%s %s", ename, fn);
428 }
429 else
430 {
Jari Aalto95732b42005-12-07 14:08:12 +0000431 fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
432 command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
433 sprintf (command, "%s %s", fcedit, fn);
Jari Aalto726f6381996-08-26 18:22:31 +0000434 }
Jari Aaltod166f041997-06-05 14:59:13 +0000435 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000436 if (retval != EXECUTION_SUCCESS)
437 {
438 unlink (fn);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000439 free (fn);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000440 return (EXECUTION_FAILURE);
441 }
Jari Aalto726f6381996-08-26 18:22:31 +0000442
Jari Aaltod166f041997-06-05 14:59:13 +0000443 /* Make sure parse_and_execute doesn't turn this off, even though a
444 call to parse_and_execute farther up the function call stack (e.g.,
445 if this is called by vi_edit_and_execute_command) may have already
446 called bash_history_disable. */
447 remember_on_history = 1;
Jari Aalto726f6381996-08-26 18:22:31 +0000448
Jari Aaltod166f041997-06-05 14:59:13 +0000449 /* Turn on the `v' flag while fc_execute_file runs so the commands
Jari Aalto726f6381996-08-26 18:22:31 +0000450 will be echoed as they are read by the parser. */
451 begin_unwind_frame ("fc builtin");
Jari Aalto28ef6c32001-04-06 19:14:31 +0000452 add_unwind_protect ((Function *)xfree, fn);
Jari Aalto726f6381996-08-26 18:22:31 +0000453 add_unwind_protect (unlink, fn);
454 unwind_protect_int (echo_input_at_read);
455 echo_input_at_read = 1;
456
Jari Aaltod166f041997-06-05 14:59:13 +0000457 retval = fc_execute_file (fn);
Jari Aalto726f6381996-08-26 18:22:31 +0000458
459 run_unwind_frame ("fc builtin");
460
461 return (retval);
462}
463
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000464/* Return 1 if LIST->word->word is a legal number for fc's use. */
465static int
466fc_number (list)
467 WORD_LIST *list;
468{
469 char *s;
470
471 if (list == 0)
472 return 0;
473 s = list->word->word;
474 if (*s == '-')
475 s++;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000476 return (legal_number (s, (intmax_t *)NULL));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000477}
478
Jari Aalto726f6381996-08-26 18:22:31 +0000479/* Return an absolute index into HLIST which corresponds to COMMAND. If
480 COMMAND is a number, then it was specified in relative terms. If it
481 is a string, then it is the start of a command line present in HLIST. */
482static int
483fc_gethnum (command, hlist)
484 char *command;
485 HIST_ENTRY **hlist;
486{
Chet Ramey89a92862011-11-21 20:49:12 -0500487 int sign, n, clen, rh;
Chet Rameyac50fba2014-02-26 09:36:43 -0500488 register int i, j, last_hist, real_last;
Jari Aalto726f6381996-08-26 18:22:31 +0000489 register char *s;
490
Jari Aalto31859422009-01-12 13:36:28 +0000491 sign = 1;
Jari Aalto726f6381996-08-26 18:22:31 +0000492 /* Count history elements. */
493 for (i = 0; hlist[i]; i++);
494
495 /* With the Bash implementation of history, the current command line
496 ("fc blah..." and so on) is already part of the history list by
497 the time we get to this point. This just skips over that command
498 and makes the last command that this deals with be the last command
Jari Aaltod166f041997-06-05 14:59:13 +0000499 the user entered before the fc. We need to check whether the
500 line was actually added (HISTIGNORE may have caused it to not be),
Jari Aalto31859422009-01-12 13:36:28 +0000501 so we check hist_last_line_added. This needs to agree with the
502 calculation of last_hist in fc_builtin above. */
Chet Ramey89a92862011-11-21 20:49:12 -0500503 /* Even though command substitution through parse_and_execute turns off
504 remember_on_history, command substitution in a shell when set -o history
505 has been enabled (interactive or not) should use it in the last_hist
506 calculation as if it were on. */
507 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
Chet Ramey7aaa6612011-11-22 20:00:53 -0500508 last_hist = i - rh - hist_last_line_added;
509
510 if (i == last_hist && hlist[last_hist] == 0)
511 while (last_hist >= 0 && hlist[last_hist] == 0)
512 last_hist--;
513 if (last_hist < 0)
514 return (-1);
515
Chet Rameyac50fba2014-02-26 09:36:43 -0500516 real_last = i;
Chet Ramey7aaa6612011-11-22 20:00:53 -0500517 i = last_hist;
Jari Aalto726f6381996-08-26 18:22:31 +0000518
519 /* No specification defaults to most recent command. */
520 if (command == NULL)
521 return (i);
522
Chet Rameyac50fba2014-02-26 09:36:43 -0500523 /* back up from the end to the last non-null history entry */
524 while (hlist[real_last] == 0 && real_last > 0)
525 real_last--;
526
Jari Aalto726f6381996-08-26 18:22:31 +0000527 /* Otherwise, there is a specification. It can be a number relative to
528 the current position, or an absolute history number. */
529 s = command;
530
531 /* Handle possible leading minus sign. */
532 if (s && (*s == '-'))
533 {
534 sign = -1;
535 s++;
536 }
537
Jari Aaltof73dda02001-11-13 17:56:06 +0000538 if (s && DIGIT(*s))
Jari Aalto726f6381996-08-26 18:22:31 +0000539 {
540 n = atoi (s);
541 n *= sign;
542
Jari Aalto726f6381996-08-26 18:22:31 +0000543 /* If the value is negative or zero, then it is an offset from
544 the current history item. */
545 if (n < 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000546 {
547 n += i + 1;
548 return (n < 0 ? 0 : n);
549 }
Jari Aalto726f6381996-08-26 18:22:31 +0000550 else if (n == 0)
Chet Rameyac50fba2014-02-26 09:36:43 -0500551 return ((sign == -1) ? real_last : i);
Jari Aalto726f6381996-08-26 18:22:31 +0000552 else
Jari Aalto7117c2d2002-07-17 14:10:11 +0000553 {
554 n -= history_base;
555 return (i < n ? i : n);
556 }
Jari Aalto726f6381996-08-26 18:22:31 +0000557 }
558
559 clen = strlen (command);
560 for (j = i; j >= 0; j--)
561 {
562 if (STREQN (command, histline (j), clen))
563 return (j);
564 }
565 return (-1);
566}
567
568/* Locate the most recent history line which begins with
569 COMMAND in HLIST, and return a malloc()'ed copy of it. */
570static char *
571fc_gethist (command, hlist)
572 char *command;
573 HIST_ENTRY **hlist;
574{
575 int i;
576
Jari Aalto95732b42005-12-07 14:08:12 +0000577 if (hlist == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000578 return ((char *)NULL);
579
580 i = fc_gethnum (command, hlist);
581
582 if (i >= 0)
583 return (savestring (histline (i)));
584 else
585 return ((char *)NULL);
586}
587
Jari Aaltof73dda02001-11-13 17:56:06 +0000588#ifdef INCLUDE_UNUSED
Jari Aalto726f6381996-08-26 18:22:31 +0000589/* Read the edited history lines from STREAM and return them
590 one at a time. This can read unlimited length lines. The
591 caller should free the storage. */
592static char *
593fc_readline (stream)
594 FILE *stream;
595{
596 register int c;
597 int line_len = 0, lindex = 0;
598 char *line = (char *)NULL;
599
600 while ((c = getc (stream)) != EOF)
601 {
602 if ((lindex + 2) >= line_len)
Jari Aaltof73dda02001-11-13 17:56:06 +0000603 line = (char *)xrealloc (line, (line_len += 128));
Jari Aalto726f6381996-08-26 18:22:31 +0000604
605 if (c == '\n')
606 {
607 line[lindex++] = '\n';
608 line[lindex++] = '\0';
609 return (line);
610 }
611 else
612 line[lindex++] = c;
613 }
614
615 if (!lindex)
616 {
617 if (line)
618 free (line);
619
620 return ((char *)NULL);
621 }
622
623 if (lindex + 2 >= line_len)
624 line = (char *)xrealloc (line, lindex + 3);
625
626 line[lindex++] = '\n'; /* Finish with newline if none in file */
627 line[lindex++] = '\0';
628 return (line);
629}
Jari Aaltof73dda02001-11-13 17:56:06 +0000630#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000631
632/* Perform the SUBS on COMMAND.
633 SUBS is a list of substitutions, and COMMAND is a simple string.
634 Return a pointer to a malloc'ed string which contains the substituted
635 command. */
636static char *
637fc_dosubs (command, subs)
638 char *command;
639 REPL *subs;
640{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000641 register char *new, *t;
Jari Aalto726f6381996-08-26 18:22:31 +0000642 register REPL *r;
643
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000644 for (new = savestring (command), r = subs; r; r = r->next)
Jari Aalto726f6381996-08-26 18:22:31 +0000645 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000646 t = strsub (new, r->pat, r->rep, 1);
Jari Aalto726f6381996-08-26 18:22:31 +0000647 free (new);
648 new = t;
649 }
650 return (new);
651}
652
Jari Aalto726f6381996-08-26 18:22:31 +0000653/* Use `command' to replace the last entry in the history list, which,
654 by this time, is `fc blah...'. The intent is that the new command
655 become the history entry, and that `fc' should never appear in the
656 history list. This way you can do `r' to your heart's content. */
657static void
658fc_replhist (command)
659 char *command;
660{
Jari Aalto726f6381996-08-26 18:22:31 +0000661 int n;
662
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000663 if (command == 0 || *command == '\0')
Jari Aalto726f6381996-08-26 18:22:31 +0000664 return;
665
Jari Aalto726f6381996-08-26 18:22:31 +0000666 n = strlen (command);
Jari Aalto726f6381996-08-26 18:22:31 +0000667 if (command[n - 1] == '\n')
668 command[n - 1] = '\0';
669
670 if (command && *command)
671 {
Jari Aalto31859422009-01-12 13:36:28 +0000672 bash_delete_last_history ();
Jari Aalto726f6381996-08-26 18:22:31 +0000673 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
674 }
675}
676
Jari Aaltof73dda02001-11-13 17:56:06 +0000677#ifdef INCLUDE_UNUSED
Jari Aalto726f6381996-08-26 18:22:31 +0000678/* Add LINE to the history, after removing a single trailing newline. */
679static void
680fc_addhist (line)
681 char *line;
682{
683 register int n;
684
Jari Aalto95732b42005-12-07 14:08:12 +0000685 if (line == 0 || *line == 0)
686 return;
687
Jari Aalto726f6381996-08-26 18:22:31 +0000688 n = strlen (line);
689
690 if (line[n - 1] == '\n')
691 line[n - 1] = '\0';
692
693 if (line && *line)
Jari Aalto95732b42005-12-07 14:08:12 +0000694 maybe_add_history (line); /* Obeys HISTCONTROL setting. */
Jari Aalto726f6381996-08-26 18:22:31 +0000695}
Jari Aaltof73dda02001-11-13 17:56:06 +0000696#endif
697
Jari Aalto726f6381996-08-26 18:22:31 +0000698#endif /* HISTORY */