1 /* histfile.c - functions to manipulate the history file. */
3 /* Copyright (C) 1989-2015 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 #if defined (HAVE_LIMITS_H)
42 #include <sys/types.h>
43 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
44 # include <sys/file.h>
46 #include "posixstat.h"
49 #if defined (HAVE_STDLIB_H)
52 # include "ansi_stdlib.h"
53 #endif /* HAVE_STDLIB_H */
55 #if defined (HAVE_UNISTD_H)
65 #ifdef HISTORY_USE_MMAP
66 # include <sys/mman.h>
69 # define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
70 # define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
72 # define MAP_RFLAGS MAP_PRIVATE
73 # define MAP_WFLAGS MAP_SHARED
77 # define MAP_FAILED ((void *)-1)
80 #endif /* HISTORY_USE_MMAP */
82 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
83 on win 95/98/nt), we want to open files with O_BINARY mode so that there
84 is no \n -> \r\n conversion performed. On other systems, we don't want to
85 mess around with O_BINARY at all, so we ensure that it's defined to 0. */
86 #if defined (__EMX__) || defined (__CYGWIN__)
90 #else /* !__EMX__ && !__CYGWIN__ */
93 #endif /* !__EMX__ && !__CYGWIN__ */
106 #if !defined (PATH_MAX)
107 # define PATH_MAX 1024 /* default */
110 /* If non-zero, we write timestamps to the history file in history_do_write() */
111 int history_write_timestamps = 0;
113 /* Immediately after a call to read_history() or read_history_range(), this
114 will return the number of lines just read from the history file in that
116 int history_lines_read_from_file = 0;
118 /* Immediately after a call to write_history() or history_do_write(), this
119 will return the number of lines just written to the history file in that
120 call. This also works with history_truncate_file. */
121 int history_lines_written_to_file = 0;
123 /* Does S look like the beginning of a history timestamp entry? Placeholder
124 for more extensive tests. */
125 #define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((unsigned char)(s)[1]) )
127 static char *history_backupfile PARAMS((const char *));
128 static char *history_tempfile PARAMS((const char *));
129 static int histfile_backup PARAMS((const char *, const char *));
130 static int histfile_restore PARAMS((const char *, const char *));
132 /* Return the string that should be used in the place of this
133 filename. This only matters when you don't specify the
134 filename to read_history (), or write_history (). */
136 history_filename (filename)
137 const char *filename;
143 return_val = filename ? savestring (filename) : (char *)NULL;
148 home = sh_get_env_value ("HOME");
151 home = sh_get_env_value ("APPDATA");
157 home_len = strlen (home);
159 return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
160 strcpy (return_val, home);
161 return_val[home_len] = '/';
162 #if defined (__MSDOS__)
163 strcpy (return_val + home_len + 1, "_history");
165 strcpy (return_val + home_len + 1, ".history");
172 history_backupfile (filename)
173 const char *filename;
176 char *ret, linkbuf[PATH_MAX+1];
182 #if defined (HAVE_READLINK)
183 /* Follow symlink to avoid backing up symlink itself; call will fail if
185 if ((n = readlink (filename, linkbuf, sizeof (linkbuf) - 1)) > 0)
193 ret = xmalloc (len + 2);
201 history_tempfile (filename)
202 const char *filename;
205 char *ret, linkbuf[PATH_MAX+1];
212 #if defined (HAVE_READLINK)
213 /* Follow symlink so tempfile created in the same directory as any symlinked
214 history file; call will fail if not a symlink */
215 if ((n = readlink (filename, linkbuf, sizeof (linkbuf) - 1)) > 0)
223 ret = xmalloc (len + 11);
226 pid = (int)getpid ();
228 /* filename-PID.tmp */
230 ret[len+1] = (pid / 10000 % 10) + '0';
231 ret[len+2] = (pid / 1000 % 10) + '0';
232 ret[len+3] = (pid / 100 % 10) + '0';
233 ret[len+4] = (pid / 10 % 10) + '0';
234 ret[len+5] = (pid % 10) + '0';
235 strcpy (ret + len + 6, ".tmp");
240 /* Add the contents of FILENAME to the history list, a line at a time.
241 If FILENAME is NULL, then read from ~/.history. Returns 0 if
242 successful, or errno if not. */
244 read_history (filename)
245 const char *filename;
247 return (read_history_range (filename, 0, -1));
250 /* Read a range of lines from FILENAME, adding them to the history list.
251 Start reading at the FROM'th line and end at the TO'th. If FROM
252 is zero, start at the beginning. If TO is less than FROM, read
253 until the end of the file. If FILENAME is NULL, then read from
254 ~/.history. Returns 0 if successful, or errno if not. */
256 read_history_range (filename, from, to)
257 const char *filename;
260 register char *line_start, *line_end, *p;
261 char *input, *buffer, *bufend, *last_ts;
262 int file, current_line, chars_read;
266 int overflow_errno = EFBIG;
267 #elif defined (EOVERFLOW)
268 int overflow_errno = EOVERFLOW;
270 int overflow_errno = EIO;
273 history_lines_read_from_file = 0;
275 buffer = last_ts = (char *)NULL;
276 input = history_filename (filename);
277 file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
279 if ((file < 0) || (fstat (file, &finfo) == -1))
282 file_size = (size_t)finfo.st_size;
284 /* check for overflow on very large files */
285 if (file_size != finfo.st_size || file_size + 1 < file_size)
287 errno = overflow_errno;
291 #ifdef HISTORY_USE_MMAP
292 /* We map read/write and private so we can change newlines to NULs without
293 affecting the underlying object. */
294 buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
295 if ((void *)buffer == MAP_FAILED)
297 errno = overflow_errno;
300 chars_read = file_size;
302 buffer = (char *)malloc (file_size + 1);
305 errno = overflow_errno;
309 chars_read = read (file, buffer, file_size);
322 #ifndef HISTORY_USE_MMAP
331 /* Set TO to larger than end of file if negative. */
335 /* Start at beginning of file, work to end. */
336 bufend = buffer + chars_read;
339 /* Skip lines until we are at FROM. */
340 for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
341 if (*line_end == '\n')
344 /* If we see something we think is a timestamp, continue with this
345 line. We should check more extensively here... */
346 if (HIST_TIMESTAMP_START(p) == 0)
351 /* If there are lines left to gobble, then gobble them now. */
352 for (line_end = line_start; line_end < bufend; line_end++)
353 if (*line_end == '\n')
355 /* Change to allow Windows-like \r\n end of line delimiter. */
356 if (line_end > line_start && line_end[-1] == '\r')
363 if (HIST_TIMESTAMP_START(line_start) == 0)
365 add_history (line_start);
368 add_history_time (last_ts);
374 last_ts = line_start;
381 if (current_line >= to)
384 line_start = line_end + 1;
387 history_lines_read_from_file = current_line;
390 #ifndef HISTORY_USE_MMAP
393 munmap (buffer, file_size);
399 /* Save FILENAME to BACK, handling case where FILENAME is a symlink
400 (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
402 histfile_backup (filename, back)
403 const char *filename;
406 #if defined (HAVE_READLINK)
407 char linkbuf[PATH_MAX+1];
410 /* Follow to target of symlink to avoid renaming symlink itself */
411 if ((n = readlink (filename, linkbuf, sizeof (linkbuf) - 1)) > 0)
414 return (rename (linkbuf, back));
417 return (rename (filename, back));
420 /* Restore ORIG from BACKUP handling case where ORIG is a symlink
421 (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
423 histfile_restore (backup, orig)
427 #if defined (HAVE_READLINK)
428 char linkbuf[PATH_MAX+1];
431 /* Follow to target of symlink to avoid renaming symlink itself */
432 if ((n = readlink (orig, linkbuf, sizeof (linkbuf) - 1)) > 0)
435 return (rename (backup, linkbuf));
438 return (rename (backup, orig));
441 /* Truncate the history file FNAME, leaving only LINES trailing lines.
442 If FNAME is NULL, then use ~/.history. Writes a new file and renames
443 it to the original name. Returns 0 on success, errno on failure. */
445 history_truncate_file (fname, lines)
449 char *buffer, *filename, *tempname, *bp, *bp1; /* bp1 == bp+1 */
450 int file, chars_read, rv, orig_lines, exists;
454 history_lines_written_to_file = 0;
456 buffer = (char *)NULL;
457 filename = history_filename (fname);
459 file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
462 /* Don't try to truncate non-regular files. */
463 if (file == -1 || fstat (file, &finfo) == -1)
472 if (S_ISREG (finfo.st_mode) == 0)
483 file_size = (size_t)finfo.st_size;
485 /* check for overflow on very large files */
486 if (file_size != finfo.st_size || file_size + 1 < file_size)
491 #elif defined (EOVERFLOW)
492 rv = errno = EOVERFLOW;
499 buffer = (char *)malloc (file_size + 1);
507 chars_read = read (file, buffer, file_size);
512 rv = (chars_read < 0) ? errno : 0;
517 /* Count backwards from the end of buffer until we have passed
518 LINES lines. bp1 is set funny initially. But since bp[1] can't
519 be a comment character (since it's off the end) and *bp can't be
520 both a newline and the history comment character, it should be OK. */
521 for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
523 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
528 /* If this is the first line, then the file contains exactly the
529 number of lines we want to truncate to, so we don't need to do
530 anything. It's the first line if we don't find a newline between
531 the current value of i and 0. Otherwise, write from the start of
532 this line until the end of the buffer. */
533 for ( ; bp > buffer; bp--)
535 if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
543 /* Write only if there are more lines in the file than we want to
548 /* No-op if LINES == 0 at this point */
549 history_lines_written_to_file = orig_lines - lines;
553 tempname = history_tempfile (filename);
555 if ((file = open (tempname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) != -1)
557 if (write (file, bp, chars_read - (bp - buffer)) < 0)
560 if (close (file) < 0 && rv == 0)
569 history_lines_written_to_file = orig_lines - lines;
571 if (rv == 0 && filename && tempname)
572 rv = histfile_restore (tempname, filename);
578 history_lines_written_to_file = 0;
581 /* Make sure the new filename is owned by the same user as the old. If one
582 user is running this, it's a no-op. If the shell is running after sudo
583 with a shared history file, we don't want to leave the history file
585 if (rv == 0 && exists)
586 chown (filename, finfo.st_uid, finfo.st_gid);
594 /* Workhorse function for writing history. Writes the last NELEMENT entries
595 from the history list to FILENAME. OVERWRITE is non-zero if you
596 wish to replace FILENAME with the entries. */
598 history_do_write (filename, nelements, overwrite)
599 const char *filename;
600 int nelements, overwrite;
603 char *output, *tempname, *histname;
604 int file, mode, rv, exists;
606 #ifdef HISTORY_USE_MMAP
609 history_lines_written_to_file = 0;
611 mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
613 mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
615 histname = history_filename (filename);
616 tempname = (overwrite && histname) ? history_tempfile (histname) : 0;
617 output = tempname ? tempname : histname;
618 exists = histname ? (stat (histname, &finfo) == 0) : 0;
620 file = output ? open (output, mode, 0600) : -1;
631 #ifdef HISTORY_USE_MMAP
632 cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
635 if (nelements > history_length)
636 nelements = history_length;
638 /* Build a buffer of all the lines to write, and write them in one syscall.
639 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
641 HIST_ENTRY **the_history; /* local */
646 the_history = history_list ();
647 /* Calculate the total number of bytes to write. */
648 for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
650 buffer_size += 2 + HISTENT_BYTES (the_history[i]);
653 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
654 buffer_size += strlen (the_history[i]->timestamp) + 1;
655 buffer_size += strlen (the_history[i]->line) + 1;
659 /* Allocate the buffer, and fill it. */
660 #ifdef HISTORY_USE_MMAP
661 if (ftruncate (file, buffer_size+cursize) == -1)
663 buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
664 if ((void *)buffer == MAP_FAILED)
676 buffer = (char *)malloc (buffer_size);
689 for (j = 0, i = history_length - nelements; i < history_length; i++)
691 if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
693 strcpy (buffer + j, the_history[i]->timestamp);
694 j += strlen (the_history[i]->timestamp);
697 strcpy (buffer + j, the_history[i]->line);
698 j += strlen (the_history[i]->line);
702 #ifdef HISTORY_USE_MMAP
703 if (msync (buffer, buffer_size, MS_ASYNC) != 0 || munmap (buffer, buffer_size) != 0)
706 if (write (file, buffer, buffer_size) < 0)
712 history_lines_written_to_file = nelements;
714 if (close (file) < 0 && rv == 0)
717 if (rv == 0 && histname && tempname)
718 rv = histfile_restore (tempname, histname);
724 history_lines_written_to_file = 0;
727 /* Make sure the new filename is owned by the same user as the old. If one
728 user is running this, it's a no-op. If the shell is running after sudo
729 with a shared history file, we don't want to leave the history file
731 if (rv == 0 && exists)
732 chown (histname, finfo.st_uid, finfo.st_gid);
740 /* Append NELEMENT entries to FILENAME. The entries appended are from
741 the end of the list minus NELEMENTs up to the end of the list. */
743 append_history (nelements, filename)
745 const char *filename;
747 return (history_do_write (filename, nelements, HISTORY_APPEND));
750 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
751 then write the history list to ~/.history. Values returned
752 are as in read_history ().*/
754 write_history (filename)
755 const char *filename;
757 return (history_do_write (filename, history_length, HISTORY_OVERWRITE));