|
|
1.1 ! root 1: /* ini_file.c */ ! 2: ! 3: /* Functions to parse ini files */ ! 4: ! 5: /* $Id: ini_file.c,v 1.63 2004/12/23 22:26:44 rswindell Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This library is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU Lesser General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU Lesser General Public License for more details: lgpl.txt or * ! 18: * http://www.fsf.org/copyleft/lesser.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include <stdlib.h> /* strtol */ ! 39: #include <string.h> /* strlen */ ! 40: #include <ctype.h> /* isdigit */ ! 41: #if !defined(NO_SOCKET_SUPPORT) ! 42: #include "sockwrap.h" /* inet_addr */ ! 43: #endif ! 44: #include "dirwrap.h" /* fexist */ ! 45: #include "filewrap.h" /* chsize */ ! 46: #include "ini_file.h" ! 47: ! 48: /* Maximum length of entire line, includes '\0' */ ! 49: #define INI_MAX_LINE_LEN (INI_MAX_VALUE_LEN*2) ! 50: #define INI_COMMENT_CHAR ';' ! 51: #define INI_OPEN_SECTION_CHAR '[' ! 52: #define INI_CLOSE_SECTION_CHAR ']' ! 53: #define INI_NEW_SECTION ((char*)~0) ! 54: ! 55: static ini_style_t default_style; ! 56: ! 57: static char* section_name(char* p) ! 58: { ! 59: char* tp; ! 60: ! 61: SKIP_WHITESPACE(p); ! 62: if(*p!=INI_OPEN_SECTION_CHAR) ! 63: return(NULL); ! 64: p++; ! 65: SKIP_WHITESPACE(p); ! 66: tp=strrchr(p,INI_CLOSE_SECTION_CHAR); ! 67: if(tp==NULL) ! 68: return(NULL); ! 69: *tp=0; ! 70: truncsp(p); ! 71: ! 72: return(p); ! 73: } ! 74: ! 75: static BOOL seek_section(FILE* fp, const char* section) ! 76: { ! 77: char* p; ! 78: char str[INI_MAX_LINE_LEN]; ! 79: ! 80: rewind(fp); ! 81: ! 82: if(section==ROOT_SECTION) ! 83: return(TRUE); ! 84: ! 85: while(!feof(fp)) { ! 86: if(fgets(str,sizeof(str),fp)==NULL) ! 87: break; ! 88: if((p=section_name(str))==NULL) ! 89: continue; ! 90: if(stricmp(p,section)==0) ! 91: return(TRUE); ! 92: } ! 93: return(FALSE); ! 94: } ! 95: ! 96: static size_t find_section_index(str_list_t list, const char* section) ! 97: { ! 98: char* p; ! 99: char str[INI_MAX_VALUE_LEN]; ! 100: size_t i; ! 101: ! 102: for(i=0; list[i]!=NULL; i++) { ! 103: SAFECOPY(str,list[i]); ! 104: if((p=section_name(str))!=NULL && stricmp(p,section)==0) ! 105: return(i); ! 106: } ! 107: ! 108: return(i); ! 109: } ! 110: ! 111: static size_t find_section(str_list_t list, const char* section) ! 112: { ! 113: size_t i; ! 114: ! 115: if(section==ROOT_SECTION) ! 116: return(0); ! 117: ! 118: i=find_section_index(list,section); ! 119: if(list[i]!=NULL) ! 120: i++; ! 121: return(i); ! 122: } ! 123: ! 124: static char* key_name(char* p, char** vp) ! 125: { ! 126: char* equal; ! 127: char* colon; ! 128: ! 129: *vp=NULL; ! 130: ! 131: if(p==NULL) ! 132: return(NULL); ! 133: ! 134: /* Parse value name */ ! 135: SKIP_WHITESPACE(p); ! 136: if(*p==INI_COMMENT_CHAR) ! 137: return(NULL); ! 138: if(*p==INI_OPEN_SECTION_CHAR) ! 139: return(INI_NEW_SECTION); ! 140: equal=strchr(p,'='); ! 141: colon=strchr(p,':'); ! 142: if(colon==NULL || (equal!=NULL && equal<colon)) { ! 143: *vp=equal; ! 144: colon=NULL; ! 145: } else ! 146: *vp=colon; ! 147: ! 148: if(*vp==NULL) ! 149: return(NULL); ! 150: ! 151: *(*vp)=0; ! 152: truncsp(p); ! 153: ! 154: /* Parse value */ ! 155: (*vp)++; ! 156: SKIP_WHITESPACE(*vp); ! 157: if(colon!=NULL) ! 158: truncnl(*vp); /* "key : value" - truncate new-line chars only */ ! 159: else ! 160: truncsp(*vp); /* "key = value" - truncate all white-space chars */ ! 161: ! 162: return(p); ! 163: } ! 164: ! 165: static char* read_value(FILE* fp, const char* section, const char* key, char* value) ! 166: { ! 167: char* p; ! 168: char* vp=NULL; ! 169: char str[INI_MAX_LINE_LEN]; ! 170: ! 171: if(fp==NULL) ! 172: return(NULL); ! 173: ! 174: if(!seek_section(fp,section)) ! 175: return(NULL); ! 176: ! 177: while(!feof(fp)) { ! 178: if(fgets(str,sizeof(str),fp)==NULL) ! 179: break; ! 180: if((p=key_name(str,&vp))==NULL) ! 181: continue; ! 182: if(p==INI_NEW_SECTION) ! 183: break; ! 184: if(stricmp(p,key)!=0) ! 185: continue; ! 186: if(vp==NULL) ! 187: break; ! 188: /* key found */ ! 189: sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,vp); ! 190: return(value); ! 191: } ! 192: ! 193: return(NULL); ! 194: } ! 195: ! 196: static size_t get_value(str_list_t list, const char* section, const char* key, char* value) ! 197: { ! 198: char str[INI_MAX_LINE_LEN]; ! 199: char* p; ! 200: char* vp; ! 201: size_t i; ! 202: ! 203: value[0]=0; ! 204: for(i=find_section(list, section); list[i]!=NULL; i++) { ! 205: SAFECOPY(str, list[i]); ! 206: if((p=key_name(str,&vp))==NULL) ! 207: continue; ! 208: if(p==INI_NEW_SECTION) ! 209: break; ! 210: if(stricmp(p,key)!=0) ! 211: continue; ! 212: sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,vp); ! 213: return(i); ! 214: } ! 215: ! 216: return(i); ! 217: } ! 218: ! 219: BOOL iniSectionExists(str_list_t* list, const char* section) ! 220: { ! 221: size_t i; ! 222: ! 223: if(section==ROOT_SECTION) ! 224: return(TRUE); ! 225: ! 226: i=find_section_index(*list,section); ! 227: return((*list)[i]!=NULL); ! 228: } ! 229: ! 230: BOOL iniKeyExists(str_list_t* list, const char* section, const char* key) ! 231: { ! 232: char val[INI_MAX_VALUE_LEN]; ! 233: size_t i; ! 234: ! 235: i=get_value(*list, section, key, val); ! 236: ! 237: if((*list)[i]==NULL || *(*list)[i]==INI_OPEN_SECTION_CHAR) ! 238: return(FALSE); ! 239: ! 240: return(TRUE); ! 241: } ! 242: ! 243: BOOL iniValueExists(str_list_t* list, const char* section, const char* key) ! 244: { ! 245: char val[INI_MAX_VALUE_LEN]; ! 246: ! 247: get_value(*list, section, key, val); ! 248: ! 249: return(val[0]!=0); ! 250: } ! 251: ! 252: BOOL iniRemoveKey(str_list_t* list, const char* section, const char* key) ! 253: { ! 254: char val[INI_MAX_VALUE_LEN]; ! 255: size_t i; ! 256: ! 257: i=get_value(*list, section, key, val); ! 258: ! 259: if((*list)[i]==NULL || *(*list)[i]==INI_OPEN_SECTION_CHAR) ! 260: return(FALSE); ! 261: ! 262: return(strListDelete(list,i)); ! 263: } ! 264: ! 265: BOOL iniRemoveValue(str_list_t* list, const char* section, const char* key) ! 266: { ! 267: char val[INI_MAX_VALUE_LEN]; ! 268: size_t i; ! 269: char* p; ! 270: char* vp=NULL; ! 271: ! 272: i=get_value(*list, section, key, val); ! 273: ! 274: p=key_name((*list)[i], &vp); ! 275: if(vp==NULL) ! 276: return(FALSE); ! 277: ! 278: strcat(p,"="); ! 279: return(TRUE); ! 280: } ! 281: ! 282: BOOL iniRemoveSection(str_list_t* list, const char* section) ! 283: { ! 284: size_t i; ! 285: ! 286: i=find_section_index(*list,section); ! 287: if((*list)[i]==NULL) /* not found */ ! 288: return(FALSE); ! 289: do { ! 290: strListDelete(list,i); ! 291: } while((*list)[i]!=NULL && *(*list)[i]!=INI_OPEN_SECTION_CHAR); ! 292: ! 293: return(TRUE); ! 294: } ! 295: ! 296: BOOL iniRenameSection(str_list_t* list, const char* section, const char* newname) ! 297: { ! 298: char str[INI_MAX_LINE_LEN]; ! 299: size_t i; ! 300: ! 301: if(section==ROOT_SECTION) ! 302: return(FALSE); ! 303: ! 304: i=find_section_index(*list,newname); ! 305: if((*list)[i]!=NULL) /* duplicate */ ! 306: return(FALSE); ! 307: ! 308: i=find_section_index(*list,section); ! 309: if((*list)[i]==NULL) /* not found */ ! 310: return(FALSE); ! 311: ! 312: SAFEPRINTF(str,"[%s]",newname); ! 313: return(strListReplace(*list, i, str)!=NULL); ! 314: } ! 315: ! 316: size_t iniAddSection(str_list_t* list, const char* section ! 317: ,ini_style_t* style) ! 318: { ! 319: char str[INI_MAX_LINE_LEN]; ! 320: size_t i; ! 321: ! 322: if(section==ROOT_SECTION) ! 323: return(0); ! 324: ! 325: i=find_section_index(*list, section); ! 326: if((*list)[i]==NULL) { ! 327: if(style==NULL) ! 328: style=&default_style; ! 329: if(style->section_separator!=NULL) ! 330: strListAppend(list, style->section_separator, i++); ! 331: SAFEPRINTF(str,"[%s]",section); ! 332: strListAppend(list, str, i); ! 333: } ! 334: ! 335: return(i); ! 336: } ! 337: ! 338: char* iniSetString(str_list_t* list, const char* section, const char* key, const char* value ! 339: ,ini_style_t* style) ! 340: { ! 341: char str[INI_MAX_LINE_LEN]; ! 342: char curval[INI_MAX_VALUE_LEN]; ! 343: size_t i; ! 344: ! 345: if(style==NULL) ! 346: style=&default_style; ! 347: ! 348: iniAddSection(list, section, style); ! 349: ! 350: if(key==NULL) ! 351: return(NULL); ! 352: if(style->key_prefix==NULL) ! 353: style->key_prefix=""; ! 354: if(style->value_separator==NULL) ! 355: style->value_separator="="; ! 356: if(value==NULL) ! 357: value=""; ! 358: safe_snprintf(str, sizeof(str), "%s%-*s%s%s" ! 359: , style->key_prefix, style->key_len, key, style->value_separator, value); ! 360: i=get_value(*list, section, key, curval); ! 361: if((*list)[i]==NULL || *(*list)[i]==INI_OPEN_SECTION_CHAR) { ! 362: while(i && *(*list)[i-1]==0) i--; /* Insert before blank lines, not after */ ! 363: return strListInsert(list, str, i); ! 364: } ! 365: ! 366: if(strcmp(curval,value)==0) ! 367: return((*list)[i]); /* no change */ ! 368: ! 369: return strListReplace(*list, i, str); ! 370: } ! 371: ! 372: char* iniSetInteger(str_list_t* list, const char* section, const char* key, long value ! 373: ,ini_style_t* style) ! 374: { ! 375: char str[INI_MAX_VALUE_LEN]; ! 376: ! 377: SAFEPRINTF(str,"%ld",value); ! 378: return iniSetString(list, section, key, str, style); ! 379: } ! 380: ! 381: char* iniSetShortInt(str_list_t* list, const char* section, const char* key, ushort value ! 382: ,ini_style_t* style) ! 383: { ! 384: char str[INI_MAX_VALUE_LEN]; ! 385: ! 386: SAFEPRINTF(str,"%hu",value); ! 387: return iniSetString(list, section, key, str, style); ! 388: } ! 389: ! 390: char* iniSetHexInt(str_list_t* list, const char* section, const char* key, ulong value ! 391: ,ini_style_t* style) ! 392: { ! 393: char str[INI_MAX_VALUE_LEN]; ! 394: ! 395: SAFEPRINTF(str,"0x%lx",value); ! 396: return iniSetString(list, section, key, str, style); ! 397: } ! 398: ! 399: char* iniSetFloat(str_list_t* list, const char* section, const char* key, double value ! 400: ,ini_style_t* style) ! 401: { ! 402: char str[INI_MAX_VALUE_LEN]; ! 403: ! 404: SAFEPRINTF(str,"%g",value); ! 405: return iniSetString(list, section, key, str, style); ! 406: } ! 407: ! 408: #if !defined(NO_SOCKET_SUPPORT) ! 409: char* iniSetIpAddress(str_list_t* list, const char* section, const char* key, ulong value ! 410: ,ini_style_t* style) ! 411: { ! 412: struct in_addr in_addr; ! 413: in_addr.s_addr=htonl(value); ! 414: return iniSetString(list, section, key, inet_ntoa(in_addr), style); ! 415: } ! 416: #endif ! 417: ! 418: char* iniSetBool(str_list_t* list, const char* section, const char* key, BOOL value ! 419: ,ini_style_t* style) ! 420: { ! 421: return iniSetString(list, section, key, value ? "true":"false", style); ! 422: } ! 423: ! 424: char* iniSetBitField(str_list_t* list, const char* section, const char* key ! 425: ,ini_bitdesc_t* bitdesc, ulong value, ini_style_t* style) ! 426: { ! 427: char str[INI_MAX_VALUE_LEN]; ! 428: int i; ! 429: ! 430: if(style==NULL) ! 431: style=&default_style; ! 432: if(style->bit_separator==NULL) ! 433: style->bit_separator="|"; ! 434: str[0]=0; ! 435: for(i=0;bitdesc[i].name;i++) { ! 436: if((value&bitdesc[i].bit)==0) ! 437: continue; ! 438: if(str[0]) ! 439: strcat(str,style->bit_separator); ! 440: strcat(str,bitdesc[i].name); ! 441: value&=~bitdesc[i].bit; ! 442: } ! 443: if(value) { /* left over bits? */ ! 444: if(str[0]) ! 445: strcat(str,style->bit_separator); ! 446: sprintf(str+strlen(str), "0x%lX", value); ! 447: } ! 448: return iniSetString(list, section, key, str, style); ! 449: } ! 450: ! 451: char* iniSetStringList(str_list_t* list, const char* section, const char* key ! 452: ,const char* sep, str_list_t val_list, ini_style_t* style) ! 453: { ! 454: char value[INI_MAX_VALUE_LEN]; ! 455: size_t i; ! 456: ! 457: value[0]=0; ! 458: ! 459: if(sep==NULL) ! 460: sep=","; ! 461: ! 462: if(val_list!=NULL) ! 463: for(i=0; val_list[i]!=NULL; i++) { ! 464: if(value[0]) ! 465: strcat(value,sep); ! 466: strcat(value,val_list[i]); ! 467: } ! 468: ! 469: return iniSetString(list, section, key, value, style); ! 470: } ! 471: ! 472: char* iniReadString(FILE* fp, const char* section, const char* key, const char* deflt, char* value) ! 473: { ! 474: if(read_value(fp,section,key,value)==NULL || *value==0 /* blank */) { ! 475: if(deflt==NULL) ! 476: return(NULL); ! 477: sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,deflt); ! 478: } ! 479: ! 480: return(value); ! 481: } ! 482: ! 483: char* iniGetString(str_list_t* list, const char* section, const char* key, const char* deflt, char* value) ! 484: { ! 485: get_value(*list, section, key, value); ! 486: ! 487: if(*value==0 /* blank */) { ! 488: if(deflt==NULL) ! 489: return(NULL); ! 490: sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,deflt); ! 491: } ! 492: ! 493: return(value); ! 494: } ! 495: ! 496: static str_list_t splitList(char* list, const char* sep) ! 497: { ! 498: char* token; ! 499: ulong items=0; ! 500: str_list_t lp; ! 501: ! 502: if((lp=strListInit())==NULL) ! 503: return(NULL); ! 504: ! 505: if(sep==NULL) ! 506: sep=","; ! 507: ! 508: token=strtok(list,sep); ! 509: while(token!=NULL) { ! 510: SKIP_WHITESPACE(token); ! 511: truncsp(token); ! 512: if(strListAppend(&lp,token,items++)==NULL) ! 513: break; ! 514: token=strtok(NULL,sep); ! 515: } ! 516: ! 517: return(lp); ! 518: } ! 519: ! 520: str_list_t iniReadStringList(FILE* fp, const char* section, const char* key ! 521: ,const char* sep, const char* deflt) ! 522: { ! 523: char* value; ! 524: char buf[INI_MAX_VALUE_LEN]; ! 525: char list[INI_MAX_VALUE_LEN]; ! 526: ! 527: if((value=read_value(fp,section,key,buf))==NULL || *value==0 /* blank */) ! 528: value=(char*)deflt; ! 529: ! 530: if(value==NULL) ! 531: return(NULL); ! 532: ! 533: SAFECOPY(list,value); ! 534: ! 535: return(splitList(list,sep)); ! 536: } ! 537: ! 538: str_list_t iniGetStringList(str_list_t* list, const char* section, const char* key ! 539: ,const char* sep, const char* deflt) ! 540: { ! 541: char buf[INI_MAX_VALUE_LEN]; ! 542: char* value=buf; ! 543: ! 544: get_value(*list, section, key, value); ! 545: ! 546: if(*value==0 /* blank */) ! 547: value=(char*)deflt; ! 548: ! 549: SAFECOPY(buf,value); ! 550: ! 551: return(splitList(buf,sep)); ! 552: } ! 553: ! 554: void* iniFreeStringList(str_list_t list) ! 555: { ! 556: strListFree(&list); ! 557: return(list); ! 558: } ! 559: ! 560: void* iniFreeNamedStringList(named_string_t** list) ! 561: { ! 562: ulong i; ! 563: ! 564: if(list==NULL) ! 565: return(NULL); ! 566: ! 567: for(i=0;list[i]!=NULL;i++) { ! 568: if(list[i]->name!=NULL) ! 569: free(list[i]->name); ! 570: if(list[i]->value!=NULL) ! 571: free(list[i]->value); ! 572: free(list[i]); ! 573: } ! 574: ! 575: free(list); ! 576: return(NULL); ! 577: } ! 578: ! 579: str_list_t iniReadSectionList(FILE* fp, const char* prefix) ! 580: { ! 581: char* p; ! 582: char str[INI_MAX_LINE_LEN]; ! 583: ulong items=0; ! 584: str_list_t lp; ! 585: ! 586: if((lp=strListInit())==NULL) ! 587: return(NULL); ! 588: ! 589: if(fp==NULL) ! 590: return(lp); ! 591: ! 592: rewind(fp); ! 593: ! 594: while(!feof(fp)) { ! 595: if(fgets(str,sizeof(str),fp)==NULL) ! 596: break; ! 597: if((p=section_name(str))==NULL) ! 598: continue; ! 599: if(prefix!=NULL) ! 600: if(strnicmp(p,prefix,strlen(prefix))!=0) ! 601: continue; ! 602: if(strListAppend(&lp,p,items++)==NULL) ! 603: break; ! 604: } ! 605: ! 606: return(lp); ! 607: } ! 608: ! 609: str_list_t iniGetSectionList(str_list_t* list, const char* prefix) ! 610: { ! 611: char* p; ! 612: char str[INI_MAX_LINE_LEN]; ! 613: ulong i,items=0; ! 614: str_list_t lp; ! 615: ! 616: if((lp=strListInit())==NULL) ! 617: return(NULL); ! 618: ! 619: if(list==NULL) ! 620: return(lp); ! 621: ! 622: for(i=0;list[i];i++) { ! 623: SAFECOPY(str,list[i]); ! 624: if((p=section_name(str))==NULL) ! 625: continue; ! 626: if(prefix!=NULL) ! 627: if(strnicmp(p,prefix,strlen(prefix))!=0) ! 628: continue; ! 629: if(strListAppend(&lp,p,items++)==NULL) ! 630: break; ! 631: } ! 632: ! 633: return(lp); ! 634: } ! 635: ! 636: str_list_t iniReadKeyList(FILE* fp, const char* section) ! 637: { ! 638: char* p; ! 639: char* vp; ! 640: char str[INI_MAX_LINE_LEN]; ! 641: ulong items=0; ! 642: str_list_t lp; ! 643: ! 644: if((lp=strListInit())==NULL) ! 645: return(NULL); ! 646: ! 647: if(fp==NULL) ! 648: return(lp); ! 649: ! 650: rewind(fp); ! 651: ! 652: if(!seek_section(fp,section)) ! 653: return(lp); ! 654: ! 655: while(!feof(fp)) { ! 656: if(fgets(str,sizeof(str),fp)==NULL) ! 657: break; ! 658: if((p=key_name(str,&vp))==NULL) ! 659: continue; ! 660: if(p==INI_NEW_SECTION) ! 661: break; ! 662: if(strListAppend(&lp,p,items++)==NULL) ! 663: break; ! 664: } ! 665: ! 666: return(lp); ! 667: } ! 668: ! 669: str_list_t iniGetKeyList(str_list_t* list, const char* section) ! 670: { ! 671: char* p; ! 672: char* vp; ! 673: char str[INI_MAX_LINE_LEN]; ! 674: ulong i,items=0; ! 675: str_list_t lp; ! 676: ! 677: if((lp=strListInit())==NULL) ! 678: return(NULL); ! 679: ! 680: if(list==NULL) ! 681: return(lp); ! 682: ! 683: for(i=find_section(*list,section);list[i]==NULL;i++) { ! 684: SAFECOPY(str,list[i]); ! 685: if((p=key_name(str,&vp))==NULL) ! 686: continue; ! 687: if(p==INI_NEW_SECTION) ! 688: break; ! 689: if(strListAppend(&lp,p,items++)==NULL) ! 690: break; ! 691: } ! 692: ! 693: return(lp); ! 694: } ! 695: ! 696: ! 697: named_string_t** ! 698: iniReadNamedStringList(FILE* fp, const char* section) ! 699: { ! 700: char* name; ! 701: char* value; ! 702: char str[INI_MAX_LINE_LEN]; ! 703: ulong items=0; ! 704: named_string_t** lp; ! 705: named_string_t** np; ! 706: ! 707: if((lp=(named_string_t**)malloc(sizeof(named_string_t*)))==NULL) ! 708: return(NULL); ! 709: ! 710: *lp=NULL; ! 711: ! 712: if(fp==NULL) ! 713: return(lp); ! 714: ! 715: rewind(fp); ! 716: ! 717: if(!seek_section(fp,section)) ! 718: return(lp); ! 719: ! 720: while(!feof(fp)) { ! 721: if(fgets(str,sizeof(str),fp)==NULL) ! 722: break; ! 723: if((name=key_name(str,&value))==NULL) ! 724: continue; ! 725: if(name==INI_NEW_SECTION) ! 726: break; ! 727: if((np=(named_string_t**)realloc(lp,sizeof(named_string_t*)*(items+2)))==NULL) ! 728: break; ! 729: lp=np; ! 730: if((lp[items]=(named_string_t*)malloc(sizeof(named_string_t)))==NULL) ! 731: break; ! 732: if((lp[items]->name=strdup(name))==NULL) ! 733: break; ! 734: if((lp[items]->value=strdup(value))==NULL) ! 735: break; ! 736: items++; ! 737: } ! 738: ! 739: lp[items]=NULL; /* terminate list */ ! 740: ! 741: return(lp); ! 742: } ! 743: ! 744: named_string_t** ! 745: iniGetNamedStringList(str_list_t* list, const char* section) ! 746: { ! 747: char* name; ! 748: char* value; ! 749: char str[INI_MAX_LINE_LEN]; ! 750: ulong i,items=0; ! 751: named_string_t** lp; ! 752: named_string_t** np; ! 753: ! 754: if((lp=(named_string_t**)malloc(sizeof(named_string_t*)))==NULL) ! 755: return(NULL); ! 756: ! 757: *lp=NULL; ! 758: ! 759: if(list==NULL) ! 760: return(lp); ! 761: ! 762: for(i=find_section(*list,section);list[i]!=NULL;i++) { ! 763: SAFECOPY(str,list[i]); ! 764: if((name=key_name(str,&value))==NULL) ! 765: continue; ! 766: if(name==INI_NEW_SECTION) ! 767: break; ! 768: if((np=(named_string_t**)realloc(lp,sizeof(named_string_t*)*(items+2)))==NULL) ! 769: break; ! 770: lp=np; ! 771: if((lp[items]=(named_string_t*)malloc(sizeof(named_string_t)))==NULL) ! 772: break; ! 773: if((lp[items]->name=strdup(name))==NULL) ! 774: break; ! 775: if((lp[items]->value=strdup(value))==NULL) ! 776: break; ! 777: items++; ! 778: } ! 779: ! 780: lp[items]=NULL; /* terminate list */ ! 781: ! 782: return(lp); ! 783: } ! 784: ! 785: ! 786: /* These functions read a single key of the specified type */ ! 787: ! 788: long iniReadInteger(FILE* fp, const char* section, const char* key, long deflt) ! 789: { ! 790: char* value; ! 791: char buf[INI_MAX_VALUE_LEN]; ! 792: ! 793: if((value=read_value(fp,section,key,buf))==NULL) ! 794: return(deflt); ! 795: ! 796: if(*value==0) /* blank value */ ! 797: return(deflt); ! 798: ! 799: return(strtol(value,NULL,0)); ! 800: } ! 801: ! 802: long iniGetInteger(str_list_t* list, const char* section, const char* key, long deflt) ! 803: { ! 804: char value[INI_MAX_VALUE_LEN]; ! 805: ! 806: get_value(*list, section, key, value); ! 807: ! 808: if(*value==0) /* blank value */ ! 809: return(deflt); ! 810: ! 811: return(strtol(value,NULL,0)); ! 812: } ! 813: ! 814: ushort iniReadShortInt(FILE* fp, const char* section, const char* key, ushort deflt) ! 815: { ! 816: return((ushort)iniReadInteger(fp, section, key, deflt)); ! 817: } ! 818: ! 819: ushort iniGetShortInt(str_list_t* list, const char* section, const char* key, ushort deflt) ! 820: { ! 821: return((ushort)iniGetInteger(list, section, key, deflt)); ! 822: } ! 823: ! 824: #if !defined(NO_SOCKET_SUPPORT) ! 825: ! 826: static ulong parseIpAddress(const char* value) ! 827: { ! 828: if(strchr(value,'.')==NULL) ! 829: return(strtol(value,NULL,0)); ! 830: ! 831: return(ntohl(inet_addr(value))); ! 832: } ! 833: ! 834: ulong iniReadIpAddress(FILE* fp, const char* section, const char* key, ulong deflt) ! 835: { ! 836: char buf[INI_MAX_VALUE_LEN]; ! 837: char* value; ! 838: ! 839: if((value=read_value(fp,section,key,buf))==NULL) ! 840: return(deflt); ! 841: ! 842: if(*value==0) /* blank value */ ! 843: return(deflt); ! 844: ! 845: return(parseIpAddress(value)); ! 846: } ! 847: ! 848: ulong iniGetIpAddress(str_list_t* list, const char* section, const char* key, ulong deflt) ! 849: { ! 850: char value[INI_MAX_VALUE_LEN]; ! 851: ! 852: get_value(*list, section, key, value); ! 853: ! 854: if(*value==0) /* blank value */ ! 855: return(deflt); ! 856: ! 857: return(parseIpAddress(value)); ! 858: } ! 859: ! 860: #endif /* !NO_SOCKET_SUPPORT */ ! 861: ! 862: char* iniFileName(char* dest, size_t maxlen, const char* indir, const char* infname) ! 863: { ! 864: char dir[MAX_PATH+1]; ! 865: char fname[MAX_PATH+1]; ! 866: char ext[MAX_PATH+1]; ! 867: char* p; ! 868: ! 869: SAFECOPY(dir,indir); ! 870: backslash(dir); ! 871: SAFECOPY(fname,infname); ! 872: ext[0]=0; ! 873: if((p=getfext(fname))!=NULL) { ! 874: SAFECOPY(ext,p); ! 875: *p=0; ! 876: } ! 877: ! 878: #if !defined(NO_SOCKET_SUPPORT) ! 879: { ! 880: char hostname[128]; ! 881: ! 882: if(gethostname(hostname,sizeof(hostname))==0) { ! 883: safe_snprintf(dest,maxlen,"%s%s.%s%s",dir,fname,hostname,ext); ! 884: if(fexistcase(dest)) /* path/file.host.domain.ini */ ! 885: return(dest); ! 886: if((p=strchr(hostname,'.'))!=NULL) { ! 887: *p=0; ! 888: safe_snprintf(dest,maxlen,"%s%s.%s%s",dir,fname,hostname,ext); ! 889: if(fexistcase(dest)) /* path/file.host.ini */ ! 890: return(dest); ! 891: } ! 892: } ! 893: } ! 894: #endif ! 895: ! 896: safe_snprintf(dest,maxlen,"%s%s%s",dir,fname,ext); ! 897: fexistcase(dest); /* path/file.ini */ ! 898: return(dest); ! 899: } ! 900: ! 901: double iniReadFloat(FILE* fp, const char* section, const char* key, double deflt) ! 902: { ! 903: char buf[INI_MAX_VALUE_LEN]; ! 904: char* value; ! 905: ! 906: if((value=read_value(fp,section,key,buf))==NULL) ! 907: return(deflt); ! 908: ! 909: if(*value==0) /* blank value */ ! 910: return(deflt); ! 911: ! 912: return(atof(value)); ! 913: } ! 914: ! 915: double iniGetFloat(str_list_t* list, const char* section, const char* key, double deflt) ! 916: { ! 917: char value[INI_MAX_VALUE_LEN]; ! 918: ! 919: get_value(*list, section, key, value); ! 920: ! 921: if(*value==0) /* blank value */ ! 922: return(deflt); ! 923: ! 924: return(atof(value)); ! 925: } ! 926: ! 927: static BOOL parseBool(const char* value) ! 928: { ! 929: if(!stricmp(value,"TRUE") || !stricmp(value,"YES")) ! 930: return(TRUE); ! 931: ! 932: return(INT_TO_BOOL(strtol(value,NULL,0))); ! 933: } ! 934: ! 935: BOOL iniReadBool(FILE* fp, const char* section, const char* key, BOOL deflt) ! 936: { ! 937: char buf[INI_MAX_VALUE_LEN]; ! 938: char* value; ! 939: ! 940: if((value=read_value(fp,section,key,buf))==NULL) ! 941: return(deflt); ! 942: ! 943: if(*value==0) /* blank value */ ! 944: return(deflt); ! 945: ! 946: return(parseBool(value)); ! 947: } ! 948: ! 949: BOOL iniGetBool(str_list_t* list, const char* section, const char* key, BOOL deflt) ! 950: { ! 951: char value[INI_MAX_VALUE_LEN]; ! 952: ! 953: get_value(*list, section, key, value); ! 954: ! 955: if(*value==0) /* blank value */ ! 956: return(deflt); ! 957: ! 958: return(parseBool(value)); ! 959: } ! 960: ! 961: static ulong parseBitField(char* value, ini_bitdesc_t* bitdesc) ! 962: { ! 963: int i; ! 964: char* p; ! 965: char* tp; ! 966: ulong v=0; ! 967: ! 968: for(p=value;*p;) { ! 969: tp=strchr(p,'|'); ! 970: if(tp!=NULL) ! 971: *tp=0; ! 972: truncsp(p); ! 973: ! 974: for(i=0;bitdesc[i].name;i++) ! 975: if(!stricmp(bitdesc[i].name,p)) ! 976: break; ! 977: ! 978: if(bitdesc[i].name) ! 979: v|=bitdesc[i].bit; ! 980: else ! 981: v|=strtoul(p,NULL,0); ! 982: ! 983: if(tp==NULL) ! 984: break; ! 985: ! 986: p=tp+1; ! 987: SKIP_WHITESPACE(p); ! 988: } ! 989: ! 990: return(v); ! 991: } ! 992: ! 993: ulong iniReadBitField(FILE* fp, const char* section, const char* key, ! 994: ini_bitdesc_t* bitdesc, ulong deflt) ! 995: { ! 996: char* value; ! 997: char buf[INI_MAX_VALUE_LEN]; ! 998: ! 999: if((value=read_value(fp,section,key,buf))==NULL) ! 1000: return(deflt); ! 1001: ! 1002: return(parseBitField(value,bitdesc)); ! 1003: } ! 1004: ! 1005: ulong iniGetBitField(str_list_t* list, const char* section, const char* key, ! 1006: ini_bitdesc_t* bitdesc, ulong deflt) ! 1007: { ! 1008: char value[INI_MAX_VALUE_LEN]; ! 1009: ! 1010: get_value(*list, section, key, value); ! 1011: ! 1012: if(*value==0) /* blank value */ ! 1013: return(deflt); ! 1014: ! 1015: return(parseBitField(value,bitdesc)); ! 1016: } ! 1017: ! 1018: FILE* iniOpenFile(const char* fname) ! 1019: { ! 1020: char* mode="r+"; ! 1021: ! 1022: if(!fexist(fname)) ! 1023: mode="w+"; ! 1024: ! 1025: return(fopen(fname,mode)); ! 1026: } ! 1027: ! 1028: BOOL iniCloseFile(FILE* fp) ! 1029: { ! 1030: return(fclose(fp)==0); ! 1031: } ! 1032: ! 1033: str_list_t iniReadFile(FILE* fp) ! 1034: { ! 1035: size_t i; ! 1036: str_list_t list; ! 1037: ! 1038: rewind(fp); ! 1039: ! 1040: list = strListReadFile(fp, NULL, INI_MAX_LINE_LEN); ! 1041: if(list!=NULL) { ! 1042: /* truncate new-line chars off end of strings */ ! 1043: for(i=0; list[i]!=NULL; i++) ! 1044: truncnl(list[i]); ! 1045: } ! 1046: ! 1047: return(list); ! 1048: } ! 1049: ! 1050: BOOL iniWriteFile(FILE* fp, const str_list_t list) ! 1051: { ! 1052: size_t count; ! 1053: ! 1054: rewind(fp); ! 1055: ! 1056: if(chsize(fileno(fp),0)!=0) /* truncate */ ! 1057: return(FALSE); ! 1058: ! 1059: count = strListWriteFile(fp,list,"\n"); ! 1060: ! 1061: return(count == strListCount(list)); ! 1062: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.