diff --git a/compat.h b/compat.h
index 39e784dc..e85536cb 100644
--- a/compat.h
+++ b/compat.h
@@ -51,13 +51,6 @@
 #include <sys/filio.h>
 #endif
 
-#ifndef HAVE_BSD_TYPES
-typedef uint8_t u_int8_t;
-typedef uint16_t u_int16_t;
-typedef uint32_t u_int32_t;
-typedef uint64_t u_int64_t;
-#endif
-
 #ifdef HAVE_ERR_H
 #include <err.h>
 #else
@@ -217,6 +210,16 @@ void	warnx(const char *, ...);
 #define flock(fd, op) (0)
 #endif
 
+#ifndef HAVE_EXPLICIT_BZERO
+/* explicit_bzero.c */
+void		 explicit_bzero(void *, size_t);
+#endif
+
+#ifndef HAVE_GETDTABLECOUNT
+/* getdtablecount.c */
+int		 getdtablecount(void);
+#endif
+
 #ifndef HAVE_CLOSEFROM
 /* closefrom.c */
 void		 closefrom(int);
@@ -317,6 +320,11 @@ void		 cfmakeraw(struct termios *);
 void		*reallocarray(void *, size_t, size_t);
 #endif
 
+#ifndef HAVE_RECALLOCARRAY
+/* recallocarray.c */
+void		*recallocarray(void *, size_t, size_t, size_t);
+#endif
+
 #ifdef HAVE_UTF8PROC
 /* utf8proc.c */
 int		 utf8proc_wcwidth(wchar_t);
diff --git a/compat/asprintf.c b/compat/asprintf.c
index 2b53dbe2..95d78430 100644
--- a/compat/asprintf.c
+++ b/compat/asprintf.c
@@ -14,15 +14,14 @@
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <sys/types.h>
+
 #include <stdarg.h>
 #include <stdio.h>
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#else
-#include <inttypes.h>
-#endif
 #include <string.h>
 
+#include "compat.h"
+
 int
 asprintf(char **ret, const char *fmt, ...)
 {
diff --git a/compat/explicit_bzero.c b/compat/explicit_bzero.c
new file mode 100644
index 00000000..e8bc5b36
--- /dev/null
+++ b/compat/explicit_bzero.c
@@ -0,0 +1,15 @@
+/*	$OpenBSD: explicit_bzero.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
+/*
+ * Public domain.
+ * Written by Matthew Dempsky.
+ */
+
+#include <string.h>
+
+#include "compat.h"
+
+void
+explicit_bzero(void *buf, size_t len)
+{
+	memset(buf, 0, len);
+}
diff --git a/compat/getdtablecount.c b/compat/getdtablecount.c
new file mode 100644
index 00000000..3ccab650
--- /dev/null
+++ b/compat/getdtablecount.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+#include <sys/types.h>
+
+#include <glob.h>
+#include <unistd.h>
+
+#include "compat.h"
+
+void fatal(const char *, ...);
+void fatalx(const char *, ...);
+
+#ifdef HAVE_PROC_PID
+int
+getdtablecount(void)
+{
+	char	path[PATH_MAX];
+	glob_t	g;
+	int	n;
+
+	if (snprintf(path, sizeof path, "/proc/%ld/fd/*", (long)getpid()) < 0)
+		fatal("snprintf overflow");
+	switch (glob(path, 0, NULL, &g)) {
+	case GLOB_NOMATCH:
+		return (0);
+	case 0:
+		break;
+	default:
+		fatal("glob(\"%s\") failed", path);
+	}
+	n = g.gl_pathc;
+	globfree(&g);
+	return (n);
+}
+#else
+int
+getdtablecount(void)
+{
+	return (0);
+}
+#endif
diff --git a/compat/imsg-buffer.c b/compat/imsg-buffer.c
index 4c8d5e2c..3576d5f0 100644
--- a/compat/imsg-buffer.c
+++ b/compat/imsg-buffer.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: imsg-buffer.c,v 1.7 2015/07/12 18:40:49 nicm Exp $	*/
+/*	$OpenBSD: imsg-buffer.c,v 1.9 2017/03/17 14:51:26 deraadt Exp $	*/
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -78,7 +78,7 @@ ibuf_realloc(struct ibuf *buf, size_t len)
 		return (-1);
 	}
 
-	b = realloc(buf->buf, buf->wpos + len);
+	b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
 	if (b == NULL)
 		return (-1);
 	buf->buf = b;
@@ -180,6 +180,8 @@ again:
 void
 ibuf_free(struct ibuf *buf)
 {
+	if (buf == NULL)
+		return;
 	free(buf->buf);
 	free(buf);
 }
diff --git a/compat/imsg.c b/compat/imsg.c
index 422f37ab..987284b3 100644
--- a/compat/imsg.c
+++ b/compat/imsg.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: imsg.c,v 1.9 2015/07/12 18:40:49 nicm Exp $	*/
+/*	$OpenBSD: imsg.c,v 1.14 2017/03/24 09:34:12 nicm Exp $	*/
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -32,40 +32,6 @@ int	 imsg_fd_overhead = 0;
 
 int	 imsg_get_fd(struct imsgbuf *);
 
