smtpd: create startup.c

Martijn van Duren <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <[email protected]>
Hello tech@,

Here's a followup to the shuffling of the deckchairs diff. This diff is
basically more of the same, but creates a new startup.c for functions
and variables that would cause issues for smtpctl when added to util.c.

I realize that startup.c isn't an ideal name, but since it's needed give
each libexec binary their own main() function it's the best I could come
up with.

This diff moves the env, p_*, profiling, backend_*, smtpd_process
variables, and imsg_callback, and setup_peer(), setup_proc(),
imsg_wait(), load_pki_tree(), load_pki_keys(), fork_proc_backend(),
and imsg_dispatch() functions into startup.c.

The debug variable appears to be a dead store, so can be removed.

The next step is giving each binary their own main().

OK?

martijn@

diff d010102fe4efde3ee95164581695909c7c6b672a 7c135bf813cf25880851c83cbd4734bfe1ac67c3
commit - d010102fe4efde3ee95164581695909c7c6b672a
commit + 7c135bf813cf25880851c83cbd4734bfe1ac67c3
blob - a6337c2bb329e27300a21ffa517a5a84d0f773c5
blob + 37b6919a9da103b0f3ce6bccfcb98f6dd5a47d6e
--- usr.sbin/smtpd/smtpd/Makefile
+++ usr.sbin/smtpd/smtpd/Makefile
@@ -14,7 +14,7 @@ SRCS=	aliases.c bounce.c ca.c compress_backend.c confi
 	dispatcher.c proxy.c queue.c queue_backend.c report_smtp.c \
 	resolver.c rfc5322.c ruleset.c runq.c scheduler.c \
 	scheduler_backend.c smtp.c smtp_session.c smtpd.c srs.c ssl.c \
-	stat_backend.c table.c to.c tree.c util.c waitq.c \
+	startup.c stat_backend.c table.c to.c tree.c util.c waitq.c \
 	compress_gzip.c table_db.c table_getpwnam.c table_proc.c \
 	table_static.c queue_fs.c queue_null.c queue_proc.c \
 	queue_ram.c scheduler_ramqueue.c scheduler_null.c \
blob - 206cd414a29ac4acbb22b6a540c5ca2751098e90
blob + a00f8c6d79b8fea6b9071776ced8a909654aefd4
--- usr.sbin/smtpd/smtpd-ca/Makefile
+++ usr.sbin/smtpd/smtpd-ca/Makefile
@@ -15,7 +15,7 @@ SRCS=	aliases.c bounce.c ca.c compress_backend.c confi
 	dispatcher.c proxy.c queue.c queue_backend.c report_smtp.c \
 	resolver.c rfc5322.c ruleset.c runq.c scheduler.c \
 	scheduler_backend.c smtp.c smtp_session.c smtpd.c srs.c ssl.c \
-	stat_backend.c table.c to.c tree.c util.c waitq.c \
+	startup.c stat_backend.c table.c to.c tree.c util.c waitq.c \
 	compress_gzip.c table_db.c table_getpwnam.c table_proc.c \
 	table_static.c queue_fs.c queue_null.c queue_proc.c \
 	queue_ram.c scheduler_ramqueue.c scheduler_null.c \
blob - 22d7abdc025cccaec993ecec8f4ab7c4377fd8b3
blob + d289b421744c03b32a2296c421e9f3734cd44089
--- usr.sbin/smtpd/smtpd-control/Makefile
+++ usr.sbin/smtpd/smtpd-control/Makefile
@@ -15,7 +15,7 @@ SRCS=	aliases.c bounce.c ca.c compress_backend.c confi
 	dispatcher.c proxy.c queue.c queue_backend.c report_smtp.c \
 	resolver.c rfc5322.c ruleset.c runq.c scheduler.c \
 	scheduler_backend.c smtp.c smtp_session.c smtpd.c srs.c ssl.c \
