1 /* histfile.c - functions to manipulate the history file. */
3 /* Copyright (C) 1989, 1992 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. */
26 #define READLINE_LIBRARY
28 #if defined (HAVE_CONFIG_H)
34 #include <sys/types.h>
36 //# include <sys/file.h>
38 #include "posixstat.h"
41 #if defined (HAVE_STDLIB_H)
44 # include "ansi_stdlib.h"
45 #endif /* HAVE_STDLIB_H */
47 #if defined (HAVE_UNISTD_H)
51 #if defined (HAVE_STRING_H)
55 #endif /* !HAVE_STRING_H */
58 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
59 on win 95/98/nt), we want to open files with O_BINARY mode so that there
60 is no \n -> \r\n conversion performed. On other systems, we don't want to
61 mess around with O_BINARY at all, so we ensure that it's defined to 0. */
62 #if defined (__EMX__) || defined (__CYGWIN__)
66 #else /* !__EMX__ && !__CYGWIN__ */
69 #endif /* !__EMX__ && !__CYGWIN__ */
82 /* Return the string that should be used in the place of this
83 filename. This only matters when you don't specify the
84 filename to read_history (), or write_history (). */
86 /* L4-specific: readline does not support history file handling
89 history_filename (filename)
95 /* Add the contents of FILENAME to the history list, a line at a time.
96 If FILENAME is NULL, then read from ~/.history. Returns 0 if
97 successful, or errno if not. */
99 read_history (filename)
102 return (read_history_range (filename, 0, -1));
105 /* Read a range of lines from FILENAME, adding them to the history list.
106 Start reading at the FROM'th line and end at the TO'th. If FROM
107 is zero, start at the beginning. If TO is less than FROM, read
108 until the end of the file. If FILENAME is NULL, then read from
109 ~/.history. Returns 0 if successful, or errno if not. */
111 read_history_range (filename, from, to)
115 register int line_start, line_end;
116 char *input, *buffer;
117 int file, current_line, chars_read;
121 buffer = (char *)NULL;
122 if ((input = history_filename (filename)))
123 file = open (input, O_RDONLY|O_BINARY, 0666);
127 if ((file < 0) || (fstat (file, &finfo) == -1))
130 file_size = (size_t)finfo.st_size;
132 /* check for overflow on very large files */
133 if (file_size != finfo.st_size || file_size + 1 < file_size)
141 buffer = xmalloc (file_size + 1);
143 chars_read = read (file, buffer, file_size);
158 /* Set TO to larger than end of file if negative. */
162 /* Start at beginning of file, work to end. */
163 line_start = line_end = current_line = 0;
165 /* Skip lines until we are at FROM. */
166 while (line_start < chars_read && current_line < from)
168 for (line_end = line_start; line_end < chars_read; line_end++)
169 if (buffer[line_end] == '\n')
172 line_start = line_end + 1;
173 if (current_line == from)
178 /* If there are lines left to gobble, then gobble them now. */
179 for (line_end = line_start; line_end < chars_read; line_end++)
180 if (buffer[line_end] == '\n')
182 buffer[line_end] = '\0';
184 if (buffer[line_start])
185 add_history (buffer + line_start);
189 if (current_line >= to)
192 line_start = line_end + 1;
201 /* Truncate the history file FNAME, leaving only LINES trailing lines.
202 If FNAME is NULL, then use ~/.history. */
204 history_truncate_file (fname, lines)
209 int file, chars_read;
210 char *buffer, *filename;
214 buffer = (char *)NULL;
215 if ((filename = history_filename (fname)))
216 file = open (filename, O_RDONLY|O_BINARY, 0666);
220 if (file == -1 || fstat (file, &finfo) == -1)
223 /* Don't try to truncate non-regular files. */
224 if (S_ISREG(finfo.st_mode) == 0)
227 file_size = (size_t)finfo.st_size;
229 /* check for overflow on very large files */
230 if (file_size != finfo.st_size || file_size + 1 < file_size)
239 buffer = xmalloc (file_size + 1);
240 chars_read = read (file, buffer, file_size);
246 /* Count backwards from the end of buffer until we have passed
248 for (i = chars_read - 1; lines && i; i--)
250 if (buffer[i] == '\n')
254 /* If this is the first line, then the file contains exactly the
255 number of lines we want to truncate to, so we don't need to do
256 anything. It's the first line if we don't find a newline between
257 the current value of i and 0. Otherwise, write from the start of
258 this line until the end of the buffer. */
260 if (buffer[i] == '\n')
266 /* Write only if there are more lines in the file than we want to
268 if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
270 write (file, buffer + i, chars_read - i);
272 #if defined (__BEOS__)
273 /* BeOS ignores O_TRUNC. */
274 ftruncate (file, chars_read - i);
288 /* Workhorse function for writing history. Writes NELEMENT entries
289 from the history list to FILENAME. OVERWRITE is non-zero if you
290 wish to replace FILENAME with the entries. */
292 history_do_write (filename, nelements, overwrite)
294 int nelements, overwrite;
300 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
301 output = history_filename (filename);
303 if (!output || (file = open (output, mode, 0600)) == -1)
309 if (nelements > history_length)
310 nelements = history_length;
312 /* Build a buffer of all the lines to write, and write them in one syscall.
313 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
315 HIST_ENTRY **the_history; /* local */
319 the_history = history_list ();
320 /* Calculate the total number of bytes to write. */
321 for (buffer_size = 1, i = history_length - nelements; i < history_length; i++)
322 buffer_size += 1 + strlen (the_history[i]->line);
324 /* Allocate the buffer, and fill it. */
325 buffer = xmalloc (buffer_size);
328 for (i = history_length - nelements; i < history_length; i++)
330 strlcat (buffer, the_history[i]->line, buffer_size);
331 strlcat (buffer, "\n", buffer_size);
334 write (file, buffer, buffer_size - 1);
345 /* Append NELEMENT entries to FILENAME. The entries appended are from
346 the end of the list minus NELEMENTs up to the end of the list. */
348 append_history (nelements, filename)
352 return (history_do_write (filename, nelements, HISTORY_APPEND));
355 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
356 then write the history list to ~/.history. Values returned
357 are as in read_history ().*/
359 write_history (filename)
362 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));