oksh-noxz

[fork] Portable OpenBSD ksh, based on the Public Domain Korn Shell (pdksh).
git clone https://noxz.tech/git/oksh-noxz.git
oksh-noxz

commit: f72d80ea2d6029aa8af0a6e338a5c108c3f4db35
parent: 9f7e9069437f9add6f9ad9f23c01ee29d66fb423
author: Brian Callahan <bcallah@openbsd.org>
date:   Wed, 27 Dec 2017 15:38:11 -0500
Update to newest ksh code. NOTE this changes the default PS1 to your machine's short hostname.
MCVS/Entries90++++++++++----------
MGNUmakefile2+-
MMakefile4+-
Malloc.c4+-
Mc_ksh.c8+-
Mc_sh.c16++--
Mc_test.c45++++------
Medit.c6+-
Memacs.c41++-------
Mexec.c11+--
Mhistory.c3+-
Mksh.124++++--
Mlex.c11++-
Mlex.h4+-
Mmain.c6+-
Mmisc.c56++++++------
Msh.119+++--
Msh.h4+-
Mtable.c4+-
Mtable.h4+-
Mvar.c20++---
Mvi.c21+----
22 files changed, 179 insertions(+), 224 deletions(-)
diff --git a/CVS/Entries b/CVS/Entries
@@ -1,46 +1,46 @@
-/emacs.c/1.73/Sun Sep 17 20:17:53 2017//
-/main.c/1.83/Sun Sep 17 20:17:53 2017//
-/CONTRIBUTORS/1.10/Fri Oct 27 17:29:56 2017//
-/LEGAL/1.2/Fri Oct 27 17:29:56 2017//
-/Makefile/1.34/Fri Oct 27 17:29:56 2017//
-/NOTES/1.14/Fri Oct 27 17:29:56 2017//
-/PROJECTS/1.8/Fri Oct 27 17:29:56 2017//
-/README/1.16/Fri Oct 27 17:30:07 2017//
-/alloc.c/1.17/Fri Oct 27 17:29:56 2017//
-/c_ksh.c/1.51/Fri Oct 27 17:29:56 2017//
-/c_sh.c/1.60/Fri Oct 27 17:29:56 2017//
-/c_test.c/1.23/Fri Oct 27 17:29:56 2017//
-/c_test.h/1.4/Fri Oct 27 17:29:56 2017//
-/c_ulimit.c/1.24/Fri Oct 27 17:29:56 2017//
-/config.h/1.16/Fri Oct 27 17:29:56 2017//
-/edit.c/1.57/Fri Oct 27 17:29:56 2017//
-/edit.h/1.11/Fri Oct 27 17:29:56 2017//
-/eval.c/1.54/Fri Oct 27 17:29:56 2017//
-/exec.c/1.68/Fri Oct 27 17:29:56 2017//
-/expand.h/1.12/Fri Oct 27 17:29:56 2017//
-/expr.c/1.32/Fri Oct 27 17:29:56 2017//
-/history.c/1.74/Result of merge//
-/io.c/1.35/Fri Oct 27 17:29:56 2017//
-/jobs.c/1.55/Fri Oct 27 17:29:56 2017//
-/ksh.1/1.195/Fri Oct 27 17:30:07 2017//
-/lex.c/1.71/Fri Oct 27 17:29:56 2017//
-/lex.h/1.16/Fri Oct 27 17:29:56 2017//
-/mail.c/1.22/Fri Oct 27 17:29:56 2017//
-/misc.c/1.60/Result of merge//
-/path.c/1.19/Fri Oct 27 17:29:56 2017//
-/sh.1/1.143/Fri Oct 27 17:29:56 2017//
-/sh.h/1.65/Result of merge//
-/shf.c/1.31/Fri Oct 27 17:29:56 2017//
-/shf.h/1.8/Fri Oct 27 17:29:56 2017//
-/syn.c/1.38/Fri Oct 27 17:29:56 2017//
-/table.c/1.23/Fri Oct 27 17:29:56 2017//
-/table.h/1.12/Fri Oct 27 17:29:56 2017//
-/trap.c/1.30/Fri Oct 27 17:29:56 2017//
-/tree.c/1.27/Fri Oct 27 17:29:56 2017//
-/tree.h/1.12/Fri Oct 27 17:29:56 2017//
-/tty.c/1.16/Fri Oct 27 17:29:56 2017//
-/tty.h/1.6/Fri Oct 27 17:29:56 2017//
-/var.c/1.59/Fri Oct 27 17:29:56 2017//
-/version.c/1.12/Fri Oct 27 17:29:56 2017//
-/vi.c/1.49/Fri Oct 27 17:29:56 2017//
+/CONTRIBUTORS/1.10/Wed Dec 27 20:31:53 2017//
+/LEGAL/1.2/Wed Dec 27 20:31:53 2017//
+/Makefile/1.35/Wed Dec 27 20:32:20 2017//
+/NOTES/1.14/Wed Dec 27 20:31:53 2017//
+/PROJECTS/1.8/Wed Dec 27 20:31:53 2017//
+/README/1.16/Wed Dec 27 20:32:20 2017//
+/alloc.c/1.18/Wed Dec 27 20:32:20 2017//
+/c_ksh.c/1.52/Wed Dec 27 20:32:20 2017//
+/c_sh.c/1.62/Wed Dec 27 20:32:20 2017//
+/c_test.c/1.24/Wed Dec 27 20:32:20 2017//
+/c_test.h/1.4/Wed Dec 27 20:31:53 2017//
+/c_ulimit.c/1.24/Wed Dec 27 20:31:53 2017//
+/config.h/1.16/Wed Dec 27 20:31:53 2017//
+/edit.c/1.58/Wed Dec 27 20:32:20 2017//
+/edit.h/1.11/Wed Dec 27 20:31:53 2017//
+/emacs.c/1.77/Result of merge//
+/eval.c/1.54/Wed Dec 27 20:31:53 2017//
+/exec.c/1.70/Wed Dec 27 20:32:20 2017//
+/expand.h/1.12/Wed Dec 27 20:31:53 2017//
+/expr.c/1.32/Wed Dec 27 20:31:53 2017//
+/history.c/1.75/Result of merge//
+/io.c/1.35/Wed Dec 27 20:31:53 2017//
+/jobs.c/1.55/Wed Dec 27 20:31:53 2017//
+/ksh.1/1.197/Wed Dec 27 20:32:20 2017//
+/lex.c/1.74/Wed Dec 27 20:32:20 2017//
+/lex.h/1.17/Wed Dec 27 20:32:20 2017//
+/mail.c/1.22/Wed Dec 27 20:31:53 2017//
+/main.c/1.85/Result of merge//
+/misc.c/1.61/Wed Dec 27 20:32:21 2017//
+/path.c/1.19/Wed Dec 27 20:31:53 2017//
+/sh.1/1.145/Wed Dec 27 20:32:21 2017//
+/sh.h/1.66/Result of merge//
+/shf.c/1.31/Wed Dec 27 20:31:53 2017//
+/shf.h/1.8/Wed Dec 27 20:31:53 2017//
+/syn.c/1.38/Wed Dec 27 20:31:53 2017//
+/table.c/1.24/Wed Dec 27 20:32:21 2017//
+/table.h/1.13/Wed Dec 27 20:32:21 2017//
+/trap.c/1.30/Wed Dec 27 20:31:53 2017//
+/tree.c/1.27/Wed Dec 27 20:31:53 2017//
+/tree.h/1.12/Wed Dec 27 20:31:53 2017//
+/tty.c/1.16/Wed Dec 27 20:31:53 2017//
+/tty.h/1.6/Wed Dec 27 20:31:53 2017//
+/var.c/1.60/Wed Dec 27 20:32:21 2017//
+/version.c/1.12/Wed Dec 27 20:31:53 2017//
+/vi.c/1.50/Wed Dec 27 20:32:21 2017//
 D
