Imported from ../bash-2.05b.tar.gz.
[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-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 */