+SUBDIRS = libconfig
if BUILD_MODULE_PING
-SUBDIRS = libping .
+SUBDIRS += libping
endif
+#SUBDIRS += .
sbin_PROGRAMS = collectd
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
--- /dev/null
+ 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 <libconfig@rkeene.org>
+ Primary maintainer.
+
+People who have submitted patches:
+ * Mirko Buffoni <mirko.buffoni@synthesys.it>
+ Fixed installation issues and corrected mistakes in RPM spec file.
--- /dev/null
+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.
--- /dev/null
+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
--- /dev/null
+ 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
--- /dev/null
+ 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.
--- /dev/null
+#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 <inttypes.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef HAVE_OPENNET_H
+#include <opennet.h>
+#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
--- /dev/null
+#include "compat.h"
+#include "libconfig.h"
+#include "libconfig_private.h"
+#include "conf_apache.h"
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#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));
+}
--- /dev/null
+#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
--- /dev/null
+#include "libconfig.h"
+#include "libconfig_private.h"
+#include "conf_colon.h"
+
+int lc_process_conf_colon(const char *appname, const char *configfile) {
+ return(-1);
+}
--- /dev/null
+#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
--- /dev/null
+#include "libconfig.h"
+#include "libconfig_private.h"
+#include "conf_equal.h"
+
+int lc_process_conf_equal(const char *appname, const char *configfile) {
+ return(-1);
+}
--- /dev/null
+#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
--- /dev/null
+#include "compat.h"
+#include "libconfig.h"
+#include "libconfig_private.h"
+#include "conf_section.h"
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#include "compat.h"
+#include "libconfig.h"
+#include "libconfig_private.h"
+#include "conf_space.h"
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#include "libconfig.h"
+#include "libconfig_private.h"
+#include "conf_xml.h"
+
+int lc_process_conf_xml(const char *appname, const char *configfile) {
+ return(-1);
+}
--- /dev/null
+#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
--- /dev/null
+#include "getuid.h"
+
+uid_t getuid(void) {
+ return(0);
+}
--- /dev/null
+#ifndef _LC_GETUID_H
+#define _LC_GETUID_H
+
+typedef int uid_t;
+
+uid_t getuid(void);
+
+#endif
--- /dev/null
+#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 <string.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#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 = "<environment>";
+ 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 <APPNAME>_ */
+ 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 = "<cmdline>";
+ 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", "<no file>", lc_errline, errmsg);
+ } else {
+ snprintf(retval, sizeof(retval), "%s:%i: %s", lc_errfile, lc_errline, errmsg);
+ }
+
+ retval[sizeof(retval) - 1] = '\0';
+
+ return(retval);
+}
--- /dev/null
+# 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
--- /dev/null
+#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
--- /dev/null
+/*
+ * 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 <saurik@saurik.com> */
+
+#include <string.h>
+#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);
+}
+
--- /dev/null
+/*
+ * 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 <saurik@saurik.com> */
+
+#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
--- /dev/null
+#include <sys/types.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <stdio.h>
+
+/* 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);
+}
--- /dev/null
+#ifndef _RSK_STRTOLL_H
+#define _RSK_STRTOLL_H
+
+long long int strtoll(const char *nptr, char **endptr, int base);
+
+#endif
--- /dev/null
+#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);
+}
--- /dev/null
+#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 <windows.h>
+#endif
+#ifdef HAVE_WINDOWSX_H
+# include <windowsx.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+#endif
+#ifdef HAVE_WINSVC_H
+# include <winsvc.h>
+#endif
+
+#define _USE_WIN32_ 1
+
+#endif /* _LOCAL_WIN32_H */