diff --git a/GNUmakefile b/GNUmakefile
@@ -10,7 +10,7 @@ DOCDIR ?= ${PREFIX}/share/doc/oksh
 INSTALL = /usr/bin/install
 
 CFLAGS ?= -O2 -pipe
-CFLAGS += -Wall -DEMACS -DVI -Iportable/common
+CFLAGS += -Wall -Wshadow -DEMACS -DVI -Iportable/common
 
 OBJS =	alloc.o c_ksh.o c_sh.o c_test.o c_ulimit.o edit.o emacs.o eval.o \
 	exec.o expr.o history.o io.o jobs.o lex.o mail.o main.o misc.o \
diff --git a/Makefile b/Makefile
@@ -1,4 +1,4 @@
-#	$OpenBSD: Makefile,v 1.34 2017/08/01 14:30:05 deraadt Exp $
+#	$OpenBSD: Makefile,v 1.35 2017/12/27 13:02:57 millert Exp $
 
 PROG=	ksh
 SRCS=	alloc.c c_ksh.c c_sh.c c_test.c c_ulimit.c edit.c emacs.c eval.c \
@@ -6,7 +6,7 @@ SRCS=	alloc.c c_ksh.c c_sh.c c_test.c c_ulimit.c edit.c emacs.c eval.c \
 	misc.c path.c shf.c syn.c table.c trap.c tree.c tty.c var.c \
 	version.c vi.c
 
-DEFS=	-Wall -DEMACS -DVI
+DEFS=	-Wall -Wshadow -DEMACS -DVI
 CFLAGS+=${DEFS} -I. -I${.CURDIR} -I${.CURDIR}/../../lib/libc/gen
 MAN=	ksh.1 sh.1
 
diff --git a/alloc.c b/alloc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: alloc.c,v 1.17 2017/08/15 17:57:57 jca Exp $	*/
+/*	$OpenBSD: alloc.c,v 1.18 2017/11/02 06:55:35 tb Exp $	*/
 
 /* Public domain, like most of the rest of ksh */
 
@@ -47,7 +47,7 @@ alloc(size_t size, Area *ap)
 	if (size > SIZE_MAX - sizeof(struct link))
 		internal_errorf(1, "unable to allocate memory");
 
-	l = calloc(1, sizeof(struct link) + size);
+	l = malloc(sizeof(struct link) + size);
 	if (l == NULL)
 		internal_errorf(1, "unable to allocate memory");
 	l->next = ap->freelist;
diff --git a/c_ksh.c b/c_ksh.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: c_ksh.c,v 1.51 2017/09/03 11:52:01 jca Exp $	*/
+/*	$OpenBSD: c_ksh.c,v 1.52 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * built-in Korn commands: c_*
@@ -941,8 +941,8 @@ c_alias(char **wp)
 				afree(ap->val.s, APERM);
 			}
 			/* ignore values for -t (at&t ksh does this) */
