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;