1 /* histfile.c - functions to manipulate the history file. */
3 /* Copyright (C) 1989-2018 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 extern void _hs_append_history_line
PARAMS((int, const char *));
112 /* history file version; currently unused */
113 int history_file_version
= 1;
115 /* If non-zero, we write timestamps to the history file in history_do_write() */
116 int history_write_timestamps
= 0;
118 /* If non-zero, we assume that a history file that starts with a timestamp
119 uses timestamp-delimited entries and can include multi-line history
120 entries. Used by read_history_range */
121 int history_multiline_entries
= 0;
123 /* Immediately after a call to read_history() or read_history_range(), this
124 will return the number of lines just read from the history file in that
126 int history_lines_read_from_file
= 0;
128 /* Immediately after a call to write_history() or history_do_write(), this
129 will return the number of lines just written to the history file in that
130 call. This also works with history_truncate_file. */
131 int history_lines_written_to_file
= 0;
133 /* Does S look like the beginning of a history timestamp entry? Placeholder
134 for more extensive tests. */
135 #define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((unsigned char)(s)[1]) )
137 static char *history_backupfile
PARAMS((const char *));
138 static char *history_tempfile
PARAMS((const char *));
139 static int histfile_backup
PARAMS((const char *, const char *));
140 static int histfile_restore
PARAMS((const char *, const char *));
142 /* Return the string that should be used in the place of this
143 filename. This only matters when you don't specify the
144 filename to read_history (), or write_history (). */
146 history_filename (const char *filename
)
152 return_val
= filename
? savestring (filename
) : (char *)NULL
;
157 home
= sh_get_env_value ("HOME");
160 home
= sh_get_env_value ("APPDATA");
166 home_len
= strlen (home
);
168 return_val
= (char *)xmalloc (2 + home_len
+ 8); /* strlen(".history") == 8 */
169 strcpy (return_val
, home
);
170 return_val
[home_len
] = '/';
171 #if defined (__MSDOS__)
172 strcpy (return_val
+ home_len
+ 1, "_history");
174 strcpy (return_val
+ home_len
+ 1, ".history");
181 history_backupfile (const char *filename
)
184 char *ret
, linkbuf
[PATH_MAX
+1];
190 #if defined (HAVE_READLINK)
191 /* Follow symlink to avoid backing up symlink itself; call will fail if
193 if ((n
= readlink (filename
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
201 ret
= xmalloc (len
+ 2);
209 history_tempfile (const char *filename
)
212 char *ret
, linkbuf
[PATH_MAX
+1];
219 #if defined (HAVE_READLINK)
220 /* Follow symlink so tempfile created in the same directory as any symlinked
221 history file; call will fail if not a symlink */
222 if ((n
= readlink (filename
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
230 ret
= xmalloc (len
+ 11);
233 pid
= (int)getpid ();
235 /* filename-PID.tmp */
237 ret
[len
+1] = (pid
/ 10000 % 10) + '0';
238 ret
[len
+2] = (pid
/ 1000 % 10) + '0';
239 ret
[len
+3] = (pid
/ 100 % 10) + '0';
240 ret
[len
+4] = (pid
/ 10 % 10) + '0';
241 ret
[len
+5] = (pid
% 10) + '0';
242 strcpy (ret
+ len
+ 6, ".tmp");
247 /* Add the contents of FILENAME to the history list, a line at a time.
248 If FILENAME is NULL, then read from ~/.history. Returns 0 if
249 successful, or errno if not. */
251 read_history (const char *filename
)
253 return (read_history_range (filename
, 0, -1));
256 /* Read a range of lines from FILENAME, adding them to the history list.
257 Start reading at the FROM'th line and end at the TO'th. If FROM
258 is zero, start at the beginning. If TO is less than FROM, read
259 until the end of the file. If FILENAME is NULL, then read from
260 ~/.history. Returns 0 if successful, or errno if not. */
262 read_history_range (const char *filename
, int from
, int to
)
264 register char *line_start
, *line_end
, *p
;
265 char *input
, *buffer
, *bufend
, *last_ts
;
266 int file
, current_line
, chars_read
, has_timestamps
, reset_comment_char
;
270 int overflow_errno
= EFBIG
;
271 #elif defined (EOVERFLOW)
272 int overflow_errno
= EOVERFLOW
;
274 int overflow_errno
= EIO
;
277 history_lines_read_from_file
= 0;
279 buffer
= last_ts
= (char *)NULL
;
280 input
= history_filename (filename
);
281 file
= input
? open (input
, O_RDONLY
|O_BINARY
, 0666) : -1;
283 if ((file
< 0) || (fstat (file
, &finfo
) == -1))
286 if (S_ISREG (finfo
.st_mode
) == 0)
296 file_size
= (size_t)finfo
.st_size
;
298 /* check for overflow on very large files */
299 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
301 errno
= overflow_errno
;
308 return 0; /* don't waste time if we don't have to */
311 #ifdef HISTORY_USE_MMAP
312 /* We map read/write and private so we can change newlines to NULs without
313 affecting the underlying object. */
314 buffer
= (char *)mmap (0, file_size
, PROT_READ
|PROT_WRITE
, MAP_RFLAGS
, file
, 0);
315 if ((void *)buffer
== MAP_FAILED
)
317 errno
= overflow_errno
;
320 chars_read
= file_size
;
322 buffer
= (char *)malloc (file_size
+ 1);
325 errno
= overflow_errno
;
329 chars_read
= read (file
, buffer
, file_size
);
342 #ifndef HISTORY_USE_MMAP
351 /* Set TO to larger than end of file if negative. */
355 /* Start at beginning of file, work to end. */
356 bufend
= buffer
+ chars_read
;
357 *bufend
= '\0'; /* null-terminate buffer for timestamp checks */
360 /* Heuristic: the history comment character rarely changes, so assume we
361 have timestamps if the buffer starts with `#[:digit:]' and temporarily
362 set history_comment_char so timestamp parsing works right */
363 reset_comment_char
= 0;
364 if (history_comment_char
== '\0' && buffer
[0] == '#' && isdigit ((unsigned char)buffer
[1]))
366 history_comment_char
= '#';
367 reset_comment_char
= 1;
370 has_timestamps
= HIST_TIMESTAMP_START (buffer
);
371 history_multiline_entries
+= has_timestamps
&& history_write_timestamps
;
373 /* Skip lines until we are at FROM. */
374 for (line_start
= line_end
= buffer
; line_end
< bufend
&& current_line
< from
; line_end
++)
375 if (*line_end
== '\n')
378 /* If we see something we think is a timestamp, continue with this
379 line. We should check more extensively here... */
380 if (HIST_TIMESTAMP_START(p
) == 0)
385 /* If there are lines left to gobble, then gobble them now. */
386 for (line_end
= line_start
; line_end
< bufend
; line_end
++)
387 if (*line_end
== '\n')
389 /* Change to allow Windows-like \r\n end of line delimiter. */
390 if (line_end
> line_start
&& line_end
[-1] == '\r')
397 if (HIST_TIMESTAMP_START(line_start
) == 0)
399 if (last_ts
== NULL
&& history_length
> 0 && history_multiline_entries
)
400 _hs_append_history_line (history_length
- 1, line_start
);
402 add_history (line_start
);
405 add_history_time (last_ts
);
411 last_ts
= line_start
;
418 if (current_line
>= to
)
421 line_start
= line_end
+ 1;
424 history_lines_read_from_file
= current_line
;
425 if (reset_comment_char
)
426 history_comment_char
= '\0';
429 #ifndef HISTORY_USE_MMAP
432 munmap (buffer
, file_size
);
438 /* Save FILENAME to BACK, handling case where FILENAME is a symlink
439 (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
441 histfile_backup (const char *filename
, const char *back
)
443 #if defined (HAVE_READLINK)
444 char linkbuf
[PATH_MAX
+1];
447 /* Follow to target of symlink to avoid renaming symlink itself */
448 if ((n
= readlink (filename
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
451 return (rename (linkbuf
, back
));
454 return (rename (filename
, back
));
457 /* Restore ORIG from BACKUP handling case where ORIG is a symlink
458 (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
460 histfile_restore (const char *backup
, const char *orig
)
462 #if defined (HAVE_READLINK)
463 char linkbuf
[PATH_MAX
+1];
466 /* Follow to target of symlink to avoid renaming symlink itself */
467 if ((n
= readlink (orig
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
470 return (rename (backup
, linkbuf
));
473 return (rename (backup
, orig
));
476 /* Truncate the history file FNAME, leaving only LINES trailing lines.
477 If FNAME is NULL, then use ~/.history. Writes a new file and renames
478 it to the original name. Returns 0 on success, errno on failure. */
480 history_truncate_file (const char *fname
, int lines
)
482 char *buffer
, *filename
, *tempname
, *bp
, *bp1
; /* bp1 == bp+1 */
483 int file
, chars_read
, rv
, orig_lines
, exists
, r
;
487 history_lines_written_to_file
= 0;
489 buffer
= (char *)NULL
;
490 filename
= history_filename (fname
);
492 file
= filename
? open (filename
, O_RDONLY
|O_BINARY
, 0666) : -1;
495 /* Don't try to truncate non-regular files. */
496 if (file
== -1 || fstat (file
, &finfo
) == -1)
505 if (S_ISREG (finfo
.st_mode
) == 0)
516 file_size
= (size_t)finfo
.st_size
;
518 /* check for overflow on very large files */
519 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
524 #elif defined (EOVERFLOW)
525 rv
= errno
= EOVERFLOW
;
532 buffer
= (char *)malloc (file_size
+ 1);
540 chars_read
= read (file
, buffer
, file_size
);
545 rv
= (chars_read
< 0) ? errno
: 0;
550 /* Count backwards from the end of buffer until we have passed
551 LINES lines. bp1 is set funny initially. But since bp[1] can't
552 be a comment character (since it's off the end) and *bp can't be
553 both a newline and the history comment character, it should be OK. */
554 for (bp1
= bp
= buffer
+ chars_read
- 1; lines
&& bp
> buffer
; bp
--)
556 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
561 /* If this is the first line, then the file contains exactly the
562 number of lines we want to truncate to, so we don't need to do
563 anything. It's the first line if we don't find a newline between
564 the current value of i and 0. Otherwise, write from the start of
565 this line until the end of the buffer. */
566 for ( ; bp
> buffer
; bp
--)
568 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
576 /* Write only if there are more lines in the file than we want to
581 /* No-op if LINES == 0 at this point */
582 history_lines_written_to_file
= orig_lines
- lines
;
586 tempname
= history_tempfile (filename
);
588 if ((file
= open (tempname
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
, 0600)) != -1)
590 if (write (file
, bp
, chars_read
- (bp
- buffer
)) < 0)
593 if (close (file
) < 0 && rv
== 0)
602 history_lines_written_to_file
= orig_lines
- lines
;
604 if (rv
== 0 && filename
&& tempname
)
605 rv
= histfile_restore (tempname
, filename
);
611 history_lines_written_to_file
= 0;
614 #if defined (HAVE_CHOWN)
615 /* Make sure the new filename is owned by the same user as the old. If one
616 user is running this, it's a no-op. If the shell is running after sudo
617 with a shared history file, we don't want to leave the history file
619 if (rv
== 0 && exists
)
620 r
= chown (filename
, finfo
.st_uid
, finfo
.st_gid
);
629 /* Workhorse function for writing history. Writes the last NELEMENT entries
630 from the history list to FILENAME. OVERWRITE is non-zero if you
631 wish to replace FILENAME with the entries. */
633 history_do_write (const char *filename
, int nelements
, int overwrite
)
636 char *output
, *tempname
, *histname
;
637 int file
, mode
, rv
, exists
;
639 #ifdef HISTORY_USE_MMAP
642 history_lines_written_to_file
= 0;
644 mode
= overwrite
? O_RDWR
|O_CREAT
|O_TRUNC
|O_BINARY
: O_RDWR
|O_APPEND
|O_BINARY
;
646 mode
= overwrite
? O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
: O_WRONLY
|O_APPEND
|O_BINARY
;
648 histname
= history_filename (filename
);
649 exists
= histname
? (stat (histname
, &finfo
) == 0) : 0;
651 tempname
= (overwrite
&& exists
&& S_ISREG (finfo
.st_mode
)) ? history_tempfile (histname
) : 0;
652 output
= tempname
? tempname
: histname
;
654 file
= output
? open (output
, mode
, 0600) : -1;
665 #ifdef HISTORY_USE_MMAP
666 cursize
= overwrite
? 0 : lseek (file
, 0, SEEK_END
);
669 if (nelements
> history_length
)
670 nelements
= history_length
;
672 /* Build a buffer of all the lines to write, and write them in one syscall.
673 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
675 HIST_ENTRY
**the_history
; /* local */
680 the_history
= history_list ();
681 /* Calculate the total number of bytes to write. */
682 for (buffer_size
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
684 buffer_size
+= 2 + HISTENT_BYTES (the_history
[i
]);
687 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
688 buffer_size
+= strlen (the_history
[i
]->timestamp
) + 1;
689 buffer_size
+= strlen (the_history
[i
]->line
) + 1;
693 /* Allocate the buffer, and fill it. */
694 #ifdef HISTORY_USE_MMAP
695 if (ftruncate (file
, buffer_size
+cursize
) == -1)
697 buffer
= (char *)mmap (0, buffer_size
, PROT_READ
|PROT_WRITE
, MAP_WFLAGS
, file
, cursize
);
698 if ((void *)buffer
== MAP_FAILED
)
710 buffer
= (char *)malloc (buffer_size
);
723 for (j
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
725 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
727 strcpy (buffer
+ j
, the_history
[i
]->timestamp
);
728 j
+= strlen (the_history
[i
]->timestamp
);
731 strcpy (buffer
+ j
, the_history
[i
]->line
);
732 j
+= strlen (the_history
[i
]->line
);
736 #ifdef HISTORY_USE_MMAP
737 if (msync (buffer
, buffer_size
, MS_ASYNC
) != 0 || munmap (buffer
, buffer_size
) != 0)
740 if (write (file
, buffer
, buffer_size
) < 0)
746 history_lines_written_to_file
= nelements
;
748 if (close (file
) < 0 && rv
== 0)
751 if (rv
== 0 && histname
&& tempname
)
752 rv
= histfile_restore (tempname
, histname
);
758 history_lines_written_to_file
= 0;
761 #if defined (HAVE_CHOWN)
762 /* Make sure the new filename is owned by the same user as the old. If one
763 user is running this, it's a no-op. If the shell is running after sudo
764 with a shared history file, we don't want to leave the history file
766 if (rv
== 0 && exists
)
767 mode
= chown (histname
, finfo
.st_uid
, finfo
.st_gid
);
776 /* Append NELEMENT entries to FILENAME. The entries appended are from
777 the end of the list minus NELEMENTs up to the end of the list. */
779 append_history (int nelements
, const char *filename
)
781 return (history_do_write (filename
, nelements
, HISTORY_APPEND
));
784 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
785 then write the history list to ~/.history. Values returned
786 are as in read_history ().*/
788 write_history (const char *filename
)
790 return (history_do_write (filename
, history_length
, HISTORY_OVERWRITE
));