diff options
author | Eric Faurot <eric@cvs.openbsd.org> | 2012-01-11 17:46:38 +0000 |
---|---|---|
committer | Eric Faurot <eric@cvs.openbsd.org> | 2012-01-11 17:46:38 +0000 |
commit | cd75d18c8956e1c34385a351e7c916d308413e30 (patch) | |
tree | 4ea2632e80cffece6d42234d1b21d2e367a693f7 /usr.sbin/smtpd/smtpd.c | |
parent | 8ccc0ce2a9b3da61262dec658a93fc94497ef635 (diff) |
Simplify runner/queue by getting rid of Q_PURGE. Instead, let smtpd
periodically clear the purge/ directory. At init time, the fsqueue
backend simply moves the existing incoming/ dir in purge/ to discard
aborted sessions.
ok gilles@ chl@
Diffstat (limited to 'usr.sbin/smtpd/smtpd.c')
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index 2ea72c43737..91b5e0aeca9 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.143 2011/12/13 23:55:00 gilles Exp $ */ +/* $OpenBSD: smtpd.c,v 1.144 2012/01/11 17:46:36 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -66,6 +66,9 @@ static int offline_add(char *); static void offline_done(void); static int offline_enqueue(char *); +static void purge_task(int, short, void *); + + struct offline { TAILQ_ENTRY(offline) entry; char *path; @@ -79,6 +82,9 @@ TAILQ_HEAD(, offline) offline_q; static struct event offline_ev; static struct timeval offline_timeout; +static pid_t purge_pid; +static struct timeval purge_timeout; +static struct event purge_ev; extern char **environ; void (*imsg_callback)(struct imsgev *, struct imsg *); @@ -337,10 +343,6 @@ parent_sig_handler(int sig, short event, void *p) if (pid <= 0) continue; - child = child_lookup(pid); - if (child == NULL) - fatalx("unexpected SIGCHLD"); - fail = 0; if (WIFSIGNALED(status)) { fail = 1; @@ -355,6 +357,13 @@ parent_sig_handler(int sig, short event, void *p) } else fatalx("unexpected cause of SIGCHLD"); + if (pid == purge_pid) + purge_pid = -1; + + child = child_lookup(pid); + if (child == NULL) + goto skip; + switch (child->type) { case CHILD_DAEMON: die = 1; @@ -389,6 +398,7 @@ parent_sig_handler(int sig, short event, void *p) } child_del(child->pid); + skip: free(cause); } while (pid > 0 || (pid == -1 && errno == EINTR)); @@ -504,6 +514,8 @@ main(int argc, char *argv[]) errx(1, "error in spool directory setup"); if (ckdir(PATH_SPOOL PATH_OFFLINE, 01777, 0, 0, 1) == 0) errx(1, "error in offline directory setup"); + if (ckdir(PATH_SPOOL PATH_PURGE, 0700, env->sc_pw->pw_uid, 0, 1) == 0) + errx(1, "error in purge directory setup"); env->sc_queue = queue_backend_lookup(QT_FS); if (env->sc_queue == NULL) @@ -561,6 +573,12 @@ main(int argc, char *argv[]) offline_timeout.tv_usec = 0; evtimer_add(&offline_ev, &offline_timeout); + purge_pid = -1; + evtimer_set(&purge_ev, purge_task, NULL); + purge_timeout.tv_sec = 10; + purge_timeout.tv_usec = 0; + evtimer_add(&purge_ev, &purge_timeout); + if (event_dispatch() < 0) fatal("event_dispatch"); @@ -687,6 +705,55 @@ imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, imsg_event_add(iev); } + +static void +purge_task(int fd, short ev, void *arg) +{ + DIR *d; + struct dirent *de; + int n; + uid_t uid; + gid_t gid; + + if (purge_pid == -1) { + + n = 0; + if ((d = opendir(PATH_SPOOL PATH_PURGE))) { + while ((de = readdir(d)) != NULL) + n++; + closedir(d); + } else + log_warn("purge_task: opendir"); + + if (n > 2) { + log_debug("smtpd: forking purge process"); + switch(purge_pid = fork()) { + case -1: + log_warn("purge_task: fork"); + break; + case 0: + if (chroot(PATH_SPOOL PATH_PURGE) == -1) + fatal("smtpd: chroot"); + if (chdir("/") == -1) + fatal("smtpd: chdir"); + uid = env->sc_pw->pw_uid; + gid = env->sc_pw->pw_gid; + if (setgroups(1, &gid) || + setresgid(gid, gid, gid) || + setresuid(uid, uid, uid)) + fatal("smtpd: cannot drop privileges"); + rmtree(".", 1); + _exit(0); + break; + default: + break; + } + } + } + + evtimer_add(&purge_ev, &purge_timeout); +} + static void forkmda(struct imsgev *iev, u_int32_t id, struct deliver *deliver) |