1 /* histfile.c - functions to manipulate the history file. */
3 /* Copyright (C) 1989-2019 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)
29 # define _XOPEN_SOURCE_EXTENDED 1
34 #if defined (HAVE_CONFIG_H)
40 #if defined (HAVE_LIMITS_H)
44 #include <sys/types.h>
45 #if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
46 # include <sys/file.h>
48 #include "posixstat.h"
51 #if defined (HAVE_STDLIB_H)
54 # include "ansi_stdlib.h"
55 #endif /* HAVE_STDLIB_H */
57 #if defined (HAVE_UNISTD_H)
67 #ifdef HISTORY_USE_MMAP
68 # include <sys/mman.h>
71 # define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
72 # define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
74 # define MAP_RFLAGS MAP_PRIVATE
75 # define MAP_WFLAGS MAP_SHARED
79 # define MAP_FAILED ((void *)-1)
82 #endif /* HISTORY_USE_MMAP */
85 # define WIN32_LEAN_AND_MEAN
89 /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
90 on win 95/98/nt), we want to open files with O_BINARY mode so that there
91 is no \n -> \r\n conversion performed. On other systems, we don't want to
92 mess around with O_BINARY at all, so we ensure that it's defined to 0. */
93 #if defined (__EMX__) || defined (__CYGWIN__)
97 #else /* !__EMX__ && !__CYGWIN__ */
100 #endif /* !__EMX__ && !__CYGWIN__ */
113 #if !defined (PATH_MAX)
114 # define PATH_MAX 1024 /* default */
117 extern void _hs_append_history_line
PARAMS((int, const char *));
119 /* history file version; currently unused */
120 int history_file_version
= 1;
122 /* If non-zero, we write timestamps to the history file in history_do_write() */
123 int history_write_timestamps
= 0;
125 /* If non-zero, we assume that a history file that starts with a timestamp
126 uses timestamp-delimited entries and can include multi-line history
127 entries. Used by read_history_range */
128 int history_multiline_entries
= 0;
130 /* Immediately after a call to read_history() or read_history_range(), this
131 will return the number of lines just read from the history file in that
133 int history_lines_read_from_file
= 0;
135 /* Immediately after a call to write_history() or history_do_write(), this
136 will return the number of lines just written to the history file in that
137 call. This also works with history_truncate_file. */
138 int history_lines_written_to_file
= 0;
140 /* Does S look like the beginning of a history timestamp entry? Placeholder
141 for more extensive tests. */
142 #define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((unsigned char)(s)[1]) )
144 static char *history_backupfile
PARAMS((const char *));
145 static char *history_tempfile
PARAMS((const char *));
146 static int histfile_backup
PARAMS((const char *, const char *));
147 static int histfile_restore
PARAMS((const char *, const char *));
148 static int history_rename
PARAMS((const char *, const char *));
150 /* Return the string that should be used in the place of this
151 filename. This only matters when you don't specify the
152 filename to read_history (), or write_history (). */
154 history_filename (const char *filename
)
160 return_val
= filename
? savestring (filename
) : (char *)NULL
;
165 home
= sh_get_env_value ("HOME");
168 home
= sh_get_env_value ("APPDATA");
174 home_len
= strlen (home
);
176 return_val
= (char *)xmalloc (2 + home_len
+ 8); /* strlen(".history") == 8 */
177 strcpy (return_val
, home
);
178 return_val
[home_len
] = '/';
179 #if defined (__MSDOS__)
180 strcpy (return_val
+ home_len
+ 1, "_history");
182 strcpy (return_val
+ home_len
+ 1, ".history");
189 history_backupfile (const char *filename
)
192 char *ret
, linkbuf
[PATH_MAX
+1];
198 #if defined (HAVE_READLINK)
199 /* Follow symlink to avoid backing up symlink itself; call will fail if
201 if ((n
= readlink (filename
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
209 ret
= xmalloc (len
+ 2);
217 history_tempfile (const char *filename
)
220 char *ret
, linkbuf
[PATH_MAX
+1];
227 #if defined (HAVE_READLINK)
228 /* Follow symlink so tempfile created in the same directory as any symlinked
229 history file; call will fail if not a symlink */
230 if ((n
= readlink (filename
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
238 ret
= xmalloc (len
+ 11);
241 pid
= (int)getpid ();
243 /* filename-PID.tmp */
245 ret
[len
+1] = (pid
/ 10000 % 10) + '0';
246 ret
[len
+2] = (pid
/ 1000 % 10) + '0';
247 ret
[len
+3] = (pid
/ 100 % 10) + '0';
248 ret
[len
+4] = (pid
/ 10 % 10) + '0';
249 ret
[len
+5] = (pid
% 10) + '0';
250 strcpy (ret
+ len
+ 6, ".tmp");
255 /* Add the contents of FILENAME to the history list, a line at a time.
256 If FILENAME is NULL, then read from ~/.history. Returns 0 if
257 successful, or errno if not. */
259 read_history (const char *filename
)
261 return (read_history_range (filename
, 0, -1));
264 /* Read a range of lines from FILENAME, adding them to the history list.
265 Start reading at the FROM'th line and end at the TO'th. If FROM
266 is zero, start at the beginning. If TO is less than FROM, read
267 until the end of the file. If FILENAME is NULL, then read from
268 ~/.history. Returns 0 if successful, or errno if not. */
270 read_history_range (const char *filename
, int from
, int to
)
272 register char *line_start
, *line_end
, *p
;
273 char *input
, *buffer
, *bufend
, *last_ts
;
274 int file
, current_line
, chars_read
, has_timestamps
, reset_comment_char
;
278 int overflow_errno
= EFBIG
;
279 #elif defined (EOVERFLOW)
280 int overflow_errno
= EOVERFLOW
;
282 int overflow_errno
= EIO
;
285 history_lines_read_from_file
= 0;
287 buffer
= last_ts
= (char *)NULL
;
288 input
= history_filename (filename
);
289 file
= input
? open (input
, O_RDONLY
|O_BINARY
, 0666) : -1;
291 if ((file
< 0) || (fstat (file
, &finfo
) == -1))
294 if (S_ISREG (finfo
.st_mode
) == 0)
304 file_size
= (size_t)finfo
.st_size
;
306 /* check for overflow on very large files */
307 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
309 errno
= overflow_errno
;
317 return 0; /* don't waste time if we don't have to */
320 #ifdef HISTORY_USE_MMAP
321 /* We map read/write and private so we can change newlines to NULs without
322 affecting the underlying object. */
323 buffer
= (char *)mmap (0, file_size
, PROT_READ
|PROT_WRITE
, MAP_RFLAGS
, file
, 0);
324 if ((void *)buffer
== MAP_FAILED
)
326 errno
= overflow_errno
;
329 chars_read
= file_size
;
331 buffer
= (char *)malloc (file_size
+ 1);
334 errno
= overflow_errno
;
338 chars_read
= read (file
, buffer
, file_size
);
351 #ifndef HISTORY_USE_MMAP
360 /* Set TO to larger than end of file if negative. */
364 /* Start at beginning of file, work to end. */
365 bufend
= buffer
+ chars_read
;
366 *bufend
= '\0'; /* null-terminate buffer for timestamp checks */
369 /* Heuristic: the history comment character rarely changes, so assume we
370 have timestamps if the buffer starts with `#[:digit:]' and temporarily
371 set history_comment_char so timestamp parsing works right */
372 reset_comment_char
= 0;
373 if (history_comment_char
== '\0' && buffer
[0] == '#' && isdigit ((unsigned char)buffer
[1]))
375 history_comment_char
= '#';
376 reset_comment_char
= 1;
379 has_timestamps
= HIST_TIMESTAMP_START (buffer
);
380 history_multiline_entries
+= has_timestamps
&& history_write_timestamps
;
382 /* Skip lines until we are at FROM. */
385 for (line_start
= line_end
= buffer
; line_end
< bufend
&& current_line
< from
; line_end
++)
386 if (*line_end
== '\n')
389 /* If we see something we think is a timestamp, continue with this
390 line. We should check more extensively here... */
391 if (HIST_TIMESTAMP_START(p
) == 0)
396 /* If we are at the last line (current_line == from) but we have
397 timestamps (has_timestamps), then line_start points to the
398 text of the last command, and we need to skip to its end. */
399 if (current_line
>= from
&& has_timestamps
)
401 for (line_end
= p
; line_end
< bufend
&& *line_end
!= '\n'; line_end
++)
403 line_start
= (*line_end
== '\n') ? line_end
+ 1 : line_end
;
407 /* If there are lines left to gobble, then gobble them now. */
408 for (line_end
= line_start
; line_end
< bufend
; line_end
++)
409 if (*line_end
== '\n')
411 /* Change to allow Windows-like \r\n end of line delimiter. */
412 if (line_end
> line_start
&& line_end
[-1] == '\r')
419 if (HIST_TIMESTAMP_START(line_start
) == 0)
421 if (last_ts
== NULL
&& history_length
> 0 && history_multiline_entries
)
422 _hs_append_history_line (history_length
- 1, line_start
);
424 add_history (line_start
);
427 add_history_time (last_ts
);
433 last_ts
= line_start
;
440 if (current_line
>= to
)
443 line_start
= line_end
+ 1;
446 history_lines_read_from_file
= current_line
;
447 if (reset_comment_char
)
448 history_comment_char
= '\0';
451 #ifndef HISTORY_USE_MMAP
454 munmap (buffer
, file_size
);
460 /* We need a special version for WIN32 because Windows rename() refuses to
461 overwrite an existing file. */
463 history_rename (const char *old
, const char *new)
466 return (MoveFileEx (old
, new, MOVEFILE_REPLACE_EXISTING
) == 0 ? -1 : 0);
468 return (rename (old
, new));
472 /* Save FILENAME to BACK, handling case where FILENAME is a symlink
473 (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
475 histfile_backup (const char *filename
, const char *back
)
477 #if defined (HAVE_READLINK)
478 char linkbuf
[PATH_MAX
+1];
481 /* Follow to target of symlink to avoid renaming symlink itself */
482 if ((n
= readlink (filename
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
485 return (history_rename (linkbuf
, back
));
488 return (history_rename (filename
, back
));
491 /* Restore ORIG from BACKUP handling case where ORIG is a symlink
492 (e.g., ~/.bash_history -> .histfiles/.bash_history.$HOSTNAME) */
494 histfile_restore (const char *backup
, const char *orig
)
496 #if defined (HAVE_READLINK)
497 char linkbuf
[PATH_MAX
+1];
500 /* Follow to target of symlink to avoid renaming symlink itself */
501 if ((n
= readlink (orig
, linkbuf
, sizeof (linkbuf
) - 1)) > 0)
504 return (history_rename (backup
, linkbuf
));
507 return (history_rename (backup
, orig
));
510 /* Should we call chown, based on whether finfo and nfinfo describe different
511 files with different owners? */
513 #define SHOULD_CHOWN(finfo, nfinfo) \
514 (finfo.st_uid != nfinfo.st_uid || finfo.st_gid != nfinfo.st_gid)
516 /* Truncate the history file FNAME, leaving only LINES trailing lines.
517 If FNAME is NULL, then use ~/.history. Writes a new file and renames
518 it to the original name. Returns 0 on success, errno on failure. */
520 history_truncate_file (const char *fname
, int lines
)
522 char *buffer
, *filename
, *tempname
, *bp
, *bp1
; /* bp1 == bp+1 */
523 int file
, chars_read
, rv
, orig_lines
, exists
, r
;
524 struct stat finfo
, nfinfo
;
527 history_lines_written_to_file
= 0;
529 buffer
= (char *)NULL
;
530 filename
= history_filename (fname
);
532 file
= filename
? open (filename
, O_RDONLY
|O_BINARY
, 0666) : -1;
535 /* Don't try to truncate non-regular files. */
536 if (file
== -1 || fstat (file
, &finfo
) == -1)
545 nfinfo
.st_uid
= finfo
.st_uid
;
546 nfinfo
.st_gid
= finfo
.st_gid
;
548 if (S_ISREG (finfo
.st_mode
) == 0)
559 file_size
= (size_t)finfo
.st_size
;
561 /* check for overflow on very large files */
562 if (file_size
!= finfo
.st_size
|| file_size
+ 1 < file_size
)
567 #elif defined (EOVERFLOW)
568 rv
= errno
= EOVERFLOW
;
575 buffer
= (char *)malloc (file_size
+ 1);
583 chars_read
= read (file
, buffer
, file_size
);
588 rv
= (chars_read
< 0) ? errno
: 0;
593 /* Count backwards from the end of buffer until we have passed
594 LINES lines. bp1 is set funny initially. But since bp[1] can't
595 be a comment character (since it's off the end) and *bp can't be
596 both a newline and the history comment character, it should be OK. */
597 for (bp1
= bp
= buffer
+ chars_read
- 1; lines
&& bp
> buffer
; bp
--)
599 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
604 /* If this is the first line, then the file contains exactly the
605 number of lines we want to truncate to, so we don't need to do
606 anything. It's the first line if we don't find a newline between
607 the current value of i and 0. Otherwise, write from the start of
608 this line until the end of the buffer. */
609 for ( ; bp
> buffer
; bp
--)
611 if (*bp
== '\n' && HIST_TIMESTAMP_START(bp1
) == 0)
619 /* Write only if there are more lines in the file than we want to
624 /* No-op if LINES == 0 at this point */
625 history_lines_written_to_file
= orig_lines
- lines
;
629 tempname
= history_tempfile (filename
);
631 if ((file
= open (tempname
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
, 0600)) != -1)
633 if (write (file
, bp
, chars_read
- (bp
- buffer
)) < 0)
636 if (fstat (file
, &nfinfo
) < 0 && rv
== 0)
639 if (close (file
) < 0 && rv
== 0)
648 history_lines_written_to_file
= orig_lines
- lines
;
650 if (rv
== 0 && filename
&& tempname
)
651 rv
= histfile_restore (tempname
, filename
);
658 history_lines_written_to_file
= 0;
661 #if defined (HAVE_CHOWN)
662 /* Make sure the new filename is owned by the same user as the old. If one
663 user is running this, it's a no-op. If the shell is running after sudo
664 with a shared history file, we don't want to leave the history file
666 if (rv
== 0 && exists
&& SHOULD_CHOWN (finfo
, nfinfo
))
667 r
= chown (filename
, finfo
.st_uid
, finfo
.st_gid
);
676 /* Workhorse function for writing history. Writes the last NELEMENT entries
677 from the history list to FILENAME. OVERWRITE is non-zero if you
678 wish to replace FILENAME with the entries. */
680 history_do_write (const char *filename
, int nelements
, int overwrite
)
683 char *output
, *tempname
, *histname
;
684 int file
, mode
, rv
, exists
;
685 struct stat finfo
, nfinfo
;
686 #ifdef HISTORY_USE_MMAP
689 history_lines_written_to_file
= 0;
691 mode
= overwrite
? O_RDWR
|O_CREAT
|O_TRUNC
|O_BINARY
: O_RDWR
|O_APPEND
|O_BINARY
;
693 mode
= overwrite
? O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
: O_WRONLY
|O_APPEND
|O_BINARY
;
695 histname
= history_filename (filename
);
696 exists
= histname
? (stat (histname
, &finfo
) == 0) : 0;
698 tempname
= (overwrite
&& exists
&& S_ISREG (finfo
.st_mode
)) ? history_tempfile (histname
) : 0;
699 output
= tempname
? tempname
: histname
;
701 file
= output
? open (output
, mode
, 0600) : -1;
712 #ifdef HISTORY_USE_MMAP
713 cursize
= overwrite
? 0 : lseek (file
, 0, SEEK_END
);
716 if (nelements
> history_length
)
717 nelements
= history_length
;
719 /* Build a buffer of all the lines to write, and write them in one syscall.
720 Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
722 HIST_ENTRY
**the_history
; /* local */
727 the_history
= history_list ();
728 /* Calculate the total number of bytes to write. */
729 for (buffer_size
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
731 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
732 buffer_size
+= strlen (the_history
[i
]->timestamp
) + 1;
733 buffer_size
+= strlen (the_history
[i
]->line
) + 1;
736 /* Allocate the buffer, and fill it. */
737 #ifdef HISTORY_USE_MMAP
738 if (ftruncate (file
, buffer_size
+cursize
) == -1)
740 buffer
= (char *)mmap (0, buffer_size
, PROT_READ
|PROT_WRITE
, MAP_WFLAGS
, file
, cursize
);
741 if ((void *)buffer
== MAP_FAILED
)
753 buffer
= (char *)malloc (buffer_size
);
766 for (j
= 0, i
= history_length
- nelements
; i
< history_length
; i
++)
768 if (history_write_timestamps
&& the_history
[i
]->timestamp
&& the_history
[i
]->timestamp
[0])
770 strcpy (buffer
+ j
, the_history
[i
]->timestamp
);
771 j
+= strlen (the_history
[i
]->timestamp
);
774 strcpy (buffer
+ j
, the_history
[i
]->line
);
775 j
+= strlen (the_history
[i
]->line
);
779 #ifdef HISTORY_USE_MMAP
780 if (msync (buffer
, buffer_size
, MS_ASYNC
) != 0 || munmap (buffer
, buffer_size
) != 0)
783 if (write (file
, buffer
, buffer_size
) < 0)
789 history_lines_written_to_file
= nelements
;
791 if (close (file
) < 0 && rv
== 0)
794 if (rv
== 0 && histname
&& tempname
)
795 rv
= histfile_restore (tempname
, histname
);
802 history_lines_written_to_file
= 0;
805 #if defined (HAVE_CHOWN)
806 /* Make sure the new filename is owned by the same user as the old. If one
807 user is running this, it's a no-op. If the shell is running after sudo
808 with a shared history file, we don't want to leave the history file
810 if (rv
== 0 && exists
)
811 mode
= chown (histname
, finfo
.st_uid
, finfo
.st_gid
);
820 /* Append NELEMENT entries to FILENAME. The entries appended are from
821 the end of the list minus NELEMENTs up to the end of the list. */
823 append_history (int nelements
, const char *filename
)
825 return (history_do_write (filename
, nelements
, HISTORY_APPEND
));
828 /* Overwrite FILENAME with the current history. If FILENAME is NULL,
829 then write the history list to ~/.history. Values returned
830 are as in read_history ().*/
832 write_history (const char *filename
)
834 return (history_do_write (filename
, history_length
, HISTORY_OVERWRITE
));