loksh-noxz

[fork] a Linux port of OpenBSD's ksh
git clone https://noxz.tech/git/loksh-noxz.git
Log | Files | README

commit: fccb6733b45f73f7006f2870f1789717463ff3d7
parent: f1e00bfda58adf6dadbce7a8195090e89162762c
author: Chris Noxz <chris@noxz.tech>
date:   Tue, 9 Mar 2021 20:24:15 +0100
Update to use dimkr's lolibc together with meson/ninja
M.gitignore3+-
A.gitmodules3+
ADockerfile3+
DMakefile42--
MREADME.md19+-
Mc_sh.c1-
Mc_ulimit.c1-
Dcharclass.h29--
Mci.sh22+-
Medit.c1-
Mhistory.c7+-
Mio.c2+-
Mjobs.c5-
Mlex.h2-
Mmain.c18+-
Ameson.build32++
Mmisc.c7+-
Dreallocarray.c38--
Msh.h2-
Dstdlib.h45--
Dstring.h45--
Dstrlcat.c55--
Dstrlcpy.c50--
Dstrtonum.c65---
Asubprojects/lolibc1+
Dsys/queue.h534--------------------
Dsys/time.h79---
Mtable.h2-
Mtrap.c51+-
Dunvis.c285-----------
Mvar.c2+-
Mvi.c1+
Dvis.c241---------
Dvis.h88----
34 files changed, 110 insertions(+), 1671 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,2 +1 @@
-ksh
-*.o
+build
diff --git a/.gitmodules b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "subprojects/lolibc"]
+	path = subprojects/lolibc
+	url = https://github.com/dimkr/lolibc
diff --git a/Dockerfile b/Dockerfile
@@ -0,0 +1,3 @@
+FROM dimkr/c-dev:clang
+
+RUN apt-get -y --no-install-recommends install pkg-config libncurses5-dev
diff --git a/Makefile b/Makefile
@@ -1,42 +0,0 @@
-CC ?= cc
-CFLAGS ?= -O2
-override CFLAGS += -isystem . -D_GNU_SOURCE -DEMACS -DVI -std=gnu99 -Wall -Wno-format-security -Wno-pointer-sign
-LDFLAGS ?=
-DESTDIR ?= /
-PREFIX ?= /usr
-BIN_DIR ?= $(PREFIX)/bin
-BIN_NAME ?= ksh
-MAN_DIR ?= $(PREFIX)/share/man
-DOC_DIR ?= $(PREFIX)/share/doc/loksh
-
-NCURSES_CFLAGS = $(shell pkg-config --cflags ncursesw)
-NCURSES_LDFLAGS = $(shell pkg-config --libs ncursesw)
-
-
-OBJECTS = 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 \
-          vis.o unvis.o strlcpy.o strlcat.o reallocarray.o strtonum.o
-HEADERS = c_test.h charclass.h config.h edit.h expand.h ksh_limval.h lex.h \
-          proto.h sh.h shf.h table.h tree.h tty.h
-
-all: ksh
-
-%.o: %.c $(HEADERS)
-	$(CC) -c -o $@ $< $(CFLAGS) $(NCURSES_CFLAGS)
-
-ksh: $(OBJECTS)
-	$(CC) -o $@ $^ $(LDFLAGS) $(NCURSES_LDFLAGS)
-
-clean:
-	rm -f $(BIN_NAME) *.o
-
-install: all
-	install -v -D -m 755 ksh $(DESTDIR)/$(BIN_DIR)/$(BIN_NAME)
-	install -v -D -m 644 ksh.1 $(DESTDIR)/$(MAN_DIR)/man1/$(BIN_NAME).1
-	install -v -m 644 sh.1 $(DESTDIR)/$(MAN_DIR)/man1/sh.1
-	install -v -D -m 644 README.md $(DESTDIR)/$(DOC_DIR)/README.md
-	install -v -m 644 README $(DESTDIR)/$(DOC_DIR)/README
-	install -v -m 644 CONTRIBUTORS $(DESTDIR)/$(DOC_DIR)/CONTRIBUTORS
-	install -v -m 644 PROJECTS $(DESTDIR)/$(DOC_DIR)/PROJETCS
-	install -v -m 644 LEGAL $(DESTDIR)/$(DOC_DIR)/LEGAL
diff --git a/README.md b/README.md
@@ -6,13 +6,28 @@
 |_|\___/|_|\_\___/_| |_|
 ```
 
-[![Build Status](https://travis-ci.org/dimkr/loksh.svg?branch=master)](https://travis-ci.org/dimkr/loksh)
+[![Build Status](https://github.com/dimkr/loksh/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/dimkr/loksh/actions)
 
 ## Overview
 
 loksh is a [Linux](https://www.kernel.org/) port of [OpenBSD](http://www.openbsd.org/)'s *ksh*.
 
-Unlike other ports of *ksh*, loksh targets only one platform, follows upstream closely and keeps changes to a minimum. loksh does not add any extra features; this reduces the risk of introducing security vulnerabilities and makes loksh a good fit for resource-constrained systems.
+Unlike other ports of *ksh*, loksh targets only one platform, follows upstream closely and [keeps changes to a minimum](https://github.com/dimkr/loksh/compare/upstream%2Fmaster...master). loksh does not add any extra features; this reduces the risk of introducing security vulnerabilities and makes loksh a good fit for resource-constrained systems.
+
+## Installation
+
+loksh is included in many distributions:
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/loksh.svg?minversion=6.7.5&header=)](https://repology.org/project/loksh/versions)
+
+For example, under [Alpine Linux](https://alpinelinux.org/), loksh can be installed using `apk add loksh`.
+
+Alternatively, to build and install loksh from source:
+
+```bash
+meson --prefix=/usr build
+ninja -C build install
+```
 
 ## Legal Information
 
diff --git a/c_sh.c b/c_sh.c
@@ -4,7 +4,6 @@
  * built-in Bourne commands
  */
 
-#include <sys/types.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/time.h>
diff --git a/c_ulimit.c b/c_ulimit.c
@@ -18,7 +18,6 @@
 	that was originally under case SYSULIMIT in source file "xec.c".
 */
 
-#include <sys/types.h>
 #include <sys/resource.h>
 
 #include <ctype.h>
diff --git a/charclass.h b/charclass.h
@@ -1,29 +0,0 @@
-/*
- * Public domain, 2008, Todd C. Miller <millert@openbsd.org>
- *
- * $OpenBSD: charclass.h,v 1.2 2019/01/25 00:19:25 millert Exp $
- */
-
-/*
- * POSIX character class support for fnmatch() and glob().
- */
-static struct cclass {
-	const char *name;
-	int (*isctype)(int);
-} cclasses[] = {
-	{ "alnum",	isalnum },
-	{ "alpha",	isalpha },
-	{ "blank",	isblank },
-	{ "cntrl",	iscntrl },
-	{ "digit",	isdigit },
-	{ "graph",	isgraph },
-	{ "lower",	islower },
-	{ "print",	isprint },
-	{ "punct",	ispunct },
-	{ "space",	isspace },
-	{ "upper",	isupper },
-	{ "xdigit",	isxdigit },
-	{ NULL,		NULL }
-};
-
-#define NCCLASSES	(sizeof(cclasses) / sizeof(cclasses[0]) - 1)
diff --git a/ci.sh b/ci.sh
@@ -1,16 +1,24 @@
 #!/bin/sh -xe
 
-jobs=`nproc`
-make -j$jobs
-make DESTDIR=dst install
+meson --buildtype=release --prefix=/usr build
+DESTDIR=../dst ninja -C build install
+./dst/usr/bin/ksh -c "kill -l"
+[ "`echo 'kill -l 9' | ./dst/usr/bin/ksh`" != KILL ] && exit 1
+[ -n "`./dst/usr/bin/ksh -c 'echo &' 2>&1 | grep 'internal error'`" ] && exit 1
 [ "`./dst/usr/bin/ksh -c 'echo $((1337 * 2))'`" -ne 2674 ] && exit 1
 [ "`./dst/usr/bin/ksh -c 'seq 1337 | sort -rn | head -n 1'`" -ne 1337 ] && exit 1
-make clean
-CC=clang make -j$jobs
+CC=clang meson --buildtype=release build-clang
+ninja -C build-clang
 
 if [ "`readlink /proc/$$/exe`" != /tmp/ksh ]
 then
-	cp -f ksh /tmp/
-	make clean
+	cp -f dst/usr/bin/ksh /tmp/
+	rm -rf build build-clang dst
 	exec /tmp/ksh -xe $0
 fi
+
+for i in arm-any32-linux-musleabi mips-any32-linux-musl
+do
+	meson --buildtype=release --cross-file=$i build-$i
+	ninja -C build-$i
+done
diff --git a/edit.c b/edit.c
@@ -9,7 +9,6 @@
 
 #include <sys/ioctl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 
 #include <ctype.h>
 #include <errno.h>
diff --git a/history.c b/history.c
@@ -12,11 +12,7 @@
  *		things.
  */
 
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/file.h>
 
 #include <errno.h>
 #include <fcntl.h>
@@ -25,7 +21,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <vis.h>
-#include <inttypes.h>
 
 #include "sh.h"
 
@@ -729,7 +724,7 @@ history_open(void)
 	struct stat	sb;
 	int		fd, fddup;
 
-	if ((fd = open(hname, O_RDWR | O_CREAT, 0600)) == -1)
+	if ((fd = open(hname, O_RDWR | O_CREAT | O_EXLOCK, 0600)) == -1)
 		return NULL;
 	if (fstat(fd, &sb) == -1 || sb.st_uid != getuid()) {
 		close(fd);
diff --git a/io.c b/io.c
@@ -109,7 +109,7 @@ internal_warningf(const char *fmt, ...)
 }
 
 /* Warn and unwind when something that shouldn't happen does */
-__attribute__((__noreturn__)) void
+__dead void
 internal_errorf(const char *fmt, ...)
 {
 	va_list va;
diff --git a/jobs.c b/jobs.c
@@ -15,7 +15,6 @@
  *
  */
 
-#include <sys/types.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -150,11 +149,7 @@ static int		kill_job(Job *, int);
 void
 j_init(int mflagset)
 {
-#ifdef CHILD_MAX
 	child_max = CHILD_MAX; /* so syscon() isn't always being called */
-#else
-	child_max = sysconf(_SC_CHILD_MAX);
-#endif
 
 	sigemptyset(&sm_default);
 	sigprocmask(SIG_SETMASK, &sm_default, NULL);
diff --git a/lex.h b/lex.h
@@ -6,8 +6,6 @@
 
 /* $From: lex.h,v 1.4 1994/05/31 13:34:34 michael Exp $ */
 
-#include <inttypes.h>
-
 #define	IDENT	64
 
 typedef struct source Source;
diff --git a/main.c b/main.c
@@ -17,10 +17,6 @@
 
 #include "sh.h"
 
-#ifndef _PW_NAME_LEN
-#	define _PW_NAME_LEN 32 /* see the useradd(8) man page */
-#endif
-
 extern char **environ;
 
 /*
@@ -150,6 +146,20 @@ main(int argc, char *argv[])
 
 	kshname = argv[0];
 
+	if (issetugid()) { /* could later drop privileges */
+		if (pledge("stdio rpath wpath cpath fattr flock getpw proc "
+		    "exec tty id", NULL) == -1) {
+			perror("pledge");
+			exit(1);
+		}
+	} else {
+		if (pledge("stdio rpath wpath cpath fattr flock getpw proc "
+		    "exec tty", NULL) == -1) {
+			perror("pledge");
+			exit(1);
+		}
+	}
+
 	ainit(&aperm);		/* initialize permanent Area */
 
 	/* set up base environment */
diff --git a/meson.build b/meson.build
@@ -0,0 +1,32 @@
+project('loksh', 'c', version: '6.8')
+
+lolibc = subproject('lolibc')
+
+c_args = ['-D_GNU_SOURCE', '-DEMACS', '-DVI', '-Wno-format-security', '-Wno-pointer-sign']
+deps = []
+
+ncurses = dependency('ncurses', required: false)
+if ncurses.found()
+	deps += [ncurses]
+else
+	c_args += ['-DSMALL']
+endif
+
+ksh = executable('ksh',
+                 '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',
+                 c_args: c_args + lolibc.get_variable('lolibc_c_args'),
+                 include_directories: lolibc.get_variable('lolibc_includes'),
+                 dependencies: deps,
+                 link_with: lolibc.get_variable('liblolibc'),
+                 install: true)
+
+install_man('ksh.1', 'sh.1')
+
+install_data('README.md',
+             'README',
+             'CONTRIBUTORS',
+             'PROJECTS',
+             'LEGAL',
+             install_dir: join_paths(get_option('datadir'), 'doc', 'loksh'))
diff --git a/misc.c b/misc.c
@@ -11,8 +11,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <grp.h>
-#include <sys/auxv.h>
 
 #include "sh.h"
 #include "charclass.h"
@@ -294,7 +292,7 @@ change_flag(enum sh_flag f,
 		}
 	} else
 	/* Turning off -p? */
-	if (f == FPRIVILEGED && oldval && !newval && getauxval(AT_SECURE) &&
+	if (f == FPRIVILEGED && oldval && !newval && issetugid() &&
 	    !dropped_privileges) {
 		gid_t gid = getgid();
 
@@ -302,6 +300,9 @@ change_flag(enum sh_flag f,
 		setgroups(1, &gid);
 		setresuid(ksheuid, ksheuid, ksheuid);
 
+		if (pledge("stdio rpath wpath cpath fattr flock getpw proc "
+		    "exec tty", NULL) == -1)
+			bi_errorf("pledge fail");
 		dropped_privileges = 1;
 	} else if (f == FPOSIX && newval) {
 		Flag(FBRACEEXPAND) = 0;
diff --git a/reallocarray.c b/reallocarray.c
@@ -1,38 +0,0 @@
-/*	$OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $	*/
-/*
- * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-/*
- * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
- * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
- */
-#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
-
-void *
-reallocarray(void *optr, size_t nmemb, size_t size)
-{
-	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
-	    nmemb > 0 && SIZE_MAX / nmemb < size) {
-		errno = ENOMEM;
-		return NULL;
-	}
-	return realloc(optr, size * nmemb);
-}
diff --git a/sh.h b/sh.h
@@ -15,9 +15,7 @@
 #include <stdarg.h>
 #include <stddef.h>
 #include <signal.h>
-#include <time.h>
 #include <stdbool.h>
-#include <fcntl.h>
 
 /* end of common headers */
 
diff --git a/stdlib.h b/stdlib.h
@@ -1,45 +0,0 @@
-#ifndef _COMPAT_STDLIB_H_
-#define _COMPAT_STDLIB_H_
-
-#include_next <stdlib.h>
-
-/*	$OpenBSD: stdlib.h,v 1.76 2019/05/10 15:03:24 otto Exp $	*/
-/*	$NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $	*/
-
-/*-
- * Copyright (c) 1990 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.
- *
- *	@(#)stdlib.h	5.13 (Berkeley) 6/4/91
- */
-
-void	*reallocarray(void *, size_t, size_t);
-
-long long
-	 strtonum(const char *, long long, long long, const char **);
-
-#endif
diff --git a/string.h b/string.h
@@ -1,45 +0,0 @@
-#ifndef _COMPAT_STRING_H_
-#define _COMPAT_STRING_H_
-
-#include_next <string.h>
-
-/*	$OpenBSD: string.h,v 1.32 2017/09/05 03:16:13 schwarze Exp $	*/
-/*	$NetBSD: string.h,v 1.6 1994/10/26 00:56:30 cgd Exp $	*/
-
-/*-
- * Copyright (c) 1990 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.
- *
- *	@(#)string.h	5.10 (Berkeley) 3/9/91
- */
-
-size_t	 strlcat(char *, const char *, size_t)
-		__attribute__ ((__bounded__(__string__,1,3)));
-size_t	 strlcpy(char *, const char *, size_t)
-		__attribute__ ((__bounded__(__string__,1,3)));
-
-#endif
diff --git a/strlcat.c b/strlcat.c
@@ -1,55 +0,0 @@
-/*	$OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $	*/
-
-/*
- * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Appends src to string dst of size dsize (unlike strncat, dsize is the
- * full size of dst, not space left).  At most dsize-1 characters
- * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
- * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
- * If retval >= dsize, truncation occurred.
- */
-size_t
-strlcat(char *dst, const char *src, size_t dsize)
-{
-	const char *odst = dst;
-	const char *osrc = src;
-	size_t n = dsize;
-	size_t dlen;
-
-	/* Find the end of dst and adjust bytes left but don't go past end. */
-	while (n-- != 0 && *dst != '\0')
-		dst++;
-	dlen = dst - odst;
-	n = dsize - dlen;
-
-	if (n-- == 0)
-		return(dlen + strlen(src));
-	while (*src != '\0') {
-		if (n != 0) {
-			*dst++ = *src;
-			n--;
-		}
-		src++;
-	}
-	*dst = '\0';
-
-	return(dlen + (src - osrc));	/* count does not include NUL */
-}
diff --git a/strlcpy.c b/strlcpy.c
@@ -1,50 +0,0 @@
-/*	$OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $	*/
-
-/*
- * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Copy string src to buffer dst of size dsize.  At most dsize-1
- * chars will be copied.  Always NUL terminates (unless dsize == 0).
- * Returns strlen(src); if retval >= dsize, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t dsize)
-{
-	const char *osrc = src;
-	size_t nleft = dsize;
-
-	/* Copy as many bytes as will fit. */
-	if (nleft != 0) {
-		while (--nleft != 0) {
-			if ((*dst++ = *src++) == '\0')
-				break;
-		}
-	}
-
-	/* Not enough room in dst, add NUL and traverse rest of src. */
-	if (nleft == 0) {
-		if (dsize != 0)
-			*dst = '\0';		/* NUL-terminate dst */
-		while (*src++)
-			;
-	}
-
-	return(src - osrc - 1);	/* count does not include NUL */
-}
diff --git a/strtonum.c b/strtonum.c
@@ -1,65 +0,0 @@
-/*	$OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $	*/
-
-/*
- * Copyright (c) 2004 Ted Unangst and Todd Miller
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-
-#define	INVALID		1
-#define	TOOSMALL	2
-#define	TOOLARGE	3
-
-long long
-strtonum(const char *numstr, long long minval, long long maxval,
-    const char **errstrp)
-{
-	long long ll = 0;
-	int error = 0;
-	char *ep;
-	struct errval {
-		const char *errstr;
-		int err;
-	} ev[4] = {
-		{ NULL,		0 },
-		{ "invalid",	EINVAL },
-		{ "too small",	ERANGE },
-		{ "too large",	ERANGE },
-	};
-
-	ev[0].err = errno;
-	errno = 0;
-	if (minval > maxval) {
-		error = INVALID;
-	} else {
-		ll = strtoll(numstr, &ep, 10);
-		if (numstr == ep || *ep != '\0')
-			error = INVALID;
-		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
-			error = TOOSMALL;
-		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
-			error = TOOLARGE;
-	}
-	if (errstrp != NULL)
-		*errstrp = ev[error].errstr;
-	errno = ev[error].err;
-	if (error)
-		ll = 0;
-
-	return (ll);
-}
diff --git a/subprojects/lolibc b/subprojects/lolibc
@@ -0,0 +1 @@
+Subproject commit 801784932948e693c9cf172bec73fd26a244e3d0
diff --git a/sys/queue.h b/sys/queue.h
@@ -1,534 +0,0 @@
-/*	$OpenBSD: queue.h,v 1.45 2018/07/12 14:22:54 sashan Exp $	*/
-/*	$NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $	*/
-
-/*
- * Copyright (c) 1991, 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.
- *
- *	@(#)queue.h	8.5 (Berkeley) 8/20/94
- */
-
-#ifndef	_SYS_QUEUE_H_
-#define	_SYS_QUEUE_H_
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * lists, simple queues, tail queues and XOR simple queues.
- *
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction.  Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A simple queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are singly
- * linked to save space, so elements can only be removed from the
- * head of the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the
- * list. A simple queue may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * An XOR simple queue is used in the same way as a regular simple queue.
- * The difference is that the head structure also includes a "cookie" that
- * is XOR'd with the queue pointer (first, last or next) to generate the
- * real pointer value.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- */
-
-#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
-#define _Q_INVALID ((void *)-1)
-#define _Q_INVALIDATE(a) (a) = _Q_INVALID
-#else
-#define _Q_INVALIDATE(a)
-#endif
-
-/*
- * Singly-linked List definitions.
- */
-#define SLIST_HEAD(name, type)						\
-struct name {								\
-	struct type *slh_first;	/* first element */			\
-}
-
-#define	SLIST_HEAD_INITIALIZER(head)					\
-	{ NULL }
-
-#define SLIST_ENTRY(type)						\
-struct {								\
-	struct type *sle_next;	/* next element */			\
-}
-
-/*
- * Singly-linked List access methods.
- */
-#define	SLIST_FIRST(head)	((head)->slh_first)
-#define	SLIST_END(head)		NULL
-#define	SLIST_EMPTY(head)	(SLIST_FIRST(head) == SLIST_END(head))
-#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
-
-#define	SLIST_FOREACH(var, head, field)					\
-	for((var) = SLIST_FIRST(head);					\
-	    (var) != SLIST_END(head);					\
-	    (var) = SLIST_NEXT(var, field))
-
-#define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
-	for ((var) = SLIST_FIRST(head);				\
-	    (var) && ((tvar) = SLIST_NEXT(var, field), 1);		\
-	    (var) = (tvar))
-
-/*
- * Singly-linked List functions.
- */
-#define	SLIST_INIT(head) {						\
-	SLIST_FIRST(head) = SLIST_END(head);				\
-}
-
-#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
-	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
-	(slistelm)->field.sle_next = (elm);				\
-} while (0)
-
-#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
-	(elm)->field.sle_next = (head)->slh_first;			\
-	(head)->slh_first = (elm);					\
-} while (0)
-
-#define	SLIST_REMOVE_AFTER(elm, field) do {				\
-	(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;	\
-} while (0)
-
-#define	SLIST_REMOVE_HEAD(head, field) do {				\
-	(head)->slh_first = (head)->slh_first->field.sle_next;		\
-} while (0)
-
-#define SLIST_REMOVE(head, elm, type, field) do {			\
-	if ((head)->slh_first == (elm)) {				\
-		SLIST_REMOVE_HEAD((head), field);			\
-	} else {							\
-		struct type *curelm = (head)->slh_first;		\
-									\
-		while (curelm->field.sle_next != (elm))			\
-			curelm = curelm->field.sle_next;		\
-		curelm->field.sle_next =				\
-		    curelm->field.sle_next->field.sle_next;		\
-	}								\
-	_Q_INVALIDATE((elm)->field.sle_next);				\
-} while (0)
-
-/*
- * List definitions.
- */
-#define LIST_HEAD(name, type)						\
-struct name {								\
-	struct type *lh_first;	/* first element */			\
-}
-
-#define LIST_HEAD_INITIALIZER(head)					\
-	{ NULL }
-
-#define LIST_ENTRY(type)						\
-struct {								\
-	struct type *le_next;	/* next element */			\
-	struct type **le_prev;	/* address of previous next element */	\
-}
-
-/*
- * List access methods.
- */
-#define	LIST_FIRST(head)		((head)->lh_first)
-#define	LIST_END(head)			NULL
-#define	LIST_EMPTY(head)		(LIST_FIRST(head) == LIST_END(head))
-#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
-
-#define LIST_FOREACH(var, head, field)					\
-	for((var) = LIST_FIRST(head);					\
-	    (var)!= LIST_END(head);					\
-	    (var) = LIST_NEXT(var, field))
-
-#define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
-	for ((var) = LIST_FIRST(head);				\
-	    (var) && ((tvar) = LIST_NEXT(var, field), 1);		\
-	    (var) = (tvar))
-
-/*
- * List functions.
- */
-#define	LIST_INIT(head) do {						\
-	LIST_FIRST(head) = LIST_END(head);				\
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do {			\
-	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
-		(listelm)->field.le_next->field.le_prev =		\
-		    &(elm)->field.le_next;				\
-	(listelm)->field.le_next = (elm);				\
-	(elm)->field.le_prev = &(listelm)->field.le_next;		\
-} while (0)
-
-#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
-	(elm)->field.le_prev = (listelm)->field.le_prev;		\
-	(elm)->field.le_next = (listelm);				\
-	*(listelm)->field.le_prev = (elm);				\
-	(listelm)->field.le_prev = &(elm)->field.le_next;		\
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do {				\
-	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
-		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
-	(head)->lh_first = (elm);					\
-	(elm)->field.le_prev = &(head)->lh_first;			\
-} while (0)
-
-#define LIST_REMOVE(elm, field) do {					\
-	if ((elm)->field.le_next != NULL)				\
-		(elm)->field.le_next->field.le_prev =			\
-		    (elm)->field.le_prev;				\
-	*(elm)->field.le_prev = (elm)->field.le_next;			\
-	_Q_INVALIDATE((elm)->field.le_prev);				\
-	_Q_INVALIDATE((elm)->field.le_next);				\
-} while (0)
-
-#define LIST_REPLACE(elm, elm2, field) do {				\
-	if (((elm2)->field.le_next = (elm)->field.le_next) != NULL)	\
-		(elm2)->field.le_next->field.le_prev =			\
-		    &(elm2)->field.le_next;				\
-	(elm2)->field.le_prev = (elm)->field.le_prev;			\
-	*(elm2)->field.le_prev = (elm2);				\
-	_Q_INVALIDATE((elm)->field.le_prev);				\
-	_Q_INVALIDATE((elm)->field.le_next);				\
-} while (0)
-
-/*
- * Simple queue definitions.
- */
-#define SIMPLEQ_HEAD(name, type)					\
-struct name {								\
-	struct type *sqh_first;	/* first element */			\
-	struct type **sqh_last;	/* addr of last next element */		\
-}
-
-#define SIMPLEQ_HEAD_INITIALIZER(head)					\
-	{ NULL, &(head).sqh_first }
-
-#define SIMPLEQ_ENTRY(type)						\
-struct {								\
-	struct type *sqe_next;	/* next element */			\
-}
-
-/*
- * Simple queue access methods.
- */
-#define	SIMPLEQ_FIRST(head)	    ((head)->sqh_first)
-#define	SIMPLEQ_END(head)	    NULL
-#define	SIMPLEQ_EMPTY(head)	    (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
-#define	SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
-
-#define SIMPLEQ_FOREACH(var, head, field)				\
-	for((var) = SIMPLEQ_FIRST(head);				\
-	    (var) != SIMPLEQ_END(head);					\
-	    (var) = SIMPLEQ_NEXT(var, field))
-
-#define	SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)			\
-	for ((var) = SIMPLEQ_FIRST(head);				\
-	    (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1);		\
-	    (var) = (tvar))
-
-/*
- * Simple queue functions.
- */
-#define	SIMPLEQ_INIT(head) do {						\
-	(head)->sqh_first = NULL;					\
-	(head)->sqh_last = &(head)->sqh_first;				\
-} while (0)
-
-#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
-	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
-		(head)->sqh_last = &(elm)->field.sqe_next;		\
-	(head)->sqh_first = (elm);					\
-} while (0)
-
-#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
-	(elm)->field.sqe_next = NULL;					\
-	*(head)->sqh_last = (elm);					\
-	(head)->sqh_last = &(elm)->field.sqe_next;			\
-} while (0)
-
-#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
-	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
-		(head)->sqh_last = &(elm)->field.sqe_next;		\
-	(listelm)->field.sqe_next = (elm);				\
-} while (0)
-
-#define SIMPLEQ_REMOVE_HEAD(head, field) do {			\
-	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
-		(head)->sqh_last = &(head)->sqh_first;			\
-} while (0)
-
-#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do {			\
-	if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
-	    == NULL)							\
-		(head)->sqh_last = &(elm)->field.sqe_next;		\
-} while (0)
-
-#define SIMPLEQ_CONCAT(head1, head2) do {				\
-	if (!SIMPLEQ_EMPTY((head2))) {					\
-		*(head1)->sqh_last = (head2)->sqh_first;		\
-		(head1)->sqh_last = (head2)->sqh_last;			\
-		SIMPLEQ_INIT((head2));					\
-	}								\
-} while (0)
-
-/*
- * XOR Simple queue definitions.
- */
-#define XSIMPLEQ_HEAD(name, type)					\
-struct name {								\
-	struct type *sqx_first;	/* first element */			\
-	struct type **sqx_last;	/* addr of last next element */		\
-	unsigned long sqx_cookie;					\
-}
-
-#define XSIMPLEQ_ENTRY(type)						\
-struct {								\
-	struct type *sqx_next;	/* next element */			\
-}
-
-/*
- * XOR Simple queue access methods.
- */
-#define XSIMPLEQ_XOR(head, ptr)	    ((__typeof(ptr))((head)->sqx_cookie ^ \
-					(unsigned long)(ptr)))
-#define	XSIMPLEQ_FIRST(head)	    XSIMPLEQ_XOR(head, ((head)->sqx_first))
-#define	XSIMPLEQ_END(head)	    NULL
-#define	XSIMPLEQ_EMPTY(head)	    (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
-#define	XSIMPLEQ_NEXT(head, elm, field)    XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
-
-
-#define XSIMPLEQ_FOREACH(var, head, field)				\
-	for ((var) = XSIMPLEQ_FIRST(head);				\
-	    (var) != XSIMPLEQ_END(head);				\
-	    (var) = XSIMPLEQ_NEXT(head, var, field))
-
-#define	XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar)			\
-	for ((var) = XSIMPLEQ_FIRST(head);				\
-	    (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1);	\
-	    (var) = (tvar))
-
-/*
- * XOR Simple queue functions.
- */
-#define	XSIMPLEQ_INIT(head) do {					\
-	arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
-	(head)->sqx_first = XSIMPLEQ_XOR(head, NULL);			\
-	(head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first);	\
-} while (0)
-
-#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
-	if (((elm)->field.sqx_next = (head)->sqx_first) ==		\
-	    XSIMPLEQ_XOR(head, NULL))					\
-		(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
-	(head)->sqx_first = XSIMPLEQ_XOR(head, (elm));			\
-} while (0)
-
-#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
-	(elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL);		\
-	*(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
-	(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);	\
-} while (0)
-
-#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
-	if (((elm)->field.sqx_next = (listelm)->field.sqx_next) ==	\
-	    XSIMPLEQ_XOR(head, NULL))					\
-		(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
-	(listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm));		\
-} while (0)
-
-#define XSIMPLEQ_REMOVE_HEAD(head, field) do {				\
-	if (((head)->sqx_first = XSIMPLEQ_XOR(head,			\
-	    (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
-		(head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
-} while (0)
-
-#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do {			\
-	if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head,			\
-	    (elm)->field.sqx_next)->field.sqx_next)			\
-	    == XSIMPLEQ_XOR(head, NULL))				\
-		(head)->sqx_last = 					\
-		    XSIMPLEQ_XOR(head, &(elm)->field.sqx_next);		\
-} while (0)
-
-
-/*
- * Tail queue definitions.
- */
-#define TAILQ_HEAD(name, type)						\
-struct name {								\
-	struct type *tqh_first;	/* first element */			\
-	struct type **tqh_last;	/* addr of last next element */		\
-}
-
-#define TAILQ_HEAD_INITIALIZER(head)					\
-	{ NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type)						\
-struct {								\
-	struct type *tqe_next;	/* next element */			\
-	struct type **tqe_prev;	/* address of previous next element */	\
-}
-
-/*
- * Tail queue access methods.
- */
-#define	TAILQ_FIRST(head)		((head)->tqh_first)
-#define	TAILQ_END(head)			NULL
-#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
-#define TAILQ_LAST(head, headname)					\
-	(*(((struct headname *)((head)->tqh_last))->tqh_last))
-/* XXX */
-#define TAILQ_PREV(elm, headname, field)				\
-	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-#define	TAILQ_EMPTY(head)						\
-	(TAILQ_FIRST(head) == TAILQ_END(head))
-
-#define TAILQ_FOREACH(var, head, field)					\
-	for((var) = TAILQ_FIRST(head);					\
-	    (var) != TAILQ_END(head);					\
-	    (var) = TAILQ_NEXT(var, field))
-
-#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
-	for ((var) = TAILQ_FIRST(head);					\
-	    (var) != TAILQ_END(head) &&					\
-	    ((tvar) = TAILQ_NEXT(var, field), 1);			\
-	    (var) = (tvar))
-
-
-#define TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
-	for((var) = TAILQ_LAST(head, headname);				\
-	    (var) != TAILQ_END(head);					\
-	    (var) = TAILQ_PREV(var, headname, field))
-
-#define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
-	for ((var) = TAILQ_LAST(head, headname);			\
-	    (var) != TAILQ_END(head) &&					\
-	    ((tvar) = TAILQ_PREV(var, headname, field), 1);		\
-	    (var) = (tvar))
-
-/*
- * Tail queue functions.
- */
-#define	TAILQ_INIT(head) do {						\
-	(head)->tqh_first = NULL;					\
-	(head)->tqh_last = &(head)->tqh_first;				\
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do {			\
-	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
-		(head)->tqh_first->field.tqe_prev =			\
-		    &(elm)->field.tqe_next;				\
-	else								\
-		(head)->tqh_last = &(elm)->field.tqe_next;		\
-	(head)->tqh_first = (elm);					\
-	(elm)->field.tqe_prev = &(head)->tqh_first;			\
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do {			\
-	(elm)->field.tqe_next = NULL;					\
-	(elm)->field.tqe_prev = (head)->tqh_last;			\
-	*(head)->tqh_last = (elm);					\
-	(head)->tqh_last = &(elm)->field.tqe_next;			\
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
-	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
-		(elm)->field.tqe_next->field.tqe_prev =			\
-		    &(elm)->field.tqe_next;				\
-	else								\
-		(head)->tqh_last = &(elm)->field.tqe_next;		\
-	(listelm)->field.tqe_next = (elm);				\
-	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
-} while (0)
-
-#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
-	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
-	(elm)->field.tqe_next = (listelm);				\
-	*(listelm)->field.tqe_prev = (elm);				\
-	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
-} while (0)
-
-#define TAILQ_REMOVE(head, elm, field) do {				\
-	if (((elm)->field.tqe_next) != NULL)				\
-		(elm)->field.tqe_next->field.tqe_prev =			\
-		    (elm)->field.tqe_prev;				\
-	else								\
-		(head)->tqh_last = (elm)->field.tqe_prev;		\
-	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
-	_Q_INVALIDATE((elm)->field.tqe_prev);				\
-	_Q_INVALIDATE((elm)->field.tqe_next);				\
-} while (0)
-
-#define TAILQ_REPLACE(head, elm, elm2, field) do {			\
-	if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)	\
-		(elm2)->field.tqe_next->field.tqe_prev =		\
-		    &(elm2)->field.tqe_next;				\
-	else								\
-		(head)->tqh_last = &(elm2)->field.tqe_next;		\
-	(elm2)->field.tqe_prev = (elm)->field.tqe_prev;			\
-	*(elm2)->field.tqe_prev = (elm2);				\
-	_Q_INVALIDATE((elm)->field.tqe_prev);				\
-	_Q_INVALIDATE((elm)->field.tqe_next);				\
-} while (0)
-
-#define TAILQ_CONCAT(head1, head2, field) do {				\
-	if (!TAILQ_EMPTY(head2)) {					\
-		*(head1)->tqh_last = (head2)->tqh_first;		\
-		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
-		(head1)->tqh_last = (head2)->tqh_last;			\
-		TAILQ_INIT((head2));					\
-	}								\
-} while (0)
-
-#endif	/* !_SYS_QUEUE_H_ */
diff --git a/sys/time.h b/sys/time.h
@@ -1,79 +0,0 @@
-/*	$OpenBSD: time.h,v 1.46 2019/08/03 22:53:45 cheloha Exp $	*/
-/*	$NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $	*/
-
-/*
- * Copyright (c) 1982, 1986, 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.
- *
- *	@(#)time.h	8.2 (Berkeley) 7/10/94
- */
-
-#ifndef _SYS_TIME_H_
-#define _SYS_TIME_H_
-
-/* Operations on timevals. */
-#define	timerclear(tvp)		(tvp)->tv_sec = (tvp)->tv_usec = 0
-#define	timerisset(tvp)		((tvp)->tv_sec || (tvp)->tv_usec)
-#define	timercmp(tvp, uvp, cmp)						\
-	(((tvp)->tv_sec == (uvp)->tv_sec) ?				\
-	    ((tvp)->tv_usec cmp (uvp)->tv_usec) :			\
-	    ((tvp)->tv_sec cmp (uvp)->tv_sec))
-#define	timeradd(tvp, uvp, vvp)						\
-	do {								\
-		(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;		\
-		(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec;	\
-		if ((vvp)->tv_usec >= 1000000) {			\
-			(vvp)->tv_sec++;				\
-			(vvp)->tv_usec -= 1000000;			\
-		}							\
-	} while (0)
-#define	timersub(tvp, uvp, vvp)						\
-	do {								\
-		(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
-		(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;	\
-		if ((vvp)->tv_usec < 0) {				\
-			(vvp)->tv_sec--;				\
-			(vvp)->tv_usec += 1000000;			\
-		}							\
-	} while (0)
-
-/* Operations on timespecs. */
-#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 /* !_SYS_TIME_H_ */
diff --git a/table.h b/table.h
@@ -2,8 +2,6 @@
 
 /* $From: table.h,v 1.3 1994/05/31 13:34:34 michael Exp $ */
 
-#include <inttypes.h>
-
 /*
  * generic hashed associative table for commands and variables.
  */
diff --git a/trap.c b/trap.c
@@ -11,47 +11,28 @@
 
 #include "sh.h"
 
-Trap sigtraps[NSIG + 1] = {
-	{ SIGEXIT_, "EXIT", "Signal 0" },
-	{ 1 , "HUP", "Hangup" },
-	{ 2 , "INT", "Interrupt" },
-	{ 3 , "QUIT", "Quit" },
-	{ 4 , "ILL", "Illegal instruction" },
-	{ 5 , "TRAP", "Trace trap" },
-	{ 6 , "ABRT", "Abort" },
-	{ 7 , "BUS", "Bus error" },
-	{ 8 , "FPE", "Floating point exception" },
-	{ 9 , "KILL", "Killed" },
-	{ 10 , "USR1", "User defined signal 1" },
-	{ 11 , "SEGV", "Memory fault" },
-	{ 12 , "USR2", "User defined signal 2" },
-	{ 13 , "PIPE", "Broken pipe" },
-	{ 14 , "ALRM", "Alarm clock" },
-	{ 15 , "TERM", "Terminated" },
-	{ 16 , "STKFLT", "Stack fault" },
-	{ 17 , "CHLD", "Child exited" },
-	{ 18 , "CONT", "Continued" },
-	{ 19 , "STOP", "Stopped (signal)" },
-	{ 20 , "TSTP", "Stopped" },
-	{ 21 , "TTIN", "Stopped (tty input)" },
-	{ 22 , "TTOU", "Stopped (tty output)" },
-	{ 23 , "URG", "Urgent I/O condition" },
-	{ 24 , "XCPU", "CPU time limit exceeded" },
-	{ 25 , "XFSZ", "File size limit exceeded" },
-	{ 26 , "VTALRM", "Virtual timer expired" },
-	{ 27 , "PROF", "Profiling timer expired" },
-	{ 28 , "WINCH", "Window size change" },
-	{ 29 , "IO", "I/O possible" },
-	{ 30 , "PWR", "Power-fail/Restart" },
-	{ 31 , "UNUSED", "Unused" },
-	{ SIGERR_,  "ERR",  "Error handler" }
-};
+Trap sigtraps[NSIG + 1];
 
 static struct sigaction Sigact_ign, Sigact_trap;
 
 void
 inittraps(void)
 {
+	int	i;
+
+	/* Populate sigtraps based on sys_signame and sys_siglist. */
+	for (i = 0; i <= NSIG; i++) {
+		sigtraps[i].signal = i;
+		if (i == SIGERR_) {
+			sigtraps[i].name = "ERR";
+			sigtraps[i].mess = "Error handler";
+		} else {
+			sigtraps[i].name = sys_signame[i];
+			sigtraps[i].mess = sys_siglist[i];
+		}
+	}
+	sigtraps[SIGEXIT_].name = "EXIT";	/* our name for signal 0 */
+
 	sigemptyset(&Sigact_ign.sa_mask);
 	Sigact_ign.sa_flags = 0; /* interruptible */
 	Sigact_ign.sa_handler = SIG_IGN;
diff --git a/unvis.c b/unvis.c
@@ -1,285 +0,0 @@
-/*	$OpenBSD: unvis.c,v 1.17 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 <ctype.h>
-#include <vis.h>
-
-/*
- * decode driven by state machine
- */
-#define	S_GROUND	0	/* haven't seen escape char */
-#define	S_START		1	/* start decoding special sequence */
-#define	S_META		2	/* metachar started (M) */
-#define	S_META1		3	/* metachar more, regular char (-) */
-#define	S_CTRL		4	/* control char started (^) */
-#define	S_OCTAL2	5	/* octal digit 2 */
-#define	S_OCTAL3	6	/* octal digit 3 */
-
-#define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-
-/*
- * unvis - decode characters previously encoded by vis
- */
-int
-unvis(char *cp, char c, int *astate, int flag)
-{
-
-	if (flag & UNVIS_END) {
-		if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		} 
-		return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
-	}
-
-	switch (*astate) {
-
-	case S_GROUND:
-		*cp = 0;
-		if (c == '\\') {
-			*astate = S_START;
-			return (0);
-		} 
-		*cp = c;
-		return (UNVIS_VALID);
-
-	case S_START:
-		switch(c) {
-		case '-':
-			*cp = 0;
-			*astate = S_GROUND;
-			return (0);
-		case '\\':
-		case '"':
-			*cp = c;
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case '0': case '1': case '2': case '3':
-		case '4': case '5': case '6': case '7':
-			*cp = (c - '0');
-			*astate = S_OCTAL2;
-			return (0);
-		case 'M':
-			*cp = (char) 0200;
-			*astate = S_META;
-			return (0);
-		case '^':
-			*astate = S_CTRL;
-			return (0);
-		case 'n':
-			*cp = '\n';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 'r':
-			*cp = '\r';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 'b':
-			*cp = '\b';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 'a':
-			*cp = '\007';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 'v':
-			*cp = '\v';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 't':
-			*cp = '\t';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 'f':
-			*cp = '\f';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 's':
-			*cp = ' ';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case 'E':
-			*cp = '\033';
-			*astate = S_GROUND;
-			return (UNVIS_VALID);
-		case '\n':
-			/*
-			 * hidden newline
-			 */
-			*astate = S_GROUND;
-			return (UNVIS_NOCHAR);
-		case '$':
-			/*
-			 * hidden marker
-			 */
-			*astate = S_GROUND;
-			return (UNVIS_NOCHAR);
-		}
-		*astate = S_GROUND;
-		return (UNVIS_SYNBAD);
-		 
-	case S_META:
-		if (c == '-')
-			*astate = S_META1;
-		else if (c == '^')
-			*astate = S_CTRL;
-		else {
-			*astate = S_GROUND;
-			return (UNVIS_SYNBAD);
-		}
-		return (0);
-		 
-	case S_META1:
-		*astate = S_GROUND;
-		*cp |= c;
-		return (UNVIS_VALID);
-		 
-	case S_CTRL:
-		if (c == '?')
-			*cp |= 0177;
-		else
-			*cp |= c & 037;
-		*astate = S_GROUND;
-		return (UNVIS_VALID);
-
-	case S_OCTAL2:	/* second possible octal digit */
-		if (isoctal(c)) {
-			/* 
-			 * yes - and maybe a third 
-			 */
-			*cp = (*cp << 3) + (c - '0');
-			*astate = S_OCTAL3;	
-			return (0);
-		} 
-		/* 
-		 * no - done with current sequence, push back passed char 
-		 */
-		*astate = S_GROUND;
-		return (UNVIS_VALIDPUSH);
-
-	case S_OCTAL3:	/* third possible octal digit */
-		*astate = S_GROUND;
-		if (isoctal(c)) {
-			*cp = (*cp << 3) + (c - '0');
-			return (UNVIS_VALID);
-		}
-		/*
-		 * we were done, push back passed char
-		 */
-		return (UNVIS_VALIDPUSH);
-
-	default:	
-		/* 
-		 * decoder in unknown state - (probably uninitialized) 
-		 */
-		*astate = S_GROUND;
-		return (UNVIS_SYNBAD);
-	}
-}
-
-/*
- * strunvis - decode src into dst 
- *
- *	Number of chars decoded into dst is returned, -1 on error.
- *	Dst is null terminated.
- */
-
-int
-strunvis(char *dst, const char *src)
-{
-	char c;
-	char *start = dst;
-	int state = 0;
-
-	while ((c = *src++)) {
-	again:
-		switch (unvis(dst, c, &state, 0)) {
-		case UNVIS_VALID:
-			dst++;
-			break;
-		case UNVIS_VALIDPUSH:
-			dst++;
-			goto again;
-		case 0:
-		case UNVIS_NOCHAR:
-			break;
-		default:
-			*dst = '\0';
-			return (-1);
-		}
-	}
-	if (unvis(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);
-}
-
diff --git a/var.c b/var.c
@@ -1042,7 +1042,7 @@ setspec(struct tbl *vp)
 		break;
 	case V_RANDOM:
 		vp->flag &= ~SPECIAL;
-		srand((unsigned int)intval(vp));
+		srand_deterministic((unsigned int)intval(vp));
 		vp->flag |= SPECIAL;
 		break;
 	case V_SECONDS:
diff --git a/vi.c b/vi.c
@@ -14,6 +14,7 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ttydefaults.h>
 #ifndef SMALL
 # include <term.h>
 # include <curses.h>
diff --git a/vis.c b/vis.c
@@ -1,241 +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>
-
-#define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-#define	isvisible(c,flag)						\
-	(((c) == '\\' || (flag & VIS_ALL) == 0) &&			\
-	(((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) &&		\
-	(((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') ||	\
-		(flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) ||	\
-	((flag & VIS_SP) == 0 && (c) == ' ') ||				\
-	((flag & VIS_TAB) == 0 && (c) == '\t') ||			\
-	((flag & VIS_NL) == 0 && (c) == '\n') ||			\
-	((flag & VIS_SAFE) && ((c) == '\b' ||				\
-		(c) == '\007' || (c) == '\r' ||				\
-		isgraph((u_char)(c))))))
-
-/*
- * vis - visually encode characters
- */
-char *
-vis(char *dst, int c, int flag, int nextc)
-{
-	if (isvisible(c, flag)) {
-		if ((c == '"' && (flag & VIS_DQ) != 0) ||
-		    (c == '\\' && (flag & VIS_NOSLASH) == 0))
-			*dst++ = '\\';
-		*dst++ = c;
-		*dst = '\0';
-		return (dst);
-	}
-
-	if (flag & VIS_CSTYLE) {
-		switch(c) {
-		case '\n':
-			*dst++ = '\\';
-			*dst++ = 'n';
-			goto done;
-		case '\r':
-			*dst++ = '\\';
-			*dst++ = 'r';
-			goto done;
-		case '\b':
-			*dst++ = '\\';
-			*dst++ = 'b';
-			goto done;
-		case '\a':
-			*dst++ = '\\';
-			*dst++ = 'a';
-			goto done;
-		case '\v':
-			*dst++ = '\\';
-			*dst++ = 'v';
-			goto done;
-		case '\t':
-			*dst++ = '\\';
-			*dst++ = 't';
-			goto done;
-		case '\f':
-			*dst++ = '\\';
-			*dst++ = 'f';
-			goto done;
-		case ' ':
-			*dst++ = '\\';
-			*dst++ = 's';
-			goto done;
-		case '\0':
-			*dst++ = '\\';
-			*dst++ = '0';
-			if (isoctal(nextc)) {
-				*dst++ = '0';
-				*dst++ = '0';
-			}
-			goto done;
-		}
-	}
-	if (((c & 0177) == ' ') || (flag & VIS_OCTAL) ||
-	    ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) {
-		*dst++ = '\\';
-		*dst++ = ((u_char)c >> 6 & 07) + '0';
-		*dst++ = ((u_char)c >> 3 & 07) + '0';
-		*dst++ = ((u_char)c & 07) + '0';
-		goto done;
-	}
-	if ((flag & VIS_NOSLASH) == 0)
-		*dst++ = '\\';
-	if (c & 0200) {
-		c &= 0177;
-		*dst++ = 'M';
-	}
-	if (iscntrl((u_char)c)) {
-		*dst++ = '^';
-		if (c == 0177)
-			*dst++ = '?';
-		else
-			*dst++ = c + '@';
-	} else {
-		*dst++ = '-';
-		*dst++ = c;
-	}
-done:
-	*dst = '\0';
-	return (dst);
-}
-
-/*
- * strvis, strnvis, strvisx - visually encode characters from src into dst
- *	
- *	Dst must be 4 times the size of src to account for possible
- *	expansion.  The length of dst, not including the trailing NULL,
- *	is returned. 
- *
- *	Strnvis will write no more than siz-1 bytes (and will NULL terminate).
- *	The number of bytes needed to fully encode the string is returned.
- *
- *	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)
-{
-	char c;
-	char *start;
-
-	for (start = dst; (c = *src);)
-		dst = vis(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)
-{
-	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);
-}
-
-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);
-}
diff --git a/vis.h b/vis.h
@@ -1,88 +0,0 @@
-/*	$OpenBSD: vis.h,v 1.15 2015/07/20 01:52:27 millert Exp $	*/
-/*	$NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $	*/
-
-/*-
- * Copyright (c) 1990 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.
- *
- *	@(#)vis.h	5.9 (Berkeley) 4/3/91
- */
-
-#ifndef _VIS_H_
-#define	_VIS_H_
-
-/*
- * to select alternate encoding format
- */
-#define	VIS_OCTAL	0x01	/* use octal \ddd format */
-#define	VIS_CSTYLE	0x02	/* use \[nrft0..] where appropriate */
-
-/*
- * to alter set of characters encoded (default is to encode all
- * non-graphic except space, tab, and newline).
- */
-#define	VIS_SP		0x04	/* also encode space */
-#define	VIS_TAB		0x08	/* also encode tab */
-#define	VIS_NL		0x10	/* also encode newline */
-#define	VIS_WHITE	(VIS_SP | VIS_TAB | VIS_NL)
-#define	VIS_SAFE	0x20	/* only encode "unsafe" characters */
-#define	VIS_DQ		0x200	/* backslash-escape double quotes */
-#define	VIS_ALL		0x400	/* encode all characters */
-
-/*
- * other
- */
-#define	VIS_NOSLASH	0x40	/* inhibit printing '\' */
-#define	VIS_GLOB	0x100	/* encode glob(3) magics and '#' */
-
-/*
- * unvis return codes
- */
-#define	UNVIS_VALID	 1	/* character valid */
-#define	UNVIS_VALIDPUSH	 2	/* character valid, push back passed char */
-#define	UNVIS_NOCHAR	 3	/* valid sequence, no character produced */
-#define	UNVIS_SYNBAD	-1	/* unrecognized escape sequence */
-#define	UNVIS_ERROR	-2	/* decoder in unknown state (unrecoverable) */
-
-/*
- * unvis flags
- */
-#define	UNVIS_END	1	/* no more characters */
-
-char	*vis(char *, int, int, int);
-int	strvis(char *, const char *, int);
-int	stravis(char **, const char *, int);
-int	strnvis(char *, const char *, size_t, int)
-		__attribute__ ((__bounded__(__string__,1,3)));
-int	strvisx(char *, const char *, size_t, int)
-		__attribute__ ((__bounded__(__string__,1,3)));
-int	strunvis(char *, const char *);
-int	unvis(char *, char, int *, int);
-ssize_t strnunvis(char *, const char *, size_t)
-		__attribute__ ((__bounded__(__string__,1,3)));
-
-#endif /* !_VIS_H_ */