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>