1
/* histfile.c - functions to manipulate the history file. */
3
/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
5
This file contains the GNU History Library (the Library), a set of
6
routines for managing the text of previously typed lines.
8
The Library 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 2, or (at your option)
13
The Library is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
General Public License for more details.
18
The GNU General Public License is often shipped with GNU software, and
19
is generally kept in a file called COPYING or LICENSE. If you do not
20
have a copy of the license, write to the Free Software Foundation,
21
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23
/* The goal is to make the implementation transparent, so that you
24
don't have to know what data types are used, just what functions
25
you can call. I think I have done that. */
27
#define READLINE_LIBRARY
29
#if defined (__TANDEM)
33
#if defined (HAVE_CONFIG_H)
34
# include "config_readline.h"
39
#include <sys/types.h>
40
#if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
41
# include <sys/file.h>
43
#include "posixstat.h"
46
#if defined (HAVE_STDLIB_H)
49
# include "ansi_stdlib.h"
50
#endif /* HAVE_STDLIB_H */
52
#if defined (HAVE_UNISTD_H)
56
#if defined (__EMX__) || defined (__CYGWIN__)
60
#ifdef HISTORY_USE_MMAP
61
# include <sys/mman.h>
64
# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
65
# define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
67
# define MAP_RFLAGS MAP_PRIVATE
68
# define MAP_WFLAGS MAP_SHARED
72
# define MAP_FAILED ((void *)-1)
75
#endif /* HISTORY_USE_MMAP */
77
/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
78
on win 95/98/nt), we want to open files with O_BINARY mode so that there
79
is no \n -> \r\n conversion performed. On other systems, we don't want to
80
mess around with O_BINARY at all, so we ensure that it's defined to 0. */
81
#if defined (__EMX__) || defined (__CYGWIN__)
85
#else /* !__EMX__ && !__CYGWIN__ */
88
#endif /* !__EMX__ && !__CYGWIN__ */
101
/* If non-zero, we write timestamps to the history file in history_do_write() */
102
int history_write_timestamps = 0;
104
/* Does S look like the beginning of a history timestamp entry? Placeholder
105
for more extensive tests. */
106
#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char)
108
/* Return the string that should be used in the place of this
109
filename. This only matters when you don't specify the
110
filename to read_history (), or write_history (). */
112
history_filename (filename)
113
const char *filename;
119
return_val = filename ? savestring (filename) : (char *)NULL;
124
home = sh_get_env_value ("HOME");
132
home_len = strlen (home);
134
return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
135
strcpy (return_val, home);
136
return_val[home_len] = '/';
137
#if defined (__MSDOS__)
138
strcpy (return_val + home_len + 1, "_history");
140
strcpy (return_val + home_len + 1, ".history");
146
/* Add the contents of FILENAME to the history list, a line at a time.
147
If FILENAME is NULL, then read from ~/.history. Returns 0 if
148
successful, or errno if not. */
150
read_history (filename)
151
const char *filename;
153
return (read_history_range (filename, 0, -1));
156
/* Read a range of lines from FILENAME, adding them to the history list.
157
Start reading at the FROM'th line and end at the TO'th. If FROM
158
is zero, start at the beginning. If TO is less than FROM, read
159
until the end of the file. If FILENAME is NULL, then read from
160
~/.history. Returns 0 if successful, or errno if not. */
162
read_history_range (filename, from, to)
163
const char *filename;
166
register char *line_start, *line_end, *p;
167
char *input, *buffer, *bufend, *last_ts;
168
int file, current_line, chars_read;
172
int overflow_errno = EFBIG;
173
#elif defined (EOVERFLOW)
174
int overflow_errno = EOVERFLOW;
176
int overflow_errno = EIO;
179
buffer = last_ts = (char *)NULL;
180
input = history_filename (filename);
181
file = open (input, O_RDONLY|O_BINARY, 0666);
183
if ((file < 0) || (fstat (file, &finfo) == -1))
186
file_size = (size_t)finfo.st_size;
188
/* check for overflow on very large files */
189
if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
190
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;
314
size_t bytes_written;
316
buffer = (char *)NULL;
317
filename = history_filename (fname);
318
file = open (filename, O_RDONLY|O_BINARY, 0666);
321
/* Don't try to truncate non-regular files. */
322
if (file == -1 || fstat (file, &finfo) == -1)
330
if (S_ISREG (finfo.st_mode) == 0)
341
file_size = (size_t)finfo.st_size;
343
/* check for overflow on very large files */
344
if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) ||
345
file_size + 1 < file_size)
350
#elif defined (EOVERFLOW)
351
rv = errno = EOVERFLOW;
358
buffer = (char *)malloc (file_size + 1);
365
chars_read = read (file, buffer, file_size);
370
rv = (chars_read < 0) ? errno : 0;
374
/* Count backwards from the end of buffer until we have passed
375
LINES lines. bp1 is set funny initially. But since bp[1] can't
376
be a comment character (since it's off the end) and *bp can't be
377
both a newline and the history comment character, it should be OK. */
378
for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
380
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
385
/* If this is the first line, then the file contains exactly the
386
number of lines we want to truncate to, so we don't need to do
387
anything. It's the first line if we don't find a newline between
388
the current value of i and 0. Otherwise, write from the start of
389
this line until the end of the buffer. */
390
for ( ; bp > buffer; bp--)
392
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
400
/* Write only if there are more lines in the file than we want to
402
if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
404
bytes_written= write (file, bp, chars_read - (bp - buffer));
406
#if defined (__BEOS__)
407
/* BeOS ignores O_TRUNC. */
408
ftruncate (file, chars_read - (bp - buffer));
422
/* Workhorse function for writing history. Writes NELEMENT entries
423
from the history list to FILENAME. OVERWRITE is non-zero if you
424
wish to replace FILENAME with the entries. */
426
history_do_write (filename, nelements, overwrite)
427
const char *filename;
428
int nelements, overwrite;
433
#ifdef HISTORY_USE_MMAP
436
mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
438
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
440
output = history_filename (filename);
443
if ((file = open (output, mode, 0600)) == -1)
449
#ifdef HISTORY_USE_MMAP
450
cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
453
if (nelements > history_length)
454
nelements = history_length;
456
/* Build a buffer of all the lines to write, and write them in one syscall.
457
Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
459
HIST_ENTRY **the_history; /* local */
464
the_history = history_list ();
465
/* Calculate the total number of bytes to write. */
466
for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
468
buffer_size += 2 + HISTENT_BYTES (the_history[i]);
471
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
472
buffer_size += strlen (the_history[i]->timestamp) + 1;
473
buffer_size += strlen (the_history[i]->line) + 1;
477
/* Allocate the buffer, and fill it. */
478
#ifdef HISTORY_USE_MMAP
479
if (ftruncate (file, buffer_size+cursize) == -1)
481
buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
482
if ((void *)buffer == MAP_FAILED)
491
buffer = (char *)malloc (buffer_size);
501
for (j = 0, i = history_length - nelements; i < history_length; i++)
503
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
505
strcpy (buffer + j, the_history[i]->timestamp);
506
j += strlen (the_history[i]->timestamp);
509
strcpy (buffer + j, the_history[i]->line);
510
j += strlen (the_history[i]->line);
514
#ifdef HISTORY_USE_MMAP
515
if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
518
if (write (file, buffer, buffer_size) < 0)
531
/* Append NELEMENT entries to FILENAME. The entries appended are from
532
the end of the list minus NELEMENTs up to the end of the list. */
534
append_history (nelements, filename)
536
const char *filename;
538
return (history_do_write (filename, nelements, HISTORY_APPEND));
541
/* Overwrite FILENAME with the current history. If FILENAME is NULL,
542
then write the history list to ~/.history. Values returned
543
are as in read_history ().*/
545
write_history (filename)
546
const char *filename;
548
return (history_do_write (filename, history_length, HISTORY_OVERWRITE));