Commit Diff


commit - c2f554ff612cef4c72eea5a7da22d508b8c36d3c
commit + f36fd90a2e6ab101692fba0fa643aec5035597cd
blob - 3fdff78bcab1fcf6493998cb99b64ff5a5da4f63
blob + abf3c24bc711201666a48e52c79d2bdde00dea31
--- .gitignore
+++ .gitignore
@@ -1,2 +1,10 @@
+Makefile.configure
+amused
+config.h
+config.h.old
+config.log
+config.log.old
+**/*.d
+**/*.o
 **/obj
 **/tags
blob - 5a598e37a5ea16dd8da1dc46006c6e7595d42ad7
blob + b209c639fe00cd307f6816a5e1c56083e45f7cce
--- Makefile
+++ Makefile
@@ -1,47 +1,104 @@
-PROG=	amused
-SRCS=	amused.c control.c log.c xmalloc.c player.c ctl.c playlist.c \
-	player_flac.c player_123.c player_opus.c player_oggvorbis.c
+.PHONY: all clean distclean install
 
-.include "amused-version.mk"
+VERSION =	0.10
 
-CPPFLAGS += -I/usr/local/include -I/usr/local/include/opus
+PROG =		amused
 
-LDADD =	-levent -lm -lsndio -lutil \
-	-L/usr/local/lib -lmpg123 -lvorbisfile -lopusfile -lFLAC
-DPADD =	${LIBEVENT} ${LIBM} ${LIBSNDIO} ${LIBUTIL}
+SOURCES =	amused.c \
+		compats.c \
+		control.c \
+		ctl.c \
+		log.c \
+		player.c \
+		player_123.c \
+		player_flac.c \
+		player_oggvorbis.c \
+		player_opus.c \
+		playlist.c \
+		xmalloc.c
 
-.if "${AMUSED_RELEASE}" == "Yes"
-PREFIX ?= /usr/local
-BINDIR ?= ${PREFIX}/bin
-MANDIR ?= ${PREFIX}/man/man
-.else
-NOMAN = Yes
-CFLAGS += -Werror -Wall -Wstrict-prototypes -Wunused-variable
-PREFIX ?= ${HOME}
-BINDIR ?= ${PREFIX}/bin
-BINOWN ?= ${USER}
-.if !defined(BINGRP)
-BINGRP != id -g -n
-.endif
-DEBUG = -O0 -g
-.endif
+OBJS =		${SOURCES:.c=.o}
 
-release: clean
-	sed -i -e 's/_RELEASE=No/_RELEASE=Yes/' amused-version.mk
-	${MAKE} dist
-	sed -i -e 's/_RELEASE=Yes/_RELEASE=No/' amused-version.mk
+HEADERS =	amused.h \
+		control.h \
+		log.h \
+		playlist.h \
+		xmalloc.h
 
-dist: clean
-	mkdir /tmp/amused-${AMUSED_VERSION}
-	pax -rw * /tmp/amused-${AMUSED_VERSION}
-	find /tmp/amused-${AMUSED_VERSION} -type d -name obj -delete
-	rm /tmp/amused-${AMUSED_VERSION}/amused-dist.txt
-	tar -C /tmp -zcf amused-${AMUSED_VERSION}.tar.gz amused-${AMUSED_VERSION}
-	rm -rf /tmp/amused-${AMUSED_VERSION}
-	tar -ztf amused-${AMUSED_VERSION}.tar.gz | \
-		sed -e 's/^amused-${AMUSED_VERSION}//' | \
-		sort > amused-dist.txt.new
-	diff -u amused-dist.txt{,.new}
-	rm amused-dist.txt.new
+DISTFILES =	CHANGES \
+		LICENSE \
+		Makefile \
+		README.md \
+		amused.1 \
+		configure \
+		configure.local.example \
+		imsg.h \
+		queue.h \
+		tests.c \
+		${HEADERS} \
+		${SOURCES}
 
-.include <bsd.prog.mk>
+all: ${PROG}
+
+Makefile.configure config.h: configure tests.c
+	@echo "$@ is out of date; please run ./configure"
+	@exit 1
+
+include Makefile.configure
+
+# -- targets --
+
+${PROG}: ${OBJS}
+	${CC} -o $@ ${OBJS} ${LDFLAGS} ${LDADD}
+
+clean:
+	rm -f ${OBJS} ${PROG}
+
+distclean: clean
+	rm -f Makefile.configure config.h config.h.old config.log config.log.old
+
+install:
+	mkdir -p ${DESTDIR}${BINDIR}
+	mkdir -p ${DESTDIR}${MANDIR}/man1
+	${INSTALL_PROGRAM} ${PROG} ${DESTDIR}${BINDIR}
+	${INSTALL_MAN} amused.1 ${DESTDIR}${MANDIR}/man1/${PROG}.1
+
+install-local:
+	mkdir -p ${HOME}/bin
+	${INSTALL_PROGRAM} ${PROG} ${HOME}/bin
+
+uninstall:
+	rm ${DESTDIR}${BINDIR}/${PROG}
+	rm ${DESTDIR}${MANDIR}/man1/${PROG}.1
+
+# --- maintainer targets ---
+
+dist: ${PROG}-${VERSION}.sha256
+
+${PROG}-${VERSION}.sha256: ${PROG}-${VERSION}.tar.gz
+	sha256 ${PROG}-${VERSION}.tar.gz > $@
+
+${PROG}-${VERSION}.tar.gz: ${DISTFILES}
+	mkdir -p .dist/${PROG}-${VERSION}
+	${INSTALL} -m 0644 ${DISTFILES} .dist/${PROG}-${VERSION}
+	cd .dist/${PROG}-${VERSION} && chmod 755 configure
+	cd .dist && tar zcf ../$@ ${PROG}-${VERSION}
+	rm -rf .dist/
+
+# --- dependency management ---
+
+# these .d files are produced during the first build if the compiler
+# supports it.
+
+-include amused.d
+-include compats.d
+-include control.d
+-include ctl.d
+-include log.d
+-include player.d
+-include player_123.d
+-include player_flac.d
+-include player_oggvorbis.d
+-include player_opus.d
+-include playlist.d
+-include xmalloc.d
blob - 1b2a36f67a77108d86f6f486789032bfd5b6bc5f (mode 644)
blob + /dev/null
--- amused-dist.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-
-/CHANGES
-/LICENSE
-/Makefile
-/README.md
-/amused-version.mk
-/amused.1
-/amused.c
-/amused.h
-/control.c
-/control.h
-/ctl.c
-/log.c
-/log.h
-/player.c
-/player_123.c
-/player_flac.c
-/player_oggvorbis.c
-/player_opus.c
-/playlist.c
-/playlist.h
-/xmalloc.c
-/xmalloc.h
blob - 1a4652276f1281058098b73a5b88aa9ddadecb69 (mode 644)
blob + /dev/null
--- amused-version.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-AMUSED_RELEASE=No
-AMUSED_VERSION_NUMBER=0.10
-
-.if ${AMUSED_RELEASE} == Yes
-AMUSED_VERSION=${AMUSED_VERSION_NUMBER}
-.else
-AMUSED_VERSION=${AMUSED_VERSION_NUMBER}-current
-.endif
blob - 238295db07b7cbc0d8793381b38d5936f4dec604
blob + bf368c371689924a2eaedfb47abd27af8a2f6db4
--- amused.c
+++ amused.c
@@ -14,14 +14,12 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <sys/types.h>
-#include <sys/queue.h>
+#include "config.h"
+
 #include <sys/socket.h>
 #include <sys/stat.h>
-#include <sys/uio.h>
 #include <sys/wait.h>
 
-#include <event.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
@@ -32,7 +30,6 @@
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>
-#include <imsg.h>
 
 #include "amused.h"
 #include "control.h"