-			newval = tflag ? search(alias, path, X_OK, NULL) :
-			    val;
+			newval = tflag ? search(alias, search_path, X_OK, NULL)
+			    : val;
 			if (newval) {
 				ap->val.s = str_save(newval, APERM);
 				ap->flag |= ALLOC|ISSET;
@@ -1184,7 +1184,7 @@ c_kill(char **wp)
 					shprintf("%s%s", p, sigtraps[i].name);
 			shprintf("\n");
 		} else {
-			int mess_width = 0, w, i;
+			int mess_width = 0, w;
 			struct kill_info ki = {
 				.num_width = 1,
 				.name_width = 0,
diff --git a/c_sh.c b/c_sh.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: c_sh.c,v 1.60 2017/07/22 09:37:21 anton Exp $	*/
+/*	$OpenBSD: c_sh.c,v 1.62 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * built-in Bourne commands
@@ -200,7 +200,7 @@ c_dot(char **wp)
 
 	if ((cp = wp[builtin_opt.optind]) == NULL)
 		return 0;
-	file = search(cp, path, R_OK, &err);
+	file = search(cp, search_path, R_OK, &err);
 	if (file == NULL) {
 		bi_errorf("%s: %s", cp, err ? strerror(err) : "not found");
 		return 1;
@@ -250,7 +250,7 @@ int
 c_read(char **wp)
 {
 	int c = 0;
-	int expand = 1, history = 0;
+	int expand = 1, savehist = 0;
 	int expanding;
 	int ecode = 0;
 	char *cp;
@@ -274,7 +274,7 @@ c_read(char **wp)
 			expand = 0;
 			break;
 		case 's':
-			history = 1;
+			savehist = 1;
 			break;
 		case 'u':
 			if (!*(cp = builtin_opt.optarg))
@@ -320,7 +320,7 @@ c_read(char **wp)
 	 * coproc_readw_close(fd);
 	 */
 
-	if (history)
+	if (savehist)
 		Xinit(xs, xp, 128, ATEMP);
 	expanding = 0;
 	Xinit(cs, cp, 128, ATEMP);
@@ -348,7 +348,7 @@ c_read(char **wp)
 				}
 				break;
 			}
-			if (history) {
+			if (savehist) {
 				Xcheck(xs, xp);
 				Xput(xs, xp, c);
 			}
@@ -361,7 +361,7 @@ c_read(char **wp)
 						/* set prompt in case this is
 						 * called from .profile or $ENV
 						 */
-						set_prompt(PS2, NULL);
+						set_prompt(PS2);
 						pprompt(prompt, 0);
 					}
 				} else if (c != EOF)
@@ -404,7 +404,7 @@ c_read(char **wp)
 	}
 
 	shf_flush(shf);
-	if (history) {
+	if (savehist) {
 		Xput(xs, xp, '\0');
 		source->line++;
 		histsave(source->line, Xstring(xs, xp), 1);
diff --git a/c_test.c b/c_test.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: c_test.c,v 1.23 2015/12/14 13:59:42 tb Exp $	*/
+/*	$OpenBSD: c_test.c,v 1.24 2017/12/26 19:10:31 millert Exp $	*/
 
 /*
  * test(1); version 7-like  --  author Erik Baalbergen
@@ -89,7 +89,6 @@ static const struct t_op b_ops [] = {
 	{"",	TO_NONOP }
 };
 
-static int	test_stat(const char *, struct stat *);
 static int	test_eaccess(const char *, int);
 static int	test_oexpr(Test_env *, int);
 static int	test_aexpr(Test_env *, int);
@@ -241,39 +240,39 @@ test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
 	case TO_FILEX: /* -x */
 		return test_eaccess(opnd1, X_OK) == 0;
 	case TO_FILAXST: /* -a */
-		return test_stat(opnd1, &b1) == 0;
+		return stat(opnd1, &b1) == 0;
 	case TO_FILEXST: /* -e */
 		/* at&t ksh does not appear to do the /dev/fd/ thing for
 		 * this (unless the os itself handles it)
 		 */
 		return stat(opnd1, &b1) == 0;
 	case TO_FILREG: /* -r */
-		return test_stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode);
+		return stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode);
 	case TO_FILID: /* -d */
-		return test_stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode);
+		return stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode);
 	case TO_FILCDEV: /* -c */
-		return test_stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode);
+		return stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode);
 	case TO_FILBDEV: /* -b */
-		return test_stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode);
+		return stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode);
 	case TO_FILFIFO: /* -p */
-		return test_stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode);
+		return stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode);
 	case TO_FILSYM: /* -h -L */
 		return lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode);
 	case TO_FILSOCK: /* -S */
-		return test_stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode);
+		return stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode);
 	case TO_FILCDF:/* -H HP context dependent files (directories) */
 		return 0;
 	case TO_FILSETU: /* -u */
-		return test_stat(opnd1, &b1) == 0 &&
+		return stat(opnd1, &b1) == 0 &&
 		    (b1.st_mode & S_ISUID) == S_ISUID;
 	case TO_FILSETG: /* -g */
-		return test_stat(opnd1, &b1) == 0 &&
+		return stat(opnd1, &b1) == 0 &&
 		    (b1.st_mode & S_ISGID) == S_ISGID;
 	case TO_FILSTCK: /* -k */
-		return test_stat(opnd1, &b1) == 0 &&
+		return stat(opnd1, &b1) == 0 &&
 		    (b1.st_mode & S_ISVTX) == S_ISVTX;
 	case TO_FILGZ: /* -s */
-		return test_stat(opnd1, &b1) == 0 && b1.st_size > 0L;
+		return stat(opnd1, &b1) == 0 && b1.st_size > 0L;
 	case TO_FILTT: /* -t */
 		if (opnd1 && !bi_getn(opnd1, &res)) {
 			te->flags |= TEF_ERROR;
@@ -284,9 +283,9 @@ test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
 		}
 		return res;
 	case TO_FILUID: /* -O */
-		return test_stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid;
+		return stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid;
 	case TO_FILGID: /* -G */
