Module Name:    src
Committed By:   kre
Date:           Sat Jul 13 13:43:58 UTC 2024

Modified Files:
        src/bin/sh: histedit.c input.c myhistedit.h mystring.c mystring.h sh.1
            trap.c var.c var.h

Log Message:
Implement the HISTFILE and HISTAPPEND variables.

See the (newly updated) sh(1) for details.
Also add the -z option to fc (clear history).

None of this exists in SMALL shells.


To generate a diff of this commit:
cvs rdiff -u -r1.70 -r1.71 src/bin/sh/histedit.c
cvs rdiff -u -r1.72 -r1.73 src/bin/sh/input.c
cvs rdiff -u -r1.15 -r1.16 src/bin/sh/myhistedit.h
cvs rdiff -u -r1.20 -r1.21 src/bin/sh/mystring.c
cvs rdiff -u -r1.11 -r1.12 src/bin/sh/mystring.h
cvs rdiff -u -r1.261 -r1.262 src/bin/sh/sh.1
cvs rdiff -u -r1.56 -r1.57 src/bin/sh/trap.c
cvs rdiff -u -r1.83 -r1.84 src/bin/sh/var.c
cvs rdiff -u -r1.40 -r1.41 src/bin/sh/var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/histedit.c
diff -u src/bin/sh/histedit.c:1.70 src/bin/sh/histedit.c:1.71
--- src/bin/sh/histedit.c:1.70	Fri Jul 12 07:30:30 2024
+++ src/bin/sh/histedit.c	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: histedit.c,v 1.70 2024/07/12 07:30:30 kre Exp $	*/
+/*	$NetBSD: histedit.c,v 1.71 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -37,13 +37,15 @@
 #if 0
 static char sccsid[] = "@(#)histedit.c	8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: histedit.c,v 1.70 2024/07/12 07:30:30 kre Exp $");
+__RCSID("$NetBSD: histedit.c,v 1.71 2024/07/13 13:43:58 kre Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <paths.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -62,6 +64,7 @@ __RCSID("$NetBSD: histedit.c,v 1.70 2024
 #include "myhistedit.h"
 #include "error.h"
 #include "alias.h"
+#include "redir.h"
 
 #ifndef SMALL		/* almost all the rest of this file */
 
@@ -78,6 +81,11 @@ int displayhist;
 static FILE *el_in, *el_out;
 static int curpos;
 
+static char *HistFile = NULL;
+static const char *HistFileOpen = NULL;
+FILE *HistFP = NULL;
+static int History_fd;
+
 #ifdef DEBUG
 extern FILE *tracefile;
 #endif
@@ -88,6 +96,7 @@ static int str_to_event(const char *, in
 static int comparator(const void *, const void *);
 static char **sh_matches(const char *, int, int);
 static unsigned char sh_complete(EditLine *, int);
+static FILE *Hist_File_Open(const char *);
 
 /*
  * Set history and editing status.  Called whenever the status may
@@ -112,9 +121,10 @@ histedit(void)
 			hist = history_init();
 			INTON;
 
-			if (hist != NULL)
+			if (hist != NULL) {
 				sethistsize(histsizeval(), histsizeflags());
-			else
+				sethistfile(histfileval(), histfileflags());
+			} else
 				out2str("sh: can't initialize history\n");
 		}
 		if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
@@ -260,13 +270,294 @@ sethistsize(char *hs, int flags)
 
 	if (hist != NULL) {
 		INTOFF;
-		history(hist, &he, H_SETSIZE, histsize);
+		/* H_SETSIZE actually sets n-1 as the limit */
+		history(hist, &he, H_SETSIZE, histsize + 1);
 		history(hist, &he, H_SETUNIQUE, 1);
 		INTON;
 	}
 }
 
 void
