changeset 1065:d8db515adbd4

misc: remove usage of BSD errx?() functions
author David Demelier <markand@malikania.fr>
date Mon, 12 Jul 2021 20:40:45 +0200
parents f7f73da81a5f
children 1da37177a428
files irccd/conf.y irccd/main.c irccdctl/irccdctl.c lib/irccd/irccd.c lib/irccd/server.c lib/irccd/util.c lib/irccd/util.h man/libirccd-util.3 plugins/links/links.c tests/test-dl-plugin.c tests/test-plugin-ask.c tests/test-plugin-auth.c tests/test-plugin-hangman.c tests/test-plugin-history.c tests/test-plugin-joke.c tests/test-plugin-logger.c tests/test-plugin-plugin.c tests/test-plugin-tictactoe.c
diffstat 18 files changed, 112 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/irccd/conf.y	Mon Jul 05 21:50:14 2021 +0200
+++ b/irccd/conf.y	Mon Jul 12 20:40:45 2021 +0200
@@ -18,13 +18,13 @@
 
 %{
 
-#include <err.h>
+#include <errno.h>
 #include <grp.h>
 #include <limits.h>
 #include <pwd.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <stdlib.h>
 
 #include <irccd/irccd.h>
 #include <irccd/log.h>
@@ -294,7 +294,7 @@
 		else if (strcmp($5, "syslog") == 0)
 			irc_log_to_syslog();
 		else
-			errx(1, "missing log file path");
+			irc_util_die("missing log file path\n");
 
 		free($3);
 		free($5);
@@ -318,7 +318,7 @@
 		struct passwd *pwd;
 
 		if (!(pwd = getpwnam($2)))
-			errx(1, "invalid uid: %s", $2);
+			irc_util_die("invalid uid: %s\n", $2);
 
 		free($2);
 		$$ = pwd->pw_uid;
@@ -335,7 +335,7 @@
 		struct group *grp;
 
 		if (!(grp = getgrnam($2)))
-			errx(1, "invalid uid: %s", $2);
+			irc_util_die("invalid uid: %s\n", $2);
 
 		free($2);
 		$$ = grp->gr_gid;
@@ -501,7 +501,7 @@
 			else if (strcmp(s->value, "AUTO-RECONNECT") == 0)
 				$$->flags |= IRC_SERVER_FLAGS_AUTO_RECO;
 			else
-				errx(1, "invalid server option: %s", s->value);
+				irc_util_die("invalid server option: %s\n", s->value);
 		}
 
 		string_list_finish($2);
@@ -520,15 +520,15 @@
 		char *at;
 
 		if (irc_bot_server_get($2))
-			errx(1, "server %s already exists", $2);
+			irc_util_die("server %s already exists\n", $2);
 		if (!$4->hostname)
-			errx(1, "missing server hostname");
+			irc_util_die("missing server hostname\n");
 		if (!$4->nickname)
-			errx(1, "missing server nickname");
+			irc_util_die("missing server nickname\n");
 		if (!$4->username)
-			errx(1, "missing server username");
+			irc_util_die("missing server username\n");
 		if (!$4->realname)
-			errx(1, "missing server realname");
+			irc_util_die("missing server realname\n");
 
 		s = irc_server_new($2, $4->nickname, $4->username, $4->realname,
 			$4->hostname, $4->port);
@@ -638,7 +638,7 @@
 		const char *location = $3 ? $3->location : NULL;
 
 		if (irc_bot_plugin_get($2))
-			errx(1, "plugin %s already exists", $2);
+			irc_util_die("plugin %s already exists\n", $2);
 		if (!(p = irc_bot_plugin_find($2, location)))
 			goto cleanup;
 
