Commit Diff


commit - 338f06f4e569807582f005f5804ca3abc412b255
commit + 12042ad7003375b746b4e2bccbf33ae7a90cbb98
blob - bcbdc5f2e383a0bd338077fcddc98166b00a74ee
blob + c77ea7cb406ea5434104a64db624cbfba0663e18
--- .gitignore
+++ .gitignore
@@ -7,3 +7,9 @@ iri_test
 docs
 lex.yy.c
 y.tab.*
+Makefile.local
+config.h
+config.h.old
+config.log
+config.log.old
+configure.local
blob - 75ac4701609a24868e8ac5c57a0b8fe3a3778dba
blob + 7cb798d302a874682ab8389b1ceb83bcb59b4c3a
--- Makefile
+++ Makefile
@@ -1,18 +1,12 @@
-CC =		cc
-CFLAGS =	-Wall -Wextra -g
-LDFLAGS =	-ltls
-LEX =		lex
-YACC =		yacc
+.PHONY: all static clean test install
 
-PREFIX =	/usr/local
+all: Makefile.local gmid TAGS
 
-# /usr/local/lib on FreeBSD
-LIBDIR =	/usr/lib/
+Makefile.local: configure
+	./configure
 
-.PHONY: all static clean test install
+include Makefile.local
 
-all: gmid TAGS
-
 lex.yy.c: lex.l y.tab.c
 	${LEX} lex.l
 
@@ -20,7 +14,7 @@ y.tab.c: parse.y
 	${YACC} -b y -d parse.y
 
 SRCS = gmid.c iri.c utf8.c ex.c server.c sandbox.c mime.c
-OBJS = ${SRCS:.c=.o} lex.yy.o y.tab.o
+OBJS = ${SRCS:.c=.o} lex.yy.o y.tab.o ${COMPAT}
 
 gmid: ${OBJS}
 	${CC} ${OBJS} -o gmid ${LDFLAGS}
@@ -36,6 +30,7 @@ TAGS: ${SRCS}
 
 clean:
 	rm -f *.o lex.yy.c y.tab.c y.tab.h y.output gmid iri_test
+	rm -f Makefile.local
 
 iri_test: iri_test.o iri.o utf8.o
 	${CC} iri_test.o iri.o utf8.o -o iri_test ${LDFLAGS}
