Annotation of sbbs/xpdev/ini_file.c, revision 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.