1 /* histfile.c - functions to manipulate the history file. */
3 /* Copyright (C) 1989-2009 Free Software Foundation, Inc.
5 This file contains the GNU History Library (History), a set of
6 routines for managing the text of previously typed lines.
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.
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.
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/>.
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. */
26 #define READLINE_LIBRARY
28 #if defined (__TANDEM)
32 #if defined (HAVE_CONFIG_H)
38 #include <sys/types.h>
39 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
40 # include <sys/file.h>
42 #include "posixstat.h"
45 #if defined (HAVE_STDLIB_H)
48 # include "ansi_stdlib.h"
49 #endif /* HAVE_STDLIB_H */
51 #if defined (HAVE_UNISTD_H)
61 #ifdef HISTORY_USE_MMAP
62 # include <sys/mman.h>
65 # define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
66 # define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
68 # define MAP_RFLAGS MAP_PRIVATE
69 # define MAP_WFLAGS MAP_SHARED
73 # define MAP_FAILED ((void *)-1)
76 #endif /* HISTORY_USE_MMAP */
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__)
86 #else /* !__EMX__ && !__CYGWIN__ */
89 #endif /* !__EMX__ && !__CYGWIN__ */
102 /* If non-zero, we write timestamps to the history file in history_do_write() */
103 int history_write_timestamps = 0;
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]) )
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 (). */
113 history_filename (filename)
114 const char *filename;
120 return_val = filename ? savestring (filename) : (char *)NULL;
125 home = sh_get_env_value ("HOME");
133 home_len = strlen (home);
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");
141 strcpy (return_val + home_len + 1, ".history");
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. */
151 read_history (filename)
152 const char *filename;
154 return (read_history_range (filename, 0, -1));
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. */
163 read_history_range (filename, from, to)
164 const char *filename;
167 register char *line_start, *line_end, *p;
168 char *input, *buffer, *bufend, *last_ts;
169 int file, current_line, chars_read;
173 int overflow_errno = EFBIG;
174 #elif defined (EOVERFLOW)
175 int overflow_errno = EOVERFLOW;
177 int overflow_errno = EIO;
180 buffer = last_ts = (char *)NULL;
181 input = history_filename (filename);
182 file = open (input, O_RDONLY|O_BINARY, 0666);
184 if ((file < 0) || (fstat (file, &finfo) == -1))
187 file_size = (size_t)finfo.st_size;
189 /* check for overflow on very large files */
190 if (file_size != finfo.st_size || file_size + 1 < file_size)
192 errno = overflow_errno;
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)
202 errno = overflow_errno;
205 chars_read = file_size;
207 buffer = (char *)malloc (file_size + 1);
210 errno = overflow_errno;
214 chars_read = read (file, buffer, file_size);
227 #ifndef HISTORY_USE_MMAP
236 /* Set TO to larger than end of file if negative. */
240 /* Start at beginning of file, work to end. */
241 bufend = buffer + chars_read;
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')
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)
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')
260 /* Change to allow Windows-like \r\n end of line delimiter. */
261 if (line_end > line_start && line_end[-1] == '\r')
268 if (HIST_TIMESTAMP_START(line_start) == 0)
270 add_history (line_start);
273 add_history_time (last_ts);
279 last_ts = line_start;
286 if (current_line >= to)
289 line_start = line_end + 1;
293 #ifndef HISTORY_USE_MMAP
296 munmap (buffer, file_size);
302 /* Truncate the history file FNAME, leaving only LINES trailing lines.
303 If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
306 history_truncate_file (fname, lines)
310 char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */
311 int file, chars_read, rv;
315 buffer = (char *)NULL;
316 filename = history_filename (fname);
317 file = open (filename, O_RDONLY|O_BINARY, 0666);
320 /* Don't try to truncate non-regular files. */
321 if (file == -1 || fstat (file, &finfo) == -1)
329 if (S_ISREG (finfo.st_mode) == 0)
340 file_size = (size_t)finfo.st_size;
342 /* check for overflow on very large files */
343 if (file_size != finfo.st_size || file_size + 1 < file_size)
348 #elif defined (EOVERFLOW)
349 rv = errno = EOVERFLOW;
356 buffer = (char *)malloc (file_size + 1);
363 chars_read = read (file, buffer, file_size);
368 rv = (chars_read < 0) ? errno : 0;
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--)
378 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
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--)
390 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
398 /* Write only if there are more lines in the file than we want to
400 if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
402 write (file, bp, chars_read - (bp - buffer));
404 #if defined (__BEOS__)
405 /* BeOS ignores O_TRUNC. */
406 ftruncate (file, chars_read - (bp - buffer));
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. */
424 history_do_write (filename, nelements, overwrite)
425 const char *filename;
426 int nelements, overwrite;
431 #ifdef HISTORY_USE_MMAP
434 mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
436 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
438 output = history_filename (filename);
441 if ((file = open (output, mode, 0600)) == -1)
447 #ifdef HISTORY_USE_MMAP
448 cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
451 if (nelements > history_length)
452 nelements = history_length;
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). */
457 HIST_ENTRY **the_history; /* local */
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++)
466 buffer_size += 2 + HISTENT_BYTES (the_history[i]);
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;
475 /* Allocate the buffer, and fill it. */
476 #ifdef HISTORY_USE_MMAP
477 if (ftruncate (file, buffer_size+cursize) == -1)
479 buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
480 if ((void *)buffer == MAP_FAILED)
489 buffer = (char *)malloc (buffer_size);
499 for (j = 0, i = history_length - nelements; i < history_length; i++)
501 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
503 strcpy (buffer + j, the_history[i]->timestamp);
504 j += strlen (the_history[i]->timestamp);
507 strcpy (buffer + j, the_history[i]->line);
508 j += strlen (the_history[i]->line);
512 #ifdef HISTORY_USE_MMAP
513 if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
516 if (write (file, buffer, buffer_size) < 0)
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. */
532 append_history (nelements, filename)
534 const char *filename;
536 return (history_do_write (filename, nelements, HISTORY_APPEND));
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 ().*/
543 write_history (filename)
544 const char *filename;
546 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));