blob - /dev/null
blob + a402eb60f55fb2b692600268f4b7d5cdebce55e5 (mode 644)
--- /dev/null
+++ compats.c
@@ -0,0 +1,1545 @@
+#include "config.h"
+#if !HAVE_ERR
+/*
+ * Copyright (c) 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 <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void
+vwarnx(const char *fmt, va_list ap)
+{
+	fprintf(stderr, "%s: ", getprogname());
+	if (fmt != NULL)
+		vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+}
+
+void
+vwarnc(int code, const char *fmt, va_list ap)
+{
+	fprintf(stderr, "%s: ", getprogname());
+	if (fmt != NULL) {
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, ": ");
+	}
+	fprintf(stderr, "%s\n", strerror(code));
+}
+
+void
+vwarn(const char *fmt, va_list ap)
+{
+	int sverrno;
+
+	sverrno = errno;
+	fprintf(stderr, "%s: ", getprogname());
+	if (fmt != NULL) {
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, ": ");
+	}
+	fprintf(stderr, "%s\n", strerror(sverrno));
+}
+
+void
+verrc(int eval, int code, const char *fmt, va_list ap)
+{
+	fprintf(stderr, "%s: ", getprogname());
+	if (fmt != NULL) {
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, ": ");
+	}
+	fprintf(stderr, "%s\n", strerror(code));
+	exit(eval);
+}
+
+void
+verrx(int eval, const char *fmt, va_list ap)
+{
+	fprintf(stderr, "%s: ", getprogname());
+	if (fmt != NULL)
+		vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+	exit(eval);
+}
+
+void
+verr(int eval, const char *fmt, va_list ap)
+{
+	int sverrno;
+
+	sverrno = errno;
+	fprintf(stderr, "%s: ", getprogname());
+	if (fmt != NULL) {
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, ": ");
+	}
+	fprintf(stderr, "%s\n", strerror(sverrno));
+	exit(eval);
+}
+
+void
+err(int eval, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	verr(eval, fmt, ap);
+	va_end(ap);
+}
+
+void
+errc(int eval, int code, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	verrc(eval, code, fmt, ap);
+	va_end(ap);
+}
+
+void
+errx(int eval, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	verrx(eval, fmt, ap);
+	va_end(ap);
+}
+
+void
+warn(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vwarn(fmt, ap);
+	va_end(ap);
+}
+
+void
+warnc(int code, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vwarnc(code, fmt, ap);
+	va_end(ap);
+}
+
+void
+warnx(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vwarnx(fmt, ap);
+	va_end(ap);
+}
+#endif /* !HAVE_ERR */
+#if !HAVE_FLOCK
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+/*
+ * flock(2) emulation on top of fcntl advisory locks.  This is "good
+ * enough" for amused, not a _real_ emulation.  flock and fcntl locks
+ * have subtly different behaviours!
+ */
+int
+flock(int fd, int op)
+{
+	struct flock l;
+	int cmd;
+
+	memset(&l, 0, sizeof(l));
+	l.l_whence = SEEK_SET;
+
+	if (op & LOCK_SH)
+		l.l_type = F_RDLCK;
+	else if (op & LOCK_EX)
+		l.l_type = F_WRLCK;
+	else {
+		errno = EINVAL;
+		return -1;
+	}
+
+	cmd = F_SETLKW;
+	if (op & LOCK_NB)
+		cmd = F_SETLK;
+
+	return fcntl(fd, cmd, &l);
+}
+#endif /* HAVE_FLOCK */
+#if !HAVE_FREEZERO
+#include <stdlib.h>
+#include <string.h>
+
+void
+freezero(void *ptr, size_t len)
+{
+	if (ptr == NULL)
+		return;
+	memset(ptr, 0, len);
+	free(ptr);
+}
+#endif /* HAVE_FREEZERO */
+#if !HAVE_EXPLICIT_BZERO
+/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */
+/*
+ * Public domain.
+ * Written by Ted Unangst
+ */
+
+#include <string.h>
+
+/*
+ * explicit_bzero - don't let the compiler optimize away bzero
+ */
+
+#if HAVE_MEMSET_S
+
+void
+explicit_bzero(void *p, size_t n)
+{
+	if (n == 0)
+		return;
+	(void)memset_s(p, n, 0, n);
+}
+
+#else /* HAVE_MEMSET_S */
+
+#include <strings.h>
+
+/*
+ * Indirect memset through a volatile pointer to hopefully avoid
+ * dead-store optimisation eliminating the call.
+ */
+static void (* volatile ssh_memset)(void *, int, size_t) = memset;
+
+void
+explicit_bzero(void *p, size_t n)
+{
+	if (n == 0)
+		return;
+	/*
+	 * clang -fsanitize=memory needs to intercept memset-like functions
+	 * to correctly detect memory initialisation. Make sure one is called
+	 * directly since our indirection trick above sucessfully confuses it.
+	 */
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+	memset(p, 0, n);
+# endif
+#endif
+
+	ssh_memset(p, 0, n);
+}
+
+#endif /* HAVE_MEMSET_S */
+#endif /* !HAVE_EXPLICIT_BZERO */
+#if !HAVE_GETPROGNAME
+/*
+ * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
+ * Copyright (c) 2017 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2020 Stephen Gregoratto <dev@sgregoratto.me>
+ *
+ * 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 MIND, 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>
+
+#if HAVE_GETEXECNAME
+#include <stdlib.h>
+const char *
+getprogname(void)
+{
+	return getexecname();
+}
+#elif HAVE_PROGRAM_INVOCATION_SHORT_NAME
+const char *
+getprogname(void)
+{
+	return (program_invocation_short_name);
+}
+#elif HAVE___PROGNAME
+const char *
+getprogname(void)
+{
+	extern char	*__progname;
+
+	return (__progname);
+}
+#else
+#warning No getprogname available.
+const char *
+getprogname(void)
+{
+	return ("amused");
+}
+#endif
+#endif /* !HAVE_GETPROGNAME */
+#if !HAVE_IMSG
+/*	$OpenBSD: imsg-buffer.c,v 1.13 2021/03/31 17:42:24 eric Exp $	*/
+/*	$OpenBSD: imsg.c,v 1.17 2022/01/28 10:41:44 claudio Exp $	*/
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@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 "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "imsg.h"
+
+static int	ibuf_realloc(struct ibuf *, size_t);
+static void	ibuf_enqueue(struct msgbuf *, struct ibuf *);
+static void	ibuf_dequeue(struct msgbuf *, struct ibuf *);
+
+struct ibuf *
+ibuf_open(size_t len)
+{
+	struct ibuf	*buf;
+
+	if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
+		return (NULL);
+	if ((buf->buf = malloc(len)) == NULL) {
+		free(buf);
+		return (NULL);
+	}
+	buf->size = buf->max = len;
+	buf->fd = -1;
+
+	return (buf);
+}
+
+struct ibuf *
+ibuf_dynamic(size_t len, size_t max)
+{
+	struct ibuf	*buf;
+
+	if (max < len)
+		return (NULL);
+
+	if ((buf = ibuf_open(len)) == NULL)
+		return (NULL);
+
+	if (max > 0)
+		buf->max = max;
+
+	return (buf);
+}
+
+static int
+ibuf_realloc(struct ibuf *buf, size_t len)
+{
+	unsigned char	*b;
+
+	/* on static buffers max is eq size and so the following fails */
+	if (buf->wpos + len > buf->max) {
+		errno = ERANGE;
+		return (-1);
+	}
+
+	b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
+	if (b == NULL)
+		return (-1);
+	buf->buf = b;
+	buf->size = buf->wpos + len;
+
+	return (0);
+}
+
+int
+ibuf_add(struct ibuf *buf, const void *data, size_t len)
+{
+	if (buf->wpos + len > buf->size)
+		if (ibuf_realloc(buf, len) == -1)
+			return (-1);
+
+	memcpy(buf->buf + buf->wpos, data, len);
+	buf->wpos += len;
+	return (0);
+}
+
+void *
+ibuf_reserve(struct ibuf *buf, size_t len)
+{
+	void	*b;
+
+	if (buf->wpos + len > buf->size)
+		if (ibuf_realloc(buf, len) == -1)
+			return (NULL);
+
+	b = buf->buf + buf->wpos;
+	buf->wpos += len;
+	return (b);
+}
+
+void *
+ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
+{
+	/* only allowed to seek in already written parts */
+	if (pos + len > buf->wpos)
+		return (NULL);
+
+	return (buf->buf + pos);
+}
+
+size_t
+ibuf_size(struct ibuf *buf)
+{
+	return (buf->wpos);
+}
+
+size_t
+ibuf_left(struct ibuf *buf)
+{
+	return (buf->max - buf->wpos);
+}
+
+void
+ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+	ibuf_enqueue(msgbuf, buf);
+}
+
+int
+ibuf_write(struct msgbuf *msgbuf)
+{
+	struct iovec	 iov[IOV_MAX];
+	struct ibuf	*buf;
+	unsigned int	 i = 0;
+	ssize_t	n;
+
+	memset(&iov, 0, sizeof(iov));
+	TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+		if (i >= IOV_MAX)
+			break;
+		iov[i].iov_base = buf->buf + buf->rpos;
+		iov[i].iov_len = buf->wpos - buf->rpos;
+		i++;
+	}
+
+again:
+	if ((n = writev(msgbuf->fd, iov, i)) == -1) {
+		if (errno == EINTR)
+			goto again;
+		if (errno == ENOBUFS)
+			errno = EAGAIN;
+		return (-1);
+	}
+
+	if (n == 0) {			/* connection closed */
+		errno = 0;
+		return (0);
+	}
+
+	msgbuf_drain(msgbuf, n);
+
+	return (1);
+}
+
+void
+ibuf_free(struct ibuf *buf)
+{
+	if (buf == NULL)
+		return;
+	freezero(buf->buf, buf->size);
+	free(buf);
+}
+
+void
+msgbuf_init(struct msgbuf *msgbuf)
+{
+	msgbuf->queued = 0;
+	msgbuf->fd = -1;
+	TAILQ_INIT(&msgbuf->bufs);
+}
+
+void
+msgbuf_drain(struct msgbuf *msgbuf, size_t n)
+{
+	struct ibuf	*buf, *next;
+
+	for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
+	    buf = next) {
+		next = TAILQ_NEXT(buf, entry);
+		if (buf->rpos + n >= buf->wpos) {
+			n -= buf->wpos - buf->rpos;
+			ibuf_dequeue(msgbuf, buf);
+		} else {
+			buf->rpos += n;
+			n = 0;
+		}
+	}
+}
+
+void
+msgbuf_clear(struct msgbuf *msgbuf)
+{
+	struct ibuf	*buf;
+
+	while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
+		ibuf_dequeue(msgbuf, buf);
+}
+
+int
+msgbuf_write(struct msgbuf *msgbuf)
+{
+	struct iovec	 iov[IOV_MAX];
+	struct ibuf	*buf, *buf0 = NULL;
+	unsigned int	 i = 0;
+	ssize_t		 n;
+	struct msghdr	 msg;
+	struct cmsghdr	*cmsg;
+	union {
+		struct cmsghdr	hdr;
+		char		buf[CMSG_SPACE(sizeof(int))];
+	} cmsgbuf;
+
+	memset(&iov, 0, sizeof(iov));
+	memset(&msg, 0, sizeof(msg));
+	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
+	TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+		if (i >= IOV_MAX)
+			break;
+		if (i > 0 && buf->fd != -1)
+			break;
+		iov[i].iov_base = buf->buf + buf->rpos;
+		iov[i].iov_len = buf->wpos - buf->rpos;
+		i++;
+		if (buf->fd != -1)
+			buf0 = buf;
+	}
+
+	msg.msg_iov = iov;
+	msg.msg_iovlen = i;
+
+	if (buf0 != NULL) {
+		msg.msg_control = (caddr_t)&cmsgbuf.buf;
+		msg.msg_controllen = sizeof(cmsgbuf.buf);
+		cmsg = CMSG_FIRSTHDR(&msg);
+		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+		cmsg->cmsg_level = SOL_SOCKET;
+		cmsg->cmsg_type = SCM_RIGHTS;
+		*(int *)CMSG_DATA(cmsg) = buf0->fd;
+	}
+
+again:
+	if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
+		if (errno == EINTR)
+			goto again;
+		if (errno == ENOBUFS)
+			errno = EAGAIN;
+		return (-1);
+	}
+
+	if (n == 0) {			/* connection closed */
+		errno = 0;
+		return (0);
+	}
+
+	/*
+	 * assumption: fd got sent if sendmsg sent anything
+	 * this works because fds are passed one at a time
+	 */
+	if (buf0 != NULL) {
+		close(buf0->fd);
+		buf0->fd = -1;
+	}
+
+	msgbuf_drain(msgbuf, n);
+
+	return (1);
+}
+
+static void
+ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+	TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
+	msgbuf->queued++;
+}
+
+static void
+ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+	TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
+
+	if (buf->fd != -1)
+		close(buf->fd);
+
+	msgbuf->queued--;
+	ibuf_free(buf);
+}
+
+/* imsg.c */
+
+int	 imsg_fd_overhead = 0;
+
+static int	 imsg_get_fd(struct imsgbuf *);
+
+void
+imsg_init(struct imsgbuf *ibuf, int fd)
+{
+	msgbuf_init(&ibuf->w);
+	memset(&ibuf->r, 0, sizeof(ibuf->r));
+	ibuf->fd = fd;
+	ibuf->w.fd = fd;
+	ibuf->pid = getpid();
+	TAILQ_INIT(&ibuf->fds);
+}
+
+ssize_t
+imsg_read(struct imsgbuf *ibuf)
+{
+	struct msghdr		 msg;
+	struct cmsghdr		*cmsg;
+	union {
+		struct cmsghdr hdr;
+		char	buf[CMSG_SPACE(sizeof(int) * 1)];
+	} cmsgbuf;
+	struct iovec		 iov;
+	ssize_t			 n = -1;
+	int			 fd;
+	struct imsg_fd		*ifd;
+
+	memset(&msg, 0, sizeof(msg));
+	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
+
+	iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
+	iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = &cmsgbuf.buf;
+	msg.msg_controllen = sizeof(cmsgbuf.buf);
+
+	if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
+		return (-1);
+
+again:
+	if (getdtablecount() + imsg_fd_overhead +
+	    (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
+	    >= getdtablesize()) {
+		errno = EAGAIN;
+		free(ifd);
+		return (-1);
+	}
+
+	if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
+		if (errno == EINTR)
+			goto again;
+		goto fail;
+	}
+
+	ibuf->r.wpos += n;
+
+	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+	    cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+		if (cmsg->cmsg_level == SOL_SOCKET &&
+		    cmsg->cmsg_type == SCM_RIGHTS) {
+			int i;
+			int j;
+
+			/*
+			 * We only accept one file descriptor.  Due to C
+			 * padding rules, our control buffer might contain
+			 * more than one fd, and we must close them.
+			 */
+			j = ((char *)cmsg + cmsg->cmsg_len -
+			    (char *)CMSG_DATA(cmsg)) / sizeof(int);
+			for (i = 0; i < j; i++) {
+				fd = ((int *)CMSG_DATA(cmsg))[i];
+				if (ifd != NULL) {
+					ifd->fd = fd;
+					TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
+					    entry);
+					ifd = NULL;
+				} else
+					close(fd);
+			}
+		}
+		/* we do not handle other ctl data level */
+	}
+
+fail:
+	free(ifd);
+	return (n);
+}
+
+ssize_t
+imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
+{
+	size_t			 av, left, datalen;
+
+	av = ibuf->r.wpos;
+
+	if (IMSG_HEADER_SIZE > av)
+		return (0);
+
+	memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
+	if (imsg->hdr.len < IMSG_HEADER_SIZE ||
+	    imsg->hdr.len > MAX_IMSGSIZE) {
+		errno = ERANGE;
+		return (-1);
+	}
+	if (imsg->hdr.len > av)
+		return (0);
+	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+	ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
+	if (datalen == 0)
+		imsg->data = NULL;
+	else if ((imsg->data = malloc(datalen)) == NULL)
+		return (-1);
+
+	if (imsg->hdr.flags & IMSGF_HASFD)
+		imsg->fd = imsg_get_fd(ibuf);
+	else
+		imsg->fd = -1;
+
+	if (datalen != 0)
+		memcpy(imsg->data, ibuf->r.rptr, datalen);
+
+	if (imsg->hdr.len < av) {
+		left = av - imsg->hdr.len;
+		memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
+		ibuf->r.wpos = left;
+	} else
+		ibuf->r.wpos = 0;
+
+	return (datalen + IMSG_HEADER_SIZE);
+}
+
+int
+imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
+    int fd, const void *data, uint16_t datalen)
+{
+	struct ibuf	*wbuf;
+
+	if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
+		return (-1);
+
+	if (imsg_add(wbuf, data, datalen) == -1)
+		return (-1);
+
+	wbuf->fd = fd;
+
+	imsg_close(ibuf, wbuf);
+
+	return (1);
+}
+
+int
+imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
+    int fd, const struct iovec *iov, int iovcnt)
+{
+	struct ibuf	*wbuf;
+	int		 i, datalen = 0;
+
+	for (i = 0; i < iovcnt; i++)
+		datalen += iov[i].iov_len;
+
+	if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
+		return (-1);
+
+	for (i = 0; i < iovcnt; i++)
+		if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
+			return (-1);
+
+	wbuf->fd = fd;
+
+	imsg_close(ibuf, wbuf);
+
+	return (1);
+}
+
+/* ARGSUSED */
+struct ibuf *
+imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
+    uint16_t datalen)
+{
+	struct ibuf	*wbuf;
+	struct imsg_hdr	 hdr;
+
+	datalen += IMSG_HEADER_SIZE;
+	if (datalen > MAX_IMSGSIZE) {
+		errno = ERANGE;
+		return (NULL);
+	}
+
+	hdr.type = type;
+	hdr.flags = 0;
+	hdr.peerid = peerid;
+	if ((hdr.pid = pid) == 0)
+		hdr.pid = ibuf->pid;
+	if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
+		return (NULL);
+	}
+	if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
+		return (NULL);
+
+	return (wbuf);
+}
+
+int
+imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
+{
+	if (datalen)
+		if (ibuf_add(msg, data, datalen) == -1) {
+			ibuf_free(msg);
+			return (-1);
+		}
+	return (datalen);
+}
+
+void
+imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
+{
+	struct imsg_hdr	*hdr;
+
+	hdr = (struct imsg_hdr *)msg->buf;
+
+	hdr->flags &= ~IMSGF_HASFD;
+	if (msg->fd != -1)
+		hdr->flags |= IMSGF_HASFD;
+
+	hdr->len = (uint16_t)msg->wpos;
+
+	ibuf_close(&ibuf->w, msg);
+}
+
+void
+imsg_free(struct imsg *imsg)
+{
+	freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
+}
+
+static int
+imsg_get_fd(struct imsgbuf *ibuf)
+{
+	int		 fd;
+	struct imsg_fd	*ifd;
+
+	if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
+		return (-1);
+
+	fd = ifd->fd;
+	TAILQ_REMOVE(&ibuf->fds, ifd, entry);
+	free(ifd);
+
+	return (fd);
+}
+
+int
+imsg_flush(struct imsgbuf *ibuf)
+{
+	while (ibuf->w.queued)
+		if (msgbuf_write(&ibuf->w) <= 0)
+			return (-1);
+	return (0);
+}
+
+void
+imsg_clear(struct imsgbuf *ibuf)
+{
+	int	fd;
+
+	msgbuf_clear(&ibuf->w);
+	while ((fd = imsg_get_fd(ibuf)) != -1)
+		close(fd);
+}
+#endif /* HAVE_IMSG */
+#if !HAVE_MEMMEM
+/*-
+ * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+/*
+ * Find the first occurrence of the byte string s in byte string l.
+ */
+void *
+memmem(const void *l, size_t l_len, const void *s, size_t s_len)
+{
+	const char *cur, *last;
+	const char *cl = l;
+	const char *cs = s;
+
+	/* a zero length needle should just return the haystack */
+	if (l_len == 0)
+		return (void *)cl;
+
+	/* "s" must be smaller or equal to "l" */
+	if (l_len < s_len)
+		return NULL;
+
+	/* special case where s_len == 1 */
+	if (s_len == 1)
+		return memchr(l, *cs, l_len);
+
+	/* the last position where its possible to find "s" in "l" */
+	last = cl + l_len - s_len;
+
+	for (cur = cl; cur <= last; cur++)
+		if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
+			return (void *)cur;
+
+	return NULL;
+}
+#endif /* !HAVE_MEMMEM */
+#if !HAVE_MEMRCHR
+/*
+ * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 <string.h>
+
+/*
+ * Reverse memchr()
+ * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
+ */
+void *
+memrchr(const void *s, int c, size_t n)
+{
+    const unsigned char *cp;
+
+    if (n != 0) {
+        cp = (unsigned char *)s + n;
+        do {
+            if (*(--cp) == (unsigned char)c)
+                return((void *)cp);
+        } while (--n != 0);
+    }
+    return(NULL);
+}
+#endif /* !HAVE_MEMRCHR */
+#if !HAVE_OPTRESET
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *	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.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int	BSDopterr = 1,		/* if error message should be printed */
+	BSDoptind = 1,		/* index into parent argv vector */
+	BSDoptopt,		/* character checked for validity */
+	BSDoptreset;		/* reset getopt */
+char	*BSDoptarg;		/* argument associated with option */
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+BSDgetopt(int nargc, char *const *nargv, const char *ostr)
+{
+	static const char *place = EMSG;	/* option letter processing */
+	char *oli;				/* option letter list index */
+
+	if (ostr == NULL)
+		return (-1);
+
+	if (BSDoptreset || !*place) {		/* update scanning pointer */
+		BSDoptreset = 0;
+		if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
+			place = EMSG;
+			return (-1);
+		}
+		if (place[1] && *++place == '-') {	/* found "--" */
+			if (place[1])
+				return (BADCH);
+			++BSDoptind;
+			place = EMSG;
+			return (-1);
+		}
+	}					/* option letter okay? */
+	if ((BSDoptopt = (int)*place++) == (int)':' ||
+	    !(oli = strchr(ostr, BSDoptopt))) {
+		/*
+		 * if the user didn't specify '-' as an option,
+		 * assume it means -1.
+		 */
+		if (BSDoptopt == (int)'-')
+			return (-1);
+		if (!*place)
+			++BSDoptind;
+		if (BSDopterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "%s: unknown option -- %c\n", getprogname(),
+			    BSDoptopt);
+		return (BADCH);
+	}
+	if (*++oli != ':') {			/* don't need argument */
+		BSDoptarg = NULL;
+		if (!*place)
+			++BSDoptind;
+	}
+	else {					/* need an argument */
+		if (*place)			/* no white space */
+			BSDoptarg = (char *)place;
+		else if (nargc <= ++BSDoptind) {	/* no arg */
+			place = EMSG;
+			if (*ostr == ':')
+				return (BADARG);
+			if (BSDopterr)
+				(void)fprintf(stderr,
+				    "%s: option requires an argument -- %c\n",
+				    getprogname(), BSDoptopt);
+			return (BADCH);
+		}
+		else				/* white space */
+			BSDoptarg = nargv[BSDoptind];
+		place = EMSG;
+		++BSDoptind;
+	}
+	return (BSDoptopt);			/* dump back option letter */
+}
+#endif
+#if !HAVE_REALLOCARRAY
+/*
+ * 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);
+}
+#endif /* !HAVE_REALLOCARRAY */
+#if !HAVE_RECALLOCARRAY
+/*
+ * Copyright (c) 2008, 2017 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.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.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 *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+	size_t oldsize, newsize;
+	void *newptr;
+
+	if (ptr == NULL)
+		return calloc(newnmemb, size);
+
+	if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	newsize = newnmemb * size;
+
+	if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+		errno = EINVAL;
+		return NULL;
+	}
+	oldsize = oldnmemb * size;
+	
+	/*
+	 * Don't bother too much if we're shrinking just a bit,
+	 * we do not shrink for series of small steps, oh well.
+	 */
+	if (newsize <= oldsize) {
+		size_t d = oldsize - newsize;
+
+		if (d < oldsize / 2 && d < (size_t)getpagesize()) {
+			memset((char *)ptr + newsize, 0, d);
+			return ptr;
+		}
+	}
+
+	newptr = malloc(newsize);
+	if (newptr == NULL)
+		return NULL;
+
+	if (newsize > oldsize) {
+		memcpy(newptr, ptr, oldsize);
+		memset((char *)newptr + oldsize, 0, newsize - oldsize);
+	} else
+		memcpy(newptr, ptr, newsize);
+
+	explicit_bzero(ptr, oldsize);
+	free(ptr);
+
+	return newptr;
+}
+#endif /* !HAVE_RECALLOCARRAY */
+#if !HAVE_SETPROCTITLE
+/*
+ * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
+ *
+ * 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 MIND, 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.
+ */
+
+# if HAVE_PR_SET_NAME
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/prctl.h>
+void
+setproctitle(const char *fmt, ...)
+{
+	char	title[16], name[16], *cp;
+	va_list	ap;
+	int	used;
+
+	va_start(ap, fmt);
+	vsnprintf(title, sizeof(title), fmt, ap);
+	va_end(ap);
+
+	used = snprintf(name, sizeof(name), "%s: %s", getprogname(), title);
+	if (used >= (int)sizeof(name)) {
+		cp = strrchr(name, ' ');
+		if (cp != NULL)
+			*cp = '\0';
+	}
+	prctl(PR_SET_NAME, name);
+}
+# else
+void
+setproctitle(const char *fmt, ...)
+{
+	return;
+}
+# endif
+#endif /* !HAVE_SETPROCTITLE */
+#if !HAVE_STRLCAT
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (n-- != 0 && *d != '\0')
+		d++;
+	dlen = d - dst;
+	n = siz - dlen;
+
+	if (n == 0)
+		return(dlen + strlen(s));
+	while (*s != '\0') {
+		if (n != 1) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return(dlen + (s - src));	/* count does not include NUL */
+}
+#endif /* !HAVE_STRLCAT */
+#if !HAVE_STRLCPY
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0) {
+		while (--n != 0) {
+			if ((*d++ = *s++) == '\0')
+				break;
+		}
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
+#endif /* !HAVE_STRLCPY */
+#if !HAVE_STRNDUP
+/*	$OpenBSD$	*/
+/*
+ * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+strndup(const char *str, size_t maxlen)
+{
+	char *copy;
+	size_t len;
+
+	len = strnlen(str, maxlen);
+	copy = malloc(len + 1);
+	if (copy != NULL) {
+		(void)memcpy(copy, str, len);
+		copy[len] = '\0';
+	}
+
+	return copy;
+}
+#endif /* !HAVE_STRNDUP */
+#if !HAVE_STRNLEN
+/*	$OpenBSD$	*/
+
+/*
+ * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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>
+
+size_t
+strnlen(const char *str, size_t maxlen)
+{
+	const char *cp;
+
+	for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
+		;
+
+	return (size_t)(cp - str);
+}
+#endif /* !HAVE_STRNLEN */
+#if !HAVE_STRTONUM
+/*
+ * 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);
+}
+#endif /* !HAVE_STRTONUM */
blob - /dev/null
blob + 979457af0604a374897fc0ff068d7dde6bc7aa18 (mode 755)
--- /dev/null
+++ configure
@@ -0,0 +1,941 @@
+#! /bin/sh
+#
+# Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
+# Copyright (c) 2017, 2018 Kristaps Dzonsons <kristaps@bsd.lv>
+#
+# 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.
+
+OCONFIGURE_VERSION="0.3.8"
+
+#
+# This script outputs two files: config.h and Makefile.configure.
+# It tries to read from configure.local, which contains predefined
+# values we won't autoconfigure.
+#
+# If you want to use configure with your project, have your GNUmakefile
+# or BSDmakefile---whichever---try to import/include Makefile.configure
+# at the beginning of the file.
+#
+# Like so (note no quotes, no period, etc.):
+#
+#   include Makefile.configure
+#
+# If it exists, configure was run; otherwise, it wasn't.
+#
+# You'll probably want to change parts of this file.  I've noted the
+# parts that you'll probably change in the section documentation.
+#
+# See https://github.com/kristapsdz/oconfigure for more.
+
+set -e
+
+# try to be helpful
+case "$1" in
+--help|-h)
+	cat <<EOF
+\`configure' configures amused to adapt to many kinds of systems.
+
+Usage: $0 [-h] [--prefix=path] [VAR=VALUE]...
+
+The options are as follows:
+
+    -h, --help     print this help message
+
+    --prefix=path  equivalent to specifying the PREFIX variable, supported
+                   for compatibility with other common "configure" scripts.
+
+Variables available:
+
+    LDADD                  generic linker flags
+    LDADD_IMSG             linker flags for libimsg
+    LDADD_LIBEVENT         linker flags for libevent
+    LDADD_LIBEVENT2        linker flags for libevent2
+    LDADD_LIBFLAC          linker flags for libflac
+    LDADD_LIBMPG123        linker flags for libmpg123
+    LDADD_LIBOPUSFILE      linker flags for libopusfile
+    LDADD_LIBVORBISFILE    linker flags for libvorbisfile
+    LDADD_SNDIO            linker flags for libsndio
+    LDADD_LIBSOCKET        linker flags for libsocket
+    LDFLAGS                extra linker flags
+    CPPFLAGS               C preprocessors flags
+    DESTDIR                destination directory
+    PREFIX                 where to install files
+    MANDIR                 where to install man pages (PREFIX/man)
+    LIBDIR                 where to install libraries (PREFIX/lib)
+    BINDIR                 where to install executables (PREFIX/bin)
+    SHAREDIR               where to install misc files (PREFIX/share)
+    SBINDIR                where to install system executables (PREFIX/sbin)
+    INCLUDEDIR             where to install header files (PREFIX/include)
+    PKG_CONFIG             path to the pkg-config program or empty to disable
+
+EOF
+	exit 0 ;;
+esac
+
+#----------------------------------------------------------------------
+# Prepare for running: move aside previous configure runs.
+# Output file descriptor usage:
+#  1 (stdout): config.h or Makefile.configure
+#  2 (stderr): original stderr, usually to the console
+#  3: config.log
+# You DO NOT want to change this.
+#----------------------------------------------------------------------
+
+[ -w config.log ] && mv config.log config.log.old
+[ -w config.h   ] && mv config.h config.h.old
+
+exec 3> config.log
+echo "config.log: writing..."
+
+# GNU submake prints different output if invoked recursively, which
+# messes up CC and CFLAGS detection.  Pass --no-print-directory if
+# we have a MAKELEVEL (GNU and FreeBSD make) and the argument is
+# allowed.
+
+MAKE_FLAGS=""
+
+if [ -n "${MAKELEVEL}" ]; then
+	if [ "${MAKELEVEL}" -gt 0 ] ; then
+		MAKE_FLAGS="--no-print-directory"
+		echo "all:" | make ${MAKE_FLAGS} -sf - 2>/dev/null || MAKE_FLAGS=""
+	fi
+fi
+
+if [ -n "$MAKE_FLAGS" ]; then
+	echo "GNU submake detected: using --no-print-directory" 1>&2
+	echo "GNU submake detected: using --no-print-directory" 1>&3
+fi
+
+#----------------------------------------------------------------------
+# Initialize all variables here such that nothing can leak in from the
+# environment except for CC and CFLAGS, which we might have passed in.
+#----------------------------------------------------------------------
+
+CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make ${MAKE_FLAGS} -sf -`
+CFLAGS=`printf "all:\\n\\t@echo \\\$(CFLAGS)\\n" | make ${MAKE_FLAGS} -sf -`
+CFLAGS="${CFLAGS} -g -W -Wall -Wmissing-prototypes -Wstrict-prototypes"
+CFLAGS="${CFLAGS} -Wmissing-declarations -Wno-unused-parameter"
+CFLAGS="${CFLAGS} -Wno-sign-compare"
+LDADD=
+LDADD_IMSG=
+LDADD_LIBEVENT=
+LDADD_LIBEVENT2=
+LDADD_LIB_FLAC=
+LDADD_LIB_MPG123=
+LDADD_LIB_VORBISFILE=
+LDADD_LIB_SNDIO=
+LDADD_LIB_SOCKET=
+LDADD_STATIC=
+CPPFLAGS=
+LDFLAGS=
+DESTDIR=
+PREFIX="/usr/local"
+BINDIR=
+SBINDIR=
+INCLUDEDIR=
+LIBDIR=
+MANDIR=
+SHAREDIR=
+INSTALL="install"
+INSTALL_PROGRAM=
+INSTALL_LIB=
+INSTALL_MAN=
+INSTALL_DATA=
+PKG_CONFIG=
+
+# SunOS sets "cc", but this doesn't exist.
+# It does have gcc, so try that instead.
+# Prefer clang, though.
+
+command -v ${CC} 2>/dev/null 1>&2 || {
+	echo "${CC} not found: trying clang" 1>&2
+	echo "${CC} not found: trying clang" 1>&3
+	CC=clang
+	command -v ${CC} 2>/dev/null 1>&2 || {
+		echo "${CC} not found: trying gcc" 1>&2
+		echo "${CC} not found: trying gcc" 1>&3
+		CC=gcc
+		command -v ${CC} 2>/dev/null 1>&2 || {
+			echo "gcc not found: giving up" 1>&2
+			echo "gcc not found: giving up" 1>&3
+			exit 1
+		}
+	}
+}
+
+command -v pkg-config 2>/dev/null 1>&2 && {
+	PKG_CONFIG=pkg-config
+	echo "pkg-config found" 1>&2
+	echo "pkg-config found" 1>&3
+} || {
+	echo "pkg-config not found" 1>&2
+	echo "pkg-config not found" 1>&3
+}
+
+#----------------------------------------------------------------------
+# Allow certain variables to be overriden on the command line.
+#----------------------------------------------------------------------
+
+while [ $# -gt 0 ]; do
+	key=${1%%=*}
+	val=${1#*=}
+
+	if [ "$key" = "--prefix" ]; then
+		key=PREFIX
+		if [ "$1" = "--prefix" ]; then
+			if ! shift 2>&1 >/dev/null; then
+				echo "$0: missing value for --prefix" 1>&2
+				exit 1
+			fi
+			val="$1"
+		fi
+	fi
+
+	if [ "$1" = "$key" ]; then
+		echo "$0: invalid key-value: $1" 1>&2
+		exit 1
+	fi
+
+	shift
+
+	case "$key" in
+	LDADD)
+		LDADD="$val" ;;
+	LDADD_IMSG)
+		LDADD_IMSG="$val" ;;
+	LDADD_LIBEVENT)
+		LDADD_LIBEVENT="$val" ;;
+	LDADD_LIBEVENT2)
+		LDADD_LIBEVENT2="$val" ;;
+	LDADD_LIBFLAC)
+		LDADD_LIBFLAC="$val" ;;
+	LDADD_LIBMPG123)
+		LDADD_LIBMPG123="$val" ;;
+	LDADD_LIBOPUSFILE)
+		LDADD_LIBOPUSFILE="$val" ;;
+	LDADD_LIBVORBISFILE)
+		LDADD_LIBVORBISFILE="$val" ;;
+	LDADD_SNDIO)
+		LDADD_SNDIO="$val" ;;
+	LDADD_LIBSOCKET)
+		LDADD_LIBSOCKET="$val" ;;
+	LDFLAGS)
+		LDFLAGS="$val" ;;
+	CPPFLAGS)
+		CPPFLAGS="$val" ;;
+	DESTDIR)
+		DESTDIR="$val" ;;
+	PREFIX)
+		PREFIX="$val" ;;
+	MANDIR)
+		MANDIR="$val" ;;
+	LIBDIR)
+		LIBDIR="$val" ;;
+	BINDIR)
+		BINDIR="$val" ;;
+	SHAREDIR)
+		SHAREDIR="$val" ;;
+	SBINDIR)
+		SBINDIR="$val" ;;
+	INCLUDEDIR)
+		INCLUDEDIR="$val" ;;
+	PKG_CONFIG)
+		PKG_CONFIG="$val" ;;
+	*)
+		echo "$0: invalid key: $key" 1>&2
+		exit 1
+	esac
+done
+
+
+#----------------------------------------------------------------------
+# These are the values that will be pushed into config.h after we test
+# for whether they're supported or not.
+# Each of these must have a runtest(), below.
+# Please sort by alpha, for clarity.
+# You WANT to change this.
+#----------------------------------------------------------------------
+
+HAVE_CAPSICUM=
+HAVE_ERR=
+HAVE_EXPLICIT_BZERO=
+HAVE_FLOCK=
+HAVE_FREEZERO=
+HAVE_GETDTABLECOUNT=
+HAVE_GETEXECNAME=
+HAVE_GETPROGNAME=
+HAVE_INFTIM=
+HAVE_IMSG=
+HAVE_LANDLOCK=
+HAVE_LIBEVENT=
+HAVE_LIBEVENT2=0		# may not be checked, set to zero
+HAVE_LIB_FLAC=
+HAVE_LIB_MPG123=
+HAVE_LIB_OPUSFILE=
+HAVE_LIB_VORBISFILE=
+HAVE_LIB_SNDIO=
+HAVE_LIB_SOCKET=
+HAVE_MEMMEM=
+HAVE_MEMRCHR=
+HAVE_MEMSET_S=
+HAVE_OPTRESET=
+HAVE_PATH_MAX=
+HAVE_PLEDGE=
+HAVE_PROGRAM_INVOCATION_SHORT_NAME=
+HAVE_PR_SET_NAME=
+HAVE_REALLOCARRAY=
+HAVE_RECALLOCARRAY=
+HAVE_SANDBOX_INIT=
+HAVE_SETPROCTITLE=
+HAVE_SIO_FLUSH=
+HAVE_SOCK_NONBLOCK=
+HAVE_STRLCAT=
+HAVE_STRLCPY=
+HAVE_STRNDUP=
+HAVE_STRNLEN=
+HAVE_STRTONUM=
+HAVE_SYS_FILE=
+HAVE_SYS_QUEUE=
+HAVE_SYSTRACE=0
+HAVE_UNVEIL=
+HAVE___PROGNAME=
+
+#----------------------------------------------------------------------
+# Allow configure.local to override all variables, default settings,
+# command-line arguments, and tested features, above.
+# You PROBABLY DO NOT want to change this.
+#----------------------------------------------------------------------
+
+if [ -r ./configure.local ]; then
+	echo "configure.local: reading..." 1>&2
+	echo "configure.local: reading..." 1>&3
+	cat ./configure.local 1>&3
+	. ./configure.local
+else
+	echo "configure.local: no (fully automatic configuration)" 1>&2
+	echo "configure.local: no (fully automatic configuration)" 1>&3
+fi
+
+echo 1>&3
+
+#----------------------------------------------------------------------
+# Infrastructure for running tests.
+# These consists of a series of functions that will attempt to run the
+# given test file and record its exit into a HAVE_xxx variable.
+# You DO NOT want to change this.
+#----------------------------------------------------------------------
+
+COMP="${CC} ${CFLAGS} ${CPPFLAGS} -Wno-unused -Werror"
+
+# Check whether this HAVE_ setting is manually overridden.
+# If yes, use the override, if no, do not decide anything yet.
+# Arguments: lower-case test name, manual value
+
+ismanual() {
+	[ -z "${3}" ] && return 1
+	echo "${1}: manual (HAVE_${2}=${3})" 1>&2
+	echo "${1}: manual (HAVE_${2}=${3})" 1>&3
+	echo 1>&3
+	return 0
+}
+
+# Run a single autoconfiguration test.
+# In case of success, enable the feature.
+# In case of failure, do not decide anything yet.
+# Arguments: lower-case test name, upper-case test name, additional
+# CFLAGS, additional LIBS.
+
+singletest() {
+	extralib=""
+	pkgcfs=""
+	pkglib=""
+
+	cat 1>&3 << __HEREDOC__
+${1}: testing...
+${COMP} -DTEST_${2} ${3} -o test-${1} tests.c ${LDFLAGS} ${4}
+__HEREDOC__
+	if ${COMP} -DTEST_${2} ${3} -o "test-${1}" tests.c ${LDFLAGS} ${4} 1>&3 2>&3; then
+		echo "${1}: ${CC} succeeded" 1>&3
+	else
+		if [ -n "${5}" ] ; then
+			echo "${1}: ${CC} failed with $? (retrying)" 1>&3
+			cat 1>&3 << __HEREDOC__
+${1}: testing...
+${COMP} -DTEST_${2} ${3} -o test-${1} tests.c ${LDFLAGS} ${5}
+__HEREDOC__
+			if ${COMP} -DTEST_${2} ${3} -o "test-${1}" tests.c ${LDFLAGS} ${5} 1>&3 2>&3; then
+				echo "${1}: ${CC} succeeded" 1>&3
+				extralib="(with ${5})"
+			else
+				test -n "${PKG_CONFIG}" -a -n "${6}" && ${PKG_CONFIG} "$6"
+				if [ $? -eq 0 ]; then
+					echo "${1}: ${CC} failed with $? (retrying)" 1>&3
+					pkgcfs=$($PKG_CONFIG --cflags "${6}")
+					pkglib=$($PKG_CONFIG --libs "${6}")
+					cat 1>&3 << __HEREDOC__
+${1}: testing...
+${COMP} -DTEST_${2} ${3} ${pkgcfs} -o test-${1} tests.c ${LDFLAGS} ${pkglib}
+__HEREDOC__
+					if ${COMP} -DTEST_${2} ${3} ${pkgcfs} -o test-${1} tests.c ${LDFLAGS} ${pkglib} 1>&3 2>&3; then
+						echo "${1}: ${CC} succeeded" 1>&3
+						extralib="(with ${pkgcfs} ${pkglib})"
+					else
+						echo "${1}: ${CC} failed with $?" 1>&3
+						echo 1>&3
+						return 1
+					fi
+				else
+					echo "${1}: ${CC} failed with $?" 1>&3
+					echo 1>&3
+					return 1
+				fi
+			fi
+		else
+			echo "${1}: ${CC} failed with $?" 1>&3
+			echo 1>&3
+			return 1
+		fi
+	fi
+
+	if [ -n "${pkgcfs}" -o -n "${pkglib}" ]
+	then
+		CFLAGS="${CFLAGS} ${pkgcfs}"
+		eval "LDADD_${2}=\"${pkglib}\""
+	elif [ -n "${extralib}" ]
+	then
+		eval "LDADD_${2}=\"${5}\""
+	elif [ -n "${4}" ]
+	then
+		eval "LDADD_${2}=\"${4}\""
+	fi
+
+	echo "${1}: yes ${extralib}" 1>&2
+	echo "${1}: yes ${extralib}" 1>&3
+	echo 1>&3
+	eval HAVE_${2}=1
+	rm "test-${1}"
+	return 0
+}
+
+# Run a complete autoconfiguration test, including the check for
+# a manual override and disabling the feature on failure.
+# Arguments: lower case name, upper case name, additional CFLAGS,
+# additional LDADD, alternative LDADD, pkg-config name.
+
+runtest() {
+	eval _manual=\${HAVE_${2}}
+	ismanual "${1}" "${2}" "${_manual}" && return 0
+	singletest "${1}" "${2}" "${3}" "${4}" "${5}" "${6}" && return 0
+	echo "${1}: no" 1>&2
+	eval HAVE_${2}=0
+	return 1
+}
+
+#----------------------------------------------------------------------
+# Begin running the tests themselves.
+# All of your tests must be defined here.
+# Please sort as the HAVE_xxxx values were defined.
+# You WANT to change this.
+# It consists of the following columns:
+#    runtest
+#    (1) test file
+#    (2) macro to set
+#    (3) argument to cc *before* -o
+#    (4) argument to cc *after*
+#    (5) alternative argument to cc *after*
+#    (6) name for pkg-config auto-discovery
+#----------------------------------------------------------------------
+
+if runtest -MMD _MMD -MMD; then
+	CFLAGS="${CFLAGS} -MMD"
+	echo "adding -MMD to CFLAGS" 1>&2
+	echo "adding -MMD to CFLAGS" 1>&3
+fi
+
+runtest capsicum	CAPSICUM			  || true
+runtest err		ERR				  || true
+runtest explicit_bzero	EXPLICIT_BZERO			  || true
+runtest flock		FLOCK				  || true
+runtest freezero	FREEZERO			  || true
+runtest getdtablecount	GETDTABLECOUNT			  || true
+runtest getexecname	GETEXECNAME			  || true
+runtest getprogname	GETPROGNAME			  || true
+runtest imsg		IMSG "" "" "-lutil"		  || true
+runtest INFTIM		INFTIM				  || true
+runtest landlock	LANDLOCK			  || true
+
+runtest libevent	LIBEVENT "" "" "-levent"	  || \
+runtest libevent2	LIBEVENT2 "" "" "-levent_extra -levent_core" "libevent" || true
+
+runtest lib_flac	LIB_FLAC "" "" "-lFLAC" "flac"	  || true
+runtest lib_mpg123	LIB_MPG123 "" "" "-lmpg123" "libmpg123" || true
+runtest lib_opusfile	LIB_OPUSFILE "" "" "-lopusfile"	"opusfile"  || true
+runtest lib_vorbisfile	LIB_VORBISFILE "" "" "-lvorbisfile" "vorbisfile" || true
+
+runtest lib_sndio	LIB_SNDIO "" "" "-lsndio" "sndio" || true
+runtest lib_socket	LIB_SOCKET "" "" "-lsocket -lnsl" || true
+runtest memmem		MEMMEM			  	  || true
+runtest memrchr		MEMRCHR			  	  || true
+runtest memset_s	MEMSET_S			  || true
+runtest optreset	OPTRESET			  || true
+runtest PATH_MAX	PATH_MAX			  || true
+runtest pledge		PLEDGE				  || true
+runtest program_invocation_short_name	PROGRAM_INVOCATION_SHORT_NAME || true
+runtest PR_SET_NAME	PR_SET_NAME			  || true
+runtest reallocarray	REALLOCARRAY			  || true
+runtest recallocarray	RECALLOCARRAY			  || true
+runtest sandbox_init	SANDBOX_INIT	"-Wno-deprecated" || true
+runtest setproctitle	SETPROCTITLE			  || true
+runtest sio_flush	SIO_FLUSH "" "" "${LDADD_LIB_SNDIO}" || true
+runtest SOCK_NONBLOCK	SOCK_NONBLOCK			  || true
+runtest static		STATIC "" "-static"		  || true
+runtest strlcat		STRLCAT				  || true
+runtest strlcpy		STRLCPY				  || true
+runtest strndup		STRNDUP				  || true
+runtest strnlen		STRNLEN				  || true
+runtest strtonum	STRTONUM			  || true
+runtest sys_queue	SYS_QUEUE			  || true
+runtest sys_file	SYS_FILE			  || true
+runtest unveil		UNVEIL				  || true
+runtest __progname	__PROGNAME			  || true
+
+if [ "${HAVE_LIBEVENT}" -eq 0 -a "${HAVE_LIBEVENT2}" -eq 0 ]; then
+	echo "Fatal: missing libevent" 1>&2
+	echo "Fatal: missing libevent" 1>&3
+	exit 1
+fi
+
+if [ "${HAVE_LIB_FLAC}" -eq 0 -o \
+     "${HAVE_LIB_MPG123}" -eq 0 -o \
+     "${HAVE_LIB_OPUSFILE}" -eq 0 -o \
+     "${HAVE_LIB_VORBISFILE}" -eq 0 ]; then
+	echo "Fatal: missing required audio libraries" 1>&2
+	echo "Fatal: missing required audio libraries" 1>&3
+	exit 1
+fi
+
+if [ "${HAVE_LIB_SNDIO}" -eq 0 ]; then
+	echo "Fatal: missing libsndio" 1>&2
+	echo "Fatal: missing libsndio" 1>&3
+	exit 1
+fi
+
+#----------------------------------------------------------------------
+# Output writing: generate the config.h file.
+# This file contains all of the HAVE_xxxx variables necessary for
+# compiling your source.
+# You must include "config.h" BEFORE any other variables.
+# You WANT to change this.
+#----------------------------------------------------------------------
+
+exec > config.h
+
+# Start with prologue.
+
+cat << __HEREDOC__
+#ifndef OCONFIGURE_CONFIG_H
+#define OCONFIGURE_CONFIG_H
+
+#ifdef __cplusplus
+# error "Do not use C++: this is a C application."
+#endif
+#if !defined(__GNUC__) || (__GNUC__ < 4)
+# define __attribute__(x)
+#endif
+#if defined(__linux__) || defined(__MINT__)
+# define _GNU_SOURCE /* memmem, memrchr, setresuid... */
+# define _DEFAULT_SOURCE /* le32toh, crypt, ... */
+#endif
+#if defined(__NetBSD__)
+# define _OPENBSD_SOURCE /* reallocarray, etc. */
+#endif
+#if defined(__sun)
+# ifndef _XOPEN_SOURCE /* SunOS already defines */
+#  define _XOPEN_SOURCE /* XPGx */
+# endif
+# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */
+# ifndef __EXTENSIONS__ /* SunOS already defines */
+#  define __EXTENSIONS__ /* reallocarray, etc. */
+# endif
+#endif
+#if !defined(__BEGIN_DECLS)
+# define __BEGIN_DECLS
+#endif
+#if !defined(__END_DECLS)
+# define __END_DECLS
+#endif
+
+__HEREDOC__
+
+# This is just for size_t, mode_t, and dev_t.
+# Most of these functions, in the real world, pull in <string.h> or
+# someting that pulls in support for size_t.
+# Our function declarations are standalone, so specify them here.
+
+if [ ${HAVE_IMSG} -eq 0 -o \
+     ${HAVE_MEMMEM} -eq 0 -o \
+     ${HAVE_MEMRCHR} -eq 0 -o \
+     ${HAVE_REALLOCARRAY} -eq 0 -o \
+     ${HAVE_RECALLOCARRAY} -eq 0 -o \
+     ${HAVE_STRLCAT} -eq 0 -o \
+     ${HAVE_STRLCPY} -eq 0 -o \
+     ${HAVE_STRNDUP} -eq 0 -o \
+     ${HAVE_STRNLEN} -eq 0 ]
+then
+	echo "#include <sys/types.h> /* size_t, mode_t, dev_t */ "
+	echo
+fi
+
+if [ ${HAVE_FLOCK} -eq 0 ]; then
+	if [ ${HAVE_SYS_FILE} -eq 0 ]; then
+		HAVE_FLOCK=1
+		echo "#include <sys/file.h>"
+		echo
+	else
+		echo "int flock(int, int);"
+		echo "#define LOCK_SH 0x1"
+		echo "#define LOCK_EX 0x2"
+		echo "#define LOCK_NB 0x4"
+		echo
+	fi
+fi
+
+if [ ${HAVE_ERR} -eq 0 ]; then
+	echo "#include <stdarg.h> /* err(3) */"
+	echo
+else
+	echo "#include <err.h>"
+	echo
+fi
+
+if [ ${HAVE_PLEDGE} -eq 0 ]; then
+	echo "#define pledge(p, e) (0)"
+	echo
+else
+	echo "#include <unistd.h>"
+	echo
+fi
+
+# Now we handle our HAVE_xxxx values.
+# Most will just be defined as 0 or 1.
+
+if [ ${HAVE_PATH_MAX} -eq 0 ]
+then
+	echo "#define PATH_MAX 4096"
+	echo
+fi
+
+if [ ${HAVE_INFTIM} -eq 0 ]
+then
+	echo "#define INFTIM (-1) /* poll.h */"
+	echo
+fi
+
+cat << __HEREDOC__
+/*
+ * Results of configuration feature-testing.
+ */
+#define HAVE_CAPSICUM ${HAVE_CAPSICUM}
+#define HAVE_ERR ${HAVE_ERR}
+#define HAVE_EXPLICIT_BZERO ${HAVE_EXPLICIT_BZERO}
+#define HAVE_FLOCK ${HAVE_FLOCK}
+#define HAVE_FREEZERO ${HAVE_FREEZERO}
+#define HAVE_GETDTABLECOUNT ${HAVE_GETDTABLECOUNT}
+#define HAVE_GETEXECNAME ${HAVE_GETEXECNAME}
+#define HAVE_GETPROGNAME ${HAVE_GETPROGNAME}
+#define HAVE_INFTIM ${HAVE_INFTIM}
+#define HAVE_LANDLOCK ${HAVE_LANDLOCK}
+#define HAVE_MEMMEM ${HAVE_MEMMEM}
+#define HAVE_MEMRCHR ${HAVE_MEMRCHR}
+#define HAVE_MEMSET_S ${HAVE_MEMSET_S}
+#define HAVE_OPTRESET ${HAVE_OPTRESET}
+#define HAVE_PATH_MAX ${HAVE_PATH_MAX}
+#define HAVE_PLEDGE ${HAVE_PLEDGE}
+#define HAVE_PROGRAM_INVOCATION_SHORT_NAME ${HAVE_PROGRAM_INVOCATION_SHORT_NAME}
+#define HAVE_PR_SET_NAME ${HAVE_PR_SET_NAME}
+#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY}
+#define HAVE_RECALLOCARRAY ${HAVE_RECALLOCARRAY}
+#define HAVE_SANDBOX_INIT ${HAVE_SANDBOX_INIT}
+#define HAVE_SETPROCTITLE ${HAVE_SETPROCTITLE}
+#define HAVE_SIO_FLUSH ${HAVE_SIO_FLUSH}
+#define HAVE_SOCK_NONBLOCK ${HAVE_SOCK_NONBLOCK}
+#define HAVE_STRLCAT ${HAVE_STRLCAT}
+#define HAVE_STRLCPY ${HAVE_STRLCPY}
+#define HAVE_STRNDUP ${HAVE_STRNDUP}
+#define HAVE_STRNLEN ${HAVE_STRNLEN}
+#define HAVE_STRTONUM ${HAVE_STRTONUM}
+#define HAVE_SYS_FILE ${HAVE_SYS_FILE}
+#define HAVE_SYS_QUEUE ${HAVE_SYS_QUEUE}
+#define HAVE_SYSTRACE ${HAVE_SYSTRACE}
+#define HAVE_UNVEIL ${HAVE_UNVEIL}
+#define HAVE___PROGNAME ${HAVE___PROGNAME}
+
+__HEREDOC__
+
+# Now we do our function declarations for missing functions.
+
+[ ${HAVE_ERR} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility functions for err(3).
+ */
+extern void err(int, const char *, ...) __attribute__((noreturn));
+extern void errc(int, int, const char *, ...) __attribute__((noreturn));
+extern void errx(int, const char *, ...) __attribute__((noreturn));
+extern void verr(int, const char *, va_list) __attribute__((noreturn));
+extern void verrc(int, int, const char *, va_list) __attribute__((noreturn));
+extern void verrx(int, const char *, va_list) __attribute__((noreturn));
+extern void warn(const char *, ...);
+extern void warnx(const char *, ...);
+extern void warnc(int, const char *, ...);
+extern void vwarn(const char *, va_list);
+extern void vwarnc(int, const char *, va_list);
+extern void vwarnx(const char *, va_list);
+__HEREDOC__
+
+[ ${HAVE_EXPLICIT_BZERO} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for explicit_bzero(3).
+ */
+extern void explicit_bzero(void *, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_FREEZERO} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for freezero(3).
+ */
+extern void freezero(void *, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_MEMMEM} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for memmem(3).
+ */
+void *memmem(const void *, size_t, const void *, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_MEMRCHR} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for memrchr(3).
+ */
+void *memrchr(const void *b, int, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_GETPROGNAME} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for getprogname(3).
+ */
+extern const char *getprogname(void);
+
+__HEREDOC__
+
+[ ${HAVE_REALLOCARRAY} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for reallocarray(3).
+ */
+extern void *reallocarray(void *, size_t, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_RECALLOCARRAY} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for recallocarray(3).
+ */
+extern void *recallocarray(void *, size_t, size_t, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_SETPROCTITLE} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for setproctitle(3).
+ */
+extern void setproctitle(const char *, ...);
+
+__HEREDOC__
+
+[ ${HAVE_STRLCAT} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for strlcat(3).
+ */
+extern size_t strlcat(char *, const char *, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_STRLCPY} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for strlcpy(3).
+ */
+extern size_t strlcpy(char *, const char *, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_STRNDUP} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for strndup(3).
+ */
+extern char *strndup(const char *, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_STRNLEN} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for strnlen(3).
+ */
+extern size_t strnlen(const char *, size_t);
+
+__HEREDOC__
+
+[ ${HAVE_STRTONUM} -eq 0 ] && \
+	cat << __HEREDOC__
+/*
+ * Compatibility for strotnum(3).
+ */
+extern long long strtonum(const char *, long long, long long, const char **);
+
+__HEREDOC__
+
+if [ ${HAVE_SYS_QUEUE} -eq 0 ]; then
+	cat << __HEREDOC__
+#include "queue.h"
+__HEREDOC__
+else
+	echo "#include <sys/queue.h>"
+	echo
+fi
+
+echo "#include <sys/uio.h>"
+echo "#include <stdint.h>"
+if [ ${HAVE_IMSG} -eq 0 ]; then
+	echo "#include \"imsg.h\""
+else
+	echo "#include <imsg.h>"
+fi
+echo
+
+if [ "${HAVE_LIBEVENT2}" -eq 1 ]; then
+	cat << __HEREDOC__
+#include <event2/event.h>
+#include <event2/event_compat.h>
+#include <event2/event_struct.h>
+#include <event2/buffer.h>
+#include <event2/buffer_compat.h>
+#include <event2/bufferevent.h>
+#include <event2/bufferevent_struct.h>
+#include <event2/bufferevent_compat.h>
+
+__HEREDOC__
+elif [ "${HAVE_LIBEVENT}" -eq 1 ]; then
+	cat << __HEREDOC__
+#include <event.h>
+
+__HEREDOC__
+fi
+
+cat << __HEREDOC__
+#ifndef __dead
+# define __dead __attribute__((noreturn))
+#endif
+
+#if !HAVE_SIO_FLUSH
+#define sio_flush(hdl) (sio_stop(hdl))
+#endif
+
+#if !HAVE_GETDTABLECOUNT
+/* XXX: on linux it should be possible to inspect /proc/self/fd/ */
+#define getdtablecount() (0)
+#endif
+
+#if !HAVE_OPTRESET
+/* replace host' getopt with OpenBSD' one */
+#define opterr		BSDopterr
+#define optind		BSDoptind
+#define optopt		BSDoptopt
+#define optreset	BSDoptreset
+#define optarg		BSDoptarg
+#define getopt		BSDgetopt
+
+extern int BSDopterr, BSDoptind, BSDoptopt, BSDoptreset;
+extern char *BSDoptarg;
+#endif
+
+#endif /*!OCONFIGURE_CONFIG_H*/
+__HEREDOC__
+
+echo "config.h: written" 1>&2
+echo "config.h: written" 1>&3
+
+#----------------------------------------------------------------------
+# Now we go to generate our Makefile.configure.
+# This file is simply a bunch of Makefile variables.
+# They'll work in both GNUmakefile and BSDmakefile.
+# You MIGHT want to change this.
+#----------------------------------------------------------------------
+
+exec > Makefile.configure
+
+[ -z "${BINDIR}"     ] && BINDIR="${PREFIX}/bin"
+[ -z "${SBINDIR}"    ] && SBINDIR="${PREFIX}/sbin"
+[ -z "${INCLUDEDIR}" ] && INCLUDEDIR="${PREFIX}/include"
+[ -z "${LIBDIR}"     ] && LIBDIR="${PREFIX}/lib"
+[ -z "${MANDIR}"     ] && MANDIR="${PREFIX}/man"
+[ -z "${SHAREDIR}"   ] && SHAREDIR="${PREFIX}/share"
+
+[ -z "${INSTALL_PROGRAM}" ] && INSTALL_PROGRAM="${INSTALL} -m 0555"
+[ -z "${INSTALL_LIB}"     ] && INSTALL_LIB="${INSTALL} -m 0444"
+[ -z "${INSTALL_MAN}"     ] && INSTALL_MAN="${INSTALL} -m 0444"
+[ -z "${INSTALL_DATA}"    ] && INSTALL_DATA="${INSTALL} -m 0444"
+
+cat << __HEREDOC__
+CC		 = ${CC}
+CFLAGS		 = ${CFLAGS}
+CPPFLAGS	 = ${CPPFLAGS}
+LDADD		 = ${LDADD} ${LDADD_IMSG} ${LDADD_LIB_FLAC} ${LDADD_LIB_MPG123} \
+		   ${LDADD_LIB_OPUSFILE} ${LDADD_LIB_VORBISFILE} ${LDADD_LIB_SOCKET} \
+		   ${LDADD_LIBEVENT} ${LDADD_LIBEVENT2} ${LDADD_LIB_SNDIO}
+LDADD_STATIC	 = ${LDADD_STATIC}
+LDFLAGS		 = ${LDFLAGS}
+STATIC		 = ${STATIC}
+PREFIX		 = ${PREFIX}
+BINDIR		 = ${BINDIR}
+SHAREDIR	 = ${SHAREDIR}
+SBINDIR		 = ${SBINDIR}
+INCLUDEDIR	 = ${INCLUDEDIR}
+LIBDIR		 = ${LIBDIR}
+MANDIR		 = ${MANDIR}
+INSTALL		 = ${INSTALL}
+INSTALL_PROGRAM	 = ${INSTALL_PROGRAM}
+INSTALL_LIB	 = ${INSTALL_LIB}
+INSTALL_MAN	 = ${INSTALL_MAN}
+INSTALL_DATA	 = ${INSTALL_DATA}
+__HEREDOC__
+
+echo "Makefile.configure: written" 1>&2
+echo "Makefile.configure: written" 1>&3
+
+exit 0
blob - 889149e7a82ddf07e0169a50cf1563f629f8d7ca
blob + abf505eaf22728d250eee8a0e5d0aab25d7b86fa
--- control.c
+++ control.c
@@ -15,19 +15,17 @@
  * 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 <sys/queue.h>
+
+#include "config.h"
+
 #include <sys/stat.h>
 #include <sys/socket.h>
-#include <sys/uio.h>
 #include <sys/un.h>
 
 #include <netinet/in.h>
 #include <net/if.h>
 
 #include <errno.h>
-#include <event.h>
-#include <imsg.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
blob - /dev/null
blob + b03d0f3b83d875fd587fbb0a0d05344efbc8e130 (mode 644)
--- /dev/null
+++ configure.local.example
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2022 Omar Polo <op@openbsd.org>
+# Copyright (c) 2014-2022 Ingo Schwarze <schwarze@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.
+
+# For all settings documented in this file, there are reasonable
+# defaults and/or the ./configure script attempts autodetection.
+# Consequently, you only need to create a file ./configure.local
+# and put any of these settings into it if ./configure autodetection
+# fails or if you want to make different choices for other reasons.
+
+# If autodetection fails, please tell <op@omarpolo.com>.
+
+# We recommend that you write ./configure.local from scratch and
+# only put the lines there you need.  This file contains examples.
+# It is not intended as a template to be copied as a whole.
+
+# Some systems may want to set additional linker flags for all the
+# binaries, for example for hardening options.
+
+LDFLAGS="-Wl,-z,relro"
+
+# It may be needed to change the flags for the individual libraries.
+
+LDADD_IMSG="-limsg"
+LDADD_LIBEVENT2="-L/opt/lib/ -levent_extra -levent_core"
+LDADD_LIB_FLAC=
+LDADD_LIB_MPG123=
+LDADD_LIB_VORBISFILE=
+LDADD_LIB_SNDIO=
+LDADD_LIB_SOCKET=
+
+# To disable the autoconfiguration via pkg-config set PKG_CONFIG to
+# the empty string:
+
+PKG_CONFIG=
+
+# It is possible to change the utility program used for installation
+# and the modes files are installed with.  The defaults are:
+
+INSTALL="install"
+INSTALL_PROGRAM="${INSTALL} -m 0555"
+INSTALL_LIB="${INSTALL} -m 0444"
+INSTALL_MAN="${INSTALL} -m 0444"
+INSTALL_DATA="${INSTALL} -m 0444"
+
+# In rare cases, it may be required to skip individual automatic tests.
+# Each of the following variables can be set to 0 (test will not be run
+# and will be regarded as failed) or 1 (test will not be run and will
+# be regarded as successful).
+
+HAVE_CAPSICUM=0
+HAVE_ERR=0
+HAVE_EXPLICIT_BZERO=0
+HAVE_GETEXECNAME=0
+HAVE_GETPROGNAME=0
+HAVE_IMSG=0
+HAVE_LANDLOCK=0
+HAVE_LIBEVENT=0
+HAVE_LIBEVENT2=0
+HAVE_LIB_FLAC=0
+HAVE_LIB_MPG123=0
+HAVE_LIB_OPUSFILE=0
+HAVE_LIB_VORBISFILE=0
+HAVE_MEMMEM=0
+HAVE_MEMRCHR=0
+HAVE_PATH_MAX=0
+HAVE_PLEDGE=0
+HAVE_PROGRAM_INVOCATION_SHORT_NAME=0
+HAVE_REALLOCARRAY=0
+HAVE_RECALLOCARRAY=0
+HAVE_SANDBOX_INIT=0
+HAVE_STRLCAT=0
+HAVE_STRLCPY=0
+HAVE_STRNDUP=0
+HAVE_STRNLEN=0
+HAVE_STRTONUM=0
+HAVE_SYS_QUEUE=0
+HAVE_UNVEIL=0
+HAVE___PROGNAME=0
blob - 6956d3da03063292f2b60ea8d676994887cf70dc
blob + c4629edaa511ae2d9c584c4d1ac6c9458242e1ee
--- ctl.c
+++ ctl.c
@@ -15,14 +15,12 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <sys/types.h>
+#include "config.h"
+
 #include <sys/socket.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
 #include <sys/un.h>
 
 #include <errno.h>
-#include <event.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <stdio.h>
@@ -31,7 +29,6 @@
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>
-#include <imsg.h>
 
 #include "amused.h"
 #include "log.h"
blob - 179235943ad862e0426e472d7b0922bf3fef0371
blob + 852ef4b4d7bb5f4041ef126c2db5bde8213e8c5c
--- log.c
+++ log.c
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
blob - /dev/null
blob + 5b092cfcfd53b5b09a2d5932010f421d6795e0aa (mode 644)
--- /dev/null
+++ imsg.h
@@ -0,0 +1,113 @@
+/*	$OpenBSD: imsg.h,v 1.5 2019/01/20 02:50:03 bcook Exp $	*/
+
+/*
+ * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
+ * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@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.
+ */
+
+#ifndef _IMSG_H_
+#define _IMSG_H_
+
+#include <stdint.h>
+
+#define IBUF_READ_SIZE		65535
+#define IMSG_HEADER_SIZE	sizeof(struct imsg_hdr)
+#define MAX_IMSGSIZE		16384
+
+struct ibuf {
+	TAILQ_ENTRY(ibuf)	 entry;
+	unsigned char		*buf;
+	size_t			 size;
+	size_t			 max;
+	size_t			 wpos;
+	size_t			 rpos;
+	int			 fd;
+};
+
+struct msgbuf {
+	TAILQ_HEAD(, ibuf)	 bufs;
+	uint32_t		 queued;
+	int			 fd;
+};
+
+struct ibuf_read {
+	unsigned char		 buf[IBUF_READ_SIZE];
+	unsigned char		*rptr;
+	size_t			 wpos;
+};
+
+struct imsg_fd {
+	TAILQ_ENTRY(imsg_fd)	entry;
+	int			fd;
+};
+
+struct imsgbuf {
+	TAILQ_HEAD(, imsg_fd)	 fds;
+	struct ibuf_read	 r;
+	struct msgbuf		 w;
+	int			 fd;
+	pid_t			 pid;
+};
+
+#define IMSGF_HASFD	1
+
+struct imsg_hdr {
+	uint32_t	 type;
+	uint16_t	 len;
+	uint16_t	 flags;
+	uint32_t	 peerid;
+	uint32_t	 pid;
+};
+
+struct imsg {
+	struct imsg_hdr	 hdr;
+	int		 fd;
+	void		*data;
+};
+
+
+/* buffer.c */
+struct ibuf	*ibuf_open(size_t);
+struct ibuf	*ibuf_dynamic(size_t, size_t);
+int		 ibuf_add(struct ibuf *, const void *, size_t);
+void		*ibuf_reserve(struct ibuf *, size_t);
+void		*ibuf_seek(struct ibuf *, size_t, size_t);
+size_t		 ibuf_size(struct ibuf *);
+size_t		 ibuf_left(struct ibuf *);
+void		 ibuf_close(struct msgbuf *, struct ibuf *);
+int		 ibuf_write(struct msgbuf *);
+void		 ibuf_free(struct ibuf *);
+void		 msgbuf_init(struct msgbuf *);
+void		 msgbuf_clear(struct msgbuf *);
+int		 msgbuf_write(struct msgbuf *);
+void		 msgbuf_drain(struct msgbuf *, size_t);
+
+/* imsg.c */
+void	 imsg_init(struct imsgbuf *, int);
+ssize_t	 imsg_read(struct imsgbuf *);
+ssize_t	 imsg_get(struct imsgbuf *, struct imsg *);
+int	 imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
+	    const void *, uint16_t);
+int	 imsg_composev(struct imsgbuf *, uint32_t, uint32_t,  pid_t, int,
+	    const struct iovec *, int);
+struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
+int	 imsg_add(struct ibuf *, const void *, uint16_t);
+void	 imsg_close(struct imsgbuf *, struct ibuf *);
+void	 imsg_free(struct imsg *);
+int	 imsg_flush(struct imsgbuf *);
+void	 imsg_clear(struct imsgbuf *);
+
+#endif
blob - 0686e1258936c821114600db32ee00b4d1a7f0fa
blob + 25f2a3acd47767a1524498b0ea97d08b54ae2ee6
--- player.c
+++ player.c
@@ -14,22 +14,18 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
+#include "config.h"
 
 #include <limits.h>
 
 #include <assert.h>
 #include <errno.h>
-#include <event.h>
 #include <poll.h>
 #include <signal.h>
 #include <sndio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
-#include <imsg.h>
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>
blob - ddf86c28d7b98f0a796b5ffa55cd87f02b4c673b
blob + 020ef8df21b9634a7671a55b57e93507a59c6114
--- player_123.c
+++ player_123.c
@@ -14,16 +14,12 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "config.h"
+
 #include <sys/mman.h>
 #include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
 
-#include <err.h>
-#include <event.h>
 #include <limits.h>
-#include <imsg.h>
 #include <unistd.h>
 
 #include <mpg123.h>
blob - fb7d7f6e5fb27589c7b28218ed1c71c88c7091f6
blob + 7df1d378d1b826a3bab7a241cf6c9d7f257c9b0f
--- player_flac.c
+++ player_flac.c
@@ -14,19 +14,14 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
+#include "config.h"
 
-#include <err.h>
-#include <event.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
-#include <imsg.h>
 
 #include <FLAC/stream_decoder.h>
 
blob - a2263c30c54ee0d24dcd7a852cfeb7f91a4211cd
blob + e287375ce6df3b24e132769563a7bcabe2403f4e
--- player_oggvorbis.c
+++ player_oggvorbis.c
@@ -14,19 +14,14 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
+#include "config.h"
 
-#include <err.h>
-#include <event.h>
 #include <fcntl.h>
 #include <math.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdint.h>
-#include <imsg.h>
 #include <unistd.h>
 
 #include <vorbis/codec.h>
blob - 2a20b6840acc75e98eab54cbc2c4ffe84faeafe2
blob + 7e291f0c988483c73189fce7d8bab69f7cd10fdf
--- player_opus.c
+++ player_opus.c
@@ -14,19 +14,14 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
+#include "config.h"
 
-#include <err.h>
-#include <event.h>
 #include <fcntl.h>
 #include <math.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdint.h>
-#include <imsg.h>
 #include <unistd.h>
 
 #include <opusfile.h>
blob - f2821ef2c9500cc78ba6202d4a4a171047d46fd4
blob + bf38c046e3d2ddc87a94439913eed4bea6109160
--- playlist.c
+++ playlist.c
@@ -14,6 +14,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "config.h"
+
 #include <sys/types.h>
 
 #include <regex.h>
blob - f05ceadf51129ffe6559594eeea12fa517db5f69
blob + aeb15eb2aa91cbb4d041a78af3a54eab3c8c9de7
--- xmalloc.c
+++ xmalloc.c
@@ -13,6 +13,8 @@
  * called by a name other than "ssh" or "Secure Shell".
  */
 
+#include "config.h"
+
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
blob - /dev/null
blob + 9cd9aad01fe0196eb6bb233493e4dabc0dc20625 (mode 644)
--- /dev/null
+++ queue.h
@@ -0,0 +1,619 @@
+/*
+ * A compatible version of OpenBSD <sys/queue.h>.
+ */
+/*
+ * 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
+ */
+
+/* OPENBSD ORIGINAL: sys/sys/queue.h */
+
+/*
+ * Require for OS/X and other platforms that have old/broken/incomplete
+ * <sys/queue.h>.
+ */
+
+#undef LIST_EMPTY
+#undef LIST_END
+#undef LIST_ENTRY
+#undef LIST_FIRST
+#undef LIST_FOREACH
+#undef LIST_FOREACH_SAFE
+#undef LIST_HEAD
+#undef LIST_HEAD_INITIALIZER
+#undef LIST_INIT
+#undef LIST_INSERT_AFTER
+#undef LIST_INSERT_BEFORE
+#undef LIST_INSERT_HEAD
+#undef LIST_NEXT
+#undef LIST_REMOVE
+#undef LIST_REPLACE
+#undef SIMPLEQ_CONCAT
+#undef SIMPLEQ_EMPTY
+#undef SIMPLEQ_END
+#undef SIMPLEQ_ENTRY
+#undef SIMPLEQ_FIRST
+#undef SIMPLEQ_FOREACH
+#undef SIMPLEQ_FOREACH_SAFE
+#undef SIMPLEQ_HEAD
+#undef SIMPLEQ_HEAD_INITIALIZER
+#undef SIMPLEQ_INIT
+#undef SIMPLEQ_INSERT_AFTER
+#undef SIMPLEQ_INSERT_HEAD
+#undef SIMPLEQ_INSERT_TAIL
+#undef SIMPLEQ_NEXT
+#undef SIMPLEQ_REMOVE_AFTER
+#undef SIMPLEQ_REMOVE_HEAD
+#undef SLIST_EMPTY
+#undef SLIST_END
+#undef SLIST_ENTRY
+#undef SLIST_FIRST
+#undef SLIST_FOREACH
+#undef SLIST_FOREACH_SAFE
+#undef SLIST_HEAD
+#undef SLIST_HEAD_INITIALIZER
+#undef SLIST_INIT
+#undef SLIST_INSERT_AFTER
+#undef SLIST_INSERT_HEAD
+#undef SLIST_NEXT
+#undef SLIST_REMOVE
+#undef SLIST_REMOVE_AFTER
+#undef SLIST_REMOVE_HEAD
+#undef TAILQ_CONCAT
+#undef TAILQ_EMPTY
+#undef TAILQ_END
+#undef TAILQ_ENTRY
+#undef TAILQ_FIRST
+#undef TAILQ_FOREACH
+#undef TAILQ_FOREACH_REVERSE
+#undef TAILQ_FOREACH_REVERSE_SAFE
+#undef TAILQ_FOREACH_SAFE
+#undef TAILQ_HEAD
+#undef TAILQ_HEAD_INITIALIZER
+#undef TAILQ_INIT
+#undef TAILQ_INSERT_AFTER
+#undef TAILQ_INSERT_BEFORE
+#undef TAILQ_INSERT_HEAD
+#undef TAILQ_INSERT_TAIL
+#undef TAILQ_LAST
+#undef TAILQ_NEXT
+#undef TAILQ_PREV
+#undef TAILQ_REMOVE
+#undef TAILQ_REPLACE
+#undef XSIMPLEQ_EMPTY
+#undef XSIMPLEQ_END
+#undef XSIMPLEQ_ENTRY
+#undef XSIMPLEQ_FIRST
+#undef XSIMPLEQ_FOREACH
+#undef XSIMPLEQ_FOREACH_SAFE
+#undef XSIMPLEQ_HEAD
+#undef XSIMPLEQ_INIT
+#undef XSIMPLEQ_INSERT_AFTER
+#undef XSIMPLEQ_INSERT_HEAD
+#undef XSIMPLEQ_INSERT_TAIL
+#undef XSIMPLEQ_NEXT
+#undef XSIMPLEQ_REMOVE_AFTER
+#undef XSIMPLEQ_REMOVE_HEAD
+#undef XSIMPLEQ_XOR
+
+/*
+ * 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)
blob - /dev/null
blob + ab9a2cfc5f1241b1c375cc1e3fc555c5fc35a06a (mode 644)
--- /dev/null
+++ tests.c
@@ -0,0 +1,955 @@
+#if TEST__MMD
+int
+main(void)
+{
+	return 0;
+}
+#endif /* TEST_NOOP */
+#if TEST___PROGNAME
+int
+main(void)
+{
+	extern char *__progname;
+
+	return !__progname;
+}
+#endif /* TEST___PROGNAME */
+#if TEST_ARC4RANDOM
+#include <stdlib.h>
+
+int
+main(void)
+{
+	return (arc4random() + 1) ? 0 : 1;
+}
+#endif /* TEST_ARC4RANDOM */
+#if TEST_B64_NTOP
+#include <netinet/in.h>
+#include <resolv.h>
+
+int
+main(void)
+{
+	const char *src = "hello world";
+	char output[1024];
+
+	return b64_ntop((const unsigned char *)src, 11, output, sizeof(output)) > 0 ? 0 : 1;
+}
+#endif /* TEST_B64_NTOP */
+#if TEST_CAPSICUM
+#include <sys/capsicum.h>
+
+int
+main(void)
+{
+	cap_enter();
+	return(0);
+}
+#endif /* TEST_CAPSICUM */
+#if TEST_CRYPT
+#if defined(__linux__)
+# define _GNU_SOURCE /* old glibc */
+# define _DEFAULT_SOURCE /* new glibc */
+#endif
+#if defined(__sun)
+# ifndef _XOPEN_SOURCE /* SunOS already defines */
+#  define _XOPEN_SOURCE /* XPGx */
+# endif
+# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */
+# ifndef __EXTENSIONS__ /* SunOS already defines */
+#  define __EXTENSIONS__ /* reallocarray, etc. */
+# endif
+#endif
+#include <unistd.h>
+
+int main(void)
+{
+	char	*v;
+
+	v = crypt("this_is_a_key", "123455");
+	return v == NULL;
+}
+#endif /* TEST_CRYPT */
+#if TEST_CRYPT_NEWHASH
+#include <pwd.h> /* _PASSWORD_LEN */
+#include <unistd.h>
+
+int
+main(void)
+{
+	const char	*v = "password";
+	char		 hash[_PASSWORD_LEN];
+
+	if (crypt_newhash(v, "bcrypt,a", hash, sizeof(hash)) == -1)
+		return 1;
+	if (crypt_checkpass(v, hash) == -1)
+		return 1;
+
+	return 0;
+}
+#endif /* TEST_CRYPT_NEWHASH */
+#if TEST_ENDIAN_H
+#ifdef __linux__
+# define _DEFAULT_SOURCE
+#endif
+#include <endian.h>
+
+int
+main(void)
+{
+	return !htole32(23);
+}
+#endif /* TEST_ENDIAN_H */
+#if TEST_ERR
+/*
+ * Copyright (c) 2015 Ingo Schwarze <schwarze@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 <err.h>
+#include <errno.h>
+
+int
+main(void)
+{
+	warnx("%d. warnx", 1);
+	warnc(ENOENT, "%d. warn", ENOENT);
+	warn("%d. warn", 2);
+	err(0, "%d. err", 3);
+	errx(0, "%d. err", 3);
+	errc(0, ENOENT, "%d. err", 3);
+	/* NOTREACHED */
+	return 1;
+}
+#endif /* TEST_ERR */
+#if TEST_EXPLICIT_BZERO
+#include <string.h>
+
+int
+main(void)
+{
+	char foo[10];
+
+	explicit_bzero(foo, sizeof(foo));
+	return(0);
+}
+#endif /* TEST_EXPLICIT_BZERO */
+#if TEST_FLOCK
+#include <fcntl.h>
+
+int
+main(void)
+{
+	flock(0, LOCK_SH|LOCK_NB);
+	return 0;
+}
+#endif /* TEST_FLOCK */
+#if TEST_FREEZERO
+#include <stdlib.h>
+
+int
+main(void)
+{
+	freezero(NULL, 0);
+	return 0;
+}
+#endif /* TEST_FREEZERO */
+#if TEST_FTS
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+
+int
+main(void)
+{
+	const char	*argv[2];
+	FTS		*ftsp;
+	FTSENT		*entry;
+
+	argv[0] = ".";
+	argv[1] = (char *)NULL;
+
+	ftsp = fts_open((char * const *)argv,
+	    FTS_PHYSICAL | FTS_NOCHDIR, NULL);
+
+	if (ftsp == NULL)
+		return 1;
+
+	entry = fts_read(ftsp);
+
+	if (entry == NULL)
+		return 1;
+
+	if (fts_set(ftsp, entry, FTS_SKIP) != 0) 
+		return 1;
+
+	if (fts_close(ftsp) != 0)
+		return 1;
+
+	return 0;
+}
+#endif /* TEST_FTS */
+#if TEST_GETEXECNAME
+#include <stdlib.h>
+
+int
+main(void)
+{
+	const char * progname;
+
+	progname = getexecname();
+	return progname == NULL;
+}
+#endif /* TEST_GETEXECNAME */
+#if TEST_GETPROGNAME
+#include <stdlib.h>
+
+int
+main(void)
+{
+	const char * progname;
+
+	progname = getprogname();
+	return progname == NULL;
+}
+#endif /* TEST_GETPROGNAME */
+#if TEST_IMSG
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+#include <stdint.h>
+#include <imsg.h>
+
+int
+main(void)
+{
+	struct imsgbuf ibuf;
+
+	imsg_init(&ibuf, 3);
+	imsg_clear(&ibuf);
+	return 0;
+}
+#endif /* TEST_IMSG */
+#if TEST_INFTIM
+/*
+ * Linux doesn't (always?) have this.
+ */
+
+#include <poll.h>
+#include <stdio.h>
+
+int
+main(void)
+{
+	printf("INFTIM is defined to be %ld\n", (long)INFTIM);
+	return 0;
+}
+#endif /* TEST_INFTIM */
+#if TEST_LANDLOCK
+#include <linux/landlock.h>
+#include <linux/prctl.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#ifndef landlock_create_ruleset
+static inline int landlock_create_ruleset(const struct landlock_ruleset_attr *const attr,
+	const size_t size, const __u32 flags)
+{
+	return syscall(__NR_landlock_create_ruleset, attr, size, flags);
+}
+#endif
+
+#ifndef landlock_restrict_self
+static inline int landlock_restrict_self(const int ruleset_fd,
+	const __u32 flags)
+{
+	return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
+}
+#endif
+
+int
+main(void)
+{
+	uint64_t mask = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE;
+	struct landlock_ruleset_attr rules = {
+		.handled_access_fs = mask
+	};
+	int fd = landlock_create_ruleset(&rules, sizeof(rules), 0);
+
+	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
+		return 1;
+	return landlock_restrict_self(fd, 0) ? 1 : 0;
+}
+#endif /* TEST_LANDLOCK */
+#if TEST_LIB_SOCKET
+#include <sys/socket.h>
+
+int
+main(void)
+{
+	int fds[2], c;
+
+	c = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+	return c == -1;
+}
+#endif /* TEST_LIB_SOCKET */
+#if TEST_MD5
+#include <sys/types.h>
+#include <md5.h>
+
+int main(void)
+{
+	MD5_CTX ctx;
+	char result[MD5_DIGEST_STRING_LENGTH];
+
+	MD5Init(&ctx);
+	MD5Update(&ctx, (const unsigned char *)"abcd", 4);
+	MD5End(&ctx, result);
+
+	return 0;
+}
+#endif /* TEST_MD5 */
+#if TEST_MEMMEM
+#define _GNU_SOURCE
+#include <string.h>
+
+int
+main(void)
+{
+	char *a = memmem("hello, world", strlen("hello, world"), "world", strlen("world"));
+	return(NULL == a);
+}
+#endif /* TEST_MEMMEM */
+#if TEST_MEMRCHR
+#if defined(__linux__) || defined(__MINT__)
+#define _GNU_SOURCE	/* See test-*.c what needs this. */
+#endif
+#include <string.h>
+
+int
+main(void)
+{
+	const char *buf = "abcdef";
+	void *res;
+
+	res = memrchr(buf, 'a', strlen(buf));
+	return(NULL == res ? 1 : 0);
+}
+#endif /* TEST_MEMRCHR */
+#if TEST_MEMSET_S
+#include <string.h>
+
+int main(void)
+{
+	char buf[10];
+	memset_s(buf, 0, 'c', sizeof(buf));
+	return 0;
+}
+#endif /* TEST_MEMSET_S */
+#if TEST_MKFIFOAT
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(void) {
+	mkfifoat(AT_FDCWD, "this/path/should/not/exist", 0600);
+	return 0;
+}
+#endif /* TEST_MKFIFOAT */
+#if TEST_MKNODAT
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(void) {
+	mknodat(AT_FDCWD, "this/path/should/not/exist", S_IFIFO | 0600, 0);
+	return 0;
+}
+#endif /* TEST_MKNODAT */
+#if TEST_OPTRESET
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+	optreset = 1;
+	getopt(argc, argv, "");
+	return 0;
+}
+#endif /* TEST_OPTRESET */
+#if TEST_OSBYTEORDER_H
+#include <libkern/OSByteOrder.h>
+
+int
+main(void)
+{
+	return !OSSwapHostToLittleInt32(23);
+}
+#endif /* TEST_OSBYTEORDER_H */
+#if TEST_PATH_MAX
+/*
+ * POSIX allows PATH_MAX to not be defined, see
+ * http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html;
+ * the GNU Hurd is an example of a system not having it.
+ *
+ * Arguably, it would be better to test sysconf(_SC_PATH_MAX),
+ * but since the individual *.c files include "config.h" before
+ * <limits.h>, overriding an excessive value of PATH_MAX from
+ * "config.h" is impossible anyway, so for now, the simplest
+ * fix is to provide a value only on systems not having any.
+ * So far, we encountered no system defining PATH_MAX to an
+ * impractically large value, even though POSIX explicitly
+ * allows that.
+ *
+ * The real fix would be to replace all static buffers of size
+ * PATH_MAX by dynamically allocated buffers.  But that is
+ * somewhat intrusive because it touches several files and
+ * because it requires changing struct mlink in mandocdb.c.
+ * So i'm postponing that for now.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+
+int
+main(void)
+{
+	printf("PATH_MAX is defined to be %ld\n", (long)PATH_MAX);
+	return 0;
+}
+#endif /* TEST_PATH_MAX */
+#if TEST_PLEDGE
+#include <unistd.h>
+
+int
+main(void)
+{
+	return !!pledge("stdio", NULL);
+}
+#endif /* TEST_PLEDGE */
+#if TEST_PROGRAM_INVOCATION_SHORT_NAME
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <errno.h>
+
+int
+main(void)
+{
+
+	return !program_invocation_short_name;
+}
+#endif /* TEST_PROGRAM_INVOCATION_SHORT_NAME */
+#if TEST_PR_SET_NAME
+#include <sys/prctl.h>
+
+int
+main(void)
+{
+	prctl(PR_SET_NAME, "foo");
+	return 0;
+}
+#endif /* TEST_PR_SET_NAME */
+#if TEST_READPASSPHRASE
+#include <stddef.h>
+#include <readpassphrase.h>
+
+int
+main(void)
+{
+	return !!readpassphrase("prompt: ", NULL, 0, 0);
+}
+#endif /* TEST_READPASSPHRASE */
+#if TEST_REALLOCARRAY
+#ifdef __NetBSD__
+# define _OPENBSD_SOURCE
+#endif
+#include <stdlib.h>
+
+int
+main(void)
+{
+	return !reallocarray(NULL, 2, 2);
+}
+#endif /* TEST_REALLOCARRAY */
+#if TEST_RECALLOCARRAY
+#include <stdlib.h>
+
+int
+main(void)
+{
+	return !recallocarray(NULL, 0, 2, 2);
+}
+#endif /* TEST_RECALLOCARRAY */
+#if TEST_SANDBOX_INIT
+#include <sandbox.h>
+
+int
+main(void)
+{
+	char	*ep;
+	int	 rc;
+
+	rc = sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, &ep);
+	if (-1 == rc)
+		sandbox_free_error(ep);
+	return(-1 == rc);
+}
+#endif /* TEST_SANDBOX_INIT */
+#if TEST_SETPROCTITLE
+#include <stdlib.h>
+
+int
+main(void)
+{
+	setproctitle("#%d test program", 7);
+	return 0;
+}
+#endif
+#if TEST_SIO_FLUSH
+#include <sndio.h>
+
+int
+main(void)
+{
+	struct sio_hdl *hdl;
+	hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1);
+	sio_flush(hdl);
+	sio_close(hdl);
+}
+#endif /* TEST_SIO_FLUSH */
+#if TEST_SCAN_SCALED
+#include <util.h>
+
+int
+main(void)
+{
+	char *cinput = (char *)"1.5K", buf[FMT_SCALED_STRSIZE];
+	long long ninput = 10483892, result;
+	return scan_scaled(cinput, &result) == 0;
+}
+#endif /* TEST_SCAN_SCALED */
+#if TEST_SECCOMP_FILTER
+#include <sys/prctl.h>
+#include <linux/seccomp.h>
+#include <errno.h>
+
+int
+main(void)
+{
+
+	prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, 0);
+	return(EFAULT == errno ? 0 : 1);
+}
+#endif /* TEST_SECCOMP_FILTER */
+#if TEST_SETRESGID
+#define _GNU_SOURCE /* linux */
+#include <sys/types.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+	return setresgid(-1, -1, -1) == -1;
+}
+#endif /* TEST_SETRESGID */
+#if TEST_SETRESUID
+#define _GNU_SOURCE /* linux */
+#include <sys/types.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+	return setresuid(-1, -1, -1) == -1;
+}
+#endif /* TEST_SETRESUID */
+#if TEST_SHA2
+#include <sys/types.h>
+#include <sha2.h>
+
+int main(void)
+{
+	SHA2_CTX ctx;
+	char result[SHA256_DIGEST_STRING_LENGTH];
+
+	SHA256Init(&ctx);
+	SHA256Update(&ctx, (const unsigned char *)"abcd", 4);
+	SHA256End(&ctx, result);
+
+	return 0;
+}
+#endif /* TEST_SHA2 */
+#if TEST_SOCK_NONBLOCK
+/*
+ * Linux doesn't (always?) have this.
+ */
+
+#include <sys/socket.h>
+
+int
+main(void)
+{
+	int fd[2];
+	socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0, fd);
+	return 0;
+}
+#endif /* TEST_SOCK_NONBLOCK */
+#if TEST_STATIC
+int
+main(void)
+{
+	return 0; /* not meant to do anything */
+}
+#endif /* TEST_STATIC */
+#if TEST_STRLCAT
+#include <string.h>
+
+int
+main(void)
+{
+	char buf[3] = "a";
+	return ! (strlcat(buf, "b", sizeof(buf)) == 2 &&
+	    buf[0] == 'a' && buf[1] == 'b' && buf[2] == '\0');
+}
+#endif /* TEST_STRLCAT */
+#if TEST_STRLCPY
+#include <string.h>
+
+int
+main(void)
+{
+	char buf[2] = "";
+	return ! (strlcpy(buf, "a", sizeof(buf)) == 1 &&
+	    buf[0] == 'a' && buf[1] == '\0');
+}
+#endif /* TEST_STRLCPY */
+#if TEST_STRNDUP
+#include <string.h>
+
+int
+main(void)
+{
+	const char *foo = "bar";
+	char *baz;
+
+	baz = strndup(foo, 1);
+	return(0 != strcmp(baz, "b"));
+}
+#endif /* TEST_STRNDUP */
+#if TEST_STRNLEN
+#include <string.h>
+
+int
+main(void)
+{
+	const char *foo = "bar";
+	size_t sz;
+
+	sz = strnlen(foo, 1);
+	return(1 != sz);
+}
+#endif /* TEST_STRNLEN */
+#if TEST_STRTONUM
+/*
+ * Copyright (c) 2015 Ingo Schwarze <schwarze@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.
+ */
+#ifdef __NetBSD__
+# define _OPENBSD_SOURCE
+#endif
+#include <stdlib.h>
+
+int
+main(void)
+{
+	const char *errstr;
+
+	if (strtonum("1", 0, 2, &errstr) != 1)
+		return 1;
+	if (errstr != NULL)
+		return 2;
+	if (strtonum("1x", 0, 2, &errstr) != 0)
+		return 3;
+	if (errstr == NULL)
+		return 4;
+	if (strtonum("2", 0, 1, &errstr) != 0)
+		return 5;
+	if (errstr == NULL)
+		return 6;
+	if (strtonum("0", 1, 2, &errstr) != 0)
+		return 7;
+	if (errstr == NULL)
+		return 8;
+	return 0;
+}
+#endif /* TEST_STRTONUM */
+#if TEST_SYS_BYTEORDER_H
+#include <sys/byteorder.h>
+
+int
+main(void)
+{
+	return !LE_32(23);
+}
+#endif /* TEST_SYS_BYTEORDER_H */
+#if TEST_SYS_ENDIAN_H
+#include <sys/endian.h>
+
+int
+main(void)
+{
+	return !htole32(23);
+}
+#endif /* TEST_SYS_ENDIAN_H */
+#if TEST_SYS_MKDEV_H
+#include <sys/types.h>
+#include <sys/mkdev.h>
+
+int
+main(void)
+{
+	return !minor(0);
+}
+#endif /* TEST_SYS_MKDEV_H */
+#if TEST_SYS_FILE
+#include <sys/file.h>
+
+int
+main(void)
+{
+	flock(0, LOCK_SH|LOCK_NB);
+	return 0;
+}
+#endif /* TEST_SYS_FILE */
+#if TEST_SYS_QUEUE
+#include <sys/queue.h>
+#include <stddef.h>
+
+struct foo {
+	int bar;
+	TAILQ_ENTRY(foo) entries;
+};
+
+TAILQ_HEAD(fooq, foo);
+
+int
+main(void)
+{
+	struct fooq foo_q, bar_q;
+	struct foo *p, *tmp;
+	int i = 0;
+
+	TAILQ_INIT(&foo_q);
+	TAILQ_INIT(&bar_q);
+
+	/*
+	 * Use TAILQ_FOREACH_SAFE because some systems (e.g., Linux)
+	 * have TAILQ_FOREACH but not the safe variant.
+	 */
+
+	TAILQ_FOREACH_SAFE(p, &foo_q, entries, tmp)
+		p->bar = i++;
+
+	/* Test for newer macros as well. */
+
+	TAILQ_CONCAT(&foo_q, &bar_q, entries);
+	return 0;
+}
+#endif /* TEST_SYS_QUEUE */
+#if TEST_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+
+int
+main(void)
+{
+	return !minor(0);
+}
+#endif /* TEST_SYS_SYSMACROS_H */
+#if TEST_SYS_TREE
+#include <sys/tree.h>
+#include <stdlib.h>
+
+struct node {
+	RB_ENTRY(node) entry;
+	int i;
+};
+
+static int
+intcmp(struct node *e1, struct node *e2)
+{
+	return (e1->i < e2->i ? -1 : e1->i > e2->i);
+}
+
+RB_HEAD(inttree, node) head = RB_INITIALIZER(&head);
+RB_PROTOTYPE(inttree, node, entry, intcmp)
+RB_GENERATE(inttree, node, entry, intcmp)
+
+int testdata[] = {
+	20, 16, 17, 13, 3, 6, 1, 8, 2, 4
+};
+
+int
+main(void)
+{
+	size_t i;
+	struct node *n;
+
+	for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) {
+		if ((n = malloc(sizeof(struct node))) == NULL)
+			return 1;
+		n->i = testdata[i];
+		RB_INSERT(inttree, &head, n);
+	}
+
+	return 0;
+}
+
+#endif /* TEST_SYS_TREE */
+#if TEST_UNVEIL
+#include <unistd.h>
+
+int
+main(void)
+{
+	return -1 != unveil(NULL, NULL);
+}
+#endif /* TEST_UNVEIL */
+#if TEST_WAIT_ANY
+#include <sys/wait.h>
+
+int
+main(void)
+{
+	int st;
+
+	return waitpid(WAIT_ANY, &st, WNOHANG) != -1;
+}
+#endif /* TEST_WAIT_ANY */
+#if TEST_LIBEVENT
+#include <event.h>
+
+int
+main(void)
+{
+	struct event ev;
+
+	event_set(&ev, 0, EV_READ, NULL, NULL);
+	event_add(&ev, NULL);
+	event_del(&ev);
+	return 0;
+}
+#endif /* TEST_LIBEVENT */
+#if TEST_LIBEVENT2
+#include <event2/event.h>
+#include <event2/event_compat.h>
+#include <event2/event_struct.h>
+#include <event2/buffer.h>
+#include <event2/buffer_compat.h>
+#include <event2/bufferevent.h>
+#include <event2/bufferevent_struct.h>
+#include <event2/bufferevent_compat.h>
+
+int
+main(void)
+{
+	struct event ev;
+
+	event_set(&ev, 0, EV_READ, NULL, NULL);
+	event_add(&ev, NULL);
+	event_del(&ev);
+	return 0;
+}
+#endif /* TEST_LIBEVENT2 */
+#if TEST_LIB_FLAC
+#include <FLAC/stream_decoder.h>
+
+int
+main(void)
+{
+	FLAC__StreamDecoder *decoder = NULL;
+	FLAC__StreamDecoderInitStatus init_status;
+
+	decoder = FLAC__stream_decoder_new();
+	FLAC__stream_decoder_delete(decoder);
+	return 0;
+}
+#endif /* TEST_LIB_FLAC */
+#if TEST_LIB_MPG123
+#include <mpg123.h>
+
+int
+main(void)
+{
+	mpg123_handle *mh;
+
+	mh = mpg123_new(NULL, NULL);
+	mpg123_delete(mh);
+	return 0;
+}
+#endif/* TEST_LIB_MPG123 */
+#if TEST_LIB_OPUSFILE
+#include <stdio.h>
+#include <opusfile.h>
+
+int
+main(void)
+{
+	FILE *f;
+	OggOpusFile *of;
+	OpusFileCallbacks cb = {NULL, NULL, NULL, NULL};
+	int r;
+
+	f = op_fdopen(&cb, 0, "r");
+	of = op_open_callbacks(f, &cb, NULL, 0, &r);
+	op_free(of);
+	return 0;
+}
+#endif /* TEST_LIB_OPUSFILE */
+#if TEST_LIB_VORBISFILE
+#include <stdio.h>
+#include <vorbis/vorbisfile.h>
+
+int
+main(void)
+{
+	OggVorbis_File vf;
+
+	ov_open_callbacks(stdin, &vf, NULL, 0, OV_CALLBACKS_NOCLOSE);
+	ov_clear(&vf);
+	return 0;
+}
+#endif /* TEST_LIB_VORBISFILE */
+#if TEST_LIB_SNDIO
+#include <sndio.h>
+
+int
+main(void)
+{
+	struct sio_hdl *hdl;
+	hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1);
+	sio_close(hdl);
+}
+#endif /* TEST_LIB_SNDIO */