about summary refs log tree commit homepage
path: root/inherit.c
diff options
context:
space:
mode:
Diffstat (limited to 'inherit.c')
-rw-r--r--inherit.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/inherit.c b/inherit.c
index ca7afa7..0229a04 100644
--- a/inherit.c
+++ b/inherit.c
@@ -89,6 +89,55 @@ static bool listener_close_each(void *_l, void *unused)
         return true;
 }
 
+static void listeners_init(void)
+{
+        if (listeners) return;
+        listeners = hash_initialize(3, NULL, listener_hash, listener_cmp, free);
+        mog_oom_if_null(listeners);
+        atexit(listeners_cleanup);
+}
+
+static unsigned long listen_env(const char *env)
+{
+        const char *e = getenv(env);
+        unsigned long tmp;
+        char *end;
+
+        if (!e) return ULONG_MAX;
+        errno = 0;
+        tmp = strtoul(e, &end, 10);
+        if (errno) die_errno("failed to parse %s: %s", env, e);
+        if (*end) die("trailing byte in %s: %s", env, e);
+
+        return tmp;
+}
+
+/* systemd-style socket activation in the vein of sd_listen_fds(3) */
+static void systemd_inherit_fds(void)
+{
+        const int listen_fds_start = 3; /* SD_LISTEN_FDS_START */
+        int fd, listen_fds_end;
+        unsigned long tmp = listen_env("LISTEN_PID");
+
+        if (getpid() != (pid_t)tmp) goto out;
+
+        tmp = listen_env("LISTEN_FDS");
+        if (tmp > INT_MAX) die("LISTEN_FDS out of range: %lu", tmp);
+
+        listeners_init();
+        listen_fds_end = listen_fds_start + (int)tmp;
+        for (fd = listen_fds_start; fd < listen_fds_end; fd++) {
+                if (mog_set_cloexec(fd, true) == 0)
+                        register_listen_fd(fd);
+                else
+                        die("inherited out %d of %lu LISTEN_FDS",
+                            fd - listen_fds_start, tmp);
+        }
+out:
+        unsetenv("LISTEN_FDS");
+        unsetenv("LISTEN_PID");
+}
+
 /* close all inherited listeners we do not need */
 void mog_inherit_cleanup(void)
 {
@@ -131,13 +180,12 @@ void mog_inherit_init(void)
         unsigned long fd;
         unsigned endbyte;
 
+        systemd_inherit_fds();
+
         if (orig == NULL)
                 return;
 
-        listeners = hash_initialize(3, NULL, listener_hash, listener_cmp, free);
-        mog_oom_if_null(listeners);
-        atexit(listeners_cleanup);
-
+        listeners_init();
         fds = xstrdup(orig);
         tip = fds;