Annotation of embedaddon/istgt/src/istgt_conf.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
1.1 misho 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);
1.1.1.2 ! misho 47: static void istgt_append_cf_item(CF_SECTION *sp, CF_ITEM *ip);
! 48: static void istgt_append_cf_value(CF_ITEM *ip, CF_VALUE *vp);
1.1 misho 49:
50: CONFIG *
51: istgt_allocate_config(void)
52: {
53: CONFIG *cp;
54:
55: cp = xmalloc(sizeof *cp);
56: memset(cp, 0, sizeof *cp);
57: cp->file = NULL;
58: cp->section = NULL;
59:
60: return cp;
61: }
62:
63: void
64: istgt_free_config(CONFIG *cp)
65: {
66: if (cp == NULL)
67: return;
68: if (cp->section != NULL) {
69: istgt_free_all_cf_section(cp->section);
70: }
71: xfree(cp->file);
72: xfree(cp);
73: }
74:
75: static CF_SECTION *
76: istgt_allocate_cf_section(void)
77: {
78: CF_SECTION *sp;
79:
80: sp = xmalloc(sizeof *sp);
81: memset(sp, 0, sizeof *sp);
82: sp->next = NULL;
83: sp->item = NULL;
84:
85: return sp;
86: }
87:
88: static void
89: istgt_free_cf_section(CF_SECTION *sp)
90: {
91: if (sp == NULL)
92: return;
93: if (sp->item) {
94: istgt_free_all_cf_item(sp->item);
95: }
96: xfree(sp->name);
97: xfree(sp);
98: }
99:
100: static void
101: istgt_free_all_cf_section(CF_SECTION *sp)
102: {
103: CF_SECTION *next;
104:
105: if (sp == NULL)
106: return;
107: while (sp != NULL) {
108: next = sp->next;
109: istgt_free_cf_section(sp);
110: sp = next;
111: }
112: }
113:
114: static CF_ITEM *
115: istgt_allocate_cf_item(void)
116: {
117: CF_ITEM *ip;
118:
119: ip = xmalloc(sizeof *ip);
120: memset(ip, 0, sizeof *ip);
121: ip->next = NULL;
122: ip->key = NULL;
123: ip->val = NULL;
124:
125: return ip;
126: }
127:
128: static void
129: istgt_free_cf_item(CF_ITEM *ip)
130: {
131: if (ip == NULL)
132: return;
133: if (ip->val != NULL) {
134: istgt_free_all_cf_value(ip->val);
135: }
136: xfree(ip->key);
137: xfree(ip);
138: }
139:
140: static void
141: istgt_free_all_cf_item(CF_ITEM *ip)
142: {
143: CF_ITEM *next;
144:
145: if (ip == NULL)
146: return;
147: while (ip != NULL) {
148: next = ip->next;
149: istgt_free_cf_item(ip);
150: ip = next;
151: }
152: }
153:
154: static CF_VALUE *
155: istgt_allocate_cf_value(void)
156: {
157: CF_VALUE *vp;
158:
159: vp = xmalloc(sizeof *vp);
160: memset(vp, 0, sizeof *vp);
161: vp->next = NULL;
162: vp->value = NULL;
163:
164: return vp;
165: }
166:
167: static void
168: istgt_free_cf_value(CF_VALUE *vp)
169: {
170: if (vp == NULL)
171: return;
172: xfree(vp->value);
173: xfree(vp);
174: }
175:
176: static void
177: istgt_free_all_cf_value(CF_VALUE *vp)
178: {
179: CF_VALUE *next;
180:
181: if (vp == NULL)
182: return;
183: while (vp != NULL) {
184: next = vp->next;
185: istgt_free_cf_value(vp);
186: vp = next;
187: }
188: }
189:
1.1.1.2 ! misho 190: void
! 191: istgt_copy_cf_item(CF_SECTION *sp_dst, CF_SECTION *sp_src)
! 192: {
! 193: CF_ITEM *ip, *ip_old;
! 194: CF_VALUE *vp, *vp_old;
! 195:
! 196: istgt_free_all_cf_item(sp_dst->item);
! 197: sp_dst->item = NULL;
! 198:
! 199: ip_old = sp_src->item;
! 200: while (ip_old != NULL) {
! 201: ip = istgt_allocate_cf_item();
! 202: istgt_append_cf_item(sp_dst, ip);
! 203: ip->key = xstrdup(ip_old->key);
! 204: ip->val = NULL;
! 205:
! 206: vp_old = ip_old->val;
! 207: while (vp_old != NULL) {
! 208: vp = istgt_allocate_cf_value();
! 209: istgt_append_cf_value(ip, vp);
! 210: vp->value = xstrdup(vp_old->value);
! 211:
! 212: vp_old = vp_old->next;
! 213: }
! 214: ip_old = ip_old->next;
! 215: }
! 216: }
! 217:
1.1 misho 218: CF_SECTION *
219: istgt_find_cf_section(CONFIG *cp, const char *name)
220: {
221: CF_SECTION *sp;
222:
223: if (name == NULL || name[0] == '\0')
224: return NULL;
225:
226: for (sp = cp->section; sp != NULL; sp = sp->next) {
227: if (sp->name != NULL && sp->name[0] == name[0]
228: && strcasecmp(sp->name, name) == 0) {
229: return sp;
230: }
231: }
232:
233: return NULL;
234: }
235:
236: static void
237: istgt_append_cf_section(CONFIG *cp, CF_SECTION *sp)
238: {
239: CF_SECTION *last;
240:
241: if (cp == NULL)
242: return;
243: if (cp->section == NULL) {
244: cp->section = sp;
245: return;
246: }
247: for (last = cp->section; last->next != NULL; last = last->next)
248: ;
249: last->next = sp;
250: }
251:
252: CF_ITEM *
253: istgt_find_cf_nitem(CF_SECTION *sp, const char *key, int idx)
254: {
255: CF_ITEM *ip;
256: int i;
257:
258: if (key == NULL || key[0] == '\0')
259: return NULL;
260:
261: i = 0;
262: for (ip = sp->item; ip != NULL; ip = ip->next) {
263: if (ip->key != NULL && ip->key[0] == key[0]
264: && strcasecmp(ip->key, key) == 0) {
265: if (i == idx) {
266: return ip;
267: }
268: i++;
269: }
270: }
271:
272: return NULL;
273: }
274:
275: CF_ITEM *
276: istgt_find_cf_item(CF_SECTION *sp, const char *key)
277: {
278: return istgt_find_cf_nitem(sp, key, 0);
279: }
280:
281: static void
282: istgt_append_cf_item(CF_SECTION *sp, CF_ITEM *ip)
283: {
284: CF_ITEM *last;
285:
286: if (sp == NULL)
287: return;
288: if (sp->item == NULL) {
289: sp->item = ip;
290: return;
291: }
292: for (last = sp->item; last->next != NULL; last = last->next)
293: ;
294: last->next = ip;
295: }
296:
297: static void
298: istgt_append_cf_value(CF_ITEM *ip, CF_VALUE *vp)
299: {
300: CF_VALUE *last;
301:
302: if (ip == NULL)
303: return;
304: if (ip->val == NULL) {
305: ip->val = vp;
306: return;
307: }
308: for (last = ip->val; last->next != NULL; last = last->next)
309: ;
310: last->next = vp;
311: }
312:
313: static void
314: istgt_set_cf_section_type(CF_SECTION *sp)
315: {
316: static struct cfst_table_t {
317: const char *name;
318: CF_SECTION_TYPE type;
319: } cfst_table[] = {
320: { "Global", ST_GLOBAL },
321: { "UnitControl", ST_UNITCONTROL },
322: { "PortalGroup", ST_PORTALGROUP },
323: { "InitiatorGroup", ST_INITIATORGROUP },
324: { "LogicalUnit", ST_LOGICAL_UNIT },
325: { "AuthGroup", ST_AUTHGROUP },
326: { NULL, ST_INVALID },
327: };
328: int i;
329:
330: if (sp == NULL || sp->name == NULL)
331: return;
332: for (i = 0; cfst_table[i].name != NULL; i++) {
333: if (sp->name[0] == cfst_table[i].name[0]
334: && strncasecmp(sp->name, cfst_table[i].name,
335: strlen(cfst_table[i].name)) == 0) {
336: sp->type = cfst_table[i].type;
337: return;
338: }
339: }
340: sp->type = ST_NONE;
341: }
342:
343: static int
344: parse_line(CONFIG *cp, char *lp)
345: {
346: CF_SECTION *sp;
347: CF_ITEM *ip;
348: CF_VALUE *vp;
349: char *arg;
350: char *key;
351: char *val;
352: char *p;
353: int num;
354:
355: arg = trim_string(lp);
356: if (arg[0] == '[') {
357: /* section */
358: arg++;
359: key = strsepq(&arg, "]");
360: if (key == NULL || arg != NULL) {
361: fprintf(stderr, "broken section\n");
362: return -1;
363: }
364: /* determine section number */
365: for (p = key; *p != '\0' && !isdigit((int) *p); p++)
366: ;
367: if (*p != '\0') {
368: num = (int)strtol(p, NULL, 10);
369: } else {
370: num = 0;
371: }
372:
373: sp = istgt_find_cf_section(cp, key);
374: if (sp == NULL) {
375: sp = istgt_allocate_cf_section();
376: istgt_append_cf_section(cp, sp);
377: }
378: cp->current_section = sp;
379: sp->name = xstrdup(key);
380: sp->num = num;
381: istgt_set_cf_section_type(sp);
382: } else {
383: /* parameters */
384: sp = cp->current_section;
385: if (sp == NULL) {
386: fprintf(stderr, "unknown section\n");
387: return -1;
388: }
389: key = strsepq(&arg, CF_DELIM);
390: if (key == NULL) {
391: fprintf(stderr, "broken key\n");
392: return -1;
393: }
394:
395: ip = istgt_allocate_cf_item();
396: istgt_append_cf_item(sp, ip);
397: ip->key = xstrdup(key);
398: ip->val = NULL;
399: if (arg != NULL) {
400: /* key has value(s) */
401: while (arg != NULL) {
402: val = strsepq(&arg, CF_DELIM);
403: vp = istgt_allocate_cf_value();
404: istgt_append_cf_value(ip, vp);
405: vp->value = xstrdup(val);
406: }
407: }
408: }
409:
410: return 0;
411: }
412:
413: static char *
414: fgets_line (FILE *fp)
415: {
416: char *dst, *p;
417: size_t total, len;
418:
419: dst = p = xmalloc(MAX_TMPBUF);
420: dst[0] = '\0';
421: total = 0;
422:
423: while (fgets(p, MAX_TMPBUF, fp) != NULL) {
424: len = strlen(p);
425: total += len;
426: if (len + 1 < MAX_TMPBUF || dst[total - 1] == '\n') {
427: return xrealloc(dst, total + 1);
428: }
429: dst = xrealloc (dst, total + MAX_TMPBUF);
430: p = dst + total;
431: }
432:
433: if (feof(fp) && total != 0) {
434: dst = xrealloc(dst, total + 2);
435: dst[total] = '\n';
436: dst[total + 1] = '\0';
437: return dst;
438: }
439:
440: xfree(dst);
441:
442: return NULL;
443: }
444:
445: int
446: istgt_read_config(CONFIG *cp, const char *file)
447: {
448: FILE *fp;
449: char *lp, *p;
450: char *lp2, *q;
451: int line;
452: int n, n2;
453:
454: if (file == NULL || file[0] == '\0')
455: return -1;
456: fp = fopen(file, "r");
457: if (fp == NULL) {
458: fprintf(stderr, "open error: %s\n", file);
459: return -1;
460: }
461: cp->file = xstrdup(file);
462:
463: line = 1;
464: while ((lp = fgets_line(fp)) != NULL) {
465: /* skip spaces */
466: for (p = lp; *p != '\0' && isspace((int) *p); p++)
467: ;
468: /* skip comment, empty line */
469: if (p[0] == '#' || p[0] == '\0')
470: goto next_line;
471:
472: /* concatenate line end with '\' */
473: n = strlen(p);
474: while (n > 2 && p[n - 1] == '\n' && p[n - 2] == '\\') {
475: n -= 2;
476: lp2 = fgets_line(fp);
477: if (lp2 == NULL)
478: break;
479: line++;
480: n2 = strlen(lp2);
481: q = xmalloc(n + n2 + 1);
482: memcpy(q, p, n);
483: memcpy(q + n, lp2, n2);
484: q[n + n2] = '\0';
485: xfree(lp2);
486: xfree(lp);
487: p = lp = q;
488: n += n2;
489: }
490:
491: /* parse one line */
492: if (parse_line(cp, p) < 0) {
493: fprintf(stderr, "parse error at line %d of %s\n", line, cp->file);
494: }
495: next_line:
496: line++;
497: xfree(lp);
498: }
499:
500: fclose(fp);
501: return 0;
502: }
503:
504: int
505: istgt_print_config(CONFIG *cp)
506: {
507: CF_SECTION *sp;
508: CF_ITEM *ip;
509: CF_VALUE *vp;
510:
511: if (cp == NULL)
512: return -1;
513:
514: /* empty config? */
515: sp = cp->section;
516: if (sp == NULL)
517: return 0;
518:
519: while (sp != NULL) {
520: printf("Section: %s\n", sp->name);
521: ip = sp->item;
522: while (ip != NULL) {
523: printf(" Item: %s ", ip->key);
524: vp = ip->val;
525: while (vp != NULL) {
526: printf("Val: %s ", vp->value);
527: vp = vp->next;
528: }
529: printf("\n");
530: ip = ip->next;
531: }
532: sp = sp->next;
533: }
534:
535: return 0;
536: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>