-int	 available_fds(unsigned int);
-
-/*
- * The original code calls getdtablecount() which is OpenBSD specific. Use
- * available_fds() from OpenSMTPD instead.
- */
-int
-available_fds(unsigned int n)
-{
-	unsigned int	i;
-	int		ret, fds[256];
-
-	if (n > (sizeof(fds)/sizeof(fds[0])))
-		return (1);
-
-	ret = 0;
-	for (i = 0; i < n; i++) {
-		fds[i] = -1;
-		if ((fds[i] = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-			if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
-				fds[i] = socket(AF_INET6, SOCK_DGRAM, 0);
-			if (fds[i] < 0) {
-				ret = 1;
-				break;
-			}
-		}
-	}
-
-	for (i = 0; i < n && fds[i] >= 0; i++)
-		close(fds[i]);
-
-	return (ret);
-}
-
 void
 imsg_init(struct imsgbuf *ibuf, int fd)
 {
@@ -105,19 +71,18 @@ imsg_read(struct imsgbuf *ibuf)
 		return (-1);
 
 again:
-	if (available_fds(imsg_fd_overhead +
-	    (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))) {
+	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 == EMSGSIZE)
-			goto fail;
-		if (errno != EINTR && errno != EAGAIN)
-			goto fail;
-		goto again;
+		if (errno == EINTR)
+			goto again;
+		goto fail;
 	}
 
 	ibuf->r.wpos += n;
@@ -151,8 +116,7 @@ again:
 	}
 
 fail:
-	if (ifd)
-		free(ifd);
+	free(ifd);
 	return (n);
 }
 
@@ -176,7 +140,9 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
 		return (0);
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
-	if ((imsg->data = malloc(datalen)) == NULL)
+	if (datalen == 0)
+		imsg->data = NULL;
+	else if ((imsg->data = malloc(datalen)) == NULL)
 		return (-1);
 
 	if (imsg->hdr.flags & IMSGF_HASFD)
@@ -197,8 +163,8 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
 }
 
 int
-imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
-    pid_t pid, int fd, const void *data, u_int16_t datalen)
+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;
 
@@ -216,8 +182,8 @@ imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
 }
 
 int
-imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
-    pid_t pid, int fd, const struct iovec *iov, int iovcnt)
+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;
@@ -241,8 +207,8 @@ imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
 
 /* ARGSUSED */
 struct ibuf *
-imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
-    pid_t pid, u_int16_t datalen)
+imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
+    uint16_t datalen)
 {
 	struct ibuf	*wbuf;
 	struct imsg_hdr	 hdr;
@@ -268,7 +234,7 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
 }
 
 int
-imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen)
+imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
 {
 	if (datalen)
 		if (ibuf_add(msg, data, datalen) == -1) {
@@ -289,7 +255,7 @@ imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
 	if (msg->fd != -1)
 		hdr->flags |= IMSGF_HASFD;
 
-	hdr->len = (u_int16_t)msg->wpos;
+	hdr->len = (uint16_t)msg->wpos;
 
 	ibuf_close(&ibuf->w, msg);
 }
diff --git a/compat/imsg.h b/compat/imsg.h
index 89946578..8bf94147 100644
--- a/compat/imsg.h
+++ b/compat/imsg.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: imsg.h,v 1.3 2013/12/26 17:32:33 eric Exp $	*/
+/*	$OpenBSD: imsg.h,v 1.4 2017/03/24 09:34:12 nicm Exp $	*/
 
 /*
  * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -37,7 +37,7 @@ struct ibuf {
 
 struct msgbuf {
 	TAILQ_HEAD(, ibuf)	 bufs;
-	u_int32_t		 queued;
+	uint32_t		 queued;
 	int			 fd;
 };
 
@@ -63,11 +63,11 @@ struct imsgbuf {
 #define IMSGF_HASFD	1
 
 struct imsg_hdr {
-	u_int32_t	 type;
-	u_int16_t	 len;
-	u_int16_t	 flags;
-	u_int32_t	 peerid;
-	u_int32_t	 pid;
+	uint32_t	 type;
+	uint16_t	 len;
+	uint16_t	 flags;
+	uint32_t	 peerid;
+	uint32_t	 pid;
 };
 
 struct imsg {
@@ -97,13 +97,12 @@ void		 msgbuf_drain(struct msgbuf *, size_t);
 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 *, u_int32_t, u_int32_t, pid_t,
-	    int, const void *, u_int16_t);
-int	 imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t,  pid_t,
-	    int, const struct iovec *, int);
-struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
-	    u_int16_t);
-int	 imsg_add(struct ibuf *, const void *, u_int16_t);
+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 *);
diff --git a/compat/recallocarray.c b/compat/recallocarray.c
new file mode 100644
index 00000000..74a919a1
--- /dev/null
+++ b/compat/recallocarray.c
@@ -0,0 +1,82 @@
+/*	$OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $	*/
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "compat.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;
+}
diff --git a/configure.ac b/configure.ac
index db0baf1a..115dd1de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,9 +102,12 @@ AC_REPLACE_FUNCS([ \
 	asprintf \
 	cfmakeraw \
 	closefrom \
+	explicit_bzero \
 	fgetln \
 	fparseln \
+	getdtablecount \
 	getprogname \
+	recallocarray \
 	reallocarray \
 	setenv \
 	setproctitle \
@@ -457,23 +460,6 @@ if test "x$found_forkpty" = xyes; then
 fi
 AM_CONDITIONAL(NEED_FORKPTY, test "x$found_forkpty" = xno)
 
-# Check for BSD-style integer types.
-AC_MSG_CHECKING(for BSD-style unsigned types)
-AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-	[
-		#include <sys/types.h>
-		#ifdef HAVE_STDINT_H
-		#include <stdint.h>
-		#else
-		#include <inttypes.h>
-		#endif
-		int main(void)
-		{ u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; }
-	])],
-	[AC_DEFINE(HAVE_BSD_TYPES) AC_MSG_RESULT(yes)],
-	AC_MSG_RESULT(no)
-)
-
 # Look for a suitable queue.h.
 AC_CHECK_DECL(
 	TAILQ_CONCAT,