Annotation of sbbs/xpdev/ini_file.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.