Annotation of embedaddon/istgt/src/istgt_conf.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2010 Daisuke Aoyama <aoyama@peach.ne.jp>.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: */
27:
28: #ifdef HAVE_CONFIG_H
29: #include "config.h"
30: #endif
31:
32: #include <ctype.h>
33: #include <stdio.h>
34: #include <stdlib.h>
35: #include <string.h>
36:
37: #include "istgt.h"
38: #include "istgt_misc.h"
39: #include "istgt_conf.h"
40:
41: //#define CF_DELIM " \t,;"
42: #define CF_DELIM " \t"
43:
44: static void istgt_free_all_cf_section(CF_SECTION *sp);
45: static void istgt_free_all_cf_item(CF_ITEM *ip);
46: static void istgt_free_all_cf_value(CF_VALUE *vp);
47:
48: CONFIG *
49: istgt_allocate_config(void)
50: {
51: CONFIG *cp;
52:
53: cp = xmalloc(sizeof *cp);
54: memset(cp, 0, sizeof *cp);
55: cp->file = NULL;
56: cp->section = NULL;
57:
58: return cp;
59: }
60:
61: void
62: istgt_free_config(CONFIG *cp)
63: {
64: if (cp == NULL)
65: return;
66: if (cp->section != NULL) {
67: istgt_free_all_cf_section(cp->section);
68: }
69: xfree(cp->file);
70: xfree(cp);
71: }
72:
73: static CF_SECTION *
74: istgt_allocate_cf_section(void)
75: {
76: CF_SECTION *sp;
77:
78: sp = xmalloc(sizeof *sp);
79: memset(sp, 0, sizeof *sp);
80: sp->next = NULL;
81: sp->item = NULL;
82:
83: return sp;
84: }
85:
86: static void
87: istgt_free_cf_section(CF_SECTION *sp)
88: {
89: if (sp == NULL)
90: return;
91: if (sp->item) {
92: istgt_free_all_cf_item(sp->item);
93: }
94: xfree(sp->name);
95: xfree(sp);
96: }
97:
98: static void
99: istgt_free_all_cf_section(CF_SECTION *sp)
100: {
101: CF_SECTION *next;
102:
103: if (sp == NULL)
104: return;
105: while (sp != NULL) {
106: next = sp->next;
107: istgt_free_cf_section(sp);
108: sp = next;
109: }
110: }
111:
112: static CF_ITEM *
113: istgt_allocate_cf_item(void)
114: {
115: CF_ITEM *ip;
116:
117: ip = xmalloc(sizeof *ip);
118: memset(ip, 0, sizeof *ip);
119: ip->next = NULL;
120: ip->key = NULL;
121: ip->val = NULL;
122:
123: return ip;
124: }
125:
126: static void
127: istgt_free_cf_item(CF_ITEM *ip)
128: {
129: if (ip == NULL)
130: return;
131: if (ip->val != NULL) {
132: istgt_free_all_cf_value(ip->val);
133: }
134: xfree(ip->key);
135: xfree(ip);
136: }
137:
138: static void
139: istgt_free_all_cf_item(CF_ITEM *ip)
140: {
141: CF_ITEM *next;
142:
143: if (ip == NULL)
144: return;
145: while (ip != NULL) {
146: next = ip->next;
147: istgt_free_cf_item(ip);
148: ip = next;
149: }
150: }
151:
152: static CF_VALUE *
153: istgt_allocate_cf_value(void)
154: {
155: CF_VALUE *vp;
156:
157: vp = xmalloc(sizeof *vp);
158: memset(vp, 0, sizeof *vp);
159: vp->next = NULL;
160: vp->value = NULL;
161:
162: return vp;
163: }
164:
165: static void
166: istgt_free_cf_value(CF_VALUE *vp)
167: {
168: if (vp == NULL)
169: return;
170: xfree(vp->value);
171: xfree(vp);
172: }
173:
174: static void
175: istgt_free_all_cf_value(CF_VALUE *vp)
176: {
177: CF_VALUE *next;
178:
179: if (vp == NULL)
180: return;
181: while (vp != NULL) {
182: next = vp->next;
183: istgt_free_cf_value(vp);
184: vp = next;
185: }
186: }
187:
188: CF_SECTION *
189: istgt_find_cf_section(CONFIG *cp, const char *name)
190: {
191: CF_SECTION *sp;
192:
193: if (name == NULL || name[0] == '\0')
194: return NULL;
195:
196: for (sp = cp->section; sp != NULL; sp = sp->next) {
197: if (sp->name != NULL && sp->name[0] == name[0]
198: && strcasecmp(sp->name, name) == 0) {
199: return sp;
200: }
201: }
202:
203: return NULL;
204: }
205:
206: static void
207: istgt_append_cf_section(CONFIG *cp, CF_SECTION *sp)
208: {
209: CF_SECTION *last;
210:
211: if (cp == NULL)
212: return;
213: if (cp->section == NULL) {
214: cp->section = sp;
215: return;
216: }
217: for (last = cp->section; last->next != NULL; last = last->next)
218: ;
219: last->next = sp;
220: }
221:
222: CF_ITEM *
223: istgt_find_cf_nitem(CF_SECTION *sp, const char *key, int idx)
224: {
225: CF_ITEM *ip;
226: int i;
227:
228: if (key == NULL || key[0] == '\0')
229: return NULL;
230:
231: i = 0;
232: for (ip = sp->item; ip != NULL; ip = ip->next) {
233: if (ip->key != NULL && ip->key[0] == key[0]
234: && strcasecmp(ip->key, key) == 0) {
235: if (i == idx) {
236: return ip;
237: }
238: i++;
239: }
240: }
241:
242: return NULL;
243: }
244:
245: CF_ITEM *
246: istgt_find_cf_item(CF_SECTION *sp, const char *key)
247: {
248: return istgt_find_cf_nitem(sp, key, 0);
249: }
250:
251: static void
252: istgt_append_cf_item(CF_SECTION *sp, CF_ITEM *ip)
253: {
254: CF_ITEM *last;
255:
256: if (sp == NULL)
257: return;
258: if (sp->item == NULL) {
259: sp->item = ip;
260: return;
261: }
262: for (last = sp->item; last->next != NULL; last = last->next)
263: ;
264: last->next = ip;
265: }
266:
267: static void
268: istgt_append_cf_value(CF_ITEM *ip, CF_VALUE *vp)
269: {
270: CF_VALUE *last;
271:
272: if (ip == NULL)
273: return;
274: if (ip->val == NULL) {
275: ip->val = vp;
276: return;
277: }
278: for (last = ip->val; last->next != NULL; last = last->next)
279: ;
280: last->next = vp;
281: }
282:
283: static void
284: istgt_set_cf_section_type(CF_SECTION *sp)
285: {
286: static struct cfst_table_t {
287: const char *name;
288: CF_SECTION_TYPE type;
289: } cfst_table[] = {
290: { "Global", ST_GLOBAL },
291: { "UnitControl", ST_UNITCONTROL },
292: { "PortalGroup", ST_PORTALGROUP },
293: { "InitiatorGroup", ST_INITIATORGROUP },
294: { "LogicalUnit", ST_LOGICAL_UNIT },
295: { "AuthGroup", ST_AUTHGROUP },
296: { NULL, ST_INVALID },
297: };
298: int i;
299:
300: if (sp == NULL || sp->name == NULL)
301: return;
302: for (i = 0; cfst_table[i].name != NULL; i++) {
303: if (sp->name[0] == cfst_table[i].name[0]
304: && strncasecmp(sp->name, cfst_table[i].name,
305: strlen(cfst_table[i].name)) == 0) {
306: sp->type = cfst_table[i].type;
307: return;
308: }
309: }
310: sp->type = ST_NONE;
311: }
312:
313: static int
314: parse_line(CONFIG *cp, char *lp)
315: {
316: CF_SECTION *sp;
317: CF_ITEM *ip;
318: CF_VALUE *vp;
319: char *arg;
320: char *key;
321: char *val;
322: char *p;
323: int num;
324:
325: arg = trim_string(lp);
326: if (arg[0] == '[') {
327: /* section */
328: arg++;
329: key = strsepq(&arg, "]");
330: if (key == NULL || arg != NULL) {
331: fprintf(stderr, "broken section\n");
332: return -1;
333: }
334: /* determine section number */
335: for (p = key; *p != '\0' && !isdigit((int) *p); p++)
336: ;
337: if (*p != '\0') {
338: num = (int)strtol(p, NULL, 10);
339: } else {
340: num = 0;
341: }
342:
343: sp = istgt_find_cf_section(cp, key);
344: if (sp == NULL) {
345: sp = istgt_allocate_cf_section();
346: istgt_append_cf_section(cp, sp);
347: }
348: cp->current_section = sp;
349: sp->name = xstrdup(key);
350: sp->num = num;
351: istgt_set_cf_section_type(sp);
352: } else {
353: /* parameters */
354: sp = cp->current_section;
355: if (sp == NULL) {
356: fprintf(stderr, "unknown section\n");
357: return -1;
358: }
359: key = strsepq(&arg, CF_DELIM);
360: if (key == NULL) {
361: fprintf(stderr, "broken key\n");
362: return -1;
363: }
364:
365: ip = istgt_allocate_cf_item();
366: istgt_append_cf_item(sp, ip);
367: ip->key = xstrdup(key);
368: ip->val = NULL;
369: if (arg != NULL) {
370: /* key has value(s) */
371: while (arg != NULL) {
372: val = strsepq(&arg, CF_DELIM);
373: vp = istgt_allocate_cf_value();
374: istgt_append_cf_value(ip, vp);
375: vp->value = xstrdup(val);
376: }
377: }
378: }
379:
380: return 0;
381: }
382:
383: static char *
384: fgets_line (FILE *fp)
385: {
386: char *dst, *p;
387: size_t total, len;
388:
389: dst = p = xmalloc(MAX_TMPBUF);
390: dst[0] = '\0';
391: total = 0;
392:
393: while (fgets(p, MAX_TMPBUF, fp) != NULL) {
394: len = strlen(p);
395: total += len;
396: if (len + 1 < MAX_TMPBUF || dst[total - 1] == '\n') {
397: return xrealloc(dst, total + 1);
398: }
399: dst = xrealloc (dst, total + MAX_TMPBUF);
400: p = dst + total;
401: }
402:
403: if (feof(fp) && total != 0) {
404: dst = xrealloc(dst, total + 2);
405: dst[total] = '\n';
406: dst[total + 1] = '\0';
407: return dst;
408: }
409:
410: xfree(dst);
411:
412: return NULL;
413: }
414:
415: int
416: istgt_read_config(CONFIG *cp, const char *file)
417: {
418: FILE *fp;
419: char *lp, *p;
420: char *lp2, *q;
421: int line;
422: int n, n2;
423:
424: if (file == NULL || file[0] == '\0')
425: return -1;
426: fp = fopen(file, "r");
427: if (fp == NULL) {
428: fprintf(stderr, "open error: %s\n", file);
429: return -1;
430: }
431: cp->file = xstrdup(file);
432:
433: line = 1;
434: while ((lp = fgets_line(fp)) != NULL) {
435: /* skip spaces */
436: for (p = lp; *p != '\0' && isspace((int) *p); p++)
437: ;
438: /* skip comment, empty line */
439: if (p[0] == '#' || p[0] == '\0')
440: goto next_line;
441:
442: /* concatenate line end with '\' */
443: n = strlen(p);
444: while (n > 2 && p[n - 1] == '\n' && p[n - 2] == '\\') {
445: n -= 2;
446: lp2 = fgets_line(fp);
447: if (lp2 == NULL)
448: break;
449: line++;
450: n2 = strlen(lp2);
451: q = xmalloc(n + n2 + 1);
452: memcpy(q, p, n);
453: memcpy(q + n, lp2, n2);
454: q[n + n2] = '\0';
455: xfree(lp2);
456: xfree(lp);
457: p = lp = q;
458: n += n2;
459: }
460:
461: /* parse one line */
462: if (parse_line(cp, p) < 0) {
463: fprintf(stderr, "parse error at line %d of %s\n", line, cp->file);
464: }
465: next_line:
466: line++;
467: xfree(lp);
468: }
469:
470: fclose(fp);
471: return 0;
472: }
473:
474: int
475: istgt_print_config(CONFIG *cp)
476: {
477: CF_SECTION *sp;
478: CF_ITEM *ip;
479: CF_VALUE *vp;
480:
481: if (cp == NULL)
482: return -1;
483:
484: /* empty config? */
485: sp = cp->section;
486: if (sp == NULL)
487: return 0;
488:
489: while (sp != NULL) {
490: printf("Section: %s\n", sp->name);
491: ip = sp->item;
492: while (ip != NULL) {
493: printf(" Item: %s ", ip->key);
494: vp = ip->val;
495: while (vp != NULL) {
496: printf("Val: %s ", vp->value);
497: vp = vp->next;
498: }
499: printf("\n");
500: ip = ip->next;
501: }
502: sp = sp->next;
503: }
504:
505: return 0;
506: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>