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