diff options
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 55 |
1 files changed, 55 insertions, 0 deletions
@@ -1,5 +1,6 @@ /* Copyright 2016 Luke Shumaker */ +#include <ctype.h> /* for isdigit */ #include <stdlib.h> #include <error.h> #include <errno.h> @@ -17,3 +18,57 @@ void *xrealloc(void *ptr, size_t size) } return ret; } + +bool is_numeric(const char *str) { + for (size_t i = 0; str[i] != '\0'; i++) + if (!isdigit(str[i])) + return false; + if (str[0] == '\0') + return false; + return true; +} + +int get_fd(const char *addr) { + int sock; + if (strcmp(addr, "stdin") == 0) { + sock = 0; + } else if (strcmp(addr, "stdout") == 0) { + sock = 1; + } else if (strcmp(addr, "stderr") == 0) { + sock = 2; + } else if (strncmp(addr, "systemd", strlen("systemd")) == 0) { + sock = 3; /* <systemd/sd-daemon.h>:SD_LISTEN_FDS_START */ + addr = &addr[strlen("systemd")]; + switch (addr[0]) { + case '\0': + /* do nothing */ + break; + case ':': + addr = &addr[1]; + if (is_numeric(addr)) { + sock += atoi(addr); + } else { + const char *e = getenv("LISTEN_FDNAMES"); + if (e == NULL) + return -ENOTCONN; + error(0, 0, "LISTEN_FDNAMES=\"%s\"", e); + char *names = strdupa(e); + char *name = NULL; + int i = -1; + do { + name = strsep(&names, ":"); + error(0, 0, "name=\"%s\"", name); + i++; + } while (name != NULL && strcmp(name, addr) != 0); + if (name == NULL) + return -ENOENT; + sock += i; + } + } + } else { + if (!is_numeric(addr)) + return -EINVAL; + sock = atoi(addr); + } + return sock; +} |