]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/fc.def
Imported from ../bash-2.05b.tar.gz.
[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-2002 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 it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
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
16 for more details.
17
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, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22 $PRODUCES fc.c
23
24 $BUILTIN fc
25 $FUNCTION fc_builtin
26 $DEPENDS_ON HISTORY
27 $SHORT_DOC fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
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 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
35 then vi.
36
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).
40
41 With the `fc -s [pat=rep ...] [command]' format, the 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 $END
48
49 #include <config.h>
50
51 #if defined (HISTORY)
52 #ifndef _MINIX
53 # include <sys/param.h>
54 #endif
55 #include "../bashtypes.h"
56 #include "posixstat.h"
57 #ifndef _MINIX
58 # include <sys/file.h>
59 #endif
60
61 #if defined (HAVE_UNISTD_H)
62 # include <unistd.h>
63 #endif
64
65 #include <stdio.h>
66 #include <chartypes.h>
67
68 #include "../bashansi.h"
69 #include <errno.h>
70
71 #include "../shell.h"
72 #include "../builtins.h"
73 #include "../flags.h"
74 #include "../bashhist.h"
75 #include "maxpath.h"
76 #include <readline/history.h>
77 #include "bashgetopt.h"
78 #include "common.h"
79
80 #if !defined (errno)
81 extern int errno;
82 #endif /* !errno */
83
84 extern int echo_input_at_read;
85 extern int current_command_line_count;
86 extern int literal_history;
87
88 extern int unlink __P((const char *));
89
90 extern FILE *sh_mktmpfp __P((char *, int, char **));
91
92 /* **************************************************************** */
93 /* */
94 /* The K*rn shell style fc command (Fix Command) */
95 /* */
96 /* **************************************************************** */
97
98 /* fc builtin command (fix command) for Bash for those who
99 like K*rn-style history better than csh-style.
100
101 fc [-e ename] [-nlr] [first] [last]
102
103 FIRST and LAST can be numbers specifying the range, or FIRST can be
104 a string, which means the most recent command beginning with that
105 string.
106
107 -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
108 then the editor which corresponds to the current readline editing
109 mode, then vi.
110
111 -l means list lines instead of editing.
112 -n means no line numbers listed.
113 -r means reverse the order of the lines (making it newest listed first).
114
115 fc -e - [pat=rep ...] [command]
116 fc -s [pat=rep ...] [command]
117
118 Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
119 */
120
121 /* Data structure describing a list of global replacements to perform. */
122 typedef struct repl {
123 struct repl *next;
124 char *pat;
125 char *rep;
126 } REPL;
127
128 /* Accessors for HIST_ENTRY lists that are called HLIST. */
129 #define histline(i) (hlist[(i)]->line)
130 #define histdata(i) (hlist[(i)]->data)
131
132 #define FREE_RLIST() \
133 do { \
134 for (rl = rlist; rl; ) { \
135 REPL *r; \
136 r = rl->next; \
137 if (rl->pat) \
138 free (rl->pat); \
139 if (rl->rep) \
140 free (rl->rep); \
141 free (rl); \
142 rl = r; \
143 } \
144 } while (0)
145
146 static char *fc_dosubs __P((char *, REPL *));
147 static char *fc_gethist __P((char *, HIST_ENTRY **));
148 static int fc_gethnum __P((char *, HIST_ENTRY **));
149 static int fc_number __P((WORD_LIST *));
150 static void fc_replhist __P((char *));
151 #ifdef INCLUDE_UNUSED
152 static char *fc_readline __P((FILE *));
153 static void fc_addhist __P((char *));
154 #endif
155
156 /* String to execute on a file that we want to edit. */
157 #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
158
159 int
160 fc_builtin (list)
161 WORD_LIST *list;
162 {
163 register int i;
164 register char *sep;
165 int numbering, reverse, listing, execute;
166 int histbeg, histend, last_hist, retval, opt;
167 FILE *stream;
168 REPL *rlist, *rl;
169 char *ename, *command, *newcom;
170 HIST_ENTRY **hlist;
171 char *fn;
172
173 numbering = 1;
174 reverse = listing = execute = 0;
175 ename = (char *)NULL;
176
177 /* Parse out the options and set which of the two forms we're in. */
178 reset_internal_getopt ();
179 lcurrent = list; /* XXX */
180 while (fc_number (loptend = lcurrent) == 0 &&
181 (opt = internal_getopt (list, ":e:lnrs")) != -1)
182 {
183 switch (opt)
184 {
185 case 'n':
186 numbering = 0;
187 break;
188
189 case 'l':
190 listing = 1;
191 break;
192
193 case 'r':
194 reverse = 1;
195 break;
196
197 case 's':
198 execute = 1;
199 break;
200
201 case 'e':
202 ename = list_optarg;
203 break;
204
205 default:
206 builtin_usage ();
207 return (EX_USAGE);
208 }
209 }
210
211 list = loptend;
212
213 if (ename && (*ename == '-') && (ename[1] == '\0'))
214 execute = 1;
215
216 /* The "execute" form of the command (re-run, with possible string
217 substitutions). */
218 if (execute)
219 {
220 rlist = (REPL *)NULL;
221 while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
222 {
223 *sep++ = '\0';
224 rl = (REPL *)xmalloc (sizeof (REPL));
225 rl->next = (REPL *)NULL;
226 rl->pat = savestring (list->word->word);
227 rl->rep = savestring (sep);
228
229 if (rlist == NULL)
230 rlist = rl;
231 else
232 {
233 rl->next = rlist;
234 rlist = rl;
235 }
236 list = list->next;
237 }
238
239 /* If we have a list of substitutions to do, then reverse it
240 to get the replacements in the proper order. */
241
242 rlist = REVERSE_LIST (rlist, REPL *);
243
244 hlist = history_list ();
245
246 /* If we still have something in list, it is a command spec.
247 Otherwise, we use the most recent command in time. */
248 command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
249
250 if (command == NULL)
251 {
252 builtin_error ("no command found");
253 if (rlist)
254 FREE_RLIST ();
255
256 return (EXECUTION_FAILURE);
257 }
258
259 if (rlist)
260 {
261 newcom = fc_dosubs (command, rlist);
262 free (command);
263 FREE_RLIST ();
264 command = newcom;
265 }
266
267 fprintf (stderr, "%s\n", command);
268 fc_replhist (command); /* replace `fc -s' with command */
269 return (parse_and_execute (command, "fc", SEVAL_NOHIST));
270 }
271
272 /* This is the second form of the command (the list-or-edit-and-rerun
273 form). */
274 hlist = history_list ();
275 if (hlist == 0)
276 return (EXECUTION_SUCCESS);
277 for (i = 0; hlist[i]; i++);
278
279 /* With the Bash implementation of history, the current command line
280 ("fc blah..." and so on) is already part of the history list by
281 the time we get to this point. This just skips over that command
282 and makes the last command that this deals with be the last command
283 the user entered before the fc. We need to check whether the
284 line was actually added (HISTIGNORE may have caused it to not be),
285 so we check hist_last_line_added. */
286
287 last_hist = i - 1 - hist_last_line_added;
288
289 if (list)
290 {
291 histbeg = fc_gethnum (list->word->word, hlist);
292 list = list->next;
293
294 if (list)
295 histend = fc_gethnum (list->word->word, hlist);
296 else
297 histend = listing ? last_hist : histbeg;
298 }
299 else
300 {
301 /* The default for listing is the last 16 history items. */
302 if (listing)
303 {
304 histend = last_hist;
305 histbeg = histend - 16;
306 if (histbeg < 0)
307 histbeg = 0;
308 }
309 else
310 /* For editing, it is the last history command. */
311 histbeg = histend = last_hist;
312 }
313
314 /* We print error messages for line specifications out of range. */
315 if ((histbeg < 0) || (histend < 0))
316 {
317 sh_erange ((char *)NULL, "history specification");
318 return (EXECUTION_FAILURE);
319 }
320
321 if (histend < histbeg)
322 {
323 i = histend;
324 histend = histbeg;
325 histbeg = i;
326
327 reverse = 1;
328 }
329
330 if (listing)
331 stream = stdout;
332 else
333 {
334 numbering = 0;
335 stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
336 if (stream == 0)
337 {
338 builtin_error ("cannot open temp file %s", fn ? fn : "");
339 FREE (fn);
340 return (EXECUTION_FAILURE);
341 }
342 }
343
344 for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
345 {
346 QUIT;
347 if (numbering)
348 fprintf (stream, "%d", i + history_base);
349 if (listing)
350 fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
351 fprintf (stream, "%s\n", histline (i));
352 }
353
354 if (listing)
355 return (EXECUTION_SUCCESS);
356
357 fclose (stream);
358
359 /* Now edit the file of commands. */
360 if (ename)
361 {
362 command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
363 sprintf (command, "%s %s", ename, fn);
364 }
365 else
366 {
367 command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn));
368 sprintf (command, "%s %s", FC_EDIT_COMMAND, fn);
369 }
370 retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
371 if (retval != EXECUTION_SUCCESS)
372 {
373 unlink (fn);
374 free (fn);
375 return (EXECUTION_FAILURE);
376 }
377
378 /* Make sure parse_and_execute doesn't turn this off, even though a
379 call to parse_and_execute farther up the function call stack (e.g.,
380 if this is called by vi_edit_and_execute_command) may have already
381 called bash_history_disable. */
382 remember_on_history = 1;
383
384 /* Turn on the `v' flag while fc_execute_file runs so the commands
385 will be echoed as they are read by the parser. */
386 begin_unwind_frame ("fc builtin");
387 add_unwind_protect ((Function *)xfree, fn);
388 add_unwind_protect (unlink, fn);
389 unwind_protect_int (echo_input_at_read);
390 echo_input_at_read = 1;
391
392 retval = fc_execute_file (fn);
393
394 run_unwind_frame ("fc builtin");
395
396 return (retval);
397 }
398
399 /* Return 1 if LIST->word->word is a legal number for fc's use. */
400 static int
401 fc_number (list)
402 WORD_LIST *list;
403 {
404 char *s;
405
406 if (list == 0)
407 return 0;
408 s = list->word->word;
409 if (*s == '-')
410 s++;
411 return (legal_number (s, (intmax_t *)NULL));
412 }
413
414 /* Return an absolute index into HLIST which corresponds to COMMAND. If
415 COMMAND is a number, then it was specified in relative terms. If it
416 is a string, then it is the start of a command line present in HLIST. */
417 static int
418 fc_gethnum (command, hlist)
419 char *command;
420 HIST_ENTRY **hlist;
421 {
422 int sign = 1, n, clen;
423 register int i, j;
424 register char *s;
425
426 /* Count history elements. */
427 for (i = 0; hlist[i]; i++);
428
429 /* With the Bash implementation of history, the current command line
430 ("fc blah..." and so on) is already part of the history list by
431 the time we get to this point. This just skips over that command
432 and makes the last command that this deals with be the last command
433 the user entered before the fc. We need to check whether the
434 line was actually added (HISTIGNORE may have caused it to not be),
435 so we check hist_last_line_added. */
436 i -= 1 + hist_last_line_added;
437
438 /* No specification defaults to most recent command. */
439 if (command == NULL)
440 return (i);
441
442 /* Otherwise, there is a specification. It can be a number relative to
443 the current position, or an absolute history number. */
444 s = command;
445
446 /* Handle possible leading minus sign. */
447 if (s && (*s == '-'))
448 {
449 sign = -1;
450 s++;
451 }
452
453 if (s && DIGIT(*s))
454 {
455 n = atoi (s);
456 n *= sign;
457
458 /* If the value is negative or zero, then it is an offset from
459 the current history item. */
460 if (n < 0)
461 {
462 n += i + 1;
463 return (n < 0 ? 0 : n);
464 }
465 else if (n == 0)
466 return (i);
467 else
468 {
469 n -= history_base;
470 return (i < n ? i : n);
471 }
472 }
473
474 clen = strlen (command);
475 for (j = i; j >= 0; j--)
476 {
477 if (STREQN (command, histline (j), clen))
478 return (j);
479 }
480 return (-1);
481 }
482
483 /* Locate the most recent history line which begins with
484 COMMAND in HLIST, and return a malloc()'ed copy of it. */
485 static char *
486 fc_gethist (command, hlist)
487 char *command;
488 HIST_ENTRY **hlist;
489 {
490 int i;
491
492 if (!hlist)
493 return ((char *)NULL);
494
495 i = fc_gethnum (command, hlist);
496
497 if (i >= 0)
498 return (savestring (histline (i)));
499 else
500 return ((char *)NULL);
501 }
502
503 #ifdef INCLUDE_UNUSED
504 /* Read the edited history lines from STREAM and return them
505 one at a time. This can read unlimited length lines. The
506 caller should free the storage. */
507 static char *
508 fc_readline (stream)
509 FILE *stream;
510 {
511 register int c;
512 int line_len = 0, lindex = 0;
513 char *line = (char *)NULL;
514
515 while ((c = getc (stream)) != EOF)
516 {
517 if ((lindex + 2) >= line_len)
518 line = (char *)xrealloc (line, (line_len += 128));
519
520 if (c == '\n')
521 {
522 line[lindex++] = '\n';
523 line[lindex++] = '\0';
524 return (line);
525 }
526 else
527 line[lindex++] = c;
528 }
529
530 if (!lindex)
531 {
532 if (line)
533 free (line);
534
535 return ((char *)NULL);
536 }
537
538 if (lindex + 2 >= line_len)
539 line = (char *)xrealloc (line, lindex + 3);
540
541 line[lindex++] = '\n'; /* Finish with newline if none in file */
542 line[lindex++] = '\0';
543 return (line);
544 }
545 #endif
546
547 /* Perform the SUBS on COMMAND.
548 SUBS is a list of substitutions, and COMMAND is a simple string.
549 Return a pointer to a malloc'ed string which contains the substituted
550 command. */
551 static char *
552 fc_dosubs (command, subs)
553 char *command;
554 REPL *subs;
555 {
556 register char *new, *t;
557 register REPL *r;
558
559 for (new = savestring (command), r = subs; r; r = r->next)
560 {
561 t = strsub (new, r->pat, r->rep, 1);
562 free (new);
563 new = t;
564 }
565 return (new);
566 }
567
568 /* Use `command' to replace the last entry in the history list, which,
569 by this time, is `fc blah...'. The intent is that the new command
570 become the history entry, and that `fc' should never appear in the
571 history list. This way you can do `r' to your heart's content. */
572 static void
573 fc_replhist (command)
574 char *command;
575 {
576 register int i;
577 HIST_ENTRY **hlist, *histent, *discard;
578 int n;
579
580 if (command == 0 || *command == '\0')
581 return;
582
583 hlist = history_list ();
584
585 if (hlist == NULL)
586 return;
587
588 for (i = 0; hlist[i]; i++);
589 i--;
590
591 /* History_get () takes a parameter that should be
592 offset by history_base. */
593
594 histent = history_get (history_base + i); /* Don't free this */
595 if (histent == NULL)
596 return;
597
598 n = strlen (command);
599
600 if (command[n - 1] == '\n')
601 command[n - 1] = '\0';
602
603 if (command && *command)
604 {
605 discard = remove_history (i);
606 if (discard)
607 {
608 FREE (discard->line);
609 free ((char *) discard);
610 }
611 maybe_add_history (command); /* Obeys HISTCONTROL setting. */
612 }
613 }
614
615 #ifdef INCLUDE_UNUSED
616 /* Add LINE to the history, after removing a single trailing newline. */
617 static void
618 fc_addhist (line)
619 char *line;
620 {
621 register int n;
622
623 n = strlen (line);
624
625 if (line[n - 1] == '\n')
626 line[n - 1] = '\0';
627
628 if (line && *line)
629 maybe_add_history (line);
630 }
631 #endif
632
633 #endif /* HISTORY */