@@ -671,7 +671,7 @@
 	: T_HOOK T_STRING T_TO T_STRING
 	{
 		if (irc_bot_hook_get($2))
-			errx(1, "hook %s already exists", $2);
+			irc_util_die("hook %s already exists\n", $2);
 
 		irc_bot_hook_add(irc_hook_new($2, $4));
 
@@ -685,14 +685,14 @@
 void
 yyerror(const char *err)
 {
-	errx(1, "%s:%d: %s", confpath, yylineno, err);
+	irc_util_die("%s:%d: %s\n", confpath, yylineno, err);
 }
 
 void
 config_open(const char *path)
 {
 	if (!(yyin = fopen(path, "r")))
-		err(1, "%s", path);
+		irc_util_die("%s: %s\n", path, strerror(errno));
 
 	strlcpy(confpath, path, sizeof (confpath));
 	yyparse();
--- a/irccd/main.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/irccd/main.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,7 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
 #include <errno.h>
 #include <poll.h>
 #include <signal.h>
@@ -133,7 +132,7 @@
 	sigemptyset(&sig.sa_mask);
 
 	if (sigaction(SIGINT, &sig, NULL) < 0 || sigaction(SIGTERM, &sig, NULL) < 0)
-		err(1, "sigaction");
+		irc_util_die("sigaction: %s\n", strerror(errno));
 }
 
 static void
@@ -203,7 +202,7 @@
 		pb = pollables();
 
 		if (poll(pb.fds, pb.fdsz, 1000) < 0 && errno != EINTR)
-			err(1, "poll");
+			irc_util_die("poll: %s\n", strerror(errno));
 
 		flush(&pb);
 
--- a/irccdctl/irccdctl.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/irccdctl/irccdctl.c	Mon Jul 12 20:40:45 2021 +0200
@@ -21,7 +21,6 @@
 #include <sys/un.h>
 #include <assert.h>
 #include <ctype.h>
-#include <err.h>
 #include <errno.h>
 #include <limits.h>
 #include <stdarg.h>
@@ -56,9 +55,9 @@
 		ssize_t nr;
 
 		if ((nr = recv(sock, buf, sizeof (buf) - 1, 0)) <= 0)
-			errc(1, nr == 0 ? ECONNRESET : errno, "abort");
+			irc_util_die("abort: %s\n", strerror(nr == 0 ? ECONNRESET : errno));
 		if (strlcat(in, buf, sizeof (in)) >= sizeof (in))
-			errc(1, EMSGSIZE, "abort");
+			irc_util_die("abort: %s\n", strerror(EMSGSIZE));
 	}
 
 	*nl = '\0';
@@ -76,12 +75,12 @@
 	};
 
 	if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
-		err(1, "socket");
+		irc_util_die("abort: socket: %s\n", strerror(errno));
 	if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (tv)) < 0 ||
 	    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv)) < 0)
-		err(1, "setsockopt");
+		irc_util_die("abort: setsockopt: %s\n", strerror(errno));
 	if (connect(sock, (const struct sockaddr *)&sockaddr, SUN_LEN(&sockaddr)) < 0)
-		err(1, "connect");
+		irc_util_die("abort: connect: %s\n", strerror(errno));
 }
 
 static void
@@ -91,7 +90,7 @@
 	int major, minor, patch;
 
 	if ((sscanf(poll(), "IRCCD %d.%d.%d", &major, &minor, &patch) != 3))
-		errx(1, "abort: not irccd instance");
+		irc_util_die("abort: not irccd instance\n");
 	if (verbose)
 		printf("connected to irccd %d.%d.%d\n", major, minor, patch);
 }
@@ -108,7 +107,7 @@
 
 	if (strlcat(out, buf, sizeof (out)) >= sizeof (out) ||
 	    strlcat(out, "\n", sizeof (out)) >= sizeof (out))
