Annotation of libaitcfg/src/parse.c, revision 1.5.2.3
1.2 misho 1: /*************************************************************************
2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.5.2.3 ! misho 6: * $Id: parse.c,v 1.5.2.2 2010/03/22 19:16:34 misho Exp $
1.2 misho 7: *
1.5.2.3 ! misho 8: **************************************************************************
! 9: The ELWIX and AITNET software is distributed under the following
! 10: terms:
! 11:
! 12: All of the documentation and software included in the ELWIX and AITNET
! 13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
! 14:
! 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
! 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
! 17:
! 18: Redistribution and use in source and binary forms, with or without
! 19: modification, are permitted provided that the following conditions
! 20: are met:
! 21: 1. Redistributions of source code must retain the above copyright
! 22: notice, this list of conditions and the following disclaimer.
! 23: 2. Redistributions in binary form must reproduce the above copyright
! 24: notice, this list of conditions and the following disclaimer in the
! 25: documentation and/or other materials provided with the distribution.
! 26: 3. All advertising materials mentioning features or use of this software
! 27: must display the following acknowledgement:
! 28: This product includes software developed by Michael Pounov <misho@elwix.org>
! 29: ELWIX - Embedded LightWeight unIX and its contributors.
! 30: 4. Neither the name of AITNET nor the names of its contributors
! 31: may be used to endorse or promote products derived from this software
! 32: without specific prior written permission.
! 33:
! 34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
! 35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 44: SUCH DAMAGE.
! 45: */
1.1 misho 46: #include "global.h"
47: #include "aitcfg.h"
48:
49:
50: // cfgDbg() Debug/Log operation
51: static inline int cfgDbg(FILE *f, char *fmt, ...)
52: {
53: int ret = 0;
54: va_list lst;
55:
56: va_start(lst, fmt);
57: ret = vfprintf(f, fmt, lst);
58: va_end(lst);
59:
60: return ret;
61: }
62:
1.3 misho 63: /*
64: * InvertQueue() InvertQueue order //{cfg} list of elements for revert
65: * @cfg = Head list element for revert
66: */
67: static inline void InvertQueue(sl_config * __restrict cfg)
68: {
69: struct tagPair *item, *next, *prev = NULL;
70:
71: for (item = cfg->slh_first; item; item = next) {
72: next = item->sle_next;
73: item->sle_next = prev;
74: prev = item;
75: }
76: cfg->slh_first = prev;
77: }
78:
79: // cfgWrite() Write to file from config list
80: static inline int cfgWrite(FILE *f, sl_config * __restrict cfg, int whitespace)
81: {
82: struct tagPair *av;
83: time_t tim;
84: char szTime[MAX_STR + 1];
85: u_char szSection[MAX_STR + 1];
86:
87: bzero(szSection, MAX_STR + 1);
88:
89: bzero(szTime, MAX_STR + 1);
90: time(&tim);
91: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
92: if (!cfgDbg(f, "## Write Config :: %s\n#\n", szTime)) {
93: LOGERR;
94: return -1;
95: }
96:
97: InvertQueue(cfg);
98: for (av = cfg->slh_first; av; av = av->sle_next) {
99: if (av->psSection && strcmp((char*) av->psSection, (char*) szSection)) {
100: strlcpy((char*) szSection, (char*) av->psSection, MAX_STR + 1);
101: if (!cfgDbg(f, "\n[%s]\n", av->psSection)) {
102: LOGERR;
103: return -1;
104: }
105: }
106: if (!av->psSection && *szSection) {
107: bzero(szSection, MAX_STR + 1);
108: if (!cfgDbg(f, "\n[]\n")) {
109: LOGERR;
110: return -1;
111: }
112: }
113:
114: if (whitespace) {
115: if (!cfgDbg(f, "%s = %s\n", av->psAttribute, av->psValue)) {
116: LOGERR;
117: return -1;
118: }
119: } else {
120: if (!cfgDbg(f, "%s=%s\n", av->psAttribute, av->psValue)) {
121: LOGERR;
122: return -1;
123: }
124: }
125: }
126: InvertQueue(cfg);
127:
128: bzero(szTime, MAX_STR + 1);
129: time(&tim);
130: strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
131: if (!cfgDbg(f, "\n#\n## Done. :: %s\n", szTime)) {
132: LOGERR;
133: return -1;
134: }
135:
136: return 0;
137: }
138:
139: // ---------------------------------------------------
1.1 misho 140:
141: /*
142: * ReadConfig() Read from file and add new item to config list
143: * @f = file resource
144: * @cfg = Head list element
145: * return: 0 ok; -1 error:: can`t allocate memory
146: */
147: int ReadConfig(FILE *f, sl_config * __restrict cfg)
148: {
149: u_char szLine[MAX_STR + 1];
150: u_char szSection[MAX_STR + 1], *psAttr, *psVal;
151: int pos;
152: struct tagPair *av;
153:
154: memset(szSection, 0, MAX_STR + 1);
155: while (!feof(f)) {
156: memset(szLine, 0, MAX_STR + 1);
157: fgets((char*) szLine, MAX_STR, f);
1.5.2.2 misho 158: io_TrimStr(szLine);
1.1 misho 159: #ifdef __DEBUG
160: cfgDbg(stdout, "DEBUG:: RAW |%s|\n", szLine);
161: #endif
162:
163: // End of config
164: if (*szLine == '.')
165: break;
166: // Comment
167: if (*szLine == '#' || *szLine == ';' || !*szLine)
168: continue;
169:
170: #ifdef __DEBUG
171: cfgDbg(stdout, "DEBUG:: Clean |%s|\n", szLine);
172: #endif
173:
174: // Section
175: if (*szLine == '[') {
176: pos = strlen((char*) szLine) - 1;
177: if (szLine[pos] != ']') {
1.2 misho 178: #ifdef __DEBUG
1.1 misho 179: cfgDbg(stdout, "WARNING:: Ignore section %s ... not closed breket\n", szLine);
1.2 misho 180: #endif
1.1 misho 181: } else {
182: szLine[pos] = 0;
183: strncpy((char*) szSection, (char*) szLine + 1, MAX_STR);
184: #ifdef __DEBUG
185: cfgDbg(stdout, "DEBUG:: Section %s\n", szSection);
186: #endif
187: }
188: continue;
189: }
190:
191: // Devide pairs
192: pos = strchr((char*) szLine, '=') ? strchr((char*) szLine, '=') - (char*) szLine : 0;
193: if (!pos) {
1.2 misho 194: #ifdef __DEBUG
1.1 misho 195: cfgDbg(stdout, "WARNING:: Ignore a/v %s ... format error!\n", szLine);
1.2 misho 196: #endif
1.1 misho 197: continue;
198: } else {
199: av = malloc(sizeof(struct tagPair));
200: if (!av) {
201: LOGERR;
202: return -1;
203: } else {
1.2 misho 204: memset(av, 0, sizeof(struct tagPair));
1.1 misho 205: // added new element
206: av->sle_next = cfg->slh_first;
207: cfg->slh_first = av;
208: }
209: // added section name to element
210: if (*szSection) {
211: av->psSection = malloc(strlen((char*) szSection) + 1);
212: if (!av->psSection) {
213: LOGERR;
214: free(av);
215: return -1;
216: } else
1.2 misho 217: strlcpy((char*) av->psSection, (char*) szSection, strlen((char*) szSection) + 1);
1.1 misho 218: } else
219: av->psSection = NULL;
220:
221: psAttr = szLine;
222: psVal = (szLine + pos + 1);
223: szLine[pos] = 0;
1.5.2.2 misho 224: io_RTrimStr(psAttr);
225: io_LTrimStr(psVal);
226: io_UnquotStr(psVal);
1.1 misho 227: #ifdef __DEBUG
228: cfgDbg(stdout, "DEBUG:: Attr(%p) ->%s size=%d Value(%p) ->%s size=%d\n",
229: psAttr, psAttr, strlen((char*) psAttr), psVal, psVal, strlen((char*) psVal));
230: #endif
231: // added attribute to element
232: av->psAttribute = malloc(strlen((char*) psAttr) + 1);
233: if (!av->psAttribute) {
234: LOGERR;
235: free(av->psSection);
236: free(av);
237: return -1;
238: } else
1.2 misho 239: strlcpy((char*) av->psAttribute, (char*) psAttr, strlen((char*) psAttr) + 1);
1.1 misho 240: // added value to element
241: av->psValue = malloc(strlen((char*) psVal) + 1);
242: if (!av->psValue) {
243: LOGERR;
244: free(av->psAttribute);
245: free(av->psSection);
246: free(av);
247: return -1;
248: } else
1.2 misho 249: strlcpy((char*) av->psValue, (char*) psVal, strlen((char*) psVal) + 1);
1.1 misho 250: }
251: }
252:
253: return 0;
254: }
255:
256: /*
257: * WriteConfig() Write to file from items in config list
258: * @f = file resource
259: * @cfg = Head list element
260: * return: 0 ok; -1 error:: can`t write to file
261: */
262: int WriteConfig(FILE *f, sl_config * __restrict cfg)
263: {
1.3 misho 264: return cfgWrite(f, cfg, 1);
265: }
266:
267: /*
268: * cfg_WriteConfig() Write to file from items in config list without whitespaces!
269: * @f = file resource
270: * @cfg = Head list element
271: * return: 0 ok; -1 error:: can`t write to file
272: */
273: int cfg_WriteConfig(FILE *f, sl_config * __restrict cfg)
274: {
275: return cfgWrite(f, cfg, 0);
276: }
277:
278: /*
279: * ConcatConfig() Concat two list in one
280: * @cfg = Head list element of main list
281: * @add_cfg = Head list element of added list
282: * return: 0 ok; -1 error:: can`t concat lists
283: */
284: int ConcatConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
285: {
286: struct tagPair *item;
287: int ret = 0;
288:
289: if (!cfg || !add_cfg)
290: return -1;
291:
292: for (item = cfg->slh_first; item->sle_next; item = item->sle_next);
293: item->sle_next = add_cfg->slh_first;
294:
295: add_cfg->slh_first = NULL;
296:
297: return ret;
298: }
1.1 misho 299:
1.3 misho 300: /*
301: * MergeConfig() Marge two list in one cfg and destroy add_cfg
302: * @cfg = Head list element of main list
303: * @add_cfg = Head list element of merged list (destroy after all!)
304: * return: 0 ok; -1 error:: can`t merge lists
305: */
306: int MergeConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg)
307: {
308: struct tagPair *item, *merge, *add_next, *next = NULL;
309: int flg;
1.1 misho 310:
1.3 misho 311: if (!cfg || !add_cfg)
1.1 misho 312: return -1;
313:
1.3 misho 314: item = add_cfg->slh_first;
315: while (item) {
316: add_next = item->sle_next;
317:
318: for (flg = 0, merge = cfg->slh_first, next = merge->sle_next; next;
319: merge = merge->sle_next, next = merge->sle_next) {
320: if (!merge->psSection && !item->psSection) {
321: flg = 1;
322: merge->sle_next = item;
323: item->sle_next = next;
324: break;
325: }
326: if (merge->psSection && item->psSection &&
327: !strcmp((char*) merge->psSection, (char*) item->psSection)) {
328: flg = 1;
329: merge->sle_next = item;
330: item->sle_next = next;
331: break;
1.1 misho 332: }
333: }
1.3 misho 334:
335: if (!flg) {
336: if (!merge->sle_next) {
337: merge->sle_next = item;
338: item->sle_next = NULL;
339: } else
1.1 misho 340: return -1;
341: }
342:
1.3 misho 343: item = add_next;
1.1 misho 344: }
345:
1.3 misho 346: add_cfg->slh_first = NULL;
1.1 misho 347:
348: return 0;
349: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>