File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimd / libite / lfile.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 09:12:58 2017 UTC (7 years, 3 months ago) by misho
Branches: pimd, MAIN
CVS tags: v2_3_2, HEAD
libite

    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>