Added src/libconfig so distribution
authorocto <octo>
Tue, 13 Dec 2005 17:57:47 +0000 (17:57 +0000)
committerocto <octo>
Tue, 13 Dec 2005 17:57:47 +0000 (17:57 +0000)
30 files changed:
src/Makefile.am
src/libconfig/AUTHORS [new file with mode: 0644]
src/libconfig/LICENSE [new file with mode: 0644]
src/libconfig/Makefile.am [new file with mode: 0644]
src/libconfig/README [new file with mode: 0644]
src/libconfig/TODO [new file with mode: 0644]
src/libconfig/compat.h [new file with mode: 0644]
src/libconfig/conf_apache.c [new file with mode: 0644]
src/libconfig/conf_apache.h [new file with mode: 0644]
src/libconfig/conf_colon.c [new file with mode: 0644]
src/libconfig/conf_colon.h [new file with mode: 0644]
src/libconfig/conf_equal.c [new file with mode: 0644]
src/libconfig/conf_equal.h [new file with mode: 0644]
src/libconfig/conf_section.c [new file with mode: 0644]
src/libconfig/conf_section.h [new file with mode: 0644]
src/libconfig/conf_space.c [new file with mode: 0644]
src/libconfig/conf_space.h [new file with mode: 0644]
src/libconfig/conf_xml.c [new file with mode: 0644]
src/libconfig/conf_xml.h [new file with mode: 0644]
src/libconfig/getuid.c [new file with mode: 0644]
src/libconfig/getuid.h [new file with mode: 0644]
src/libconfig/libconfig.c [new file with mode: 0644]
src/libconfig/libconfig.h [new file with mode: 0644]
src/libconfig/libconfig_private.h [new file with mode: 0644]
src/libconfig/strsep.c [new file with mode: 0644]
src/libconfig/strsep.h [new file with mode: 0644]
src/libconfig/strtoll.c [new file with mode: 0644]
src/libconfig/strtoll.h [new file with mode: 0644]
src/libconfig/test-lc.c [new file with mode: 0644]
src/libconfig/win32.h [new file with mode: 0644]

index 4f271bf..8ec68e9 100644 (file)
@@ -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 (file)
index 0000000..53f27bf
--- /dev/null
@@ -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 <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.
diff --git a/src/libconfig/LICENSE b/src/libconfig/LICENSE
new file mode 100644 (file)
index 0000000..4af06fb
--- /dev/null
@@ -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 (file)
index 0000000..071784f
--- /dev/null
@@ -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 (file)
index 0000000..7274223
--- /dev/null
@@ -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 (file)
index 0000000..6ba4ed3
--- /dev/null
@@ -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 (file)
index 0000000..9d22038
--- /dev/null
@@ -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 <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
diff --git a/src/libconfig/conf_apache.c b/src/libconfig/conf_apache.c
new file mode 100644 (file)
index 0000000..1497d1e
--- /dev/null
@@ -0,0 +1,371 @@
+#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));
+}
diff --git a/src/libconfig/conf_apache.h b/src/libconfig/conf_apache.h
new file mode 100644 (file)
index 0000000..36c556e
--- /dev/null
@@ -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 (file)
index 0000000..f184309
--- /dev/null
@@ -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 (file)
index 0000000..7d2323c
--- /dev/null
@@ -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 (file)
index 0000000..a214330
--- /dev/null
@@ -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 (file)
index 0000000..82e0f04
--- /dev/null
@@ -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 (file)
index 0000000..fb948c1
--- /dev/null
@@ -0,0 +1,201 @@
+#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);
+}
diff --git a/src/libconfig/conf_section.h b/src/libconfig/conf_section.h
new file mode 100644 (file)
index 0000000..1d1a94c
--- /dev/null
@@ -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 (file)
index 0000000..50a9b23
--- /dev/null
@@ -0,0 +1,109 @@
+#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);
+}
diff --git a/src/libconfig/conf_space.h b/src/libconfig/conf_space.h
new file mode 100644 (file)
index 0000000..6cf0462
--- /dev/null
@@ -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 (file)
index 0000000..85edd51
--- /dev/null
@@ -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 (file)
index 0000000..f0deffb
--- /dev/null
@@ -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 (file)
index 0000000..d6e17c7
--- /dev/null
@@ -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 (file)
index 0000000..77745c7
--- /dev/null
@@ -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 (file)
index 0000000..9f80a76
--- /dev/null
@@ -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 <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);
+}
diff --git a/src/libconfig/libconfig.h b/src/libconfig/libconfig.h
new file mode 100644 (file)
index 0000000..8c2f361
--- /dev/null
@@ -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 (file)
index 0000000..8310a85
--- /dev/null
@@ -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 (file)
index 0000000..f82ea13
--- /dev/null
@@ -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 <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);
+}
+
diff --git a/src/libconfig/strsep.h b/src/libconfig/strsep.h
new file mode 100644 (file)
index 0000000..3b375b3
--- /dev/null
@@ -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 <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
diff --git a/src/libconfig/strtoll.c b/src/libconfig/strtoll.c
new file mode 100644 (file)
index 0000000..a98025a
--- /dev/null
@@ -0,0 +1,43 @@
+#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);
+}
diff --git a/src/libconfig/strtoll.h b/src/libconfig/strtoll.h
new file mode 100644 (file)
index 0000000..7910303
--- /dev/null
@@ -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 (file)
index 0000000..ed492d8
--- /dev/null
@@ -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 (file)
index 0000000..06f3a0d
--- /dev/null
@@ -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 <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 */