-		return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid();
+		return stat(opnd1, &b1) == 0 && b1.st_gid == getegid();
 	/*
 	 * Binary Operators
 	 */
@@ -360,27 +359,19 @@ test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
 	return 1;
 }
 
-/* Nasty kludge to handle Korn's bizarre /dev/fd hack */
-static int
-test_stat(const char *path, struct stat *statb)
-{
-	return stat(path, statb);
-}
-
-/* Routine to handle Korn's /dev/fd hack, and to deal with X_OK on
- * non-directories when running as root.
+/* Routine to deal with X_OK on non-directories when running as root.
  */
 static int
-test_eaccess(const char *path, int mode)
+test_eaccess(const char *path, int amode)
 {
 	int res;
 
-	res = access(path, mode);
+	res = access(path, amode);
 	/*
 	 * On most (all?) unixes, access() says everything is executable for
 	 * root - avoid this on files by using stat().
 	 */
-	if (res == 0 && ksheuid == 0 && (mode & X_OK)) {
+	if (res == 0 && ksheuid == 0 && (amode & X_OK)) {
 		struct stat statb;
 
 		if (stat(path, &statb) < 0)
diff --git a/edit.c b/edit.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: edit.c,v 1.57 2016/09/08 12:12:40 nicm Exp $	*/
+/*	$OpenBSD: edit.c,v 1.58 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * Command line editing - common code
@@ -229,7 +229,7 @@ set_editmode(const char *ed)
 	if ((rcp = strrchr(ed, '/')))
 		ed = ++rcp;
 	for (i = 0; i < NELEM(edit_flags); i++)
-		if (strstr(ed, options[(int) edit_flags[i]].name)) {
+		if (strstr(ed, sh_options[(int) edit_flags[i]].name)) {
 			change_flag(edit_flags[i], OF_SPECIAL, 1);
 			return;
 		}
@@ -459,7 +459,7 @@ x_command_glob(int flags, const char *str, int slen, char ***wordsp)
 	for (l = genv->loc; l; l = l->next)
 		glob_table(pat, &w, &l->funs);
 
-	glob_path(flags, pat, &w, path);
+	glob_path(flags, pat, &w, search_path);
 	if ((fpath = str_val(global("FPATH"))) != null)
 		glob_path(flags, pat, &w, fpath);
 
diff --git a/emacs.c b/emacs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: emacs.c,v 1.73 2017/08/30 17:02:53 jca Exp $	*/
+/*	$OpenBSD: emacs.c,v 1.77 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  *  Emacs-like command line editing and history
@@ -190,7 +190,6 @@ static int	x_search_char_back(int);
 static int	x_search_hist(int);
 static int	x_set_mark(int);
 static int	x_transpose(int);
-static int	x_version(int);
 static int	x_xchg_point_mark(int);
 static int	x_yank(int);
 static int	x_comp_list(int);
@@ -247,7 +246,6 @@ static const struct x_ftab x_ftab[] = {
 	{ x_search_hist,	"search-history",		0 },
 	{ x_set_mark,		"set-mark-command",		0 },
 	{ x_transpose,		"transpose-chars",		0 },
-	{ x_version,		"version",			0 },
 	{ x_xchg_point_mark,	"exchange-point-and-mark",	0 },
 	{ x_yank,		"yank",				0 },
 	{ x_comp_list,		"complete-list",		0 },
@@ -1476,6 +1474,7 @@ x_init_emacs(void)
 	kb_add(x_del_back,		NULL, CTRL('?'), 0);
 	kb_add(x_del_back,		NULL, CTRL('H'), 0);
 	kb_add(x_del_char,		NULL, CTRL('['), '[', '3', '~', 0); /* delete */
+	kb_add(x_del_bword,		NULL, CTRL('W'), 0);
 	kb_add(x_del_bword,		NULL, CTRL('['), CTRL('?'), 0);
 	kb_add(x_del_bword,		NULL, CTRL('['), CTRL('H'), 0);
 	kb_add(x_del_bword,		NULL, CTRL('['), 'h', 0);
@@ -1497,7 +1496,6 @@ x_init_emacs(void)
 	kb_add(x_mv_fword,		NULL, CTRL('['), 'f', 0);
 	kb_add(x_goto_hist,		NULL, CTRL('['), 'g', 0);
 	/* kill-line */
-	kb_add(x_del_bword,		NULL, CTRL('W'), 0); /* not what man says */
 	kb_add(x_kill,			NULL, CTRL('K'), 0);
 	kb_add(x_enumerate,		NULL, CTRL('['), '?', 0);
 	kb_add(x_list_comm,		NULL, CTRL('X'), '?', 0);
@@ -1509,6 +1507,7 @@ x_init_emacs(void)
 	kb_add(x_prev_histword,		NULL, CTRL('['), '.', 0);
 	kb_add(x_prev_histword,		NULL, CTRL('['), '_', 0);
 	/* how to handle: quote: ^^ */
+	kb_add(x_literal,		NULL, CTRL('^'), 0);
 	kb_add(x_draw_line,		NULL, CTRL('L'), 0);
 	kb_add(x_search_char_back,	NULL, CTRL('['), CTRL(']'), 0);
 	kb_add(x_search_char_forw,	NULL, CTRL(']'), 0);
@@ -1520,7 +1519,6 @@ x_init_emacs(void)
 	kb_add(x_fold_upper,		NULL, CTRL('['), 'U', 0);
 	kb_add(x_fold_upper,		NULL, CTRL('['), 'u', 0);
 	kb_add(x_literal,		NULL, CTRL('V'), 0);
-	kb_add(x_literal,		NULL, CTRL('^'), 0);
 	kb_add(x_yank,			NULL, CTRL('Y'), 0);
 	kb_add(x_meta_yank,		NULL, CTRL('['), 'y', 0);
 	/* man page ends here */
@@ -1542,6 +1540,8 @@ x_init_emacs(void)
 	kb_add(x_mv_end,		NULL, CTRL('['), 'O', 'F', 0); /* end */
 	kb_add(x_mv_begin,		NULL, CTRL('['), '[', '1', '~', 0); /* home */
 	kb_add(x_mv_end,		NULL, CTRL('['), '[', '4', '~', 0); /* end */
+	kb_add(x_mv_begin,		NULL, CTRL('['), '[', '7', '~', 0); /* home */
+	kb_add(x_mv_end,		NULL, CTRL('['), '[', '8', '~', 0); /* end */
 
 	/* can't be bound */
 	kb_add(x_set_arg,		NULL, CTRL('['), '0', 0);
@@ -1626,35 +1626,6 @@ x_xchg_point_mark(int c)
 	return KSTD;
 }
 
-static int
-x_version(int c)
-{
-	char *o_xbuf = xbuf, *o_xend = xend;
-	char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp;
-	int lim = x_lastcp() - xbp;
-
-	xbuf = xbp = xcp = (char *) ksh_version + 4;
-	xend = xep = (char *) ksh_version + 4 + strlen(ksh_version + 4);
-	x_redraw(lim);
-	x_flush();
-
-	c = x_e_getc();
-	xbuf = o_xbuf;
-	xend = o_xend;
-	xbp = o_xbp;
-	xep = o_xep;
-	xcp = o_xcp;
-	x_redraw(strlen(ksh_version));
-
-	if (c < 0)
-		return KSTD;
-	/* This is what at&t ksh seems to do...  Very bizarre */
-	if (c != ' ')
-		x_e_ungetc(c);
-
-	return KSTD;
-}
-
 static int
 x_noop(int c)
 {
@@ -2028,8 +1999,6 @@ x_prev_histword(int c)
 			rcp++;
 		x_ins(rcp);
 	} else {
-		int c;
-
 		rcp = cp;
 		/*
 		 * ignore white-space at start of line
diff --git a/exec.c b/exec.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: exec.c,v 1.68 2016/12/11 17:49:19 millert Exp $	*/
+/*	$OpenBSD: exec.c,v 1.70 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * execute command tree
@@ -409,7 +409,7 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags,
 	volatile int rv = 0;
 	char *cp;
 	char **lastp;
-	static struct op texec; /* Must be static (XXX but why?) */
+	struct op texec;
 	int type_flags;
 	int keepasn_ok;
 	int fcflags = FC_BI|FC_FUNC|FC_PATH;
@@ -684,6 +684,7 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags,
 		}
 
 		/* to fork we set up a TEXEC node and call execute */
+		memset(&texec, 0, sizeof(texec));
 		texec.type = TEXEC;
 		texec.left = t;	/* for tprint */
 		texec.str = tp->val.s;
@@ -706,7 +707,7 @@ scriptexec(struct op *tp, char **ap)
 
 	shell = str_val(global("EXECSHELL"));
 	if (shell && *shell)
-		shell = search(shell, path, X_OK, NULL);
+		shell = search(shell, search_path, X_OK, NULL);
 	if (!shell || !*shell)
 		shell = _PATH_BSHELL;
 
@@ -899,8 +900,8 @@ findcom(const char *name, int flags)
 			}
 			tp->flag = DEFINED;	/* make ~ISSET */
 		}
