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