Import readline 7.0 (patch 5)
[external/binutils.git] / readline / histfile.c
1 /* histfile.c - functions to manipulate the history file. */
2
3 /* Copyright (C) 1989-2016 Free Software Foundation, Inc.
4
5    This file contains the GNU History Library (History), a set of
6    routines for managing the text of previously typed lines.
7
8    History is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
12
13    History is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with History.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* The goal is to make the implementation transparent, so that you
23    don't have to know what data types are used, just what functions
24    you can call.  I think I have done that. */
25
26 #define READLINE_LIBRARY
27
28 #if defined (__TANDEM)
29 #  include <floss.h>
30 #endif
31
32 #if defined (HAVE_CONFIG_H)
33 #  include <config.h>
34 #endif
35
36 #include <stdio.h>
37
38 #if defined (HAVE_LIMITS_H)
39 #  include <limits.h>
40 #endif
41
42 #include <sys/types.h>
43 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
44 #  include <sys/file.h>
45 #endif
46 #include "posixstat.h"
47 #include <fcntl.h>
48
49 #if defined (HAVE_STDLIB_H)
50 #  include <stdlib.h>
51 #else
52 #  include "ansi_stdlib.h"
53 #endif /* HAVE_STDLIB_H */
54
55 #if defined (HAVE_UNISTD_H)
56 #  include <unistd.h>
57 #endif
58
59 #include <ctype.h>
60
61 #if defined (__EMX__)
62 #  undef HAVE_MMAP
63 #endif
64
65 #ifdef HISTORY_USE_MMAP
66 #  include <sys/mman.h>
67
68 #  ifdef MAP_FILE
69 #    define MAP_RFLAGS  (MAP_FILE|MAP_PRIVATE)
70 #    define MAP_WFLAGS  (MAP_FILE|MAP_SHARED)
71 #  else
72 #    define MAP_RFLAGS  MAP_PRIVATE
73 #    define MAP_WFLAGS  MAP_SHARED
74 #  endif
75
76 #  ifndef MAP_FAILED
77 #    define MAP_FAILED  ((void *)-1)
78 #  endif
79
80 #endif /* HISTORY_USE_MMAP */
81
82 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
83    on win 95/98/nt), we want to open files with O_BINARY mode so that there
84    is no \n -> \r\n conversion performed.  On other systems, we don't want to
85    mess around with O_BINARY at all, so we ensure that it's defined to 0. */
86 #if defined (__EMX__) || defined (__CYGWIN__)
87 #  ifndef O_BINARY
88 #    define O_BINARY 0
89 #  endif
90 #else /* !__EMX__ && !__CYGWIN__ */
91 #  undef O_BINARY
92 #  define O_BINARY 0
93 #endif /* !__EMX__ && !__CYGWIN__ */
94
95 #include <errno.h>
96 #if !defined (errno)
97 extern int errno;
98 #endif /* !errno */
99
100 #include "history.h"
101 #include "histlib.h"
102
103 #include "rlshell.h"
104 #include "xmalloc.h"
105
106 #if !defined (PATH_MAX)
107 #  define PATH_MAX      1024    /* default */
108 #endif
109
110 extern void _hs_append_history_line PARAMS((int, const char *));
111
112 /* history file version; currently unused */
113 int history_file_version = 1;
114
115 /* If non-zero, we write timestamps to the history file in history_do_write() */
116 int history_write_timestamps = 0;
117
118 /* If non-zero, we assume that a history file that starts with a timestamp
119    uses timestamp-delimited entries and can include multi-line history
120    entries. Used by read_history_range */
121 int history_multiline_entries = 0;
122
123 /* Immediately after a call to read_history() or read_history_range(), this
124    will return the number of lines just read from the history file in that
125    call. */
126 int history_lines_read_from_file = 0;
127
128 /* Immediately after a call to write_history() or history_do_write(), this
129    will return the number of lines just written to the history file in that
130    call.  This also works with history_truncate_file. */
131 int history_lines_written_to_file = 0;
132
133 /* Does S look like the beginning of a history timestamp entry?  Placeholder
134    for more extensive tests. */
135 #define HIST_TIMESTAMP_START(s)         (*(s) == history_comment_char && isdigit ((unsigned char)(s)[1]) )
136
137 static char *history_backupfile PARAMS((const char *));
138 static char *history_tempfile PARAMS((const char *));
139 static int histfile_backup PARAMS((const char *, const char *));
140 static int histfile_restore PARAMS((const char *, const char *));
141
142 /* Return the string that should be used in the place of this
143    filename.  This only matters when you don't specify the
144    filename to read_history (), or write_history (). */
145 static char *
146 history_filename (filename)
147      const char *filename;
148 {
149   char *return_val;
150   const char *home;
151   int home_len;
152
153   return_val = filename ? savestring (filename) : (char *)NULL;
154
155   if (return_val)
156     return (return_val);
157   
158   home = sh_get_env_value ("HOME");
159 #if defined (_WIN32)
160   if (home == 0)
161     home = sh_get_env_value ("APPDATA");
162 #endif
163
164   if (home == 0)
165     return (NULL);
166   else
167     home_len = strlen (home);
168
169   return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
170   strcpy (return_val, home);
171   return_val[home_len] = '/';
172 #if defined (__MSDOS__)
173   strcpy (return_val + home_len + 1, "_history");
174 #else
175   strcpy (return_val + home_len + 1, ".history");
176 #endif
177
178   return (return_val);
179 }
180
181 static char *
182 history_backupfile (filename)
183      const char *filename;
184 {
185   const char *fn;
186   char *ret, linkbuf[PATH_MAX+1];
187   size_t len;
188   ssize_t n;
189   struct stat fs;
190
191   fn = filename;  
192 #if defined (HAVE_READLINK)
193   /* Follow symlink to avoid backing up symlink itself; call will fail if
194      not a symlink */
195   if ((n = readlink (filename, linkbuf, sizeof (linkbuf) - 1)) > 0)
196     {
197       linkbuf[n] = '\0';
198       fn = linkbuf;
199     }
200 #endif
201       
202   len = strlen (fn);
203   ret = xmalloc (len + 2);
204   strcpy (ret, fn);
205   ret[len] = '-';
206   ret[len+1] = '\0';
207   return ret;
208 }
209   
210 static char *
211 history_tempfile (filename)
212      const char *filename;
213 {
214   const char *fn;
215   char *ret, linkbuf[PATH_MAX+1];
216   size_t len;
217   ssize_t n;
218   struct stat fs;
219   int pid;
220
221   fn = filename;  
222 #if defined (HAVE_READLINK)
223   /* Follow symlink so tempfile created in the same directory as any symlinked
224      history file; call will fail if not a symlink */
225   if ((n = readlink (filename, linkbuf, sizeof (linkbuf) - 1)) > 0)
226     {
227       linkbuf[n] = '\0';
228       fn = linkbuf;
229     }
230 #endif
231       
232   len = strlen (fn);
233   ret = xmalloc (len + 11);
234   strcpy (ret, fn);
235
236   pid = (int)getpid ();
237
238   /* filename-PID.tmp */
239   ret[len] = '-';
240   ret[len+1] = (pid / 10000 % 10) + '0';
241   ret[len+2] = (pid / 1000 % 10) + '0';
242   ret[len+3] = (pid / 100 % 10) + '0';
243   ret[len+4] = (pid / 10 % 10) + '0';
244   ret[len+5] = (pid % 10) + '0';
245   strcpy (ret + len + 6, ".tmp");
246
247   return ret;
248 }
249   
250 /* Add the contents of FILENAME to the history list, a line at a time.
251    If FILENAME is NULL, then read from ~/.history.  Returns 0 if
252    successful, or errno if not. */
253 int
254 read_history (filename)
255      const char *filename;
256 {
257   return (read_history_range (filename, 0, -1));
258 }
259
260 /* Read a range of lines from FILENAME, adding them to the history list.
261    Start reading at the FROM'th line and end at the TO'th.  If FROM
262    is zero, start at the beginning.  If TO is less than FROM, read
263    until the end of the file.  If FILENAME is NULL, then read from
264    ~/.history.  Returns 0 if successful, or errno if not. */
265 int
266 read_history_range (filename, from, to)
267      const char *filename;
268      int from, to;
269 {
270   register char *line_start, *line_end, *p;
271   char *input, *buffer, *bufend, *last_ts;
272   int file, current_line, chars_read, has_timestamps, reset_comment_char;
273   struct stat finfo;
274   size_t file_size;
275 #if defined (EFBIG)
276   int overflow_errno = EFBIG;
277 #elif defined (EOVERFLOW)
278   int overflow_errno = EOVERFLOW;
279 #else
280   int overflow_errno = EIO;
281 #endif
282
283   history_lines_read_from_file = 0;
284
285   buffer = last_ts = (char *)NULL;
286   input = history_filename (filename);
287   file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
288
289   if ((file < 0) || (fstat (file, &finfo) == -1))
290     goto error_and_exit;
291
292   file_size = (size_t)finfo.st_size;
293
294   /* check for overflow on very large files */
295   if (file_size != finfo.st_size || file_size + 1 < file_size)
296     {
297       errno = overflow_errno;
298       goto error_and_exit;
299     }
300
301 #ifdef HISTORY_USE_MMAP
302   /* We map read/write and private so we can change newlines to NULs without
303      affecting the underlying object. */
304   buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
305   if ((void *)buffer == MAP_FAILED)
306     {
307       errno = overflow_errno;
308       goto error_and_exit;
309     }
310   chars_read = file_size;
311 #else
312   buffer = (char *)malloc (file_size + 1);
313   if (buffer == 0)
314     {
315       errno = overflow_errno;
316       goto error_and_exit;
317     }
318
319   chars_read = read (file, buffer, file_size);
320 #endif
321   if (chars_read < 0)
322     {
323   error_and_exit:
324       if (errno != 0)
325         chars_read = errno;
326       else
327         chars_read = EIO;
328       if (file >= 0)
329         close (file);
330
331       FREE (input);
332 #ifndef HISTORY_USE_MMAP
333       FREE (buffer);
334 #endif
335
336       return (chars_read);
337     }
338
339   close (file);
340
341   /* Set TO to larger than end of file if negative. */
342   if (to < 0)
343     to = chars_read;
344
345   /* Start at beginning of file, work to end. */
346   bufend = buffer + chars_read;
347   current_line = 0;
348
349   /* Heuristic: the history comment character rarely changes, so assume we
350      have timestamps if the buffer starts with `#[:digit:]' and temporarily
351      set history_comment_char so timestamp parsing works right */
352   reset_comment_char = 0;
353   if (history_comment_char == '\0' && buffer[0] == '#' && isdigit ((unsigned char)buffer[1]))
354     {
355       history_comment_char = '#';
356       reset_comment_char = 1;
357     }
358
359   has_timestamps = HIST_TIMESTAMP_START (buffer);
360   history_multiline_entries += has_timestamps && history_write_timestamps;  
361
362   /* Skip lines until we are at FROM. */
363   for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
364     if (*line_end == '\n')
365       {
366         p = line_end + 1;
367         /* If we see something we think is a timestamp, continue with this
368            line.  We should check more extensively here... */
369         if (HIST_TIMESTAMP_START(p) == 0)
370           current_line++;
371         line_start = p;
372       }
373
374   /* If there are lines left to gobble, then gobble them now. */
375   for (line_end = line_start; line_end < bufend; line_end++)
376     if (*line_end == '\n')
377       {
378         /* Change to allow Windows-like \r\n end of line delimiter. */
379         if (line_end > line_start && line_end[-1] == '\r')
380           line_end[-1] = '\0';
381         else
382           *line_end = '\0';
383
384         if (*line_start)
385           {
386             if (HIST_TIMESTAMP_START(line_start) == 0)
387               {
388                 if (last_ts == NULL && history_multiline_entries)
389                   _hs_append_history_line (history_length - 1, line_start);
390                 else
391                   add_history (line_start);
392                 if (last_ts)
393                   {
394                     add_history_time (last_ts);
395                     last_ts = NULL;
396                   }
397               }
398             else
399               {
400                 last_ts = line_start;
401                 current_line--;
402               }
403           }
404
405         current_line++;
406
407         if (current_line >= to)
408           break;
409
410         line_start = line_end + 1;
411       }
412
413   history_lines_read_from_file = current_line;
414   if (reset_comment_char)
415     history_comment_char = '\0';
416
417   FREE (input);
418 #ifndef HISTORY_USE_MMAP
419   FREE (buffer);
420 #else
421   munmap (buffer, file_size);
422 #endif
423
424   return (0);
425 }
426
427 /* Save FILENAME to BACK, handling case where FILENAME is a symlink
428    (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
429 static int
430 histfile_backup (filename, back)
431      const char *filename;
432      const char *back;
433 {
434 #if defined (HAVE_READLINK)
435   char linkbuf[PATH_MAX+1];
436   ssize_t n;
437
438   /* Follow to target of symlink to avoid renaming symlink itself */
439   if ((n = readlink (filename, linkbuf, sizeof (linkbuf) - 1)) > 0)
440     {
441       linkbuf[n] = '\0';
442       return (rename (linkbuf, back));
443     }
444 #endif
445   return (rename (filename, back));
446 }
447
448 /* Restore ORIG from BACKUP handling case where ORIG is a symlink
449    (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
450 static int
451 histfile_restore (backup, orig)
452      const char *backup;
453      const char *orig;
454 {
455 #if defined (HAVE_READLINK)
456   char linkbuf[PATH_MAX+1];
457   ssize_t n;
458
459   /* Follow to target of symlink to avoid renaming symlink itself */
460   if ((n = readlink (orig, linkbuf, sizeof (linkbuf) - 1)) > 0)
461     {
462       linkbuf[n] = '\0';
463       return (rename (backup, linkbuf));
464     }
465 #endif
466   return (rename (backup, orig));
467 }
468
469 /* Truncate the history file FNAME, leaving only LINES trailing lines.
470    If FNAME is NULL, then use ~/.history.  Writes a new file and renames
471    it to the original name.  Returns 0 on success, errno on failure. */
472 int
473 history_truncate_file (fname, lines)
474      const char *fname;
475      int lines;
476 {
477   char *buffer, *filename, *tempname, *bp, *bp1;                /* bp1 == bp+1 */
478   int file, chars_read, rv, orig_lines, exists, r;
479   struct stat finfo;
480   size_t file_size;
481
482   history_lines_written_to_file = 0;
483
484   buffer = (char *)NULL;
485   filename = history_filename (fname);
486   tempname = 0;
487   file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
488   rv = exists = 0;
489
490   /* Don't try to truncate non-regular files. */
491   if (file == -1 || fstat (file, &finfo) == -1)
492     {
493       rv = errno;
494       if (file != -1)
495         close (file);
496       goto truncate_exit;
497     }
498   exists = 1;
499
500   if (S_ISREG (finfo.st_mode) == 0)
501     {
502       close (file);
503 #ifdef EFTYPE
504       rv = EFTYPE;
505 #else
506       rv = EINVAL;
507 #endif
508       goto truncate_exit;
509     }
510
511   file_size = (size_t)finfo.st_size;
512
513   /* check for overflow on very large files */
514   if (file_size != finfo.st_size || file_size + 1 < file_size)
515     {
516       close (file);
517 #if defined (EFBIG)
518       rv = errno = EFBIG;
519 #elif defined (EOVERFLOW)
520       rv = errno = EOVERFLOW;
521 #else
522       rv = errno = EINVAL;
523 #endif
524       goto truncate_exit;
525     }
526
527   buffer = (char *)malloc (file_size + 1);
528   if (buffer == 0)
529     {
530       rv = errno;
531       close (file);
532       goto truncate_exit;
533     }
534
535   chars_read = read (file, buffer, file_size);
536   close (file);
537
538   if (chars_read <= 0)
539     {
540       rv = (chars_read < 0) ? errno : 0;
541       goto truncate_exit;
542     }
543
544   orig_lines = lines;
545   /* Count backwards from the end of buffer until we have passed
546      LINES lines.  bp1 is set funny initially.  But since bp[1] can't
547      be a comment character (since it's off the end) and *bp can't be
548      both a newline and the history comment character, it should be OK. */
549   for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
550     {
551       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
552         lines--;
553       bp1 = bp;
554     }
555
556   /* If this is the first line, then the file contains exactly the
557      number of lines we want to truncate to, so we don't need to do
558      anything.  It's the first line if we don't find a newline between
559      the current value of i and 0.  Otherwise, write from the start of
560      this line until the end of the buffer. */
561   for ( ; bp > buffer; bp--)
562     {
563       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
564         {
565           bp++;
566           break;
567         }
568       bp1 = bp;
569     }
570
571   /* Write only if there are more lines in the file than we want to
572      truncate to. */
573   if (bp <= buffer)
574     {
575       rv = 0;
576       /* No-op if LINES == 0 at this point */
577       history_lines_written_to_file = orig_lines - lines;
578       goto truncate_exit;
579     }
580
581   tempname = history_tempfile (filename);
582
583   if ((file = open (tempname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) != -1)
584     {
585       if (write (file, bp, chars_read - (bp - buffer)) < 0)
586         rv = errno;
587
588       if (close (file) < 0 && rv == 0)
589         rv = errno;
590     }
591   else
592     rv = errno;
593
594  truncate_exit:
595   FREE (buffer);
596
597   history_lines_written_to_file = orig_lines - lines;
598
599   if (rv == 0 && filename && tempname)
600     rv = histfile_restore (tempname, filename);
601
602   if (rv != 0)
603     {
604       if (tempname)
605         unlink (tempname);
606       history_lines_written_to_file = 0;
607     }
608
609   /* Make sure the new filename is owned by the same user as the old.  If one
610      user is running this, it's a no-op.  If the shell is running after sudo
611      with a shared history file, we don't want to leave the history file
612      owned by root. */
613   if (rv == 0 && exists)
614     r = chown (filename, finfo.st_uid, finfo.st_gid);
615
616   xfree (filename);
617   FREE (tempname);
618
619   return rv;
620 }
621
622 /* Workhorse function for writing history.  Writes the last NELEMENT entries
623    from the history list to FILENAME.  OVERWRITE is non-zero if you
624    wish to replace FILENAME with the entries. */
625 static int
626 history_do_write (filename, nelements, overwrite)
627      const char *filename;
628      int nelements, overwrite;
629 {
630   register int i;
631   char *output, *tempname, *histname;
632   int file, mode, rv, exists;
633   struct stat finfo;
634 #ifdef HISTORY_USE_MMAP
635   size_t cursize;
636
637   history_lines_written_to_file = 0;
638
639   mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
640 #else
641   mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
642 #endif
643   histname = history_filename (filename);
644   exists = histname ? (stat (histname, &finfo) == 0) : 0;
645
646   tempname = (overwrite && exists && S_ISREG (finfo.st_mode)) ? history_tempfile (histname) : 0;
647   output = tempname ? tempname : histname;
648
649   file = output ? open (output, mode, 0600) : -1;
650   rv = 0;
651
652   if (file == -1)
653     {
654       rv = errno;
655       FREE (histname);
656       FREE (tempname);
657       return (rv);
658     }
659
660 #ifdef HISTORY_USE_MMAP
661   cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
662 #endif
663
664   if (nelements > history_length)
665     nelements = history_length;
666
667   /* Build a buffer of all the lines to write, and write them in one syscall.
668      Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
669   {
670     HIST_ENTRY **the_history;   /* local */
671     register int j;
672     int buffer_size;
673     char *buffer;
674
675     the_history = history_list ();
676     /* Calculate the total number of bytes to write. */
677     for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
678 #if 0
679       buffer_size += 2 + HISTENT_BYTES (the_history[i]);
680 #else
681       {
682         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
683           buffer_size += strlen (the_history[i]->timestamp) + 1;
684         buffer_size += strlen (the_history[i]->line) + 1;
685       }
686 #endif
687
688     /* Allocate the buffer, and fill it. */
689 #ifdef HISTORY_USE_MMAP
690     if (ftruncate (file, buffer_size+cursize) == -1)
691       goto mmap_error;
692     buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
693     if ((void *)buffer == MAP_FAILED)
694       {
695 mmap_error:
696         rv = errno;
697         close (file);
698         if (tempname)
699           unlink (tempname);
700         FREE (histname);
701         FREE (tempname);
702         return rv;
703       }
704 #else    
705     buffer = (char *)malloc (buffer_size);
706     if (buffer == 0)
707       {
708         rv = errno;
709         close (file);
710         if (tempname)
711           unlink (tempname);
712         FREE (histname);
713         FREE (tempname);
714         return rv;
715       }
716 #endif
717
718     for (j = 0, i = history_length - nelements; i < history_length; i++)
719       {
720         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
721           {
722             strcpy (buffer + j, the_history[i]->timestamp);
723             j += strlen (the_history[i]->timestamp);
724             buffer[j++] = '\n';
725           }
726         strcpy (buffer + j, the_history[i]->line);
727         j += strlen (the_history[i]->line);
728         buffer[j++] = '\n';
729       }
730
731 #ifdef HISTORY_USE_MMAP
732     if (msync (buffer, buffer_size, MS_ASYNC) != 0 || munmap (buffer, buffer_size) != 0)
733       rv = errno;
734 #else
735     if (write (file, buffer, buffer_size) < 0)
736       rv = errno;
737     xfree (buffer);
738 #endif
739   }
740
741   history_lines_written_to_file = nelements;
742
743   if (close (file) < 0 && rv == 0)
744     rv = errno;
745
746   if (rv == 0 && histname && tempname)
747     rv = histfile_restore (tempname, histname);
748
749   if (rv != 0)
750     {
751       if (tempname)
752         unlink (tempname);
753       history_lines_written_to_file = 0;
754     }
755
756   /* Make sure the new filename is owned by the same user as the old.  If one
757      user is running this, it's a no-op.  If the shell is running after sudo
758      with a shared history file, we don't want to leave the history file
759      owned by root. */
760   if (rv == 0 && exists)
761     mode = chown (histname, finfo.st_uid, finfo.st_gid);
762
763   FREE (histname);
764   FREE (tempname);
765
766   return (rv);
767 }
768
769 /* Append NELEMENT entries to FILENAME.  The entries appended are from
770    the end of the list minus NELEMENTs up to the end of the list. */
771 int
772 append_history (nelements, filename)
773      int nelements;
774      const char *filename;
775 {
776   return (history_do_write (filename, nelements, HISTORY_APPEND));
777 }
778
779 /* Overwrite FILENAME with the current history.  If FILENAME is NULL,
780    then write the history list to ~/.history.  Values returned
781    are as in read_history ().*/
782 int
783 write_history (filename)
784      const char *filename;
785 {
786   return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
787 }