summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/control.c123
-rw-r--r--usr.sbin/smtpd/parser.c3
-rw-r--r--usr.sbin/smtpd/parser.h3
-rw-r--r--usr.sbin/smtpd/queue.c14
-rw-r--r--usr.sbin/smtpd/runner.c14
-rw-r--r--usr.sbin/smtpd/smtp.c12
-rw-r--r--usr.sbin/smtpd/smtp_session.c8
-rw-r--r--usr.sbin/smtpd/smtpctl.c47
-rw-r--r--usr.sbin/smtpd/smtpd.c63
-rw-r--r--usr.sbin/smtpd/smtpd.h36
10 files changed, 310 insertions, 13 deletions
diff --git a/usr.sbin/smtpd/control.c b/usr.sbin/smtpd/control.c
index 387751f1c02..2dafdf100b4 100644
--- a/usr.sbin/smtpd/control.c
+++ b/usr.sbin/smtpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.10 2009/01/27 23:39:41 gilles Exp $ */
+/* $OpenBSD: control.c,v 1.11 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -58,6 +58,7 @@ void control_dispatch_mfa(int, short, void *);
void control_dispatch_queue(int, short, void *);
void control_dispatch_runner(int, short, void *);
void control_dispatch_smtp(int, short, void *);
+void control_dispatch_parent(int, short, void *);
struct ctl_connlist ctl_conns;
@@ -90,6 +91,7 @@ control(struct smtpd *env)
{ PROC_RUNNER, control_dispatch_runner },
{ PROC_SMTP, control_dispatch_smtp },
{ PROC_MFA, control_dispatch_mfa },
+ { PROC_PARENT, control_dispatch_parent },
};
switch (pid = fork()) {
@@ -162,7 +164,7 @@ control(struct smtpd *env)
TAILQ_INIT(&ctl_conns);
- config_peers(env, peers, 4);
+ config_peers(env, peers, 5);
control_listen(env);
event_dispatch();
control_shutdown();
@@ -346,6 +348,17 @@ control_dispatch_ext(int fd, short event, void *arg)
messagep, sizeof(*messagep));
break;
}
+ case IMSG_STATS: {
+ struct stats s;
+
+ s.fd = fd;
+ imsg_compose(env->sc_ibufs[PROC_PARENT], IMSG_STATS, 0, 0, -1, &s, sizeof(s));
+ imsg_compose(env->sc_ibufs[PROC_QUEUE], IMSG_STATS, 0, 0, -1, &s, sizeof(s));
+ imsg_compose(env->sc_ibufs[PROC_RUNNER], IMSG_STATS, 0, 0, -1, &s, sizeof(s));
+ imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_STATS, 0, 0, -1, &s, sizeof(s));
+
+ break;
+ }
case IMSG_CTL_SHUTDOWN:
/* NEEDS_FIX */
log_debug("received shutdown request");
@@ -461,6 +474,67 @@ badcred:
}
void
+control_dispatch_parent(int sig, short event, void *p)
+{
+ struct smtpd *env = p;
+ struct imsgbuf *ibuf;
+ struct imsg imsg;
+ ssize_t n;
+
+ ibuf = env->sc_ibufs[PROC_PARENT];
+ switch (event) {
+ case EV_READ:
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read_error");
+ if (n == 0) {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&ibuf->ev);
+ event_loopexit(NULL);
+ return;
+ }
+ break;
+ case EV_WRITE:
+ if (msgbuf_write(&ibuf->w) == -1)
+ fatal("msgbuf_write");
+ imsg_event_add(ibuf);
+ return;
+ default:
+ fatalx("unknown event");
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("control_dispatch_parent: imsg_read error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_STATS: {
+ struct stats *s;
+ struct ctl_conn *c;
+
+ s = imsg.data;
+ if ((c = control_connbyfd(s->fd)) == NULL) {
+ log_warn("control_dispatch_parent: fd %d not found", s->fd);
+ return;
+ }
+
+ imsg_compose(&c->ibuf, IMSG_PARENT_STATS, 0, 0, -1,
+ &s->u.parent, sizeof(s->u.parent));
+
+ break;
+ }
+ default:
+ log_debug("control_dispatch_parent: unexpected imsg %d",
+ imsg.hdr.type);
+ break;
+ }
+ imsg_free(&imsg);
+ }
+ imsg_event_add(ibuf);
+}
+
+void
control_dispatch_lka(int sig, short event, void *p)
{
struct smtpd *env = p;
@@ -694,6 +768,21 @@ control_dispatch_queue(int sig, short event, void *p)
&ss->msg, sizeof(struct message));
break;
}
+ case IMSG_STATS: {
+ struct stats *s;
+ struct ctl_conn *c;
+
+ s = imsg.data;
+ if ((c = control_connbyfd(s->fd)) == NULL) {
+ log_warn("control_dispatch_queue: fd %d not found", s->fd);
+ return;
+ }
+
+ imsg_compose(&c->ibuf, IMSG_QUEUE_STATS, 0, 0, -1,
+ &s->u.queue, sizeof(s->u.queue));
+
+ break;
+ }
default:
log_debug("control_dispatch_queue: unexpected imsg %d",
imsg.hdr.type);
@@ -740,6 +829,21 @@ control_dispatch_runner(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_STATS: {
+ struct stats *s;
+ struct ctl_conn *c;
+
+ s = imsg.data;
+ if ((c = control_connbyfd(s->fd)) == NULL) {
+ log_warn("control_dispatch_runner: fd %d not found", s->fd);
+ return;
+ }
+
+ imsg_compose(&c->ibuf, IMSG_RUNNER_STATS, 0, 0, -1,
+ &s->u.runner, sizeof(s->u.runner));
+
+ break;
+ }
default:
log_debug("control_dispatch_runner: unexpected imsg %d",
imsg.hdr.type);
@@ -786,6 +890,21 @@ control_dispatch_smtp(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
+ case IMSG_STATS: {
+ struct stats *s;
+ struct ctl_conn *c;
+
+ s = imsg.data;
+ if ((c = control_connbyfd(s->fd)) == NULL) {
+ log_warn("control_dispatch_queue: fd %d not found", s->fd);
+ return;
+ }
+
+ imsg_compose(&c->ibuf, IMSG_SMTP_STATS, 0, 0, -1,
+ &s->u.smtp, sizeof(s->u.smtp));
+
+ break;
+ }
default:
log_debug("control_dispatch_smtp: unexpected imsg %d",
imsg.hdr.type);
diff --git a/usr.sbin/smtpd/parser.c b/usr.sbin/smtpd/parser.c
index ae1a886b307..54386cb678d 100644
--- a/usr.sbin/smtpd/parser.c
+++ b/usr.sbin/smtpd/parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.5 2009/01/04 22:35:09 gilles Exp $ */
+/* $OpenBSD: parser.c,v 1.6 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -72,6 +72,7 @@ static const struct token t_main[] = {
static const struct token t_show[] = {
{KEYWORD, "queue", SHOW_QUEUE, NULL},
{KEYWORD, "runqueue", SHOW_RUNQUEUE, NULL},
+ {KEYWORD, "stats", SHOW_STATS, NULL},
{ENDTOKEN, "", NONE, NULL}
};
diff --git a/usr.sbin/smtpd/parser.h b/usr.sbin/smtpd/parser.h
index 7cf6e3bf94d..21d4e517b1b 100644
--- a/usr.sbin/smtpd/parser.h
+++ b/usr.sbin/smtpd/parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.5 2009/01/04 22:35:09 gilles Exp $ */
+/* $OpenBSD: parser.h,v 1.6 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -23,6 +23,7 @@ enum actions {
MONITOR,
SHOW_QUEUE,
SHOW_RUNQUEUE,
+ SHOW_STATS,
PAUSE_MDA,
PAUSE_MTA,
PAUSE_SMTP,
diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c
index 0b4d1857d4a..8e33f7333ce 100644
--- a/usr.sbin/smtpd/queue.c
+++ b/usr.sbin/smtpd/queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.c,v 1.52 2009/01/29 12:43:25 jacekm Exp $ */
+/* $OpenBSD: queue.c,v 1.53 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -55,6 +55,8 @@ int queue_remove_layout_envelope(char *, struct message *);
int queue_commit_layout_message(char *, struct message *);
int queue_open_layout_messagefile(char *, struct message *);
+struct s_queue s_queue;
+
void
queue_sig_handler(int sig, short event, void *p)
{
@@ -157,6 +159,14 @@ queue_dispatch_control(int sig, short event, void *p)
break;
}
+ case IMSG_STATS: {
+ struct stats *s;
+
+ s = imsg.data;
+ s->u.queue = s_queue;
+ imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, s, sizeof(*s));
+ break;
+ }
default:
log_debug("queue_dispatch_control: unexpected imsg %d",
imsg.hdr.type);
@@ -234,6 +244,8 @@ queue_dispatch_smtp(int sig, short event, void *p)
messagep = imsg.data;
ss.id = messagep->session_id;
+ s_queue.inserts++;
+
if (! queue_commit_incoming_message(messagep))
ss.code = 421;
diff --git a/usr.sbin/smtpd/runner.c b/usr.sbin/smtpd/runner.c
index 7e4ce43eae2..9acb8f94e75 100644
--- a/usr.sbin/smtpd/runner.c
+++ b/usr.sbin/smtpd/runner.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: runner.c,v 1.27 2009/01/29 12:43:25 jacekm Exp $ */
+/* $OpenBSD: runner.c,v 1.28 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -77,6 +77,8 @@ int runner_check_loop(struct message *);
struct batch *batch_record(struct smtpd *, struct message *);
struct batch *batch_lookup(struct smtpd *, struct message *);
+struct s_runner s_runner;
+
void
runner_sig_handler(int sig, short event, void *p)
{
@@ -138,6 +140,14 @@ runner_dispatch_control(int sig, short event, void *p)
case IMSG_MTA_RESUME:
env->sc_opts &= ~SMTPD_MTA_PAUSED;
break;
+ case IMSG_STATS: {
+ struct stats *s;
+
+ s = imsg.data;
+ s->u.runner = s_runner;
+ imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, s, sizeof(*s));
+ break;
+ }
default:
log_debug("queue_dispatch_control: unexpected imsg %d",
imsg.hdr.type);
@@ -185,6 +195,7 @@ runner_dispatch_queue(int sig, short event, void *p)
switch (imsg.hdr.type) {
case IMSG_RUNNER_UPDATE_ENVELOPE: {
+ s_runner.active--;
queue_message_update(imsg.data);
break;
}
@@ -860,6 +871,7 @@ batch_record(struct smtpd *env, struct message *messagep)
}
TAILQ_INSERT_TAIL(&batchp->messages, messagep, entry);
+ s_runner.active++;
return batchp;
}
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c
index ee77f657380..2d10a710dd5 100644
--- a/usr.sbin/smtpd/smtp.c
+++ b/usr.sbin/smtpd/smtp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp.c,v 1.17 2009/01/28 19:38:46 gilles Exp $ */
+/* $OpenBSD: smtp.c,v 1.18 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -48,6 +48,8 @@ void smtp_accept(int, short, void *);
void session_timeout(int, short, void *);
void session_auth_pickup(struct session *, char *, size_t);
+struct s_smtp s_smtp;
+
void
smtp_sig_handler(int sig, short event, void *p)
{
@@ -505,6 +507,14 @@ smtp_dispatch_control(int sig, short event, void *p)
case IMSG_SMTP_RESUME:
smtp_resume(env);
break;
+ case IMSG_STATS: {
+ struct stats *s;
+
+ s = imsg.data;
+ s->u.smtp = s_smtp;
+ imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, s, sizeof(*s));
+ break;
+ }
default:
log_debug("smtp_dispatch_control: unexpected imsg %d",
imsg.hdr.type);
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index 3e6e5fdf0f2..935bed2b676 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp_session.c,v 1.46 2009/01/29 15:40:35 gilles Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.47 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -73,6 +73,8 @@ int session_set_path(struct path *, char *);
void session_timeout(int, short, void *);
void session_cleanup(struct session *);
+extern struct s_smtp s_smtp;
+
struct session_timeout {
enum session_state state;
time_t timeout;
@@ -743,6 +745,8 @@ session_init(struct listener *l, struct session *s)
s->s_l = l;
s->s_id = queue_generate_id();
+ s_smtp.clients++;
+
strlcpy(s->s_hostname, "<unknown>", MAXHOSTNAMELEN);
strlcpy(s->s_msg.session_hostname, s->s_hostname, MAXHOSTNAMELEN);
imsg_compose(s->s_env->sc_ibufs[PROC_LKA], IMSG_LKA_HOST, 0, 0, -1, s,
@@ -900,6 +904,8 @@ session_destroy(struct session *s)
log_debug("session_destroy: killing client: %p", s);
close(s->s_fd);
+ s_smtp.clients--;
+
if (s->s_bev != NULL) {
bufferevent_free(s->s_bev);
}
diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c
index 42f150be901..dbebeaacc91 100644
--- a/usr.sbin/smtpd/smtpctl.c
+++ b/usr.sbin/smtpd/smtpctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpctl.c,v 1.7 2009/01/29 12:43:25 jacekm Exp $ */
+/* $OpenBSD: smtpctl.c,v 1.8 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -44,6 +44,7 @@
__dead void usage(void);
int show_command_output(struct imsg*);
+int show_stats_output(struct imsg *);
int enqueue(int, char **);
struct imsgname {
@@ -168,6 +169,9 @@ connected:
case RESUME_SMTP:
imsg_compose(ibuf, IMSG_SMTP_RESUME, 0, 0, -1, NULL, 0);
break;
+ case SHOW_STATS:
+ imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, NULL, 0);
+ break;
case MONITOR:
/* XXX */
break;
@@ -201,6 +205,9 @@ connected:
case RESUME_SMTP:
done = show_command_output(&imsg);
break;
+ case SHOW_STATS:
+ done = show_stats_output(&imsg);
+ break;
case NONE:
break;
case MONITOR:
@@ -234,3 +241,41 @@ show_command_output(struct imsg *imsg)
}
return (1);
}
+
+int
+show_stats_output(struct imsg *imsg)
+{
+ static int left = 4;
+ static struct s_parent s_parent;
+ static struct s_queue s_queue;
+ static struct s_runner s_runner;
+ static struct s_smtp s_smtp;
+
+ switch (imsg->hdr.type) {
+ case IMSG_PARENT_STATS:
+ s_parent = *(struct s_parent *)imsg->data;
+ break;
+ case IMSG_QUEUE_STATS:
+ s_queue = *(struct s_queue *)imsg->data;
+ break;
+ case IMSG_RUNNER_STATS:
+ s_runner = *(struct s_runner *)imsg->data;
+ break;
+ case IMSG_SMTP_STATS:
+ s_smtp = *(struct s_smtp *)imsg->data;
+ break;
+ default:
+ errx(1, "show_stats_output: bad hdr type (%d)", imsg->hdr.type);
+ }
+
+ left--;
+ if (left > 0)
+ return (0);
+
+ printf("parent.uptime = %zd\n", time(NULL) - s_parent.start);
+ printf("queue.inserts = %zd\n", s_queue.inserts);
+ printf("runner.active = %zd\n", s_runner.active);
+ printf("smtp.clients = %zd\n", s_smtp.clients);
+
+ return (1);
+}
diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c
index 3d1d6dab8c5..96e1a9871f8 100644
--- a/usr.sbin/smtpd/smtpd.c
+++ b/usr.sbin/smtpd/smtpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.c,v 1.26 2009/01/28 19:38:46 gilles Exp $ */
+/* $OpenBSD: smtpd.c,v 1.27 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -53,6 +53,7 @@ void parent_dispatch_lka(int, short, void *);
void parent_dispatch_mda(int, short, void *);
void parent_dispatch_mfa(int, short, void *);
void parent_dispatch_smtp(int, short, void *);
+void parent_dispatch_control(int, short, void *);
void parent_sig_handler(int, short, void *);
int parent_open_message_file(struct batch *);
int parent_mailbox_init(struct passwd *, char *);
@@ -74,6 +75,7 @@ pid_t control_pid = 0;
pid_t smtp_pid = 0;
pid_t runner_pid = 0;
+struct s_parent s_parent;
int __b64_pton(char const *, unsigned char *, size_t);
@@ -449,6 +451,60 @@ parent_dispatch_smtp(int fd, short event, void *p)
}
void
+parent_dispatch_control(int sig, short event, void *p)
+{
+ struct smtpd *env = p;
+ struct imsgbuf *ibuf;
+ struct imsg imsg;
+ ssize_t n;
+
+ ibuf = env->sc_ibufs[PROC_CONTROL];
+ switch (event) {
+ case EV_READ:
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read_error");
+ if (n == 0) {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&ibuf->ev);
+ event_loopexit(NULL);
+ return;
+ }
+ break;
+ case EV_WRITE:
+ if (msgbuf_write(&ibuf->w) == -1)
+ fatal("msgbuf_write");
+ imsg_event_add(ibuf);
+ return;
+ default:
+ fatalx("unknown event");
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("parent_dispatch_control: imsg_read error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_STATS: {
+ struct stats *s;
+
+ s = imsg.data;
+ s->u.parent = s_parent;
+ imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, s, sizeof(*s));
+ break;
+ }
+ default:
+ log_debug("parent_dispatch_control: unexpected imsg %d",
+ imsg.hdr.type);
+ break;
+ }
+ imsg_free(&imsg);
+ }
+ imsg_event_add(ibuf);
+}
+
+void
parent_sig_handler(int sig, short event, void *p)
{
int i;
@@ -536,6 +592,7 @@ main(int argc, char *argv[])
struct event ev_sighup;
struct timeval tv;
struct peer peers[] = {
+ { PROC_CONTROL, parent_dispatch_control },
{ PROC_LKA, parent_dispatch_lka },
{ PROC_MDA, parent_dispatch_mda },
{ PROC_MFA, parent_dispatch_mfa },
@@ -617,6 +674,8 @@ main(int argc, char *argv[])
setproctitle("parent");
SPLAY_INIT(&env.mdaproc_queue);
+ s_parent.start = time(NULL);
+
event_init();
signal_set(&ev_sigint, SIGINT, parent_sig_handler, &env);
@@ -629,7 +688,7 @@ main(int argc, char *argv[])
signal_add(&ev_sighup, NULL);
signal(SIGPIPE, SIG_IGN);
- config_peers(&env, peers, 4);
+ config_peers(&env, peers, 5);
evtimer_set(&env.sc_ev, parent_send_config, &env);
bzero(&tv, sizeof(tv));
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index a1a49696ace..9ae8818cf55 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.61 2009/01/29 15:40:35 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.62 2009/01/29 21:59:15 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -180,6 +180,7 @@ enum imsg_type {
IMSG_QUEUE_REMOVE_MESSAGE,
IMSG_QUEUE_COMMIT_MESSAGE,
IMSG_QUEUE_TEMPFAIL,
+ IMSG_QUEUE_STATS,
IMSG_QUEUE_REMOVE_SUBMISSION,
IMSG_QUEUE_MESSAGE_UPDATE,
@@ -187,6 +188,7 @@ enum imsg_type {
IMSG_QUEUE_MESSAGE_FILE,
IMSG_RUNNER_UPDATE_ENVELOPE,
+ IMSG_RUNNER_STATS,
IMSG_BATCH_CREATE,
IMSG_BATCH_APPEND,
@@ -195,6 +197,7 @@ enum imsg_type {
IMSG_PARENT_MAILBOX_OPEN,
IMSG_PARENT_MESSAGE_OPEN,
IMSG_PARENT_MAILBOX_RENAME,
+ IMSG_PARENT_STATS,
IMSG_PARENT_AUTHENTICATE,
IMSG_PARENT_SEND_CONFIG,
@@ -202,10 +205,13 @@ enum imsg_type {
IMSG_MDA_PAUSE,
IMSG_MTA_PAUSE,
IMSG_SMTP_PAUSE,
+ IMSG_SMTP_STATS,
IMSG_MDA_RESUME,
IMSG_MTA_RESUME,
- IMSG_SMTP_RESUME
+ IMSG_SMTP_RESUME,
+
+ IMSG_STATS
};
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
@@ -634,6 +640,32 @@ struct smtpd {
SPLAY_HEAD(mdaproctree, mdaproc) mdaproc_queue;
};
+struct s_parent {
+ time_t start;
+};
+
+struct s_queue {
+ size_t inserts;
+};
+
+struct s_runner {
+ size_t active;
+};
+
+struct s_smtp {
+ size_t clients;
+};
+
+struct stats {
+ int fd;
+ union u_stats {
+ struct s_parent parent;
+ struct s_queue queue;
+ struct s_runner runner;
+ struct s_smtp smtp;
+ } u;
+};
+
struct submit_status {
u_int64_t id;
int code;