1 /* histfile.c - functions to manipulate the history file. */
3 /* Copyright (C) 1989-2010 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");
130 home_len = strlen (home);
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");
138 strcpy (return_val + home_len + 1, ".history");
145 history_backupfile (filename)
146 const char *filename;
151 len = strlen (filename);
152 ret = xmalloc (len + 2);
153 strcpy (ret, filename);
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. */
163 read_history (filename)
164 const char *filename;
166 return (read_history_range (filename, 0, -1));
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. */
175 read_history_range (filename, from, to)
176 const char *filename;
179 register char *line_start, *line_end, *p;
180 char *input, *buffer, *bufend, *last_ts;
181 int file, current_line, chars_read;
185 int overflow_errno = EFBIG;
186 #elif defined (EOVERFLOW)
187 int overflow_errno = EOVERFLOW;
189 int overflow_errno = EIO;
192 buffer = last_ts = (char *)NULL;
193 input = history_filename (filename);
194 file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
196 if ((file < 0) || (fstat (file, &finfo) == -1))
199 file_size = (size_t)finfo.st_size;
201 /* check for overflow on very large files */
202 if (file_size != finfo.st_size || file_size + 1 < file_size)
204 errno = overflow_errno;
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)
214 errno = overflow_errno;
217 chars_read = file_size;
219 buffer = (char *)malloc (file_size + 1);
222 errno = overflow_errno;
226 chars_read = read (file, buffer, file_size);
239 #ifndef HISTORY_USE_MMAP
248 /* Set TO to larger than end of file if negative. */
252 /* Start at beginning of file, work to end. */
253 bufend = buffer + chars_read;
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')
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)
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')
272 /* Change to allow Windows-like \r\n end of line delimiter. */
273 if (line_end > line_start && line_end[-1] == '\r')
280 if (HIST_TIMESTAMP_START(line_start) == 0)
282 add_history (line_start);
285 add_history_time (last_ts);
291 last_ts = line_start;
298 if (current_line >= to)
301 line_start = line_end + 1;
305 #ifndef HISTORY_USE_MMAP
308 munmap (buffer, file_size);
314 /* Truncate the history file FNAME, leaving only LINES trailing lines.
315 If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
318 history_truncate_file (fname, lines)
322 char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */
323 int file, chars_read, rv;
327 buffer = (char *)NULL;
328 filename = history_filename (fname);
329 file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
332 /* Don't try to truncate non-regular files. */
333 if (file == -1 || fstat (file, &finfo) == -1)
341 if (S_ISREG (finfo.st_mode) == 0)
352 file_size = (size_t)finfo.st_size;
354 /* check for overflow on very large files */
355 if (file_size != finfo.st_size || file_size + 1 < file_size)
360 #elif defined (EOVERFLOW)
361 rv = errno = EOVERFLOW;
368 buffer = (char *)malloc (file_size + 1);
375 chars_read = read (file, buffer, file_size);
380 rv = (chars_read < 0) ? errno : 0;
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--)
390 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
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--)
402 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
410 /* Write only if there are more lines in the file than we want to
412 if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
414 if (write (file, bp, chars_read - (bp - buffer)) < 0)
417 #if defined (__BEOS__)
418 /* BeOS ignores O_TRUNC. */
419 ftruncate (file, chars_read - (bp - buffer));
422 if (close (file) < 0 && rv == 0)
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. */
438 history_do_write (filename, nelements, overwrite)
439 const char *filename;
440 int nelements, overwrite;
443 char *output, *bakname;
445 #ifdef HISTORY_USE_MMAP
448 mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
450 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
452 output = history_filename (filename);
453 bakname = (overwrite && output) ? history_backupfile (output) : 0;
455 if (output && bakname)
456 rename (output, bakname);
458 file = output ? open (output, mode, 0600) : -1;
464 if (output && bakname)
465 rename (bakname, output);
471 #ifdef HISTORY_USE_MMAP
472 cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
475 if (nelements > history_length)
476 nelements = history_length;
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). */
481 HIST_ENTRY **the_history; /* local */
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++)
490 buffer_size += 2 + HISTENT_BYTES (the_history[i]);
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;
499 /* Allocate the buffer, and fill it. */
500 #ifdef HISTORY_USE_MMAP
501 if (ftruncate (file, buffer_size+cursize) == -1)
503 buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
504 if ((void *)buffer == MAP_FAILED)
509 if (output && bakname)
510 rename (bakname, output);
516 buffer = (char *)malloc (buffer_size);
521 if (output && bakname)
522 rename (bakname, output);
529 for (j = 0, i = history_length - nelements; i < history_length; i++)
531 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
533 strcpy (buffer + j, the_history[i]->timestamp);
534 j += strlen (the_history[i]->timestamp);
537 strcpy (buffer + j, the_history[i]->line);
538 j += strlen (the_history[i]->line);
542 #ifdef HISTORY_USE_MMAP
543 if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
546 if (write (file, buffer, buffer_size) < 0)
552 if (close (file) < 0 && rv == 0)
555 if (rv != 0 && output && bakname)
556 rename (bakname, output);
557 else if (rv == 0 && bakname)
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. */
569 append_history (nelements, filename)
571 const char *filename;
573 return (history_do_write (filename, nelements, HISTORY_APPEND));
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 ().*/
580 write_history (filename)
581 const char *filename;
583 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));