Annotation of embedaddon/pimd/libite/lfile.c, revision 1.1.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>