/* * Copyright (c) 2008-2017 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Configuration file loading. */ #include #include #include #include #include #include #include #include #include #include #include #include "mailprocd.h" CFG_File * CFG_OpenFile(const char *dir, const char *file) { char path[FILENAME_MAX]; CFG_File *cf; char *data, *s, *line; size_t len, nRead; ssize_t rv; int fd; Strlcpy(path, dir, sizeof(path)); Strlcat(path, "/", sizeof(path)); Strlcat(path, file, sizeof(path)); if ((fd = open(path, O_RDONLY)) == -1) { MPD_SetError("%s: %s", path, strerror(errno)); return (NULL); } if ((len = (size_t)lseek(fd, 0, SEEK_END)) == 0) { if ((cf = malloc(sizeof(CFG_File))) == NULL) { MPD_SetErrorS("Out of memory"); close(fd); return (NULL); } cf->keys = NULL; cf->vals = NULL; cf->nvals = 0; return (cf); } lseek(fd, 0, SEEK_SET); if ((data = malloc(len+1)) == NULL) { close(fd); return (NULL); } for (nRead = 0; nRead < len; ) { rv = read(fd, &data[nRead], len-nRead); if (rv == -1) { if (errno == EINTR) { continue; } goto fail_read; } else if (rv == 0) { goto fail_read; } nRead += rv; } data[nRead] = '\0'; close(fd); if ((cf = malloc(sizeof(CFG_File))) == NULL) { goto outofmem; } if ((cf->keys = malloc(sizeof(char **))) == NULL) { free(cf); goto outofmem; } if ((cf->vals = malloc(sizeof(char **))) == NULL) { free(cf->keys); free(cf); goto outofmem; } cf->nvals = 0; s = data; while ((line = strsep(&s, "\n")) != NULL) { char *c = &line[0], *cKey, *cVal; while (isspace(*c)) { c++; } if (*c == '#') continue; cKey = strsep(&c, "="); cVal = strsep(&c, "="); if (cKey == NULL || cVal == NULL) continue; while (isspace(*cKey)) { cKey++; } while (isspace(*cVal)) { cVal++; } len = strlen(cKey)-1; for (;;) { if (!isspace(cKey[len])) { break; } cKey[len] = '\0'; len--; } cf->keys = realloc(cf->keys, (cf->nvals+1)*sizeof(char *)); cf->vals = realloc(cf->vals, (cf->nvals+1)*sizeof(char *)); if (cf->keys == NULL || cf->vals == NULL) { goto outofmem; } if ((cf->keys[cf->nvals] = strdup(cKey)) == NULL) { goto outofmem; } if ((cf->vals[cf->nvals] = strdup(cVal)) == NULL) { goto outofmem; } cf->nvals++; } free(data); return (cf); fail_read: MPD_SetErrorS("Read error"); close(fd); free(data); return (NULL); outofmem: MPD_SetErrorS("Out of memory"); free(data); return (NULL); } void CFG_CloseFile(CFG_File *cf) { free(cf->keys); free(cf->vals); free(cf); } void CFG_GetInt(CFG_File *cf, const char *key, int *pVal, int dVal) { Uint i; char *val; for (i = 0; i < cf->nvals; i++) { if (!strcasecmp(cf->keys[i], key)) { val = cf->vals[i]; if (!strcasecmp(val, "true") || !strcasecmp(val, "yes") || !strcasecmp(val, "on")) { *pVal = 1; } else if (!strcasecmp(val, "false") || !strcasecmp(val, "no") || !strcasecmp(val, "off")) { *pVal = 0; } else { *pVal = (int)strtol(cf->vals[i], NULL, 10); } return; } } *pVal = dVal; } void CFG_GetUint(CFG_File *cf, const char *key, Uint *pVal, Uint dVal) { Uint i; for (i = 0; i < cf->nvals; i++) { if (strcasecmp(cf->keys[i], key) == 0) { *pVal = strtoul(cf->vals[i], NULL, 10); return; } } *pVal = dVal; } void CFG_GetFlt(CFG_File *cf, const char *key, float *pVal, float dVal) { Uint i; for (i = 0; i < cf->nvals; i++) { if (strcasecmp(cf->keys[i], key) == 0) { *pVal = (float)strtod(cf->vals[i], NULL); return; } } *pVal = (float)dVal; } void CFG_GetDbl(CFG_File *cf, const char *key, double *pVal, double dVal) { Uint i; for (i = 0; i < cf->nvals; i++) { if (strcasecmp(cf->keys[i], key) == 0) { *pVal = strtod(cf->vals[i], NULL); return; } } *pVal = dVal; } void CFG_GetStr(CFG_File *cf, const char *key, char **pVal, const char *dVal) { Uint i; size_t len; char *s; for (i = 0; i < cf->nvals; i++) { if (strcasecmp(cf->keys[i], key) == 0) { if ((s = strdup(cf->vals[i])) == NULL) { Fatal("Out of memory"); } if (*s == '"' || *s == '\'') { s++; } len = strlen(s); if (s[len-1] == '"' || s[len-1] == '\'') { s[len-1] = '\0'; } *pVal = s; return; } } if ((*pVal = strdup(dVal)) == NULL) Fatal("Out of memory"); } void CFG_CopyStr(CFG_File *cf, const char *key, char *dst, size_t len, const char *dVal) { Uint i; size_t sLen; for (i = 0; i < cf->nvals; i++) { if (strcasecmp(cf->keys[i], key) == 0) { char *s = cf->vals[i]; if (*s == '"' || *s == '\'') { s++; } Strlcpy(dst, s, len); sLen = strlen(dst); if (dst[sLen-1] == '"' || dst[sLen-1] == '\'') { dst[sLen-1] = '\0'; } return; } } Strlcpy(dst, dVal, len); }