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