-	stat_backend.c table.c to.c tree.c util.c waitq.c \
+	startup.c stat_backend.c table.c to.c tree.c util.c waitq.c \
 	compress_gzip.c table_db.c table_getpwnam.c table_proc.c \
 	table_static.c queue_fs.c queue_null.c queue_proc.c \
 	queue_ram.c scheduler_ramqueue.c scheduler_null.c \
blob - 9aa8e1c7ceb3112f7aaba17352f5b5aa3b242bf7
blob + f4c47fd8387e2bf7ee7c22a395f5e74b099be30d
--- usr.sbin/smtpd/smtpd-dispatcher/Makefile
+++ usr.sbin/smtpd/smtpd-dispatcher/Makefile
@@ -15,7 +15,7 @@ SRCS=	aliases.c bounce.c ca.c compress_backend.c confi
 	dispatcher.c proxy.c queue.c queue_backend.c report_smtp.c \
 	resolver.c rfc5322.c ruleset.c runq.c scheduler.c \
 	scheduler_backend.c smtp.c smtp_session.c smtpd.c srs.c ssl.c \
-	stat_backend.c table.c to.c tree.c util.c waitq.c \
+	startup.c stat_backend.c table.c to.c tree.c util.c waitq.c \
 	compress_gzip.c table_db.c table_getpwnam.c table_proc.c \
 	table_static.c queue_fs.c queue_null.c queue_proc.c \
 	queue_ram.c scheduler_ramqueue.c scheduler_null.c \
blob - 03476d16571fc4fb85105215a79543bfb9882166
blob + 0b82bec27876d79e60fa80a4a65436fe3633142e
--- usr.sbin/smtpd/smtpd-lka/Makefile
+++ usr.sbin/smtpd/smtpd-lka/Makefile
@@ -15,7 +15,7 @@ SRCS=	aliases.c bounce.c ca.c compress_backend.c confi
 	dispatcher.c proxy.c queue.c queue_backend.c report_smtp.c \
 	resolver.c rfc5322.c ruleset.c runq.c scheduler.c \
 	scheduler_backend.c smtp.c smtp_session.c smtpd.c srs.c ssl.c \
-	stat_backend.c table.c to.c tree.c util.c waitq.c \
+	startup.c stat_backend.c table.c to.c tree.c util.c waitq.c \
 	compress_gzip.c table_db.c table_getpwnam.c table_proc.c \
 	table_static.c queue_fs.c queue_null.c queue_proc.c \
 	queue_ram.c scheduler_ramqueue.c scheduler_null.c \
blob - 6fce8a91f1035dffdd28a98bb546d0ed5c62b977
blob + 7b6651dbeda248bc110f0b655118e59e23dfd9b2
--- usr.sbin/smtpd/smtpd-queue/Makefile
+++ usr.sbin/smtpd/smtpd-queue/Makefile
@@ -15,7 +15,7 @@ SRCS=	aliases.c bounce.c ca.c compress_backend.c confi
 	dispatcher.c proxy.c queue.c queue_backend.c report_smtp.c \
 	resolver.c rfc5322.c ruleset.c runq.c scheduler.c \
 	scheduler_backend.c smtp.c smtp_session.c smtpd.c srs.c ssl.c \
-	stat_backend.c table.c to.c tree.c util.c waitq.c \
+	startup.c stat_backend.c table.c to.c tree.c util.c waitq.c \
 	compress_gzip.c table_db.c table_getpwnam.c table_proc.c \
 	table_static.c queue_fs.c queue_null.c queue_proc.c \
 	queue_ram.c scheduler_ramqueue.c scheduler_null.c \
