1 This file is fc.def, from which is created fc.c.
2 It implements the builtin "fc" in Bash.
4 Copyright (C) 1987, 1989, 1991 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 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
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
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.
27 $SHORT_DOC fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
29 FIRST and LAST can be numbers specifying the range, or FIRST can be a
30 string, which means the most recent command beginning with that
33 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
34 then the editor which corresponds to the current readline editing
37 -l means list lines instead of editing.
38 -n means no line numbers listed.
39 -r means reverse the order of the lines (making it newest listed first).
41 With the `fc -s [pat=rep ...] [command]' format, the 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
53 # include <sys/param.h>
55 #include "../bashtypes.h"
56 #include "../posixstat.h"
58 # include <sys/file.h>
61 #if defined (HAVE_UNISTD_H)
67 #include "../bashansi.h"
71 #include "../builtins.h"
73 #include "../maxpath.h"
74 #include "../bashhist.h"
75 #include <readline/history.h>
76 #include "bashgetopt.h"
83 extern int echo_input_at_read;
84 extern int current_command_line_count;
85 extern int literal_history;
89 extern int fc_execute_file ();
91 /* **************************************************************** */
93 /* The K*rn shell style fc command (Fix Command) */
95 /* **************************************************************** */
97 /* fc builtin command (fix command) for Bash for those who
98 like K*rn-style history better than csh-style.
100 fc [-e ename] [-nlr] [first] [last]
102 FIRST and LAST can be numbers specifying the range, or FIRST can be
103 a string, which means the most recent command beginning with that
106 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
107 then the editor which corresponds to the current readline editing
110 -l means list lines instead of editing.
111 -n means no line numbers listed.
112 -r means reverse the order of the lines (making it newest listed first).
114 fc -e - [pat=rep ...] [command]
115 fc -s [pat=rep ...] [command]
117 Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
120 static char *fc_dosubs (), *fc_gethist (), *fc_readline ();
121 static int fc_gethnum (), fc_number ();
122 static void fc_replhist (), fc_addhist ();
124 /* Data structure describing a list of global replacements to perform. */
125 typedef struct repl {
131 /* Accessors for HIST_ENTRY lists that are called HLIST. */
132 #define histline(i) (hlist[(i)]->line)
133 #define histdata(i) (hlist[(i)]->data)
135 #define FREE_RLIST() \
137 for (rl = rlist; rl; ) { \
149 /* String to execute on a file that we want to edit. */
150 #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
158 int numbering, reverse, listing, execute;
159 int histbeg, histend, last_hist, retval, first, opt;
162 char *ename, *command, *newcom, *line;
167 reverse = listing = execute = 0;
168 ename = (char *)NULL;
170 /* Parse out the options and set which of the two forms we're in. */
171 reset_internal_getopt ();
172 lcurrent = list; /* XXX */
173 while (fc_number (loptend = lcurrent) == 0 &&
174 (opt = internal_getopt (list, ":e:lnrs")) != -1)
206 if (ename && (*ename == '-') && (ename[1] == '\0'))
209 /* The "execute" form of the command (re-run, with possible string
213 rlist = (REPL *)NULL;
214 while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
217 rl = (REPL *)xmalloc (sizeof (REPL));
218 rl->next = (REPL *)NULL;
219 rl->pat = savestring (list->word->word);
220 rl->rep = savestring (sep);
232 /* If we have a list of substitutions to do, then reverse it
233 to get the replacements in the proper order. */
235 if (rlist && rlist->next)
236 rlist = (REPL *)reverse_list ((GENERIC_LIST *) rlist);
238 hlist = history_list ();
240 /* If we still have something in list, it is a command spec.
241 Otherwise, we use the most recent command in time. */
242 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
246 builtin_error ("no command found");
250 return (EXECUTION_FAILURE);
255 newcom = fc_dosubs (command, rlist);
261 fprintf (stderr, "%s\n", command);
262 fc_replhist (command); /* replace `fc -s' with command */
263 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
266 /* This is the second form of the command (the list-or-edit-and-rerun
268 hlist = history_list ();
270 return (EXECUTION_SUCCESS);
271 for (i = 0; hlist[i]; i++);
273 /* With the Bash implementation of history, the current command line
274 ("fc blah..." and so on) is already part of the history list by
275 the time we get to this point. This just skips over that command
276 and makes the last command that this deals with be the last command
277 the user entered before the fc. We need to check whether the
278 line was actually added (HISTIGNORE may have caused it to not be),
279 so we check hist_last_line_added. */
281 last_hist = i - 1 - hist_last_line_added;
285 histbeg = fc_gethnum (list->word->word, hlist);
289 histend = fc_gethnum (list->word->word, hlist);
291 histend = listing ? last_hist : histbeg;
295 /* The default for listing is the last 16 history items. */
299 histbeg = histend - 16;
304 /* For editing, it is the last history command. */
305 histbeg = histend = last_hist;
308 /* We print error messages for line specifications out of range. */
309 if ((histbeg < 0) || (histend < 0) ||
310 (histbeg > last_hist) || (histend > last_hist))
312 builtin_error ("history specification out of range");
313 return (EXECUTION_FAILURE);
316 if (histend < histbeg)
330 /* XXX - this is raceable */
331 sprintf (fn, "/tmp/bash%d", (int)time ((time_t *) 0) + (int)getpid ());
333 stream = fopen (fn, "w");
337 builtin_error ("cannot open temp file %s", fn);
338 return (EXECUTION_FAILURE);
342 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
346 fprintf (stream, "%d", i + history_base);
348 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
349 fprintf (stream, "%s\n", histline (i));
353 return (EXECUTION_SUCCESS);
357 /* Now edit the file of commands. */
360 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
361 sprintf (command, "%s %s", ename, fn);
365 command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn));
366 sprintf (command, "%s %s", FC_EDIT_COMMAND, fn);
368 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
369 if (retval != EXECUTION_SUCCESS)
372 return (EXECUTION_FAILURE);
375 /* Now reopen the file and execute the edited commands. */
377 stream = fopen (fn, "r");
381 builtin_error ("cannot reopen temp file %s", fn);
383 return (EXECUTION_FAILURE);
386 retval = EXECUTION_SUCCESS;
390 /* Make sure parse_and_execute doesn't turn this off, even though a
391 call to parse_and_execute farther up the function call stack (e.g.,
392 if this is called by vi_edit_and_execute_command) may have already
393 called bash_history_disable. */
394 remember_on_history = 1;
396 /* First, write the commands to the history file. This will not happen
397 when we call parse_and_execute, since parse_and_execute disables
398 the command line history while it executes. */
400 opt = current_command_line_count;
401 while ((line = fc_readline (stream)) != NULL)
406 continue; /* Skip blank lines. */
412 /* If we retrieved only one command from the history file, but we
413 read multiple lines from the edited file, and literal_history
414 has been set by `shopt', we assume that it was a compound
415 command stored with embedded newlines. In this case, we want
416 the history code to store it as one command again. */
417 if (literal_history && histbeg == histend)
418 current_command_line_count = 1;
423 if (literal_history && histbeg == histend)
424 current_command_line_count++;
431 current_command_line_count = opt;
434 /* Turn on the `v' flag while fc_execute_file runs so the commands
435 will be echoed as they are read by the parser. */
436 begin_unwind_frame ("fc builtin");
437 add_unwind_protect (unlink, fn);
438 unwind_protect_int (echo_input_at_read);
439 echo_input_at_read = 1;
441 retval = fc_execute_file (fn);
443 run_unwind_frame ("fc builtin");
448 /* Return 1 if LIST->word->word is a legal number for fc's use. */
457 s = list->word->word;
460 return (legal_number (s, (long *)NULL));
463 /* Return an absolute index into HLIST which corresponds to COMMAND. If
464 COMMAND is a number, then it was specified in relative terms. If it
465 is a string, then it is the start of a command line present in HLIST. */
467 fc_gethnum (command, hlist)
471 int sign = 1, n, clen;
475 /* Count history elements. */
476 for (i = 0; hlist[i]; i++);
478 /* With the Bash implementation of history, the current command line
479 ("fc blah..." and so on) is already part of the history list by
480 the time we get to this point. This just skips over that command
481 and makes the last command that this deals with be the last command
482 the user entered before the fc. We need to check whether the
483 line was actually added (HISTIGNORE may have caused it to not be),
484 so we check hist_last_line_added. */
485 i -= 1 + hist_last_line_added;
487 /* No specification defaults to most recent command. */
491 /* Otherwise, there is a specification. It can be a number relative to
492 the current position, or an absolute history number. */
495 /* Handle possible leading minus sign. */
496 if (s && (*s == '-'))
507 /* Anything specified greater than the last history element that we
508 deal with is an error. */
509 if (n > i + history_base)
512 /* If the value is negative or zero, then it is an offset from
513 the current history item. */
519 return (n - history_base);
522 clen = strlen (command);
523 for (j = i; j >= 0; j--)
525 if (STREQN (command, histline (j), clen))
531 /* Locate the most recent history line which begins with
532 COMMAND in HLIST, and return a malloc()'ed copy of it. */
534 fc_gethist (command, hlist)
541 return ((char *)NULL);
543 i = fc_gethnum (command, hlist);
546 return (savestring (histline (i)));
548 return ((char *)NULL);
551 /* Read the edited history lines from STREAM and return them
552 one at a time. This can read unlimited length lines. The
553 caller should free the storage. */
559 int line_len = 0, lindex = 0;
560 char *line = (char *)NULL;
562 while ((c = getc (stream)) != EOF)
564 if ((lindex + 2) >= line_len)
565 line = (char *) xrealloc (line, (line_len += 128));
569 line[lindex++] = '\n';
570 line[lindex++] = '\0';
582 return ((char *)NULL);
585 if (lindex + 2 >= line_len)
586 line = (char *)xrealloc (line, lindex + 3);
588 line[lindex++] = '\n'; /* Finish with newline if none in file */
589 line[lindex++] = '\0';
593 /* Perform the SUBS on COMMAND.
594 SUBS is a list of substitutions, and COMMAND is a simple string.
595 Return a pointer to a malloc'ed string which contains the substituted
598 fc_dosubs (command, subs)
602 register char *new, *t;
605 for (new = savestring (command), r = subs; r; r = r->next)
607 t = strsub (new, r->pat, r->rep, 1);
614 /* Use `command' to replace the last entry in the history list, which,
615 by this time, is `fc blah...'. The intent is that the new command
616 become the history entry, and that `fc' should never appear in the
617 history list. This way you can do `r' to your heart's content. */
619 fc_replhist (command)
623 HIST_ENTRY **hlist, *histent, *discard;
626 if (command == 0 || *command == '\0')
629 hlist = history_list ();
634 for (i = 0; hlist[i]; i++);
637 /* History_get () takes a parameter that should be
638 offset by history_base. */
640 histent = history_get (history_base + i); /* Don't free this */
644 n = strlen (command);
646 if (command[n - 1] == '\n')
647 command[n - 1] = '\0';
649 if (command && *command)
651 discard = remove_history (i);
654 FREE (discard->line);
655 free ((char *) discard);
657 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
661 /* Add LINE to the history, after removing a single trailing newline. */
670 if (line[n - 1] == '\n')
674 maybe_add_history (line);