openrc/src/librc/librc-misc.c
2009-05-01 15:11:40 +01:00

221 lines
5.1 KiB
C

/*
rc-misc.c
rc misc functions
*/
/*
* Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
* 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)