blob - 93076c8a5241d7202b0810b4d3d723377dbaba1d
blob + d26854ca8cd02f506b2c4ebaf93fc204f0130a2c
--- usr.sbin/smtpd/smtpd-scheduler/Makefile
+++ usr.sbin/smtpd/smtpd-scheduler/Makefile
@@ -15,7 +15,7 @@ SRCS=	aliases.c bounce.c ca.c compress_backend.c confi
 	dispatcher.c proxy.c queue.c queue_backend.c report_smtp.c \
 	resolver.c rfc5322.c ruleset.c runq.c scheduler.c \
 	scheduler_backend.c smtp.c smtp_session.c smtpd.c srs.c ssl.c \
-	stat_backend.c table.c to.c tree.c util.c waitq.c \
+	startup.c stat_backend.c table.c to.c tree.c util.c waitq.c \
 	compress_gzip.c table_db.c table_getpwnam.c table_proc.c \
 	table_static.c queue_fs.c queue_null.c queue_proc.c \
 	queue_ram.c scheduler_ramqueue.c scheduler_null.c \
blob - 7292b6810caaa49358b7b92ef3f26ade95d2ea42
blob + de95861f48bf015b5cc1cce1857a8318d266111b
--- usr.sbin/smtpd/smtpd.c
+++ usr.sbin/smtpd/smtpd.c
@@ -59,12 +59,8 @@ static void forkmda(struct mproc *, uint64_t, struct d
 static int parent_forward_open(char *, char *, uid_t, gid_t);
 static struct child *child_add(pid_t, int, const char *);
 static struct mproc *start_child(int, char **, char *);
-static struct mproc *setup_peer(enum smtp_proc_type, pid_t, int);
 static void setup_peers(struct mproc *, struct mproc *);
 static void setup_done(struct mproc *);
-static void setup_proc(void);
-static struct mproc *setup_peer(enum smtp_proc_type, pid_t, int);
-static int imsg_wait(struct imsgbuf *, struct imsg *, int);
 
 static void	offline_scan(int, short, void *);
 static int	offline_add(char *, uid_t, gid_t);
@@ -73,8 +69,6 @@ static int	offline_enqueue(char *, uid_t, gid_t);
 
 static void	purge_task(void);
 static int	parent_auth_user(const char *, const char *);
-static void	load_pki_tree(void);
-static void	load_pki_keys(void);
 
 static void	fork_filter_processes(void);
 static void	fork_filter_process(const char *, struct filter_proc *);
@@ -115,26 +109,11 @@ static struct timeval		offline_timeout;
 static pid_t			purge_pid = -1;
 
 extern char	**environ;
-void		(*imsg_callback)(struct mproc *, struct imsg *);
 
-enum smtp_proc_type	smtpd_process;
+extern const char	*backend_queue;
+extern const char	*backend_scheduler;
+extern const char	*backend_stat;
 
-struct smtpd	*env = NULL;
-
-struct mproc	*p_control = NULL;
-struct mproc	*p_lka = NULL;
-struct mproc	*p_parent = NULL;
-struct mproc	*p_queue = NULL;
-struct mproc	*p_scheduler = NULL;
-struct mproc	*p_dispatcher = NULL;
-struct mproc	*p_ca = NULL;
-
-const char	*backend_queue = "fs";
-const char	*backend_scheduler = "ramqueue";
-const char	*backend_stat = "ram";
-
-int	profiling = 0;
-int	debug = 0;
 int	foreground = 0;
 int	control_socket = -1;
 
@@ -483,7 +462,6 @@ main(int argc, char *argv[])
 
 	flags = 0;
 	opts = 0;
-	debug = 0;
 	tracing = 0;
 
 	log_init(1, LOG_MAIL);
@@ -523,7 +501,6 @@ main(int argc, char *argv[])
 			usage();
 			break;
 		case 'n':
-			debug = 2;
 			opts |= SMTPD_OPT_NOACTION;
 			break;
 		case 'f':
@@ -902,136 +879,6 @@ setup_done(struct mproc *p)
 	imsg_free(&imsg);
 }
 
