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: 53a5705a6e059c5da430860a073914374c3d1f86
parent: 5b00926ae0455d1796c135ce5879299652ad3713
author: Brian Callahan <bcallah@openbsd.org>
date:   Sun, 7 Jan 2018 18:38:45 -0500
Convert GNU make to a configure script and POSIX make.
While here, update to the latest ksh code.
MCVS/Entries90++--
DGNUmakefile88----
DMakefile17-
MREADME.md23+-
Mc_ksh.c6+-
Rportable/common/charclass.hcharclass.hcharclass.h|
Mconfig.h7+-
Aconfigure339+++++++++++++++
Medit.c2+-
Memacs.c36+-
Meval.c2+-
Mexpand.h4+-
Mhistory.c4+-
Mjobs.c56+--
Mlex.c2+-
Mlex.h2+-
Mmain.c4+-
Mmisc.c10+-
Mpath.c2+-
Rportable/linux/queue.hportable.hportable.h|
Dportable/common/vis.c63---
Dportable/darwin/darwin.h52---
Dportable/freebsd/freebsd.h30--
Dportable/linux/linux.h60---
Dportable/linux/setmode.c455--------------------
Dportable/netbsd/netbsd.h24--
Aprescue.h8+
Rportable/common/reallocarray.creallocarray.creallocarray.c|
Mrescue.sh143+++---
Msh.h19+-
Rportable/linux/signame.csigname.csigname.c|
Rportable/linux/strlcat.cstrlcat.cstrlcat.c|
Rportable/linux/strlcpy.cstrlcpy.cstrlcpy.c|
Rportable/common/strtonum.cstrtonum.cstrtonum.c|
Mtree.c2+-
Rportable/linux/unvis.cunvis.cunvis.c|
Mvar.c4+-
Mvi.c2+-
Rportable/linux/vis.cvis.cvis.c|
Rportable/linux/vis.hvis.hvis.h|
40 files changed, 725 insertions(+), 1149 deletions(-)
diff --git a/CVS/Entries b/CVS/Entries
@@ -1,46 +1,46 @@
-/main.c/1.85/Result of merge//
-/sh.h/1.66/Result of merge//
-/CONTRIBUTORS/1.10/Wed Jan  3 02:30:53 2018//
-/LEGAL/1.2/Wed Jan  3 02:30:53 2018//
-/Makefile/1.36/Wed Jan  3 02:31:13 2018//
-/NOTES/1.14/Wed Jan  3 02:30:53 2018//
-/PROJECTS/1.8/Wed Jan  3 02:30:53 2018//
-/README/1.16/Wed Jan  3 02:31:13 2018//
-/alloc.c/1.18/Wed Jan  3 02:30:53 2018//
-/c_ksh.c/1.53/Wed Jan  3 02:31:13 2018//
-/c_sh.c/1.62/Wed Jan  3 02:30:53 2018//
-/c_test.c/1.24/Wed Jan  3 02:30:53 2018//
-/c_test.h/1.4/Wed Jan  3 02:30:53 2018//
-/c_ulimit.c/1.24/Wed Jan  3 02:30:53 2018//
-/config.h/1.16/Wed Jan  3 02:30:53 2018//
-/edit.c/1.59/Wed Jan  3 02:31:13 2018//
-/edit.h/1.11/Wed Jan  3 02:30:53 2018//
-/emacs.c/1.78/Result of merge//
-/eval.c/1.55/Wed Jan  3 02:31:13 2018//
-/exec.c/1.70/Wed Jan  3 02:30:53 2018//
-/expand.h/1.13/Wed Jan  3 02:31:13 2018//
-/expr.c/1.32/Wed Jan  3 02:30:53 2018//
-/history.c/1.76/Result of merge//
-/io.c/1.35/Wed Jan  3 02:30:53 2018//
-/jobs.c/1.55/Wed Jan  3 02:30:53 2018//
-/ksh.1/1.197/Wed Jan  3 02:30:53 2018//
-/lex.c/1.75/Wed Jan  3 02:31:14 2018//
-/lex.h/1.18/Wed Jan  3 02:31:14 2018//
-/mail.c/1.22/Wed Jan  3 02:30:53 2018//
-/misc.c/1.62/Wed Jan  3 02:31:14 2018//
-/path.c/1.20/Wed Jan  3 02:31:14 2018//
-/sh.1/1.146/Wed Jan  3 02:31:14 2018//
-/shf.c/1.31/Wed Jan  3 02:30:54 2018//
-/shf.h/1.8/Wed Jan  3 02:30:54 2018//
-/syn.c/1.38/Wed Jan  3 02:30:54 2018//
-/table.c/1.24/Wed Jan  3 02:30:54 2018//
-/table.h/1.13/Wed Jan  3 02:30:54 2018//
-/trap.c/1.30/Wed Jan  3 02:30:54 2018//
-/tree.c/1.28/Wed Jan  3 02:31:14 2018//
-/tree.h/1.12/Wed Jan  3 02:30:54 2018//
-/tty.c/1.16/Wed Jan  3 02:30:54 2018//
-/tty.h/1.6/Wed Jan  3 02:30:54 2018//
-/var.c/1.61/Wed Jan  3 02:31:14 2018//
-/version.c/1.12/Wed Jan  3 02:30:54 2018//
-/vi.c/1.51/Wed Jan  3 02:31:14 2018//
+/CONTRIBUTORS/1.10/Sun Jan  7 20:03:32 2018//
+/LEGAL/1.2/Sun Jan  7 20:03:32 2018//
+/Makefile/1.38/Sun Jan  7 23:21:17 2018//
+/NOTES/1.14/Sun Jan  7 20:03:32 2018//
+/PROJECTS/1.8/Sun Jan  7 20:03:32 2018//
+/README/1.16/Sun Jan  7 23:21:17 2018//
+/alloc.c/1.18/Sun Jan  7 20:03:32 2018//
+/c_ksh.c/1.56/Sun Jan  7 23:21:17 2018//
+/c_sh.c/1.62/Sun Jan  7 20:03:32 2018//
+/c_test.c/1.24/Sun Jan  7 20:03:32 2018//
+/c_test.h/1.4/Sun Jan  7 20:03:32 2018//
+/c_ulimit.c/1.24/Sun Jan  7 20:03:32 2018//
+/config.h/1.17/Result of merge//
+/edit.c/1.61/Sun Jan  7 23:21:17 2018//
+/edit.h/1.11/Sun Jan  7 20:03:32 2018//
+/emacs.c/1.81/Result of merge//
+/eval.c/1.57/Sun Jan  7 23:21:17 2018//
+/exec.c/1.70/Sun Jan  7 20:03:32 2018//
+/expand.h/1.15/Sun Jan  7 23:21:17 2018//
+/expr.c/1.32/Sun Jan  7 20:03:32 2018//
+/history.c/1.78/Result of merge//
+/io.c/1.35/Sun Jan  7 20:03:32 2018//
+/jobs.c/1.57/Sun Jan  7 23:21:17 2018//
+/ksh.1/1.197/Sun Jan  7 20:03:32 2018//
+/lex.c/1.77/Sun Jan  7 23:21:18 2018//
+/lex.h/1.20/Sun Jan  7 23:21:18 2018//
+/mail.c/1.22/Sun Jan  7 20:03:32 2018//
+/main.c/1.86/Result of merge//
+/misc.c/1.65/Sun Jan  7 23:21:18 2018//
+/path.c/1.22/Sun Jan  7 23:21:18 2018//
+/sh.1/1.146/Sun Jan  7 20:03:32 2018//
+/sh.h/1.68/Sun Jan  7 23:21:18 2018//
+/shf.c/1.31/Sun Jan  7 20:03:32 2018//
+/shf.h/1.8/Sun Jan  7 20:03:32 2018//
+/syn.c/1.38/Sun Jan  7 20:03:32 2018//
+/table.c/1.24/Sun Jan  7 20:03:32 2018//
+/table.h/1.13/Sun Jan  7 20:03:32 2018//
+/trap.c/1.30/Sun Jan  7 20:03:32 2018//
+/tree.c/1.30/Sun Jan  7 23:21:18 2018//
+/tree.h/1.12/Sun Jan  7 20:03:32 2018//
+/tty.c/1.16/Sun Jan  7 20:03:32 2018//
+/tty.h/1.6/Sun Jan  7 20:03:32 2018//
+/var.c/1.63/Sun Jan  7 23:21:18 2018//
+/version.c/1.12/Sun Jan  7 20:03:32 2018//
+/vi.c/1.53/Sun Jan  7 23:21:18 2018//
 D
diff --git a/GNUmakefile b/GNUmakefile
@@ -1,88 +0,0 @@
-# oksh portable GNUmakefile
-# This file written by Brian Callahan <bcallah@openbsd.org>
-# and released into the Public Domain.
-
-PROG = oksh
-
-PREFIX ?= /usr/local
-MANDIR ?= ${PREFIX}/man
-DOCDIR ?= ${PREFIX}/share/doc/oksh
-INSTALL = /usr/bin/install
-
-CFLAGS ?= -O2 -pipe
-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 \
-	path.o shf.o syn.o table.o trap.o tree.o tty.o var.o version.o vi.o
-
-#
-# Portability stuff.
-#
-UNAME_S := $(shell uname -s)
-ifeq ($(UNAME_S),Linux)
-GROUP =	root
-OBJS +=	portable/common/reallocarray.o portable/linux/setmode.o \
-	portable/linux/signame.o portable/linux/strlcat.o \
-	portable/linux/strlcpy.o portable/common/strtonum.o \
-	portable/linux/unvis.o portable/linux/vis.o
-CFLAGS += -D_GNU_SOURCE
-else ifeq ($(UNAME_S),FreeBSD)
-GROUP =	bin
-OBJS +=	portable/common/reallocarray.o portable/common/vis.o
-else ifeq ($(UNAME_S),DragonFly)
-GROUP =	bin
-OBJS += portable/common/reallocarray.o portable/common/vis.o
-else ifeq ($(UNAME_S),NetBSD)
-GROUP =	bin
-OBJS += portable/common/reallocarray.o
-else ifeq ($(UNAME_S),Darwin)
-GROUP =	bin
-OBJS += portable/common/reallocarray.o portable/common/strtonum.o \
-	portable/common/vis.o
-CFLAGS += -D_GNU_SOURCE
-else ifeq ($(UNAME_S),OpenBSD)
-GROUP =	bin
-else ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN)
-OBJS +=	portable/common/reallocarray.o portable/linux/setmode.o \
-	portable/linux/signame.o portable/linux/strlcat.o \
-	portable/linux/strlcpy.o portable/common/strtonum.o \
-	portable/linux/unvis.o portable/linux/vis.o
-CFLAGS += -D_GNU_SOURCE
-endif
-
-#
-# Only update /etc/shells at install time, not during update
-#
-ifneq ($(UNAME_S),Darwin)
-UPDATE := `grep -w ${PREFIX}/bin/${PROG} /etc/shells > /dev/null;\
-	[ $$? -ne 0 ] && echo "${PREFIX}/bin/${PROG}" >> /etc/shells`
-endif
-
-ifneq ($(UNAME_S),Darwin)
-all: ${OBJS}
-	${CC} -o ${PROG} ${OBJS}
-else
-all: oksh
-
-oksh: ${OBJS}
-	${CC} ${CFLAGS} ${LDFLAGS} -o ${PROG} ${OBJS}
-endif
-
-install: all
-ifeq ($(UNAME_S),Darwin)
-	@mkdir -p ${PREFIX}/bin ${PREFIX}/share/man/man1
-	${INSTALL} -m 755 ${PROG} ${PREFIX}/bin
-	${INSTALL} -m 644 ${PROG}.1 ${PREFIX}/share/man/man1
-else ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN)
-	@mkdir -p ${PREFIX}/bin ${MANDIR}/man1
-	${INSTALL} -c -s -m 555 ${PROG} ${PREFIX}/bin
-	${INSTALL} -c -m 444 oksh.1 ${MANDIR}/man1/${PROG}.1
-else
-	${INSTALL} -c -s -o root -g ${GROUP} -m 555 ${PROG} ${PREFIX}/bin
-	${INSTALL} -c -o root -g ${GROUP} -m 444 oksh.1 ${MANDIR}/man1/${PROG}.1
-	echo ${UPDATE}
-endif
-
-clean:
-	rm -f ${PROG} ${OBJS}
diff --git a/Makefile b/Makefile
@@ -1,17 +0,0 @@
-#	$OpenBSD: Makefile,v 1.36 2018/01/01 19:45:56 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 \
-	exec.c expr.c history.c io.c jobs.c lex.c mail.c main.c \
-	misc.c path.c shf.c syn.c table.c trap.c tree.c tty.c var.c \
-	version.c vi.c
-
-WARNINGS=yes
-DEFS=	-DEMACS -DVI
-CFLAGS+=${DEFS} -I. -I${.CURDIR} -I${.CURDIR}/../../lib/libc/gen
-MAN=	ksh.1 sh.1
-
-LINKS=	${BINDIR}/ksh ${BINDIR}/rksh
-LINKS+=	${BINDIR}/ksh ${BINDIR}/sh
-
-.include <bsd.prog.mk>
diff --git a/README.md b/README.md
@@ -1,13 +1,13 @@
 oksh
 ====