-		errc(1, EMSGSIZE, "abort");
+		irc_util_die("abort: %s\n", strerror(EMSGSIZE));
 
 	while (out[0]) {
 		ssize_t ns, len;
@@ -116,7 +115,7 @@
 		len = strlen(out);
 
 		if ((ns = send(sock, out, len, MSG_NOSIGNAL)) <= 0)
-			err(1, "send");
+			irc_util_die("abort: send: %s\n", strerror(errno));
 
 		if (ns >= len)
 			memset(out, 0, sizeof (out));
@@ -131,7 +130,7 @@
 	char *response = poll();
 
 	if (strncmp(response, "OK", 2) != 0)
-		errx(1, "abort: %s", response);
+		irc_util_die("abort: %s\n", response);
 
 	/* Skip "OK". */
 	response += 2;
@@ -371,7 +370,7 @@
 		req("%s %s", cmd, argv[0]);
 
 	if (sscanf(line = ok(), "%zu", &num) != 1)
-		errx(1, "could not retrieve list");
+		irc_util_die("abort: could not retrieve list\n");
 
 	if (argc == 2)
 		puts(poll());
@@ -396,7 +395,7 @@
 	req(cmd);
 
 	if (strncmp(list = poll(), "OK ", 3) != 0)
-		errx(1, "failed to retrieve plugin list");
+		irc_util_die("abort: failed to retrieve plugin list\n");
 
 	list += 3;
 
@@ -459,7 +458,7 @@
 	req("PLUGIN-INFO %s", argv[0]);
 
 	if (strncmp((response = poll()), "OK ", 3) != 0)
-		errx(1, "failed to retrieve plugin information");
+		irc_util_die("abort: failed to retrieve plugin information\n");
 
 	printf("%-16s%s\n", "name:", response + 3);
 	printf("%-16s%s\n", "summary:", poll());
@@ -528,7 +527,7 @@
 	char out[IRC_BUF_LEN];
 
 	if (!(fp = fmemopen(out, sizeof (out) - 1, "w")))
-		err(1, "fmemopen");
+		irc_util_die("abort: fmemopen: %s\n", strerror(errno));
 
 	/* TODO: invalid option. */
 	for (int ch; (ch = ketopt(&ko, argc, argv, 0, "c:e:i:o:p:s:", NULL)) != -1; )
@@ -538,12 +537,12 @@
 	argv += ko.ind;
 
 	if (argc < 1)
-		errx(1, "missing accept or drop rule action");
+		irc_util_die("abort: missing accept or drop rule action\n");
 
 	fprintf(fp, "%s", argv[0]);
 
 	if (ferror(fp) || feof(fp))
-		err(1, "fprintf");
+		irc_util_die("abort: fprintf: %s\n", strerror(errno));
 
 	fclose(fp);
 	req("RULE-ADD %s %s", argv[0], out);
@@ -558,7 +557,7 @@
 	char out[IRC_BUF_LEN];
 
 	if (!(fp = fmemopen(out, sizeof (out) - 1, "w")))
-		err(1, "fmemopen");
+		irc_util_die("abort: fmemopen: %s\n", strerror(errno));
 
 	/* TODO: invalid option. */
 	for (int ch; (ch = ketopt(&ko, argc, argv, 0, "a:C:c:E:e:O:o:P:p:S:s:", NULL)) != -1; ) {
@@ -572,10 +571,9 @@
 	argv += ko.ind;
 
 	if (argc < 1)
-		errx(1, "missing rule index");
-
+		irc_util_die("abort: missing rule index\n");
 	if (ferror(fp) || feof(fp))
-		err(1, "fprintf");
+		irc_util_die("abort: fprintf: %s\n", strerror(errno));
 
 	fclose(fp);
 	req("RULE-EDIT %s %s", argv[0], out);
@@ -605,7 +603,7 @@
 	req("RULE-LIST");
 
 	if (sscanf(ok(), "%zu", &num) != 1)
-		errx(1, "could not retrieve rule list");
+		irc_util_die("abort: could not retrieve rule list\n");
 
 	for (size_t i = 0; i < num; ++i) {
 		printf("%-16s%zu\n", "index:", i);
@@ -630,9 +628,9 @@
 	const char *errstr;
 
 	if ((from = strtonum(argv[0], 0, LLONG_MAX, &errstr)) == 0 && errstr)
-		err(1, "%s", argv[0]);
+		irc_util_die("abort: %s: %s\n", argv[0], errstr);
 	if ((to = strtonum(argv[1], 0, LLONG_MAX, &errstr)) == 0 && errstr)
-		err(1, "%s", argv[1]);
+		irc_util_die("abort: %s: %s\n", argv[1], errstr);
 
 	req("RULE-MOVE %lld %lld", from, to);
 	ok();
@@ -683,7 +681,7 @@
 	argv += ko.ind;
 
 	if (argc < 2)
-		errx(1, "missing id and/or host");
+		irc_util_die("abort: missing id and/or host\n");
 
 	req("SERVER-CONNECT %s %s %s%s %s %s %s", argv[0], argv[1], (ssl ? "+" : ""),
 	    port, nickname, username, realname);
@@ -720,12 +718,12 @@
 	req("SERVER-INFO %s", argv[0]);
 
 	if (strncmp(list = poll(), "OK ", 3) != 0)
-		errx(1, "failed to retrieve server information");
+		irc_util_die("abort: failed to retrieve server information\n");
 
 	printf("%-16s%s\n", "name:", list + 3);
 
 	if (irc_util_split((list = poll()), args, 3, ' ') < 2)
-		errx(1, "malformed server connection");
+		irc_util_die("abort: malformed server connection\n");
 
 	printf("%-16s%s\n", "hostname:", args[0]);
 	printf("%-16s%s\n", "port:", args[1]);
@@ -734,7 +732,7 @@
 		printf("%-16s%s\n", "ssl:", "true");
 
 	if (irc_util_split((list = poll()), args, 3, ' ') != 3)
-		errx(1, "malformed server ident");
+		irc_util_die("abort: malformed server ident\n");
 
 	printf("%-16s%s\n", "nickname:", args[0]);
 	printf("%-16s%s\n", "username:", args[0]);
@@ -853,7 +851,7 @@
 
 	/* Turn off timeout to receive indefinitely. */
 	if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv)) < 0)