-static void
-setup_proc(void)
-{
-	struct imsgbuf *ibuf;
-	struct imsg imsg;
-        int setup = 1;
-
-	log_procinit(proc_title(smtpd_process));
-
-	p_parent = calloc(1, sizeof(*p_parent));
-	if (p_parent == NULL)
-		fatal("calloc");
-	if((p_parent->name = strdup("parent")) == NULL)
-		fatal("strdup");
-	p_parent->proc = PROC_PARENT;
-	p_parent->handler = imsg_dispatch;
-	mproc_init(p_parent, 3);
-
-	ibuf = &p_parent->imsgbuf;
-
-	while (setup) {
-		if (imsg_wait(ibuf, &imsg, 10000) == -1)
-			fatal("imsg_wait");
-
-		switch (imsg.hdr.type) {
-		case IMSG_SETUP_KEY:
-			env->sc_queue_key = strdup(imsg.data);
-			break;
-		case IMSG_SETUP_PEER:
-			setup_peer(imsg.hdr.peerid, imsg.hdr.pid,
-			    imsg_get_fd(&imsg));
-			break;
-		case IMSG_SETUP_DONE:
-			setup = 0;
-			break;
-		default:
-			fatal("bad imsg %d", imsg.hdr.type);
-		}
-		imsg_free(&imsg);
-	}
-
-	if (imsg_compose(ibuf, IMSG_SETUP_DONE, 0, 0, -1, NULL, 0) == -1)
-		fatal("imsg_compose");
-
-	if (imsgbuf_flush(ibuf) == -1)
-		fatal("imsgbuf_flush");
-
-	log_debug("setup_proc: %s done", proc_title(smtpd_process));
-}
-
-static struct mproc *
-setup_peer(enum smtp_proc_type proc, pid_t pid, int sock)
-{
-	struct mproc *p, **pp;
-
-	log_debug("setup_peer: %s -> %s[%u] fd=%d", proc_title(smtpd_process),
-	    proc_title(proc), pid, sock);
-
-	if (sock == -1)
-		fatalx("peer socket not received");
-
-	switch (proc) {
-	case PROC_LKA:
-		pp = &p_lka;
-		break;
-	case PROC_QUEUE:
-		pp = &p_queue;
-		break;
-	case PROC_CONTROL:
-		pp = &p_control;
-		break;
-	case PROC_SCHEDULER:
-		pp = &p_scheduler;
-		break;
-	case PROC_DISPATCHER:
-		pp = &p_dispatcher;
-		break;
-	case PROC_CA:
-		pp = &p_ca;
-		break;
-	default:
-		fatalx("unknown peer");
-	}
-
-	if (*pp)
-		fatalx("peer already set");
-
-	p = calloc(1, sizeof(*p));
-	if (p == NULL)
-		fatal("calloc");
-	if((p->name = strdup(proc_title(proc))) == NULL)
-		fatal("strdup");
-	mproc_init(p, sock);
-	p->pid = pid;
-	p->proc = proc;
-	p->handler = imsg_dispatch;
-
-	*pp = p;
-
-	return p;
-}
-
-static int
-imsg_wait(struct imsgbuf *ibuf, struct imsg *imsg, int timeout)
-{
-	struct pollfd pfd[1];
-	ssize_t n;
-
-	pfd[0].fd = ibuf->fd;
-	pfd[0].events = POLLIN;
-
-	while (1) {
-		if ((n = imsg_get(ibuf, imsg)) == -1)
-			return -1;
-		if (n)
-			return 1;
-
-		n = poll(pfd, 1, timeout);
-		if (n == -1)
-			return -1;
-		if (n == 0) {
-			errno = ETIMEDOUT;
-			return -1;
-		}
-
-		if (imsgbuf_read(ibuf) != 1)
-			return -1;
-	}
-}
-
 int
 smtpd(void) {
 	struct event	 ev_sigint;
@@ -1093,111 +940,6 @@ smtpd(void) {
 	return (0);
 }
 
-static void
-load_pki_tree(void)
-{
-	struct pki	*pki;
-	struct ca	*sca;
-	const char	*k;
-	void		*iter_dict;
-
-	log_debug("debug: init ssl-tree");
-	iter_dict = NULL;
-	while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
-		log_debug("info: loading pki information for %s", k);
-		if (pki->pki_cert_file == NULL)
-			fatalx("load_pki_tree: missing certificate file");
-		if (pki->pki_key_file == NULL)
-			fatalx("load_pki_tree: missing key file");
-
-		if (!ssl_load_certificate(pki, pki->pki_cert_file))
-			fatalx("load_pki_tree: failed to load certificate file");
-	}
-
-	log_debug("debug: init ca-tree");
-	iter_dict = NULL;
-	while (dict_iter(env->sc_ca_dict, &iter_dict, &k, (void **)&sca)) {
-		log_debug("info: loading CA information for %s", k);
-		if (!ssl_load_cafile(sca, sca->ca_cert_file))
-			fatalx("load_pki_tree: failed to load CA file");
-	}
-}
-
-void
-load_pki_keys(void)
-{
-	struct pki	*pki;
-	const char	*k;
-	void		*iter_dict;
-
-	log_debug("debug: init ssl-tree");
-	iter_dict = NULL;
-	while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
-		log_debug("info: loading pki keys for %s", k);
-
-		if (!ssl_load_keyfile(pki, pki->pki_key_file, k))
-			fatalx("load_pki_keys: failed to load key file");
-	}
-}
-
-int
-fork_proc_backend(const char *key, const char *conf, const char *procname,
-    int do_stdout)
-{
-	pid_t		pid;
-	int		sp[2];
-	char		path[PATH_MAX];
-	char		name[PATH_MAX];
-	char		*arg;
-
-	if (strlcpy(name, conf, sizeof(name)) >= sizeof(name)) {
-		log_warnx("warn: %s-proc: conf too long", key);
-		return (-1);
-	}
-
-	arg = strchr(name, ':');
-	if (arg)
-		*arg++ = '\0';
-
-	if (snprintf(path, sizeof(path), PATH_LIBEXEC "/%s-%s", key, name) >=
-	    (ssize_t)sizeof(path)) {
-		log_warn("warn: %s-proc: exec path too long", key);
-		return (-1);
-	}
-
-	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) == -1) {
-		log_warn("warn: %s-proc: socketpair", key);
-		return (-1);
-	}
-
-	if ((pid = fork()) == -1) {
-		log_warn("warn: %s-proc: fork", key);
-		close(sp[0]);
-		close(sp[1]);
-		return (-1);
-	}
-
-	if (pid == 0) {
-		/* child process */
-		dup2(sp[0], STDIN_FILENO);
-		if (do_stdout)
-			dup2(sp[0], STDOUT_FILENO);
-		if (closefrom(STDERR_FILENO + 1) == -1)
-			exit(1);
-
-		if (procname == NULL)
-			procname = name;
-
-		execl(path, procname, arg, (char *)NULL);
-		fatal("execl: %s", path);
-	}
-
-	/* parent process */
-	close(sp[0]);
-
-	return (sp[1]);
-}
-
 struct child *
 child_add(pid_t pid, int type, const char *title)
 {
@@ -1835,54 +1577,6 @@ parent_forward_open(char *username, char *directory, u
 	return fd;
 }
 
-void
-imsg_dispatch(struct mproc *p, struct imsg *imsg)
-{
-	struct timespec	t0, t1, dt;
-	int		msg;
-
-	if (imsg == NULL) {
-		imsg_callback(p, imsg);
-		return;
-	}
-
-	log_imsg(smtpd_process, p->proc, imsg);
-
-	if (profiling & PROFILE_IMSG)
-		clock_gettime(CLOCK_MONOTONIC, &t0);
-
-	msg = imsg->hdr.type;
-	imsg_callback(p, imsg);
-
-	if (profiling & PROFILE_IMSG) {
-		clock_gettime(CLOCK_MONOTONIC, &t1);
-		timespecsub(&t1, &t0, &dt);
-
-		log_debug("profile-imsg: %s %s %s %d %lld.%09ld",
-		    proc_name(smtpd_process),
-		    proc_name(p->proc),
-		    imsg_to_str(msg),
-		    (int)imsg->hdr.len,
-		    (long long)dt.tv_sec,
-		    dt.tv_nsec);
-
-		if (profiling & PROFILE_TOSTAT) {
-			char	key[STAT_KEY_SIZE];
-			/* can't profstat control process yet */
-			if (smtpd_process == PROC_CONTROL)
-				return;
-
-			if (!bsnprintf(key, sizeof key,
-				"profiling.imsg.%s.%s.%s",
-				proc_name(smtpd_process),
-				proc_name(p->proc),
-				imsg_to_str(msg)))
-				return;
-			stat_set(key, stat_timespec(&dt));
-		}
-	}
-}
-
 int
 parent_auth_user(const char *username, const char *password)
 {
blob - b8268d69c6985d4d42234b550c8cfe6086d465b3
blob + fe8bcb8204fbf40110bcecfdf4ee634876b35013
--- usr.sbin/smtpd/smtpd.h
+++ usr.sbin/smtpd/smtpd.h
@@ -1614,6 +1614,12 @@ const char *srs_encode(const char *, const char *);
 const char *srs_decode(const char *);
 
 
+/* startup.c */
+void setup_proc(void);
+int imsg_wait(struct imsgbuf *, struct imsg *, int);
+void load_pki_tree(void);
+void load_pki_keys(void);
+
 /* stat_backend.c */
 struct stat_backend	*stat_backend_lookup(const char *);
 void	stat_increment(const char *, size_t);
blob - /dev/null
blob + 8195f93b98fd0b9a8bd5993d675cc69cc2ce4287 (mode 644)
--- /dev/null
+++ usr.sbin/smtpd/startup.c
@@ -0,0 +1,332 @@
+/*	$OpenBSD$	*/
+
+/*
+ * Copyright (c) 2008 Gilles Chehade <[email protected]>
+ * Copyright (c) 2008 Pierre-Yves Ritschard <[email protected]>
+ * Copyright (c) 2009 Jacek Masiulaniec <[email protected]>
+ *
+ * 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 <poll.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+#include "log.h"
+#include "ssl.h"
+
+struct smtpd		*env = NULL;
+
+struct mproc		*p_control = NULL;
+struct mproc		*p_lka = NULL;
+struct mproc		*p_parent = NULL;
+struct mproc		*p_queue = NULL;
+struct mproc		*p_scheduler = NULL;
+struct mproc		*p_dispatcher = NULL;
+struct mproc		*p_ca = NULL;
+
+int			 profiling = 0;
+
+enum smtp_proc_type	 smtpd_process;
+
+const char		*backend_queue = "fs";
+const char		*backend_scheduler = "ramqueue";
+const char		*backend_stat = "ram";
+
+void (*imsg_callback)(struct mproc *, struct imsg *);
+
+static struct mproc *
+setup_peer(enum smtp_proc_type proc, pid_t pid, int sock)
+{
+	struct mproc *p, **pp;
+
+	log_debug("setup_peer: %s -> %s[%u] fd=%d", proc_title(smtpd_process),
+	    proc_title(proc), pid, sock);
+
+	if (sock == -1)
+		fatalx("peer socket not received");
+
+	switch (proc) {
+	case PROC_LKA:
+		pp = &p_lka;
+		break;
+	case PROC_QUEUE:
+		pp = &p_queue;
+		break;
+	case PROC_CONTROL:
+		pp = &p_control;
+		break;
+	case PROC_SCHEDULER:
+		pp = &p_scheduler;
+		break;
+	case PROC_DISPATCHER:
+		pp = &p_dispatcher;
+		break;
+	case PROC_CA:
+		pp = &p_ca;
+		break;
+	default:
+		fatalx("unknown peer");
+	}
+
+	if (*pp)
+		fatalx("peer already set");
+
+	p = calloc(1, sizeof(*p));
+	if (p == NULL)
+		fatal("calloc");
+	if((p->name = strdup(proc_title(proc))) == NULL)
+		fatal("strdup");
+	mproc_init(p, sock);
+	p->pid = pid;
+	p->proc = proc;
+	p->handler = imsg_dispatch;
+
+	*pp = p;
+
+	return p;
+}
+
+void
+setup_proc(void)
+{
+	struct imsgbuf *ibuf;
+	struct imsg imsg;
+        int setup = 1;
+
+	log_procinit(proc_title(smtpd_process));
+
+	p_parent = calloc(1, sizeof(*p_parent));
+	if (p_parent == NULL)
+		fatal("calloc");
+	if((p_parent->name = strdup("parent")) == NULL)
+		fatal("strdup");
+	p_parent->proc = PROC_PARENT;
+	p_parent->handler = imsg_dispatch;
+	mproc_init(p_parent, 3);
+
+	ibuf = &p_parent->imsgbuf;
+
+	while (setup) {
+		if (imsg_wait(ibuf, &imsg, 10000) == -1)
+			fatal("imsg_wait");
+
+		switch (imsg.hdr.type) {
+		case IMSG_SETUP_KEY:
+			env->sc_queue_key = strdup(imsg.data);
+			break;
+		case IMSG_SETUP_PEER:
+			setup_peer(imsg.hdr.peerid, imsg.hdr.pid,
+			    imsg_get_fd(&imsg));
+			break;
+		case IMSG_SETUP_DONE:
+			setup = 0;
+			break;
+		default:
+			fatal("bad imsg %d", imsg.hdr.type);
+		}
+		imsg_free(&imsg);
+	}
+
+	if (imsg_compose(ibuf, IMSG_SETUP_DONE, 0, 0, -1, NULL, 0) == -1)
+		fatal("imsg_compose");
+
+	if (imsgbuf_flush(ibuf) == -1)
+		fatal("imsgbuf_flush");
+
+	log_debug("setup_proc: %s done", proc_title(smtpd_process));
+}
+
+int
+imsg_wait(struct imsgbuf *ibuf, struct imsg *imsg, int timeout)
+{
+	struct pollfd pfd[1];
+	ssize_t n;
+
+	pfd[0].fd = ibuf->fd;
+	pfd[0].events = POLLIN;
+
+	while (1) {
+		if ((n = imsg_get(ibuf, imsg)) == -1)
+			return -1;
+		if (n)
+			return 1;
+
+		n = poll(pfd, 1, timeout);
+		if (n == -1)
+			return -1;
+		if (n == 0) {
+			errno = ETIMEDOUT;
+			return -1;
+		}
+
+		if (imsgbuf_read(ibuf) != 1)
+			return -1;
+	}
+}
+
+void
+load_pki_tree(void)
+{
+	struct pki	*pki;
+	struct ca	*sca;
+	const char	*k;
+	void		*iter_dict;
+
+	log_debug("debug: init ssl-tree");
+	iter_dict = NULL;
+	while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
+		log_debug("info: loading pki information for %s", k);
+		if (pki->pki_cert_file == NULL)
+			fatalx("load_pki_tree: missing certificate file");
+		if (pki->pki_key_file == NULL)
+			fatalx("load_pki_tree: missing key file");
+
+		if (!ssl_load_certificate(pki, pki->pki_cert_file))
+			fatalx("load_pki_tree: failed to load certificate file");
+	}
+
+	log_debug("debug: init ca-tree");
+	iter_dict = NULL;
+	while (dict_iter(env->sc_ca_dict, &iter_dict, &k, (void **)&sca)) {
+		log_debug("info: loading CA information for %s", k);
+		if (!ssl_load_cafile(sca, sca->ca_cert_file))
+			fatalx("load_pki_tree: failed to load CA file");
+	}
+}
+
+void
+load_pki_keys(void)
+{
+	struct pki	*pki;
+	const char	*k;
+	void		*iter_dict;
+
+	log_debug("debug: init ssl-tree");
+	iter_dict = NULL;
+	while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
+		log_debug("info: loading pki keys for %s", k);
+
+		if (!ssl_load_keyfile(pki, pki->pki_key_file, k))
+			fatalx("load_pki_keys: failed to load key file");
+	}
+}
+
+int
+fork_proc_backend(const char *key, const char *conf, const char *procname,
+    int do_stdout)
+{
+	pid_t		pid;
+	int		sp[2];
+	char		path[PATH_MAX];
+	char		name[PATH_MAX];
+	char		*arg;
+
+	if (strlcpy(name, conf, sizeof(name)) >= sizeof(name)) {
+		log_warnx("warn: %s-proc: conf too long", key);
+		return (-1);
+	}
+
+	arg = strchr(name, ':');
+	if (arg)
+		*arg++ = '\0';
+
+	if (snprintf(path, sizeof(path), PATH_LIBEXEC "/%s-%s", key, name) >=
+	    (ssize_t)sizeof(path)) {
+		log_warn("warn: %s-proc: exec path too long", key);
+		return (-1);
+	}
+
+	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) == -1) {
+		log_warn("warn: %s-proc: socketpair", key);
+		return (-1);
+	}
+
+	if ((pid = fork()) == -1) {
+		log_warn("warn: %s-proc: fork", key);
+		close(sp[0]);
+		close(sp[1]);
+		return (-1);
+	}
+
+	if (pid == 0) {
+		/* child process */
+		dup2(sp[0], STDIN_FILENO);
+		if (do_stdout)
+			dup2(sp[0], STDOUT_FILENO);
+		if (closefrom(STDERR_FILENO + 1) == -1)
+			exit(1);
+
+		if (procname == NULL)
+			procname = name;
+
+		execl(path, procname, arg, (char *)NULL);
+		fatal("execl: %s", path);
+	}
+
+	/* parent process */
+	close(sp[0]);
+
+	return (sp[1]);
+}
+
+void
+imsg_dispatch(struct mproc *p, struct imsg *imsg)
+{
+	struct timespec	t0, t1, dt;
+	int		msg;
+
+	if (imsg == NULL) {
+		imsg_callback(p, imsg);
+		return;
+	}
+
+	log_imsg(smtpd_process, p->proc, imsg);
+
+	if (profiling & PROFILE_IMSG)
+		clock_gettime(CLOCK_MONOTONIC, &t0);
+
+	msg = imsg->hdr.type;
+	imsg_callback(p, imsg);
+
+	if (profiling & PROFILE_IMSG) {
+		clock_gettime(CLOCK_MONOTONIC, &t1);
+		timespecsub(&t1, &t0, &dt);
+
+		log_debug("profile-imsg: %s %s %s %d %lld.%09ld",
+		    proc_name(smtpd_process),
+		    proc_name(p->proc),
+		    imsg_to_str(msg),
+		    (int)imsg->hdr.len,
+		    (long long)dt.tv_sec,
+		    dt.tv_nsec);
+
+		if (profiling & PROFILE_TOSTAT) {
+			char	key[STAT_KEY_SIZE];
+			/* can't profstat control process yet */
+			if (smtpd_process == PROC_CONTROL)
+				return;
+
+			if (!bsnprintf(key, sizeof key,
+				"profiling.imsg.%s.%s.%s",
+				proc_name(smtpd_process),
+				proc_name(p->proc),
+				imsg_to_str(msg)))
+				return;
+			stat_set(key, stat_timespec(&dt));
+		}
+	}
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.