-		npath = search(name, flags & FC_DEFPATH ? def_path : path,
-		    X_OK, &tp->u2.errno_);
+		npath = search(name, flags & FC_DEFPATH ? def_path :
+		    search_path, X_OK, &tp->u2.errno_);
 		if (npath) {
 			if (tp == &temp) {
 				tp->val.s = npath;
diff --git a/history.c b/history.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: history.c,v 1.74 2017/10/23 15:43:38 jca Exp $	*/
+/*	$OpenBSD: history.c,v 1.75 2017/11/21 17:57:41 tb Exp $	*/
 
 /*
  * command history
@@ -611,6 +611,7 @@ init_histvec(void)
 		 */
 		histbase = areallocarray(NULL, histsize + 1, sizeof(char *),
 		    APERM);
+		*histbase = NULL;
 		history = histbase + 1;
 		histptr = history - 1;
 	}
diff --git a/ksh.1 b/ksh.1
@@ -1,8 +1,8 @@
-.\"	$OpenBSD: ksh.1,v 1.195 2017/08/30 17:08:45 jca Exp $
+.\"	$OpenBSD: ksh.1,v 1.197 2017/12/12 11:34:38 tb Exp $
 .\"
 .\"	Public Domain
 .\"
-.Dd $Mdocdate: August 30 2017 $
+.Dd $Mdocdate: December 12 2017 $
 .Dt KSH 1
 .Os
 .Sh NAME
@@ -1539,7 +1539,7 @@ By the way, don't blame me for
 this hack; it's in the original
 .Nm .
 .Pp
-The default prompt is
+The default prompt is the first part of the hostname, followed by
 .Sq $\ \&
 for non-root users,
 .Sq #\ \&
@@ -4656,7 +4656,7 @@ Simply causes the character to appear as literal input.
 Most ordinary characters are bound to this.
 .It Xo backward-char:
 .Op Ar n
-.No ^B , ^XD
+.No ^B , ^X^D
 .Xc
 Moves the cursor backward
 .Ar n
@@ -4749,7 +4749,7 @@ Deletes
 characters after the cursor.
 .It Xo delete-word-backward:
 .Op Ar n
-.No ERASE , ^[^? , ^[^H , ^[h
+.No WERASE , ^[ERASE , ^W, ^[^? , ^[^H , ^[h
 .Xc
 Deletes
 .Ar n
@@ -4758,9 +4758,9 @@ words before the cursor.
 .Op Ar n
 .No ^[d
 .Xc
-Deletes characters after the cursor up to the end of
+Deletes
 .Ar n
-words.
+words after the cursor.
 .It Xo down-history:
 .Op Ar n
 .No ^N , ^XB
@@ -4830,8 +4830,6 @@ Goes to history number
 .Ar n .
 .It kill-line: KILL
 Deletes the entire input line.
-.It kill-region: ^W
-Deletes the input between the cursor and the mark.
 .It Xo kill-to-eol:
 .Op Ar n
 .No ^K
@@ -4938,6 +4936,14 @@ Immediately after a
 .Ic yank ,
 replaces the inserted text string with the next previously killed text string.
 .El
+.Pp
+The following editing commands lack default bindings but can be used with the
+.Ic bind
+command:
+.Bl -tag -width Ds
+.It kill-region
+Deletes the input between the cursor and the mark.
+.El
 .Ss Vi editing mode
 The vi command-line editor in
 .Nm
diff --git a/lex.c b/lex.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: lex.c,v 1.71 2017/07/04 11:46:15 anton Exp $	*/
+/*	$OpenBSD: lex.c,v 1.74 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * lexical analysis and source input
@@ -1165,7 +1165,7 @@ getsc_line(Source *s)
 #endif /* HISTORY */
 	}
 	if (interactive)
-		set_prompt(PS2, NULL);
+		set_prompt(PS2);
 }
 
 static char *
@@ -1180,7 +1180,7 @@ special_prompt_expand(char *str)
 }
 
 void
-set_prompt(int to, Source *s)
+set_prompt(int to)
 {
 	char *ps1;
 	Area *saved_atemp;
@@ -1246,7 +1246,8 @@ dopprompt(const char *sp, int ntruncate, const char **spp, int doprint)
 			cp++;
 			if (!*cp)
 				break;
-			if (Flag(FSH))
+			/* Expand \h and \$ for both, sh(1) and ksh(1) */
+			if (Flag(FSH) && !(*cp == 'h' || *cp == 'p'))
 				snprintf(strbuf, sizeof strbuf, "\\%c", *cp);
 			else switch (*cp) {
 			case 'a':	/* '\' 'a' bell */
@@ -1445,8 +1446,6 @@ dopprompt(const char *sp, int ntruncate, const char **spp, int doprint)
 		else if (*++cp == '!')
 			c = *cp++;
 		else {
-			char *p;
-
 			shf_snprintf(p = nbuf, sizeof(nbuf), "%d",
 			    source->line + 1);
 			len = strlen(nbuf);
diff --git a/lex.h b/lex.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: lex.h,v 1.16 2015/10/10 07:35:16 nicm Exp $	*/
+/*	$OpenBSD: lex.h,v 1.17 2017/12/07 01:54:33 tb Exp $	*/
 
 /*
  * Source input, lexer and parser
@@ -118,5 +118,5 @@ int	yylex(int);
 void	yyerror(const char *, ...)
 	    __attribute__((__noreturn__, __format__ (printf, 1, 2)));
 Source * pushs(int, Area *);
-void	set_prompt(int, Source *);
+void	set_prompt(int);
 void	pprompt(const char *, int);
diff --git a/main.c b/main.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: main.c,v 1.83 2017/08/11 23:10:55 guenther Exp $	*/
+/*	$OpenBSD: main.c,v 1.85 2017/12/12 00:18:58 tb Exp $	*/
 
 /*
  * startup, main loop, environments and error handling
@@ -318,7 +318,7 @@ main(int argc, char *argv[])
 		/* Set PS1 if it isn't set */
 		if (!(vp->flag & ISSET)) {
 			/* setstr can't fail here */
-			setstr(vp, safe_prompt, KSH_RETURN_ERROR);
+			setstr(vp, "\\h\\$ ", KSH_RETURN_ERROR);
 		}
 	}
 
@@ -611,7 +611,7 @@ shell(Source *volatile s, volatile int toplevel)
 			got_sigwinch = 1;
 			j_notify();
 			mcheck();
-			set_prompt(PS1, s);
+			set_prompt(PS1);
 		}
 
 		t = compile(s);
diff --git a/misc.c b/misc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: misc.c,v 1.60 2017/10/19 07:54:05 jca Exp $	*/
+/*	$OpenBSD: misc.c,v 1.61 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * Miscellaneous functions
@@ -115,7 +115,7 @@ Xcheck_grow_(XString *xsp, char *xp, int more)
 	return xsp->beg + (xp - old_beg);
 }
 
-const struct option options[] = {
+const struct option sh_options[] = {
 	/* Special cases (see parse_args()): -A, -o, -s.
 	 * Options are sorted by their longnames - the order of these
 	 * entries MUST match the order of sh_flag F* enumerations in sh.h.
@@ -183,8 +183,8 @@ option(const char *n)
 {
 	int i;
 
-	for (i = 0; i < NELEM(options); i++)
-		if (options[i].name && strcmp(options[i].name, n) == 0)
+	for (i = 0; i < NELEM(sh_options); i++)
+		if (sh_options[i].name && strcmp(sh_options[i].name, n) == 0)
 			return i;
 
 	return -1;
@@ -195,7 +195,7 @@ struct options_info {
 	struct {
 		const char *name;
 		int	flag;
-	} opts[NELEM(options)];
+	} opts[NELEM(sh_options)];
 };
 
 static char *options_fmt_entry(void *arg, int i, char *buf, int buflen);
@@ -225,10 +225,10 @@ printoptions(int verbose)
 		/* verbose version */
 		shprintf("Current option settings\n");
 
-		for (i = n = oi.opt_width = 0; i < NELEM(options); i++) {
-			if (options[i].name) {
-				len = strlen(options[i].name);
-				oi.opts[n].name = options[i].name;
+		for (i = n = oi.opt_width = 0; i < NELEM(sh_options); i++) {
+			if (sh_options[i].name) {
+				len = strlen(sh_options[i].name);
+				oi.opts[n].name = sh_options[i].name;
 				oi.opts[n++].flag = i;
 				if (len > oi.opt_width)
 					oi.opt_width = len;
@@ -239,11 +239,11 @@ printoptions(int verbose)
 	} else {
 		/* short version ala ksh93 */
 		shprintf("set");
-		for (i = 0; i < NELEM(options); i++) {
-			if (options[i].name)
+		for (i = 0; i < NELEM(sh_options); i++) {
+			if (sh_options[i].name)
 				shprintf(" %co %s",
 					 Flag(i) ? '-' : '+',
-					 options[i].name);
+					 sh_options[i].name);
 		}
 		shprintf("\n");
 	}
@@ -256,9 +256,9 @@ getoptions(void)
 	char m[(int) FNFLAGS + 1];
 	char *cp = m;
 
-	for (i = 0; i < NELEM(options); i++)
-		if (options[i].c && Flag(i))
-			*cp++ = options[i].c;
+	for (i = 0; i < NELEM(sh_options); i++)
+		if (sh_options[i].c && Flag(i))
+			*cp++ = sh_options[i].c;
 	*cp = 0;
 	return str_save(m, ATEMP);
 }
@@ -328,8 +328,8 @@ parse_args(char **argv,
     int what,			/* OF_CMDLINE or OF_SET */
     int *setargsp)
 {
-	static char cmd_opts[NELEM(options) + 3]; /* o:\0 */
-	static char set_opts[NELEM(options) + 5]; /* Ao;s\0 */
+	static char cmd_opts[NELEM(sh_options) + 3]; /* o:\0 */
+	static char set_opts[NELEM(sh_options) + 5]; /* Ao;s\0 */
 	char *opts;
 	char *array = NULL;
 	Getopt go;
@@ -345,12 +345,12 @@ parse_args(char **argv,
 		/* see set_opts[] declaration */
 		strlcpy(set_opts, "A:o;s", sizeof set_opts);
 		q = set_opts + strlen(set_opts);
-		for (i = 0; i < NELEM(options); i++) {
-			if (options[i].c) {
-				if (options[i].flags & OF_CMDLINE)
-					*p++ = options[i].c;
-				if (options[i].flags & OF_SET)
-					*q++ = options[i].c;
+		for (i = 0; i < NELEM(sh_options); i++) {
+			if (sh_options[i].c) {
+				if (sh_options[i].flags & OF_CMDLINE)
+					*p++ = sh_options[i].c;
+				if (sh_options[i].flags & OF_SET)
+					*q++ = sh_options[i].c;
 			}
 		}
 		*p = '\0';
@@ -395,7 +395,7 @@ parse_args(char **argv,
 				 * if the output of "set +o" is to be used.
 				 */
 				;
-			else if (i >= 0 && (options[i].flags & what))
+			else if (i >= 0 && (sh_options[i].flags & what))
 				change_flag((enum sh_flag) i, what, set);
 			else {
 				bi_errorf("%s: bad option", go.optarg);
@@ -412,14 +412,14 @@ parse_args(char **argv,
 				sortargs = 1;
 				break;
 			}
-			for (i = 0; i < NELEM(options); i++)
-				if (optc == options[i].c &&
-				    (what & options[i].flags)) {
+			for (i = 0; i < NELEM(sh_options); i++)
+				if (optc == sh_options[i].c &&
+				    (what & sh_options[i].flags)) {
 					change_flag((enum sh_flag) i, what,
 					    set);
 					break;
 				}
-			if (i == NELEM(options)) {
+			if (i == NELEM(sh_options)) {
 				internal_errorf(1, "parse_args: `%c'", optc);
 				return -1; /* not reached */
 			}
diff --git a/sh.1 b/sh.1
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: sh.1,v 1.143 2017/06/01 20:37:38 tb Exp $
+.\"	$OpenBSD: sh.1,v 1.145 2017/12/15 20:51:28 jmc Exp $
 .\"
 .\" Copyright (c) 2015 Jason McIntyre <jmc@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: June 1 2017 $
+.Dd $Mdocdate: December 15 2017 $
 .Dt SH 1
 .Os
 .Sh NAME
@@ -2101,11 +2101,6 @@ A
 .Sq !\&
 in the prompt is expanded to the number of the next command in history
 to be typed.
-The default value is
-.Sq $\ \&
-for normal users and
-.Sq #\ \&
-for root.
 .It Ev PS2
 Newline prompt displayed in an interactive shell
 when a newline has been entered
@@ -2226,6 +2221,16 @@ and
 built-ins should exit/return from the outermost loop if the argument
 .Ar n
 is greater than the level of loops.
+.It
+The default value for the
+.Ev PS1
+user prompt contains the machine's hostname,
+followed by
+.Sq $\ \&
+for normal users and
+.Sq #\ \&
+for root;
+POSIX does not include the hostname.
 .El
 .Pp
 Enabling POSIX mode changes some behaviour to make
diff --git a/sh.h b/sh.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: sh.h,v 1.65 2017/10/19 07:54:05 jca Exp $	*/
+/*	$OpenBSD: sh.h,v 1.66 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * Public Domain Bourne/Korn shell
@@ -138,7 +138,7 @@ struct option {
     char	c;	/* character flag (if any) */
     short	flags;	/* OF_* */
 };
-extern const struct option options[];
+extern const struct option sh_options[];
 
 /*
  * flags (the order of these enums MUST match the order in misc.c(options[]))
diff --git a/table.c b/table.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: table.c,v 1.23 2015/11/01 15:38:53 mmcc Exp $	*/
+/*	$OpenBSD: table.c,v 1.24 2017/12/27 13:02:57 millert Exp $	*/
 
 /*
  * dynamic hashed associative table for commands and variables
@@ -18,7 +18,7 @@ struct table aliases;	/* aliases */
 struct table keywords;	/* keywords */
 struct table homedirs;	/* homedir() cache */
 
-char *path;		/* copy of either PATH or def_path */
+char *search_path;	/* copy of either PATH or def_path */
 const char *def_path;	/* path to use if PATH not set */
 char *tmpdir;		/* TMPDIR value */
 const char *prompt;
diff --git a/table.h b/table.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: table.h,v 1.12 2017/08/30 17:08:45 jca Exp $	*/
+/*	$OpenBSD: table.h,v 1.13 2017/12/27 13:02:57 millert Exp $	*/
 
 /* $From: table.h,v 1.3 1994/05/31 13:34:34 michael Exp $ */
 
@@ -175,7 +175,7 @@ extern const struct builtin shbuiltins [], kshbuiltins [];
 #define PS1	0		/* command */
 #define PS2	1		/* command continuation */
 
-extern char *path;		/* copy of either PATH or def_path */
+extern char *search_path;	/* copy of either PATH or def_path */
 extern const char *def_path;	/* path to use if PATH not set */
 extern char *tmpdir;		/* TMPDIR value */
 extern const char *prompt;
diff --git a/var.c b/var.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: var.c,v 1.59 2017/08/30 17:08:45 jca Exp $	*/
+/*	$OpenBSD: var.c,v 1.60 2017/12/27 13:02:57 millert Exp $	*/
 
 #include <sys/stat.h>
 
@@ -525,11 +525,11 @@ formatstr(struct tbl *vp, const char *s)
 		int slen;
 
 		if (vp->flag & RJUST) {
-			const char *q = s + olen;
-			/* strip trailing spaces (at&t ksh uses q[-1] == ' ') */
-			while (q > s && isspace((unsigned char)q[-1]))
-				--q;
-			slen = q - s;
+			const char *r = s + olen;
+			/* strip trailing spaces (at&t ksh uses r[-1] == ' ') */
+			while (r > s && isspace((unsigned char)r[-1]))
+				--r;
+			slen = r - s;
 			if (slen > vp->u2.field) {
 				s += slen - vp->u2.field;
 				slen = vp->u2.field;
@@ -960,8 +960,8 @@ setspec(struct tbl *vp)
 
 	switch (special(vp->name)) {
 	case V_PATH:
-		afree(path, APERM);
-		path = str_save(str_val(vp), APERM);
+		afree(search_path, APERM);
+		search_path = str_save(str_val(vp), APERM);
 		flushcom(1);	/* clear tracked aliases */
 		break;
 	case V_IFS:
@@ -1067,8 +1067,8 @@ unsetspec(struct tbl *vp)
 {
 	switch (special(vp->name)) {
 	case V_PATH:
-		afree(path, APERM);
-		path = str_save(def_path, APERM);
+		afree(search_path, APERM);
+		search_path = str_save(def_path, APERM);
 		flushcom(1);	/* clear tracked aliases */
 		break;
 	case V_IFS:
diff --git a/vi.c b/vi.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vi.c,v 1.49 2017/09/02 18:53:53 deraadt Exp $	*/
+/*	$OpenBSD: vi.c,v 1.50 2017/11/27 04:23:50 tb Exp $	*/
 
 /*
  *	vi command editing
@@ -140,7 +140,6 @@ const unsigned char	classify[128] = {
 #define VREDO		7		/* . */
 #define VLIT		8		/* ^V */
 #define VSEARCH		9		/* /, ? */
-#define VVERSION	10		/* <ESC> ^V */
 
 static char		undocbuf[LINE];
 
@@ -223,7 +222,7 @@ x_vi(char *buf, size_t len)
 				trapsig(c == edchars.intr ? SIGINT : SIGQUIT);
 				x_mode(false);
 				unwind(LSHELL);
-			} else if (c == edchars.eof && state != VVERSION) {
+			} else if (c == edchars.eof) {
 				if (es->linelen == 0) {
 					x_vi_zotc(edchars.eof);
 					c = -1;
@@ -301,14 +300,6 @@ vi_hook(int ch)
 						return -1;
 					refresh(0);
 				}
-				if (state == VVERSION) {
-					save_cbuf();
-					es->cursor = 0;
-					es->linelen = 0;
-					putbuf(ksh_version + 4,
-					    strlen(ksh_version + 4), 0);
-					refresh(0);
-				}
 			}
 		}
 		break;
@@ -323,12 +314,6 @@ vi_hook(int ch)
 		state = VNORMAL;
 		break;
 
-	case VVERSION:
-		restore_cbuf();
-		state = VNORMAL;
-		refresh(0);
-		break;
-
 	case VARG1:
 		if (isdigit(ch))
 			argc1 = argc1 * 10 + ch - '0';
@@ -554,8 +539,6 @@ nextstate(int ch)
 		return VXCH;
 	else if (ch == '.')
 		return VREDO;
-	else if (ch == CTRL('v'))
-		return VVERSION;
 	else if (is_cmd(ch))
 		return VCMD;
 	else