Initial git import.
[platform/upstream/multipath-tools.git] / libmultipath / parser.c
1 /* 
2  * Part:        Configuration file parser/reader. Place into the dynamic
3  *              data structure representation the conf file
4  *  
5  * Version:     $Id: parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
6  * 
7  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
8  *              
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.
13  *
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.
18  */
19
20 #include <syslog.h>
21
22 #include "parser.h"
23 #include "memory.h"
24
25 /* local vars */
26 static int sublevel = 0;
27
28 int
29 keyword_alloc(vector keywords, char *string, int (*handler) (vector))
30 {
31         struct keyword *keyword;
32
33         keyword = (struct keyword *) MALLOC(sizeof (struct keyword));
34
35         if (!keyword)
36                 return 1;
37         
38         if (!vector_alloc_slot(keywords)) {
39                 FREE(keyword);
40                 return 1;
41         }
42         keyword->string = string;
43         keyword->handler = handler;
44
45         vector_set_slot(keywords, keyword);
46
47         return 0;
48 }
49
50 int
51 install_keyword_root(char *string, int (*handler) (vector))
52 {
53         return keyword_alloc(keywords, string, handler);
54 }
55
56 void
57 install_sublevel(void)
58 {
59         sublevel++;
60 }
61
62 void
63 install_sublevel_end(void)
64 {
65         sublevel--;
66 }
67
68 int
69 install_keyword(char *string, int (*handler) (vector))
70 {
71         int i = 0;
72         struct keyword *keyword;
73
74         /* fetch last keyword */
75         keyword = VECTOR_SLOT(keywords, VECTOR_SIZE(keywords) - 1);
76
77         /* position to last sub level */
78         for (i = 0; i < sublevel; i++)
79                 keyword =
80                     VECTOR_SLOT(keyword->sub, VECTOR_SIZE(keyword->sub) - 1);
81
82         /* First sub level allocation */
83         if (!keyword->sub)
84                 keyword->sub = vector_alloc();
85
86         if (!keyword->sub)
87                 return 1;
88
89         /* add new sub keyword */
90         return keyword_alloc(keyword->sub, string, handler);
91 }
92
93 void
94 free_keywords(vector keywords)
95 {
96         struct keyword *keyword;
97         int i;
98
99         for (i = 0; i < VECTOR_SIZE(keywords); i++) {
100                 keyword = VECTOR_SLOT(keywords, i);
101                 if (keyword->sub)
102                         free_keywords(keyword->sub);
103                 FREE(keyword);
104         }
105         vector_free(keywords);
106 }
107
108 vector
109 alloc_strvec(char *string)
110 {
111         char *cp, *start, *token;
112         int strlen;
113         int in_string;
114         vector strvec;
115
116         if (!string)
117                 return NULL;
118
119         cp = string;
120
121         /* Skip white spaces */
122         while (isspace((int) *cp) && *cp != '\0')
123                 cp++;
124
125         /* Return if there is only white spaces */
126         if (*cp == '\0')
127                 return NULL;
128
129         /* Return if string begin with a comment */
130         if (*cp == '!' || *cp == '#')
131                 return NULL;
132
133         /* Create a vector and alloc each command piece */
134         strvec = vector_alloc();
135
136         if (!strvec)
137                 return NULL;
138
139         in_string = 0;
140         while (1) {
141                 if (!vector_alloc_slot(strvec))
142                         goto out;
143
144                 start = cp;
145                 if (*cp == '"') {
146                         cp++;
147                         token = MALLOC(2);
148
149                         if (!token)
150                                 goto out;
151
152                         *(token) = '"';
153                         *(token + 1) = '\0';
154                         if (in_string)
155                                 in_string = 0;
156                         else
157                                 in_string = 1;
158
159                 } else {
160                         while ((in_string || !isspace((int) *cp)) && *cp
161                                 != '\0' && *cp != '"')
162                                 cp++;
163                         strlen = cp - start;
164                         token = MALLOC(strlen + 1);
165
166                         if (!token)
167                                 goto out;
168
169                         memcpy(token, start, strlen);
170                         *(token + strlen) = '\0';
171                 }
172                 vector_set_slot(strvec, token);
173
174                 while (isspace((int) *cp) && *cp != '\0')
175                         cp++;
176                 if (*cp == '\0' || *cp == '!' || *cp == '#')
177                         return strvec;
178         }
179 out:
180         vector_free(strvec);
181         return NULL;
182 }
183
184 int
185 read_line(char *buf, int size)
186 {
187         int ch;
188         int count = 0;
189
190         while ((ch = fgetc(stream)) != EOF && (int) ch != '\n'
191                && (int) ch != '\r') {
192                 if (count < size)
193                         buf[count] = (int) ch;
194                 else
195                         break;
196                 count++;
197         }
198         return (ch == EOF) ? 0 : 1;
199 }
200
201 vector
202 read_value_block(void)
203 {
204         char *buf;
205         int i;
206         char *str = NULL;
207         char *dup;
208         vector vec = NULL;
209         vector elements = vector_alloc();
210
211         buf = (char *) MALLOC(MAXBUF);
212
213         if (!buf)
214                 return NULL;
215
216         if (!elements)
217                 goto out;
218
219         while (read_line(buf, MAXBUF)) {
220                 vec = alloc_strvec(buf);
221                 if (vec) {
222                         str = VECTOR_SLOT(vec, 0);
223                         if (!strcmp(str, EOB)) {
224                                 free_strvec(vec);
225                                 break;
226                         }
227
228                         if (VECTOR_SIZE(vec))
229                                 for (i = 0; i < VECTOR_SIZE(vec); i++) {
230                                         str = VECTOR_SLOT(vec, i);
231                                         dup = (char *) MALLOC(strlen(str) + 1);
232                                         memcpy(dup, str, strlen(str));
233
234                                         if (!vector_alloc_slot(elements))
235                                                 goto out1;
236
237                                         vector_set_slot(elements, dup);
238                                 }
239                         free_strvec(vec);
240                 }
241                 memset(buf, 0, MAXBUF);
242         }
243         FREE(buf);
244         return elements;
245 out1:
246         FREE(dup);
247 out:
248         FREE(buf);
249         return NULL;
250 }
251
252 int
253 alloc_value_block(vector strvec, void (*alloc_func) (vector))
254 {
255         char *buf;
256         char *str = NULL;
257         vector vec = NULL;
258
259         buf = (char *) MALLOC(MAXBUF);
260
261         if (!buf)
262                 return 1;
263
264         while (read_line(buf, MAXBUF)) {
265                 vec = alloc_strvec(buf);
266                 if (vec) {
267                         str = VECTOR_SLOT(vec, 0);
268                         if (!strcmp(str, EOB)) {
269                                 free_strvec(vec);
270                                 break;
271                         }
272
273                         if (VECTOR_SIZE(vec))
274                                 (*alloc_func) (vec);
275
276                         free_strvec(vec);
277                 }
278                 memset(buf, 0, MAXBUF);
279         }
280         FREE(buf);
281         return 0;
282 }
283
284 void *
285 set_value(vector strvec)
286 {
287         char *str = VECTOR_SLOT(strvec, 1);
288         int size = strlen(str);
289         int i = 0;
290         int len = 0;
291         char *alloc = NULL;
292         char *tmp;
293
294         if (*str == '"') {
295                 for (i = 2; i < VECTOR_SIZE(strvec); i++) {
296                         str = VECTOR_SLOT(strvec, i);
297                         len += strlen(str);
298                         if (!alloc)
299                                 alloc =
300                                     (char *) MALLOC(sizeof (char *) *
301                                                     (len + 1));
302                         else {
303                                 alloc =
304                                     REALLOC(alloc, sizeof (char *) * (len + 1));
305                                 tmp = VECTOR_SLOT(strvec, i-1);
306                                 if (*str != '"' && *tmp != '"')
307                                         strncat(alloc, " ", 1);
308                         }
309
310                         if (i != VECTOR_SIZE(strvec)-1)
311                                 strncat(alloc, str, strlen(str));
312                 }
313         } else {
314                 alloc = MALLOC(sizeof (char *) * (size + 1));
315                 memcpy(alloc, str, size);
316         }
317         return alloc;
318 }
319
320 /* non-recursive configuration stream handler */
321 static int kw_level = 0;
322 int
323 process_stream(vector keywords)
324 {
325         int i;
326         int r = 0;
327         struct keyword *keyword;
328         char *str;
329         char *buf;
330         vector strvec;
331
332         buf = MALLOC(MAXBUF);
333
334         if (!buf)
335                 return 1;
336
337         while (read_line(buf, MAXBUF)) {
338                 strvec = alloc_strvec(buf);
339                 memset(buf,0, MAXBUF);
340
341                 if (!strvec)
342                         continue;
343
344                 str = VECTOR_SLOT(strvec, 0);
345
346                 if (!strcmp(str, EOB) && kw_level > 0) {
347                         free_strvec(strvec);
348                         break;
349                 }
350
351                 for (i = 0; i < VECTOR_SIZE(keywords); i++) {
352                         keyword = VECTOR_SLOT(keywords, i);
353
354                         if (!strcmp(keyword->string, str)) {
355                                 if (keyword->handler)
356                                         r += (*keyword->handler) (strvec);
357
358                                 if (keyword->sub) {
359                                         kw_level++;
360                                         r += process_stream(keyword->sub);
361                                         kw_level--;
362                                 }
363                                 break;
364                         }
365                 }
366                 
367                 free_strvec(strvec);
368         }
369
370         FREE(buf);
371         return r;
372 }
373
374 /* Data initialization */
375 int
376 init_data(char *conf_file, vector (*init_keywords) (void))
377 {
378         int r;
379
380         stream = fopen(conf_file, "r");
381         if (!stream) {
382                 syslog(LOG_WARNING, "Configuration file open problem");
383                 return 1;
384         }
385
386         /* Init Keywords structure */
387         (*init_keywords) ();
388
389 /* Dump configuration *
390   vector_dump(keywords);
391   dump_keywords(keywords, 0);
392 */
393
394         /* Stream handling */
395         r = process_stream(keywords);
396         fclose(stream);
397         free_keywords(keywords);
398
399         return r;
400 }