bmf-milter

bmf filter milter daemon
git clone git://r-36.net/bmf-milter
Log | Files | Refs | LICENSE

commit 95f0bdc0f1a4d74ef7fa12c3dc7e768d7cb3b7d0
parent 1f931b2c026025c601d33e720e5d494e44915960
Author: Christoph Lohmann <20h@r-36.net>
Date:   Sun, 14 Jun 2020 14:37:43 +0200

Add some daemon features for deployment.

Diffstat:
bmf-milter.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 110 insertions(+), 9 deletions(-)

diff --git a/bmf-milter.c b/bmf-milter.c @@ -9,6 +9,8 @@ #include <fcntl.h> #include <errno.h> #include <stdio.h> +#include <grp.h> +#include <pwd.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> @@ -115,7 +117,7 @@ mlfi_helo(SMFICTX *ctx, char *helohost) return SMFIS_CONTINUE; } - switch((pid = fork())) { + switch ((pid = fork())) { case 0: while(dup2(priv->execpipe[0], 0) < 0 && errno == EINTR); close(priv->execpipe[1]); @@ -330,26 +332,66 @@ struct smfiDesc smfilter = }; void +sighandler(int sig) +{ + int i; + + switch (sig) { + case SIGCHLD: + while (waitpid(-1, NULL, WNOHANG) > 0); + break; + case SIGINT: + case SIGQUIT: + case SIGABRT: + case SIGTERM: + case SIGKILL: + smfi_stop(); + break; + default: + break; + } +} + +void +initsignals(void) +{ + signal(SIGCHLD, sighandler); + signal(SIGHUP, sighandler); + signal(SIGINT, sighandler); + signal(SIGQUIT, sighandler); + signal(SIGABRT, sighandler); + signal(SIGTERM, sighandler); + signal(SIGKILL, sighandler); + + /* + * done by smfi_main(): + * signal(SIGPIPE, SIG_IGN); + */ +} + +void usage(char *argv0) { fprintf(stderr, - "Usage: %s [-h] [-d dbglvl] [-p listen] [-t timeout]\n", + "Usage: %s [-hd] [-v dbglvl] [-p listen] [-t timeout] " + "[-u user] [-g group]\n", argv0); } int main(int argc, char *argv[]) { - char *argv0, *port; - int timeout; - - port = "inet:9957"; - timeout = -1; + char *argv0, *user = NULL, *group = NULL, *port = "inet:9957"; + int timeout = -1, dofork = 1; + struct passwd *us = NULL; + struct group *gr = NULL; ARGBEGIN(argv0) { case 'd': - smfi_setdbg(atoi(EARGF(argv0))); - dodebug = 1; + dofork = 0; + break; + case 'g': + group = EARGF(usage(argv0)); break; case 'p': port = EARGF(usage(argv0)); @@ -357,11 +399,70 @@ main(int argc, char *argv[]) case 't': timeout = atoi(EARGF(usage(argv0))); break; + case 'u': + user = EARGF(usage(argv0)); + break; + case 'v': + smfi_setdbg(atoi(EARGF(argv0))); + dodebug = 1; + break; default: usage(argv0); return 1; } ARGEND; + if (group != NULL) { + errno = 0; + if ((gr = getgrnam(group)) == NULL) { + if (errno == 0) { + fprintf(stderr, "no such group '%s'\n", + group); + } else { + perror("getgrnam"); + } + return 1; + } + } + + if (user != NULL) { + errno = 0; + if ((us = getpwnam(user)) == NULL) { + if (errno == 0) { + fprintf(stderr, "no such user '%s'\n", + user); + } else { + perror("getpwnam"); + } + return 1; + } + } + + if (dofork) { + switch (fork()) { + case -1: + perror("fork"); + return 1; + case 0: + break; + default: + return 0; + } + } + + if (gr != NULL) { + if (setgroups(1, &gr->gr_gid) != 0 || setgid(gr->gr_gid) != 0) + return -1; + } + if (us != NULL) { + if (gr == NULL) { + if (setgroups(1, &us->pw_gid) != 0 || + setgid(us->pw_gid) != 0) + return -1; + } + if (setuid(us->pw_uid) != 0) + return -1; + } + if (smfi_setconn(port) == MI_FAILURE) { perror("smfi_setconn"); return 1;