Annotation of embedaddon/pimd/libite/lfile.c, revision 1.1

1.1     ! misho       1: /* Parse UNIX /etc configuration files like /etc/protocols and /etc/services
        !             2:  *
        !             3:  * Copyright (c) 2015  Joachim Nilsson <troglobit@gmail.com>
        !             4:  *
        !             5:  * Permission to use, copy, modify, and/or distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: 
        !            18: #include <errno.h>
        !            19: #include <stdio.h>             /* FILE */
        !            20: #include <stdlib.h>            /* atoi() */
        !            21: #include <string.h>            /* strlen(), strncmp(), strtok_r() */
        !            22: #include <sys/param.h>         /* MAX() */
        !            23: 
        !            24: typedef struct lfile {
        !            25:        FILE *fp;
        !            26:        char buf[256];
        !            27:        char *sep, *save;
        !            28: } lfile_t;
        !            29: 
        !            30: /**
        !            31:  * lfopen - Open file and return parsing context
        !            32:  * @file: File to parse
        !            33:  * @sep:  Separator(s) to use in lftok()
        !            34:  *
        !            35:  * Returns:
        !            36:  * Pointer to a &lftile_t parser context, or %NULL on error.
        !            37:  */
        !            38: lfile_t *lfopen(char *file, char *sep)
        !            39: {
        !            40:        lfile_t *lf;
        !            41: 
        !            42:        if (!file || !sep) {
        !            43:                errno = EINVAL;
        !            44:                return NULL;
        !            45:        }
        !            46: 
        !            47:        /* Use calloc for clearing buf on behalf of lftok() */
        !            48:        lf = calloc(sizeof(*lf), sizeof(char));
        !            49:        if (lf) {
        !            50:                lf->fp   = fopen(file, "r");
        !            51:                lf->sep  = sep;
        !            52:                lf->save = lf->buf;
        !            53: 
        !            54:                if (!lf->fp) {
        !            55:                        free(lf);
        !            56:                        return NULL;
        !            57:                }
        !            58:        }
        !            59: 
        !            60:        return lf;
        !            61: }
        !            62: 
        !            63: /**
        !            64:  * lfclose - Close a parser context
        !            65:  * @lf: Pointer to &lfile_t context from lfopen()
        !            66:  */
        !            67: void lfclose(lfile_t *lf)
        !            68: {
        !            69:        if (!lf)
        !            70:                return;
        !            71: 
        !            72:        if (lf->fp)
        !            73:                fclose(lf->fp);
        !            74:        free(lf);
        !            75: }
        !            76: 
        !            77: /**
        !            78:  * lftok - Get next token in file
        !            79:  * @lf: Pointer to &lfile_t context from lfopen()
        !            80:  *
        !            81:  * Returns:
        !            82:  * Next token, read from file previously opened with lfopen(),
        !            83:  * or %NULL if EOF.
        !            84:  */
        !            85: char *lftok(lfile_t *lf)
        !            86: {
        !            87:        char *token;
        !            88: 
        !            89:        if (!lf || !lf->fp || !lf->sep) {
        !            90:                errno = EINVAL;
        !            91:                return NULL;
        !            92:        }
        !            93: 
        !            94:        token = strtok_r(NULL, lf->sep, &lf->save);
        !            95:        if (!token) {
        !            96:                while (fgets(lf->buf, sizeof(lf->buf), lf->fp)) {
        !            97:                        if (lf->buf[0] == '#')
        !            98:                                continue;
        !            99: 
        !           100:                        token = strtok_r(lf->buf, lf->sep, &lf->save);
        !           101:                        if (!token)
        !           102:                                continue;
        !           103:                        
        !           104:                        return token;
        !           105:                }
        !           106: 
        !           107:                errno = ENOENT;
        !           108:                return NULL;
        !           109:        }
        !           110: 
        !           111:        return token;
        !           112: }
        !           113: 
        !           114: /**
        !           115:  * lfgetkey - Find key in file
        !           116:  * @lf:  Pointer to &lfile_t context from lfopen()
        !           117:  * @key: Key to look for
        !           118:  *
        !           119:  * Locate @key from the current position in the file parser context
        !           120:  * returned from lfopen().  Please note, the search for @key does not
        !           121:  * start from the beginning of the file, it searches from the current
        !           122:  * position.  To restart search from the beginning use rewind() on the
        !           123:  * lf->fp.
        !           124:  *
        !           125:  * Returns:
        !           126:  * The value to @key, or %NULL if not found.
        !           127:  */
        !           128: char *lfgetkey(lfile_t *lf, char *key)
        !           129: {
        !           130:        char *token;
        !           131: 
        !           132:        while ((token = lftok(lf))) {
        !           133:                if (token[0] == '#')
        !           134:                        continue;
        !           135: 
        !           136:                if (!strncmp(token, key, MAX(strlen(token), strlen(key))))
        !           137:                        return lftok(lf);
        !           138:        }
        !           139: 
        !           140:        return NULL;
        !           141: }
        !           142: 
        !           143: /**
        !           144:  * lfgetint - Same as lfgetkey() but returns an integer
        !           145:  * @lf:  Pointer to &lfile_t context from lfopen()
        !           146:  * @key: Key to look for
        !           147:  *
        !           148:  * This function is the same as lfgetkey() but returns the positive
        !           149:  * integer value for the matching @key, if found.
        !           150:  *
        !           151:  * Returns:
        !           152:  * The positive integer value for @key, or -1 if not found.
        !           153:  */
        !           154: int lfgetint(lfile_t *lf, char *key)
        !           155: {
        !           156:        char *token = lfgetkey(lf, key);
        !           157: 
        !           158:        if (token)
        !           159:                return atoi(token);
        !           160: 
        !           161:        return -1;
        !           162: }
        !           163: 
        !           164: /**
        !           165:  * fgetint - Find the integer value for key in a file
        !           166:  * @file: File to search for @key
        !           167:  * @sep:  Separator for tokens in @file
        !           168:  * @key:  Key to look for in @file
        !           169:  *
        !           170:  * This is a convenience wrapper for lfopen(), lfgetint(), and
        !           171:  * lfclose().
        !           172:  *
        !           173:  * Returns:
        !           174:  * The positive integer value for @key, or -1 if not found.
        !           175:  */
        !           176: int fgetint(char *file, char *sep, char *key)
        !           177: {
        !           178:        int val = -1;
        !           179:        lfile_t *lf;
        !           180: 
        !           181:        lf = lfopen(file, sep);
        !           182:        if (lf) {
        !           183:                val = lfgetint(lf, key);
        !           184:                lfclose(lf);
        !           185:        }
        !           186: 
        !           187:        return val;
        !           188: }
        !           189: 
        !           190: #ifdef UNITTEST
        !           191: int main(void)
        !           192: {
        !           193:        int val;
        !           194:        lfile_t lf;
        !           195: 
        !           196:        val = fgetint("/etc/protocols", " \n\t", "udp");
        !           197:        if (val == -1) {
        !           198:                perror("Failed locating 'udp' protocol");
        !           199:                return 1;
        !           200:        }
        !           201:        printf("udp has proto %d\n", val);
        !           202: 
        !           203:        val = fgetint("/etc/services", " /\n\t", "ftp");
        !           204:        if (val == -1) {
        !           205:                perror("Failed locating 'ftp' service");
        !           206:                return 1;
        !           207:        }
        !           208:        printf("ftp is inet port %d\n", val);
        !           209: 
        !           210:        val = fgetint("/etc/group", "x:\n", "utmp");
        !           211:        if (val == -1) {
        !           212:                perror("Failed locating group 'utmp'");
        !           213:                return 1;
        !           214:        }
        !           215:        printf("utmp is gid %d\n", val);
        !           216: 
        !           217:        val = fgetint("/etc/passwd", "x:\n", "nobody");
        !           218:        if (val == -1) {
        !           219:                perror("Failed locating user 'nobody'");
        !           220:                return 1;
        !           221:        }
        !           222:        printf("nobody is uid %d\n", val);
        !           223: 
        !           224:        return 0;
        !           225: }
        !           226: #endif
        !           227: 
        !           228: /**
        !           229:  * Local Variables:
        !           230:  *  compile-command: "make V=1 -f lfile.mk"
        !           231:  *  version-control: t
        !           232:  *  indent-tabs-mode: t
        !           233:  *  c-file-style: "linux"
        !           234:  * End:
        !           235:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>