1 This file is fc.def, from which is created fc.c.
2 It implements the builtin "fc" in Bash.
4 Copyright (C) 1987-2009 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
26 $SHORT_DOC fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]
27 Display or execute commands from the history list.
29 fc is used to list or edit and re-execute commands from the history list.
30 FIRST and LAST can be numbers specifying the range, or FIRST can be a
31 string, which means the most recent command beginning with that
35 -e ENAME select which editor to use. Default is FCEDIT, then EDITOR,
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)
41 With the `fc -s [pat=rep ...] [command]' format, COMMAND is
42 re-executed after the substitution OLD=NEW is performed.
44 A useful alias to use with this is r='fc -s', so that typing `r cc'
45 runs the last command beginning with `cc' and typing `r' re-executes
49 Returns success or status of executed command; non-zero if an error occurs.
56 # include <sys/param.h>
58 #include "../bashtypes.h"
59 #include "posixstat.h"
60 #if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
61 # include <sys/file.h>
64 #if defined (HAVE_UNISTD_H)
69 #include <chartypes.h>
71 #include "../bashansi.h"
72 #include "../bashintl.h"
76 #include "../builtins.h"
78 #include "../bashhist.h"
80 #include <readline/history.h>
81 #include "bashgetopt.h"
88 extern int current_command_line_count;
89 extern int literal_history;
90 extern int posixly_correct;
92 extern int unlink __P((const char *));
94 extern FILE *sh_mktmpfp __P((char *, int, char **));
96 /* **************************************************************** */
98 /* The K*rn shell style fc command (Fix Command) */
100 /* **************************************************************** */
102 /* fc builtin command (fix command) for Bash for those who
103 like K*rn-style history better than csh-style.
105 fc [-e ename] [-nlr] [first] [last]
107 FIRST and LAST can be numbers specifying the range, or FIRST can be
108 a string, which means the most recent command beginning with that
111 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
112 then the editor which corresponds to the current readline editing
115 -l means list lines instead of editing.
116 -n means no line numbers listed.
117 -r means reverse the order of the lines (making it newest listed first).
119 fc -e - [pat=rep ...] [command]
120 fc -s [pat=rep ...] [command]
122 Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
125 /* Data structure describing a list of global replacements to perform. */
126 typedef struct repl {
132 /* Accessors for HIST_ENTRY lists that are called HLIST. */
133 #define histline(i) (hlist[(i)]->line)
134 #define histdata(i) (hlist[(i)]->data)
136 #define FREE_RLIST() \
138 for (rl = rlist; rl; ) { \
150 static char *fc_dosubs __P((char *, REPL *));
151 static char *fc_gethist __P((char *, HIST_ENTRY **));
152 static int fc_gethnum __P((char *, HIST_ENTRY **));
153 static int fc_number __P((WORD_LIST *));
154 static void fc_replhist __P((char *));
155 #ifdef INCLUDE_UNUSED
156 static char *fc_readline __P((FILE *));
157 static void fc_addhist __P((char *));
160 /* String to execute on a file that we want to edit. */
161 #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
162 #if defined (STRICT_POSIX)
163 # define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
165 # define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
174 int numbering, reverse, listing, execute;
175 int histbeg, histend, last_hist, retval, opt;
178 char *ename, *command, *newcom, *fcedit;
183 reverse = listing = execute = 0;
184 ename = (char *)NULL;
186 /* Parse out the options and set which of the two forms we're in. */
187 reset_internal_getopt ();
188 lcurrent = list; /* XXX */
189 while (fc_number (loptend = lcurrent) == 0 &&
190 (opt = internal_getopt (list, ":e:lnrs")) != -1)
222 if (ename && (*ename == '-') && (ename[1] == '\0'))
225 /* The "execute" form of the command (re-run, with possible string
229 rlist = (REPL *)NULL;
230 while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
233 rl = (REPL *)xmalloc (sizeof (REPL));
234 rl->next = (REPL *)NULL;
235 rl->pat = savestring (list->word->word);
236 rl->rep = savestring (sep);
248 /* If we have a list of substitutions to do, then reverse it
249 to get the replacements in the proper order. */
251 rlist = REVERSE_LIST (rlist, REPL *);
253 hlist = history_list ();
255 /* If we still have something in list, it is a command spec.
256 Otherwise, we use the most recent command in time. */
257 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
261 builtin_error (_("no command found"));
265 return (EXECUTION_FAILURE);
270 newcom = fc_dosubs (command, rlist);
276 fprintf (stderr, "%s\n", command);
277 fc_replhist (command); /* replace `fc -s' with command */
278 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
281 /* This is the second form of the command (the list-or-edit-and-rerun
283 hlist = history_list ();
285 return (EXECUTION_SUCCESS);
286 for (i = 0; hlist[i]; i++);
288 /* With the Bash implementation of history, the current command line
289 ("fc blah..." and so on) is already part of the history list by
290 the time we get to this point. This just skips over that command
291 and makes the last command that this deals with be the last command
292 the user entered before the fc. We need to check whether the
293 line was actually added (HISTIGNORE may have caused it to not be),
294 so we check hist_last_line_added. */
296 last_hist = i - remember_on_history - hist_last_line_added;
300 histbeg = fc_gethnum (list->word->word, hlist);
304 histend = fc_gethnum (list->word->word, hlist);
306 histend = listing ? last_hist : histbeg;
310 /* The default for listing is the last 16 history items. */
314 histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
319 /* For editing, it is the last history command. */
320 histbeg = histend = last_hist;
323 /* "When not listing, the fc command that caused the editing shall not be
324 entered into the history list." */
325 if (listing == 0 && hist_last_line_added)
327 bash_delete_last_history ();
328 /* If we're editing a single command -- the last command in the
329 history -- and we just removed the dummy command added by
330 edit_and_execute_command (), we need to check whether or not we
331 just removed the last command in the history and need to back
332 the pointer up. remember_on_history is off because we're running
333 in parse_and_execute(). */
334 if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
335 last_hist = histbeg = --histend;
338 /* We print error messages for line specifications out of range. */
339 if ((histbeg < 0) || (histend < 0))
341 sh_erange ((char *)NULL, _("history specification"));
342 return (EXECUTION_FAILURE);
345 if (histend < histbeg)
359 stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
362 builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
364 return (EXECUTION_FAILURE);
368 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
372 fprintf (stream, "%d", i + history_base);
376 fputs ("\t", stream);
378 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
380 fprintf (stream, "%s\n", histline (i));
384 return (sh_chkwrite (EXECUTION_SUCCESS));
391 return (EXECUTION_FAILURE);
395 /* Now edit the file of commands. */
398 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
399 sprintf (command, "%s %s", ename, fn);
403 fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
404 command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
405 sprintf (command, "%s %s", fcedit, fn);
407 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
408 if (retval != EXECUTION_SUCCESS)
412 return (EXECUTION_FAILURE);
415 /* Make sure parse_and_execute doesn't turn this off, even though a
416 call to parse_and_execute farther up the function call stack (e.g.,
417 if this is called by vi_edit_and_execute_command) may have already
418 called bash_history_disable. */
419 remember_on_history = 1;
421 /* Turn on the `v' flag while fc_execute_file runs so the commands
422 will be echoed as they are read by the parser. */
423 begin_unwind_frame ("fc builtin");
424 add_unwind_protect ((Function *)xfree, fn);
425 add_unwind_protect (unlink, fn);
426 unwind_protect_int (echo_input_at_read);
427 echo_input_at_read = 1;
429 retval = fc_execute_file (fn);
431 run_unwind_frame ("fc builtin");
436 /* Return 1 if LIST->word->word is a legal number for fc's use. */
445 s = list->word->word;
448 return (legal_number (s, (intmax_t *)NULL));
451 /* Return an absolute index into HLIST which corresponds to COMMAND. If
452 COMMAND is a number, then it was specified in relative terms. If it
453 is a string, then it is the start of a command line present in HLIST. */
455 fc_gethnum (command, hlist)
464 /* Count history elements. */
465 for (i = 0; hlist[i]; i++);
467 /* With the Bash implementation of history, the current command line
468 ("fc blah..." and so on) is already part of the history list by
469 the time we get to this point. This just skips over that command
470 and makes the last command that this deals with be the last command
471 the user entered before the fc. We need to check whether the
472 line was actually added (HISTIGNORE may have caused it to not be),
473 so we check hist_last_line_added. This needs to agree with the
474 calculation of last_hist in fc_builtin above. */
475 i -= remember_on_history + hist_last_line_added;
477 /* No specification defaults to most recent command. */
481 /* Otherwise, there is a specification. It can be a number relative to
482 the current position, or an absolute history number. */
485 /* Handle possible leading minus sign. */
486 if (s && (*s == '-'))
497 /* If the value is negative or zero, then it is an offset from
498 the current history item. */
502 return (n < 0 ? 0 : n);
509 return (i < n ? i : n);
513 clen = strlen (command);
514 for (j = i; j >= 0; j--)
516 if (STREQN (command, histline (j), clen))
522 /* Locate the most recent history line which begins with
523 COMMAND in HLIST, and return a malloc()'ed copy of it. */
525 fc_gethist (command, hlist)
532 return ((char *)NULL);
534 i = fc_gethnum (command, hlist);
537 return (savestring (histline (i)));
539 return ((char *)NULL);
542 #ifdef INCLUDE_UNUSED
543 /* Read the edited history lines from STREAM and return them
544 one at a time. This can read unlimited length lines. The
545 caller should free the storage. */
551 int line_len = 0, lindex = 0;
552 char *line = (char *)NULL;
554 while ((c = getc (stream)) != EOF)
556 if ((lindex + 2) >= line_len)
557 line = (char *)xrealloc (line, (line_len += 128));
561 line[lindex++] = '\n';
562 line[lindex++] = '\0';
574 return ((char *)NULL);
577 if (lindex + 2 >= line_len)
578 line = (char *)xrealloc (line, lindex + 3);
580 line[lindex++] = '\n'; /* Finish with newline if none in file */
581 line[lindex++] = '\0';
586 /* Perform the SUBS on COMMAND.
587 SUBS is a list of substitutions, and COMMAND is a simple string.
588 Return a pointer to a malloc'ed string which contains the substituted
591 fc_dosubs (command, subs)
595 register char *new, *t;
598 for (new = savestring (command), r = subs; r; r = r->next)
600 t = strsub (new, r->pat, r->rep, 1);
607 /* Use `command' to replace the last entry in the history list, which,
608 by this time, is `fc blah...'. The intent is that the new command
609 become the history entry, and that `fc' should never appear in the
610 history list. This way you can do `r' to your heart's content. */
612 fc_replhist (command)
617 if (command == 0 || *command == '\0')
620 n = strlen (command);
621 if (command[n - 1] == '\n')
622 command[n - 1] = '\0';
624 if (command && *command)
626 bash_delete_last_history ();
627 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
631 #ifdef INCLUDE_UNUSED
632 /* Add LINE to the history, after removing a single trailing newline. */
639 if (line == 0 || *line == 0)
644 if (line[n - 1] == '\n')
648 maybe_add_history (line); /* Obeys HISTCONTROL setting. */