No specific user configuration
[platform/upstream/bash.git] / lib / readline / histfile.c
1 /* histfile.c - functions to manipulate the history file. */
2
3 /* Copyright (C) 1989-2010 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 #include <sys/types.h>
39 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
40 #  include <sys/file.h>
41 #endif
42 #include "posixstat.h"
43 #include <fcntl.h>
44
45 #if defined (HAVE_STDLIB_H)
46 #  include <stdlib.h>
47 #else
48 #  include "ansi_stdlib.h"
49 #endif /* HAVE_STDLIB_H */
50
51 #if defined (HAVE_UNISTD_H)
52 #  include <unistd.h>
53 #endif
54
55 #include <ctype.h>
56
57 #if defined (__EMX__)
58 #  undef HAVE_MMAP
59 #endif
60
61 #ifdef HISTORY_USE_MMAP
62 #  include <sys/mman.h>
63
64 #  ifdef MAP_FILE
65 #    define MAP_RFLAGS  (MAP_FILE|MAP_PRIVATE)
66 #    define MAP_WFLAGS  (MAP_FILE|MAP_SHARED)
67 #  else
68 #    define MAP_RFLAGS  MAP_PRIVATE
69 #    define MAP_WFLAGS  MAP_SHARED
70 #  endif
71
72 #  ifndef MAP_FAILED
73 #    define MAP_FAILED  ((void *)-1)
74 #  endif
75
76 #endif /* HISTORY_USE_MMAP */
77
78 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
79    on win 95/98/nt), we want to open files with O_BINARY mode so that there
80    is no \n -> \r\n conversion performed.  On other systems, we don't want to
81    mess around with O_BINARY at all, so we ensure that it's defined to 0. */
82 #if defined (__EMX__) || defined (__CYGWIN__)
83 #  ifndef O_BINARY
84 #    define O_BINARY 0
85 #  endif
86 #else /* !__EMX__ && !__CYGWIN__ */
87 #  undef O_BINARY
88 #  define O_BINARY 0
89 #endif /* !__EMX__ && !__CYGWIN__ */
90
91 #include <errno.h>
92 #if !defined (errno)
93 extern int errno;
94 #endif /* !errno */
95
96 #include "history.h"
97 #include "histlib.h"
98
99 #include "rlshell.h"
100 #include "xmalloc.h"
101
102 /* If non-zero, we write timestamps to the history file in history_do_write() */
103 int history_write_timestamps = 0;
104
105 /* Does S look like the beginning of a history timestamp entry?  Placeholder
106    for more extensive tests. */
107 #define HIST_TIMESTAMP_START(s)         (*(s) == history_comment_char && isdigit ((s)[1]) )
108
109 /* Return the string that should be used in the place of this
110    filename.  This only matters when you don't specify the
111    filename to read_history (), or write_history (). */
112 static char *
113 history_filename (filename)
114      const char *filename;
115 {
116   char *return_val;
117   const char *home;
118   int home_len;
119
120   return_val = filename ? savestring (filename) : (char *)NULL;
121
122   if (return_val)
123     return (return_val);
124   
125   home = sh_get_env_value ("HOME");
126
127   if (home == 0)
128     return (NULL);
129   else
130     home_len = strlen (home);
131
132   return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
133   strcpy (return_val, home);
134   return_val[home_len] = '/';
135 #if defined (__MSDOS__)
136   strcpy (return_val + home_len + 1, "_history");
137 #else
138   strcpy (return_val + home_len + 1, ".history");
139 #endif
140
141   return (return_val);
142 }
143
144 static char *
145 history_backupfile (filename)
146      const char *filename;
147 {
148   char *ret;
149   size_t len;
150
151   len = strlen (filename);
152   ret = xmalloc (len + 2);
153   strcpy (ret, filename);
154   ret[len] = '-';
155   ret[len+1] = '\0';
156   return ret;
157 }
158   
159 /* Add the contents of FILENAME to the history list, a line at a time.
160    If FILENAME is NULL, then read from ~/.history.  Returns 0 if
161    successful, or errno if not. */
162 int
163 read_history (filename)
164      const char *filename;
165 {
166   return (read_history_range (filename, 0, -1));
167 }
168
169 /* Read a range of lines from FILENAME, adding them to the history list.
170    Start reading at the FROM'th line and end at the TO'th.  If FROM
171    is zero, start at the beginning.  If TO is less than FROM, read
172    until the end of the file.  If FILENAME is NULL, then read from
173    ~/.history.  Returns 0 if successful, or errno if not. */
174 int
175 read_history_range (filename, from, to)
176      const char *filename;
177      int from, to;
178 {
179   register char *line_start, *line_end, *p;
180   char *input, *buffer, *bufend, *last_ts;
181   int file, current_line, chars_read;
182   struct stat finfo;
183   size_t file_size;
184 #if defined (EFBIG)
185   int overflow_errno = EFBIG;
186 #elif defined (EOVERFLOW)
187   int overflow_errno = EOVERFLOW;
188 #else
189   int overflow_errno = EIO;
190 #endif
191
192   buffer = last_ts = (char *)NULL;
193   input = history_filename (filename);
194   file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
195
196   if ((file < 0) || (fstat (file, &finfo) == -1))
197     goto error_and_exit;
198
199   file_size = (size_t)finfo.st_size;
200
201   /* check for overflow on very large files */
202   if (file_size != finfo.st_size || file_size + 1 < file_size)
203     {
204       errno = overflow_errno;
205       goto error_and_exit;
206     }
207
208 #ifdef HISTORY_USE_MMAP
209   /* We map read/write and private so we can change newlines to NULs without
210      affecting the underlying object. */
211   buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
212   if ((void *)buffer == MAP_FAILED)
213     {
214       errno = overflow_errno;
215       goto error_and_exit;
216     }
217   chars_read = file_size;
218 #else
219   buffer = (char *)malloc (file_size + 1);
220   if (buffer == 0)
221     {
222       errno = overflow_errno;
223       goto error_and_exit;
224     }
225
226   chars_read = read (file, buffer, file_size);
227 #endif
228   if (chars_read < 0)
229     {
230   error_and_exit:
231       if (errno != 0)
232         chars_read = errno;
233       else
234         chars_read = EIO;
235       if (file >= 0)
236         close (file);
237
238       FREE (input);
239 #ifndef HISTORY_USE_MMAP
240       FREE (buffer);
241 #endif
242
243       return (chars_read);
244     }
245
246   close (file);
247
248   /* Set TO to larger than end of file if negative. */
249   if (to < 0)
250     to = chars_read;
251
252   /* Start at beginning of file, work to end. */
253   bufend = buffer + chars_read;
254   current_line = 0;
255
256   /* Skip lines until we are at FROM. */
257   for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
258     if (*line_end == '\n')
259       {
260         p = line_end + 1;
261         /* If we see something we think is a timestamp, continue with this
262            line.  We should check more extensively here... */
263         if (HIST_TIMESTAMP_START(p) == 0)
264           current_line++;
265         line_start = p;
266       }
267
268   /* If there are lines left to gobble, then gobble them now. */
269   for (line_end = line_start; line_end < bufend; line_end++)
270     if (*line_end == '\n')
271       {
272         /* Change to allow Windows-like \r\n end of line delimiter. */
273         if (line_end > line_start && line_end[-1] == '\r')
274           line_end[-1] = '\0';
275         else
276           *line_end = '\0';
277
278         if (*line_start)
279           {
280             if (HIST_TIMESTAMP_START(line_start) == 0)
281               {
282                 add_history (line_start);
283                 if (last_ts)
284                   {
285                     add_history_time (last_ts);
286                     last_ts = NULL;
287                   }
288               }
289             else
290               {
291                 last_ts = line_start;
292                 current_line--;
293               }
294           }
295
296         current_line++;
297
298         if (current_line >= to)
299           break;
300
301         line_start = line_end + 1;
302       }
303
304   FREE (input);
305 #ifndef HISTORY_USE_MMAP
306   FREE (buffer);
307 #else
308   munmap (buffer, file_size);
309 #endif
310
311   return (0);
312 }
313
314 /* Truncate the history file FNAME, leaving only LINES trailing lines.
315    If FNAME is NULL, then use ~/.history.  Returns 0 on success, errno
316    on failure. */
317 int
318 history_truncate_file (fname, lines)
319      const char *fname;
320      int lines;
321 {
322   char *buffer, *filename, *bp, *bp1;           /* bp1 == bp+1 */
323   int file, chars_read, rv;
324   struct stat finfo;
325   size_t file_size;
326
327   buffer = (char *)NULL;
328   filename = history_filename (fname);
329   file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
330   rv = 0;
331
332   /* Don't try to truncate non-regular files. */
333   if (file == -1 || fstat (file, &finfo) == -1)
334     {
335       rv = errno;
336       if (file != -1)
337         close (file);
338       goto truncate_exit;
339     }
340
341   if (S_ISREG (finfo.st_mode) == 0)
342     {
343       close (file);
344 #ifdef EFTYPE
345       rv = EFTYPE;
346 #else
347       rv = EINVAL;
348 #endif
349       goto truncate_exit;
350     }
351
352   file_size = (size_t)finfo.st_size;
353
354   /* check for overflow on very large files */
355   if (file_size != finfo.st_size || file_size + 1 < file_size)
356     {
357       close (file);
358 #if defined (EFBIG)
359       rv = errno = EFBIG;
360 #elif defined (EOVERFLOW)
361       rv = errno = EOVERFLOW;
362 #else
363       rv = errno = EINVAL;
364 #endif
365       goto truncate_exit;
366     }
367
368   buffer = (char *)malloc (file_size + 1);
369   if (buffer == 0)
370     {
371       close (file);
372       goto truncate_exit;
373     }
374
375   chars_read = read (file, buffer, file_size);
376   close (file);
377
378   if (chars_read <= 0)
379     {
380       rv = (chars_read < 0) ? errno : 0;
381       goto truncate_exit;
382     }
383
384   /* Count backwards from the end of buffer until we have passed
385      LINES lines.  bp1 is set funny initially.  But since bp[1] can't
386      be a comment character (since it's off the end) and *bp can't be
387      both a newline and the history comment character, it should be OK. */
388   for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
389     {
390       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
391         lines--;
392       bp1 = bp;
393     }
394
395   /* If this is the first line, then the file contains exactly the
396      number of lines we want to truncate to, so we don't need to do
397      anything.  It's the first line if we don't find a newline between
398      the current value of i and 0.  Otherwise, write from the start of
399      this line until the end of the buffer. */
400   for ( ; bp > buffer; bp--)
401     {
402       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
403         {
404           bp++;
405           break;
406         }
407       bp1 = bp;
408     }
409
410   /* Write only if there are more lines in the file than we want to
411      truncate to. */
412   if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
413     {
414       if (write (file, bp, chars_read - (bp - buffer)) < 0)
415         rv = errno;
416
417 #if defined (__BEOS__)
418       /* BeOS ignores O_TRUNC. */
419       ftruncate (file, chars_read - (bp - buffer));
420 #endif
421
422       if (close (file) < 0 && rv == 0)
423         rv = errno;
424     }
425
426  truncate_exit:
427
428   FREE (buffer);
429
430   xfree (filename);
431   return rv;
432 }
433
434 /* Workhorse function for writing history.  Writes NELEMENT entries
435    from the history list to FILENAME.  OVERWRITE is non-zero if you
436    wish to replace FILENAME with the entries. */
437 static int
438 history_do_write (filename, nelements, overwrite)
439      const char *filename;
440      int nelements, overwrite;
441 {
442   register int i;
443   char *output, *bakname;
444   int file, mode, rv;
445 #ifdef HISTORY_USE_MMAP
446   size_t cursize;
447
448   mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
449 #else
450   mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
451 #endif
452   output = history_filename (filename);
453   bakname = (overwrite && output) ? history_backupfile (output) : 0;
454
455   if (output && bakname)
456     rename (output, bakname);
457
458   file = output ? open (output, mode, 0600) : -1;
459   rv = 0;
460
461   if (file == -1)
462     {
463       rv = errno;
464       if (output && bakname)
465         rename (bakname, output);
466       FREE (output);
467       FREE (bakname);
468       return (rv);
469     }
470
471 #ifdef HISTORY_USE_MMAP
472   cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
473 #endif
474
475   if (nelements > history_length)
476     nelements = history_length;
477
478   /* Build a buffer of all the lines to write, and write them in one syscall.
479      Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
480   {
481     HIST_ENTRY **the_history;   /* local */
482     register int j;
483     int buffer_size;
484     char *buffer;
485
486     the_history = history_list ();
487     /* Calculate the total number of bytes to write. */
488     for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
489 #if 0
490       buffer_size += 2 + HISTENT_BYTES (the_history[i]);
491 #else
492       {
493         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
494           buffer_size += strlen (the_history[i]->timestamp) + 1;
495         buffer_size += strlen (the_history[i]->line) + 1;
496       }
497 #endif
498
499     /* Allocate the buffer, and fill it. */
500 #ifdef HISTORY_USE_MMAP
501     if (ftruncate (file, buffer_size+cursize) == -1)
502       goto mmap_error;
503     buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
504     if ((void *)buffer == MAP_FAILED)
505       {
506 mmap_error:
507         rv = errno;
508         close (file);
509         if (output && bakname)
510           rename (bakname, output);
511         FREE (output);
512         FREE (bakname);
513         return rv;
514       }
515 #else    
516     buffer = (char *)malloc (buffer_size);
517     if (buffer == 0)
518       {
519         rv = errno;
520         close (file);
521         if (output && bakname)
522           rename (bakname, output);
523         FREE (output);
524         FREE (bakname);
525         return rv;
526       }
527 #endif
528
529     for (j = 0, i = history_length - nelements; i < history_length; i++)
530       {
531         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
532           {
533             strcpy (buffer + j, the_history[i]->timestamp);
534             j += strlen (the_history[i]->timestamp);
535             buffer[j++] = '\n';
536           }
537         strcpy (buffer + j, the_history[i]->line);
538         j += strlen (the_history[i]->line);
539         buffer[j++] = '\n';
540       }
541
542 #ifdef HISTORY_USE_MMAP
543     if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
544       rv = errno;
545 #else
546     if (write (file, buffer, buffer_size) < 0)
547       rv = errno;
548     xfree (buffer);
549 #endif
550   }
551
552   if (close (file) < 0 && rv == 0)
553     rv = errno;
554
555   if (rv != 0 && output && bakname)
556     rename (bakname, output);
557   else if (rv == 0 && bakname)
558     unlink (bakname);
559
560   FREE (output);
561   FREE (bakname);
562
563   return (rv);
564 }
565
566 /* Append NELEMENT entries to FILENAME.  The entries appended are from
567    the end of the list minus NELEMENTs up to the end of the list. */
568 int
569 append_history (nelements, filename)
570      int nelements;
571      const char *filename;
572 {
573   return (history_do_write (filename, nelements, HISTORY_APPEND));
574 }
575
576 /* Overwrite FILENAME with the current history.  If FILENAME is NULL,
577    then write the history list to ~/.history.  Values returned
578    are as in read_history ().*/
579 int
580 write_history (filename)
581      const char *filename;
582 {
583   return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
584 }