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)
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 (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
191 errno
= overflow_errno
;
195 #ifdef HISTORY_USE_MMAP
196 /* We map read/write and private so we can change newlines to NULs without
197 affecting the underlying object. */
198 buffer
= (char *)mmap (0, file_size
, PROT_READ
|PROT_WRITE
, MAP_RFLAGS
, file
, 0);
199 if ((void *)buffer
== MAP_FAILED
)
201 errno
= overflow_errno
;
204 chars_read
= file_size
;
206 buffer
= (char *)malloc (file_size
+ 1);
209 errno
= overflow_errno
;
213 chars_read
= read (file
, buffer
, file_size
);
226 #ifndef HISTORY_USE_MMAP
235 /* Set TO to larger than end of file if negative. */
239 /* Start at beginning of file, work to end. */
240 bufend
= buffer
+ chars_read
;
243 /* Skip lines until we are at FROM. */
244 for (line_start
= line_end
= buffer
; line_end
< bufend
&& current_line
< from
; line_end
++)
245 if (*line_end
== '\n')
248 /* If we see something we think is a timestamp, continue with this
249 line. We should check more extensively here... */
250 if (HIST_TIMESTAMP_START(p
) == 0)
255 /* If there are lines left to gobble, then gobble them now. */
256 for (line_end
= line_start
; line_end
< bufend
; line_end
++)
257 if (*line_end
== '\n')
259 if (line_end
- 1 >= line_start
&& *(line_end
- 1) == '\r')
260 *(line_end
- 1) = '\0';
266 if (HIST_TIMESTAMP_START(line_start
) == 0)
268 add_history (line_start
);
271 add_history_time (last_ts
);
277 last_ts
= line_start
;
284 if (current_line
>= to
)
287 line_start
= line_end
+ 1;
291 #ifndef HISTORY_USE_MMAP
294 munmap (buffer
, file_size
);
300 /* Truncate the history file FNAME, leaving only LINES trailing lines.
301 If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
304 history_truncate_file (fname
, lines
)
308 char *buffer
, *filename
, *bp
, *bp1
; /* bp1 == bp+1 */
309 int file
, chars_read
, rv
;
313 buffer
= (char *)NULL
;
314 filename
= history_filename (fname
);
315 file
= open (filename
, O_RDONLY
|O_BINARY
, 0666);
318 /* Don't try to truncate non-regular files. */
319 if (file
== -1 || fstat (file
, &finfo
) == -1)
327 if (S_ISREG (finfo
.st_mode
) == 0)
338 file_size
= (size_t)finfo
.st_size
;
340 /* check for overflow on very large files */
341 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
346 #elif defined (EOVERFLOW)
347 rv
= errno
= EOVERFLOW
;
354 buffer
= (char *)malloc (file_size
+ 1);
361 chars_read
= read (file
, buffer
, file_size
);
366 rv
= (chars_read
< 0) ? errno
: 0;
370 /* Count backwards from the end of buffer until we have passed
371 LINES lines. bp1 is set funny initially. But since bp[1] can't
372 be a comment character (since it's off the end) and *bp can't be
373 both a newline and the history comment character, it should be OK. */
374 for (bp1
= bp
= buffer
+ chars_read
- 1; lines
&& bp
> buffer
; bp
--)
376 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
381 /* If this is the first line, then the file contains exactly the
382 number of lines we want to truncate to, so we don't need to do
383 anything. It's the first line if we don't find a newline between
384 the current value of i and 0. Otherwise, write from the start of
385 this line until the end of the buffer. */
386 for ( ; bp
> buffer
; bp
--)
388 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
396 /* Write only if there are more lines in the file than we want to
398 if (bp
> buffer
&& ((file
= open (filename
, O_WRONLY
|O_TRUNC
|O_BINARY
, 0600)) != -1))
400 write (file
, bp
, chars_read
- (bp
- buffer
));
402 #if defined (__BEOS__)
403 /* BeOS ignores O_TRUNC. */
404 ftruncate (file
, chars_read
- (bp
- buffer
));
418 /* Workhorse function for writing history. Writes NELEMENT entries
419 from the history list to FILENAME. OVERWRITE is non-zero if you
420 wish to replace FILENAME with the entries. */
422 history_do_write (filename
, nelements
, overwrite
)
423 const char *filename
;
424 int nelements
, overwrite
;
429 #ifdef HISTORY_USE_MMAP
432 mode
= overwrite
? O_RDWR
|O_CREAT
|O_TRUNC
|O_BINARY
: O_RDWR
|O_APPEND
|O_BINARY
;
434 mode
= overwrite
? O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
: O_WRONLY
|O_APPEND
|O_BINARY
;
436 output
= history_filename (filename
);
439 if ((file
= open (output
, mode
, 0600)) == -1)
445 #ifdef HISTORY_USE_MMAP
446 cursize
= overwrite
? 0 : lseek (file
, 0, SEEK_END
);
449 if (nelements
> history_length
)
450 nelements
= history_length
;
452 /* Build a buffer of all the lines to write, and write them in one syscall.
453 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
455 HIST_ENTRY
**the_history
; /* local */
460 the_history
= history_list ();
461 /* Calculate the total number of bytes to write. */
462 for (buffer_size
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
464 buffer_size
+= 2 + HISTENT_BYTES (the_history
[i
]);
467 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
468 buffer_size
+= strlen (the_history
[i
]->timestamp
) + 1;
469 buffer_size
+= strlen (the_history
[i
]->line
) + 1;
473 /* Allocate the buffer, and fill it. */
474 #ifdef HISTORY_USE_MMAP
475 if (ftruncate (file
, buffer_size
+cursize
) == -1)
477 buffer
= (char *)mmap (0, buffer_size
, PROT_READ
|PROT_WRITE
, MAP_WFLAGS
, file
, cursize
);
478 if ((void *)buffer
== MAP_FAILED
)
487 buffer
= (char *)malloc (buffer_size
);
497 for (j
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
499 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
501 strcpy (buffer
+ j
, the_history
[i
]->timestamp
);
502 j
+= strlen (the_history
[i
]->timestamp
);
505 strcpy (buffer
+ j
, the_history
[i
]->line
);
506 j
+= strlen (the_history
[i
]->line
);
510 #ifdef HISTORY_USE_MMAP
511 if (msync (buffer
, buffer_size
, 0) != 0 || munmap (buffer
, buffer_size
) != 0)
514 if (write (file
, buffer
, buffer_size
) < 0)
527 /* Append NELEMENT entries to FILENAME. The entries appended are from
528 the end of the list minus NELEMENTs up to the end of the list. */
530 append_history (nelements
, filename
)
532 const char *filename
;
534 return (history_do_write (filename
, nelements
, HISTORY_APPEND
));
537 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
538 then write the history list to ~/.history. Values returned
539 are as in read_history ().*/
541 write_history (filename
)
542 const char *filename
;
544 return (history_do_write (filename
, history_length
, HISTORY_OVERWRITE
));
This page took 0.040809 seconds and 4 git commands to generate.