+sethistfile(char *hs, int flags)
+{
+	const char *file;
+	HistEvent he;
+
+	CTRACE(DBG_HISTORY, ("Set HISTFILE=%s [%x] %s\n",
+	    (hs == NULL ? "''" : hs), flags, "!hist" + (hist != NULL)));
+
+	if (hs == NULL || *hs == '\0' || (flags & VUNSET)) {
+		if (HistFP != NULL) {
+			fclose(HistFP);
+			HistFP = NULL;
+		}
+		if (HistFile != NULL) {
+			free(HistFile);
+			HistFile = NULL;
+			HistFileOpen = NULL;
+		}
+		return;
+	}
+
+	if (hist != NULL) {
+		file = expandvar(hs, flags);
+		if (file == NULL || *file == '\0')
+			return;
+
+		INTOFF;
+
+		history(hist, &he, H_LOAD, file);
+
+		/*
+		 * This is needed so sethistappend() can work
+		 * on the current (new) filename, not the previous one.
+		 */
+		if (HistFile != NULL)
+			free(HistFile);
+
+		HistFile = strdup(hs);
+		/*
+		 * We need to ensure that HistFile & HistFileOpen
+		 * are not equal .. we know HistFile has just altered.
+		 * If they happen to be equal (both NULL perhaps, or
+		 * the strdup() just above happned to return the same
+		 * buffer as was freed the line before) then simply
+		 * set HistFileOpen to something which cannot be the
+		 * same as anything allocated, or NULL.   Its only
+		 * use is to compare against HistFile.
+		 */
+		if (HistFile == HistFileOpen)
+			HistFileOpen = "";
+
+		sethistappend((histappflags() & VUNSET) ? NULL : histappval(),
+			~VUNSET & 0xFFFF);
+
+		INTON;
+	}
+}
+
+void
+sethistappend(char *s, int flags __diagused)
+{
+	CTRACE(DBG_HISTORY, ("Set HISTAPPEND=%s [%x] %s ",
+	    (s == NULL ? "''" : s), flags, "!hist" + (hist != NULL)));
+
+	INTOFF;
+	if (flags & VUNSET || !boolstr(s)) {
+		CTRACE(DBG_HISTORY, ("off"));
+
+		if (HistFP != NULL) {
+			CTRACE(DBG_HISTORY, (" closing"));
+
+			fclose(HistFP);
+			HistFP = NULL;
+			HistFileOpen = NULL;
+		}
+	} else {
+		CTRACE(DBG_HISTORY, ("on"));
+
+		if (HistFileOpen != HistFile || HistFP == NULL) {
+			if (HistFP != NULL) {
+				CTRACE(DBG_HISTORY, (" closing prev"));
+				fclose(HistFP);
+				HistFP = NULL;
+			}
+			if (hist != NULL &&
+			    HistFile != NULL &&
+			    HistFP == NULL) {
+				CTRACE(DBG_HISTORY, ("\n"));
+
+				save_sh_history();
+
+				CTRACE(DBG_HISTORY, ("opening: "));
+
+				HistFP = Hist_File_Open(HistFile);
+				if (HistFP != NULL)
+					HistFileOpen = HistFile;
+				else {
+					CTRACE(DBG_HISTORY, ("open failed"));
+				}
+			}
+		}
+	}
+	INTON;
+
+	CTRACE(DBG_HISTORY, ("\n"));
+}
+
+static void
+History_FD_Renumbered(int from, int to)
+{
+	if (History_fd == from)
+		History_fd = to;
+
+	VTRACE(DBG_HISTORY, ("History_FD_Renumbered(%d,%d)-> %d\n",
+	    from, to, History_fd));
+}
+
+/*
+ * The callback functions for the FILE* returned by funopen2()
+ */
+static ssize_t
+Hist_Write(void *cookie, const void *buf, size_t len)
+{
+	if (cookie != (void *)&History_fd) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	return write(History_fd, buf, len);
+}
+
+static int
+Hist_Close(void *cookie)
+{
+	if (cookie == (void *)&History_fd) {
+		sh_close(History_fd);
+		History_fd = -1;
+		return 0;
+	}
+
+	VTRACE(DBG_HISTORY, ("HistClose(%p) != %p\n", cookie, &History_fd));
+
+	errno = EINVAL;
+	return -1;
+}
+
+static off_t
+Hist_Seek(void *cookie, off_t pos, int whence)
+{
+	if (cookie != (void *)&History_fd) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	return lseek(History_fd, pos, whence);
+}
+
+/*
+ * a variant of open() for history files.
+ */
+static int
+open_history_file(const char *name, int mode)
+{
+	int fd;
+	struct stat statb;
+
+	fd = open(name, mode, S_IWUSR|S_IRUSR);
+
+	VTRACE(DBG_HISTORY, ("open_history_file(\"%s\", %#x) -> %d\n",
+	    name, mode, fd));
+
+	if (fd == -1)
+		return -1;
+
+	if (fstat(fd, &statb) == -1) {
+		VTRACE(DBG_HISTORY, ("history file fstat(%d) failed [%d]\n",
+		    fd, errno));
+		close(fd);
+		return -1;
+	}
+
+	if (statb.st_uid != getuid()) {
+		VTRACE(DBG_HISTORY,
+		    ("history file wrong user (uid=%d file=%d)\n",
+			getuid(), statb.st_uid));
+		close(fd);
+		return -1;
+	}
+
+	return fd;
+}
+
+static FILE *
+Hist_File_Open(const char *name)
+{
+	FILE *fd;
+	int n;
+
+	INTOFF;
+
+	n = open_history_file(name, O_WRONLY|O_CREAT|O_APPEND|O_CLOEXEC);
+
+	VTRACE(DBG_HISTORY, ("History_File_Open(\"%s\") -> %d", name, n));
+	if (n == -1) {
+		VTRACE(DBG_HISTORY, (" [%d]\n", errno));
+		INTON;
+		return NULL;
+	}
+
+	n = to_upper_fd(n);
+	(void) lseek(n, 0, SEEK_END);
+	VTRACE(DBG_HISTORY, (" -> %d", n));
+
+	History_fd = n;
+	register_sh_fd(n, History_FD_Renumbered);
+
+	if ((fd =
+	    funopen2(&History_fd, NULL, Hist_Write, Hist_Seek, NULL,
+		     Hist_Close)) == NULL) {
+
+		VTRACE(DBG_HISTORY, ("; funopen2 failed[%d]\n", errno));
+
+		sh_close(n);
+		History_fd = -1;
+		INTON;
+		return NULL;
+	}
+	setlinebuf(fd);
+
+	VTRACE(DBG_HISTORY, (" fd:%p\n", fd));
+
+	INTON;
+
+	return fd;
+}
+
+void
+save_sh_history(void)
+{
+	char *var;
+	const char *file;
+	int fd;
+	FILE *fp;
+	HistEvent he;
+
+	if (HistFP != NULL) {
+		/* don't close, just make sure nothing in buffer */
+		(void) fflush(HistFP);
+		return;
+	}
+
+	if (hist == NULL)
+		return;
+
+	var = histfileval();
+	if ((histfileflags() & VUNSET) || *var == '\0')
+		return;
+
+	file = expandvar(var, histfileflags());
+
+	VTRACE(DBG_HISTORY,
+	    ("save_sh_history('%s')\n", file == NULL ? "" : file));
+
+	if (file == NULL || *file == '\0')
+		return;
+
+	INTOFF;
+	fd = open_history_file(file, O_WRONLY|O_CREAT|O_TRUNC);
+	if (fd != -1) {
+		fp = fdopen(fd, "w");
+		if (fp != NULL) {
+			(void) history(hist, &he, H_SAVE_FP, fp);
+			fclose(fp);
+		} else
+			close(fd);
+	}
+	INTON;
+}
+
+void
 setterm(char *term, int flags __unused)
 {
 	INTOFF;
@@ -278,6 +569,9 @@ setterm(char *term, int flags __unused)
 	INTON;
 }
 
