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