-		err(1, "setsockopt");
+		irc_util_die("abort: setsockopt: %s\n", strerror(errno));
 
 	while ((ev = poll()))
 		show(ev);
@@ -916,13 +914,13 @@
 	const struct cmd *c;
 
 	if (!(c = find_cmd(argv[0])))
-		errx(1, "abort: command not found");
+		irc_util_die("abort: command not found\n");
 
 	--argc;
 	++argv;
 
 	if ((c->minargs != -1 && argc < c->minargs) || (c->minargs != -1 && argc > c->maxargs))
-		errx(1, "abort: invalid number of arguments");
+		irc_util_die("abort: invalid number of arguments\n");
 
 	c->exec(argc, argv);
 }
--- a/lib/irccd/irccd.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/lib/irccd/irccd.c	Mon Jul 12 20:40:45 2021 +0200
@@ -19,7 +19,6 @@
 #include <sys/wait.h>
 #include <assert.h>
 #include <ctype.h>
-#include <err.h>
 #include <errno.h>
 #include <poll.h>
 #include <signal.h>
@@ -181,10 +180,10 @@
 	if (fd->fd != pipes[0] || !(fd->revents & POLLIN))
 		return;
 
-	if (read(fd->fd, &df, sizeof (df)) != sizeof (df))
-		err(1, "read");
-
-	df.exec(df.data);
+	if (read(fd->fd, &df, sizeof (df)) == sizeof (df))
+		df.exec(df.data);
+	else
+		irc_log_warn("irccd: %s", strerror(errno));
 }
 
 static struct irc_plugin *
@@ -261,7 +260,7 @@
 	irc_log_to_console();
 
 	if (pipe(pipes) < 0)
-		err(1, "pipe");
+		irc_util_die("pipe: %s\n", strerror(errno));
 
 	sa.sa_flags = SA_SIGINFO;
 	sa.sa_sigaction = handle_sigchld;
