Annotation of embedaddon/istgt/src/istgt_conf.c, revision 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>