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