/* util.c - miscellaneous utility functions * * Copyright (C) 2016 Luke Shumaker * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include /* for isdigit */ #include #include #include #include "util.h" void *xrealloc(void *ptr, size_t size) { void *ret = realloc(ptr, size); if (ret == NULL) { if (ptr==NULL) error(1, errno, "Could not allocate memory"); else error(1, errno, "Could not re-allocate memory"); } 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; /* :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; char *names = strdupa(e); char *name = NULL; int i = -1; do { name = strsep(&names, ":"); 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; }