Re: smtpd: create startup.c
"Theo de Raadt" <[email protected]>
| Newsgroups | gmane.os.openbsd.tech |
|---|---|
| Message-ID | <[email protected]> |
I think this is the right approach. It will take a few steps to see
clearly how to split this (it is not going to split the way sshd did).
> 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));
> + }
> + }
> +}
>