]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/fc.def
Bash-4.0 patchlevel 38
[thirdparty/bash.git] / builtins / fc.def
1 This file is fc.def, from which is created fc.c.
2 It implements the builtin "fc" in Bash.
3
4 Copyright (C) 1987-2009 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
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.
12
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.
17
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/>.
20
21 $PRODUCES fc.c
22
23 $BUILTIN fc
24 $FUNCTION fc_builtin
25 $DEPENDS_ON HISTORY
26 $SHORT_DOC fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]
27 Display or execute commands from the history list.
28
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
32 string.
33
34 Options:
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)
40
41 With the `fc -s [pat=rep ...] [command]' format, COMMAND is
42 re-executed after the substitution OLD=NEW is performed.
43
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
46 the last command.
47
48 Exit Status:
49 Returns success or status of executed command; non-zero if an error occurs.
50 $END
51
52 #include <config.h>
53
54 #if defined (HISTORY)
55 #ifndef _MINIX
56 # include <sys/param.h>
57 #endif
58 #include "../bashtypes.h"
59 #include "posixstat.h"
60 #if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
61 # include <sys/file.h>
62 #endif
63
64 #if defined (HAVE_UNISTD_H)
65 # include <unistd.h>
66 #endif
67
68 #include <stdio.h>
69 #include <chartypes.h>
70
71 #include "../bashansi.h"
72 #include "../bashintl.h"
73 #include <errno.h>
74
75 #include "../shell.h"
76 #include "../builtins.h"
77 #include "../flags.h"
78 #include "../bashhist.h"
79 #include "maxpath.h"
80 #include <readline/history.h>
81 #include "bashgetopt.h"
82 #include "common.h"
83
84 #if !defined (errno)
85 extern int errno;
86 #endif /* !errno */
87
88 extern int current_command_line_count;
89 extern int literal_history;
90 extern int posixly_correct;
91 extern int subshell_environment, interactive_shell;
92
93 extern int unlink __P((const char *));
94
95 extern FILE *sh_mktmpfp __P((char *, int, char **));
96
97 /* **************************************************************** */
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
126 /* Data structure describing a list of global replacements to perform. */
127 typedef struct repl {
128 struct repl *next;
129 char *pat;
130 char *rep;
131 } REPL;
132
133 /* 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
151 static char *fc_dosubs __P((char *, REPL *));
152 static char *fc_gethist __P((char *, HIST_ENTRY **));
153 static int fc_gethnum __P((char *, HIST_ENTRY **));
154 static int fc_number __P((WORD_LIST *));
155 static void fc_replhist __P((char *));
156 #ifdef INCLUDE_UNUSED
157 static char *fc_readline __P((FILE *));
158 static void fc_addhist __P((char *));
159 #endif
160
161 /* String to execute on a file that we want to edit. */
162 #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
163 #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
168
169 int
170 fc_builtin (list)
171 WORD_LIST *list;
172 {
173 register int i;
174 register char *sep;
175 int numbering, reverse, listing, execute;
176 int histbeg, histend, last_hist, retval, opt, rh;
177 FILE *stream;
178 REPL *rlist, *rl;
179 char *ename, *command, *newcom, *fcedit;
180 HIST_ENTRY **hlist;
181 char *fn;
182
183 numbering = 1;
184 reverse = listing = execute = 0;
185 ename = (char *)NULL;
186
187 /* Parse out the options and set which of the two forms we're in. */
188 reset_internal_getopt ();
189 lcurrent = list; /* XXX */
190 while (fc_number (loptend = lcurrent) == 0 &&
191 (opt = internal_getopt (list, ":e:lnrs")) != -1)
192 {
193 switch (opt)
194 {
195 case 'n':
196 numbering = 0;
197 break;
198
199 case 'l':
200 listing = 1;
201 break;
202
203 case 'r':
204 reverse = 1;
205 break;
206
207 case 's':
208 execute = 1;
209 break;
210
211 case 'e':
212 ename = list_optarg;
213 break;
214
215 default:
216 builtin_usage ();
217 return (EX_USAGE);
218 }
219 }
220
221 list = loptend;
222
223 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 {
230 rlist = (REPL *)NULL;
231 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
252 rlist = REVERSE_LIST (rlist, REPL *);
253
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. */
258 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
259
260 if (command == NULL)
261 {
262 builtin_error (_("no command found"));
263 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
277 fprintf (stderr, "%s\n", command);
278 fc_replhist (command); /* replace `fc -s' with command */
279 /* Posix says that the re-executed commands should be entered into the
280 history. */
281 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
282 }
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
295 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. */
298
299 /* 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;
305
306 if (list)
307 {
308 histbeg = fc_gethnum (list->word->word, hlist);
309 list = list->next;
310
311 if (list)
312 histend = fc_gethnum (list->word->word, hlist);
313 else
314 histend = listing ? last_hist : histbeg;
315 }
316 else
317 {
318 /* The default for listing is the last 16 history items. */
319 if (listing)
320 {
321 histend = last_hist;
322 histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
323 if (histbeg < 0)
324 histbeg = 0;
325 }
326 else
327 /* For editing, it is the last history command. */
328 histbeg = histend = last_hist;
329 }
330
331 /* "When not listing, the fc command that caused the editing shall not be
332 entered into the history list." */
333 if (listing == 0 && hist_last_line_added)
334 {
335 bash_delete_last_history ();
336 /* If we're editing a single command -- the last command in the
337 history -- and we just removed the dummy command added by
338 edit_and_execute_command (), we need to check whether or not we
339 just removed the last command in the history and need to back
340 the pointer up. remember_on_history is off because we're running
341 in parse_and_execute(). */
342 if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
343 last_hist = histbeg = --histend;
344 }
345
346 /* We print error messages for line specifications out of range. */
347 if ((histbeg < 0) || (histend < 0))
348 {
349 sh_erange ((char *)NULL, _("history specification"));
350 return (EXECUTION_FAILURE);
351 }
352
353 if (histend < histbeg)
354 {
355 i = histend;
356 histend = histbeg;
357 histbeg = i;
358
359 reverse = 1;
360 }
361
362 if (listing)
363 stream = stdout;
364 else
365 {
366 numbering = 0;
367 stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
368 if (stream == 0)
369 {
370 builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
371 FREE (fn);
372 return (EXECUTION_FAILURE);
373 }
374 }
375
376 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
377 {
378 QUIT;
379 if (numbering)
380 fprintf (stream, "%d", i + history_base);
381 if (listing)
382 {
383 if (posixly_correct)
384 fputs ("\t", stream);
385 else
386 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
387 }
388 fprintf (stream, "%s\n", histline (i));
389 }
390
391 if (listing)
392 return (sh_chkwrite (EXECUTION_SUCCESS));
393
394 fflush (stream);
395 if (ferror (stream))
396 {
397 sh_wrerror ();
398 fclose (stream);
399 return (EXECUTION_FAILURE);
400 }
401 fclose (stream);
402
403 /* Now edit the file of commands. */
404 if (ename)
405 {
406 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
407 sprintf (command, "%s %s", ename, fn);
408 }
409 else
410 {
411 fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
412 command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
413 sprintf (command, "%s %s", fcedit, fn);
414 }
415 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
416 if (retval != EXECUTION_SUCCESS)
417 {
418 unlink (fn);
419 free (fn);
420 return (EXECUTION_FAILURE);
421 }
422
423 /* Make sure parse_and_execute doesn't turn this off, even though a
424 call to parse_and_execute farther up the function call stack (e.g.,
425 if this is called by vi_edit_and_execute_command) may have already
426 called bash_history_disable. */
427 remember_on_history = 1;
428
429 /* Turn on the `v' flag while fc_execute_file runs so the commands
430 will be echoed as they are read by the parser. */
431 begin_unwind_frame ("fc builtin");
432 add_unwind_protect ((Function *)xfree, fn);
433 add_unwind_protect (unlink, fn);
434 unwind_protect_int (echo_input_at_read);
435 echo_input_at_read = 1;
436
437 retval = fc_execute_file (fn);
438
439 run_unwind_frame ("fc builtin");
440
441 return (retval);
442 }
443
444 /* Return 1 if LIST->word->word is a legal number for fc's use. */
445 static int
446 fc_number (list)
447 WORD_LIST *list;
448 {
449 char *s;
450
451 if (list == 0)
452 return 0;
453 s = list->word->word;
454 if (*s == '-')
455 s++;
456 return (legal_number (s, (intmax_t *)NULL));
457 }
458
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. */
462 static int
463 fc_gethnum (command, hlist)
464 char *command;
465 HIST_ENTRY **hlist;
466 {
467 int sign, n, clen, rh;
468 register int i, j;
469 register char *s;
470
471 sign = 1;
472 /* Count history elements. */
473 for (i = 0; hlist[i]; i++);
474
475 /* With the Bash implementation of history, the current command line
476 ("fc blah..." and so on) is already part of the history list by
477 the time we get to this point. This just skips over that command
478 and makes the last command that this deals with be the last command
479 the user entered before the fc. We need to check whether the
480 line was actually added (HISTIGNORE may have caused it to not be),
481 so we check hist_last_line_added. This needs to agree with the
482 calculation of last_hist in fc_builtin above. */
483 /* Even though command substitution through parse_and_execute turns off
484 remember_on_history, command substitution in a shell when set -o history
485 has been enabled (interactive or not) should use it in the last_hist
486 calculation as if it were on. */
487 rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
488 i -= rh + hist_last_line_added;
489
490 /* No specification defaults to most recent command. */
491 if (command == NULL)
492 return (i);
493
494 /* Otherwise, there is a specification. It can be a number relative to
495 the current position, or an absolute history number. */
496 s = command;
497
498 /* Handle possible leading minus sign. */
499 if (s && (*s == '-'))
500 {
501 sign = -1;
502 s++;
503 }
504
505 if (s && DIGIT(*s))
506 {
507 n = atoi (s);
508 n *= sign;
509
510 /* If the value is negative or zero, then it is an offset from
511 the current history item. */
512 if (n < 0)
513 {
514 n += i + 1;
515 return (n < 0 ? 0 : n);
516 }
517 else if (n == 0)
518 return (i);
519 else
520 {
521 n -= history_base;
522 return (i < n ? i : n);
523 }
524 }
525
526 clen = strlen (command);
527 for (j = i; j >= 0; j--)
528 {
529 if (STREQN (command, histline (j), clen))
530 return (j);
531 }
532 return (-1);
533 }
534
535 /* Locate the most recent history line which begins with
536 COMMAND in HLIST, and return a malloc()'ed copy of it. */
537 static char *
538 fc_gethist (command, hlist)
539 char *command;
540 HIST_ENTRY **hlist;
541 {
542 int i;
543
544 if (hlist == 0)
545 return ((char *)NULL);
546
547 i = fc_gethnum (command, hlist);
548
549 if (i >= 0)
550 return (savestring (histline (i)));
551 else
552 return ((char *)NULL);
553 }
554
555 #ifdef INCLUDE_UNUSED
556 /* Read the edited history lines from STREAM and return them
557 one at a time. This can read unlimited length lines. The
558 caller should free the storage. */
559 static char *
560 fc_readline (stream)
561 FILE *stream;
562 {
563 register int c;
564 int line_len = 0, lindex = 0;
565 char *line = (char *)NULL;
566
567 while ((c = getc (stream)) != EOF)
568 {
569 if ((lindex + 2) >= line_len)
570 line = (char *)xrealloc (line, (line_len += 128));
571
572 if (c == '\n')
573 {
574 line[lindex++] = '\n';
575 line[lindex++] = '\0';
576 return (line);
577 }
578 else
579 line[lindex++] = c;
580 }
581
582 if (!lindex)
583 {
584 if (line)
585 free (line);
586
587 return ((char *)NULL);
588 }
589
590 if (lindex + 2 >= line_len)
591 line = (char *)xrealloc (line, lindex + 3);
592
593 line[lindex++] = '\n'; /* Finish with newline if none in file */
594 line[lindex++] = '\0';
595 return (line);
596 }
597 #endif
598
599 /* Perform the SUBS on COMMAND.
600 SUBS is a list of substitutions, and COMMAND is a simple string.
601 Return a pointer to a malloc'ed string which contains the substituted
602 command. */
603 static char *
604 fc_dosubs (command, subs)
605 char *command;
606 REPL *subs;
607 {
608 register char *new, *t;
609 register REPL *r;
610
611 for (new = savestring (command), r = subs; r; r = r->next)
612 {
613 t = strsub (new, r->pat, r->rep, 1);
614 free (new);
615 new = t;
616 }
617 return (new);
618 }
619
620 /* Use `command' to replace the last entry in the history list, which,
621 by this time, is `fc blah...'. The intent is that the new command
622 become the history entry, and that `fc' should never appear in the
623 history list. This way you can do `r' to your heart's content. */
624 static void
625 fc_replhist (command)
626 char *command;
627 {
628 int n;
629
630 if (command == 0 || *command == '\0')
631 return;
632
633 n = strlen (command);
634 if (command[n - 1] == '\n')
635 command[n - 1] = '\0';
636
637 if (command && *command)
638 {
639 bash_delete_last_history ();
640 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
641 }
642 }
643
644 #ifdef INCLUDE_UNUSED
645 /* Add LINE to the history, after removing a single trailing newline. */
646 static void
647 fc_addhist (line)
648 char *line;
649 {
650 register int n;
651
652 if (line == 0 || *line == 0)
653 return;
654
655 n = strlen (line);
656
657 if (line[n - 1] == '\n')
658 line[n - 1] = '\0';
659
660 if (line && *line)
661 maybe_add_history (line); /* Obeys HISTCONTROL setting. */
662 }
663 #endif
664
665 #endif /* HISTORY */