-Portable OpenBSD ksh(1).
+Portable OpenBSD `ksh(1)`.
 
 Why?
 ----
 Because other operating systems deserve a good shell to use.
-Originally a port of ksh to FreeBSD. The default FreeBSD shell is tcsh.
-No one likes tcsh. DragonFly BSD should also just work.
-Later NetBSD support was added. NetBSD also has a ksh variant so it might
+Originally a port of `ksh` to FreeBSD. The default FreeBSD shell is `tcsh`.
+DragonFly BSD should also just work.
+Later, NetBSD support was added. NetBSD also has a `ksh` variant so it might
 be less useful there.
 Linux support, tested on Slackware and Ubuntu, exists. This includes Cygwin.
 Darwin (Mac OS X) supported as well.
@@ -15,12 +15,19 @@ Other operating system support welcome and appreciated.
 
 Dependencies
 ------------
-GNU make is used for building.
-This build dependency will be removed in a future version of `oksh`.
+A C compiler that understands the `long long` type. A C99 compiler is the
+easiest way to ensure that oksh will build correctly.
+
+A `configure` script that produces a POSIX `Makefile` is available to ease
+building and installation and can be run by:
+```
+$ ./configure
+$ make && sudo make install
+```
 
 In case of emergency
 --------------------
-If you cannot obtain GNU make for whatever reason, a rescue script,
+If you cannot execute make for whatever reason, a rescue script,
 `rescue.sh`, is available. This script contains nothing more than a
 hand-written list of compiler invocations which will build `oksh` in the
 most basic and portable way possible. This rescue shell is perfectly
@@ -33,4 +40,4 @@ The rest are BSD or ISC licensed.
 
 Get a tarball
 -------------
-http://devio.us/~bcallah/oksh/oksh-20180102.tar.gz
+http://devio.us/~bcallah/oksh/oksh-20180107.tar.gz
diff --git a/c_ksh.c b/c_ksh.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: c_ksh.c,v 1.53 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: c_ksh.c,v 1.56 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * built-in Korn commands: c_*
@@ -1068,7 +1068,6 @@ c_jobs(char **wp)
 	return rv;
 }
 
-#ifdef JOBS
 int
 c_fgbg(char **wp)
 {
@@ -1092,7 +1091,6 @@ c_fgbg(char **wp)
 	 */
 	return (bg || Flag(FPOSIX)) ? 0 : rv;
 }
