/* rc-misc.c rc misc functions */ /* * Copyright (c) 2007-2008 Roy Marples * 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 AUTHOR 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. */ #include "librc.h" bool rc_yesno(const char *value) { if (!value) { errno = ENOENT; return false; } if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "y") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) return true; if (strcasecmp(value, "no") != 0 && strcasecmp(value, "n") != 0 && strcasecmp(value, "false") != 0 && strcasecmp(value, "0") != 0) errno = EINVAL; return false; } librc_hidden_def(rc_yesno) ssize_t rc_getline(char **line, size_t *len, FILE *fp) { char *p; size_t last = 0; while(!feof(fp)) { if (*line == NULL || last != 0) { *len += BUFSIZ; *line = xrealloc(*line, *len); } p = *line + last; memset(p, 0, BUFSIZ); if (fgets(p, BUFSIZ, fp) == NULL) break; last += strlen(p); if (last && (*line)[last - 1] == '\n') { (*line)[last - 1] = '\0'; break; } } return last; } librc_hidden_def(rc_getline) RC_STRINGLIST * rc_config_list(const char *file) { FILE *fp; char *buffer = NULL; size_t len = 0; char *p; char *token; RC_STRINGLIST *list = rc_stringlist_new(); if (!(fp = fopen(file, "r"))) return list; while ((rc_getline(&buffer, &len, fp))) { p = buffer; /* Strip leading spaces/tabs */ while ((*p == ' ') || (*p == '\t')) p++; /* Get entry - we do not want comments */ token = strsep(&p, "#"); if (token && (strlen(token) > 1)) { /* If not variable assignment then skip */ if (strchr(token, '=')) { /* Stip the newline if present */ if (token[strlen(token) - 1] == '\n') token[strlen(token) - 1] = 0; rc_stringlist_add(list, token); } } } fclose(fp); free(buffer); return list; } librc_hidden_def(rc_config_list) RC_STRINGLIST * rc_config_load(const char *file) { RC_STRINGLIST *list; RC_STRINGLIST *config; char *token; RC_STRING *line; RC_STRING *cline; size_t i = 0; bool replaced; char *entry; char *newline; char *p; list = rc_config_list(file); config = rc_stringlist_new(); TAILQ_FOREACH(line, list, entries) { /* Get entry */ p = line->value; if (! p) continue; if (strncmp(p, "export ", 7) == 0) p += 7; if (! (token = strsep(&p, "="))) continue; entry = xstrdup(token); /* Preserve shell coloring */ if (*p == '$') token = line->value; else do { /* Bash variables are usually quoted */ token = strsep(&p, "\"\'"); } while (token && *token == '\0'); /* Drop a newline if that's all we have */ if (token) { i = strlen(token) - 1; if (token[i] == '\n') token[i] = 0; i = strlen(entry) + strlen(token) + 2; newline = xmalloc(sizeof(char) * i); snprintf(newline, i, "%s=%s", entry, token); } else { i = strlen(entry) + 2; newline = xmalloc(sizeof(char) * i); snprintf(newline, i, "%s=", entry); } replaced = false; /* In shells the last item takes precedence, so we need to remove any prior values we may already have */ TAILQ_FOREACH(cline, config, entries) { p = strchr(cline->value, '='); if (p && strncmp(entry, cline->value, (size_t)(p - cline->value)) == 0) { /* We have a match now - to save time we directly replace it */ free(cline->value); cline->value = newline; replaced = true; break; } } if (!replaced) { rc_stringlist_add(config, newline); free(newline); } free(entry); } rc_stringlist_free(list); return config; } librc_hidden_def(rc_config_load) char * rc_config_value(RC_STRINGLIST *list, const char *entry) { RC_STRING *line; char *p; size_t len, dif; len = strlen(entry); TAILQ_FOREACH(line, list, entries) { p = strchr(line->value, '='); if (p != NULL) { dif = (p - line->value); if (dif == len && strncmp(entry, line->value, dif) == 0) return ++p; } } return NULL; } librc_hidden_def(rc_config_value)