From: "Theo de Raadt" Subject: Re: smtpd: create startup.c To: Martijn van Duren Cc: tech@openbsd.org Date: Thu, 02 Jul 2026 08:43:51 -0600 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 > + * Copyright (c) 2008 Pierre-Yves Ritschard > + * Copyright (c) 2009 Jacek Masiulaniec > + * > + * 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 > +#include > +#include > +#include > +#include > + > +#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)); > + } > + } > +} >