@@ -269,7 +268,7 @@
 	sigemptyset(&sa.sa_mask);
 
 	if (sigaction(SIGCHLD, &sa, NULL) < 0)
-		err(1, "sigaction");
+		irc_util_die("sigaction: %s\n", strerror(errno));
 }
 
 void
@@ -641,7 +640,7 @@
 	};
 
 	if (write(pipes[1], &df, sizeof (df)) != sizeof (df))
-		err(1, "write");
+		irc_log_warn("write: %s\n", strerror(errno));
 }
 
 void
--- a/lib/irccd/server.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/lib/irccd/server.c	Mon Jul 12 20:40:45 2021 +0200
@@ -18,7 +18,6 @@
 
 #include <assert.h>
 #include <errno.h>
-#include <err.h>
 #include <poll.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -533,7 +532,7 @@
 	ch = irc_server_find(s, ev->names.channel);
 
 	if (!(fp = open_memstream(&ev->names.names, &length)))
-		err(1, "open_memstream");
+		return;
 
 	LIST_FOREACH(u, &ch->users, link) {
 		for (size_t i = 0; i < IRC_UTIL_SIZE(s->params.prefixes); ++i)
--- a/lib/irccd/util.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/lib/irccd/util.c	Mon Jul 12 20:40:45 2021 +0200
@@ -17,7 +17,7 @@
  */
 
 #include <assert.h>
-#include <err.h>
+#include <errno.h>
 #include <libgen.h>
 #include <limits.h>
 #include <stdarg.h>
@@ -33,7 +33,7 @@
 	void *ret;
 
 	if (!(ret = malloc(size)))
-		err(1, "malloc");
+		irc_util_die("malloc: %s\n", strerror(errno));
 
 	return ret;
 }
@@ -44,7 +44,7 @@
 	void *ret;
 
 	if (!(ret = calloc(n, size)))
-		err(1, "calloc");
+		irc_util_die("calloc: %s\n", strerror(errno));
 
 	return ret;
 }
@@ -55,7 +55,7 @@
 	void *ret;
 
 	if (!(ret = realloc(ptr, size)) && size)
-		err(1, "realloc");
+		irc_util_die("realloc: %s\n", strerror(errno));
 
 	return ret;
 }
@@ -66,7 +66,7 @@
 	void *ret;
 
 	if (!(ret = reallocarray(ptr, n, size)))
-		err(1, "reallocarray");
+		irc_util_die("reallocarray: %s\n", strerror(errno));
 
 	return ret;
 }
@@ -74,12 +74,9 @@
 void *
 irc_util_memdup(const void *ptr, size_t size)
 {
-	void *ret;
+	assert(ptr);
 
-	if (!(ret = malloc(size)))
-		err(1, "malloc");
-
-	return memcpy(ret, ptr, size);
+	return memcpy(irc_util_malloc(size), ptr, size);
 }
 
 char *
@@ -88,7 +85,7 @@
 	char *ret;
 
 	if (!(ret = strdup(src)))
-		err(1, "strdup");
+		irc_util_die("strdup: %s\n", strerror(errno));
 
 	return ret;
 }
@@ -101,7 +98,7 @@
 	char *ret;
 
 	if (!(ret = strndup(src, n)))
-		err(1, "strndup");
+		irc_util_die("strndup: %s\n", strerror(errno));
 
 	return ret;
 }
@@ -169,3 +166,16 @@
 
 	return buf;
 }
