/**************************************************************************************************
$Id: conf.c,v 1.26 2005/04/21 16:25:45 bboy Exp $
conf.c: Routines to read the configuration file.
Copyright (C) 2002-2005 Don Moore <bboy@bboy.net>
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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**************************************************************************************************/
#include "mydnsutil.h"
/**************************************************************************************************
CONF_TRIM_COMMENTS
Trim comments from a line, obeying escape characters.
**************************************************************************************************/
static void
conf_trim_comments(char *s)
{
register char *c;
for (c = s; *c; c++)
{
if (*c == '\\')
c++;
else if (c[0] == '#' || (c[0] == '/' && (c[1] == '*' || c[1] == '/')))
{
*c = '\0';
return;
}
}
}
/*--- conf_trim_comments() ----------------------------------------------------------------------*/
/**************************************************************************************************
CONF_GET_OPTION
Parses the provided line, splitting a "name = value" pair, and escapes text.
**************************************************************************************************/
static void
conf_get_option(char *str, char **namep, char **valuep)
{
register char *c;
register int got_equal = 0; /* Have we found a valid equal sign yet? */
register size_t nlen, vlen;
char *name, *value;
if (!(name = malloc(1 * sizeof(char))))
Err("malloc");
if (!(value = malloc(1 * sizeof(char))))
Err("malloc");
nlen = vlen = (size_t)0;
name[0] = '\0';
value[0] = '\0';
*namep = *valuep = (char *)NULL;
for (c = str; *c; c++)
{
if (*c == '=' && !got_equal)
{
got_equal = 1;
continue;
}
if (*c == '\\')
c++;
if (!got_equal)
{
if (!name)
{
if (!(name = malloc(nlen + 2)))
Err("malloc");
}
else
{
if (!(name = realloc(name, (nlen + 2))))
Err("realloc");
}
name[nlen++] = *c;
name[nlen] = '\0';
}
else
{
if (!value)
{
if (!(value = malloc(vlen + 2)))
Err("malloc");
}
else
{
if (!(value = realloc(value, (vlen + 2))))
Err("realloc");
}
value[vlen++] = *c;
value[vlen] = '\0';
}
}
strtrim(name);
strtolower(name);
strtrim(value);
if (strlen(name))
*namep = name;
else
{
Free(name);
}
if (strlen(value))
*valuep = value;
else
{
Free(value);
}
}
/*--- conf_get_option() -------------------------------------------------------------------------*/
/**************************************************************************************************
CONF_CLOBBER
Overwrite a value if defaulted.
**************************************************************************************************/
void
conf_clobber(CONF **confp, char *name, char *value)
{
CONF *conf = *confp, *c; /* Start of list/found item */
if (!name || !value)
return;
for (c = conf; c; c = c->next)
if (c->name && !memcmp(c->name, name, strlen(c->name)) && c->defaulted)
{
Free(c->value);
c->value = strdup(value);
}
}
/*--- conf_clobber() ----------------------------------------------------------------------------*/
/**************************************************************************************************
CONF_SET
Sets a configuration value.
**************************************************************************************************/
void
conf_set(CONF **confp, char *name, char *value, int defaulted)
{
CONF *conf = *confp; /* Start of list */
CONF *new; /* New item to add */
register CONF *c;
if (!name)
return;
/* Try to find the specified option in the current list */
for (c = conf; c; c = c->next)
if (c->name && !memcmp(c->name, name, strlen(c->name)))
{
/* Found in current list; append field separator and value */
if (!strcasecmp(c->name, "listen")
|| !strcasecmp(c->name, "no-listen")
|| !strcasecmp(c->name, "bind"))
{
if (!c->value)
{
if (!(c->value = malloc(strlen(value) + 2)))
Err("malloc");
}
else
{
if (!(c->value = realloc(c->value, strlen(c->value) + strlen(value) + 2)))
Err("realloc");
}
strcpy(c->value + strlen(c->value) + 1, value);
c->value[strlen(c->value)] = CONF_FS_CHAR;
}
return;
}
/* Add new item to array */
if (!(new = (CONF *)calloc(1, sizeof(CONF))))
Err("calloc");
if (!(new->name = strdup(name)))
Err("strdup");
if (!(new->value = value ? (char *)strdup(value) : (char *)NULL))
Err("strdup");
new->defaulted = defaulted;
new->next = conf;
conf = new;
*confp = conf;
}
/*--- conf_set() --------------------------------------------------------------------------------*/
/**************************************************************************************************
CONF_GET
Returns the value associated with the specified name.
**************************************************************************************************/
char *
conf_get(CONF **confp, char *name, int *defaulted)
{
CONF *conf = *confp; /* Start of list */
register CONF *c;
if (defaulted)
*defaulted = 1;
for (c = conf; c; c = c->next)
if (!memcmp(c->name, name, strlen(c->name))
|| (c->altname && !memcmp(c->altname, name, strlen(c->name))))
{
if (defaulted)
*defaulted = c->defaulted;
return (c->value);
}
return (NULL);
}
/*--- conf_get() --------------------------------------------------------------------------------*/
/**************************************************************************************************
CONF_LOAD
Load the MyDNS configuration file.
**************************************************************************************************/
void
conf_load(CONF **confp, const char *filename)
{
FILE *fp; /* Input file pointer */
char linebuf[BUFSIZ]; /* Input line buffer */
char *name, *value; /* Name and value from `linebuf' */
CONF *conf = *confp; /* Config list */
int lineno = 0; /* Current line number in config */
struct stat st; /* File stat for conf file */
/* If the config file is not present at all, that's not an error */
if (stat(filename, &st))
{
Verbose("%s: %s", filename, strerror(errno));
return;
}
/* Read config file */
if ((fp = fopen(filename, "r")))
{
while (fgets(linebuf, sizeof(linebuf), fp))
{
lineno++;
conf_trim_comments(linebuf);
conf_get_option(linebuf, &name, &value);
if (name)
{
#if 0
if (!value)
Warnx(_("%s: line %d: option \"%s\" given without a value - ignored"), filename, lineno, name);
else
#endif
if (value)
conf_set(&conf, name, value, 0);
Free(name);
}
if (value)
{
Free(value);
}
}
fclose(fp);
}
else
{
Verbose("%s: %s", filename, strerror(errno));
return;
}
*confp = conf;
}
/*--- conf_load() -------------------------------------------------------------------------------*/
/* vi:set ts=3: */
/* NEED_PO */
syntax highlighted by Code2HTML, v. 0.9.1