diff options
Diffstat (limited to 'inherit.c')
-rw-r--r-- | inherit.c | 56 |
1 files changed, 52 insertions, 4 deletions
@@ -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; |