tAdd some daemon features for deployment. - 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
t@@ -9,6 +9,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
t@@ -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]);
t@@ -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));
t@@ -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;