+
+noreturn void
+irc_util_die(const char *fmt, ...)
+{
+	assert(fmt);
+
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
--- a/lib/irccd/util.h	Mon Jul 05 21:50:14 2021 +0200
+++ b/lib/irccd/util.h	Mon Jul 12 20:40:45 2021 +0200
@@ -20,6 +20,7 @@
 #define IRCCD_UTIL_H
 
 #include <stddef.h>
+#include <stdnoreturn.h>
 
 #if defined(__cplusplus)
 extern "C" {
@@ -63,6 +64,9 @@
 char *
 irc_util_printf(char *, size_t, const char *, ...);
 
+noreturn void
+irc_util_die(const char *, ...);
+
 #if defined(__cplusplus)
 }
 #endif
--- a/man/libirccd-util.3	Mon Jul 05 21:50:14 2021 +0200
+++ b/man/libirccd-util.3	Mon Jul 12 20:40:45 2021 +0200
@@ -46,6 +46,8 @@
 .Fn irc_util_split "char *str, const char **args, size_t max, char delimiter"
 .Ft char *
 .Fn irc_util_printf "char *str, size_t strsz, const char *fmt, ..."
+.Ft noreturn void
+.Fn irc_util_die "const char *fmt, ..."
 .\" DESCRIPTION
 .Sh DESCRIPTION
 This header provides several function for memory management and basic string
@@ -170,8 +172,15 @@
 signature except that it returns the
 .Fa str
 argument for convenience.
+.Pp
+The
+.Fn irc_util_die
+function is a function that writes a message format using the same signature as
+.Xr printf 3
+and exits with code 1. It is meant to be used when the program is unable to
+recover from a fatal error and should be avoided in library code.
 .\" RETURN VALUES
-.Sh RETURN VALUELS
+.Sh RETURN VALUES
 All memory functions
 .Fn irc_util_malloc ,
 .Fn irc_util_calloc ,
--- a/plugins/links/links.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/plugins/links/links.c	Mon Jul 12 20:40:45 2021 +0200
@@ -18,7 +18,6 @@
 
 #include <assert.h>
 #include <ctype.h>
-#include <err.h>
 #include <errno.h>
 #include <pthread.h>
 #include <regex.h>
--- a/tests/test-dl-plugin.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-dl-plugin.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,7 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
+#include <errno.h>
+#include <string.h>
 
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
@@ -26,6 +27,7 @@
 #include <irccd/event.h>
 #include <irccd/plugin.h>
 #include <irccd/server.h>
+#include <irccd/util.h>
 
 static struct irc_plugin *plugin;
 
@@ -36,7 +38,7 @@
 
 	/* TODO: No idea how to stop greatest from here. */
 	if ((plugin = dl_plugin_open("example", TOP "/tests/data/example-dl-plugin.so")) == NULL)
-		err(1, "dlopen");
+		irc_util_die("dlopen: %s\n", strerror(errno));
 }
 
 static void
--- a/tests/test-plugin-ask.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-ask.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
-
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
 
@@ -25,6 +23,7 @@
 #include <irccd/js-plugin.h>
 #include <irccd/plugin.h>
 #include <irccd/server.h>
+#include <irccd/util.h>
 
 static struct irc_server *server;
 static struct irc_plugin *plugin;
