nandsim_rcfile.c revision 259065
1190372Sedwin/* 2153761Swollman * Copyright (c) 1999, Boris Popov 364499Swollman * All rights reserved. 42742Swollman * 52742Swollman * Redistribution and use in source and binary forms, with or without 62742Swollman * modification, are permitted provided that the following conditions 72742Swollman * are met: 8158421Swollman * 1. Redistributions of source code must retain the above copyright 92742Swollman * notice, this list of conditions and the following disclaimer. 10158421Swollman * 2. Redistributions in binary form must reproduce the above copyright 11158421Swollman * notice, this list of conditions and the following disclaimer in the 122742Swollman * documentation and/or other materials provided with the distribution. 1386222Swollman * 3. Neither the name of the author nor the names of any co-contributors 1420094Swollman * may be used to endorse or promote products derived from this software 1520094Swollman * without specific prior written permission. 1620094Swollman * 1720094Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1820094Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19158421Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20158421Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2120094Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2219878Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2319878Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2419878Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2519878Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2619878Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2719878Swollman * SUCH DAMAGE. 2819878Swollman * 2919878Swollman * from: FreeBSD: src/lib/libncp/ncpl_rcfile.c,v 1.5 2007/01/09 23:27:39 imp Exp 3058787Sru */ 3158787Sru 3258787Sru#include <sys/cdefs.h> 3358787Sru__FBSDID("$FreeBSD: releng/10.0/usr.sbin/nandsim/nandsim_rcfile.c 235537 2012-05-17 10:11:18Z gber $"); 3458787Sru#include <sys/types.h> 3558787Sru#include <sys/queue.h> 3658787Sru#include <ctype.h> 3758787Sru#include <errno.h> 3858787Sru#include <stdio.h> 3958787Sru#include <string.h> 4058787Sru#include <stdlib.h> 4158787Sru#include <pwd.h> 4258787Sru#include <unistd.h> 4358787Sru 4458787Sru#include "nandsim_rcfile.h" 4558787Sru 4658787SruSLIST_HEAD(rcfile_head, rcfile); 4758787Srustatic struct rcfile_head pf_head = {NULL}; 482742Swollmanstatic struct rcsection *rc_findsect(struct rcfile *rcp, 492742Swollman const char *sectname, int sect_id); 502742Swollmanstatic struct rcsection *rc_addsect(struct rcfile *rcp, 512742Swollman const char *sectname); 522742Swollmanstatic int rc_sect_free(struct rcsection *rsp); 532742Swollmanstatic struct rckey *rc_sect_findkey(struct rcsection *rsp, 542742Swollman const char *keyname); 5519878Swollmanstatic struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name, 562742Swollman char *value); 572742Swollmanstatic void rc_key_free(struct rckey *p); 582742Swollmanstatic void rc_parse(struct rcfile *rcp); 5919878Swollman 602742Swollmanstatic struct rcfile* rc_find(const char *filename); 612742Swollman 62149514Swollman/* 6321217Swollman * open rcfile and load its content, if already open - return previous handle 649908Swollman */ 659908Swollmanint 662742Swollmanrc_open(const char *filename, const char *mode,struct rcfile **rcfile) 6719878Swollman{ 6819878Swollman struct rcfile *rcp; 6919878Swollman FILE *f; 7019878Swollman rcp = rc_find(filename); 7119878Swollman if (rcp) { 7219878Swollman *rcfile = rcp; 7319878Swollman return (0); 7419878Swollman } 7519878Swollman f = fopen (filename, mode); 7619878Swollman if (f == NULL) 7719878Swollman return errno; 7819878Swollman rcp = malloc(sizeof(struct rcfile)); 7919878Swollman if (rcp == NULL) { 8019878Swollman fclose(f); 8119878Swollman return ENOMEM; 8219878Swollman } 8393799Swollman bzero(rcp, sizeof(struct rcfile)); 8458787Sru rcp->rf_name = strdup(filename); 8558787Sru rcp->rf_f = f; 8619878Swollman SLIST_INSERT_HEAD(&pf_head, rcp, rf_next); 8719878Swollman rc_parse(rcp); 8819878Swollman *rcfile = rcp; 899908Swollman return (0); 90149514Swollman} 919908Swollman 929908Swollmanint 939908Swollmanrc_close(struct rcfile *rcp) 9421217Swollman{ 9519878Swollman struct rcsection *p,*n; 9619878Swollman 979908Swollman fclose(rcp->rf_f); 98149514Swollman for (p = SLIST_FIRST(&rcp->rf_sect); p; ) { 999908Swollman n = p; 1009908Swollman p = SLIST_NEXT(p,rs_next); 1019908Swollman rc_sect_free(n); 1029908Swollman } 10358787Sru free(rcp->rf_name); 10458787Sru SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next); 10558787Sru free(rcp); 10664499Swollman return (0); 10764499Swollman} 108175034Sedwin 109175034Sedwinstatic struct rcfile* 110175034Sedwinrc_find(const char *filename) 111175034Sedwin{ 112175034Sedwin struct rcfile *p; 11358787Sru 11458787Sru SLIST_FOREACH(p, &pf_head, rf_next) 11567578Swollman if (strcmp (filename, p->rf_name) == 0) 11658787Sru return (p); 11758787Sru return (0); 11858787Sru} 119149514Swollman 12064499Swollman/* Find section with given name and id */ 12164499Swollmanstatic struct rcsection * 12264499Swollmanrc_findsect(struct rcfile *rcp, const char *sectname, int sect_id) 12364499Swollman{ 12486222Swollman struct rcsection *p; 12586222Swollman 12686222Swollman SLIST_FOREACH(p, &rcp->rf_sect, rs_next) 12786222Swollman if (strcmp(p->rs_name, sectname) == 0 && p->rs_id == sect_id) 12886222Swollman return (p); 12986222Swollman return (NULL); 13086222Swollman} 13186222Swollman 13286222Swollmanstatic struct rcsection * 13386222Swollmanrc_addsect(struct rcfile *rcp, const char *sectname) 13486222Swollman{ 13586222Swollman struct rcsection *p; 13686222Swollman int id = 0; 13786222Swollman p = rc_findsect(rcp, sectname, 0); 13886222Swollman if (p) { 13986222Swollman /* 14086222Swollman * If section with that name already exists -- add one more, 14186222Swollman * same named, but with different id (higher by one) 14286222Swollman */ 14386222Swollman while (p != NULL) { 14486222Swollman id = p->rs_id + 1; 14586222Swollman p = rc_findsect(rcp, sectname, id); 14686222Swollman } 147175034Sedwin } 148175034Sedwin p = malloc(sizeof(*p)); 149175034Sedwin if (!p) 150175034Sedwin return (NULL); 151175034Sedwin p->rs_name = strdup(sectname); 152175034Sedwin p->rs_id = id; 153175034Sedwin SLIST_INIT(&p->rs_keys); 154175034Sedwin SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next); 155175034Sedwin return (p); 156175034Sedwin} 157175034Sedwin 158175034Sedwinstatic int 159175034Sedwinrc_sect_free(struct rcsection *rsp) 160175034Sedwin{ 161175034Sedwin struct rckey *p,*n; 162175034Sedwin 163175034Sedwin for (p = SLIST_FIRST(&rsp->rs_keys); p; ) { 164175034Sedwin n = p; 165175034Sedwin p = SLIST_NEXT(p,rk_next); 166175034Sedwin rc_key_free(n); 167183066Sedwin } 168183066Sedwin free(rsp->rs_name); 169183066Sedwin free(rsp); 170183066Sedwin return (0); 171183066Sedwin} 172183066Sedwin 173183066Sedwinstatic struct rckey * 174183066Sedwinrc_sect_findkey(struct rcsection *rsp, const char *keyname) 175183066Sedwin{ 176183066Sedwin struct rckey *p; 177183066Sedwin 178183066Sedwin SLIST_FOREACH(p, &rsp->rs_keys, rk_next) 179183066Sedwin if (strcmp(p->rk_name, keyname)==0) 180183864Sedwin return (p); 181183864Sedwin return (NULL); 182183864Sedwin} 183183864Sedwin 184183864Sedwinstatic struct rckey * 185183864Sedwinrc_sect_addkey(struct rcsection *rsp, const char *name, char *value) 186183864Sedwin{ 187183864Sedwin struct rckey *p; 188183864Sedwin p = rc_sect_findkey(rsp, name); 189183864Sedwin if (p) { 190183864Sedwin free(p->rk_value); 191183864Sedwin } else { 192183864Sedwin p = malloc(sizeof(*p)); 193183864Sedwin if (!p) 194183864Sedwin return (NULL); 195183864Sedwin SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next); 196184406Sedwin p->rk_name = strdup(name); 197184406Sedwin } 198184406Sedwin p->rk_value = value ? strdup(value) : strdup(""); 199184406Sedwin return (p); 200184406Sedwin} 201184406Sedwin 202184406Sedwinstatic void 203184406Sedwinrc_key_free(struct rckey *p) 204184406Sedwin{ 205184406Sedwin free(p->rk_value); 206184406Sedwin free(p->rk_name); 207184406Sedwin free(p); 208184406Sedwin} 209184406Sedwin 210184406Sedwinenum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue}; 211184406Sedwin 212184406Sedwinstatic void 213184406Sedwinrc_parse(struct rcfile *rcp) 214184406Sedwin{ 215184406Sedwin FILE *f = rcp->rf_f; 216175034Sedwin int state = stNewLine, c; 217175034Sedwin struct rcsection *rsp = NULL; 218183066Sedwin struct rckey *rkp = NULL; 219175034Sedwin char buf[2048]; 220136638Swollman char *next = buf, *last = &buf[sizeof(buf)-1]; 221136638Swollman 222136638Swollman while ((c = getc (f)) != EOF) { 223136638Swollman if (c == '\r') 224136638Swollman continue; 225136638Swollman if (state == stNewLine) { 226136638Swollman next = buf; 22793799Swollman if (isspace(c)) 228158421Swollman continue; /* skip leading junk */ 22993799Swollman if (c == '[') { 230158421Swollman state = stHeader; 23193799Swollman rsp = NULL; 23293799Swollman continue; 233158421Swollman } 234136638Swollman if (c == '#' || c == ';') { 235136638Swollman state = stSkipToEOL; 236136638Swollman } else { /* something meaningful */ 237136638Swollman state = stGetKey; 238136638Swollman } 239136638Swollman } 240136638Swollman if (state == stSkipToEOL || next == last) {/* ignore long lines */ 241136638Swollman if (c == '\n') { 242136638Swollman state = stNewLine; 243136638Swollman next = buf; 244136638Swollman } 245136638Swollman continue; 246136638Swollman } 247136638Swollman if (state == stHeader) { 248136638Swollman if (c == ']') { 249136638Swollman *next = 0; 250136638Swollman next = buf; 251136638Swollman rsp = rc_addsect(rcp, buf); 252136638Swollman state = stSkipToEOL; 253136638Swollman } else 254136638Swollman *next++ = c; 255136638Swollman continue; 256136638Swollman } 257136638Swollman if (state == stGetKey) { 258136638Swollman if (c == ' ' || c == '\t')/* side effect: 'key name='*/ 259136638Swollman continue; /* become 'keyname=' */ 260136638Swollman if (c == '\n') { /* silently ignore ... */ 261136638Swollman state = stNewLine; 262136638Swollman continue; 263136638Swollman } 264136638Swollman if (c != '=') { 265136638Swollman *next++ = c; 266136638Swollman continue; 267136638Swollman } 268136638Swollman *next = 0; 269136638Swollman if (rsp == NULL) { 270136638Swollman fprintf(stderr, "Key '%s' defined before " 271136638Swollman "section\n", buf); 272136638Swollman state = stSkipToEOL; 273136638Swollman continue; 274136638Swollman } 275136638Swollman rkp = rc_sect_addkey(rsp, buf, NULL); 276136638Swollman next = buf; 277136638Swollman state = stGetValue; 278136638Swollman continue; 27993799Swollman } 280177591Sedwin /* only stGetValue left */ 281177591Sedwin if (state != stGetValue) { 282177591Sedwin fprintf(stderr, "Well, I can't parse file " 283177591Sedwin "'%s'\n",rcp->rf_name); 284177591Sedwin state = stSkipToEOL; 285177591Sedwin } 286177591Sedwin if (c != '\n') { 287177591Sedwin *next++ = c; 288177591Sedwin continue; 289177591Sedwin } 290177591Sedwin *next = 0; 291177591Sedwin rkp->rk_value = strdup(buf); 292177591Sedwin state = stNewLine; 293177591Sedwin rkp = NULL; 294177591Sedwin } /* while */ 295177591Sedwin if (c == EOF && state == stGetValue) { 296177591Sedwin *next = 0; 297177591Sedwin rkp->rk_value = strdup(buf); 298177591Sedwin } 299177591Sedwin} 300177591Sedwin 301177591Sedwinint 302177591Sedwinrc_getstringptr(struct rcfile *rcp, const char *section, int sect_id, 303177591Sedwin const char *key, char **dest) 304177591Sedwin{ 305177591Sedwin struct rcsection *rsp; 306177591Sedwin struct rckey *rkp; 307177591Sedwin 308177591Sedwin *dest = NULL; 309177591Sedwin rsp = rc_findsect(rcp, section, sect_id); 310177591Sedwin if (!rsp) 311177591Sedwin return (ENOENT); 312177591Sedwin rkp = rc_sect_findkey(rsp,key); 313177591Sedwin if (!rkp) 314177591Sedwin return (ENOENT); 315177591Sedwin *dest = rkp->rk_value; 316177591Sedwin return (0); 317177591Sedwin} 318177591Sedwin 319177591Sedwinint 320177591Sedwinrc_getstring(struct rcfile *rcp, const char *section, int sect_id, 321177591Sedwin const char *key, unsigned int maxlen, char *dest) 322177591Sedwin{ 323177591Sedwin char *value; 324177591Sedwin int error; 325177591Sedwin 326177591Sedwin error = rc_getstringptr(rcp, section, sect_id, key, &value); 327177591Sedwin if (error) 328177591Sedwin return (error); 329177591Sedwin if (strlen(value) >= maxlen) { 330177591Sedwin fprintf(stderr, "line too long for key '%s' in section '%s'," 331177591Sedwin "max = %d\n",key, section, maxlen); 332177591Sedwin return (EINVAL); 333177591Sedwin } 334177591Sedwin strcpy(dest,value); 335177591Sedwin return (0); 336177591Sedwin} 337177591Sedwin 338177591Sedwinint 339177591Sedwinrc_getint(struct rcfile *rcp, const char *section, int sect_id, 340177591Sedwin const char *key, int *value) 341177591Sedwin{ 342177591Sedwin struct rcsection *rsp; 343177591Sedwin struct rckey *rkp; 344177591Sedwin 345177591Sedwin rsp = rc_findsect(rcp, section, sect_id); 346181421Sedwin if (!rsp) 347158421Swollman return (ENOENT); 348158421Swollman rkp = rc_sect_findkey(rsp,key); 349181421Sedwin if (!rkp) 350181421Sedwin return (ENOENT); 351181421Sedwin errno = 0; 352181421Sedwin *value = strtol(rkp->rk_value,NULL,0); 353181421Sedwin if (errno) { 354190372Sedwin fprintf(stderr, "invalid int value '%s' for key '%s' in " 355190372Sedwin "section '%s'\n",rkp->rk_value,key,section); 356190372Sedwin return (errno); 357190372Sedwin } 35893799Swollman return (0); 359190372Sedwin} 360190372Sedwin 361190372Sedwin/* 362190372Sedwin * 1,yes,true 363190372Sedwin * 0,no,false 364190372Sedwin */ 365190372Sedwinint 366190372Sedwinrc_getbool(struct rcfile *rcp, const char *section, int sect_id, 367190372Sedwin const char *key, int *value) 368190372Sedwin{ 369190372Sedwin struct rcsection *rsp; 370190372Sedwin struct rckey *rkp; 371190372Sedwin char *p; 372190372Sedwin 373190372Sedwin rsp = rc_findsect(rcp, section, sect_id); 374190372Sedwin if (!rsp) 375190372Sedwin return (ENOENT); 376190372Sedwin rkp = rc_sect_findkey(rsp,key); 377190372Sedwin if (!rkp) 378190372Sedwin return (ENOENT); 379190372Sedwin p = rkp->rk_value; 380190372Sedwin while (*p && isspace(*p)) p++; 381190372Sedwin if (*p == '0' || strcasecmp(p,"no") == 0 || 382190372Sedwin strcasecmp(p, "false") == 0 || 383190372Sedwin strcasecmp(p, "off") == 0) { 384190372Sedwin *value = 0; 385190372Sedwin return (0); 386190372Sedwin } 387190372Sedwin if (*p == '1' || strcasecmp(p,"yes") == 0 || 388190372Sedwin strcasecmp(p, "true") == 0 || 389190372Sedwin strcasecmp(p, "on") == 0) { 390190372Sedwin *value = 1; 391190372Sedwin return (0); 392190372Sedwin } 393190372Sedwin fprintf(stderr, "invalid boolean value '%s' for key '%s' in section " 394190372Sedwin "'%s' \n",p, key, section); 395190372Sedwin return (EINVAL); 396190372Sedwin} 397190372Sedwin 398190372Sedwin/* Count how many sections with given name exists in configuration. */ 3992742Swollmanint rc_getsectionscount(struct rcfile *f, const char *sectname) 40020094Swollman{ 401136638Swollman struct rcsection *p; 402136638Swollman int count = 0; 40393799Swollman 40419878Swollman p = rc_findsect(f, sectname, 0); 40558787Sru if (p) { 40693799Swollman while (p != NULL) { 40793799Swollman count = p->rs_id + 1; 408175034Sedwin p = rc_findsect(f, sectname, count); 40920094Swollman } 410184406Sedwin return (count); 411184406Sedwin } else 41220094Swollman return (0); 413158421Swollman} 41493799Swollman 41593799Swollmanchar ** 41693799Swollmanrc_getkeys(struct rcfile *rcp, const char *sectname, int sect_id) 41793799Swollman{ 41893799Swollman struct rcsection *rsp; 41993799Swollman struct rckey *p; 420136638Swollman char **names_tbl; 42193799Swollman int i = 0, count = 0; 42220094Swollman 42358787Sru rsp = rc_findsect(rcp, sectname, sect_id); 42493799Swollman if (rsp == NULL) 42593799Swollman return (NULL); 42693799Swollman 42793799Swollman SLIST_FOREACH(p, &rsp->rs_keys, rk_next) 428175034Sedwin count++; 42920094Swollman 430184406Sedwin names_tbl = malloc(sizeof(char *) * (count + 1)); 431184406Sedwin if (names_tbl == NULL) 432184406Sedwin return (NULL); 433184406Sedwin 434184406Sedwin SLIST_FOREACH(p, &rsp->rs_keys, rk_next) 435184406Sedwin names_tbl[i++] = p->rk_name; 436184406Sedwin 437184406Sedwin names_tbl[i] = NULL; 438184406Sedwin return (names_tbl); 439184406Sedwin} 440184406Sedwin 441184406Sedwin