Add simple parser for UNIX configuration files.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2015-10-25 22:50:10 +01:00
1 parent db08b20f23
commit c4eb5cb124
4 files changed
+250 -2

No files matched your search

+3 -2
View File
@@ -34,8 +34,8 @@ LDFLAGS = $(EXTRA_LDFLAGS)
DISTFILES = README LICENSE DISTFILES = README LICENSE
HEADERS = lite.h HEADERS = lite.h
OBJS := chomp.o copyfile.o dir.o fexist.o fisdir.o fmode.o fsendfile.o OBJS := chomp.o copyfile.o dir.o fexist.o fisdir.o fmode.o fsendfile.o
OBJS += ifconfig.o makepath.o pidfile.o pidfilefn.o progress.o rsync.o OBJS += ifconfig.o lfile.o makepath.o pidfile.o pidfilefn.o progress.o
OBJS += strlcpy.o strlcat.o strtonum.o tempfile.o tree.o OBJS += rsync.o strlcpy.o strlcat.o strtonum.o tempfile.o tree.o
DEPS := $(OBJS:.o=.d) DEPS := $(OBJS:.o=.d)
JUNK = *~ *.bak *.map .*.d *.d DEADJOE semantic.cache *.gdb *.elf core core.* JUNK = *~ *.bak *.map .*.d *.d DEADJOE semantic.cache *.gdb *.elf core core.*
@@ -57,6 +57,7 @@ test: clean
$(MAKE) -f fexist.mk $(MAKE) -f fexist.mk
$(MAKE) -f fisdir.mk $(MAKE) -f fisdir.mk
$(MAKE) -f fsendfile.mk $(MAKE) -f fsendfile.mk
$(MAKE) -f lfile.mk
$(MAKE) -f makepath.mk $(MAKE) -f makepath.mk
$(MAKE) -f pidfilefn.mk $(MAKE) -f pidfilefn.mk
$(MAKE) -f progress.mk $(MAKE) -f progress.mk
+23
View File
@@ -133,6 +133,29 @@ Generic Functions
Basic ifconfig like operations on an interface. Only supports IPv4 Basic ifconfig like operations on an interface. Only supports IPv4
adresses. Note that mask is not CIDR notation. adresses. Note that mask is not CIDR notation.
- `lfopen(file, sep)`, `lfclose(lf)`
API for parsing UNIX style configuration files like `/etc/protocols`
and `/etc/services`.
- `lftok(lf)`
Read tokens, delimeted by `sep`, from file opened with `lfopen()`.
- `lfgetkey(lf, key)`
Find `key` in file opened with `lfopen()`, return value/argument.
- `lfgetint(lf, key)`
Wrapper for `lfgetkey()`, returns positive integer value to `key`,
or `-1` if `key` is not found.
- `fgetint(file, sep, key)`
Wrapper for `lfopen()`, `lfgetint()`, and `lfclose()`. Useful for
when only reading a single `key` from a file.
- `makepath(dir)` - `makepath(dir)`
Create all components of the specified directory. Create all components of the specified directory.
+220
View File
@@ -0,0 +1,220 @@
/* Parse UNIX /etc configuration files like /etc/protocols and /etc/services
*
* Copyright (c) 2015 Joachim Nilsson <troglobit@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <stdio.h> /* FILE */
#include <stdlib.h> /* atoi() */
#include <string.h> /* strlen(), strncmp(), strtok_r() */
#include <sys/param.h> /* MAX() */
typedef struct {
FILE *fp;
char buf[256];
char *sep, *save;
} lfile_t;
/**
* lfopen - Open file and return parsing context
* @file: File to parse
* @sep: Separator(s) to use in lftok()
*
* Returns:
* Pointer to a &lftile_t parser context, or %NULL on error.
*/
lfile_t *lfopen(char *file, char *sep)
{
lfile_t *lf;
if (!file || !sep) {
errno = EINVAL;
return NULL;
}
/* Use calloc for clearing buf on behalf of lftok() */
lf = calloc(sizeof(*lf), sizeof(char));
if (lf) {
lf->fp = fopen(file, "r");
lf->sep = sep;
if (!lf->fp) {
free(lf);
return NULL;
}
}
return lf;
}
/**
* lfclose - Close a parser context
* @lf: Pointer to &lfile_t context from lfopen()
*/
void lfclose(lfile_t *lf)
{
if (!lf)
return;
if (lf->fp)
fclose(lf->fp);
free(lf);
}
/**
* lftok - Get next token in file
* @lf: Pointer to &lfile_t context from lfopen()
*
* Returns:
* Next token, read from file previously opened with lfopen(),
* or %NULL if EOF.
*/
char *lftok(lfile_t *lf)
{
char *token;
if (!lf || !lf->fp || !lf->sep) {
errno = EINVAL;
return NULL;
}
token = strtok_r(NULL, lf->sep, &lf->save);
if (!token) {
while (fgets(lf->buf, sizeof(lf->buf), lf->fp)) {
if (lf->buf[0] == '#')
continue;
token = strtok_r(lf->buf, lf->sep, &lf->save);
if (!token)
continue;
return token;
}
errno = ENOENT;
return NULL;
}
return token;
}
/**
* lfgetkey - Find key in file
* @lf: Pointer to &lfile_t context from lfopen()
* @key: Key to look for
*
* Locate @key from the current position in the file parser context
* returned from lfopen(). Please note, the search for @key does not
* start from the beginning of the file, it searches from the current
* position. To restart search from the beginning use rewind() on the
* lf->fp.
*
* Returns:
* The value to @key, or %NULL if not found.
*/
char *lfgetkey(lfile_t *lf, char *key)
{
char *token;
while ((token = lftok(lf))) {
if (token[0] == '#')
continue;
if (!strncmp(token, key, MAX(strlen(token), strlen(key))))
return lftok(lf);
}
return NULL;
}
/**
* lfgetint - Same as lfgetkey() but returns an integer
* @lf: Pointer to &lfile_t context from lfopen()
* @key: Key to look for
*
* This function is the same as lfgetkey() but returns the positive
* integer value for the matching @key, if found.
*
* Returns:
* The positive integer value for @key, or -1 if not found.
*/
int lfgetint(lfile_t *lf, char *key)
{
char *token = lfgetkey(lf, key);
if (token)
return atoi(token);
return -1;
}
/**
* fgetint - Find the integer value for key in a file
* @file: File to search for @key
* @sep: Separator for tokens in @file
* @key: Key to look for in @file
*
* This is a convenience wrapper for lfopen(), lfgetint(), and
* lfclose().
*
* Returns:
* The positive integer value for @key, or -1 if not found.
*/
int fgetint(char *file, char *sep, char *key)
{
int val = -1;
lfile_t *lf;
lf = lfopen(file, sep);
if (lf) {
val = lfgetint(lf, key);
lfclose(lf);
}
return val;
}
#ifdef UNITTEST
int main(void)
{
int val;
lfile_t lf;
val = fgetint("/etc/protocols", " \n\t", "udp");
if (val == -1) {
perror("Failed locating 'udp' protocol");
return 1;
}
printf("udp has proto %d\n", val);
val = fgetint("/etc/services", " /\n\t", "ftp");
if (val == -1) {
perror("Failed locating 'ftp' service");
return 1;
}
printf("ftp is inet port %d\n", val);
return 0;
}
#endif
/**
* Local Variables:
* compile-command: "make V=1 -f lfile.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+4
View File
@@ -0,0 +1,4 @@
OBJS =
TARGET = lfile.test clean
include rules.mk