From f02d5d33f1c075bb2a0960a5407d1fa813d45b40 Mon Sep 17 00:00:00 2001 From: octo Date: Tue, 13 Dec 2005 17:57:47 +0000 Subject: [PATCH] Added src/libconfig so distribution --- src/Makefile.am | 13 +- src/libconfig/AUTHORS | 17 + src/libconfig/LICENSE | 19 + src/libconfig/Makefile.am | 13 + src/libconfig/README | 19 + src/libconfig/TODO | 11 + src/libconfig/compat.h | 103 +++ src/libconfig/conf_apache.c | 371 ++++++++++ src/libconfig/conf_apache.h | 8 + src/libconfig/conf_colon.c | 7 + src/libconfig/conf_colon.h | 8 + src/libconfig/conf_equal.c | 7 + src/libconfig/conf_equal.h | 8 + src/libconfig/conf_section.c | 201 ++++++ src/libconfig/conf_section.h | 8 + src/libconfig/conf_space.c | 109 +++ src/libconfig/conf_space.h | 8 + src/libconfig/conf_xml.c | 7 + src/libconfig/conf_xml.h | 8 + src/libconfig/getuid.c | 5 + src/libconfig/getuid.h | 8 + src/libconfig/libconfig.c | 1073 +++++++++++++++++++++++++++++ src/libconfig/libconfig.h | 84 +++ src/libconfig/libconfig_private.h | 28 + src/libconfig/strsep.c | 34 + src/libconfig/strsep.h | 32 + src/libconfig/strtoll.c | 43 ++ src/libconfig/strtoll.h | 6 + src/libconfig/test-lc.c | 79 +++ src/libconfig/win32.h | 44 ++ 30 files changed, 2376 insertions(+), 5 deletions(-) create mode 100644 src/libconfig/AUTHORS create mode 100644 src/libconfig/LICENSE create mode 100644 src/libconfig/Makefile.am create mode 100644 src/libconfig/README create mode 100644 src/libconfig/TODO create mode 100644 src/libconfig/compat.h create mode 100644 src/libconfig/conf_apache.c create mode 100644 src/libconfig/conf_apache.h create mode 100644 src/libconfig/conf_colon.c create mode 100644 src/libconfig/conf_colon.h create mode 100644 src/libconfig/conf_equal.c create mode 100644 src/libconfig/conf_equal.h create mode 100644 src/libconfig/conf_section.c create mode 100644 src/libconfig/conf_section.h create mode 100644 src/libconfig/conf_space.c create mode 100644 src/libconfig/conf_space.h create mode 100644 src/libconfig/conf_xml.c create mode 100644 src/libconfig/conf_xml.h create mode 100644 src/libconfig/getuid.c create mode 100644 src/libconfig/getuid.h create mode 100644 src/libconfig/libconfig.c create mode 100644 src/libconfig/libconfig.h create mode 100644 src/libconfig/libconfig_private.h create mode 100644 src/libconfig/strsep.c create mode 100644 src/libconfig/strsep.h create mode 100644 src/libconfig/strtoll.c create mode 100644 src/libconfig/strtoll.h create mode 100644 src/libconfig/test-lc.c create mode 100644 src/libconfig/win32.h diff --git a/src/Makefile.am b/src/Makefile.am index 4f271bf2..8ec68e95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,8 @@ +SUBDIRS = libconfig if BUILD_MODULE_PING -SUBDIRS = libping . +SUBDIRS += libping endif +#SUBDIRS += . sbin_PROGRAMS = collectd @@ -9,13 +11,14 @@ collectd_SOURCES = collectd.c collectd.h \ utils_mount.c utils_mount.h \ common.c common.h \ multicast.c multicast.h \ - plugin.c plugin.h + plugin.c plugin.h \ + configfile.c configfile.h #collectd_CFLAGS = -DPLUGINDIR='"$(pkglibdir)"' collectd_CPPFLAGS = -DLOCALSTATEDIR='"$(localstatedir)"' -DPLUGINDIR='"$(pkglibdir)"' -collectd_LDFLAGS = -export-dynamic +collectd_LDFLAGS = -export-dynamic -lconfig collectd_CFLAGS = -Werror -collectd_LDADD = $(LIBLTDL) "-dlopen" self -collectd_DEPENDENCIES = $(LIBLTDL) +collectd_LDADD = $(LIBLTDL) libconfig/libconfig.la "-dlopen" self +collectd_DEPENDENCIES = $(LIBLTDL) libconfig/libconfig.la if BUILD_WITH_RRDTOOL collectd_LDADD += -lrrd endif diff --git a/src/libconfig/AUTHORS b/src/libconfig/AUTHORS new file mode 100644 index 00000000..53f27bf8 --- /dev/null +++ b/src/libconfig/AUTHORS @@ -0,0 +1,17 @@ + libconfig 0.1.21 + +Release information: + pkg: libconfig version 0.1.21 + url: http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz + web: http://www.rkeene.org/oss/libconfig/ + date: Tue Oct 18 16:03:55 CDT 2005 + mail: libconfig@rkeene.org +-------------------------------------------------------------------------- + +Primary Authors: + * Roy Keene + Primary maintainer. + +People who have submitted patches: + * Mirko Buffoni + Fixed installation issues and corrected mistakes in RPM spec file. diff --git a/src/libconfig/LICENSE b/src/libconfig/LICENSE new file mode 100644 index 00000000..4af06fb8 --- /dev/null +++ b/src/libconfig/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004 Roy Keene, Keene Enterprises + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/libconfig/Makefile.am b/src/libconfig/Makefile.am new file mode 100644 index 00000000..071784f4 --- /dev/null +++ b/src/libconfig/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = foreign no-dependencies + +noinst_LTLIBRARIES = libconfig.la + +libconfig_la_LDFLAGS = -avoid-version +libconfig_la_SOURCES = \ + libconfig.c libconfig.h \ + conf_apache.c conf_apache.h \ + conf_colon.c conf_colon.h \ + conf_equal.c conf_equal.h \ + conf_section.c conf_section.h \ + conf_space.c conf_space.h \ + conf_xml.c conf_xml.h diff --git a/src/libconfig/README b/src/libconfig/README new file mode 100644 index 00000000..7274223a --- /dev/null +++ b/src/libconfig/README @@ -0,0 +1,19 @@ + libconfig 0.1.21 + +Release information: + pkg: libconfig version 0.1.21 + url: http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz + web: http://www.rkeene.org/oss/libconfig/ + date: Tue Oct 18 16:03:55 CDT 2005 + mail: libconfig@rkeene.org +-------------------------------------------------------------------------- + +Tested platforms: + Mac OS X 10.1 + HP-UX 11.11 + NetBSD 1.6.1 + FreeBSD 4.8 + OpenBSD 3.4 + SunOS 5.9 + Linux (Slackware, RedHat, Fedora Core, Debian) + IRIX 6.5 diff --git a/src/libconfig/TODO b/src/libconfig/TODO new file mode 100644 index 00000000..6ba4ed30 --- /dev/null +++ b/src/libconfig/TODO @@ -0,0 +1,11 @@ + libconfig 0.1.21 + +Release information: + pkg: libconfig version 0.1.21 + url: http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz + web: http://www.rkeene.org/oss/libconfig/ + date: Tue Oct 18 16:03:55 CDT 2005 + mail: libconfig@rkeene.org +-------------------------------------------------------------------------- + + More manual pages. diff --git a/src/libconfig/compat.h b/src/libconfig/compat.h new file mode 100644 index 00000000..9d220388 --- /dev/null +++ b/src/libconfig/compat.h @@ -0,0 +1,103 @@ +#ifndef RSK_COMPAT_H +#define RSK_COMPAT_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef __WIN32__ +#include "win32.h" +#endif + +#ifndef LC_LINEBUF_LEN +#define LC_LINEBUF_LEN 1024 +#endif + +#ifndef HAVE_GETUID +#include "getuid.h" +#endif +#ifndef HAVE_STRTOLL +#include "strtoll.h" +#endif +#ifndef HAVE_STRSEP +#include "strsep.h" +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif +#ifdef HAVE_MEMORY_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef TIME_WITH_SYS_TIME +#include +#include +#else +#ifdef HAVE_SYS_TIME_H +#include +#else +#include +#endif +#endif + +#ifdef HAVE_OPENNET_H +#include +#endif +#ifdef HAVE_LIBOPENNET +#define lc_fopen(path, mode) fopen_net(path, mode) +#define lc_fgets(buf, size, stream) fgets_net(buf, size, stream) +#define lc_feof(stream) feof_net(stream) +#define lc_fclose(stream) fclose_net(stream) +#define LC_FILE NETFILE +#else +#define lc_fopen(path, mode) fopen(path, mode) +#define lc_fgets(buf, size, stream) fgets(buf, size, stream) +#define lc_feof(stream) feof(stream) +#define lc_fclose(stream) fclose(stream) +#define LC_FILE FILE +#endif + +#endif diff --git a/src/libconfig/conf_apache.c b/src/libconfig/conf_apache.c new file mode 100644 index 00000000..1497d1e4 --- /dev/null +++ b/src/libconfig/conf_apache.c @@ -0,0 +1,371 @@ +#include "compat.h" +#include "libconfig.h" +#include "libconfig_private.h" +#include "conf_apache.h" + +#ifdef HAVE_CTYPE_H +#include +#endif + +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_DIRENT_H +#include +#endif + +static int lc_process_conf_apache_file(const char *configfile, const char *pathprefix); + +static int lc_process_conf_apache_include(const char *pathname, const char *pathprefix) { + struct stat pathinfo; + struct dirent *dinfo = NULL; + char includepath[LC_LINEBUF_LEN] = {0}; + DIR *dh = NULL; + int statret = -1, lcpcafret = -1; + int retval = 0; + + statret = stat(pathname, &pathinfo); + if (statret < 0) { + return(-1); + } + + if (S_ISDIR(pathinfo.st_mode)) { + dh = opendir(pathname); + if (dh == NULL) { + return(-1); + } + + while (1) { + dinfo = readdir(dh); + if (dinfo == NULL) { + break; + } + + /* Skip files that begin with a dot ('.') */ + if (dinfo->d_name[0] == '.') continue; + + snprintf(includepath, sizeof(includepath) - 1, "%s/%s", pathname, dinfo->d_name); + lcpcafret = lc_process_conf_apache_include(includepath, pathprefix); + if (lcpcafret < 0) { + retval = -1; + /* XXX: should we break here (abort further including of files from a directory if one fails ?) */ + } + } + + closedir(dh); + } else { + lcpcafret = lc_process_conf_apache_file(pathname, pathprefix); + if (lcpcafret < 0) { + retval = -1; + } + } + + return(retval); +} + +static int lc_process_conf_apache_file(const char *configfile, const char *pathprefix) { + LC_FILE *configfp = NULL; + const char *local_lc_errfile; + char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL, *tmp_ptr = NULL; + char *lastsection = NULL; + char qualifbuf[LC_LINEBUF_LEN] = {0}; + char *cmd = NULL, *value = NULL, *sep = NULL, *cmdend = NULL; + char *fgetsret = NULL; + int lcpvret = -1, lpcafret = -1; + int invalid_section = 0, ignore_section = 0; + int local_lc_errline; + int retval = 0; + lc_err_t save_lc_errno = LC_ERR_NONE; + + if (pathprefix != NULL) { + /* Copy the prefix, if specified. */ + strncpy(qualifbuf, pathprefix, sizeof(qualifbuf) - 1); + } + + local_lc_errfile = configfile; + local_lc_errline = 0; + + if (configfile == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVDATA; + return(-1); + } + + configfp = lc_fopen(configfile, "r"); + + if (configfp == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_CANTOPEN; + return(-1); + } + + while (1) { + fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp); + if (fgetsret == NULL) { + break; + } + if (lc_feof(configfp)) { + break; + } + + local_lc_errline++; + + /* Remove trailing crap (but not spaces). */ + linebuf_ptr = &linebuf[strlen(linebuf) - 1]; + while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) { + *linebuf_ptr = '\0'; + linebuf_ptr--; + } + + /* Remove leading spaces. */ + linebuf_ptr = &linebuf[0]; + while (*linebuf_ptr == ' ' || *linebuf_ptr == '\t') { + linebuf_ptr++; + } + + /* Handle section header. */ + if (linebuf_ptr[0] == '<' && linebuf_ptr[strlen(linebuf_ptr) - 1] == '>') { + /* Remove < and > from around the data. */ + linebuf_ptr[strlen(linebuf_ptr) - 1] = '\0'; + linebuf_ptr++; + + /* Lowercase the command part of the section. */ + tmp_ptr = linebuf_ptr; + while (*tmp_ptr != '\0' && *tmp_ptr != ' ') { + *tmp_ptr = tolower(*tmp_ptr); + tmp_ptr++; + } + + /* If this is a close section command, handle it */ + if (linebuf_ptr[0] == '/') { + linebuf_ptr++; + cmd = linebuf_ptr; + + /* Find the last section closed. */ + tmp_ptr = strrchr(qualifbuf, '.'); + if (tmp_ptr == NULL) { + lastsection = qualifbuf; + tmp_ptr = qualifbuf; + } else { + lastsection = tmp_ptr + 1; + } + + if (strcmp(cmd, lastsection) != 0) { +#ifdef DEBUG + fprintf(stderr, "Section closing does not match last opened section.\n"); + fprintf(stderr, "Last opened = \"%s\", Closing = \"%s\"\n", lastsection, cmd); +#endif + retval = -1; + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_BADFORMAT; + + /* For this error, we abort immediately. */ + break; + } + + lcpvret = lc_process_var(qualifbuf, NULL, NULL, LC_FLAGS_SECTIONEND); + if (lcpvret < 0) { +#ifdef DEBUG + fprintf(stderr, "Invalid section terminating: \"%s\"\n", qualifbuf); +#endif + } + + /* Remove the "lastsection" part.. */ + *tmp_ptr = '\0'; + + /* We just sucessfully closed the last section opened, + we must be in a valid section now since we only open + sections from within valid sections. */ + invalid_section = 0; + ignore_section = 0; + + continue; + } + /* Otherwise, open a new section. */ + + /* Don't open a section from an invalid section. */ + if (invalid_section == 1 || ignore_section == 1) { + continue; + } + + /* Parse out any argument passed. */ + sep = strpbrk(linebuf_ptr, " \t"); + + if (sep != NULL) { + cmdend = sep; + /* Delete space at the end of the command. */ + cmdend--; /* It currently derefs to the seperator.. */ + while (*cmdend <= ' ') { + *cmdend = '\0'; + cmdend--; + } + + /* Delete the seperator char and any leading space. */ + *sep = '\0'; + sep++; + while (*sep == ' ' || *sep == '\t') { + sep++; + } + value = sep; + } else { + /* XXX: should this be "" or NULL ? */ + value = ""; + } + + cmd = linebuf_ptr; + + if (qualifbuf[0] != '\0') { + strncat(qualifbuf, ".", sizeof(qualifbuf) - strlen(qualifbuf) - 1); + } + strncat(qualifbuf, cmd, sizeof(qualifbuf) - strlen(qualifbuf) - 1); + + lcpvret = lc_process_var(qualifbuf, value, NULL, LC_FLAGS_SECTIONSTART); + if (lcpvret < 0) { +#ifdef DEBUG + fprintf(stderr, "Invalid section: \"%s\"\n", qualifbuf); +#endif + invalid_section = 1; + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVSECTION; + retval = -1; + } + if (lcpvret == LC_CBRET_IGNORESECTION) { + ignore_section = 1; + } + continue; + } + + /* Drop comments and blank lines. */ + if (*linebuf_ptr == '#' || *linebuf_ptr == '\0') { + continue; + } + + /* Don't handle things for a section that doesn't exist. */ + if (invalid_section == 1) { +#ifdef DEBUG + fprintf(stderr, "Ignoring line (because invalid section): %s\n", linebuf); +#endif + continue; + } + if (ignore_section == 1) { +#ifdef DEBUG + fprintf(stderr, "Ignoring line (because ignored section): %s\n", linebuf); +#endif + continue; + } + + /* Find the command and the data in the line. */ + sep = strpbrk(linebuf_ptr, " \t"); + if (sep != NULL) { + cmdend = sep; + + /* Delete space at the end of the command. */ + cmdend--; /* It currently derefs to the seperator.. */ + while (*cmdend <= ' ') { + *cmdend = '\0'; + cmdend--; + } + + /* Delete the seperator char and any leading space. */ + *sep = '\0'; + sep++; + while (*sep == ' ' || *sep == '\t') { + sep++; + } + value = sep; + } else { + value = NULL; + } + + cmd = linebuf_ptr; + + /* Handle special commands. */ + if (strcasecmp(cmd, "include") == 0) { + if (value == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_BADFORMAT; + retval = -1; +#ifdef DEBUG + fprintf(stderr, "Invalid include command.\n"); +#endif + continue; + } + + lpcafret = lc_process_conf_apache_include(value, qualifbuf); + if (lpcafret < 0) { +#ifdef DEBUG + fprintf(stderr, "Error in included file.\n"); +#endif + retval = -1; + } + continue; + } + + /* Create the fully qualified variable name. */ + if (qualifbuf[0] != '\0') { + strncat(qualifbuf, ".", sizeof(qualifbuf) - strlen(qualifbuf) - 1); + } + strncat(qualifbuf, cmd, sizeof(qualifbuf) - strlen(qualifbuf) - 1); + + /* Call the parent and tell them we have data. */ + save_lc_errno = lc_errno; + lc_errno = LC_ERR_NONE; + lcpvret = lc_process_var(qualifbuf, NULL, value, LC_FLAGS_VAR); + if (lcpvret < 0) { + if (lc_errno == LC_ERR_NONE) { +#ifdef DEBUG + fprintf(stderr, "Invalid command: \"%s\"\n", cmd); +#endif + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVCMD; + } else { +#ifdef DEBUG + fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n"); +#endif + } + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + retval = -1; + } else { + lc_errno = save_lc_errno; + } + + /* Remove the "cmd" part of the buffer. */ + tmp_ptr = strrchr(qualifbuf, '.'); + if (tmp_ptr == NULL) { + tmp_ptr = qualifbuf; + } + *tmp_ptr = '\0'; + } + + lc_fclose(configfp); + + return(retval); +} + +int lc_process_conf_apache(const char *appname, const char *configfile) { + return(lc_process_conf_apache_file(configfile, NULL)); +} diff --git a/src/libconfig/conf_apache.h b/src/libconfig/conf_apache.h new file mode 100644 index 00000000..36c556ed --- /dev/null +++ b/src/libconfig/conf_apache.h @@ -0,0 +1,8 @@ +#ifndef LC_CONF_APACHE_H +#define LC_CONF_APACHE_H +#include "libconfig.h" +#include "libconfig_private.h" + +int lc_process_conf_apache(const char *appname, const char *configfile); + +#endif diff --git a/src/libconfig/conf_colon.c b/src/libconfig/conf_colon.c new file mode 100644 index 00000000..f1843090 --- /dev/null +++ b/src/libconfig/conf_colon.c @@ -0,0 +1,7 @@ +#include "libconfig.h" +#include "libconfig_private.h" +#include "conf_colon.h" + +int lc_process_conf_colon(const char *appname, const char *configfile) { + return(-1); +} diff --git a/src/libconfig/conf_colon.h b/src/libconfig/conf_colon.h new file mode 100644 index 00000000..7d2323c4 --- /dev/null +++ b/src/libconfig/conf_colon.h @@ -0,0 +1,8 @@ +#ifndef LC_CONF_COLON_H +#define LC_CONF_COLON_H +#include "libconfig.h" +#include "libconfig_private.h" + +int lc_process_conf_colon(const char *appname, const char *configfile); + +#endif diff --git a/src/libconfig/conf_equal.c b/src/libconfig/conf_equal.c new file mode 100644 index 00000000..a214330c --- /dev/null +++ b/src/libconfig/conf_equal.c @@ -0,0 +1,7 @@ +#include "libconfig.h" +#include "libconfig_private.h" +#include "conf_equal.h" + +int lc_process_conf_equal(const char *appname, const char *configfile) { + return(-1); +} diff --git a/src/libconfig/conf_equal.h b/src/libconfig/conf_equal.h new file mode 100644 index 00000000..82e0f045 --- /dev/null +++ b/src/libconfig/conf_equal.h @@ -0,0 +1,8 @@ +#ifndef LC_CONF_EQUAL_H +#define LC_CONF_EQUAL_H +#include "libconfig.h" +#include "libconfig_private.h" + +int lc_process_conf_equal(const char *appname, const char *configfile); + +#endif diff --git a/src/libconfig/conf_section.c b/src/libconfig/conf_section.c new file mode 100644 index 00000000..fb948c18 --- /dev/null +++ b/src/libconfig/conf_section.c @@ -0,0 +1,201 @@ +#include "compat.h" +#include "libconfig.h" +#include "libconfig_private.h" +#include "conf_section.h" + +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +int lc_process_conf_section(const char *appname, const char *configfile) { + LC_FILE *configfp = NULL; + const char *local_lc_errfile; + char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL; + char qualifbuf[LC_LINEBUF_LEN] = {0}; + char *cmd = NULL, *value = NULL, *sep = NULL, *cmdend = NULL; + char *currsection = NULL; + char *fgetsret = NULL; + int lcpvret = -1; + int invalid_section = 1, ignore_section = 0; + int local_lc_errline; + int retval = 0; + lc_err_t save_lc_errno = LC_ERR_NONE; + + local_lc_errfile = configfile; + local_lc_errline = 0; + + if (appname == NULL || configfile == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVDATA; + return(-1); + } + + configfp = lc_fopen(configfile, "r"); + + if (configfp == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_CANTOPEN; + return(-1); + } + + while (1) { + fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp); + if (fgetsret == NULL) { + break; + } + if (lc_feof(configfp)) { + break; + } + + local_lc_errline++; + + /* Remove trailing crap (but not spaces). */ + linebuf_ptr = &linebuf[strlen(linebuf) - 1]; + while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) { + *linebuf_ptr = '\0'; + linebuf_ptr--; + } + + /* Handle section header. */ + if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') { + linebuf[strlen(linebuf) - 1] = '\0'; + linebuf_ptr = &linebuf[1]; + + /* If a section was open, close it. */ + if (currsection != NULL) { + lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND); + if (lcpvret < 0) { +#ifdef DEBUG + fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection); +#endif + } + free(currsection); + } + + /* Open new section. */ + currsection = strdup(linebuf_ptr); + lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONSTART); + if (lcpvret < 0) { +#ifdef DEBUG + fprintf(stderr, "Invalid section: \"%s\"\n", currsection); +#endif + invalid_section = 1; + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVSECTION; + retval = -1; + } else { + invalid_section = 0; + ignore_section = 0; + } + + if (lcpvret == LC_CBRET_IGNORESECTION) { + ignore_section = 1; + } + continue; + } + + /* Remove leading spaces. */ + linebuf_ptr = &linebuf[0]; + while (*linebuf_ptr == ' ') { + linebuf_ptr++; + } + + /* Drop comments and blank lines. */ + if (*linebuf_ptr == ';' || *linebuf_ptr == '\0') { + continue; + } + + /* Don't handle things for a section that doesn't exist. */ + if (invalid_section == 1) { +#ifdef DEBUG + fprintf(stderr, "Ignoring line (because invalid section): %s\n", linebuf); +#endif + continue; + } + + /* Don't process commands if this section is specifically ignored. */ + if (ignore_section == 1) { +#ifdef DEBUG + fprintf(stderr, "Ignoring line (because ignored section): %s\n", linebuf); +#endif + continue; + } + + /* Find the command and the data in the line. */ + cmdend = sep = strpbrk(linebuf_ptr, "="); + if (sep == NULL) { +#ifdef DEBUG + fprintf(stderr, "Invalid line: \"%s\"\n", linebuf); +#endif + continue; + } + + /* Delete space at the end of the command. */ + cmdend--; /* It currently derefs to the seperator.. */ + while (*cmdend <= ' ') { + *cmdend = '\0'; + cmdend--; + } + + cmd = linebuf_ptr; + + /* Delete the seperator char and any leading space. */ + *sep = '\0'; + sep++; + while (*sep == ' ' || *sep == '\t') { + sep++; + } + value = sep; + + /* Create the fully qualified variable name. */ + if (currsection == NULL) { + strncpy(qualifbuf, cmd, sizeof(qualifbuf) - 1); + } else { + snprintf(qualifbuf, sizeof(qualifbuf) - 1, "%s.%s", currsection, cmd); + } + + /* Call the parent and tell them we have data. */ + save_lc_errno = lc_errno; + lc_errno = LC_ERR_NONE; + lcpvret = lc_process_var(qualifbuf, NULL, value, LC_FLAGS_VAR); + if (lcpvret < 0) { + if (lc_errno == LC_ERR_NONE) { +#ifdef DEBUG + fprintf(stderr, "Invalid command: \"%s\"\n", cmd); +#endif + lc_errno = LC_ERR_INVCMD; + } else { +#ifdef DEBUG + fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n"); +#endif + } + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + retval = -1; + } else { + lc_errno = save_lc_errno; + } + } + + /* Close any open section, and clean-up. */ + if (currsection != NULL) { + lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND); + if (lcpvret < 0) { +#ifdef DEBUG + fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection); +#endif + } + free(currsection); + } + + lc_fclose(configfp); + + return(retval); +} diff --git a/src/libconfig/conf_section.h b/src/libconfig/conf_section.h new file mode 100644 index 00000000..1d1a94c9 --- /dev/null +++ b/src/libconfig/conf_section.h @@ -0,0 +1,8 @@ +#ifndef LC_CONF_SECTION_H +#define LC_CONF_SECTION_H +#include "libconfig.h" +#include "libconfig_private.h" + +int lc_process_conf_section(const char *appname, const char *configfile); + +#endif diff --git a/src/libconfig/conf_space.c b/src/libconfig/conf_space.c new file mode 100644 index 00000000..50a9b23d --- /dev/null +++ b/src/libconfig/conf_space.c @@ -0,0 +1,109 @@ +#include "compat.h" +#include "libconfig.h" +#include "libconfig_private.h" +#include "conf_space.h" + +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +int lc_process_conf_space(const char *appname, const char *configfile) { + LC_FILE *configfp = NULL; + const char *local_lc_errfile; + char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL; + char *cmd = NULL, *value = NULL, *sep = NULL; + char *fgetsret = NULL; + int local_lc_errline; + int lcpvret = -1; + int retval = 0; + lc_err_t save_lc_errno = LC_ERR_NONE; + + local_lc_errfile = configfile; + local_lc_errline = 0; + + if (appname == NULL || configfile == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVDATA; + return(-1); + } + + configfp = lc_fopen(configfile, "r"); + + if (configfp == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_CANTOPEN; + return(-1); + } + + while (1) { + fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp); + if (fgetsret == NULL) { + break; + } + if (lc_feof(configfp)) { + break; + } + + local_lc_errline++; + + linebuf_ptr = &linebuf[strlen(linebuf) - 1]; + while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) { + *linebuf_ptr = '\0'; + linebuf_ptr--; + } + + linebuf_ptr = &linebuf[0]; + while (*linebuf_ptr == ' ') { + linebuf_ptr++; + } + + if (*linebuf_ptr == '#' || *linebuf_ptr == '\0') { + continue; + } + + + sep = strpbrk(linebuf_ptr, " \t"); + cmd = linebuf_ptr; + if (sep != NULL) { + *sep = '\0'; + sep++; + while (*sep == ' ' || *sep == '\t') { + sep++; + } + value = sep; + } else { + value = NULL; + } + + save_lc_errno = lc_errno; + lc_errno = LC_ERR_NONE; + lcpvret = lc_process_var(cmd, NULL, value, LC_FLAGS_VAR); + if (lcpvret < 0) { + if (lc_errno == LC_ERR_NONE) { +#ifdef DEBUG + fprintf(stderr, "Invalid command: \"%s\"\n", cmd); +#endif + lc_errno = LC_ERR_INVCMD; + } else { +#ifdef DEBUG + fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n"); +#endif + } + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + retval = -1; + } else { + lc_errno = save_lc_errno; + } + } + + lc_fclose(configfp); + + return(retval); +} diff --git a/src/libconfig/conf_space.h b/src/libconfig/conf_space.h new file mode 100644 index 00000000..6cf0462c --- /dev/null +++ b/src/libconfig/conf_space.h @@ -0,0 +1,8 @@ +#ifndef LC_CONF_SPACE_H +#define LC_CONF_SPACE_H +#include "libconfig.h" +#include "libconfig_private.h" + +int lc_process_conf_space(const char *appname, const char *configfile); + +#endif diff --git a/src/libconfig/conf_xml.c b/src/libconfig/conf_xml.c new file mode 100644 index 00000000..85edd519 --- /dev/null +++ b/src/libconfig/conf_xml.c @@ -0,0 +1,7 @@ +#include "libconfig.h" +#include "libconfig_private.h" +#include "conf_xml.h" + +int lc_process_conf_xml(const char *appname, const char *configfile) { + return(-1); +} diff --git a/src/libconfig/conf_xml.h b/src/libconfig/conf_xml.h new file mode 100644 index 00000000..f0deffbc --- /dev/null +++ b/src/libconfig/conf_xml.h @@ -0,0 +1,8 @@ +#ifndef LC_CONF_XML_H +#define LC_CONF_XML_H +#include "libconfig.h" +#include "libconfig_private.h" + +int lc_process_conf_xml(const char *appname, const char *configfile); + +#endif diff --git a/src/libconfig/getuid.c b/src/libconfig/getuid.c new file mode 100644 index 00000000..d6e17c72 --- /dev/null +++ b/src/libconfig/getuid.c @@ -0,0 +1,5 @@ +#include "getuid.h" + +uid_t getuid(void) { + return(0); +} diff --git a/src/libconfig/getuid.h b/src/libconfig/getuid.h new file mode 100644 index 00000000..77745c71 --- /dev/null +++ b/src/libconfig/getuid.h @@ -0,0 +1,8 @@ +#ifndef _LC_GETUID_H +#define _LC_GETUID_H + +typedef int uid_t; + +uid_t getuid(void); + +#endif diff --git a/src/libconfig/libconfig.c b/src/libconfig/libconfig.c new file mode 100644 index 00000000..9f80a768 --- /dev/null +++ b/src/libconfig/libconfig.c @@ -0,0 +1,1073 @@ +#include "compat.h" +#include "libconfig.h" +#include "libconfig_private.h" +#include "conf_section.h" +#include "conf_apache.h" +#include "conf_colon.h" +#include "conf_equal.h" +#include "conf_space.h" +#include "conf_xml.h" + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_CTYPE_H +#include +#endif + +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_PWD_H +#include +#endif + +struct lc_varhandler_st *varhandlers = NULL; +lc_err_t lc_errno = LC_ERR_NONE; +const char *lc_errfile = NULL; +int lc_optind = 0; +int lc_errline = 0; + +extern char **environ; + +static int lc_process_var_string(void *data, const char *value, const char **endptr) { + char **dataval; + + dataval = data; + *dataval = strdup(value); + + *endptr = NULL; + + return(0); +} + +static int lc_process_var_cidr(void *data, const char *value, const char **endptr) { + return(-1); +} + +static int lc_process_var_hostname6(void *data, const char *value, const char **endptr) { + return(-1); +} + +static int lc_process_var_hostname4(void *data, const char *value, const char **endptr) { + return(-1); +} + +static int lc_process_var_ip6(void *data, const char *value, const char **endptr) { + return(-1); +} + +static int lc_process_var_ip4(void *data, const char *value, const char **endptr) { + uint32_t *dataval, retval = 0; + const char *dotptr = NULL; + int tmpval = -1; +// int dotcount + + dataval = data; + + dotptr = value; + + while (1) { + tmpval = atoi(dotptr); + if (tmpval < 0) { + break; + } + + retval <<= 8; + retval |= tmpval; + + dotptr = strpbrk(dotptr, "./ \t"); + if (dotptr == NULL) { + break; + } + if (*dotptr != '.') { + break; + } + dotptr++; + } + + *dataval = retval; + + *endptr = (char *) dotptr; + + return(0); +} + +static int lc_process_var_longlong(void *data, const char *value, const char **endptr) { + long long *dataval; + + dataval = data; + *dataval = strtoll(value, (char **) endptr, 10); + + return(0); +} + +static int lc_process_var_long(void *data, const char *value, const char **endptr) { + long *dataval; + + dataval = data; + *dataval = strtoll(value, (char **) endptr, 10); + + return(0); +} + +static int lc_process_var_int(void *data, const char *value, const char **endptr) { + int *dataval; + + dataval = data; + *dataval = strtoll(value, (char **) endptr, 10); + + return(0); +} + +static int lc_process_var_short(void *data, const char *value, const char **endptr) { + short *dataval; + + dataval = data; + *dataval = strtoll(value, (char **) endptr, 10); + + return(0); +} + +static int lc_process_var_bool_byexistance(void *data, const char *value, const char **endptr) { + int *dataval; + + dataval = data; + + *dataval = 1; + + *endptr = NULL; + + return(0); +} + +static int lc_process_var_bool(void *data, const char *value, const char **endptr) { + char *trueval[] = {"enable", "true", "yes", "on", "y", "1"}; + char *falseval[] = {"disable", "false", "no", "off", "n", "0"}; + size_t chkvallen, vallen; + int *dataval; + int i; + + dataval = data; + + *dataval = -1; + + vallen = strlen(value); + + for (i = 0; i < (sizeof(trueval) / sizeof(*trueval)); i++) { + chkvallen = strlen(trueval[i]); + + /* + * Skip if there's no way we could find a match here. + */ + if (chkvallen > vallen) { + continue; + } + + /* + * Skip if there is no partial match. + */ + if (strncasecmp(value, trueval[i], chkvallen) != 0) { + continue; + } + + if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \ + value[chkvallen] == ' ') { + /* Declare a winner and set the next token. */ + *endptr = value + chkvallen; + *dataval = 1; + return(0); + } + } + + for (i = 0; i < (sizeof(falseval) / sizeof(*falseval)); i++) { + chkvallen = strlen(falseval[i]); + + /* + * Skip if there's no way we could find a match here. + */ + if (chkvallen > vallen) { + continue; + } + + /* + * Skip if there is no partial match. + */ + if (strncasecmp(value, falseval[i], chkvallen) != 0) { + continue; + } + + if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \ + value[chkvallen] == ' ') { + /* Declare a winner and set the next token. */ + *endptr = value + chkvallen; + *dataval = 0; + return(0); + } + } + + lc_errno = LC_ERR_BADFORMAT; + return(-1); +} + +static unsigned long long lc_process_size(const char *value, const char **endptr) { + unsigned long long retval = 0; + char *mult = NULL; + + retval = strtoll(value, &mult, 10); + if (mult != NULL) { + switch (tolower(mult[0])) { + case 'p': + retval *= 1125899906842624LLU; + break; + case 't': + retval *= 1958505086976LLU; + break; + case 'g': + retval *= 1073741824; + break; + case 'm': + retval *= 1048576; + break; + case 'k': + retval *= 1024; + break; + default: + break; + } + } + + return(retval); +} + +static int lc_process_var_sizelonglong(void *data, const char *value, const char **endptr) { + long long *dataval; + + dataval = data; + *dataval = lc_process_size(value, endptr); + + return(0); +} + +static int lc_process_var_sizelong(void *data, const char *value, const char **endptr) { + long *dataval; + + dataval = data; + *dataval = lc_process_size(value, endptr); + + return(0); +} + +static int lc_process_var_sizeint(void *data, const char *value, const char **endptr) { + int *dataval; + + dataval = data; + *dataval = lc_process_size(value, endptr); + + return(0); +} + +static int lc_process_var_sizeshort(void *data, const char *value, const char **endptr) { + short *dataval; + + dataval = data; + *dataval = lc_process_size(value, endptr); + + return(0); +} + +static int lc_process_var_sizesizet(void *data, const char *value, const char **endptr) { + size_t *dataval; + + dataval = data; + *dataval = lc_process_size(value, endptr); + + return(0); +} + + +static int lc_handle_type(lc_var_type_t type, const char *value, void *data) { + const char *next; + int is_list; + + is_list = type & LC_VAR_LIST; + + if (is_list == LC_VAR_LIST) { + } + + switch (type) { + case LC_VAR_STRING: + return(lc_process_var_string(data, value, &next)); + break; + case LC_VAR_LONG_LONG: + return(lc_process_var_longlong(data, value, &next)); + break; + case LC_VAR_LONG: + return(lc_process_var_long(data, value, &next)); + break; + case LC_VAR_INT: + return(lc_process_var_int(data, value, &next)); + break; + case LC_VAR_SHORT: + return(lc_process_var_short(data, value, &next)); + break; + case LC_VAR_BOOL: + return(lc_process_var_bool(data, value, &next)); + break; + case LC_VAR_SIZE_LONG_LONG: + return(lc_process_var_sizelonglong(data, value, &next)); + break; + case LC_VAR_SIZE_LONG: + return(lc_process_var_sizelong(data, value, &next)); + break; + case LC_VAR_SIZE_INT: + return(lc_process_var_sizeint(data, value, &next)); + break; + case LC_VAR_SIZE_SHORT: + return(lc_process_var_sizeshort(data, value, &next)); + break; + case LC_VAR_BOOL_BY_EXISTANCE: + return(lc_process_var_bool_byexistance(data, value, &next)); + break; + case LC_VAR_SIZE_SIZE_T: + return(lc_process_var_sizesizet(data, value, &next)); + break; + case LC_VAR_IP: + case LC_VAR_IP4: + return(lc_process_var_ip4(data, value, &next)); + break; + case LC_VAR_IP6: + return(lc_process_var_ip6(data, value, &next)); + break; + case LC_VAR_HOSTNAME4: + return(lc_process_var_hostname4(data, value, &next)); + break; + case LC_VAR_HOSTNAME6: + return(lc_process_var_hostname6(data, value, &next)); + break; + case LC_VAR_CIDR: + return(lc_process_var_cidr(data, value, &next)); + break; + case LC_VAR_TIME: + case LC_VAR_DATE: + case LC_VAR_FILENAME: + case LC_VAR_DIRECTORY: +#ifdef DEBUG + fprintf(stderr, "Not implemented yet!\n"); +#endif + return(-1); + case LC_VAR_NONE: + case LC_VAR_UNKNOWN: + case LC_VAR_SECTION: + case LC_VAR_SECTIONSTART: + case LC_VAR_SECTIONEND: + return(0); + break; + } + + return(-1); +} + +static int lc_handle(struct lc_varhandler_st *handler, const char *var, const char *varargs, const char *value, lc_flags_t flags) { + const char *localvar = NULL; + int retval; + + if (var != NULL) { + localvar = strrchr(var, '.'); + if (localvar == NULL) { + localvar = var; + } else { + localvar++; + } + } else { + localvar = NULL; + } + + switch (handler->mode) { + case LC_MODE_CALLBACK: + if (handler->callback != NULL) { + retval = handler->callback(localvar, var, varargs, value, flags, handler->extra); + if (retval < 0) { + lc_errno = LC_ERR_CALLBACK; + } + return(retval); + } + break; + case LC_MODE_VAR: + return(lc_handle_type(handler->type, value, handler->data)); + break; + } + + return(-1); +} + +static int lc_process_environment(const char *appname) { +#ifndef ENABLE_SMALL + struct lc_varhandler_st *handler = NULL; + size_t appnamelen = 0; + char varnamebuf[128] = {0}; + char **currvar; + char *sep = NULL, *value = NULL, *cmd = NULL; + char *ucase_appname = NULL, *ucase_appname_itr = NULL; + char *lastcomponent_handler = NULL; + int varnamelen = 0; + char *local_lc_errfile; + int local_lc_errline; + + /* Make sure we have an environment to screw with, if not, + no arguments were found to be in error */ + if (environ == NULL || appname == NULL) { + return(0); + } + + local_lc_errfile = ""; + local_lc_errline = 0; + + /* Allocate and create our uppercase appname. */ + ucase_appname = strdup(appname); + if (ucase_appname == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_ENOMEM; + return(-1); + } + for (ucase_appname_itr = ucase_appname; *ucase_appname_itr != '\0'; ucase_appname_itr++) { + *ucase_appname_itr = toupper(*ucase_appname_itr); + } + + appnamelen = strlen(ucase_appname); + + for (currvar = environ; *currvar != NULL; currvar++) { + /* If it doesn't begin with our appname ignore it completely. */ + if (strncmp(*currvar, ucase_appname, appnamelen) != 0) { + continue; + } + + /* Find our seperator. */ + sep = strchr(*currvar, '='); + if (sep == NULL) { + continue; + } + + varnamelen = sep - *currvar; + + /* Skip variables that would overflow our buffer. */ + if (varnamelen >= sizeof(varnamebuf)) { + continue; + } + + strncpy(varnamebuf, *currvar, varnamelen); + + varnamebuf[varnamelen] = '\0'; + value = sep + 1; + + /* We ignore APPNAME by itself. */ + if (strlen(varnamebuf) <= appnamelen) { + continue; + } + + /* Further it must be _ */ + if (varnamebuf[appnamelen] != '_') { + continue; + } + + cmd = varnamebuf + appnamelen + 1; + + /* We don't allow section specifiers, for reasons see notes in + the cmdline processor (below). */ + if (strchr(cmd, '.') != NULL) { + continue; + } + + for (handler = varhandlers; handler != NULL; handler = handler->_next) { + if (handler->var == NULL) { + continue; + } + + /* Skip handlers which don't agree with being + processed outside a config file */ + if (handler->type == LC_VAR_SECTION || + handler->type == LC_VAR_SECTIONSTART || + handler->type == LC_VAR_SECTIONEND || + handler->type == LC_VAR_UNKNOWN) { + continue; + } + + /* Find the last part of the variable and compare it with + the option being processed, if a wildcard is given. */ + if (handler->var[0] == '*' && handler->var[1] == '.') { + lastcomponent_handler = strrchr(handler->var, '.'); + if (lastcomponent_handler == NULL) { + lastcomponent_handler = handler->var; + } else { + lastcomponent_handler++; + } + } else { + lastcomponent_handler = handler->var; + } + + /* Ignore this handler if they don't match. */ + if (strcasecmp(lastcomponent_handler, cmd) != 0) { + continue; + } + + if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) { + value = NULL; + } + + /* We ignore errors from the environment variables, + they're mostly insignificant. */ + lc_handle(handler, cmd, NULL, value, LC_FLAGS_ENVIRON); + + break; + } + } + + free(ucase_appname); + +#endif + return(0); +} + +static int lc_process_cmdline(int argc, char **argv) { + struct lc_varhandler_st *handler = NULL; + char *cmdarg = NULL, *cmdoptarg = NULL; + char *lastcomponent_handler = NULL; + char **newargv = NULL; + char *usedargv = NULL; + int cmdargidx = 0; + int newargvidx = 0; + int retval = 0, chkretval = 0; + int ch = 0; + char *local_lc_errfile; + int local_lc_errline; + + local_lc_errfile = ""; + local_lc_errline = 0; + + /* Allocate "argc + 1" (+1 for the NULL terminator) elements. */ + newargv = malloc((argc + 1) * sizeof(*newargv)); + if (newargv == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_ENOMEM; + return(-1); + } + newargv[newargvidx++] = argv[0]; + newargv[argc] = NULL; + + /* Allocate space to indicate which arguments have been used. */ + usedargv = malloc(argc * sizeof(*usedargv)); + if (usedargv == NULL) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_ENOMEM; + free(newargv); + return(-1); + } + for (cmdargidx = 0; cmdargidx < argc; cmdargidx++) { + usedargv[cmdargidx] = 0; + } + + for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) { + cmdarg = argv[cmdargidx]; + + /* Make sure we have an argument here. */ + if (cmdarg == NULL) { + break; + } + + /* If the argument isn't an option, skip. */ + if (cmdarg[0] != '-') { + continue; + } + + /* Setup a pointer in the new array for the actual argument. */ + newargv[newargvidx++] = cmdarg; + usedargv[cmdargidx] = 1; + + /* Then shift the argument past the '-' so we can ignore it. */ + cmdarg++; + + /* Handle long options. */ + if (cmdarg[0] == '-') { + cmdarg++; + + /* Don't process arguments after the '--' option. */ + if (cmdarg[0] == '\0') { + break; + } + + /* Look for a variable name that matches */ + for (handler = varhandlers; handler != NULL; handler = handler->_next) { + /* Skip handlers with no variable name. */ + if (handler->var == NULL) { + continue; + } + /* Skip handlers which don't agree with being + processed on the command line. */ + if (handler->type == LC_VAR_SECTION || + handler->type == LC_VAR_SECTIONSTART || + handler->type == LC_VAR_SECTIONEND || + handler->type == LC_VAR_UNKNOWN) { + continue; + } + + /* Find the last part of the variable and compare it with + the option being processed, if a wildcard is given. */ + if (handler->var[0] == '*' && handler->var[1] == '.') { + lastcomponent_handler = strrchr(handler->var, '.'); + if (lastcomponent_handler == NULL) { + lastcomponent_handler = handler->var; + } else { + lastcomponent_handler++; + } + } else { + /* Disallow use of the fully qualified name + since there was no sectionstart portion + we cannot allow it to handle children of it. */ + if (strchr(cmdarg, '.') != NULL) { + continue; + } + lastcomponent_handler = handler->var; + } + + /* Ignore this handler if they don't match. */ + if (strcasecmp(lastcomponent_handler, cmdarg) != 0) { + continue; + } + + if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) { + cmdoptarg = NULL; + } else { + cmdargidx++; + if (cmdargidx >= argc) { + fprintf(stderr, "Argument required.\n"); + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_BADFORMAT; + free(usedargv); + free(newargv); + return(-1); + } + cmdoptarg = argv[cmdargidx]; + newargv[newargvidx++] = cmdoptarg; + usedargv[cmdargidx] = 1; + } + + chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE); + if (chkretval < 0) { + retval = -1; + } + + break; + } + + if (handler == NULL) { + fprintf(stderr, "Unknown option: --%s\n", cmdarg); + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVCMD; + free(usedargv); + free(newargv); + return(-1); + } + } else { + for (; *cmdarg != '\0'; cmdarg++) { + ch = *cmdarg; + + for (handler = varhandlers; handler != NULL; handler = handler->_next) { + if (handler->opt != ch || handler->opt == '\0') { + continue; + } + /* Skip handlers which don't agree with being + processed on the command line. */ + if (handler->type == LC_VAR_SECTION || + handler->type == LC_VAR_SECTIONSTART || + handler->type == LC_VAR_SECTIONEND || + handler->type == LC_VAR_UNKNOWN) { + continue; + } + + if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) { + cmdoptarg = NULL; + } else { + cmdargidx++; + if (cmdargidx >= argc) { + fprintf(stderr, "Argument required.\n"); + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_BADFORMAT; + free(usedargv); + free(newargv); + return(-1); + } + cmdoptarg = argv[cmdargidx]; + newargv[newargvidx++] = cmdoptarg; + usedargv[cmdargidx] = 1; + } + + chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE); + if (chkretval < 0) { + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + retval = -1; + } + + break; + } + + if (handler == NULL) { + fprintf(stderr, "Unknown option: -%c\n", ch); + lc_errfile = local_lc_errfile; + lc_errline = local_lc_errline; + lc_errno = LC_ERR_INVCMD; + free(usedargv); + free(newargv); + return(-1); + } + } + } + } + + if (retval >= 0) { + lc_optind = newargvidx; + for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) { + if (usedargv[cmdargidx] != 0) { + continue; + } + + cmdarg = argv[cmdargidx]; + + newargv[newargvidx++] = cmdarg; + } + for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) { + argv[cmdargidx] = newargv[cmdargidx]; + } + } + + free(usedargv); + free(newargv); + + return(retval); +} + + +int lc_process_var(const char *var, const char *varargs, const char *value, lc_flags_t flags) { + struct lc_varhandler_st *handler = NULL; + const char *lastcomponent_handler = NULL, *lastcomponent_var = NULL; + + lastcomponent_var = strrchr(var, '.'); + if (lastcomponent_var == NULL) { + lastcomponent_var = var; + } else { + lastcomponent_var++; + } + + for (handler = varhandlers; handler != NULL; handler = handler->_next) { + /* If either handler->var or var is NULL, skip, unless both are NULL. */ + if (handler->var != var && (handler->var == NULL || var == NULL)) { + continue; + } + + /* If both are not-NULL, compare them. */ + if (handler->var != NULL) { + /* Wild-card-ish match. */ + if (handler->var[0] == '*' && handler->var[1] == '.') { + /* Only compare the last components */ + + lastcomponent_handler = strrchr(handler->var, '.') + 1; /* strrchr() won't return NULL, because we already checked it. */ + + if (strcasecmp(lastcomponent_handler, lastcomponent_var) != 0) { + continue; + } + } else if (strcasecmp(handler->var, var) != 0) { + /* Exact (case-insensitive comparison) failed. */ + continue; + } + } + + if (value == NULL && + handler->type != LC_VAR_NONE && + handler->type != LC_VAR_BOOL_BY_EXISTANCE && + handler->type != LC_VAR_SECTION && + handler->type != LC_VAR_SECTIONSTART && + handler->type != LC_VAR_SECTIONEND) { + lc_errno = LC_ERR_BADFORMAT; + break; + } + + return(lc_handle(handler, var, varargs, value, flags)); + } + + return(-1); +} + +int lc_register_callback(const char *var, char opt, lc_var_type_t type, int (*callback)(const char *, const char *, const char *, const char *, lc_flags_t, void *), void *extra) { + struct lc_varhandler_st *newhandler = NULL; + + newhandler = malloc(sizeof(*newhandler)); + + if (newhandler == NULL) { + return(-1); + } + + if (var == NULL) { + newhandler->var = NULL; + } else { + newhandler->var = strdup(var); + } + newhandler->mode = LC_MODE_CALLBACK; + newhandler->type = type; + newhandler->callback = callback; + newhandler->opt = opt; + newhandler->extra = extra; + newhandler->_next = varhandlers; + + varhandlers = newhandler; + + return(0); +} + +int lc_register_var(const char *var, lc_var_type_t type, void *data, char opt) { + struct lc_varhandler_st *newhandler = NULL; + + newhandler = malloc(sizeof(*newhandler)); + + if (newhandler == NULL) { + return(-1); + } + + if (var == NULL) { + newhandler->var = NULL; + } else { + newhandler->var = strdup(var); + } + newhandler->mode = LC_MODE_VAR; + newhandler->type = type; + newhandler->data = data; + newhandler->opt = opt; + newhandler->extra = NULL; + newhandler->_next = varhandlers; + + varhandlers = newhandler; + + return(0); +} + +int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type) { + int chkretval = 0; + + switch (type) { + case LC_CONF_SECTION: + chkretval = lc_process_conf_section(appname, pathname); + break; + case LC_CONF_APACHE: + chkretval = lc_process_conf_apache(appname, pathname); + break; + case LC_CONF_COLON: + chkretval = lc_process_conf_colon(appname, pathname); + break; + case LC_CONF_EQUAL: + chkretval = lc_process_conf_equal(appname, pathname); + break; + case LC_CONF_SPACE: + chkretval = lc_process_conf_space(appname, pathname); + break; + case LC_CONF_XML: + chkretval = lc_process_conf_xml(appname, pathname); + break; + default: + chkretval = -1; + lc_errno = LC_ERR_INVDATA; + break; + } + + return(chkretval); +} + +static int lc_process_files(const char *appname, lc_conf_type_t type, const char *extraconfig) { +#ifdef HAVE_GETPWUID + struct passwd *pwinfo = NULL; +#endif + char configfiles[3][13][512] = {{{0}}}; + char *configfile = NULL; + char *homedir = NULL; + int configsetidx = 0, configidx = 0; + int chkretval = 0, retval = 0; + + if (extraconfig != NULL) { + snprintf(configfiles[0][0], sizeof(**configfiles) - 1, "%s", extraconfig); + } + snprintf(configfiles[1][0], sizeof(**configfiles) - 1, "/etc/%s.cfg", appname); + snprintf(configfiles[1][1], sizeof(**configfiles) - 1, "/etc/%s.conf", appname); + snprintf(configfiles[1][2], sizeof(**configfiles) - 1, "/etc/%s/%s.cfg", appname, appname); + snprintf(configfiles[1][3], sizeof(**configfiles) - 1, "/etc/%s/%s.conf", appname, appname); + snprintf(configfiles[1][4], sizeof(**configfiles) - 1, "/usr/etc/%s.cfg", appname); + snprintf(configfiles[1][5], sizeof(**configfiles) - 1, "/usr/etc/%s.conf", appname); + snprintf(configfiles[1][6], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.cfg", appname, appname); + snprintf(configfiles[1][7], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.conf", appname, appname); + snprintf(configfiles[1][8], sizeof(**configfiles) - 1, "/usr/local/etc/%s.cfg", appname); + snprintf(configfiles[1][9], sizeof(**configfiles) - 1, "/usr/local/etc/%s.conf", appname); + snprintf(configfiles[1][10], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.cfg", appname, appname); + snprintf(configfiles[1][11], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.conf", appname, appname); + if (getuid() != 0) { + homedir = getenv("HOME"); +#ifdef HAVE_GETPWUID + if (homedir == NULL) { + pwinfo = getpwuid(getuid()); + if (pwinfo != NULL) { + homedir = pwinfo->pw_dir; + } + } +#endif + if (homedir != NULL) { + if (strcmp(homedir, "/") != 0 && access(homedir, R_OK|W_OK|X_OK) == 0) { + snprintf(configfiles[2][0], sizeof(**configfiles) - 1, "%s/.%src", homedir, appname); + snprintf(configfiles[2][1], sizeof(**configfiles) - 1, "%s/.%s.cfg", homedir, appname); + snprintf(configfiles[2][2], sizeof(**configfiles) - 1, "%s/.%s.conf", homedir, appname); + snprintf(configfiles[2][3], sizeof(**configfiles) - 1, "%s/.%s/%s.cfg", homedir, appname, appname); + snprintf(configfiles[2][4], sizeof(**configfiles) - 1, "%s/.%s/%s.conf", homedir, appname, appname); + snprintf(configfiles[2][5], sizeof(**configfiles) - 1, "%s/.%s/config", homedir, appname); + } + } + } + + for (configsetidx = 0; configsetidx < 3; configsetidx++) { + for (configidx = 0; configidx < 13; configidx++) { + configfile = configfiles[configsetidx][configidx]; + if (configfile[0] == '\0') { + break; + } + if (access(configfile, R_OK) == 0) { + chkretval = lc_process_file(appname, configfile, type); + if (chkretval < 0) { + retval = -1; + } + break; + } + } + } + + return(retval); +} + +void lc_cleanup(void) { + struct lc_varhandler_st *handler = NULL, *next = NULL; + + handler = varhandlers; + while (handler != NULL) { + if (handler->var != NULL) { + free(handler->var); + } + + next = handler->_next; + + free(handler); + + handler = next; + } + + varhandlers = NULL; + + return; +} + +int lc_process(int argc, char **argv, const char *appname, lc_conf_type_t type, const char *extra) { + int retval = 0, chkretval = 0; + + /* Handle config files. */ + chkretval = lc_process_files(appname, type, extra); + if (chkretval < 0) { + retval = -1; + } + + /* Handle environment variables.*/ + chkretval = lc_process_environment(appname); + if (chkretval < 0) { + retval = -1; + } + + /* Handle command line arguments */ + chkretval = lc_process_cmdline(argc, argv); + if (chkretval < 0) { + retval = -1; + } + + return(retval); +} + + +lc_err_t lc_geterrno(void) { + lc_err_t retval; + + retval = lc_errno; + + lc_errno = LC_ERR_NONE; + + return(retval); +} + +char *lc_geterrstr(void) { + static char retval[512]; + char *errmsg = NULL; + + switch (lc_errno) { + case LC_ERR_NONE: + errmsg = "Success"; + break; + case LC_ERR_INVCMD: + errmsg = "Invalid command or option"; + break; + case LC_ERR_INVSECTION: + errmsg = "Invalid section"; + break; + case LC_ERR_INVDATA: + errmsg = "Invalid application data (internal error)"; + break; + case LC_ERR_BADFORMAT: + errmsg = "Bad data specified or incorrect format."; + break; + case LC_ERR_CANTOPEN: + errmsg = "Can't open file."; + break; + case LC_ERR_CALLBACK: + errmsg = "Error return from application handler."; + break; + case LC_ERR_ENOMEM: + errmsg = "Insuffcient memory."; + break; + } + + /* + * This is not part of the switch statement so we will get warnings + * about unhandled enum values. + */ + if (errmsg == NULL) { + errmsg = "Unknown error"; + } + + if (lc_errfile == NULL) { + snprintf(retval, sizeof(retval), "%s:%i: %s", "", lc_errline, errmsg); + } else { + snprintf(retval, sizeof(retval), "%s:%i: %s", lc_errfile, lc_errline, errmsg); + } + + retval[sizeof(retval) - 1] = '\0'; + + return(retval); +} diff --git a/src/libconfig/libconfig.h b/src/libconfig/libconfig.h new file mode 100644 index 00000000..8c2f3619 --- /dev/null +++ b/src/libconfig/libconfig.h @@ -0,0 +1,84 @@ +# ifndef _RSK_LIBCONFIG_H +# define _RSK_LIBCONFIG_H +# ifdef __cplusplus +extern "C" { +# endif + +# define LC_VAR_LIST 0x80 + +typedef enum { + LC_CONF_SECTION, + LC_CONF_APACHE, + LC_CONF_COLON, + LC_CONF_EQUAL, + LC_CONF_SPACE, + LC_CONF_XML +} lc_conf_type_t; + +typedef enum { + LC_VAR_UNKNOWN, + LC_VAR_NONE, + LC_VAR_STRING, + LC_VAR_LONG_LONG, + LC_VAR_LONG, + LC_VAR_INT, + LC_VAR_SHORT, + LC_VAR_BOOL, + LC_VAR_FILENAME, + LC_VAR_DIRECTORY, + LC_VAR_SIZE_LONG_LONG, + LC_VAR_SIZE_LONG, + LC_VAR_SIZE_INT, + LC_VAR_SIZE_SHORT, + LC_VAR_TIME, + LC_VAR_DATE, + LC_VAR_SECTION, + LC_VAR_SECTIONSTART, + LC_VAR_SECTIONEND, + LC_VAR_BOOL_BY_EXISTANCE, + LC_VAR_SIZE_SIZE_T, + LC_VAR_CIDR, + LC_VAR_IP, + LC_VAR_IP4, + LC_VAR_IP6, + LC_VAR_HOSTNAME4, + LC_VAR_HOSTNAME6, +} lc_var_type_t; + +typedef enum { + LC_FLAGS_VAR, + LC_FLAGS_CMDLINE, + LC_FLAGS_ENVIRON, + LC_FLAGS_SECTIONSTART, + LC_FLAGS_SECTIONEND +} lc_flags_t; + +typedef enum { + LC_ERR_NONE, + LC_ERR_INVCMD, + LC_ERR_INVSECTION, + LC_ERR_INVDATA, + LC_ERR_BADFORMAT, + LC_ERR_CANTOPEN, + LC_ERR_CALLBACK, + LC_ERR_ENOMEM +} lc_err_t; + +int lc_process(int argc, char **argv, const char *appname, lc_conf_type_t type, const char *extra); +int lc_register_callback(const char *var, char opt, lc_var_type_t type, int (*callback)(const char *, const char *, const char *, const char *, lc_flags_t, void *), void *extra); +int lc_register_var(const char *var, lc_var_type_t type, void *data, char opt); +lc_err_t lc_geterrno(void); +char *lc_geterrstr(void); +int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type); +void lc_cleanup(void); + +# define LC_CBRET_IGNORESECTION (255) +# define LC_CBRET_OKAY (0) +# define LC_CBRET_ERROR (-1) + +extern int lc_optind; + +# ifdef __cplusplus +} +# endif +# endif diff --git a/src/libconfig/libconfig_private.h b/src/libconfig/libconfig_private.h new file mode 100644 index 00000000..8310a859 --- /dev/null +++ b/src/libconfig/libconfig_private.h @@ -0,0 +1,28 @@ +#ifndef _RSK_LIBCONFIG_PRIVATE_H +#define _RSK_LIBCONFIG_PRIVATE_H + +#include "libconfig.h" + +extern lc_err_t lc_errno; +extern int lc_errline; +extern const char *lc_errfile; + +int lc_process_var(const char *var, const char *varargs, const char *value, lc_flags_t flags); + +struct lc_varhandler_st; + +struct lc_varhandler_st { + struct lc_varhandler_st *_next; + char *var; + char opt; + lc_var_type_t type; + enum { + LC_MODE_CALLBACK, + LC_MODE_VAR + } mode; + int (*callback)(); + void *data; + void *extra; +}; + +#endif diff --git a/src/libconfig/strsep.c b/src/libconfig/strsep.c new file mode 100644 index 00000000..f82ea134 --- /dev/null +++ b/src/libconfig/strsep.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2001, 2002, and 2003 Roy Keene + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * email: libconfig@rkeene.org + */ + +/* Compliments of Jay Freeman */ + +#include +#include "strsep.h" + +char *strsep(char **stringp, const char *delim) { + char *ret = *stringp; + if (ret == NULL) return(NULL); /* grrr */ + if ((*stringp = strpbrk(*stringp, delim)) != NULL) { + *((*stringp)++) = '\0'; + } + return(ret); +} + diff --git a/src/libconfig/strsep.h b/src/libconfig/strsep.h new file mode 100644 index 00000000..3b375b39 --- /dev/null +++ b/src/libconfig/strsep.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2001, 2002, and 2003 Roy Keene + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * email: libconfig@rkeene.org + */ + +/* Compliments of Jay Freeman */ + +#ifndef _RSK_STRSEP_H +#define _RSK_STRSEP_H + +/* This is safe, because we're only included when there's no real strsep + available. */ +#define strsep(x,y) lc_strsep(x,y) + +char *strsep(char **stringp, const char *delim); + +#endif diff --git a/src/libconfig/strtoll.c b/src/libconfig/strtoll.c new file mode 100644 index 00000000..a98025a9 --- /dev/null +++ b/src/libconfig/strtoll.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +/* We only handle base 10. */ +long long int strtoll(const char *nptr, char **endptr, int base) { + long long int retval = 0; + const char **endptrd = (const char **) endptr; + const char *idx = NULL; + int allowspace = 1; + + idx = nptr; + while (1) { + if (*idx == '\0') { + break; + } + + if (!isdigit(*idx)) { + if (*idx == '-') { + retval *= -1; + continue; + } + if ((*idx == ' ' || *idx == '\t') && allowspace) { + continue; + } + break; + } + + retval *= 10; + retval += (*idx - '0'); + + allowspace = 0; + idx++; + } + + if (endptrd != NULL) { + *endptrd = idx; + } + + return(retval); +} diff --git a/src/libconfig/strtoll.h b/src/libconfig/strtoll.h new file mode 100644 index 00000000..79103033 --- /dev/null +++ b/src/libconfig/strtoll.h @@ -0,0 +1,6 @@ +#ifndef _RSK_STRTOLL_H +#define _RSK_STRTOLL_H + +long long int strtoll(const char *nptr, char **endptr, int base); + +#endif diff --git a/src/libconfig/test-lc.c b/src/libconfig/test-lc.c new file mode 100644 index 00000000..ed492d85 --- /dev/null +++ b/src/libconfig/test-lc.c @@ -0,0 +1,79 @@ +#include "compat.h" +#include "libconfig.h" + +int help_cmd(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) { + printf("Usage info goes here\n"); + printf("\n"); + + exit(EXIT_FAILURE); +} +int sally_cmd(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) { + fprintf(stderr, "%s sets value: \"%s\" (flags=%i)\n", arg, val, flags); + return(0); +} + +int cmd_ifmodule(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) { + if (flags == LC_FLAGS_SECTIONEND) { + return(LC_CBRET_OKAY); + } + if (flags != LC_FLAGS_SECTIONSTART) { + fprintf(stderr, "IfModule can only be used as a section.\n"); + return(LC_CBRET_ERROR); + } + if (argarg == NULL) { + fprintf(stderr, "You must specify an argument to IfModule.\n"); + return(LC_CBRET_ERROR); + } + + fprintf(stderr, "IfModule (%s)\n", argarg); + return(LC_CBRET_IGNORESECTION); +} + +int main(int argc, char **argv) { + char *joeval = NULL; + size_t xval = -1; + int onoff = -1; + int lcpret = -1; + int i = 0; + int onoff2 = 0; + uint32_t ipaddr = 0; + + lc_register_var("Section", LC_VAR_SECTION, NULL, 0); + lc_register_var("Somesection", LC_VAR_SECTION, NULL, 0); + lc_register_var("Section.Test", LC_VAR_STRING, &joeval, 'j'); + lc_register_var("bob", LC_VAR_SIZE_SIZE_T, &xval, 's'); + lc_register_var("Somesection.Free", LC_VAR_BOOL, &onoff, 0); + lc_register_var("long", LC_VAR_BOOL_BY_EXISTANCE, &onoff2, 'l'); + lc_register_var("ipaddr", LC_VAR_IP, &ipaddr, 'i'); + lc_register_callback("sally", 0, LC_VAR_STRING, sally_cmd, NULL); + lc_register_callback("HELP", 'h', LC_VAR_NONE, help_cmd, NULL); + lc_register_callback("*.ifmodule", 0, LC_VAR_NONE, cmd_ifmodule, NULL); + lcpret = lc_process_file("testapp", "build/test.conf", LC_CONF_APACHE); + if (lcpret < 0) { + fprintf(stderr, "Error processing config file: %s\n", lc_geterrstr()); + return(EXIT_FAILURE); + } + + lcpret = lc_process(argc, argv, "testapp", LC_CONF_APACHE, "test.cfg"); + if (lcpret < 0) { + fprintf(stderr, "Error processing config file: %s\n", lc_geterrstr()); + return(EXIT_FAILURE); + } + + lc_cleanup(); + + if (joeval != NULL) { + fprintf(stderr, "joeval = \"%s\"\n", joeval); + } else { + fprintf(stderr, "joeval = \"(null)\"\n"); + } + fprintf(stderr, "xval = %llu\n", (unsigned long long) xval); + fprintf(stderr, "onoff = %i\n", onoff); + fprintf(stderr, "long = %i\n", onoff2); + fprintf(stderr, "ip = %08lx\n", (unsigned long) ipaddr); + for (i = lc_optind; i < argc; i++) { + fprintf(stderr, "argv[%i] = \"%s\"\n", i, argv[i]); + } + + return(0); +} diff --git a/src/libconfig/win32.h b/src/libconfig/win32.h new file mode 100644 index 00000000..06f3a0dc --- /dev/null +++ b/src/libconfig/win32.h @@ -0,0 +1,44 @@ +#if !defined(_LOCAL_WIN32_H) && defined(__WIN32__) && !defined(__CYGWIN__) +#define _LOCAL_WIN32_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef __MINGW32__ + /* MingW32 specific stuff here. */ +# if defined(HAVE_WINSOCK2_H) && defined(HAVE_LIBWSOCK32) + /* We have to override the detected configuration + because it can't detect the network libraries. */ +# define HAVE_GETHOSTBYNAME 1 +# define HAVE_INET_ADDR 1 +# define HAVE_SOCKET 1 +# endif +# define sleep(x) Sleep((x) * 1000) +#else + /* MSVC++ configuration follows */ +# undef HAVE_UNISTD_H +# define HAVE_STDLIB_H 1 +# define HAVE_WINDOWS_H 1 +# define HAVE_STDARG_H 1 +# define HAVE_WINSVC_H 1 +# define HAVE_WINSOCK2_H 1 +# define HAVE_WINDOWSX_H 1 +#endif /* __MINGW32__ */ + +#ifdef HAVE_WINDOWS_H +# include +#endif +#ifdef HAVE_WINDOWSX_H +# include +#endif +#ifdef HAVE_WINSOCK2_H +# include +#endif +#ifdef HAVE_WINSVC_H +# include +#endif + +#define _USE_WIN32_ 1 + +#endif /* _LOCAL_WIN32_H */ -- 2.30.2