@@ -38,7 +37,7 @@
 	plugin = js_plugin_open("test", TOP "/plugins/ask/ask.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	irc_server_incref(server);
 	irc_plugin_set_option(plugin, "file", TOP "/tests/data/answers.conf");
--- a/tests/test-plugin-auth.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-auth.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
-
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
 
@@ -25,6 +23,7 @@
 #include <irccd/js-plugin.h>
 #include <irccd/plugin.h>
 #include <irccd/server.h>
+#include <irccd/util.h>
 
 /*
  * 0 -> nickserv without nickname
@@ -45,7 +44,7 @@
 	plugin = js_plugin_open("test", TOP "/plugins/auth/auth.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	irc_server_incref(servers[0]);
 	irc_server_incref(servers[1]);
--- a/tests/test-plugin-hangman.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-hangman.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
-
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
 
@@ -26,6 +24,7 @@
 #include <irccd/log.h>
 #include <irccd/plugin.h>
 #include <irccd/server.h>
+#include <irccd/util.h>
 
 #define CALL(t, m) do {                                                 \
         memset(server->conn->out, 0, sizeof (server->conn->out));       \
@@ -65,7 +64,7 @@
 	plugin = js_plugin_open("hangman", TOP "/plugins/hangman/hangman.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	irc_log_to_console();
 	irc_server_incref(server);
--- a/tests/test-plugin-history.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-history.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
-
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
 
@@ -26,6 +24,7 @@
 #include <irccd/log.h>
 #include <irccd/plugin.h>
 #include <irccd/server.h>
+#include <irccd/util.h>
 
 #define CALL(t, m) do {                                                 \
         memset(server->conn->out, 0, sizeof (server->conn->out));       \
@@ -67,7 +66,7 @@
 	plugin = js_plugin_open("history", TOP "/plugins/history/history.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	irc_log_to_console();
 	irc_server_incref(server);
--- a/tests/test-plugin-joke.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-joke.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
-
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
 
@@ -25,6 +23,7 @@
 #include <irccd/js-plugin.h>
 #include <irccd/plugin.h>
 #include <irccd/server.h>
+#include <irccd/util.h>
 
 #define CALL() do {                                                     \
         memset(server->conn->out, 0, sizeof (server->conn->out));       \
@@ -51,7 +50,7 @@
 	plugin = js_plugin_open("joke", TOP "/plugins/joke/joke.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	irc_server_incref(server);
 	irc_plugin_set_template(plugin, "error", "error=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}");
--- a/tests/test-plugin-logger.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-logger.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,7 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
+#include <errno.h>
+#include <string.h>
 
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
@@ -25,6 +26,7 @@
 #include <irccd/log.h>
 #include <irccd/plugin.h>
 #include <irccd/server.h>
+#include <irccd/util.h>
 
 static struct irc_server *server;
 static struct irc_plugin *plugin;
@@ -40,7 +42,7 @@
 	plugin = js_plugin_open("logger", TOP "/plugins/logger/logger.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	irc_server_incref(server);
 	irc_plugin_set_template(plugin, "join", "join=#{server}:#{channel}:#{origin}:#{nickname}");
@@ -79,9 +81,9 @@
 	buf[0] = '\0';
 
 	if (!(fp = fopen(TOP "/tests/log", "r")))
-		err(1, "fopen");
+		irc_util_die("fopen: %s\n", strerror(errno));
 	if (!(fgets(buf, sizeof (buf), fp)))
-		err(1, "fgets");
+		irc_util_die("fgets: %s\n", strerror(errno));
 
 	fclose(fp);
 
--- a/tests/test-plugin-plugin.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-plugin.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,7 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
 #include <string.h>
 
 #define GREATEST_USE_ABBREVS 0
@@ -66,7 +65,7 @@
 	plugin = js_plugin_open("plugin", TOP "/plugins/plugin/plugin.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	/* Prepare a fake plugin. */
 	fake = irc_util_calloc(1, sizeof (*fake));
--- a/tests/test-plugin-tictactoe.c	Mon Jul 05 21:50:14 2021 +0200
+++ b/tests/test-plugin-tictactoe.c	Mon Jul 12 20:40:45 2021 +0200
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <err.h>
-
 #define GREATEST_USE_ABBREVS 0
 #include <greatest.h>
 
@@ -67,7 +65,7 @@
 	plugin = js_plugin_open("tictactoe", TOP "/plugins/tictactoe/tictactoe.js");
 
 	if (!plugin)
-		errx(1, "could not load plugin");
+		irc_util_die("could not load plugin\n");
 
 	irc_bot_init();
 	irc_server_incref(server);
@@ -108,7 +106,7 @@
 	irc_util_split(buf, lines, 5, '\n');
 
 	if (!lines[4] || sscanf(lines[4], "PRIVMSG #tictactoe :turn=#tictactoe:!tictactoe:%c:tictactoe:test\r\n", &player) != 1)
-		errx(1, "could not determine player");
+		irc_util_die("could not determine player\n");
 
 	free(buf);