2 * Part: Configuration file parser/reader. Place into the dynamic
3 * data structure representation the conf file
5 * Version: $Id: parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
7 * Author: Alexandre Cassen, <acassen@linux-vs.org>
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
27 static int sublevel = 0;
28 vector keywords = NULL;
29 vector *keywords_addr = NULL;
32 void set_current_keywords (vector *k)
39 keyword_alloc(vector keywords, char *string, int (*handler) (vector),
40 int (*print) (char *, int, void *), int unique)
42 struct keyword *keyword;
44 keyword = (struct keyword *) MALLOC(sizeof (struct keyword));
49 if (!vector_alloc_slot(keywords)) {
53 keyword->string = string;
54 keyword->handler = handler;
55 keyword->print = print;
56 keyword->unique = unique;
58 vector_set_slot(keywords, keyword);
64 install_keyword_root(char *string, int (*handler) (vector))
66 int r = keyword_alloc(keywords, string, handler, NULL, 1);
68 *keywords_addr = keywords;
73 install_sublevel(void)
79 install_sublevel_end(void)
85 _install_keyword(char *string, int (*handler) (vector),
86 int (*print) (char *, int, void *), int unique)
89 struct keyword *keyword;
91 /* fetch last keyword */
92 keyword = VECTOR_SLOT(keywords, VECTOR_SIZE(keywords) - 1);
94 /* position to last sub level */
95 for (i = 0; i < sublevel; i++)
97 VECTOR_SLOT(keyword->sub, VECTOR_SIZE(keyword->sub) - 1);
99 /* First sub level allocation */
101 keyword->sub = vector_alloc();
106 /* add new sub keyword */
107 return keyword_alloc(keyword->sub, string, handler, print, unique);
111 free_keywords(vector keywords)
113 struct keyword *keyword;
119 for (i = 0; i < VECTOR_SIZE(keywords); i++) {
120 keyword = VECTOR_SLOT(keywords, i);
122 free_keywords(keyword->sub);
125 vector_free(keywords);
129 find_keyword(vector v, char * name)
131 struct keyword *keyword;
135 if (!name || !keywords)
143 for (i = 0; i < VECTOR_SIZE(v); i++) {
144 keyword = VECTOR_SLOT(v, i);
145 if ((strlen(keyword->string) == len) &&
146 !strcmp(keyword->string, name))
149 keyword = find_keyword(keyword->sub, name);
158 snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, void *data)
164 if (!kw || !kw->print)
168 if (fwd == len || *f == '\0')
178 fwd += snprintf(buff + fwd, len - fwd, "%s", kw->string);
181 r = kw->print(buff + fwd, len - fwd, data);
182 if (!r) { /* no output if no value */
196 alloc_strvec(char *string)
198 char *cp, *start, *token;
208 /* Skip white spaces */
209 while ((isspace((int) *cp) || !isascii((int) *cp)) && *cp != '\0')
212 /* Return if there is only white spaces */
216 /* Return if string begin with a comment */
217 if (*cp == '!' || *cp == '#')
220 /* Create a vector and alloc each command piece */
221 strvec = vector_alloc();
228 if (!vector_alloc_slot(strvec))
245 } else if (!in_string && (*cp == '{' || *cp == '}')) {
256 (!isspace((int) *cp) && isascii((int) *cp) &&
257 *cp != '!' && *cp != '#' && *cp != '{' &&
258 *cp != '}')) && *cp != '\0' && *cp != '"')
261 token = MALLOC(strlen + 1);
266 memcpy(token, start, strlen);
267 *(token + strlen) = '\0';
269 vector_set_slot(strvec, token);
271 while ((isspace((int) *cp) || !isascii((int) *cp))
274 if (*cp == '\0' || *cp == '!' || *cp == '#')
283 read_line(char *buf, int size)
288 while ((ch = fgetc(stream)) != EOF && (int) ch != '\n'
289 && (int) ch != '\r') {
291 buf[count] = (int) ch;
296 return (ch == EOF) ? 0 : 1;
300 read_value_block(void)
307 vector elements = vector_alloc();
312 buf = (char *) MALLOC(MAXBUF);
317 while (read_line(buf, MAXBUF)) {
318 vec = alloc_strvec(buf);
320 str = VECTOR_SLOT(vec, 0);
321 if (!strcmp(str, EOB)) {
326 if (VECTOR_SIZE(vec))
327 for (i = 0; i < VECTOR_SIZE(vec); i++) {
328 str = VECTOR_SLOT(vec, i);
329 dup = (char *) MALLOC(strlen(str) + 1);
332 memcpy(dup, str, strlen(str));
334 if (!vector_alloc_slot(elements)) {
339 vector_set_slot(elements, dup);
343 memset(buf, 0, MAXBUF);
355 alloc_value_block(vector strvec, void (*alloc_func) (vector))
361 buf = (char *) MALLOC(MAXBUF);
366 while (read_line(buf, MAXBUF)) {
367 vec = alloc_strvec(buf);
369 str = VECTOR_SLOT(vec, 0);
370 if (!strcmp(str, EOB)) {
375 if (VECTOR_SIZE(vec))
380 memset(buf, 0, MAXBUF);
387 set_value(vector strvec)
389 char *str = VECTOR_SLOT(strvec, 1);
390 int size = strlen(str);
397 for (i = 2; i < VECTOR_SIZE(strvec); i++) {
398 str = VECTOR_SLOT(strvec, i);
402 (char *) MALLOC(sizeof (char *) *
406 REALLOC(alloc, sizeof (char *) * (len + 1));
407 tmp = VECTOR_SLOT(strvec, i-1);
408 if (alloc && *str != '"' && *tmp != '"')
409 strncat(alloc, " ", 1);
412 if (alloc && i != VECTOR_SIZE(strvec)-1)
413 strncat(alloc, str, strlen(str));
416 alloc = MALLOC(sizeof (char *) * (size + 1));
418 memcpy(alloc, str, size);
423 /* non-recursive configuration stream handler */
424 static int kw_level = 0;
426 int warn_on_duplicates(vector uniques, char *str)
431 vector_foreach_slot(uniques, tmp, i) {
432 if (!strcmp(str, tmp)) {
433 condlog(1, "multipath.conf line %d, duplicate keyword: %s", line_nr, str);
440 if (!vector_alloc_slot(uniques)) {
444 vector_set_slot(uniques, tmp);
448 void free_uniques(vector uniques)
453 vector_foreach_slot(uniques, tmp, i)
455 vector_free(uniques);
459 process_stream(vector keywords)
463 struct keyword *keyword;
469 uniques = vector_alloc();
473 buf = MALLOC(MAXBUF);
476 vector_free(uniques);
480 while (read_line(buf, MAXBUF)) {
482 strvec = alloc_strvec(buf);
483 memset(buf,0, MAXBUF);
488 str = VECTOR_SLOT(strvec, 0);
490 if (!strcmp(str, EOB) && kw_level > 0) {
495 for (i = 0; i < VECTOR_SIZE(keywords); i++) {
496 keyword = VECTOR_SLOT(keywords, i);
498 if (!strcmp(keyword->string, str)) {
499 if (keyword->unique &&
500 warn_on_duplicates(uniques, str)) {
505 if (keyword->handler)
506 r += (*keyword->handler) (strvec);
510 r += process_stream(keyword->sub);
516 if (i >= VECTOR_SIZE(keywords))
517 condlog(1, "multipath.conf +%d, invalid keyword: %s",
525 free_uniques(uniques);
529 /* Data initialization */
531 init_data(char *conf_file, void (*init_keywords) (void))
536 keywords = vector_alloc();
539 stream = fopen(conf_file, "r");
541 syslog(LOG_WARNING, "Configuration file open problem");
545 /* Init Keywords structure */
548 /* Dump configuration *
549 vector_dump(keywords);
550 dump_keywords(keywords, 0);
553 /* Stream handling */
555 r = process_stream(keywords);
557 //free_keywords(keywords);