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
52 #include <sys/param.h>
53 #include "../bashtypes.h"
54 #include "../posixstat.h"
57 #if defined (HAVE_UNISTD_H)
63 #include "../bashansi.h"
67 #include "../builtins.h"
69 #include "../maxpath.h"
70 #include "../bashhist.h"
71 #include <readline/history.h>
72 #include "bashgetopt.h"
79 extern int echo_input_at_read;
80 extern int current_command_line_count;
81 extern int literal_history;
85 extern int fc_execute_file ();
87 /* **************************************************************** */
89 /* The K*rn shell style fc command (Fix Command) */
91 /* **************************************************************** */
93 /* fc builtin command (fix command) for Bash for those who
94 like K*rn-style history better than csh-style.
96 fc [-e ename] [-nlr] [first] [last]
98 FIRST and LAST can be numbers specifying the range, or FIRST can be
99 a string, which means the most recent command beginning with that
102 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
103 then the editor which corresponds to the current readline editing
106 -l means list lines instead of editing.
107 -n means no line numbers listed.
108 -r means reverse the order of the lines (making it newest listed first).
110 fc -e - [pat=rep ...] [command]
111 fc -s [pat=rep ...] [command]
113 Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
116 static char *fc_dosubs (), *fc_gethist (), *fc_readline ();
117 static int fc_gethnum (), fc_number ();
118 static void fc_replhist (), fc_addhist ();
120 /* Data structure describing a list of global replacements to perform. */
121 typedef struct repl {
127 /* Accessors for HIST_ENTRY lists that are called HLIST. */
128 #define histline(i) (hlist[(i)]->line)
129 #define histdata(i) (hlist[(i)]->data)
131 #define FREE_RLIST() \
133 for (rl = rlist; rl; ) { \
145 /* String to execute on a file that we want to edit. */
146 #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
154 int numbering, reverse, listing, execute;
155 int histbeg, histend, last_hist, retval, first, opt;
158 char *ename, *command, *newcom, *line;
163 reverse = listing = execute = 0;
164 ename = (char *)NULL;
166 /* Parse out the options and set which of the two forms we're in. */
167 reset_internal_getopt ();
168 lcurrent = list; /* XXX */
169 while (fc_number (loptend = lcurrent) == 0 &&
170 (opt = internal_getopt (list, ":e:lnrs")) != -1)
202 if (ename && (*ename == '-') && (ename[1] == '\0'))
205 /* The "execute" form of the command (re-run, with possible string
209 rlist = (REPL *)NULL;
210 while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
213 rl = (REPL *)xmalloc (sizeof (REPL));
214 rl->next = (REPL *)NULL;
215 rl->pat = savestring (list->word->word);
216 rl->rep = savestring (sep);
228 /* If we have a list of substitutions to do, then reverse it
229 to get the replacements in the proper order. */
231 if (rlist && rlist->next)
232 rlist = (REPL *)reverse_list ((GENERIC_LIST *) rlist);
234 hlist = history_list ();
236 /* If we still have something in list, it is a command spec.
237 Otherwise, we use the most recent command in time. */
238 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
242 builtin_error ("no command found");
246 return (EXECUTION_FAILURE);
251 newcom = fc_dosubs (command, rlist);
257 fprintf (stderr, "%s\n", command);
258 fc_replhist (command); /* replace `fc -s' with command */
259 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
262 /* This is the second form of the command (the list-or-edit-and-rerun
264 hlist = history_list ();
266 return (EXECUTION_SUCCESS);
267 for (i = 0; hlist[i]; i++);
269 /* With the Bash implementation of history, the current command line
270 ("fc blah..." and so on) is already part of the history list by
271 the time we get to this point. This just skips over that command
272 and makes the last command that this deals with be the last command
273 the user entered before the fc. We need to check whether the
274 line was actually added (HISTIGNORE may have caused it to not be),
275 so we check hist_last_line_added. */
277 last_hist = i - 1 - hist_last_line_added;
281 histbeg = fc_gethnum (list->word->word, hlist);
285 histend = fc_gethnum (list->word->word, hlist);
287 histend = listing ? last_hist : histbeg;
291 /* The default for listing is the last 16 history items. */
295 histbeg = histend - 16;
300 /* For editing, it is the last history command. */
301 histbeg = histend = last_hist;
304 /* We print error messages for line specifications out of range. */
305 if ((histbeg < 0) || (histend < 0) ||
306 (histbeg > last_hist) || (histend > last_hist))
308 builtin_error ("history specification out of range");
309 return (EXECUTION_FAILURE);
312 if (histend < histbeg)
326 /* XXX - this is raceable */
327 sprintf (fn, "/tmp/bash%d", (int)time ((time_t *) 0) + (int)getpid ());
329 stream = fopen (fn, "w");
333 builtin_error ("cannot open temp file %s", fn);
334 return (EXECUTION_FAILURE);
338 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
342 fprintf (stream, "%d", i + history_base);
344 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
345 fprintf (stream, "%s\n", histline (i));
349 return (EXECUTION_SUCCESS);
353 /* Now edit the file of commands. */
356 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
357 sprintf (command, "%s %s", ename, fn);
361 command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn));
362 sprintf (command, "%s %s", FC_EDIT_COMMAND, fn);
364 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
365 if (retval != EXECUTION_SUCCESS)
368 return (EXECUTION_FAILURE);
371 /* Now reopen the file and execute the edited commands. */
373 stream = fopen (fn, "r");
377 builtin_error ("cannot reopen temp file %s", fn);
379 return (EXECUTION_FAILURE);
382 retval = EXECUTION_SUCCESS;
386 /* Make sure parse_and_execute doesn't turn this off, even though a
387 call to parse_and_execute farther up the function call stack (e.g.,
388 if this is called by vi_edit_and_execute_command) may have already
389 called bash_history_disable. */
390 remember_on_history = 1;
392 /* First, write the commands to the history file. This will not happen
393 when we call parse_and_execute, since parse_and_execute disables
394 the command line history while it executes. */
396 opt = current_command_line_count;
397 while ((line = fc_readline (stream)) != NULL)
402 continue; /* Skip blank lines. */
408 /* If we retrieved only one command from the history file, but we
409 read multiple lines from the edited file, and literal_history
410 has been set by `shopt', we assume that it was a compound
411 command stored with embedded newlines. In this case, we want
412 the history code to store it as one command again. */
413 if (literal_history && histbeg == histend)
414 current_command_line_count = 1;
419 if (literal_history && histbeg == histend)
420 current_command_line_count++;
427 current_command_line_count = opt;
430 /* Turn on the `v' flag while fc_execute_file runs so the commands
431 will be echoed as they are read by the parser. */
432 begin_unwind_frame ("fc builtin");
433 add_unwind_protect (unlink, fn);
434 unwind_protect_int (echo_input_at_read);
435 echo_input_at_read = 1;
437 retval = fc_execute_file (fn);
439 run_unwind_frame ("fc builtin");
444 /* Return 1 if LIST->word->word is a legal number for fc's use. */
453 s = list->word->word;
456 return (legal_number (s, (long *)NULL));
459 /* Return an absolute index into HLIST which corresponds to COMMAND. If
460 COMMAND is a number, then it was specified in relative terms. If it
461 is a string, then it is the start of a command line present in HLIST. */
463 fc_gethnum (command, hlist)
467 int sign = 1, n, clen;
471 /* Count history elements. */
472 for (i = 0; hlist[i]; i++);
474 /* With the Bash implementation of history, the current command line
475 ("fc blah..." and so on) is already part of the history list by
476 the time we get to this point. This just skips over that command
477 and makes the last command that this deals with be the last command
478 the user entered before the fc. We need to check whether the
479 line was actually added (HISTIGNORE may have caused it to not be),
480 so we check hist_last_line_added. */
481 i -= 1 + hist_last_line_added;
483 /* No specification defaults to most recent command. */
487 /* Otherwise, there is a specification. It can be a number relative to
488 the current position, or an absolute history number. */
491 /* Handle possible leading minus sign. */
492 if (s && (*s == '-'))
503 /* Anything specified greater than the last history element that we
504 deal with is an error. */
505 if (n > i + history_base)
508 /* If the value is negative or zero, then it is an offset from
509 the current history item. */
515 return (n - history_base);
518 clen = strlen (command);
519 for (j = i; j >= 0; j--)
521 if (STREQN (command, histline (j), clen))
527 /* Locate the most recent history line which begins with
528 COMMAND in HLIST, and return a malloc()'ed copy of it. */
530 fc_gethist (command, hlist)
537 return ((char *)NULL);
539 i = fc_gethnum (command, hlist);
542 return (savestring (histline (i)));
544 return ((char *)NULL);
547 /* Read the edited history lines from STREAM and return them
548 one at a time. This can read unlimited length lines. The
549 caller should free the storage. */
555 int line_len = 0, lindex = 0;
556 char *line = (char *)NULL;
558 while ((c = getc (stream)) != EOF)
560 if ((lindex + 2) >= line_len)
561 line = (char *) xrealloc (line, (line_len += 128));
565 line[lindex++] = '\n';
566 line[lindex++] = '\0';
578 return ((char *)NULL);
581 if (lindex + 2 >= line_len)
582 line = (char *)xrealloc (line, lindex + 3);
584 line[lindex++] = '\n'; /* Finish with newline if none in file */
585 line[lindex++] = '\0';
589 /* Perform the SUBS on COMMAND.
590 SUBS is a list of substitutions, and COMMAND is a simple string.
591 Return a pointer to a malloc'ed string which contains the substituted
594 fc_dosubs (command, subs)
598 register char *new, *t;
601 for (new = savestring (command), r = subs; r; r = r->next)
603 t = strsub (new, r->pat, r->rep, 1);
610 /* Use `command' to replace the last entry in the history list, which,
611 by this time, is `fc blah...'. The intent is that the new command
612 become the history entry, and that `fc' should never appear in the
613 history list. This way you can do `r' to your heart's content. */
615 fc_replhist (command)
619 HIST_ENTRY **hlist, *histent, *discard;
622 if (command == 0 || *command == '\0')
625 hlist = history_list ();
630 for (i = 0; hlist[i]; i++);
633 /* History_get () takes a parameter that should be
634 offset by history_base. */
636 histent = history_get (history_base + i); /* Don't free this */
640 n = strlen (command);
642 if (command[n - 1] == '\n')
643 command[n - 1] = '\0';
645 if (command && *command)
647 discard = remove_history (i);
650 FREE (discard->line);
651 free ((char *) discard);
653 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
657 /* Add LINE to the history, after removing a single trailing newline. */
666 if (line[n - 1] == '\n')
670 maybe_add_history (line);