--- libaitcfg/src/parse.c 2023/01/23 21:03:50 1.20.2.1 +++ libaitcfg/src/parse.c 2026/08/04 18:51:43 1.22.4.1 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: parse.c,v 1.20.2.1 2023/01/23 21:03:50 misho Exp $ +* $Id: parse.c,v 1.22.4.1 2026/08/04 18:51:43 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004 - 2023 +Copyright 2004 - 2026 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -47,16 +47,17 @@ SUCH DAMAGE. /* - * cfgReadConfig() - Read file and add new item at config root + * cfg_ReadConfig() - Read file and add new item at config root * * @f = File resource * @cfg = Config root + * @lvl = Level of include recursion * return: -1 error or 0 ok */ int -cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg) +cfg_ReadConfig(FILE *f, cfg_root_t * __restrict cfg, int lvl) { - char line[BUFSIZ], origin[BUFSIZ]; + char line[BUFSIZ], origin[BUFSIZ], chkattr[STRSIZ]; struct tagCfg *av = NULL; int flg = 0; char *psAttr, *psVal, szSection[STRSIZ] = { 0 }; @@ -77,8 +78,14 @@ cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg) break; #endif if (!(psAttr = strpbrk(line, "\r\n"))) { - /* skip line, too long */ - continue; + if (feof(f) && strlen(line) > 0) { + /* last line without end of line */ + strlcpy(origin, line, sizeof origin); + str_Trim(line); + } else { + /* skip line, too long */ + continue; + } } else { *psAttr = 0; strlcpy(origin, line, sizeof origin); @@ -100,21 +107,33 @@ cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg) if (!flg && AIT_ADDR(&av->cfg_val)) av->cfg_quoted += str_Unquot((char*) AIT_GET_STR(&av->cfg_val)); - /* read include file */ - if (!flg && AIT_ADDR(&av->cfg_val) && - *AIT_GET_STR(&av->cfg_attr) == '%' && - !strcmp(AIT_GET_STR(&av->cfg_attr), "%include")) { - ff = fopen(AIT_GET_STR(&av->cfg_val), "r"); - if (ff) { - cfgReadConfig(ff, cfg); - fclose(ff); - } else - EDEBUG(ELWIX_DEBUG_LOG, "Error:: Can't open %s file", - AIT_GET_STR(&av->cfg_val)); + if (lvl > 0) { + /* read include file */ + if (!flg && AIT_ADDR(&av->cfg_val) && + *AIT_GET_STR(&av->cfg_attr) == '%' && + !strcmp(AIT_GET_STR(&av->cfg_attr), "%include")) { + ff = fopen(AIT_GET_STR(&av->cfg_val), "r"); + if (ff) { + cfg_ReadConfig(ff, cfg, lvl - 1); + fclose(ff); + } else + EDEBUG(ELWIX_DEBUG_LOG, "Error:: Can't open %s file", + AIT_GET_STR(&av->cfg_val)); + } } continue; } + /* check for duplicated element */ + if (*line != '#' && *line != ';' && *line != '/' && *line != '%' && + (psAttr = strchr(line, '='))) { + strncpy(chkattr, line, psAttr - line); + chkattr[psAttr - line] = 0; + str_RTrim(chkattr); + if (cfg_findAttribute(cfg, szSection, chkattr)) + cfg_unsetAttribute(cfg, szSection, chkattr); + } + /* *NEW PAIR* alloc new pair element */ av = e_malloc(sizeof(struct tagCfg)); if (!av) { @@ -183,16 +202,18 @@ cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg) RB_INSERT(tagRC, cfg, av); CFG_RC_UNLOCK(cfg); - /* read include file */ - if (!flg && *AIT_GET_STR(&av->cfg_attr) == '%' && - !strcmp(AIT_GET_STR(&av->cfg_attr), "%include")) { - ff = fopen(AIT_GET_STR(&av->cfg_val), "r"); - if (ff) { - cfgReadConfig(ff, cfg); - fclose(ff); - } else - EDEBUG(ELWIX_DEBUG_LOG, "Error:: Can't open %s file", - AIT_GET_STR(&av->cfg_val)); + if (lvl > 0) { + /* read include file */ + if (!flg && *AIT_GET_STR(&av->cfg_attr) == '%' && + !strcmp(AIT_GET_STR(&av->cfg_attr), "%include")) { + ff = fopen(AIT_GET_STR(&av->cfg_val), "r"); + if (ff) { + cfg_ReadConfig(ff, cfg, lvl - 1); + fclose(ff); + } else + EDEBUG(ELWIX_DEBUG_LOG, "Error:: Can't open %s file", + AIT_GET_STR(&av->cfg_val)); + } } } @@ -413,15 +434,21 @@ cfgMergeConfig(cfg_root_t * __restrict cfg, cfg_root_t if (!AIT_ISEMPTY(&merge->cfg_sec) && !AIT_ISEMPTY(&item->cfg_sec) && AIT_ADDR(&merge->cfg_sec) && AIT_ADDR(&item->cfg_sec) && !strcmp(AIT_GET_STR(&merge->cfg_sec), AIT_GET_STR(&item->cfg_sec))) { - flg = 1; + flg = -1; break; } } - if (!flg) - TAILQ_INSERT_TAIL(cfg, item, cfg_next); - else - TAILQ_INSERT_AFTER(cfg, merge, item, cfg_next); + switch (flg) { + case -1: + continue; /* skip duplicated element */ + case 1: + TAILQ_INSERT_AFTER(cfg, merge, item, cfg_next); + break; + case 0: + TAILQ_INSERT_TAIL(cfg, item, cfg_next); + break; + } RB_INSERT(tagRC, cfg, item); } @@ -482,6 +509,10 @@ cfgReadLines(FILE *f, const char *delim, const char *e } if (!av_MakeExt(p, SEC_LINES_DELIM, &psSec, &psAttr)) psAttr = p; + + /* check for duplicated element */ + if (psAttr && cfg_findAttribute(cfg, psSec, psAttr)) + cfg_unsetAttribute(cfg, psSec, psAttr); /* *NEW PAIR* alloc new pair element */ av = e_malloc(sizeof(struct tagCfg));