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");
128 home
= sh_get_env_value ("APPDATA");
141 home_len
= strlen (home
);
143 return_val
= (char *)xmalloc (2 + home_len
+ 8); /* strlen(".history") == 8 */
144 strcpy (return_val
, home
);
145 return_val
[home_len
] = '/';
146 #if defined (__MSDOS__)
147 strcpy (return_val
+ home_len
+ 1, "_history");
149 strcpy (return_val
+ home_len
+ 1, ".history");
155 /* Add the contents of FILENAME to the history list, a line at a time.
156 If FILENAME is NULL, then read from ~/.history. Returns 0 if
157 successful, or errno if not. */
159 read_history (filename
)
160 const char *filename
;
162 return (read_history_range (filename
, 0, -1));
165 /* Read a range of lines from FILENAME, adding them to the history list.
166 Start reading at the FROM'th line and end at the TO'th. If FROM
167 is zero, start at the beginning. If TO is less than FROM, read
168 until the end of the file. If FILENAME is NULL, then read from
169 ~/.history. Returns 0 if successful, or errno if not. */
171 read_history_range (filename
, from
, to
)
172 const char *filename
;
175 register char *line_start
, *line_end
, *p
;
176 char *input
, *buffer
, *bufend
, *last_ts
;
177 int file
, current_line
, chars_read
;
181 int overflow_errno
= EFBIG
;
182 #elif defined (EOVERFLOW)
183 int overflow_errno
= EOVERFLOW
;
185 int overflow_errno
= EIO
;
188 buffer
= last_ts
= (char *)NULL
;
189 input
= history_filename (filename
);
190 file
= input
? open (input
, O_RDONLY
|O_BINARY
, 0666) : -1;
192 if ((file
< 0) || (fstat (file
, &finfo
) == -1))
195 file_size
= (size_t)finfo
.st_size
;
197 /* check for overflow on very large files */
198 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
200 errno
= overflow_errno
;
204 #ifdef HISTORY_USE_MMAP
205 /* We map read/write and private so we can change newlines to NULs without
206 affecting the underlying object. */
207 buffer
= (char *)mmap (0, file_size
, PROT_READ
|PROT_WRITE
, MAP_RFLAGS
, file
, 0);
208 if ((void *)buffer
== MAP_FAILED
)
210 errno
= overflow_errno
;
213 chars_read
= file_size
;
215 buffer
= (char *)malloc (file_size
+ 1);
218 errno
= overflow_errno
;
222 chars_read
= read (file
, buffer
, file_size
);
235 #ifndef HISTORY_USE_MMAP
244 /* Set TO to larger than end of file if negative. */
248 /* Start at beginning of file, work to end. */
249 bufend
= buffer
+ chars_read
;
252 /* Skip lines until we are at FROM. */
253 for (line_start
= line_end
= buffer
; line_end
< bufend
&& current_line
< from
; line_end
++)
254 if (*line_end
== '\n')
257 /* If we see something we think is a timestamp, continue with this
258 line. We should check more extensively here... */
259 if (HIST_TIMESTAMP_START(p
) == 0)
264 /* If there are lines left to gobble, then gobble them now. */
265 for (line_end
= line_start
; line_end
< bufend
; line_end
++)
266 if (*line_end
== '\n')
268 /* Change to allow Windows-like \r\n end of line delimiter. */
269 if (line_end
> line_start
&& line_end
[-1] == '\r')
276 if (HIST_TIMESTAMP_START(line_start
) == 0)
278 add_history (line_start
);
281 add_history_time (last_ts
);
287 last_ts
= line_start
;
294 if (current_line
>= to
)
297 line_start
= line_end
+ 1;
301 #ifndef HISTORY_USE_MMAP
304 munmap (buffer
, file_size
);
310 /* Truncate the history file FNAME, leaving only LINES trailing lines.
311 If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
314 history_truncate_file (fname
, lines
)
318 char *buffer
, *filename
, *bp
, *bp1
; /* bp1 == bp+1 */
319 int file
, chars_read
, rv
;
323 buffer
= (char *)NULL
;
324 filename
= history_filename (fname
);
325 file
= filename
? open (filename
, O_RDONLY
|O_BINARY
, 0666) : -1;
328 /* Don't try to truncate non-regular files. */
329 if (file
== -1 || fstat (file
, &finfo
) == -1)
337 if (S_ISREG (finfo
.st_mode
) == 0)
348 file_size
= (size_t)finfo
.st_size
;
350 /* check for overflow on very large files */
351 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
356 #elif defined (EOVERFLOW)
357 rv
= errno
= EOVERFLOW
;
364 buffer
= (char *)malloc (file_size
+ 1);
371 chars_read
= read (file
, buffer
, file_size
);
376 rv
= (chars_read
< 0) ? errno
: 0;
380 /* Count backwards from the end of buffer until we have passed
381 LINES lines. bp1 is set funny initially. But since bp[1] can't
382 be a comment character (since it's off the end) and *bp can't be
383 both a newline and the history comment character, it should be OK. */
384 for (bp1
= bp
= buffer
+ chars_read
- 1; lines
&& bp
> buffer
; bp
--)
386 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
391 /* If this is the first line, then the file contains exactly the
392 number of lines we want to truncate to, so we don't need to do
393 anything. It's the first line if we don't find a newline between
394 the current value of i and 0. Otherwise, write from the start of
395 this line until the end of the buffer. */
396 for ( ; bp
> buffer
; bp
--)
398 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
406 /* Write only if there are more lines in the file than we want to
408 if (bp
> buffer
&& ((file
= open (filename
, O_WRONLY
|O_TRUNC
|O_BINARY
, 0600)) != -1))
410 write (file
, bp
, chars_read
- (bp
- buffer
));
412 #if defined (__BEOS__)
413 /* BeOS ignores O_TRUNC. */
414 ftruncate (file
, chars_read
- (bp
- buffer
));
428 /* Workhorse function for writing history. Writes NELEMENT entries
429 from the history list to FILENAME. OVERWRITE is non-zero if you
430 wish to replace FILENAME with the entries. */
432 history_do_write (filename
, nelements
, overwrite
)
433 const char *filename
;
434 int nelements
, overwrite
;
439 #ifdef HISTORY_USE_MMAP
442 mode
= overwrite
? O_RDWR
|O_CREAT
|O_TRUNC
|O_BINARY
: O_RDWR
|O_APPEND
|O_BINARY
;
444 mode
= overwrite
? O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
: O_WRONLY
|O_APPEND
|O_BINARY
;
446 output
= history_filename (filename
);
447 file
= output
? open (output
, mode
, 0600) : -1;
456 #ifdef HISTORY_USE_MMAP
457 cursize
= overwrite
? 0 : lseek (file
, 0, SEEK_END
);
460 if (nelements
> history_length
)
461 nelements
= history_length
;
463 /* Build a buffer of all the lines to write, and write them in one syscall.
464 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
466 HIST_ENTRY
**the_history
; /* local */
471 the_history
= history_list ();
472 /* Calculate the total number of bytes to write. */
473 for (buffer_size
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
475 buffer_size
+= 2 + HISTENT_BYTES (the_history
[i
]);
478 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
479 buffer_size
+= strlen (the_history
[i
]->timestamp
) + 1;
480 buffer_size
+= strlen (the_history
[i
]->line
) + 1;
484 /* Allocate the buffer, and fill it. */
485 #ifdef HISTORY_USE_MMAP
486 if (ftruncate (file
, buffer_size
+cursize
) == -1)
488 buffer
= (char *)mmap (0, buffer_size
, PROT_READ
|PROT_WRITE
, MAP_WFLAGS
, file
, cursize
);
489 if ((void *)buffer
== MAP_FAILED
)
498 buffer
= (char *)malloc (buffer_size
);
508 for (j
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
510 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
512 strcpy (buffer
+ j
, the_history
[i
]->timestamp
);
513 j
+= strlen (the_history
[i
]->timestamp
);
516 strcpy (buffer
+ j
, the_history
[i
]->line
);
517 j
+= strlen (the_history
[i
]->line
);
521 #ifdef HISTORY_USE_MMAP
522 if (msync (buffer
, buffer_size
, 0) != 0 || munmap (buffer
, buffer_size
) != 0)
525 if (write (file
, buffer
, buffer_size
) < 0)
538 /* Append NELEMENT entries to FILENAME. The entries appended are from
539 the end of the list minus NELEMENTs up to the end of the list. */
541 append_history (nelements
, filename
)
543 const char *filename
;
545 return (history_do_write (filename
, nelements
, HISTORY_APPEND
));
548 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
549 then write the history list to ~/.history. Values returned
550 are as in read_history ().*/
552 write_history (filename
)
553 const char *filename
;
555 return (history_do_write (filename
, history_length
, HISTORY_OVERWRITE
));
This page took 0.039992 seconds and 4 git commands to generate.