/*************************************************************************
* (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
* by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: parse.c,v 1.2.2.3 2009/09/23 14:20:53 misho Exp $
*
*************************************************************************/
#include "global.h"
#include "aitcfg.h"
#include "tools.h"
// cfgDbg() Debug/Log operation
static inline int cfgDbg(FILE *f, char *fmt, ...)
{
int ret = 0;
va_list lst;
va_start(lst, fmt);
ret = vfprintf(f, fmt, lst);
va_end(lst);
return ret;
}
/*
* InvertQueue() InvertQueue order //{cfg} list of elements for revert
* @cfg = Head list element for revert
*/
static inline void InvertQueue(sl_config * __restrict cfg)
{
struct tagPair *item, *next, *prev = NULL;
for (item = cfg->slh_first; item; item = next) {
next = item->sle_next;
item->sle_next = prev;
prev = item;
}
cfg->slh_first = prev;
}
// cfgWrite() Write to file from config list
static inline int cfgWrite(FILE *f, sl_config * __restrict cfg, int whitespace)
{
struct tagPair *av;
time_t tim;
char szTime[MAX_STR + 1];
u_char szSection[MAX_STR + 1];
bzero(szSection, MAX_STR + 1);
bzero(szTime, MAX_STR + 1);
time(&tim);
strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
if (!cfgDbg(f, "## Write Config :: %s\n#\n", szTime)) {
LOGERR;
return -1;
}
InvertQueue(cfg);
for (av = cfg->slh_first; av; av = av->sle_next) {
if (av->psSection && strcmp((char*) av->psSection, (char*) szSection)) {
strlcpy((char*) szSection, (char*) av->psSection, MAX_STR + 1);
if (!cfgDbg(f, "\n[%s]\n", av->psSection)) {
LOGERR;
return -1;
}
}
if (!av->psSection && *szSection) {
bzero(szSection, MAX_STR + 1);
if (!cfgDbg(f, "\n[]\n")) {
LOGERR;
return -1;
}
}
if (whitespace) {
if (!cfgDbg(f, "%s = %s\n", av->psAttribute, av->psValue)) {
LOGERR;
return -1;
}
} else {
if (!cfgDbg(f, "%s=%s\n", av->psAttribute, av->psValue)) {
LOGERR;
return -1;
}
}
}
InvertQueue(cfg);
bzero(szTime, MAX_STR + 1);
time(&tim);
strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
if (!cfgDbg(f, "\n#\n## Done. :: %s\n", szTime)) {
LOGERR;
return -1;
}
return 0;
}
// ---------------------------------------------------
/*
* ReadConfig() Read from file and add new item to config list
* @f = file resource
* @cfg = Head list element
* return: 0 ok; -1 error:: can`t allocate memory
*/
int ReadConfig(FILE *f, sl_config * __restrict cfg)
{
u_char szLine[MAX_STR + 1];
u_char szSection[MAX_STR + 1], *psAttr, *psVal;
int pos;
struct tagPair *av;
memset(szSection, 0, MAX_STR + 1);
while (!feof(f)) {
memset(szLine, 0, MAX_STR + 1);
fgets((char*) szLine, MAX_STR, f);
trim(szLine);
#ifdef __DEBUG
cfgDbg(stdout, "DEBUG:: RAW |%s|\n", szLine);
#endif
// End of config
if (*szLine == '.')
break;
// Comment
if (*szLine == '#' || *szLine == ';' || !*szLine)
continue;
#ifdef __DEBUG
cfgDbg(stdout, "DEBUG:: Clean |%s|\n", szLine);
#endif
// Section
if (*szLine == '[') {
pos = strlen((char*) szLine) - 1;
if (szLine[pos] != ']') {
#ifdef __DEBUG
cfgDbg(stdout, "WARNING:: Ignore section %s ... not closed breket\n", szLine);
#endif
} else {
szLine[pos] = 0;
strncpy((char*) szSection, (char*) szLine + 1, MAX_STR);
#ifdef __DEBUG
cfgDbg(stdout, "DEBUG:: Section %s\n", szSection);
#endif
}
continue;
}
// Devide pairs
pos = strchr((char*) szLine, '=') ? strchr((char*) szLine, '=') - (char*) szLine : 0;
if (!pos) {
#ifdef __DEBUG
cfgDbg(stdout, "WARNING:: Ignore a/v %s ... format error!\n", szLine);
#endif
continue;
} else {
av = malloc(sizeof(struct tagPair));
if (!av) {
LOGERR;
return -1;
} else {
memset(av, 0, sizeof(struct tagPair));
// added new element
av->sle_next = cfg->slh_first;
cfg->slh_first = av;
}
// added section name to element
if (*szSection) {
av->psSection = malloc(strlen((char*) szSection) + 1);
if (!av->psSection) {
LOGERR;
free(av);
return -1;
} else
strlcpy((char*) av->psSection, (char*) szSection, strlen((char*) szSection) + 1);
} else
av->psSection = NULL;
psAttr = szLine;
psVal = (szLine + pos + 1);
szLine[pos] = 0;
rtrim(psAttr);
ltrim(psVal);
#ifdef __DEBUG
cfgDbg(stdout, "DEBUG:: Attr(%p) ->%s size=%d Value(%p) ->%s size=%d\n",
psAttr, psAttr, strlen((char*) psAttr), psVal, psVal, strlen((char*) psVal));
#endif
// added attribute to element
av->psAttribute = malloc(strlen((char*) psAttr) + 1);
if (!av->psAttribute) {
LOGERR;
free(av->psSection);
free(av);
return -1;
} else
strlcpy((char*) av->psAttribute, (char*) psAttr, strlen((char*) psAttr) + 1);
// added value to element
av->psValue = malloc(strlen((char*) psVal) + 1);
if (!av->psValue) {
LOGERR;
free(av->psAttribute);
free(av->psSection);
free(av);
return -1;
} else
strlcpy((char*) av->psValue, (char*) psVal, strlen((char*) psVal) + 1);
}
}
return 0;
}
/*
* WriteConfig() Write to file from items in config list
* @f = file resource
* @cfg = Head list element
* return: 0 ok; -1 error:: can`t write to file
*/
int WriteConfig(FILE *f, sl_config * __restrict cfg)
{
return cfgWrite(f, cfg, 1);
}
/*
* cfg_WriteConfig() Write to file from items in config list without whitespaces!
* @f = file resource
* @cfg = Head list element
* return: 0 ok; -1 error:: can`t write to file
*/
int cfg_WriteConfig(FILE *f, sl_config * __restrict cfg)
{
return cfgWrite(f, cfg, 0);
}
/*
* ConcatConfig() Concat two list in one
* @cfg = Head list element of main list
* @add_cfg = Head list element of added list
* return: 0 ok; -1 error:: can`t concat lists
*/
int ConcatConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
{
struct tagPair *item;
int ret = 0;
if (!cfg || !add_cfg)
return -1;
for (item = cfg->slh_first; item->sle_next; item = item->sle_next);
item->sle_next = add_cfg->slh_first;
return ret;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>