Date: Sat, 30 Apr 2022 08:04:22 GMT From: Piotr Pawel Stefaniak <pstef@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: d9d0812bc6e9 - stable/13 - sh: implement persistent history storage Message-ID: <202204300804.23U84MdW058650@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by pstef: URL: https://cgit.FreeBSD.org/src/commit/?id=d9d0812bc6e90f6d8f85ef0939357590d34c3a4a commit d9d0812bc6e90f6d8f85ef0939357590d34c3a4a Author: Baptiste Daroussin <bapt@FreeBSD.org> AuthorDate: 2021-03-30 08:28:08 +0000 Commit: Piotr Pawel Stefaniak <pstef@FreeBSD.org> CommitDate: 2022-04-30 07:55:42 +0000 sh: implement persistent history storage Implement persistent history storage: the strategy is simple at start: loads the existing .sh_history file at exit dump it. The implementation respects the HISTFILE variable and its POSIX definition: ~/.sh_history is used if HISTFILE is not set. to avoid sh to create the history file, set HISTSIZE to 0 or HISTFILE to en empty value (cherry picked from commit 988b1bb0c54e50654112f0bd649aee68307a5a80) sh: try to avoid overwriting HISTFILE produced by other shells If an attempt to load history from an existing history file was unsuccessful, do not try to save command history to that file on exit. (cherry picked from commit 1f82fb3834105fd8f1186b1c6d719d8a24738180) --- bin/sh/histedit.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/sh/main.c | 7 ++++++ bin/sh/myhistedit.h | 3 ++- bin/sh/sh.1 | 11 +++++++++- bin/sh/trap.c | 3 +++ 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c index cf6bebad4c1a..2001b80bd8ed 100644 --- a/bin/sh/histedit.c +++ b/bin/sh/histedit.c @@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/stat.h> #include <dirent.h> +#include <errno.h> +#include <fcntl.h> #include <limits.h> #include <paths.h> #include <stdbool.h> @@ -70,6 +72,7 @@ __FBSDID("$FreeBSD$"); History *hist; /* history cookie */ EditLine *el; /* editline cookie */ int displayhist; +static int savehist; static FILE *el_in, *el_out; static bool in_command_completion; @@ -81,6 +84,66 @@ static char **sh_matches(const char *, int, int); static const char *append_char_function(const char *); static unsigned char sh_complete(EditLine *, int); +static const char * +get_histfile(void) +{ + const char *histfile; + + /* don't try to save if the history size is 0 */ + if (hist == NULL || histsizeval() == 0) + return (NULL); + histfile = expandstr("${HISTFILE-${HOME-}/.sh_history}"); + + if (histfile[0] == '\0') + return (NULL); + return (histfile); +} + +void +histsave(void) +{ + HistEvent he; + char *histtmpname = NULL; + const char *histfile; + int fd; + FILE *f; + + if (!savehist || (histfile = get_histfile()) == NULL) + return; + INTOFF; + asprintf(&histtmpname, "%s.XXXXXXXXXX", histfile); + if (histtmpname == NULL) { + INTON; + return; + } + fd = mkstemp(histtmpname); + if (fd == -1 || (f = fdopen(fd, "w")) == NULL) { + free(histtmpname); + INTON; + return; + } + if (history(hist, &he, H_SAVE_FP, f) < 1 || + rename(histtmpname, histfile) == -1) + unlink(histtmpname); + fclose(f); + free(histtmpname); + INTON; + +} + +void +histload(void) +{ + const char *histfile; + HistEvent he; + + if ((histfile = get_histfile()) == NULL) + return; + errno = 0; + if (history(hist, &he, H_LOAD, histfile) != -1 || errno == ENOENT) + savehist = 1; +} + /* * Set history and editing status. Called whenever the status may * have changed (figures out what to do). diff --git a/bin/sh/main.c b/bin/sh/main.c index cbe026e13640..b0a5fac6fd4e 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -75,6 +75,9 @@ __FBSDID("$FreeBSD$"); #include "cd.h" #include "redir.h" #include "builtins.h" +#ifndef NO_HISTORY +#include "myhistedit.h" +#endif int rootpid; int rootshell; @@ -157,6 +160,10 @@ state2: read_profile(shinit); } } +#ifndef NO_HISTORY + if (iflag) + histload(); +#endif state3: state = 4; popstackmark(&smark2); diff --git a/bin/sh/myhistedit.h b/bin/sh/myhistedit.h index 968d23c9c1f8..1f513f0ae206 100644 --- a/bin/sh/myhistedit.h +++ b/bin/sh/myhistedit.h @@ -43,4 +43,5 @@ extern int displayhist; void histedit(void); void sethistsize(const char *); void setterm(const char *); - +void histload(void); +void histsave(void); diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 76335cfaa2cd..ca3faeff13af 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd July 6, 2020 +.Dd May 10, 2021 .Dt SH 1 .Os .Sh NAME @@ -1351,6 +1351,15 @@ If not set, the default editor is The default editor used with the .Ic fc built-in. +.It Va HISTFILE +File used for persistent history storage. +If unset +.Pa ~/.sh_history +will be used. +If set but empty or +.Va HISTSIZE +is set to 0 +the shell will not load and save the history. .It Va HISTSIZE The number of previous commands that are accessible. .It Va HOME diff --git a/bin/sh/trap.c b/bin/sh/trap.c index d7ef40274270..2dd394035ca4 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -535,6 +535,9 @@ exitshell_savedstatus(void) flushall(); #if JOBS setjobctl(0); +#endif +#ifndef NO_HISTORY + histsave(); #endif } if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN &&
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202204300804.23U84MdW058650>