+/*
+ * The built-in sh commands supported by this file
+ */
 int
 inputrc(int argc, char **argv)
 {
@@ -313,7 +607,7 @@ histcmd(volatile int argc, char ** volat
 	int ch;
 	const char * volatile editor = NULL;
 	HistEvent he;
-	volatile int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
+	volatile int lflg = 0, nflg = 0, rflg = 0, sflg = 0, zflg = 0;
 	int i, retval;
 	const char *firststr, *laststr;
 	int first, last, direction;
@@ -341,7 +635,7 @@ histcmd(volatile int argc, char ** volat
 
 	optreset = 1; optind = 1; /* initialize getopt */
 	while (not_fcnumber(argv[optind]) &&
-	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
+	      (ch = getopt(argc, argv, ":e:lnrsz")) != -1)
 		switch ((char)ch) {
 		case 'e':
 			editor = optarg;
@@ -363,6 +657,10 @@ histcmd(volatile int argc, char ** volat
 			sflg = 1;
 			VTRACE(DBG_HISTORY, ("histcmd -s\n"));
 			break;
+		case 'z':
+			zflg = 1;
+			VTRACE(DBG_HISTORY, ("histcmd -z\n"));
+			break;
 		case ':':
 			error("option -%c expects argument", optopt);
 			/* NOTREACHED */
@@ -373,6 +671,15 @@ histcmd(volatile int argc, char ** volat
 		}
 	argc -= optind, argv += optind;
 
+	if (zflg) {
+		if (argc != 0 || (lflg|nflg|rflg|sflg) != 0)
+			error("Usage: fc -z");
+
+		history(hist, &he, H_CLEAR);
+		return 0;
+	}
+
+
 	/*
 	 * If executing...
 	 */
@@ -446,7 +753,7 @@ histcmd(volatile int argc, char ** volat
 			firststr = "-16";
 			laststr = "-1";
 		} else
-			firststr = laststr = "-1";
+			firststr = laststr = "-1";	/* the exact same str */
 		break;
 	case 1:
 		firststr = argv[0];
@@ -588,6 +895,10 @@ histcmd(volatile int argc, char ** volat
 	return 0;
 }
 
+/*
+ * and finally worker functions for those built-ins
+ */
+
 static const char *
 fc_replace(const char *s, char *p, char *r)
 {

Index: src/bin/sh/input.c
diff -u src/bin/sh/input.c:1.72 src/bin/sh/input.c:1.73
--- src/bin/sh/input.c:1.72	Tue Feb 16 15:30:26 2021
+++ src/bin/sh/input.c	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: input.c,v 1.72 2021/02/16 15:30:26 kre Exp $	*/
+/*	$NetBSD: input.c,v 1.73 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
 #else
-__RCSID("$NetBSD: input.c,v 1.72 2021/02/16 15:30:26 kre Exp $");
+__RCSID("$NetBSD: input.c,v 1.73 2024/07/13 13:43:58 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -338,6 +338,10 @@ preadbuffer(void)
 		INTOFF;
 		history(hist, &he, whichprompt != 2 ? H_ENTER : H_APPEND,
 		    parsenextc);
+		if (whichprompt != 2 && HistFP != NULL) {
+			history(hist, &he, H_NSAVE_FP, (size_t)0, HistFP);
+			fflush(HistFP);
+		}
 		INTON;
 	}
 #endif

Index: src/bin/sh/myhistedit.h
diff -u src/bin/sh/myhistedit.h:1.15 src/bin/sh/myhistedit.h:1.16
--- src/bin/sh/myhistedit.h:1.15	Fri Jul 12 07:30:30 2024
+++ src/bin/sh/myhistedit.h	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: myhistedit.h,v 1.15 2024/07/12 07:30:30 kre Exp $	*/
+/*	$NetBSD: myhistedit.h,v 1.16 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -41,7 +41,13 @@ extern int displayhist;
 
 void histedit(void);
 void sethistsize(char *, int);
+void sethistfile(char *, int);
+void sethistappend(char *, int);
+void save_sh_history(void);
 void setterm(char *, int);
 int inputrc(int, char **);
 void set_editrc(char *, int);
 void set_prompt_lit(char *, int);
+
+#include <stdio.h>
+extern FILE *HistFP;

Index: src/bin/sh/mystring.c
diff -u src/bin/sh/mystring.c:1.20 src/bin/sh/mystring.c:1.21
--- src/bin/sh/mystring.c:1.20	Fri Apr  7 10:34:13 2023
+++ src/bin/sh/mystring.c	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mystring.c,v 1.20 2023/04/07 10:34:13 kre Exp $	*/
+/*	$NetBSD: mystring.c,v 1.21 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)mystring.c	8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: mystring.c,v 1.20 2023/04/07 10:34:13 kre Exp $");
+__RCSID("$NetBSD: mystring.c,v 1.21 2024/07/13 13:43:58 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -54,6 +54,8 @@ __RCSID("$NetBSD: mystring.c,v 1.20 2023
 #include <inttypes.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <strings.h>
+
 #include "shell.h"
 #include "syntax.h"
 #include "error.h"
@@ -138,3 +140,29 @@ is_number(const char *p)
 	} while (*++p != '\0');
 	return 1;
 }
+
+/*
+ * Check a string for common representations of yes/true/...
+ * Default result is false
+ */
+
+int
+boolstr(const char *s)
+{
+	size_t len;
+
+	if (s == NULL)
+		return 0;
+
+	len = strlen(s);
+	if (len == 0)
+		return 0;
+
+	if (strncasecmp(s, "true", len) == 0		||
+	    strncasecmp(s, "yes", len) == 0		||
+	    (len == 2 && strcasecmp(s, "on") == 0)	||
+	    is_digit(*s) || atoi(s) != 0)
+		return 1;
+
+	return 0;
+}

Index: src/bin/sh/mystring.h
diff -u src/bin/sh/mystring.h:1.11 src/bin/sh/mystring.h:1.12
--- src/bin/sh/mystring.h:1.11	Thu Aug  7 09:05:35 2003
+++ src/bin/sh/mystring.h	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $	*/
+/*	$NetBSD: mystring.h,v 1.12 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -40,6 +40,7 @@ void scopyn(const char *, char *, int);
 int prefix(const char *, const char *);
 int number(const char *);
 int is_number(const char *);
+int boolstr(const char *);
 
 #define equal(s1, s2)	(strcmp(s1, s2) == 0)
 #define scopy(s1, s2)	((void)strcpy(s2, s1))

Index: src/bin/sh/sh.1
diff -u src/bin/sh/sh.1:1.261 src/bin/sh/sh.1:1.262
--- src/bin/sh/sh.1:1.261	Sat Jul 13 07:11:20 2024
+++ src/bin/sh/sh.1	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-.\"	$NetBSD: sh.1,v 1.261 2024/07/13 07:11:20 kre Exp $
+.\"	$NetBSD: sh.1,v 1.262 2024/07/13 13:43:58 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
 .\"
-.Dd April 12, 2024
+.Dd July 13, 2024
 .Dt SH 1
 .\" everything except c o and s (keep them ordered)
 .ds flags abCEeFfhIiLlmnpquVvXx
@@ -781,8 +781,6 @@ generate are treated as quoted in this c
 .\"
 .\"
 .Ss Dollar Single Quotes ( Li \&$'...' )
-.\"
-.Pp
 Enclosing characters in a matched pair of single quotes, with the
 first immediately preceded by an unquoted dollar sign
 .Pq Li \&$
@@ -2904,6 +2902,8 @@ and creating it again \(en provided the 
 .It Ic fc Oo Fl e Ar editor Oc Op Ar first Op Ar last
 .It Ic fc Fl l Oo Fl nr Oc Op Ar first Op Ar last
 .It Ic fc Fl s Oo Ar old=new Oc Op Ar first
+.It Ic fc Fl z
+.Pp
 The
 .Ic fc
 built-in lists, or edits and re-executes, commands previously entered
@@ -2951,6 +2951,9 @@ nor
 .Fl s ) .
 .It Fl s
 Re-execute the command without invoking an editor.
+.It Fl z
+Clear the history buffer.
+No other options or arguments are permitted.
 .It Ar first
 .It Ar last
 Select the commands to list or edit.
@@ -2989,6 +2992,14 @@ The following environment variables affe
 .Bl -tag -width HISTSIZE
 .It Ev FCEDIT
 Name of the editor to use.
+If
+.Ev FCEDIT
+is not set,
+.Ev EDITOR
+is used, if set.
+If neither is used the
+.Ic ed
+utility is used.
 .It Ev HISTSIZE
 The number of previous commands that are accessible.
 .El
@@ -4748,8 +4759,72 @@ If set it loses its special properties, 
 See the
 .Ic specialvar
 built-in command for remedial action.
+.It Ev HISTAPPEND
+If set to one of
+.Ql true ,
+.Ql yes ,
+.Ql on ,
+or an integral value greater than zero,
+and if
+.Ev HISTFILE
+is also set, and is a valid history file,
+then as commands are read and added to the
+history buffer, they are also written to the
+.Ev HISTFILE
+named.
+.It Ev HISTFILE
+When assigned to in an interactive shell
+the contents of the file named by expanding
+the new value of
+.Ev HISTFILE
+will, if it exists,
+can be opened for reading,
+and is a suitable
+.Nm
+history file (one previously written by
+.Nm ) , 
+be read into the history buffer, 
+appending its contents to any existing history entries.
+If
+.Ev HISTFILE
+is set when
+.Nm
+exits,
+after any EXIT trap has been evaluated,
+and if
+.Ev HISTAPPEND
+is not enabled,
+or if
+.Ev HISTFILE
+is assigned when HISTAPPEND is enabled,
+or if
+.Ev HISTAPPEND
+is enabled when
+.Ev HISTFILE
+is set,
+the contents of the history buffer will be written
+to the file named after expanding this variable.
+If the file named did not previously exist, it will be created.
+If it did exist, it must be writable.
+The file will be truncated, and then if owned by the current user,
+the current history buffer will be written to it.
+.Pp
+When used for reading or writing history entries,
+variable and arithmetic expansions are performed,
+upon its value to produce a file name, and if the
+.Ev HISTFILE
+variable was set by this shell,
+rather than obtained from the environment,
+command substitutions will also be performed.
+No file will be used if an expansion error occurs,
+or if there is a command substitution in a value obtained
+from the environment.
 .It Ev HISTSIZE
 The number of lines in the history buffer for the shell.
+If unset, or set to an empty string, 100 lines will be used.
+Attempts to set HISTSIZE to anything other than a string of
+digits will generate an error.
+An invalid value found in the environment will be ignored.
 .It Ev HOME
 Set automatically by
 .Xr login 1
@@ -4757,7 +4832,7 @@ from the user's login directory in the p
 .Pq Xr passwd 5 .
 This environment variable also functions as the default argument for the
 .Ic cd
-built-in.
+built-in, and as the value of a tilde expansion without a user name.
 .It Ev HOSTNAME
 Set to the current hostname of the system, as returned by
 .Xr gethostname 3 .

Index: src/bin/sh/trap.c
diff -u src/bin/sh/trap.c:1.56 src/bin/sh/trap.c:1.57
--- src/bin/sh/trap.c:1.56	Wed Nov 10 15:26:34 2021
+++ src/bin/sh/trap.c	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.56 2021/11/10 15:26:34 kre Exp $	*/
+/*	$NetBSD: trap.c,v 1.57 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)trap.c	8.5 (Berkeley) 6/5/95";
 #else
-__RCSID("$NetBSD: trap.c,v 1.56 2021/11/10 15:26:34 kre Exp $");
+__RCSID("$NetBSD: trap.c,v 1.57 2024/07/13 13:43:58 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -70,6 +70,9 @@ __RCSID("$NetBSD: trap.c,v 1.56 2021/11/
 #include "mystring.h"
 #include "var.h"
 
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
 
 /*
  * Sigmode records the current value of the signal handlers for the various
@@ -885,6 +888,11 @@ exitshell_savedstatus(void)
 
 	INTOFF;			/*  we're done, no more interrupts. */
 
+#ifndef SMALL
+	if (rootshell)
+		save_sh_history();
+#endif
+
 	if (!setjmp(loc.loc)) {
 		handler = &loc;		/* probably unnecessary */
 		flushall();

Index: src/bin/sh/var.c
diff -u src/bin/sh/var.c:1.83 src/bin/sh/var.c:1.84
--- src/bin/sh/var.c:1.83	Fri Jul 12 07:30:30 2024
+++ src/bin/sh/var.c	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.83 2024/07/12 07:30:30 kre Exp $	*/
+/*	$NetBSD: var.c,v 1.84 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: var.c,v 1.83 2024/07/12 07:30:30 kre Exp $");
+__RCSID("$NetBSD: var.c,v 1.84 2024/07/13 13:43:58 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -107,6 +107,8 @@ struct localvar *localvars;
 
 #ifndef SMALL
 struct var vhistsize;
+struct var vhistfile;
+struct var vhistappend;
 struct var vterm;
 struct var editrc;
 struct var ps_lit;
@@ -142,6 +144,10 @@ const struct varinit varinit[] = {
 #ifndef SMALL
 	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
 	   { .set_func= sethistsize } },
+	{ &vhistfile,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTFILE=",
+	   { .set_func= sethistfile } },
+	{ &vhistappend,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTAPPEND=",
+	   { .set_func= sethistappend } },
 #endif
 	{ &vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",
 	   { NULL } },

Index: src/bin/sh/var.h
diff -u src/bin/sh/var.h:1.40 src/bin/sh/var.h:1.41
--- src/bin/sh/var.h:1.40	Fri Jul 12 07:30:30 2024
+++ src/bin/sh/var.h	Sat Jul 13 13:43:58 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.h,v 1.40 2024/07/12 07:30:30 kre Exp $	*/
+/*	$NetBSD: var.h,v 1.41 2024/07/13 13:43:58 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -99,6 +99,8 @@ extern struct var line_num;
 extern struct var editrc;
 extern struct var vterm;
 extern struct var vtermcap;
+extern struct var vhistappend;
+extern struct var vhistfile;
 extern struct var vhistsize;
 extern struct var ps_lit;
 extern struct var euname;
@@ -128,6 +130,10 @@ extern int funclineabs;
 #ifndef SMALL
 #define histsizeval()	(vhistsize.text + 9)
 #define histsizeflags()	(vhistsize.flags)
+#define histfileval()	(vhistfile.text + 9)
+#define histfileflags()	(vhistfile.flags)
+#define histappval()	(vhistappend.text + 11)
+#define histappflags()	(vhistappend.flags)
 #define termval()	(vterm.text + 5)
 #endif
 

Reply via email to