-#endif
 
 struct kill_info {
 	int num_width;
@@ -1399,10 +1397,8 @@ const struct builtin kshbuiltins [] = {
 	{"=typeset", c_typeset},
 	{"+unalias", c_unalias},
 	{"whence", c_whence},
-#ifdef JOBS
 	{"+bg", c_fgbg},
 	{"+fg", c_fgbg},
-#endif
 #ifdef EMACS
 	{"bind", c_bind},
 #endif
diff --git a/portable/common/charclass.h b/charclass.h
rename portable/common/charclass.h → charclass.h
diff --git a/config.h b/config.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: config.h,v 1.16 2017/08/01 14:30:05 deraadt Exp $	*/
+/*	$OpenBSD: config.h,v 1.17 2018/01/05 15:44:31 jca Exp $	*/
 
 /* config.h.  NOT generated automatically. */
 
@@ -11,9 +11,6 @@
 #ifndef CONFIG_H
 #define CONFIG_H
 
-/* Include job control? */
-#define JOBS 1
-
 /* Include brace-expansion? */
 #define BRACE_EXPAND 1
 
@@ -41,4 +38,6 @@
 # define HISTORY
 #endif /* EDIT */
 
+#include "portable.h"
+
 #endif /* CONFIG_H */
diff --git a/configure b/configure
@@ -0,0 +1,339 @@
+#!/bin/sh
+
+# This configure script written by Brian Callahan <bcallah@openbsd.org>
+# and released into the Public Domain.
+
+cccheck() {
+  if [ ! -z "$CC" ] ; then
+cat << EOF > conftest.c
+int main(void){return 0;}
+EOF
+    $CC -o conftest conftest.c > /dev/null 2>&1
+    if [ $? -eq 0 ] ; then
+      rm -f conftest conftest.c
+      cc="$CC"
+      return 0
+    else
+      rm -f conftest conftest.c
+    fi
+  fi
+
+  for compiler in cc clang pcc xlc gcc ; do
+cat << EOF > conftest.c
+int main(void){return 0;}
+EOF
+
+    $compiler -o conftest conftest.c > /dev/null 2>&1
+
+    if [ $? -eq 0 ] ; then
+      rm -f conftest conftest.c
+      cc="$compiler"
+      return 0
+    else
+      rm -f conftest conftest.c
+    fi
+  done
+  return 1
+}
+
+reallocarraycheck() {
+  cat << EOF > conftest.c
+#include <stdlib.h>
+int main(void){reallocarray(NULL, 0, 0);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+setresgidcheck() {
+  cat << EOF > conftest.c
+#include <sys/types.h>
+#include <unistd.h>
+int main(void){setresgid(NULL, NULL, NULL);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+setresuidcheck() {
+  cat << EOF > conftest.c
+#include <sys/types.h>
+#include <unistd.h>
+int main(void){setresuid(NULL, NULL, NULL);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+signamecheck() {
+  cat << EOF > conftest.c
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+int main(void){printf("%s",sys_signame[0]);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+sranddeterministiccheck() {
+  cat << EOF > conftest.c
+#include <stdlib.h>
+int main(void){srand_deterministic(0);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+stravischeck() {
+  cat << EOF > conftest.c
+#include <stdlib.h>
+#include <vis.h>
+int main(void){stravis(NULL, NULL, 0);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+strunvischeck() {
+  cat << EOF > conftest.c
+#include <stdlib.h>
+#include <vis.h>
+int main(void){strunvis(NULL, NULL);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+strtonumcheck() {
+  cat << EOF > conftest.c
+#include <stdlib.h>
+int main(void){strtonum(NULL, 0, 0, NULL);return 0;}
+EOF
+  $cc $tflags -o conftest conftest.c > /dev/null 2>&1
+  if [ $? -eq 0 ] ; then
+    rm -f conftest conftest.c
+    return 0
+  else
+    rm -f conftest conftest.c
+    return 1
+  fi
+}
+
+if [ ! -z "$PREFIX" ] ; then
+prefix="$PREFIX"
+else
+prefix="/usr/local"
+fi
+
+mandir="$prefix/man/man1"
+
+# Options.
+for opt
+do
+  case "$opt" in
+    --prefix=*)
+	prefix=`echo $opt | cut -d '=' -f 2`
+	;;
+    --mandir=*)
+	mandir=`echo $opt | cut -d '=' -f 2`
+	;;
+    --help|-h)
+	echo "Usage: configure [options]"
+	echo ""
+	echo "Options:"
+	printf "  --help or -h               "
+	echo "Display this help message"
+	printf "  --prefix=PREFIX            "
+	echo "Top level install directory is PREFIX [$prefix]"
+	printf "  --mandir=MANDIR            "
+	echo "Manual pages are installed to MANDIR [$mandir]"
+	exit 1
+	;;
+    *)
+	echo "Unknown option: $opt"
+	;;
+  esac
+done
+
+if [ ! -z "$CFLAGS" ] ; then
+cflags="$CFLAGS -DEMACS -DVI"
+else
+cflags="-DEMACS -DVI"
+fi
+
+printf "checking for C compiler... "
+cccheck
+if [ $? -ne 0 ] ; then
+  echo "not found"
+  echo "Please install a C compiler and re-run configure."
+  exit 1
+else
+  echo "$cc"
+fi
+
+printf "checking for OS... "
+os=`uname -s`
+echo "$os"
+
+if [ "x$os" = "xLinux" ] ; then
+  cflags="$cflags -D_GNU_SOURCE"
+elif [ "x$os" = "xNetBSD" ] ; then
+  tflags="-D_OPENBSD_SOURCE"
+  cflags="$cflags $tflags"
+else
+  tflags=""
+fi
+
+cat << EOF > pconfig.h
+/* This file automatically generated by configure.  */
+
+EOF
+
+printf "checking for reallocarray... "
+strtonumcheck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_REALLOCARRAY" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+printf "checking for setresgid... "
+setresgidcheck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_SETRESGID" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+printf "checking for setresuid... "
+setresuidcheck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_SETRESUID" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+printf "checking for srand_deterministic... "
+sranddeterministiccheck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_SRAND_DETERMINISTIC" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+printf "checking for stravis... "
+stravischeck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_STRAVIS" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+printf "checking for strtonum... "
+strtonumcheck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_STROTONUM" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+printf "checking for strunvis... "
+strunvischeck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_STRUNVIS" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+printf "checking for sys_signame... "
+signamecheck
+if [ $? -ne 0 ] ; then
+  echo "#define NEED_SIGNAME" >> pconfig.h
+  echo "no"
+else
+  echo "yes"
+fi
+
+cat << EOF > Makefile
+# This Makefile automatically generated by configure.
+
+CC =		$cc
+CFLAGS =	$cflags
+PREFIX =	$prefix
+MANDIR =	$mandir
+PROG =		oksh
+
+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 \\
+	path.o shf.o syn.o table.o trap.o tree.o tty.o var.o version.o vi.o \\
+	reallocarray.o signame.o strlcat.o strlcpy.o strtonum.o unvis.o vis.o
+
+ETS =	\`grep -w \${PREFIX}/bin/\${PROG} /etc/shells > /dev/null; \\
+	[ \$\$? -ne 0 ] && echo "\${PREFIX}/bin/\${PROG}" >> /etc/shells\`
+
+all: \${PROG}
+
+\${PROG}: \${OBJS}
+	\${CC} \${LDFLAGS} -o \${PROG} \${OBJS}
+
+install:
+	install -c -s -m 755 \${PROG} \${PREFIX}/bin
+	install -c -m 644 oksh.1 \${MANDIR}/\${PROG}.1
+	echo \${ETS}
+
+clean:
+	rm -f \${PROG} \${OBJS}
+
+distclean: clean
+	rm -f Makefile pconfig.h
+EOF
diff --git a/edit.c b/edit.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: edit.c,v 1.59 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: edit.c,v 1.61 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * Command line editing - common code
diff --git a/emacs.c b/emacs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: emacs.c,v 1.78 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: emacs.c,v 1.81 2018/01/07 19:18:56 millert Exp $	*/
 
 /*
  *  Emacs-like command line editing and history
@@ -14,9 +14,7 @@
 #include "config.h"
 #ifdef EMACS
 
-#ifdef __linux__
-#include "portable/linux/queue.h"
-#else
+#ifndef __linux__
 #include <sys/queue.h>
 #endif
 #include <sys/stat.h>
@@ -1296,13 +1294,13 @@ kb_del(struct kb_entry *k)
 static struct kb_entry *
 kb_add_string(void *func, void *args, char *str)
 {
-	unsigned int		i, count;
+	unsigned int		ele, count;
 	struct kb_entry		*k;
 	struct x_ftab		*xf = NULL;
 
-	for (i = 0; i < NELEM(x_ftab); i++)
-		if (x_ftab[i].xf_func == func) {
-			xf = (struct x_ftab *)&x_ftab[i];
+	for (ele = 0; ele < NELEM(x_ftab); ele++)
+		if (x_ftab[ele].xf_func == func) {
+			xf = (struct x_ftab *)&x_ftab[ele];
 			break;
 		}
 	if (xf == NULL)
@@ -1332,21 +1330,21 @@ static struct kb_entry *
 kb_add(void *func, void *args, ...)
 {
 	va_list			ap;
-	int			i, count;
-	char			l[LINE + 1];
-
-	va_start(ap, args);
-	count = 0;
-	while (va_arg(ap, unsigned int) != 0)
-		count++;
-	va_end(ap);
+	unsigned char		ch;
+	unsigned int		i;
+	char			line[LINE + 1];
 
 	va_start(ap, args);
-	for (i = 0; i <= count /* <= is correct */; i++)
-		l[i] = (unsigned char)va_arg(ap, unsigned int);
+	for (i = 0; i < sizeof(line) - 1; i++) {
+		ch = va_arg(ap, unsigned int);
+		if (ch == 0)
+			break;
+		line[i] = ch;
+	}
 	va_end(ap);
+	line[i] = '\0';
 
-	return (kb_add_string(func, args, l));
+	return (kb_add_string(func, args, line));
 }
 
 static void
diff --git a/eval.c b/eval.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: eval.c,v 1.55 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: eval.c,v 1.57 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * Expansion - quoting, separation, substitution, globbing
diff --git a/expand.h b/expand.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: expand.h,v 1.13 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: expand.h,v 1.15 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * Expanding strings
@@ -46,7 +46,7 @@ typedef char * XStringP;
 
 /* check if there are at least n bytes left */
 #define	XcheckN(xs, xp, n) do { \
-		    size_t more = ((xp) + (n)) - (xs).end; \
+		    ptrdiff_t more = ((xp) + (n)) - (xs).end; \
 		    if (more > 0) \
 			xp = Xcheck_grow_(&xs, xp, more); \
 		} while (0)
diff --git a/history.c b/history.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: history.c,v 1.76 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: history.c,v 1.78 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * command history
@@ -22,7 +22,7 @@
 #include <string.h>
 #include <unistd.h>
 #if defined(__linux__) || defined(__CYGWIN__)
-#include "portable/linux/vis.h"
+#include "vis.h"
 #else
 #include <vis.h>
 #endif
diff --git a/jobs.c b/jobs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: jobs.c,v 1.55 2016/03/17 23:33:23 mmcc Exp $	*/
+/*	$OpenBSD: jobs.c,v 1.57 2018/01/05 15:44:31 jca Exp $	*/
 
 /*
  * Process and job control
@@ -67,7 +67,7 @@ struct proc {
 #define JF_CHANGED	0x040	/* process has changed state */
 #define JF_KNOWN	0x080	/* $! referenced */
 #define JF_ZOMBIE	0x100	/* known, unwaited process */
-#define JF_REMOVE	0x200	/* flagged for removal (j_jobs()/j_noityf()) */
+#define JF_REMOVE	0x200	/* flagged for removal (j_jobs()/j_notify()) */
 #define JF_USETTYMODE	0x400	/* tty mode saved if process exits normally */
 #define JF_SAVEDTTYPGRP	0x800	/* j->saved_ttypgrp is valid */
 
@@ -86,10 +86,8 @@ struct job {
 	Proc	*proc_list;	/* process list */
 	Proc	*last_proc;	/* last process in list */
 	Coproc_id coproc_id;	/* 0 or id of coprocess output pipe */
-#ifdef JOBS
 	struct termios ttystate;/* saved tty state for stopped jobs */
 	pid_t	saved_ttypgrp;	/* saved tty process group for stopped jobs */
-#endif /* JOBS */
 };
 
 /* Flags for j_waitj() */
@@ -127,13 +125,11 @@ static int		child_max;	/* CHILD_MAX */
 /* held_sigchld is set if sigchld occurs before a job is completely started */
 static volatile sig_atomic_t held_sigchld;
 
-#ifdef JOBS
 static struct shf	*shl_j;
 static int		ttypgrp_ok;	/* set if can use tty pgrps */
 static pid_t		restore_ttypgrp = -1;
 static pid_t		our_pgrp;
 static int const	tt_sigs[] = { SIGTSTP, SIGTTIN, SIGTTOU };
-#endif /* JOBS */
 
 static void		j_set_async(Job *);
 static void		j_startjob(Job *);
@@ -163,7 +159,6 @@ j_init(int mflagset)
 	setsig(&sigtraps[SIGCHLD], j_sigchld,
 	    SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
 
-#ifdef JOBS
 	if (!mflagset && Flag(FTALKING))
 		Flag(FMONITOR) = 1;
 
@@ -189,10 +184,8 @@ j_init(int mflagset)
 	/* j_change() calls tty_init() */
 	if (Flag(FMONITOR))
 		j_change();
-	else
-#endif /* JOBS */
-		if (Flag(FTALKING))
-			tty_init(true);
+	else if (Flag(FTALKING))
+		tty_init(true);
 }
 
 /* suspend the shell */
@@ -267,21 +260,18 @@ j_exit(void)
 				kill_job(j, SIGHUP);
 			else
 				killpg(j->pgrp, SIGHUP);
-#ifdef JOBS
 			if (j->state == PSTOPPED) {
 				if (j->pgrp == 0)
 					kill_job(j, SIGCONT);
 				else
 					killpg(j->pgrp, SIGCONT);
 			}
-#endif /* JOBS */
 		}
 	}
 	if (killed)
 		sleep(1);
 	j_notify();
 
-#ifdef JOBS
 	if (kshpid == procpid && restore_ttypgrp >= 0) {
 		/* Need to restore the tty pgrp to what it was when the
 		 * shell started up, so that the process that started us
@@ -297,10 +287,8 @@ j_exit(void)
 		Flag(FMONITOR) = 0;
 		j_change();
 	}
-#endif /* JOBS */
 }
 
-#ifdef JOBS
 /* turn job control on or off according to Flag(FMONITOR) */
 void
 j_change(void)
@@ -389,7 +377,6 @@ j_change(void)
 			tty_close();
 	}
 }
-#endif /* JOBS */
 
 /* execute tree in child subprocess */
 int
@@ -472,7 +459,6 @@ exchild(struct op *t, int flags, volatile int *xerrok,
 	else
 		p->pid = i;
 
-#ifdef JOBS
 	/* job control set up */
 	if (Flag(FMONITOR) && !(flags&XXCOM)) {
 		int	dotty = 0;
@@ -493,7 +479,6 @@ exchild(struct op *t, int flags, volatile int *xerrok,
 		if (ttypgrp_ok && dotty && !(flags & XBGND))
 			tcsetpgrp(tty_fd, j->pgrp);
 	}
-#endif /* JOBS */
 
 	/* used to close pipe input fd */
 	if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) ||
@@ -505,7 +490,6 @@ exchild(struct op *t, int flags, volatile int *xerrok,
 			coproc_cleanup(false);
 		sigprocmask(SIG_SETMASK, &omask, NULL);
 		cleanup_parents_env();
-#ifdef JOBS
 		/* If FMONITOR or FTALKING is set, these signals are ignored,
 		 * if neither FMONITOR nor FTALKING are set, the signals have
 		 * their inherited values.
@@ -515,7 +499,6 @@ exchild(struct op *t, int flags, volatile int *xerrok,
 				setsig(&sigtraps[tt_sigs[i]], SIG_DFL,
 				    SS_RESTORE_DFL|SS_FORCE);
 		}
-#endif /* JOBS */
 		if (Flag(FBGNICE) && (flags & XBGND))
 			nice(4);
 		if ((flags & XBGND) && !Flag(FMONITOR)) {
@@ -533,10 +516,8 @@ exchild(struct op *t, int flags, volatile int *xerrok,
 		}
 		remove_job(j, "child");	/* in case of `jobs` command */
 		nzombie = 0;
-#ifdef JOBS
 		ttypgrp_ok = 0;
 		Flag(FMONITOR) = 0;
-#endif /* JOBS */
 		Flag(FTALKING) = 0;
 		tty_close();
 		cleartraps();
@@ -550,12 +531,10 @@ exchild(struct op *t, int flags, volatile int *xerrok,
 	/* Ensure next child gets a (slightly) different $RANDOM sequence */
 	change_random();
 	if (!(flags & XPIPEO)) {	/* last process in a job */
-#ifdef JOBS
 		/* YYY: Is this needed? (see also YYY above)
 		   if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND)))
 			tcsetpgrp(tty_fd, j->pgrp);
 		*/
-#endif /* JOBS */
 		j_startjob(j);
 		if (flags & XCOPROC) {
 			j->coproc_id = coproc.id;
@@ -697,10 +676,8 @@ j_kill(const char *cp, int sig)
 			rv = 1;
 		}
 	} else {
-#ifdef JOBS
 		if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP))
 			(void) killpg(j->pgrp, SIGCONT);
-#endif /* JOBS */
 		if (killpg(j->pgrp, sig) < 0) {
 			bi_errorf("%s: %s", cp, strerror(errno));
 			rv = 1;
@@ -712,7 +689,6 @@ j_kill(const char *cp, int sig)
 	return rv;
 }
 
-#ifdef JOBS
 /* fg and bg built-ins: called only if Flag(FMONITOR) set */
 int
 j_resume(const char *cp, int bg)
@@ -759,7 +735,6 @@ j_resume(const char *cp, int bg)
 	if (bg)
 		j_set_async(j);
 	else {
-# ifdef JOBS
 		/* attach tty to job */
 		if (j->state == PRUNNING) {
 			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
@@ -779,7 +754,6 @@ j_resume(const char *cp, int bg)
 				return 1;
 			}
 		}
-# endif /* JOBS */
 		j->flags |= JF_FG;
 		j->flags &= ~JF_KNOWN;
 		if (j == async_job)
@@ -791,7 +765,6 @@ j_resume(const char *cp, int bg)
 
 		if (!bg) {
 			j->flags &= ~JF_FG;
-# ifdef JOBS
 			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
 				tcsetattr(tty_fd, TCSADRAIN, &tty_state);
 			if (ttypgrp_ok && tcsetpgrp(tty_fd, our_pgrp) < 0) {
@@ -800,7 +773,6 @@ j_resume(const char *cp, int bg)
 				    tty_fd, (int) our_pgrp,
 				    strerror(errno));
 			}
-# endif /* JOBS */
 		}
 		sigprocmask(SIG_SETMASK, &omask, NULL);
 		bi_errorf("cannot continue job %s: %s",
@@ -808,17 +780,14 @@ j_resume(const char *cp, int bg)
 		return 1;
 	}
 	if (!bg) {
-# ifdef JOBS
 		if (ttypgrp_ok) {
 			j->flags &= ~(JF_SAVEDTTY | JF_SAVEDTTYPGRP);
 		}
-# endif /* JOBS */
 		rv = j_waitj(j, JW_NONE, "jw:resume");
 	}
 	sigprocmask(SIG_SETMASK, &omask, NULL);
 	return rv;
 }
-#endif /* JOBS */
 
 /* are there any running or stopped jobs ? */
 int
@@ -828,10 +797,8 @@ j_stopped_running(void)
 	int	which = 0;
 
 	for (j = job_list; j != NULL; j = j->next) {
-#ifdef JOBS
 		if (j->ppid == procpid && j->state == PSTOPPED)
 			which |= 1;
-#endif /* JOBS */
 		if (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid &&
 		    j->ppid == procpid && j->state == PRUNNING)
 			which |= 2;
@@ -919,10 +886,8 @@ j_notify(void)
 
 	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
 	for (j = job_list; j; j = j->next) {
-#ifdef JOBS
 		if (Flag(FMONITOR) && (j->flags & JF_CHANGED))
 			j_print(j, JP_MEDIUM, shl_out);
-#endif /* JOBS */
 		/* Remove job after doing reports so there aren't
 		 * multiple +/- jobs.
 		 */
@@ -1053,7 +1018,6 @@ j_waitj(Job *j,
 		int	status;
 
 		j->flags &= ~JF_FG;
-#ifdef JOBS
 		if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) {
 			/*
 			 * Save the tty's current pgrp so it can be restored
@@ -1080,7 +1044,6 @@ j_waitj(Job *j,
 				tcgetattr(tty_fd, &j->ttystate);
 			}
 		}
-#endif /* JOBS */
 		if (tty_fd >= 0) {
 			/* Only restore tty settings if job was originally
 			 * started in the foreground.  Problems can be
@@ -1110,7 +1073,6 @@ j_waitj(Job *j,
 					j->flags &= ~JF_USETTYMODE;
 			}
 		}
-#ifdef JOBS
 		/* If it looks like user hit ^C to kill a job, pretend we got
 		 * one too to break out of for loops, etc.  (at&t ksh does this
 		 * even when not monitoring, but this doesn't make sense since
@@ -1121,7 +1083,6 @@ j_waitj(Job *j,
 		    WIFSIGNALED(status) &&
 		    (sigtraps[WTERMSIG(status)].flags & TF_TTY_INTR))
 			trapsig(WTERMSIG(status));
-#endif /* JOBS */
 	}
 
 	j_usrtime = j->usrtime;
@@ -1195,12 +1156,9 @@ found:
 		timersub(&j->systime, &ru0.ru_stime, &j->systime);
 		ru0 = ru1;
 		p->status = status;
-#ifdef JOBS
 		if (WIFSTOPPED(status))
 			p->state = PSTOPPED;
-		else
-#endif /* JOBS */
-		if (WIFSIGNALED(status))
+		else if (WIFSIGNALED(status))
 			p->state = PSIGNALLED;
 		else
 			p->state = PEXITED;
@@ -1278,7 +1236,6 @@ check_job(Job *j)
 	}
 
 	j->flags |= JF_CHANGED;
-#ifdef JOBS
 	if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) {
 		/* Only put stopped jobs at the front to avoid confusing
 		 * the user (don't want finished jobs effecting %+ or %-)
@@ -1307,7 +1264,6 @@ check_job(Job *j)
 				remove_job(j, "notify");
 		}
 	}
-#endif /* JOBS */
 	if (!Flag(FMONITOR) && !(j->flags & (JF_WAITING|JF_FG)) &&
 	    j->state != PSTOPPED) {
 		if (j == async_job || (j->flags & JF_KNOWN)) {
@@ -1337,7 +1293,7 @@ j_print(Job *j, int how, struct shf *shf)
 	int	output = 0;
 
 	if (how == JP_PGRP) {
-		/* POSIX doesn't say what to do it there is no process
+		/* POSIX doesn't say what to do if there is no process
 		 * group leader (ie, !FMONITOR).  We arbitrarily return
 		 * last pid (which is what $! returns).
 		 */
diff --git a/lex.c b/lex.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: lex.c,v 1.75 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: lex.c,v 1.77 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * lexical analysis and source input
diff --git a/lex.h b/lex.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: lex.h,v 1.18 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: lex.h,v 1.20 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * Source input, lexer and parser
diff --git a/main.c b/main.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: main.c,v 1.85 2017/12/12 00:18:58 tb Exp $	*/
+/*	$OpenBSD: main.c,v 1.86 2018/01/05 15:44:31 jca Exp $	*/
 
 /*
  * startup, main loop, environments and error handling
@@ -91,9 +91,7 @@ static const char *initcoms [] = {
 	 /* Standard ksh aliases */
 	  "hash=alias -t",	/* not "alias -t --": hash -r needs to work */
 	  "type=whence -v",
-#ifdef JOBS
 	  "stop=kill -STOP",
-#endif
 	  "autoload=typeset -fu",
 	  "functions=typeset -f",
 #ifdef HISTORY
diff --git a/misc.c b/misc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: misc.c,v 1.62 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: misc.c,v 1.65 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * Miscellaneous functions
@@ -139,19 +139,13 @@ const struct option sh_options[] = {
 	{ "keyword",	'k',		OF_ANY },
 	{ "login",	'l',	    OF_CMDLINE },
 	{ "markdirs",	'X',		OF_ANY },
-#ifdef JOBS
 	{ "monitor",	'm',		OF_ANY },
-#else /* JOBS */
-	{ NULL,	'm',		     0 }, /* so FMONITOR not ifdef'd */
-#endif /* JOBS */
 	{ "noclobber",	'C',		OF_ANY },
 	{ "noexec",	'n',		OF_ANY },
 	{ "noglob",	'f',		OF_ANY },
 	{ "nohup",	  0,		OF_ANY },
 	{ "nolog",	  0,		OF_ANY }, /* no effect */
-#ifdef	JOBS
 	{ "notify",	'b',		OF_ANY },
-#endif	/* JOBS */
 	{ "nounset",	'u',		OF_ANY },
 	{ "physical",	  0,		OF_ANY }, /* non-standard */
 	{ "posix",	  0,		OF_ANY }, /* non-standard */
@@ -274,12 +268,10 @@ change_flag(enum sh_flag f,
 
 	oldval = Flag(f);
 	Flag(f) = newval;
-#ifdef JOBS
 	if (f == FMONITOR) {
 		if (what != OF_CMDLINE && newval != oldval)
 			j_change();
 	} else
-#endif /* JOBS */
 #ifdef EDIT
 	if (0
 # ifdef VI
diff --git a/path.c b/path.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: path.c,v 1.20 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: path.c,v 1.22 2018/01/06 16:28:58 millert Exp $	*/
 
 #include <sys/stat.h>
 
diff --git a/portable/linux/queue.h b/portable.h
rename portable/linux/queue.h → portable.h
@@ -1,3 +1,162 @@
+/*
+ * Multi-platform support.
+ */
+
+#ifndef _OKSH_PORTABLE_H_
+#define _OKSH_PORTABLE_H_
+
+/*
+ * Includes
+ */
+
+#ifdef __linux__
+#include <sys/file.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#endif /* __linux__ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#ifdef __APPLE__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif /* __APPLE__ */
+
+#include <time.h>
+
+#include "pconfig.h"
+
+/*
+ * Defines
+ */
+
+#ifndef CHILD_MAX
+#define CHILD_MAX	80
+#endif /* CHILD_MAX */
+
+#ifndef O_EXLOCK
+#define O_EXLOCK	0
+#endif /* O_EXLOCK */
+
+#ifndef _PW_NAME_LEN
+#ifdef __linux__
+#define _PW_NAME_LEN	LOGIN_NAME_MAX
+#else
+#define _PW_NAME_LEN	MAXLOGNAME - 1
+#endif /* __linux__ */
+#endif /* _PW_NAME_LEN */
+
+#ifndef RLIMIT_RSS
+#define	RLIMIT_RSS	5		/* resident set size */
+#endif /* RLIMIT_RSS */
+
+#ifndef RLIMIT_MEMLOCK
+#define	RLIMIT_MEMLOCK	6		/* locked-in-memory address space */
+#endif /* RLIMIT_MEMLOCK */
+
+#ifndef RLIMIT_NPROC
+#define	RLIMIT_NPROC	7		/* number of processes */
+#endif /* RLIMIT_NPROC */
+
+/* Convert clock_gettime() to clock_get_time() on Max OS X */
+#ifdef __APPLE__
+#define clock_gettime(x, y)						\
+	clock_serv_t cclock;						\
+	mach_timespec_t mts;						\
+	host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); \
+	clock_get_time(cclock, &mts);					\
+	mach_port_deallocate(mach_task_self(), cclock);			\
+	(y)->tv_sec = mts.tv_sec;					\
+	(y)->tv_nsec = mts.tv_nsec;
+#endif /* __APPLE__ */
+
+#ifdef NEED_SETRESGID
+#define setresgid(x, y, z)	setgid(x); setegid(y); setgid(z)
+#endif /* setresgid */
+
+#ifdef NEED_SETRESUID
+#define setresuid(x, y, z)	setuid(x); seteuid(y); setuid(z)
+#endif /* NEED_SETRESUID */
+
+#ifdef NEED_SRAND_DETERMINISTIC
+#define srand_deterministic(x)	srand(x)
+#endif /* NEED_SRAND_DETERMINISTIC */
+
+/* struct stat compatibility */
+#ifdef __APPLE__
+#define st_mtim	st_mtimespec
+#endif /* __APPLE__ */
+
+/* Cygwin already has a sys_signame but we want to use our own */
+#ifdef __CYGWIN__
+#define sys_signame	esys_signame
+#endif
+
+/* From OpenBSD sys/time.h */
+#ifndef __OpenBSD__
+#define timespeccmp(tsp, usp, cmp)                                      \
+        (((tsp)->tv_sec == (usp)->tv_sec) ?                             \
+            ((tsp)->tv_nsec cmp (usp)->tv_nsec) :                       \
+            ((tsp)->tv_sec cmp (usp)->tv_sec))
+
+#define timespecsub(tsp, usp, vsp)                                      \
+        do {                                                            \
+                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \
+                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \
+                if ((vsp)->tv_nsec < 0) {                               \
+                        (vsp)->tv_sec--;                                \
+                        (vsp)->tv_nsec += 1000000000L;                  \
+                }                                                       \
+        } while (0)
+#endif /* !__OpenBSD__ */
+
+/*
+ * Prototypes
+ */
+
+#ifdef NEED_REALLOCARRAY
+void	 *reallocarray(void *, size_t, size_t);
+#endif /* NEED_REALLOCARRAY */
+
+#ifdef NEED_STRAVIS
+int	  stravis(char **, const char *, int);
+#endif /* NEED_STRAVIS */
+
+#ifdef NEED_STRLCAT
+size_t	strlcat(char *, const char *, size_t);
+#endif /* NEED_STRLCAT */
+
+#ifdef NEED_STRLCPY
+size_t	strlcpy(char *, const char *, size_t);
+#endif /* NEED_STRLCPY */
+
+#ifdef NEED_STRTONUM
+long long strtonum(const char *numstr, long long minval, long long maxval,
+		   const char **errstrp);
+#endif /* NEED_STRTONUM */
+
+#ifdef NEED_STRUNVIS
+int	  strunvis(char *, const char *);
+#endif /* NEED_STRUNVIS */
+
+/*
+ * Externs
+ */
+
+#ifdef NEED_SIGNAME
+extern const char *const sys_signame[NSIG];
+#endif /* NEED_SIGNAME */
+
+/*
+ * OpenBSD sys/queue.h
+ */
+
+/* The following should only be necessary on non-BSD systems.  */
+
+#if defined(__linux__)
+
 /*	$OpenBSD: queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $	*/
 /*	$NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $	*/
 
@@ -641,3 +800,7 @@ struct {								\
 	_Q_INVALIDATE((elm)->field.cqe_prev);				\
 	_Q_INVALIDATE((elm)->field.cqe_next);				\
 } while (0)
+
+#endif /* defined(__linux__) */
+
+#endif /* !_OKSH_PORTABLE_H_ */
diff --git a/portable/common/vis.c b/portable/common/vis.c
@@ -1,63 +0,0 @@
-/*	$OpenBSD: vis.c,v 1.25 2015/09/13 11:32:51 guenther Exp $ */
-/*-
- * Copyright (c) 1989, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <ctype.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <vis.h>
-
-#ifdef __APPLE__
-#include "../darwin/darwin.h"
-#else
-#include "../freebsd/freebsd.h"
-#endif
-
-/* Mac OS X/FreeBSD/DragonFly are missing stravis(). */
-int
-stravis(char **outp, const char *src, int flag)
-{
-	char *buf;
-	int len, serrno;
-
-	buf = reallocarray(NULL, 4, strlen(src) + 1);
-	if (buf == NULL)
-		return -1;
-	len = strvis(buf, src, flag);
-	serrno = errno;
-	*outp = realloc(buf, len + 1);
-	if (*outp == NULL) {
-		*outp = buf;
-		errno = serrno;
-	}
-	return (len);
-}
diff --git a/portable/darwin/darwin.h b/portable/darwin/darwin.h
@@ -1,52 +0,0 @@
-/*
- * Mac OS X support.
- */
-
- /* Includes */
-#include <sys/param.h>
-#include <sys/time.h>
-#include <mach/clock.h>
-#include <mach/mach.h>
-
-/* Defines */
-#define _PW_NAME_LEN	MAXLOGNAME - 1
-#define srand_deterministic(x)	srand(x)
-
-/* Not really sure on these two, but it seems to work ok. */
-#define setresgid(x, y, z)	setgid(x); setegid(y); setgid(z)
-#define setresuid(x, y, z)	setuid(x); seteuid(y); setuid(z)
-
-/* Convert clock_gettime() to clock_get_time() */
-#define clock_gettime(x, y)						\
-	clock_serv_t cclock;						\
-	mach_timespec_t mts;						\
-	host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); \
-	clock_get_time(cclock, &mts);					\
-	mach_port_deallocate(mach_task_self(), cclock);			\
-	(y)->tv_sec = mts.tv_sec;					\
-	(y)->tv_nsec = mts.tv_nsec;
-
-/* struct stat compatibility */
-#define st_mtim	st_mtimespec
-
-/* From OpenBSD sys/time.h */
-#define timespeccmp(tsp, usp, cmp)                                      \
-        (((tsp)->tv_sec == (usp)->tv_sec) ?                             \
-            ((tsp)->tv_nsec cmp (usp)->tv_nsec) :                       \
-            ((tsp)->tv_sec cmp (usp)->tv_sec))
-
-#define timespecsub(tsp, usp, vsp)                                      \
-        do {                                                            \
-                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \
-                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \
-                if ((vsp)->tv_nsec < 0) {                               \
-                        (vsp)->tv_sec--;                                \
-                        (vsp)->tv_nsec += 1000000000L;                  \
-                }                                                       \
-        } while (0)
-
-/* Functions */
-void	 *reallocarray(void *, size_t, size_t);
-int	  stravis(char **, const char *, int);
-long long strtonum(const char *numstr, long long minval, long long maxval,
-		   const char **errstrp);
diff --git a/portable/freebsd/freebsd.h b/portable/freebsd/freebsd.h
@@ -1,30 +0,0 @@
-/*
- * FreeBSD and DragonFly BSD support.
- */
-
-/* Includes */
-#include <sys/param.h>
-#include <time.h>
-
-/* Defines */
-#define _PW_NAME_LEN	MAXLOGNAME - 1
-#define srand_deterministic(x)	srand(x)
-
-/* From OpenBSD sys/time.h */
-#define timespeccmp(tsp, usp, cmp)                                      \
-        (((tsp)->tv_sec == (usp)->tv_sec) ?                             \
-            ((tsp)->tv_nsec cmp (usp)->tv_nsec) :                       \
-            ((tsp)->tv_sec cmp (usp)->tv_sec))
-
-#define timespecsub(tsp, usp, vsp)                                      \
-        do {                                                            \
-                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \
-                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \
-                if ((vsp)->tv_nsec < 0) {                               \
-                        (vsp)->tv_sec--;                                \
-                        (vsp)->tv_nsec += 1000000000L;                  \
-                }                                                       \
-        } while (0)
-
-/* Prototypes */
-int	  stravis(char **, const char *, int);
diff --git a/portable/linux/linux.h b/portable/linux/linux.h
@@ -1,60 +0,0 @@
-/*
- * Linux support.
- */
-
-/* Includes */
-#include <sys/file.h>
-#include <sys/param.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <time.h>
-
-/* Defines */
-#define _PW_NAME_LEN	LOGIN_NAME_MAX
-#define O_EXLOCK	0
-#define srand_deterministic(x)	srand(x)
-#define sys_signame	esys_signame
-
-#ifndef __CYGWIN__
-#define CHILD_MAX	80
-#endif
-
-#ifdef __CYGWIN__
-#define setresgid(x, y, z)	setgid(x); setegid(x)
-#define setresuid(x, y, z)	setuid(x); seteuid(x)
-#endif
-
-/* From OpenBSD sys/time.h */
-#define	timespeccmp(tsp, usp, cmp)					\
-	(((tsp)->tv_sec == (usp)->tv_sec) ?				\
-	    ((tsp)->tv_nsec cmp (usp)->tv_nsec) :			\
-	    ((tsp)->tv_sec cmp (usp)->tv_sec))
-
-#define	timespecsub(tsp, usp, vsp)					\
-	do {								\
-		(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;		\
-		(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;	\
-		if ((vsp)->tv_nsec < 0) {				\
-			(vsp)->tv_sec--;				\
-			(vsp)->tv_nsec += 1000000000L;			\
-		}							\
-	} while (0)
-
-/* Resource limits for Cygwin, from OpenBSD sys/resource.h */
-#ifdef __CYGWIN__
-#define	RLIMIT_RSS	5		/* resident set size */
-#define	RLIMIT_MEMLOCK	6		/* locked-in-memory address space */
-#define	RLIMIT_NPROC	7		/* number of processes */
-#endif
-
-/* Functions */
-mode_t	getmode(const void *, mode_t);
-void   *reallocarray(void *, size_t, size_t);
-void   *setmode(const char *);
-size_t	strlcat(char *, const char *, size_t);
-size_t	strlcpy(char *, const char *, size_t);
-long long strtonum(const char *numstr, long long minval, long long maxval,
-		   const char **errstrp);
-
-/* Externs */
-extern const char *const sys_signame[NSIG];
diff --git a/portable/linux/setmode.c b/portable/linux/setmode.c
@@ -1,455 +0,0 @@
-/*	$OpenBSD: setmode.c,v 1.22 2014/10/11 04:14:35 deraadt Exp $	*/
-/*	$NetBSD: setmode.c,v 1.15 1997/02/07 22:21:06 christos Exp $	*/
-
-/*
- * Copyright (c) 1989, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Dave Borman at Cray Research, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef SETMODE_DEBUG
-#include <stdio.h>
-#endif
-
-#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
-#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
-
-/*
- * Linux super sucks here.
- */
-#define S_ISTXT S_ISVTX
-extern void *reallocarray(void *, size_t, size_t);
-
-typedef struct bitcmd {
-	char	cmd;
-	char	cmd2;
-	mode_t	bits;
-} BITCMD;
-
-#define	CMD2_CLR	0x01
-#define	CMD2_SET	0x02
-#define	CMD2_GBITS	0x04
-#define	CMD2_OBITS	0x08
-#define	CMD2_UBITS	0x10
-
-static BITCMD	*addcmd(BITCMD *, int, int, int, u_int);
-static void	 compress_mode(BITCMD *);
-#ifdef SETMODE_DEBUG
-static void	 dumpmode(BITCMD *);
-#endif
-
-/*
- * Given the old mode and an array of bitcmd structures, apply the operations
- * described in the bitcmd structures to the old mode, and return the new mode.
- * Note that there is no '=' command; a strict assignment is just a '-' (clear
- * bits) followed by a '+' (set bits).
- */
-mode_t
-getmode(const void *bbox, mode_t omode)
-{
-	const BITCMD *set;
-	mode_t clrval, newmode, value;
-
-	set = (const BITCMD *)bbox;
-	newmode = omode;
-	for (value = 0;; set++)
-		switch(set->cmd) {
-		/*
-		 * When copying the user, group or other bits around, we "know"
-		 * where the bits are in the mode so that we can do shifts to
-		 * copy them around.  If we don't use shifts, it gets real
-		 * grundgy with lots of single bit checks and bit sets.
-		 */
-		case 'u':
-			value = (newmode & S_IRWXU) >> 6;
-			goto common;
-
-		case 'g':
-			value = (newmode & S_IRWXG) >> 3;
-			goto common;
-
-		case 'o':
-			value = newmode & S_IRWXO;
-common:			if (set->cmd2 & CMD2_CLR) {
-				clrval =
-				    (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
-				if (set->cmd2 & CMD2_UBITS)
-					newmode &= ~((clrval<<6) & set->bits);
-				if (set->cmd2 & CMD2_GBITS)
-					newmode &= ~((clrval<<3) & set->bits);
-				if (set->cmd2 & CMD2_OBITS)
-					newmode &= ~(clrval & set->bits);
-			}
-			if (set->cmd2 & CMD2_SET) {
-				if (set->cmd2 & CMD2_UBITS)
-					newmode |= (value<<6) & set->bits;
-				if (set->cmd2 & CMD2_GBITS)
-					newmode |= (value<<3) & set->bits;
-				if (set->cmd2 & CMD2_OBITS)
-					newmode |= value & set->bits;
-			}
-			break;
-
-		case '+':
-			newmode |= set->bits;
-			break;
-
-		case '-':
-			newmode &= ~set->bits;
-			break;
-
-		case 'X':
-			if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
-				newmode |= set->bits;
-			break;
-
-		case '\0':
-		default:
-#ifdef SETMODE_DEBUG
-			(void)printf("getmode:%04o -> %04o\n", omode, newmode);
-#endif
-			return (newmode);
-		}
-}
-
-#define	ADDCMD(a, b, c, d)						\
-	if (set >= endset) {						\
-		BITCMD *newset;						\
-		setlen += SET_LEN_INCR;					\
-		newset = reallocarray(saveset, setlen, sizeof(BITCMD));	\
-		if (newset == NULL) {					\
-			free(saveset);					\
-			return (NULL);					\
-		}							\
-		set = newset + (set - saveset);				\
-		saveset = newset;					\
-		endset = newset + (setlen - 2);				\
-	}								\
-	set = addcmd(set, (a), (b), (c), (d))
-
-#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
-
-void *
-setmode(const char *p)
-{
-	char op, *ep;
-	BITCMD *set, *saveset, *endset;
-	sigset_t sigset, sigoset;
-	mode_t mask, perm, permXbits, who;
-	int equalopdone, setlen;
-	u_long perml;
-
-	if (!*p) {
-		errno = EINVAL;
-		return (NULL);
-	}
-
-	/*
-	 * Get a copy of the mask for the permissions that are mask relative.
-	 * Flip the bits, we want what's not set.  Since it's possible that
-	 * the caller is opening files inside a signal handler, protect them
-	 * as best we can.
-	 */
-	sigfillset(&sigset);
-	(void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
-	(void)umask(mask = umask(0));
-	mask = ~mask;
-	(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
-
-	setlen = SET_LEN + 2;
-	
-	if ((set = calloc((u_int)sizeof(BITCMD), setlen)) == NULL)
-		return (NULL);
-	saveset = set;
-	endset = set + (setlen - 2);
-
-	/*
-	 * If an absolute number, get it and return; disallow non-octal digits
-	 * or illegal bits.
-	 */
-	if (isdigit((unsigned char)*p)) {
-		perml = strtoul(p, &ep, 8);
-		/* The test on perml will also catch overflow. */
-		if (*ep != '\0' || (perml & ~(STANDARD_BITS|S_ISTXT))) {
-			free(saveset);
-			errno = ERANGE;
-			return (NULL);
-		}
-		perm = (mode_t)perml;
-		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
-		set->cmd = 0;
-		return (saveset);
-	}
-
-	/*
-	 * Build list of structures to set/clear/copy bits as described by
-	 * each clause of the symbolic mode.
-	 */
-	for (;;) {
-		/* First, find out which bits might be modified. */
-		for (who = 0;; ++p) {
-			switch (*p) {
-			case 'a':
-				who |= STANDARD_BITS;
-				break;
-			case 'u':
-				who |= S_ISUID|S_IRWXU;
-				break;
-			case 'g':
-				who |= S_ISGID|S_IRWXG;
-				break;
-			case 'o':
-				who |= S_IRWXO;
-				break;
-			default:
-				goto getop;
-			}
-		}
-
-getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
-			free(saveset);
-			errno = EINVAL;
-			return (NULL);
-		}
-		if (op == '=')
-			equalopdone = 0;
-
-		who &= ~S_ISTXT;
-		for (perm = 0, permXbits = 0;; ++p) {
-			switch (*p) {
-			case 'r':
-				perm |= S_IRUSR|S_IRGRP|S_IROTH;
-				break;
-			case 's':
-				/*
-				 * If specific bits where requested and
-				 * only "other" bits ignore set-id.
-				 */
-				if (who == 0 || (who & ~S_IRWXO))
-					perm |= S_ISUID|S_ISGID;
-				break;
-			case 't':
-				/*
-				 * If specific bits where requested and
-				 * only "other" bits ignore sticky.
-				 */
-				if (who == 0 || (who & ~S_IRWXO)) {
-					who |= S_ISTXT;
-					perm |= S_ISTXT;
-				}
-				break;
-			case 'w':
-				perm |= S_IWUSR|S_IWGRP|S_IWOTH;
-				break;
-			case 'X':
-				permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
-				break;
-			case 'x':
-				perm |= S_IXUSR|S_IXGRP|S_IXOTH;
-				break;
-			case 'u':
-			case 'g':
-			case 'o':
-				/*
-				 * When ever we hit 'u', 'g', or 'o', we have
-				 * to flush out any partial mode that we have,
-				 * and then do the copying of the mode bits.
-				 */
-				if (perm) {
-					ADDCMD(op, who, perm, mask);
-					perm = 0;
-				}
-				if (op == '=')
-					equalopdone = 1;
-				if (op == '+' && permXbits) {
-					ADDCMD('X', who, permXbits, mask);
-					permXbits = 0;
-				}
-				ADDCMD(*p, who, op, mask);
-				break;
-
-			default:
-				/*
-				 * Add any permissions that we haven't already
-				 * done.
-				 */
-				if (perm || (op == '=' && !equalopdone)) {
-					if (op == '=')
-						equalopdone = 1;
-					ADDCMD(op, who, perm, mask);
-					perm = 0;
-				}
-				if (permXbits) {
-					ADDCMD('X', who, permXbits, mask);
-					permXbits = 0;
-				}
-				goto apply;
-			}
-		}
-
-apply:		if (!*p)
-			break;
-		if (*p != ',')
-			goto getop;
-		++p;
-	}
-	set->cmd = 0;
-#ifdef SETMODE_DEBUG
-	(void)printf("Before compress_mode()\n");
-	dumpmode(saveset);
-#endif
-	compress_mode(saveset);
-#ifdef SETMODE_DEBUG
-	(void)printf("After compress_mode()\n");
-	dumpmode(saveset);
-#endif
-	return (saveset);
-}
-
-static BITCMD *
-addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
-{
-	switch (op) {
-	case '=':
-		set->cmd = '-';
-		set->bits = who ? who : STANDARD_BITS;
-		set++;
-
-		op = '+';
-		/* FALLTHROUGH */
-	case '+':
-	case '-':
-	case 'X':
-		set->cmd = op;
-		set->bits = (who ? who : mask) & oparg;
-		break;
-
-	case 'u':
-	case 'g':
-	case 'o':
-		set->cmd = op;
-		if (who) {
-			set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
-				    ((who & S_IRGRP) ? CMD2_GBITS : 0) |
-				    ((who & S_IROTH) ? CMD2_OBITS : 0);
-			set->bits = (mode_t)~0;
-		} else {
-			set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
-			set->bits = mask;
-		}
-	
-		if (oparg == '+')
-			set->cmd2 |= CMD2_SET;
-		else if (oparg == '-')
-			set->cmd2 |= CMD2_CLR;
-		else if (oparg == '=')
-			set->cmd2 |= CMD2_SET|CMD2_CLR;
-		break;
-	}
-	return (set + 1);
-}
-
-#ifdef SETMODE_DEBUG
-static void
-dumpmode(BITCMD *set)
-{
-	for (; set->cmd; ++set)
-		(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
-		    set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
-		    set->cmd2 & CMD2_CLR ? " CLR" : "",
-		    set->cmd2 & CMD2_SET ? " SET" : "",
-		    set->cmd2 & CMD2_UBITS ? " UBITS" : "",
-		    set->cmd2 & CMD2_GBITS ? " GBITS" : "",
-		    set->cmd2 & CMD2_OBITS ? " OBITS" : "");
-}
-#endif
-
-/*
- * Given an array of bitcmd structures, compress by compacting consecutive
- * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
- * 'g' and 'o' commands continue to be separate.  They could probably be
- * compacted, but it's not worth the effort.
- */
-static void
-compress_mode(BITCMD *set)
-{
-	BITCMD *nset;
-	int setbits, clrbits, Xbits, op;
-
-	for (nset = set;;) {
-		/* Copy over any 'u', 'g' and 'o' commands. */
-		while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
-			*set++ = *nset++;
-			if (!op)
-				return;
-		}
-
-		for (setbits = clrbits = Xbits = 0;; nset++) {
-			if ((op = nset->cmd) == '-') {
-				clrbits |= nset->bits;
-				setbits &= ~nset->bits;
-				Xbits &= ~nset->bits;
-			} else if (op == '+') {
-				setbits |= nset->bits;
-				clrbits &= ~nset->bits;
-				Xbits &= ~nset->bits;
-			} else if (op == 'X')
-				Xbits |= nset->bits & ~setbits;
-			else
-				break;
-		}
-		if (clrbits) {
-			set->cmd = '-';
-			set->cmd2 = 0;
-			set->bits = clrbits;
-			set++;
-		}
-		if (setbits) {
-			set->cmd = '+';
-			set->cmd2 = 0;
-			set->bits = setbits;
-			set++;
-		}
-		if (Xbits) {
-			set->cmd = 'X';
-			set->cmd2 = 0;
-			set->bits = Xbits;
-			set++;
-		}
-	}
-}
diff --git a/portable/netbsd/netbsd.h b/portable/netbsd/netbsd.h
@@ -1,24 +0,0 @@
-/*
- * NetBSD support.
- */
-
-/* Defines */
-#define setresgid(x, y, z)	setgid(x); setegid(x)
-#define setresuid(x, y, z)	setuid(x); seteuid(x)
-#define srand_deterministic(x)	srand(x)
-
-/* From OpenBSD sys/time.h */
-#define timespeccmp(tsp, usp, cmp)                                      \
-        (((tsp)->tv_sec == (usp)->tv_sec) ?                             \
-            ((tsp)->tv_nsec cmp (usp)->tv_nsec) :                       \
-            ((tsp)->tv_sec cmp (usp)->tv_sec))
-
-#define timespecsub(tsp, usp, vsp)                                      \
-        do {                                                            \
-                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \
-                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \
-                if ((vsp)->tv_nsec < 0) {                               \
-                        (vsp)->tv_sec--;                                \
-                        (vsp)->tv_nsec += 1000000000L;                  \
-                }                                                       \
-        } while (0)
diff --git a/prescue.h b/prescue.h
@@ -0,0 +1,8 @@
+#define NEED_REALLOCARRAY
+#define NEED_SETRESGID
+#define NEED_SETRESUID
+#define NEED_SRAND_DETERMINISTIC
+#define NEED_STRAVIS
+#define NEED_STROTONUM
+#define NEED_STRUNVIS
+#define NEED_SIGNAME
diff --git a/portable/common/reallocarray.c b/reallocarray.c
rename portable/common/reallocarray.c → reallocarray.c
@@ -15,6 +15,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef NEED_REALLOCARRAY
+
 #include <sys/types.h>
 #include <errno.h>
 #include <stdint.h>
@@ -36,3 +38,5 @@ reallocarray(void *optr, size_t nmemb, size_t size)
 	}
 	return realloc(optr, size * nmemb);
 }
+
+#endif /* NEED_REALLOCARRAY */
diff --git a/rescue.sh b/rescue.sh
@@ -7,110 +7,109 @@
 # Written by Brian Callahan <bcallah@openbsd.org>
 # Released into the Public Domain
 
-echo "cc -DEMACS -DVI -Iportable/common -o alloc.o -c alloc.c"
-cc -DEMACS -DVI -Iportable/common -o alloc.o -c alloc.c
+cp prescue.h pconfig.h
 
-echo "cc -DEMACS -DVI -Iportable/common -o c_ksh.o -c c_ksh.c"
-cc -DEMACS -DVI -Iportable/common -o c_ksh.o -c c_ksh.c
+echo cc -DEMACS -DVI -o alloc.o -c alloc.c
+cc -DEMACS -DVI -o alloc.o -c alloc.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o c_sh.o -c c_sh.c"
-cc -DEMACS -DVI -Iportable/common -o c_sh.o -c c_sh.c
+echo cc -DEMACS -DVI -o c_ksh.o -c c_ksh.c
+cc -DEMACS -DVI -o c_ksh.o -c c_ksh.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o c_test.o -c c_test.c"
-cc -DEMACS -DVI -Iportable/common -o c_test.o -c c_test.c
+echo cc -DEMACS -DVI -o c_sh.o -c c_sh.c
+cc -DEMACS -DVI -o c_sh.o -c c_sh.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o c_ulimit.o -c c_ulimit.c"
-cc -DEMACS -DVI -Iportable/common -o c_ulimit.o -c c_ulimit.c
+echo cc -DEMACS -DVI -o c_test.o -c c_test.c
+cc -DEMACS -DVI -o c_test.o -c c_test.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o edit.o -c edit.c"
-cc -DEMACS -DVI -Iportable/common -o edit.o -c edit.c
+echo cc -DEMACS -DVI -o c_ulimit.o -c c_ulimit.c
+cc -DEMACS -DVI -o c_ulimit.o -c c_ulimit.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o emacs.o -c emacs.c"
-cc -DEMACS -DVI -Iportable/common -o emacs.o -c emacs.c
+echo cc -DEMACS -DVI -o edit.o -c edit.c
+cc -DEMACS -DVI -o edit.o -c edit.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o eval.o -c eval.c"
-cc -DEMACS -DVI -Iportable/common -o eval.o -c eval.c
+echo cc -DEMACS -DVI -o emacs.o -c emacs.c
+cc -DEMACS -DVI -o emacs.o -c emacs.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o exec.o -c exec.c"
-cc -DEMACS -DVI -Iportable/common -o exec.o -c exec.c
+echo cc -DEMACS -DVI -o eval.o -c eval.c
+cc -DEMACS -DVI -o eval.o -c eval.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o expr.o -c expr.c"
-cc -DEMACS -DVI -Iportable/common -o expr.o -c expr.c
+echo cc -DEMACS -DVI -o exec.o -c exec.c
+cc -DEMACS -DVI -o exec.o -c exec.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o history.o -c history.c"
-cc -DEMACS -DVI -Iportable/common -o history.o -c history.c
+echo cc -DEMACS -DVI -o expr.o -c expr.c
+cc -DEMACS -DVI -o expr.o -c expr.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o io.o -c io.c"
-cc -DEMACS -DVI -Iportable/common -o io.o -c io.c
+echo cc -DEMACS -DVI -o history.o -c history.c
+cc -DEMACS -DVI -o history.o -c history.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o jobs.o -c jobs.c"
-cc -DEMACS -DVI -Iportable/common -o jobs.o -c jobs.c
+echo cc -DEMACS -DVI -o io.o -c io.c
+cc -DEMACS -DVI -o io.o -c io.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o lex.o -c lex.c"
-cc -DEMACS -DVI -Iportable/common -o lex.o -c lex.c
+echo cc -DEMACS -DVI -o jobs.o -c jobs.c
+cc -DEMACS -DVI -o jobs.o -c jobs.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o mail.o -c mail.c"
-cc -DEMACS -DVI -Iportable/common -o mail.o -c mail.c
+echo cc -DEMACS -DVI -o lex.o -c lex.c
+cc -DEMACS -DVI -o lex.o -c lex.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o main.o -c main.c"
-cc -DEMACS -DVI -Iportable/common -o main.o -c main.c
+echo cc -DEMACS -DVI -o mail.o -c mail.c
+cc -DEMACS -DVI -o mail.o -c mail.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o misc.o -c misc.c"
-cc -DEMACS -DVI -Iportable/common -o misc.o -c misc.c
+echo cc -DEMACS -DVI -o main.o -c main.c
+cc -DEMACS -DVI -o main.o -c main.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o path.o -c path.c"
-cc -DEMACS -DVI -Iportable/common -o path.o -c path.c
+echo cc -DEMACS -DVI -o misc.o -c misc.c
+cc -DEMACS -DVI -o misc.o -c misc.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o shf.o -c shf.c"
-cc -DEMACS -DVI -Iportable/common -o shf.o -c shf.c
+echo cc -DEMACS -DVI -o path.o -c path.c
+cc -DEMACS -DVI -o path.o -c path.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o syn.o -c syn.c"
-cc -DEMACS -DVI -Iportable/common -o syn.o -c syn.c
+echo cc -DEMACS -DVI -o shf.o -c shf.c
+cc -DEMACS -DVI -o shf.o -c shf.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o table.o -c table.c"
-cc -DEMACS -DVI -Iportable/common -o table.o -c table.c
+echo cc -DEMACS -DVI -o syn.o -c syn.c
+cc -DEMACS -DVI -o syn.o -c syn.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o trap.o -c trap.c"
-cc -DEMACS -DVI -Iportable/common -o trap.o -c trap.c
+echo cc -DEMACS -DVI -o table.o -c table.c
+cc -DEMACS -DVI -o table.o -c table.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o tree.o -c tree.c"
-cc -DEMACS -DVI -Iportable/common -o tree.o -c tree.c
+echo cc -DEMACS -DVI -o trap.o -c trap.c
+cc -DEMACS -DVI -o trap.o -c trap.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o tty.o -c tty.c"
-cc -DEMACS -DVI -Iportable/common -o tty.o -c tty.c
+echo cc -DEMACS -DVI -o tree.o -c tree.c
+cc -DEMACS -DVI -o tree.o -c tree.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o var.o -c var.c"
-cc -DEMACS -DVI -Iportable/common -o var.o -c var.c
+echo cc -DEMACS -DVI -o tty.o -c tty.c
+cc -DEMACS -DVI -o tty.o -c tty.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o version.o -c version.c"
-cc -DEMACS -DVI -Iportable/common -o version.o -c version.c
+echo cc -DEMACS -DVI -o var.o -c var.c
+cc -DEMACS -DVI -o var.o -c var.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o vi.o -c vi.c"
-cc -DEMACS -DVI -Iportable/common -o vi.o -c vi.c
+echo cc -DEMACS -DVI -o version.o -c version.c
+cc -DEMACS -DVI -o version.o -c version.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o reallocarray.o -c portable/common/reallocarray.c"
-cc -DEMACS -DVI -Iportable/common -o reallocarray.o -c portable/common/reallocarray.c
+echo cc -DEMACS -DVI -o vi.o -c vi.c
+cc -DEMACS -DVI -o vi.o -c vi.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o strtonum.o -c portable/common/strtonum.c"
-cc -DEMACS -DVI -Iportable/common -o strtonum.o -c portable/common/strtonum.c
+echo cc -DEMACS -DVI -o reallocarray.o -c reallocarray.c
+cc -DEMACS -DVI -o reallocarray.o -c reallocarray.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o setmode.o -c portable/linux/setmode.c"
-cc -DEMACS -DVI -Iportable/common -o setmode.o -c portable/linux/setmode.c
+echo cc -DEMACS -DVI -o strtonum.o -c strtonum.c
+cc -DEMACS -DVI -o strtonum.o -c strtonum.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o signame.o -c portable/linux/signame.c"
-cc -DEMACS -DVI -Iportable/common -o signame.o -c portable/linux/signame.c
+echo cc -DEMACS -DVI -o signame.o -c signame.c
+cc -DEMACS -DVI -o signame.o -c signame.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o strlcat.o -c portable/linux/strlcat.c"
-cc -DEMACS -DVI -Iportable/common -o strlcat.o -c portable/linux/strlcat.c
+echo cc -DEMACS -DVI -o strlcat.o -c strlcat.c
+cc -DEMACS -DVI -o strlcat.o -c strlcat.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o strlcpy.o -c portable/linux/strlcpy.c"
-cc -DEMACS -DVI -Iportable/common -o strlcpy.o -c portable/linux/strlcpy.c
+echo cc -DEMACS -DVI -o strlcpy.o -c strlcpy.c
+cc -DEMACS -DVI -o strlcpy.o -c strlcpy.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o unvis.o -c portable/linux/unvis.c"
-cc -DEMACS -DVI -Iportable/common -o unvis.o -c portable/linux/unvis.c
+echo cc -DEMACS -DVI -o unvis.o -c unvis.c
+cc -DEMACS -DVI -o unvis.o -c unvis.c
 
-echo "cc -DEMACS -DVI -Iportable/common -o vis.o -c portable/linux/vis.c"
-cc -DEMACS -DVI -Iportable/common -o vis.o -c portable/linux/vis.c
+echo cc -DEMACS -DVI -o vis.o -c vis.c
+cc -DEMACS -DVI -o vis.o -c vis.c
 
-echo "cc -o oksh 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 path.o shf.o syn.o table.o trap.o tree.o tty.o var.o version.o vi.o reallocarray.o strtonum.o setmode.o signame.o strlcat.o strlcpy.o unvis.o vis.o -lc"
-cc -o oksh 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 path.o shf.o syn.o table.o trap.o tree.o tty.o var.o version.o vi.o reallocarray.o strtonum.o setmode.o signame.o strlcat.o strlcpy.o unvis.o vis.o -lc
+echo cc -o oksh 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 path.o shf.o syn.o table.o trap.o tree.o tty.o var.o version.o vi.o reallocarray.o strtonum.o signame.o strlcat.o strlcpy.o unvis.o vis.o -lc
+cc -o oksh 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 path.o shf.o syn.o table.o trap.o tree.o tty.o var.o version.o vi.o reallocarray.o strtonum.o signame.o strlcat.o strlcpy.o unvis.o vis.o -lc
diff --git a/sh.h b/sh.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: sh.h,v 1.66 2017/12/27 13:02:57 millert Exp $	*/
+/*	$OpenBSD: sh.h,v 1.68 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * Public Domain Bourne/Korn shell
@@ -13,25 +13,12 @@
 #include <limits.h>
 #include <setjmp.h>
 #include <stdarg.h>
+#include <stddef.h>
 #include <signal.h>
 #include <stdbool.h>
 
 /* end of common headers */
 
-/* oksh portable: system-specific headers */
-#if defined(__linux__) || defined(__CYGWIN__)
-#include "portable/linux/linux.h"
-#endif
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-#include "portable/freebsd/freebsd.h"
-#endif
-#ifdef __NetBSD__
-#include "portable/netbsd/netbsd.h"
-#endif
-#ifdef __APPLE__
-#include "portable/darwin/darwin.h"
-#endif
-
 #define	NELEM(a) (sizeof(a) / sizeof((a)[0]))
 #define	BIT(i)	(1<<(i))	/* define bit in flag */
 
@@ -169,9 +156,7 @@ enum sh_flag {
 	FNOGLOB,	/* -f: don't do file globbing */
 	FNOHUP,		/* -H: don't kill running jobs when login shell exits */
 	FNOLOG,		/* don't save functions in history (ignored) */
-#ifdef	JOBS
 	FNOTIFY,	/* -b: asynchronous job completion notification */
-#endif
 	FNOUNSET,	/* -u: using an unset var is an error */
 	FPHYSICAL,	/* -o physical: don't do logical cd's/pwd's */
 	FPOSIX,		/* -o posix: be posixly correct */
diff --git a/portable/linux/signame.c b/signame.c
rename portable/linux/signame.c → signame.c
@@ -28,11 +28,11 @@
  * SUCH DAMAGE.
  */
 
+#ifdef NEED_SIGNAME
+
 #include <signal.h>
 #include <unistd.h>
 
-#include "linux.h"
-
 const char *const sys_signame[NSIG] = {
 	"Signal 0",
 	"HUP",		/* SIGHUP */
@@ -68,3 +68,5 @@ const char *const sys_signame[NSIG] = {
 	"USR2",		/* SIGUSR2 */
 	"THR",		/* SIGTHR */
 };
+
+#endif /* NEED_SIGNAME */
diff --git a/portable/linux/strlcat.c b/strlcat.c
rename portable/linux/strlcat.c → strlcat.c
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef NEED_STRLCAT
+
 #include <sys/types.h>
 #include <string.h>
 
@@ -53,3 +55,5 @@ strlcat(char *dst, const char *src, size_t dsize)
 
 	return(dlen + (src - osrc));	/* count does not include NUL */
 }
+
+#endif /* NEED_STRLCAT */
diff --git a/portable/linux/strlcpy.c b/strlcpy.c
rename portable/linux/strlcpy.c → strlcpy.c
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef NEED_STRLCPY
+
 #include <sys/types.h>
 #include <string.h>
 
@@ -48,3 +50,5 @@ strlcpy(char *dst, const char *src, size_t dsize)
 
 	return(src - osrc - 1);	/* count does not include NUL */
 }
+
+#endif /* NEED_STRLCPY */
diff --git a/portable/common/strtonum.c b/strtonum.c
rename portable/common/strtonum.c → strtonum.c
@@ -17,6 +17,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef NEED_STRTONUM
+
 #include <errno.h>
 #include <limits.h>
 #include <stdlib.h>
@@ -63,3 +65,5 @@ strtonum(const char *numstr, long long minval, long long maxval,
 
 	return (ll);
 }
+
+#endif /* NEED_STRTONUM */
diff --git a/tree.c b/tree.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: tree.c,v 1.28 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: tree.c,v 1.30 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  * command tree climbing
diff --git a/portable/linux/unvis.c b/unvis.c
rename portable/linux/unvis.c → unvis.c
@@ -28,8 +28,11 @@
  * SUCH DAMAGE.
  */
 
+#ifdef NEED_STRUNVIS
+
 #include <sys/types.h>
 #include <ctype.h>
+
 #include "vis.h"
 
 /*
@@ -48,8 +51,8 @@
 /*
  * unvis - decode characters previously encoded by vis
  */
-int
-unvis(char *cp, char c, int *astate, int flag)
+static int
+eunvis(char *cp, char c, int *astate, int flag)
 {
 
 	if (flag & UNVIS_END) {
@@ -221,7 +224,7 @@ strunvis(char *dst, const char *src)
 
 	while ((c = *src++)) {
 	again:
-		switch (unvis(dst, c, &state, 0)) {
+		switch (eunvis(dst, c, &state, 0)) {
 		case UNVIS_VALID:
 			dst++;
 			break;
@@ -236,50 +239,10 @@ strunvis(char *dst, const char *src)
 			return (-1);
 		}
 	}
-	if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
+	if (eunvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
 		dst++;
 	*dst = '\0';
 	return (dst - start);
 }
 
-ssize_t
-strnunvis(char *dst, const char *src, size_t sz)
-{
-	char c, p;
-	char *start = dst, *end = dst + sz - 1;
-	int state = 0;
-
-	if (sz > 0)
-		*end = '\0';
-	while ((c = *src++)) {
-	again:
-		switch (unvis(&p, c, &state, 0)) {
-		case UNVIS_VALID:
-			if (dst < end)
-				*dst = p;
-			dst++;
-			break;
-		case UNVIS_VALIDPUSH:
-			if (dst < end)
-				*dst = p;
-			dst++;
-			goto again;
-		case 0:
-		case UNVIS_NOCHAR:
-			break;
-		default:
-			if (dst <= end)
-				*dst = '\0';
-			return (-1);
-		}
-	}
-	if (unvis(&p, c, &state, UNVIS_END) == UNVIS_VALID) {
-		if (dst < end)
-			*dst = p;
-		dst++;
-	}
-	if (dst <= end)
-		*dst = '\0';
-	return (dst - start);
-}
-
+#endif /* NEED_STRUNVIS */
diff --git a/var.c b/var.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: var.c,v 1.61 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: var.c,v 1.63 2018/01/06 16:28:58 millert Exp $	*/
 
 #include <sys/stat.h>
 
@@ -997,7 +997,7 @@ setspec(struct tbl *vp)
 		break;
 	case V_HISTSIZE:
 		vp->flag &= ~SPECIAL;
-		sethistsize(intval(vp));
+		sethistsize((int) intval(vp));
 		vp->flag |= SPECIAL;
 		break;
 	case V_HISTFILE:
diff --git a/vi.c b/vi.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vi.c,v 1.51 2018/01/01 19:45:56 millert Exp $	*/
+/*	$OpenBSD: vi.c,v 1.53 2018/01/06 16:28:58 millert Exp $	*/
 
 /*
  *	vi command editing
diff --git a/portable/linux/vis.c b/vis.c
rename portable/linux/vis.c → vis.c
@@ -28,13 +28,17 @@
  * SUCH DAMAGE.
  */
 
+/* Mac OS X and FreeBSD are missing stravis */
+
+#ifdef NEED_STRAVIS
+
 #include <sys/types.h>
 #include <errno.h>
 #include <ctype.h>
 #include <limits.h>
 #include <string.h>
 #include <stdlib.h>
-#include "linux.h"
+
 #include "vis.h"
 
 #define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
@@ -53,8 +57,8 @@
 /*
  * vis - visually encode characters
  */
-char *
-vis(char *dst, int c, int flag, int nextc)
+static char *
+evis(char *dst, int c, int flag, int nextc)
 {
 	if (isvisible(c, flag)) {
 		if ((c == '"' && (flag & VIS_DQ) != 0) ||
@@ -151,61 +155,18 @@ done:
  *	Strvisx encodes exactly len bytes from src into dst.
  *	This is useful for encoding a block of data.
  */
-int
-strvis(char *dst, const char *src, int flag)
+static int
+estrvis(char *dst, const char *src, int flag)
 {
 	char c;
 	char *start;
 
 	for (start = dst; (c = *src);)
-		dst = vis(dst, c, flag, *++src);
+		dst = evis(dst, c, flag, *++src);
 	*dst = '\0';
 	return (dst - start);
 }
 
-int
-strnvis(char *dst, const char *src, size_t siz, int flag)
-{
-	char *start, *end;
-	char tbuf[5];
-	int c, i;
-
-	i = 0;
-	for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
-		if (isvisible(c, flag)) {
-			if ((c == '"' && (flag & VIS_DQ) != 0) ||
-			    (c == '\\' && (flag & VIS_NOSLASH) == 0)) {
-				/* need space for the extra '\\' */
-				if (dst + 1 >= end) {
-					i = 2;
-					break;
-				}
-				*dst++ = '\\';
-			}
-			i = 1;
-			*dst++ = c;
-			src++;
-		} else {
-			i = vis(tbuf, c, flag, *++src) - tbuf;
-			if (dst + i <= end) {
-				memcpy(dst, tbuf, i);
-				dst += i;
-			} else {
-				src--;
-				break;
-			}
-		}
-	}
-	if (siz > 0)
-		*dst = '\0';
-	if (dst + i > end) {
-		/* adjust return value for truncation */
-		while ((c = *src))
-			dst += vis(tbuf, c, flag, *++src) - tbuf;
-	}
-	return (dst - start);
-}
-
 int
 stravis(char **outp, const char *src, int flag)
 {
@@ -215,7 +176,7 @@ stravis(char **outp, const char *src, int flag)
 	buf = reallocarray(NULL, 4, strlen(src) + 1);
 	if (buf == NULL)
 		return -1;
-	len = strvis(buf, src, flag);
+	len = estrvis(buf, src, flag);
 	serrno = errno;
 	*outp = realloc(buf, len + 1);
 	if (*outp == NULL) {
@@ -225,18 +186,4 @@ stravis(char **outp, const char *src, int flag)
 	return (len);
 }
 
-int
-strvisx(char *dst, const char *src, size_t len, int flag)
-{
-	char c;
-	char *start;
-
-	for (start = dst; len > 1; len--) {
-		c = *src;
-		dst = vis(dst, c, flag, *++src);
-	}
-	if (len)
-		dst = vis(dst, *src, flag, '\0');
-	*dst = '\0';
-	return (dst - start);
-}
+#endif /* NEED_STRAVIS */
diff --git a/portable/linux/vis.h b/vis.h
rename portable/linux/vis.h → vis.h
@@ -75,7 +75,6 @@
 
 #include <sys/cdefs.h>
 
-__BEGIN_DECLS
 char	*vis(char *, int, int, int);
 int	strvis(char *, const char *, int);
 int	stravis(char **, const char *, int);
@@ -85,6 +84,4 @@ int	strunvis(char *, const char *);
 int	unvis(char *, char, int *, int);
 ssize_t strnunvis(char *, const char *, size_t);
 
-__END_DECLS
-
 #endif /* !_VIS_H_ */