]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is fc.def, from which is created fc.c. |
2 | It implements the builtin "fc" in Bash. | |
3 | ||
95732b49 | 4 | Copyright (C) 1987-2005 Free Software Foundation, Inc. |
726f6388 JA |
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 | |
bb70624e | 10 | Software Foundation; either version 2, or (at your option) any later |
726f6388 JA |
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 | |
bb70624e | 20 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
726f6388 JA |
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] | |
b72432fd | 28 | fc is used to list or edit and re-execute commands from the history list. |
726f6388 JA |
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, | |
b72432fd | 34 | then vi. |
726f6388 JA |
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 | ||
ccc6cda3 JA |
48 | #include <config.h> |
49 | ||
726f6388 | 50 | #if defined (HISTORY) |
cce855bc JA |
51 | #ifndef _MINIX |
52 | # include <sys/param.h> | |
53 | #endif | |
d166f048 | 54 | #include "../bashtypes.h" |
bb70624e | 55 | #include "posixstat.h" |
b80f6443 | 56 | #if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H) |
cce855bc JA |
57 | # include <sys/file.h> |
58 | #endif | |
ccc6cda3 JA |
59 | |
60 | #if defined (HAVE_UNISTD_H) | |
61 | # include <unistd.h> | |
62 | #endif | |
63 | ||
64 | #include <stdio.h> | |
f73dda09 | 65 | #include <chartypes.h> |
ccc6cda3 JA |
66 | |
67 | #include "../bashansi.h" | |
b80f6443 | 68 | #include "../bashintl.h" |
726f6388 | 69 | #include <errno.h> |
ccc6cda3 JA |
70 | |
71 | #include "../shell.h" | |
726f6388 JA |
72 | #include "../builtins.h" |
73 | #include "../flags.h" | |
726f6388 | 74 | #include "../bashhist.h" |
bb70624e | 75 | #include "maxpath.h" |
726f6388 JA |
76 | #include <readline/history.h> |
77 | #include "bashgetopt.h" | |
ccc6cda3 | 78 | #include "common.h" |
726f6388 | 79 | |
726f6388 JA |
80 | #if !defined (errno) |
81 | extern int errno; | |
82 | #endif /* !errno */ | |
83 | ||
d166f048 JA |
84 | extern int current_command_line_count; |
85 | extern int literal_history; | |
95732b49 | 86 | extern int posixly_correct; |
726f6388 | 87 | |
f73dda09 | 88 | extern int unlink __P((const char *)); |
726f6388 | 89 | |
28ef6c31 | 90 | extern FILE *sh_mktmpfp __P((char *, int, char **)); |
95732b49 | 91 | extern int delete_last_history __P((void)); |
d166f048 | 92 | |
726f6388 JA |
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 | ||
726f6388 JA |
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 | ||
726f6388 JA |
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 | ||
f73dda09 JA |
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 | ||
726f6388 JA |
157 | /* String to execute on a file that we want to edit. */ |
158 | #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}" | |
95732b49 JA |
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 | |
726f6388 JA |
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; | |
b72432fd | 172 | int histbeg, histend, last_hist, retval, opt; |
726f6388 | 173 | FILE *stream; |
ccc6cda3 | 174 | REPL *rlist, *rl; |
95732b49 | 175 | char *ename, *command, *newcom, *fcedit; |
726f6388 | 176 | HIST_ENTRY **hlist; |
28ef6c31 | 177 | char *fn; |
726f6388 JA |
178 | |
179 | numbering = 1; | |
180 | reverse = listing = execute = 0; | |
ccc6cda3 | 181 | ename = (char *)NULL; |
726f6388 JA |
182 | |
183 | /* Parse out the options and set which of the two forms we're in. */ | |
ccc6cda3 JA |
184 | reset_internal_getopt (); |
185 | lcurrent = list; /* XXX */ | |
186 | while (fc_number (loptend = lcurrent) == 0 && | |
187 | (opt = internal_getopt (list, ":e:lnrs")) != -1) | |
726f6388 | 188 | { |
ccc6cda3 JA |
189 | switch (opt) |
190 | { | |
191 | case 'n': | |
192 | numbering = 0; | |
193 | break; | |
726f6388 | 194 | |
ccc6cda3 JA |
195 | case 'l': |
196 | listing = 1; | |
197 | break; | |
726f6388 | 198 | |
ccc6cda3 JA |
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); | |
726f6388 | 214 | } |
726f6388 JA |
215 | } |
216 | ||
ccc6cda3 JA |
217 | list = loptend; |
218 | ||
726f6388 JA |
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 | { | |
ccc6cda3 | 226 | rlist = (REPL *)NULL; |
726f6388 JA |
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 | ||
7117c2d2 | 248 | rlist = REVERSE_LIST (rlist, REPL *); |
726f6388 JA |
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. */ | |
ccc6cda3 | 254 | command = fc_gethist (list ? list->word->word : (char *)NULL, hlist); |
726f6388 JA |
255 | |
256 | if (command == NULL) | |
257 | { | |
b80f6443 | 258 | builtin_error (_("no command found")); |
726f6388 JA |
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 | ||
ccc6cda3 JA |
273 | fprintf (stderr, "%s\n", command); |
274 | fc_replhist (command); /* replace `fc -s' with command */ | |
d166f048 | 275 | return (parse_and_execute (command, "fc", SEVAL_NOHIST)); |
726f6388 JA |
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 | |
d166f048 JA |
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. */ | |
726f6388 | 292 | |
95732b49 JA |
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 | ||
d166f048 | 298 | last_hist = i - 1 - hist_last_line_added; |
726f6388 JA |
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 | |
ccc6cda3 | 308 | histend = listing ? last_hist : histbeg; |
726f6388 JA |
309 | } |
310 | else | |
311 | { | |
312 | /* The default for listing is the last 16 history items. */ | |
313 | if (listing) | |
314 | { | |
315 | histend = last_hist; | |
95732b49 | 316 | histbeg = histend - 16 + 1; /* +1 because loop below uses >= */ |
726f6388 JA |
317 | if (histbeg < 0) |
318 | histbeg = 0; | |
319 | } | |
320 | else | |
ccc6cda3 JA |
321 | /* For editing, it is the last history command. */ |
322 | histbeg = histend = last_hist; | |
726f6388 JA |
323 | } |
324 | ||
325 | /* We print error messages for line specifications out of range. */ | |
7117c2d2 | 326 | if ((histbeg < 0) || (histend < 0)) |
726f6388 | 327 | { |
b80f6443 | 328 | sh_erange ((char *)NULL, _("history specification")); |
726f6388 JA |
329 | return (EXECUTION_FAILURE); |
330 | } | |
331 | ||
332 | if (histend < histbeg) | |
333 | { | |
ccc6cda3 | 334 | i = histend; |
726f6388 | 335 | histend = histbeg; |
ccc6cda3 JA |
336 | histbeg = i; |
337 | ||
726f6388 JA |
338 | reverse = 1; |
339 | } | |
340 | ||
341 | if (listing) | |
342 | stream = stdout; | |
343 | else | |
344 | { | |
345 | numbering = 0; | |
28ef6c31 | 346 | stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn); |
ccc6cda3 | 347 | if (stream == 0) |
726f6388 | 348 | { |
b80f6443 | 349 | builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno)); |
28ef6c31 | 350 | FREE (fn); |
726f6388 JA |
351 | return (EXECUTION_FAILURE); |
352 | } | |
353 | } | |
354 | ||
ccc6cda3 | 355 | for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++) |
726f6388 | 356 | { |
ccc6cda3 JA |
357 | QUIT; |
358 | if (numbering) | |
359 | fprintf (stream, "%d", i + history_base); | |
360 | if (listing) | |
95732b49 JA |
361 | { |
362 | if (posixly_correct) | |
363 | fputs ("\t", stream); | |
364 | else | |
365 | fprintf (stream, "\t%c", histdata (i) ? '*' : ' '); | |
366 | } | |
ccc6cda3 | 367 | fprintf (stream, "%s\n", histline (i)); |
726f6388 JA |
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 | { | |
95732b49 JA |
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); | |
726f6388 | 386 | } |
d166f048 | 387 | retval = parse_and_execute (command, "fc", SEVAL_NOHIST); |
ccc6cda3 JA |
388 | if (retval != EXECUTION_SUCCESS) |
389 | { | |
390 | unlink (fn); | |
28ef6c31 | 391 | free (fn); |
ccc6cda3 JA |
392 | return (EXECUTION_FAILURE); |
393 | } | |
726f6388 | 394 | |
d166f048 JA |
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; | |
726f6388 | 400 | |
d166f048 | 401 | /* Turn on the `v' flag while fc_execute_file runs so the commands |
726f6388 JA |
402 | will be echoed as they are read by the parser. */ |
403 | begin_unwind_frame ("fc builtin"); | |
28ef6c31 | 404 | add_unwind_protect ((Function *)xfree, fn); |
726f6388 JA |
405 | add_unwind_protect (unlink, fn); |
406 | unwind_protect_int (echo_input_at_read); | |
407 | echo_input_at_read = 1; | |
408 | ||
d166f048 | 409 | retval = fc_execute_file (fn); |
726f6388 JA |
410 | |
411 | run_unwind_frame ("fc builtin"); | |
412 | ||
413 | return (retval); | |
414 | } | |
415 | ||
ccc6cda3 JA |
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++; | |
7117c2d2 | 428 | return (legal_number (s, (intmax_t *)NULL)); |
ccc6cda3 JA |
429 | } |
430 | ||
726f6388 JA |
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 | |
d166f048 JA |
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; | |
726f6388 JA |
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 | ||
f73dda09 | 470 | if (s && DIGIT(*s)) |
726f6388 JA |
471 | { |
472 | n = atoi (s); | |
473 | n *= sign; | |
474 | ||
726f6388 JA |
475 | /* If the value is negative or zero, then it is an offset from |
476 | the current history item. */ | |
477 | if (n < 0) | |
7117c2d2 JA |
478 | { |
479 | n += i + 1; | |
480 | return (n < 0 ? 0 : n); | |
481 | } | |
726f6388 JA |
482 | else if (n == 0) |
483 | return (i); | |
484 | else | |
7117c2d2 JA |
485 | { |
486 | n -= history_base; | |
487 | return (i < n ? i : n); | |
488 | } | |
726f6388 JA |
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 | ||
95732b49 | 509 | if (hlist == 0) |
726f6388 JA |
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 | ||
f73dda09 | 520 | #ifdef INCLUDE_UNUSED |
726f6388 JA |
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) | |
f73dda09 | 535 | line = (char *)xrealloc (line, (line_len += 128)); |
726f6388 JA |
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 | } | |
f73dda09 | 562 | #endif |
726f6388 JA |
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 | { | |
ccc6cda3 | 573 | register char *new, *t; |
726f6388 JA |
574 | register REPL *r; |
575 | ||
ccc6cda3 | 576 | for (new = savestring (command), r = subs; r; r = r->next) |
726f6388 | 577 | { |
ccc6cda3 | 578 | t = strsub (new, r->pat, r->rep, 1); |
726f6388 JA |
579 | free (new); |
580 | new = t; | |
581 | } | |
582 | return (new); | |
583 | } | |
584 | ||
726f6388 JA |
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 | { | |
726f6388 JA |
593 | int n; |
594 | ||
ccc6cda3 | 595 | if (command == 0 || *command == '\0') |
726f6388 JA |
596 | return; |
597 | ||
726f6388 | 598 | n = strlen (command); |
726f6388 JA |
599 | if (command[n - 1] == '\n') |
600 | command[n - 1] = '\0'; | |
601 | ||
602 | if (command && *command) | |
603 | { | |
95732b49 | 604 | delete_last_history (); |
726f6388 JA |
605 | maybe_add_history (command); /* Obeys HISTCONTROL setting. */ |
606 | } | |
607 | } | |
608 | ||
f73dda09 | 609 | #ifdef INCLUDE_UNUSED |
726f6388 JA |
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 | ||
95732b49 JA |
617 | if (line == 0 || *line == 0) |
618 | return; | |
619 | ||
726f6388 JA |
620 | n = strlen (line); |
621 | ||
622 | if (line[n - 1] == '\n') | |
623 | line[n - 1] = '\0'; | |
624 | ||
625 | if (line && *line) | |
95732b49 | 626 | maybe_add_history (line); /* Obeys HISTCONTROL setting. */ |
726f6388 | 627 | } |
f73dda09 JA |
628 | #endif |
629 | ||
726f6388 | 630 | #endif /* HISTORY */ |