|
|
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.