File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / istgt / src / istgt_conf.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:13:23 2012 UTC (12 years, 6 months ago) by misho
Branches: istgt, MAIN
CVS tags: v20121028, v20120901, HEAD
dhcp 4.1 r7

    1: /*
    2:  * Copyright (C) 2008-2012 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: 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);
   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: 
  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: 
  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>