git: 988b1bb0c54e - main - sh: implement persistent history storage
Baptiste Daroussin
bapt at FreeBSD.org
Mon May 10 16:57:28 UTC 2021
The branch main has been updated by bapt:
URL: https://cgit.FreeBSD.org/src/commit/?id=988b1bb0c54e50654112f0bd649aee68307a5a80
commit 988b1bb0c54e50654112f0bd649aee68307a5a80
Author: Baptiste Daroussin <bapt at FreeBSD.org>
AuthorDate: 2021-03-30 08:28:08 +0000
Commit: Baptiste Daroussin <bapt at FreeBSD.org>
CommitDate: 2021-05-10 16:57:13 +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
Co-authored-by: pstef
Reviewed by: jilles
Differential Revision: https://reviews.freebsd.org/D29493
---
bin/sh/histedit.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++
bin/sh/main.c | 7 +++++++
bin/sh/myhistedit.h | 3 ++-
bin/sh/sh.1 | 11 +++++++++-
bin/sh/trap.c | 3 +++
5 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index ba2bec357181..596145790f31 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
+#include <fcntl.h>
#include <limits.h>
#include <paths.h>
#include <stdio.h>
@@ -78,6 +79,64 @@ static int comparator(const void *, const void *, void *);
static char **sh_matches(const char *, int, int);
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 ((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;
+ history(hist, &he, H_LOAD, histfile);
+}
+
/*
* 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 &&
More information about the dev-commits-src-main
mailing list