blob - /dev/null
blob + 840acd09193947bd453a6af2aec7d4f1718981d9 (mode 644)
--- /dev/null
+++ compat/err.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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 <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+/* cheat: if we don't have getprogname in stdlib, will link against
+ * compat/getprogname.c anyway. */
+const char *getprogname(void);
+
+static void vwarn_impl(const char*, va_list);
+static void vwarnx_impl(const char*, va_list);
+
+static void
+vwarn_impl(const char *fmt, va_list ap)
+{
+	fprintf(stderr, "%s: ", getprogname());
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, ": %s\n", strerror(errno));
+}
+
+static void
+vwarnx_impl(const char *fmt, va_list ap)
+{
+	fprintf(stderr, "%s: ", getprogname());
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+}
+
+void
+err(int ret, const char *fmt, ...)
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+	vwarn_impl(fmt, va);
+	va_end(ap, fmt);
+	exit(ret);
+}
+
+void
+errx(int ret, const char *fmt, ...)
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+	vwarnx_impl(fmt, va);
+	va_end(ap, fmt);
+	exit(ret);
+}
+
+void
+warn(const char *fmt, ...)
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+	vwarn_impl(fmt, va);
+	va_end(ap, fmt);
+}
+
+void
+warnx(const char *fmt, ...)
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+	vwarnx_impl(fmt, va);
+	va_end(ap, fmt);
+}
blob - /dev/null
blob + f16226871ec9600344765767613eea8043231e3c (mode 644)
--- /dev/null
+++ compat/getprogname.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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.
+ */
+
+const char *
+getprogname(void)
+{
+	return "gmid";
+}
blob - /dev/null
blob + 2aa3f74dba5602a4f5ae7d2db91adb01d2f11a67 (mode 644)
--- /dev/null
+++ compat/strlcat.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left).  At most dsize-1 characters
+ * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t dsize)
+{
+	const char *odst = dst;
+	const char *osrc = src;
+	size_t n = dsize;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end. */
+	while (n-- != 0 && *dst != '\0')
+		dst++;
+	dlen = dst - odst;
+	n = dsize - dlen;
+
+	if (n-- == 0)
+		return(dlen + strlen(src));
+	while (*src != '\0') {
+		if (n != 0) {
+			*dst++ = *src;
+			n--;
+		}
+		src++;
+	}
+	*dst = '\0';
+
+	return(dlen + (src - osrc));	/* count does not include NUL */
+}
blob - /dev/null
blob + 7edee764d4315377f7cea47be3b6c731850dc9b3 (mode 644)
--- /dev/null
+++ compat/strlcpy.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy string src to buffer dst of size dsize.  At most dsize-1
+ * chars will be copied.  Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t dsize)
+{
+	const char *osrc = src;
+	size_t nleft = dsize;
+
+	/* Copy as many bytes as will fit. */
+	if (nleft != 0) {
+		while (--nleft != 0) {
+			if ((*dst++ = *src++) == '\0')
+				break;
+		}
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src. */
+	if (nleft == 0) {
+		if (dsize != 0)
+			*dst = '\0';		/* NUL-terminate dst */
+		while (*src++)
+			;
+	}
+
+	return(src - osrc - 1);	/* count does not include NUL */
+}
blob - /dev/null
blob + d76f3efb11248fbf53f5863121e132a4d9817f92 (mode 644)
--- /dev/null
+++ compat/vasprintf.c
@@ -0,0 +1,46 @@
+/* from mandoc, with tweaks */
+/*
+ * 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.
+ *
+ * This fallback implementation is not efficient:
+ * It does the formatting twice.
+ * Short of fiddling with the unknown internals of the system's
+ * printf(3) or completely reimplementing printf(3), i can't think
+ * of another portable solution.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+vasprintf(char **ret, const char *format, va_list ap)
+{
+	char	 buf[2];
+	va_list	 ap2;
+	int	 sz;
+
+	va_copy(ap2, ap);
+	sz = vsnprintf(buf, sizeof(buf), format, ap2);
+	va_end(ap2);
+
+	if (sz != -1 && (*ret = malloc(sz + 1)) != NULL) {
+		if (vsnprintf(*ret, sz + 1, format, ap) == sz)
+			return sz;
+		free(*ret);
+	}
+	*ret = NULL;
+	return -1;
+}
blob - /dev/null
blob + 328c7cfc9e9f43443a3fa6069edfe29b0f006bb2 (mode 755)
--- /dev/null
+++ configure
@@ -0,0 +1,328 @@
+#!/bin/sh
+#
+# Copyright (c) 2021 Omar Polo <op@omarpolo.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.
+
+# adapted from mandoc configure and oconfigure, thanks schwarze@ and
+# kristaps@!
+
+set -e
+
+[ -w config.log ] && mv config.log config.log.old
+[ -w config.h   ] && mv config.h   config.h.old
+
+# Output file descriptor usage:
+# 1 (stdout): config.h, Makefile.local
+# 2 (stderr): original stderr, usually to the console
+# 3: config.log
+
+exec 3> config.log
+echo "file config.log: writing..."
+
+# --------
+# default settings: initialize all vars here
+
+CC=cc
+CFLAGS=
+LDFLAGS=-ltls
+YACC=yacc
+LEX=lex
+STATIC=
+
+HAVE_ERR=
+HAVE_GETPROGNAME=
+HAVE_LIBTLS=
+HAVE_STRLCAT=
+HAVE_STRLCPY=
+HAVE_VASPRINTF=
+
+NEED_GNU_SOURCE=0
+NEED_OPENBSD_SOURCE=0
+
+PREFIX="/usr/local"
+BINDIR=
+
+INSTALL="install"
+
+# try to auto detect CFLAGS and LDFLAGS
+which pkg-config 2>/dev/null 1>&2 && {
+        if ! got=`pkg-config --cflags libtls`; then
+		CFLAGS="$got"
+	fi
+
+	if ! got=`pkg-config --libs libtls`; then
+		LDFLAGS="$got"
+	fi
+}
+
+# auto detect lex/flex
+which ${LEX} 2>/dev/null 1>&2 || {
+	echo "${LEX} not found: trying flex" 1>&2
+	echo "${LEX} not found: trying flex" 1>&3
+	LEX=flex
+	which ${LEX} 2>/dev/null 1>&2 || {
+		echo "${LEX} not found: giving up" 1>&2
+		echo "${LEX} not found: giving up" 1>&3
+		exit 1
+	}
+}
+
+# auto detect yacc/bison
+which ${YACC} 2>/dev/null 1>&2 || {
+	echo "${YACC} not found: trying bison" 1>&2
+	echo "${YACC} not found: trying bison" 1>&3
+	YACC=bison
+	which ${YACC} 2>/dev/null 1>&2 || {
+		echo "${YACC} not found: giving up" 1>&2
+		echo "${YACC} not found: giving up" 1>&3
+		exit 1
+	}
+}
+
+# --------
+# allow certain variables to be overridden on the command line
+
+for keyvals in "$@"; do
+	key=`echo $keyvals | cut -s -d '=' -f1`
+	if [ -z "$key" ]; then
+		echo "$0: invalid key-value: $keyvals" 1>&2
+		exit 1
+	fi
+	vals=`echo $keyvals | cut -d '=' -f 2-`
+	case "$key" in
+		BINDIR)  BINDIR="$val" ;;
+		CC)      CC="$val" ;;
+		CFLAGS)  CFLAGS="$val" ;;
+		DESTDIR) DESTDIR="$val" ;;
+		LDFLAGS) LDFLAGS="$val" ;;
+		LEX)     LEX="$lex" ;;
+		PREFIX)  PREFIX="$val" ;;
+		YACC)    YACC="$val" ;;
+		*)
+			echo "$0: invalid key: $key" 1>&2
+			exit 1
+	esac
+done
+
+# --------
+# tests functions
+
+# Check whether this HAVE_ setting is manually overridden.
+# If yes, use the override, if no, do not decide anything yet.
+# Arguments: test file name, test var name, manual value
+ismanual() {
+	[ -z "${3}" ] && return 1
+	echo "tested ${1}: HAVE_${2}=${3} (manual)" 1>&2
+	echo "tested ${1}: HAVE_${2}=${3} (manual)" 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: test file name, test var name, additional CFLAGS
+singletest() {
+	n=${1}${3}
+	cat 1>&3 << __HEREDOC__
+testing ${n} ...
+${COMP} -o have/${1} have/${1}.c ${3} ${LDFLAGS}
+__HEREDOC__
+
+	if ${COMP} -o "have/${1}" "have/${1}.c" ${3} ${LDFLAGS} 1>&3 2>&3
+	then
+		echo "partial result of ${n}: ${CC} succeeded" 1>&3
+	else
+		echo "tested ${n}: no (compilation failed)" 1>&2
+		echo "result of ${n}: ${CC} failed with exit status $?" 1>&3
+		echo "result of compiling ${n}: no" 1>&3
+		echo 1>&3
+		return 1
+	fi
+
+	if ./have/${1} 1>&3 2>&3; then
+		echo "tested ${n}: yes" 1>&2
+		echo "result of running ${n}: yes" 1>&3
+		echo 1>&3
+		eval HAVE_${2}=1
+		[ "${3}" = "-D_GNU_SOURCE" ] && NEED_GNU_SOURCE=1
+		[ "${3}" = "-D_OPENBSD_SOURCE" ] && NEED_OPENBSD_SOURCE=1
+		[ "${3}" = "-lsocket" ] && LD_RECVMSG="-lsocket"
+		rm "have/${1}"
+		return 0
+	else
+		echo "tested ${n}: no (execution failed)" 1>&2
+		echo "result of ${n}: execution failed with exit status $?" 1>&3
+		echo "result of running ${n}: no" 1>&3
+		echo 1>&3
+		rm "have/${1}"
+		return 1
+	fi
+}
+
+# Run a complete autoconfiguration test, including the check for
+# a manual override and disabling the feature on failure.
+# Arguments: test file name, test var name, additional CFLAGS
+# The final argument can optionally be repeated a second time.
+runtest() {
+	eval _manual=\${HAVE_${2}}
+	ismanual "${1}" "${2}" "${_manual}" && return 0
+	singletest "${1}" "${2}" "${3}" && return 0
+	[ -n "${4}" ] && singletest "${1}" "${2}" "${4}" && return 0
+	eval HAVE_${2}=0
+	return 1
+}
+
+# --------
+# compiler options
+
+DEFCFLAGS="-g -W -Wall -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings -Wno-unused-parameter"
+
+if [ -n "${CFLAGS}" ]; then
+	COMP="${CC} ${CFLAGS} -Wno-unused -Werror"
+else
+	COMP="${CC} ${CDEFCFLAGS} -Wno-unused -Werror"
+fi
+echo -n "testing ${CC} -W: " 1>&2
+echo -n "testing ${CC} -W: " 1>&3
+runtest noop WFLAG || true
+
+if [ -n "${CFLAGS}" ]; then
+	echo "CFLAGS specified manually:" 1>&3
+elif [ ${HAVE_WFLAG} -eq 0 ]; then
+	CFLAGS="-g"
+else
+	CFLAGS="${DEFCFLAGS}"
+fi
+echo "selected CFLAGS=\"${CFLAGS}\"" 1>&2
+echo "selected CFLAGS=\"${CFLAGS}\"" 1>&3
+echo 1>&3
+
+COMP="${CC} ${CFLAGS}"
+[ ${HAVE_WFLAG} -eq 0 ] || COMP="${COMP} -Wno-unused -Werror"
+
+if [ -n "${STATIC}" ]; then
+	echo "selected STATIC=\"${STATIC}\" (manual)" 1>&2
+	echo "selected STATIC=\"${STATIC}\" (manual)" 1>&3
+	echo 1>&3
+else
+	runtest noop STATIC -static || true
+	[ ${HAVE_STATIC} -eq 0 ] || STATIC="-static"
+	echo "selected STATIC=\"${STATIC}\"" 1>&2
+	echo "selected STATIC=\"${STATIC}\"" 1>&3
+	echo 1>&3
+fi
+
+# --------
+# tests for config.h
+
+runtest err		ERR		|| true
+runtest libtls		LIBTLS		|| true
+runtest strlcat		STRLCAT		|| true
+runtest strlcpy		STRLCPY		|| true
+runtest vasprintf	VASPRINTF	"" -D_GNU_SOURCE || true
+
+if [ ${HAVE_LIBTLS} -eq 0 ]; then
+	echo "FATAL: libtls not found" 1>&2
+	echo "FATAL: libtls not found" 1>&3
+	exit 1
+fi
+
+# --------
+# write config.h
+
+exec > config.h
+
+cat <<__HEREDOC__
+#ifdef __cplusplus
+#error "Do not use C++."
+#endif
+
+__HEREDOC__
+
+[ ${NEED_GNU_SOURCE} -eq 0 ] || echo "#define _GNU_SOURCE"
+[ ${NEED_OPENBSD_SOURCE} -eq 0 ] || echo "#define _OPENBSD_SOURCE"
+
+[ ${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 ] \
+	&& echo "#include <sys/types.h>"
+[ ${HAVE_VASPRINTF} -eq 0 ] && echo "#include <stdarg.h>"
+
+cat <<__HEREDOC__
+
+#define HAVE_ERR		${HAVE_ERR}
+#define HAVE_GETPROGNAME	${HAVE_GETPROGNAME}
+#define HAVE_STRLCAT		${HAVE_STRLCAT}
+#define HAVE_STRLCPY		${HAVE_STRLCPY}
+#define HAVE_VASPRINTF		${HAVE_VASPRINTF}
+
+__HEREDOC__
+
+if [ ${HAVE_ERR} -eq 0 ]; then
+	echo "extern	void	 err(int, const char*, ...);"
+	echo "extern	void	 errx(int, const char*, ...);"
+	echo "extern	void	 warn(const char*, ...);"
+	echo "extern	void	 warnx(const char*, ...);"
+	COMPAT="${COMPAT} compat/err.o"
+fi
+
+if [ ${HAVE_STRLCAT} -eq 0 ]; then
+	echo "extern	size_t	 strlcat(char*, const char*, size_t);"
+	COMPAT="${COMPAT} compat/strlcat.o"
+fi
+if [ ${HAVE_STRLCPY} -eq 0 ]; then
+	echo "extern	size_t	 strlcpy(char*, const char*, size_t);"
+	COMPAT="${COMPAT} compat/strlcpy.o"
+fi
+if [ ${HAVE_VASPRINTF} -eq 0 ]; then
+	echo "extern	int	 vasprintf(char**, const char*, va_list);"
+	COMPAT="${COMPAT} compat/vasprintf.o"
+fi
+echo "file config.h: written" 1>&2
+echo "file config.h: written" 1>&3
+
+# --------
+# tests for Makefile.local
+
+exec > Makefile.local
+
+[ -z "${BINDIR}"          ] && BINDIR="${PREFIX}/bin"
+[ -z "${MANDIR}"          ] && MANDIR="${PREFIX}/man"
+
+[ -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}
+LDFLAGS		= ${LDFLAGS}
+YACC		= ${YACC}
+LEX		= ${LEX}
+COMPAT		= ${COMPAT}
+STATIC		= ${STATIC}
+PREFIX		= ${PREFIX}
+BINDIR		= ${BINDIR}
+INCLUDEDIR	= ${INCLUDEDIR}
+INSTALL		= ${INSTALL}
+INSTALL_PROGRAM	= ${INSTALL_PROGRAM}
+INSTALL_LIB	= ${INSTALL_LIB}
+INSTALL_MAN	= ${INSTALL_MAN}
+INSTALL_DATA	= ${INSTALL_DATA}
+__HEREDOC__
+
+echo "file Makefile.local: written" 1>&2
+echo "file Makefile.local: written" 1>&3
+
+exit 0
blob - cd38c51e0113052d04747cc2eee316bab79d26d7
blob + a6b87817e0adbcdbadbd343903fa1ccf2e3d72a7
--- gmid.h
+++ gmid.h
@@ -28,6 +28,8 @@
 #include <tls.h>
 #include <unistd.h>
 
+#include "config.h"
+
 #ifndef INFTIM
 # define INFTIM -1
 #endif
blob - /dev/null
blob + 93eb816d939712b0bb93d05c88810f247ead41f7 (mode 644)
--- /dev/null
+++ have/err.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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 <err.h>
+
+int
+main(void)
+{
+	warnx("%d. warnx", 1);
+	warn("%d. warn", 2);
+	err(0, "%d. err", 3);
+        return 1;
+}
blob - /dev/null
blob + 57c0e2b059de0ac1a0662f96d0fe211a8f30e3db (mode 644)
--- /dev/null
+++ have/getprogname.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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 <stdlib.h>
+
+int
+main(void)
+{
+	return getprogname() == NULL;
+}
blob - /dev/null
blob + 42f83e446cbba70777e97075b1abbee7a18e651e (mode 644)
--- /dev/null
+++ have/libtls.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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 <tls.h>
+
+int
+main(void)
+{
+	return tls_init() != 0;
+}
blob - /dev/null
blob + 928d54f1fb4c084ed85ffe2b0f9058f2c87778dd (mode 644)
--- /dev/null
+++ have/noop.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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.
+ */
+
+int
+main(void)
+{
+	return 0;
+}
blob - /dev/null
blob + 0a005c57f59ab5c0b9c5cb707940cb875ce21dbb (mode 644)
--- /dev/null
+++ have/strlcat.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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>
+
+int
+main(void)
+{
+	char buf[3] = "a";
+	return ! (strlcat(buf, "b", sizeof(buf)) == 2 &&
+	    buf[0] == 'a' && buf[1] == 'b' && buf[2] == '\0');
+}
blob - /dev/null
blob + d1789354e72631744c3a953289693faa450da222 (mode 644)
--- /dev/null
+++ have/strlcpy.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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>
+
+int
+main(void)
+{
+	char buf[2] = "";
+	return ! (strlcpy(buf, "a", sizeof(buf)) == 1 &&
+	    buf[0] == 'a' && buf[1] == '\0');
+}
blob - /dev/null
blob + 2d1ac0b1d15ccd93ef5b50e92cb00d65f009f3b0 (mode 644)
--- /dev/null
+++ have/vasprintf.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.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 <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+static int	testfn(char **, const char*, ...);
+
+static int
+testfn(char **ret, const char *fmt, ...)
+{
+	va_list	ap;
+	int	irc;
+
+	va_start(ap, fmt);
+	irc = vasprintf(ret, fmt, ap);
+	va_end(ap);
+
+	return irc;
+}
+
+int
+main(void)
+{
+	char	*ret;
+
+	if (testfn(&ret, "%s.", "Text") != 5)
+		return 1;
+	if (strcmp(ret, "Text."))
+		return 2;
+	return 0;
+}