Imported from ../bash-4.0-rc1.tar.gz.
[platform/upstream/bash.git] / lib / readline / histfile.c
1 /* histfile.c - functions to manipulate the history file. */
2
3 /* Copyright (C) 1989-2009 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     {
129       home = ".";
130       home_len = 1;
131     }
132   else
133     home_len = strlen (home);
134
135   return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
136   strcpy (return_val, home);
137   return_val[home_len] = '/';
138 #if defined (__MSDOS__)
139   strcpy (return_val + home_len + 1, "_history");
140 #else
141   strcpy (return_val + home_len + 1, ".history");
142 #endif
143
144   return (return_val);
145 }
146
147 /* Add the contents of FILENAME to the history list, a line at a time.
148    If FILENAME is NULL, then read from ~/.history.  Returns 0 if
149    successful, or errno if not. */
150 int
151 read_history (filename)
152      const char *filename;
153 {
154   return (read_history_range (filename, 0, -1));
155 }
156
157 /* Read a range of lines from FILENAME, adding them to the history list.
158    Start reading at the FROM'th line and end at the TO'th.  If FROM
159    is zero, start at the beginning.  If TO is less than FROM, read
160    until the end of the file.  If FILENAME is NULL, then read from
161    ~/.history.  Returns 0 if successful, or errno if not. */
162 int
163 read_history_range (filename, from, to)
164      const char *filename;
165      int from, to;
166 {
167   register char *line_start, *line_end, *p;
168   char *input, *buffer, *bufend, *last_ts;
169   int file, current_line, chars_read;
170   struct stat finfo;
171   size_t file_size;
172 #if defined (EFBIG)
173   int overflow_errno = EFBIG;
174 #elif defined (EOVERFLOW)
175   int overflow_errno = EOVERFLOW;
176 #else
177   int overflow_errno = EIO;
178 #endif
179
180   buffer = last_ts = (char *)NULL;
181   input = history_filename (filename);
182   file = open (input, O_RDONLY|O_BINARY, 0666);
183
184   if ((file < 0) || (fstat (file, &finfo) == -1))
185     goto error_and_exit;
186
187   file_size = (size_t)finfo.st_size;
188
189   /* check for overflow on very large files */
190   if (file_size != finfo.st_size || file_size + 1 < file_size)
191     {
192       errno = overflow_errno;
193       goto error_and_exit;
194     }
195
196 #ifdef HISTORY_USE_MMAP
197   /* We map read/write and private so we can change newlines to NULs without
198      affecting the underlying object. */
199   buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
200   if ((void *)buffer == MAP_FAILED)
201     {
202       errno = overflow_errno;
203       goto error_and_exit;
204     }
205   chars_read = file_size;
206 #else
207   buffer = (char *)malloc (file_size + 1);
208   if (buffer == 0)
209     {
210       errno = overflow_errno;
211       goto error_and_exit;
212     }
213
214   chars_read = read (file, buffer, file_size);
215 #endif
216   if (chars_read < 0)
217     {
218   error_and_exit:
219       if (errno != 0)
220         chars_read = errno;
221       else
222         chars_read = EIO;
223       if (file >= 0)
224         close (file);
225
226       FREE (input);
227 #ifndef HISTORY_USE_MMAP
228       FREE (buffer);
229 #endif
230
231       return (chars_read);
232     }
233
234   close (file);
235
236   /* Set TO to larger than end of file if negative. */
237   if (to < 0)
238     to = chars_read;
239
240   /* Start at beginning of file, work to end. */
241   bufend = buffer + chars_read;
242   current_line = 0;
243
244   /* Skip lines until we are at FROM. */
245   for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
246     if (*line_end == '\n')
247       {
248         p = line_end + 1;
249         /* If we see something we think is a timestamp, continue with this
250            line.  We should check more extensively here... */
251         if (HIST_TIMESTAMP_START(p) == 0)
252           current_line++;
253         line_start = p;
254       }
255
256   /* If there are lines left to gobble, then gobble them now. */
257   for (line_end = line_start; line_end < bufend; line_end++)
258     if (*line_end == '\n')
259       {
260         /* Change to allow Windows-like \r\n end of line delimiter. */
261         if (line_end > line_start && line_end[-1] == '\r')
262           line_end[-1] = '\0';
263         else
264           *line_end = '\0';
265
266         if (*line_start)
267           {
268             if (HIST_TIMESTAMP_START(line_start) == 0)
269               {
270                 add_history (line_start);
271                 if (last_ts)
272                   {
273                     add_history_time (last_ts);
274                     last_ts = NULL;
275                   }
276               }
277             else
278               {
279                 last_ts = line_start;
280                 current_line--;
281               }
282           }
283
284         current_line++;
285
286         if (current_line >= to)
287           break;
288
289         line_start = line_end + 1;
290       }
291
292   FREE (input);
293 #ifndef HISTORY_USE_MMAP
294   FREE (buffer);
295 #else
296   munmap (buffer, file_size);
297 #endif
298
299   return (0);
300 }
301
302 /* Truncate the history file FNAME, leaving only LINES trailing lines.
303    If FNAME is NULL, then use ~/.history.  Returns 0 on success, errno
304    on failure. */
305 int
306 history_truncate_file (fname, lines)
307      const char *fname;
308      int lines;
309 {
310   char *buffer, *filename, *bp, *bp1;           /* bp1 == bp+1 */
311   int file, chars_read, rv;
312   struct stat finfo;
313   size_t file_size;
314
315   buffer = (char *)NULL;
316   filename = history_filename (fname);
317   file = open (filename, O_RDONLY|O_BINARY, 0666);
318   rv = 0;
319
320   /* Don't try to truncate non-regular files. */
321   if (file == -1 || fstat (file, &finfo) == -1)
322     {
323       rv = errno;
324       if (file != -1)
325         close (file);
326       goto truncate_exit;
327     }
328
329   if (S_ISREG (finfo.st_mode) == 0)
330     {
331       close (file);
332 #ifdef EFTYPE
333       rv = EFTYPE;
334 #else
335       rv = EINVAL;
336 #endif
337       goto truncate_exit;
338     }
339
340   file_size = (size_t)finfo.st_size;
341
342   /* check for overflow on very large files */
343   if (file_size != finfo.st_size || file_size + 1 < file_size)
344     {
345       close (file);
346 #if defined (EFBIG)
347       rv = errno = EFBIG;
348 #elif defined (EOVERFLOW)
349       rv = errno = EOVERFLOW;
350 #else
351       rv = errno = EINVAL;
352 #endif
353       goto truncate_exit;
354     }
355
356   buffer = (char *)malloc (file_size + 1);
357   if (buffer == 0)
358     {
359       close (file);
360       goto truncate_exit;
361     }
362
363   chars_read = read (file, buffer, file_size);
364   close (file);
365
366   if (chars_read <= 0)
367     {
368       rv = (chars_read < 0) ? errno : 0;
369       goto truncate_exit;
370     }
371
372   /* Count backwards from the end of buffer until we have passed
373      LINES lines.  bp1 is set funny initially.  But since bp[1] can't
374      be a comment character (since it's off the end) and *bp can't be
375      both a newline and the history comment character, it should be OK. */
376   for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
377     {
378       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
379         lines--;
380       bp1 = bp;
381     }
382
383   /* If this is the first line, then the file contains exactly the
384      number of lines we want to truncate to, so we don't need to do
385      anything.  It's the first line if we don't find a newline between
386      the current value of i and 0.  Otherwise, write from the start of
387      this line until the end of the buffer. */
388   for ( ; bp > buffer; bp--)
389     {
390       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
391         {
392           bp++;
393           break;
394         }
395       bp1 = bp;
396     }
397
398   /* Write only if there are more lines in the file than we want to
399      truncate to. */
400   if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
401     {
402       write (file, bp, chars_read - (bp - buffer));
403
404 #if defined (__BEOS__)
405       /* BeOS ignores O_TRUNC. */
406       ftruncate (file, chars_read - (bp - buffer));
407 #endif
408
409       close (file);
410     }
411
412  truncate_exit:
413
414   FREE (buffer);
415
416   free (filename);
417   return rv;
418 }
419
420 /* Workhorse function for writing history.  Writes NELEMENT entries
421    from the history list to FILENAME.  OVERWRITE is non-zero if you
422    wish to replace FILENAME with the entries. */
423 static int
424 history_do_write (filename, nelements, overwrite)
425      const char *filename;
426      int nelements, overwrite;
427 {
428   register int i;
429   char *output;
430   int file, mode, rv;
431 #ifdef HISTORY_USE_MMAP
432   size_t cursize;
433
434   mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
435 #else
436   mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
437 #endif
438   output = history_filename (filename);
439   rv = 0;
440
441   if ((file = open (output, mode, 0600)) == -1)
442     {
443       FREE (output);
444       return (errno);
445     }
446
447 #ifdef HISTORY_USE_MMAP
448   cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
449 #endif
450
451   if (nelements > history_length)
452     nelements = history_length;
453
454   /* Build a buffer of all the lines to write, and write them in one syscall.
455      Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
456   {
457     HIST_ENTRY **the_history;   /* local */
458     register int j;
459     int buffer_size;
460     char *buffer;
461
462     the_history = history_list ();
463     /* Calculate the total number of bytes to write. */
464     for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
465 #if 0
466       buffer_size += 2 + HISTENT_BYTES (the_history[i]);
467 #else
468       {
469         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
470           buffer_size += strlen (the_history[i]->timestamp) + 1;
471         buffer_size += strlen (the_history[i]->line) + 1;
472       }
473 #endif
474
475     /* Allocate the buffer, and fill it. */
476 #ifdef HISTORY_USE_MMAP
477     if (ftruncate (file, buffer_size+cursize) == -1)
478       goto mmap_error;
479     buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
480     if ((void *)buffer == MAP_FAILED)
481       {
482 mmap_error:
483         rv = errno;
484         FREE (output);
485         close (file);
486         return rv;
487       }
488 #else    
489     buffer = (char *)malloc (buffer_size);
490     if (buffer == 0)
491       {
492         rv = errno;
493         FREE (output);
494         close (file);
495         return rv;
496       }
497 #endif
498
499     for (j = 0, i = history_length - nelements; i < history_length; i++)
500       {
501         if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
502           {
503             strcpy (buffer + j, the_history[i]->timestamp);
504             j += strlen (the_history[i]->timestamp);
505             buffer[j++] = '\n';
506           }
507         strcpy (buffer + j, the_history[i]->line);
508         j += strlen (the_history[i]->line);
509         buffer[j++] = '\n';
510       }
511
512 #ifdef HISTORY_USE_MMAP
513     if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
514       rv = errno;
515 #else
516     if (write (file, buffer, buffer_size) < 0)
517       rv = errno;
518     free (buffer);
519 #endif
520   }
521
522   close (file);
523
524   FREE (output);
525
526   return (rv);
527 }
528
529 /* Append NELEMENT entries to FILENAME.  The entries appended are from
530    the end of the list minus NELEMENTs up to the end of the list. */
531 int
532 append_history (nelements, filename)
533      int nelements;
534      const char *filename;
535 {
536   return (history_do_write (filename, nelements, HISTORY_APPEND));
537 }
538
539 /* Overwrite FILENAME with the current history.  If FILENAME is NULL,
540    then write the history list to ~/.history.  Values returned
541    are as in read_history ().*/
542 int
543 write_history (filename)
544      const char *filename;
545 {
546   return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
547 }