Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
authorSebastian Harl <sh@tokkee.org>
Fri, 20 Dec 2013 19:09:48 +0000 (20:09 +0100)
committerSebastian Harl <sh@tokkee.org>
Fri, 20 Dec 2013 19:09:48 +0000 (20:09 +0100)
20 files changed:
.gitignore
configure.ac
doc/Makefile.am
src/Makefile.am
src/client/sysdb.c [deleted file]
src/daemon/config.c [deleted file]
src/daemon/sysdbd.c [deleted file]
src/daemon/sysdbd.conf.sample [deleted file]
src/frontend/connection-private.h [new file with mode: 0644]
src/include/daemon/config.h [deleted file]
src/include/frontend/connection-private.h [deleted file]
src/include/utils/strbuf.h
src/tools/sysdb/main.c [new file with mode: 0644]
src/tools/sysdbd/configfile.c [new file with mode: 0644]
src/tools/sysdbd/configfile.h [new file with mode: 0644]
src/tools/sysdbd/main.c [new file with mode: 0644]
src/tools/sysdbd/sysdbd.conf.sample [new file with mode: 0644]
src/utils/dbi.c
src/utils/strbuf.c
t/utils/strbuf_test.c

index 63813b029f164e7c60eea3d0bc000b4a20644e55..e7c950e8e2872c07894260f0099af40c0359abc9 100644 (file)
@@ -11,6 +11,7 @@ src/config.h*
 Makefile
 Makefile.in
 aclocal.m4
+ar-lib
 autom4te.cache
 compile
 /config.*
@@ -31,13 +32,13 @@ ltmain.sh
 src/liboconfig/parser.c
 src/liboconfig/parser.h
 src/liboconfig/scanner.c
+src/sysdb
+src/sysdbd
 .dirstamp
 .libs
 *.la
 *.lo
 *.o
-sysdb
-sysdbd
 sysdbd.1
 sysdbd.conf.5
 sysdb.h
index dde772705dc6a913524116a4e4399dd044f0b823..b7a07e662bdaf80ccfde933aaf26ce5a38cdf0ba 100644 (file)
@@ -37,7 +37,7 @@ AC_CONFIG_SRCDIR([src/sysdb.c])
 AC_CONFIG_HEADERS([src/config.h])
 AC_PREFIX_DEFAULT([/opt/sysdb])
 
-AM_INIT_AUTOMAKE([foreign -Wall])
+AM_INIT_AUTOMAKE([foreign subdir-objects -Wall])
 
 AC_LANG(C)
 
@@ -48,6 +48,7 @@ AC_PROG_CPP
 AC_PROG_INSTALL
 AC_PROG_LN_S
 AC_PROG_MAKE_SET
+AM_PROG_AR
 
 AM_PROG_CC_C_O
 AM_PROG_LEX
@@ -184,6 +185,9 @@ if test "x$enable_strict_checks" = "xyes"; then
 fi
 AC_SUBST([STRICT_CFLAGS])
 
+m4_divert_once([HELP_ENABLE], [
+Build dependencies:])
+
 dnl Testing.
 PKG_CHECK_MODULES([CHECK], [check >= 0.9.4],
                [build_testing="yes"], [build_testing="no"])
@@ -219,6 +223,82 @@ if test "x$have_fopencookie" = "xyes"; then
        AC_DEFINE([HAVE_FOPENCOOKIE], 1)
 fi
 
+dnl readline support
+AC_ARG_WITH([readline],
+               [AS_HELP_STRING([--with-readline],
+                       [readline support (libedit/libreadline) (default: auto, prefer libedit)])],
+               [readline_support="$withval"],
+               [readline_support="auto"])
+
+if test "x$readline_support" = "xyes"; then
+       readline_support="auto"
+fi
+
+have_libedit="no"
+if test "x$readline_support" = "xauto" \
+               || test "x$readline_support" = "xlibedit"; then
+       PKG_CHECK_MODULES([LIBEDIT], [libedit],
+                       [have_libedit="yes"], [have_libedit="no"])
+       if test "x$have_libedit" = "xyes"; then
+               AC_CHECK_HEADERS([editline/readline.h], [],
+                               [AC_CHECK_HEADERS([readline.h], [],
+                                               [have_libedit="no (readline header not found"])])
+       fi
+       if test "x$have_libedit" = "xyes"; then
+               AC_CHECK_HEADERS([editline/history.h], [],
+                               [AC_CHECK_HEADERS([history.h], [],
+                                               [have_libedit="no (history header not found"])])
+       fi
+else
+       have_libedit="disabled on command-line"
+fi
+
+have_libreadline="no"
+if test "x$have_libedit" = "xno"; then
+       if test "x$readline_support" = "xauto" \
+                       || test "x$readline_support" = "xlibreadline"; then
+               AC_CHECK_LIB([readline], [readline],
+                               [have_libreadline="yes"],
+                               [have_libreadline="no (libreadline or symbol 'readline' not found)"])
+       fi
+       if test "x$have_libreadline" = "xyes"; then
+               AC_CHECK_HEADERS([readline/readline.h], [],
+                               [AC_CHECK_HEADERS([readline.h], [],
+                                               [have_libreadline="no (readline header not found"])])
+       fi
+       if test "x$have_libreadline" = "xyes"; then
+               AC_CHECK_HEADERS([readline/history.h], [],
+                               [AC_CHECK_HEADERS([history.h], [],
+                                               [have_libreadline="no (history header not found"])])
+       fi
+else
+       have_libreadline="unchecked (prefer libedit)"
+fi
+
+if test "x$have_libedit" = "xyes"; then
+       READLINE_LIBS="$LIBEDIT_LIBS"
+       READLINE_CFLAGS="$LIBEDIT_CFLAGS"
+       readline_support="libedit"
+else if test "x$have_libreadline" = "xyes"; then
+       READLINE_LIBS="-lreadline -lhistory"
+       READLINE_CFLAGS=""
+       readline_support="libreadline"
+else
+       READLINE_LIBS=""
+       READLINE_CFLAGS=""
+       if test "x$readline_support" = "xno"; then
+               AC_MSG_WARN([*** readline support disabled; disabling SysDB client])
+       else if test "x$readline_support" = "xauto"; then
+               AC_MSG_WARN([*** readline not found; disabling SysDB client])
+       else
+               AC_MSG_ERROR([readline not found])
+       fi; fi
+       readline_support="no"
+fi; fi
+AC_SUBST([READLINE_LIBS])
+AC_SUBST([READLINE_CFLAGS])
+AM_CONDITIONAL([BUILD_CLIENT], test "x$readline_support" != "no")
+
 dnl Feature checks.
 build_documentation="yes"
 
@@ -296,6 +376,8 @@ AC_MSG_RESULT([      stdio mocking:  . . . . . $have_fopencookie])
 AC_MSG_RESULT()
 AC_MSG_RESULT([  Libraries:])
 AC_MSG_RESULT([    libdbi: . . . . . . . . . . $with_libdbi])
+AC_MSG_RESULT([    libedit:  . . . . . . . . . $have_libedit])
+AC_MSG_RESULT([    libreadline:  . . . . . . . $have_libreadline])
 AC_MSG_RESULT()
 AC_MSG_RESULT([  Backends:])
 AC_MSG_RESULT([    collectd: . . . . . . . . . $enable_collectd])
index 35c3a4a39e20dc12314257d463c3959548bdce5d..a89ea25268609bb04aeca53c8e8e7f20603b5519 100644 (file)
@@ -1,3 +1,5 @@
+SUFFIXES = .1 .5 .1.txt .5.txt
+
 EXTRA_DIST = \
                sysdbd.1.txt \
                sysdbd.conf.5.txt
@@ -13,13 +15,13 @@ sysdbd.1: sysdbd.1.txt ../version
 
 sysdbd.conf.5: sysdbd.conf.5.txt ../version
 
-%.1: %.1.txt
+.1.txt.1:
        @A2X@ -d manpage -f manpage \
                -apackage_version=$(PACKAGE_VERSION) \
                -abuild_date="$$( date --utc '+%F' )" \
                $<
 
-%.5: %.5.txt
+.5.txt.5:
        @A2X@ -d manpage -f manpage \
                -apackage_version=$(PACKAGE_VERSION) \
                -abuild_date="$$( date --utc '+%F' )" \
index e547fa4b543dc873b94b420218303279d3d373ea..3f5a0071081afd13a71189fb87b6900d20bf9e5e 100644 (file)
@@ -79,20 +79,24 @@ libsysdb_la_SOURCES += \
 libsysdb_la_LIBADD += -ldbi
 endif
 
-bin_PROGRAMS = sysdb sysdbd
-
-sysdb_SOURCES = client/sysdb.c include/client/sysdb.h
-sysdb_CFLAGS = $(AM_CFLAGS) -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\""
-sysdb_LDADD = libsysdbclient.la
+bin_PROGRAMS = sysdbd
+if BUILD_CLIENT
+bin_PROGRAMS += sysdb
+
+sysdb_SOURCES = tools/sysdb/main.c include/client/sysdb.h
+sysdb_CFLAGS = -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\"" \
+               $(AM_CFLAGS) @READLINE_CFLAGS@
+sysdb_LDADD = libsysdbclient.la @READLINE_LIBS@
+endif
 
-sysdbd_SOURCES = daemon/sysdbd.c include/sysdb.h \
-               daemon/config.c include/daemon/config.h
+sysdbd_SOURCES = tools/sysdbd/main.c include/sysdb.h \
+               tools/sysdbd/configfile.c tools/sysdbd/configfile.h
 sysdbd_CFLAGS = $(AM_CFLAGS) -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\""
 sysdbd_LDADD = libsysdb.la liboconfig/liboconfig.la
 sysdbd_DEPENDENCIES = liboconfig/liboconfig.la
 
 sdbconfdir = $(sysconfdir)/sysdb
-dist_sdbconf_DATA = daemon/sysdbd.conf.sample
+dist_sdbconf_DATA = tools/sysdbd/sysdbd.conf.sample
 
 pkgbackendlibdir = $(pkglibdir)/backend
 pkgbackendcollectdlibdir = $(pkgbackendlibdir)/collectd
diff --git a/src/client/sysdb.c b/src/client/sysdb.c
deleted file mode 100644 (file)
index c2b542d..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * SysDB - src/client/sysdb.c
- * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#      include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include "client/sysdb.h"
-#include "client/sock.h"
-#include "utils/error.h"
-
-#include <errno.h>
-
-#if HAVE_LIBGEN_H
-#      include <libgen.h>
-#else /* HAVE_LIBGEN_H */
-#      define basename(path) (path)
-#endif /* ! HAVE_LIBGEN_H */
-
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <unistd.h>
-
-#include <sys/types.h>
-
-#include <pwd.h>
-
-#ifndef DEFAULT_SOCKET
-#      define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock"
-#endif
-
-static void
-exit_usage(char *name, int status)
-{
-       printf(
-"Usage: %s <options>\n"
-
-"\nOptions:\n"
-"  -h        display this help and exit\n"
-"  -V        display the version number and copyright\n"
-
-"\nSysDB client "SDB_CLIENT_VERSION_STRING SDB_CLIENT_VERSION_EXTRA", "
-PACKAGE_URL"\n", basename(name));
-       exit(status);
-} /* exit_usage */
-
-static void
-exit_version(void)
-{
-       printf("SysDB version "SDB_CLIENT_VERSION_STRING
-                       SDB_CLIENT_VERSION_EXTRA", built "BUILD_DATE"\n"
-                       "using libsysdbclient version %s%s\n"
-                       "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n"
-
-                       "\nThis is free software under the terms of the BSD license, see "
-                       "the source for\ncopying conditions. There is NO WARRANTY; not "
-                       "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
-                       "PURPOSE.\n", sdb_client_version_string(),
-                       sdb_client_version_extra());
-       exit(0);
-} /* exit_version */
-
-static const char *
-get_current_user(void)
-{
-       struct passwd pw_entry;
-       struct passwd *result = NULL;
-
-       uid_t uid;
-
-       /* needs to be static because we return a pointer into this buffer
-        * to the caller */
-       static char buf[1024];
-
-       int status;
-
-       uid = geteuid();
-
-       memset(&pw_entry, 0, sizeof(pw_entry));
-       status = getpwuid_r(uid, &pw_entry, buf, sizeof(buf), &result);
-
-       if (status || (! result)) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Failed to determine current username: %s",
-                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               return NULL;
-       }
-       return result->pw_name;
-} /* get_current_user */
-
-int
-main(int argc, char **argv)
-{
-       sdb_client_t *client;
-
-       const char *host = NULL;
-       const char *user = NULL;
-
-       while (42) {
-               int opt = getopt(argc, argv, "H:U:hV");
-
-               if (-1 == opt)
-                       break;
-
-               switch (opt) {
-                       case 'H':
-                               host = optarg;
-                               break;
-                       case 'U':
-                               user = optarg;
-                               break;
-
-                       case 'h':
-                               exit_usage(argv[0], 0);
-                               break;
-                       case 'V':
-                               exit_version();
-                               break;
-                       default:
-                               exit_usage(argv[0], 1);
-               }
-       }
-
-       if (optind < argc)
-               exit_usage(argv[0], 1);
-
-       if (! host)
-               host = DEFAULT_SOCKET;
-       if (! user) {
-               user = get_current_user();
-               if (! user)
-                       exit(1);
-       }
-
-       client = sdb_client_create(host);
-       if (! client) {
-               sdb_log(SDB_LOG_ERR, "Failed to create client object");
-               exit(1);
-       }
-       if (sdb_client_connect(client, user)) {
-               sdb_log(SDB_LOG_ERR, "Failed to connect to SysDBd");
-               sdb_client_destroy(client);
-               exit(1);
-       }
-
-       sdb_log(SDB_LOG_INFO, "SysDB client "SDB_CLIENT_VERSION_STRING
-                       SDB_CLIENT_VERSION_EXTRA"\n");
-
-       sdb_client_destroy(client);
-       return 0;
-} /* main */
-
-/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
-
diff --git a/src/daemon/config.c b/src/daemon/config.c
deleted file mode 100644 (file)
index 906f4c5..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * SysDB - src/daemon/config.c
- * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "sysdb.h"
-#include "core/plugin.h"
-#include "core/time.h"
-#include "utils/error.h"
-
-#include "daemon/config.h"
-
-#include "liboconfig/oconfig.h"
-#include "liboconfig/utils.h"
-
-#include <assert.h>
-#include <errno.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-
-/*
- * Parser error values:
- *  - Values less than zero indicate an error in the daemon or libsysdb.
- *  - Zero indicates success.
- *  - Any other values indicate parsing errors.
- */
-
-enum {
-       ERR_UNKNOWN_OPTION = 1,
-       ERR_UNKNOWN_ARG    = 2,
-       ERR_INVALID_ARG    = 3,
-       ERR_PARSE_FAILED   = 4,
-};
-
-/*
- * private variables
- */
-
-static sdb_time_t default_interval = 0;
-
-/*
- * private helper functions
- */
-
-static int
-config_get_interval(oconfig_item_t *ci, sdb_time_t *interval)
-{
-       double interval_dbl = 0.0;
-
-       assert(ci && interval);
-
-       if (oconfig_get_number(ci, &interval_dbl)) {
-               sdb_log(SDB_LOG_ERR, "config: Interval requires "
-                               "a single numeric argument\n"
-                               "\tUsage: Interval SECONDS");
-               return ERR_INVALID_ARG;
-       }
-
-       if (interval_dbl <= 0.0) {
-               sdb_log(SDB_LOG_ERR, "config: Invalid interval: %f\n"
-                               "\tInterval may not be less than or equal to zero.",
-                               interval_dbl);
-               return ERR_INVALID_ARG;
-       }
-
-       *interval = DOUBLE_TO_SDB_TIME(interval_dbl);
-       return 0;
-} /* config_get_interval */
-
-/*
- * public parse results
- */
-
-char **listen_addresses = NULL;
-size_t listen_addresses_num = 0;
-
-/*
- * token parser
- */
-
-typedef struct {
-       char *name;
-       int (*dispatcher)(oconfig_item_t *);
-} token_parser_t;
-
-static int
-daemon_add_listener(oconfig_item_t *ci)
-{
-       char **tmp;
-       char *address;
-
-       if (oconfig_get_string(ci, &address)) {
-               sdb_log(SDB_LOG_ERR, "config: Listen requires a single "
-                               "string argument\n"
-                               "\tUsage: Listen ADDRESS");
-               return ERR_INVALID_ARG;
-       }
-
-       tmp = realloc(listen_addresses,
-                       (listen_addresses_num + 1) * sizeof(*listen_addresses));
-       if (! tmp) {
-               char buf[1024];
-               sdb_log(SDB_LOG_ERR, "config: Failed to allocate memory: %s",
-                               sdb_strerror(errno, buf, sizeof(buf)));
-               return -1;
-       }
-
-       tmp[listen_addresses_num] = strdup(address);
-       if (! tmp[listen_addresses_num]) {
-               char buf[1024];
-               sdb_log(SDB_LOG_ERR, "config: Failed to allocate memory: %s",
-                               sdb_strerror(errno, buf, sizeof(buf)));
-               return -1;
-       }
-
-       listen_addresses = tmp;
-       ++listen_addresses_num;
-       return 0;
-} /* daemon_add_listener */
-
-static int
-daemon_set_interval(oconfig_item_t *ci)
-{
-       return config_get_interval(ci, &default_interval);
-} /* daemon_set_interval */
-
-static int
-daemon_load_plugin(oconfig_item_t *ci)
-{
-       char *name;
-       int i;
-
-       if (oconfig_get_string(ci, &name)) {
-               sdb_log(SDB_LOG_ERR, "config: LoadPlugin requires a single "
-                               "string argument\n"
-                               "\tUsage: LoadPlugin PLUGIN");
-               return ERR_INVALID_ARG;
-       }
-
-       for (i = 0; i < ci->children_num; ++i) {
-               oconfig_item_t *child = ci->children + i;
-
-               /* we don't currently support any options */
-               sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
-                               "inside 'LoadPlugin' -- see the documentation for "
-                               "details.", child->key);
-               continue;
-       }
-
-       /* returns a negative value on error */
-       return sdb_plugin_load(name, NULL);
-} /* daemon_load_plugin */
-
-static int
-daemon_load_backend(oconfig_item_t *ci)
-{
-       sdb_plugin_ctx_t ctx = SDB_PLUGIN_CTX_INIT;
-
-       char  plugin_name[1024];
-       char *name;
-
-       int i;
-
-       ctx.interval = default_interval;
-
-       if (oconfig_get_string(ci, &name)) {
-               sdb_log(SDB_LOG_ERR, "config: LoadBackend requires a single "
-                               "string argument\n"
-                               "\tUsage: LoadBackend BACKEND");
-               return ERR_INVALID_ARG;
-       }
-
-       snprintf(plugin_name, sizeof(plugin_name), "backend::%s", name);
-
-       for (i = 0; i < ci->children_num; ++i) {
-               oconfig_item_t *child = ci->children + i;
-
-               if (! strcasecmp(child->key, "Interval")) {
-                       if (config_get_interval(child, &ctx.interval))
-                               return ERR_INVALID_ARG;
-               }
-               else {
-                       sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
-                                       "inside 'LoadBackend' -- see the documentation for "
-                                       "details.", child->key);
-                       continue;
-               }
-       }
-
-       return sdb_plugin_load(plugin_name, &ctx);
-} /* daemon_load_backend */
-
-static int
-daemon_configure_plugin(oconfig_item_t *ci)
-{
-       char *name;
-
-       assert(ci);
-
-       if (oconfig_get_string(ci, &name)) {
-               sdb_log(SDB_LOG_ERR, "config: %s requires a single "
-                               "string argument\n"
-                               "\tUsage: LoadBackend BACKEND",
-                               ci->key);
-               return ERR_INVALID_ARG;
-       }
-
-       return sdb_plugin_configure(name, ci);
-} /* daemon_configure_backend */
-
-static token_parser_t token_parser_list[] = {
-       { "Listen", daemon_add_listener },
-       { "Interval", daemon_set_interval },
-       { "LoadPlugin", daemon_load_plugin },
-       { "LoadBackend", daemon_load_backend },
-       { "Backend", daemon_configure_plugin },
-       { "Plugin", daemon_configure_plugin },
-       { NULL, NULL },
-};
-
-/*
- * public API
- */
-
-int
-daemon_parse_config(const char *filename)
-{
-       oconfig_item_t *ci;
-       int retval = 0, i;
-
-       ci = oconfig_parse_file(filename);
-       if (! ci)
-               return ERR_PARSE_FAILED;
-
-       for (i = 0; i < ci->children_num; ++i) {
-               oconfig_item_t *child = ci->children + i;
-               int status = ERR_UNKNOWN_OPTION, j;
-
-               for (j = 0; token_parser_list[j].name; ++j) {
-                       if (! strcasecmp(token_parser_list[j].name, child->key))
-                               status = token_parser_list[j].dispatcher(child);
-               }
-
-               if (status) {
-                       sdb_error_set("config: Failed to parse option '%s'\n",
-                                       child->key);
-                       if (status == ERR_UNKNOWN_OPTION)
-                               sdb_error_append("\tUnknown option '%s' -- "
-                                               "see the documentation for details\n",
-                                               child->key);
-                       sdb_error_chomp();
-                       sdb_error_log(SDB_LOG_ERR);
-                       retval = status;
-               }
-       }
-       return retval;
-} /* daemon_parse_config */
-
-/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
-
diff --git a/src/daemon/sysdbd.c b/src/daemon/sysdbd.c
deleted file mode 100644 (file)
index 21350f3..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * SysDB - src/sysdbd.c
- * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#      include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include "sysdb.h"
-#include "core/plugin.h"
-#include "core/store.h"
-#include "utils/error.h"
-
-#include "frontend/sock.h"
-
-#include "daemon/config.h"
-
-#if HAVE_LIBGEN_H
-#      include <libgen.h>
-#else /* HAVE_LIBGEN_H */
-#      define basename(path) (path)
-#endif /* ! HAVE_LIBGEN_H */
-
-#include <errno.h>
-
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <signal.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <unistd.h>
-
-#include <pthread.h>
-
-#ifndef CONFIGFILE
-#      define CONFIGFILE SYSCONFDIR"/sysdb/sysdbd.conf"
-#endif
-
-#ifndef DEFAULT_SOCKET
-#      define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock"
-#endif
-
-static sdb_plugin_loop_t plugin_main_loop = SDB_PLUGIN_LOOP_INIT;
-static sdb_fe_loop_t frontend_main_loop = SDB_FE_LOOP_INIT;
-
-static char *default_listen_addresses[] = {
-       DEFAULT_SOCKET,
-};
-
-static void
-sigintterm_handler(int __attribute__((unused)) signo)
-{
-       frontend_main_loop.do_loop = 0;
-} /* sigintterm_handler */
-
-static void
-exit_usage(char *name, int status)
-{
-       printf(
-"Usage: %s <options>\n"
-
-"\nOptions:\n"
-"  -C FILE   the main configuration file\n"
-"            default: "CONFIGFILE"\n"
-"  -D        do not run in background (daemonize)\n"
-"\n"
-"  -h        display this help and exit\n"
-"  -V        display the version number and copyright\n"
-
-"\nSysDB daemon "SDB_VERSION_STRING SDB_VERSION_EXTRA", "PACKAGE_URL"\n",
-basename(name));
-       exit(status);
-} /* exit_usage */
-
-static void
-exit_version(void)
-{
-       printf("SysDBd version "SDB_VERSION_STRING SDB_VERSION_EXTRA", "
-                       "built "BUILD_DATE"\n"
-                       "using libsysdb version %s%s\n"
-                       "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n"
-
-                       "\nThis is free software under the terms of the BSD license, see "
-                       "the source for\ncopying conditions. There is NO WARRANTY; not "
-                       "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
-                       "PURPOSE.\n", sdb_version_string(), sdb_version_extra());
-       exit(0);
-} /* exit_version */
-
-static int
-daemonize(void)
-{
-       pid_t pid;
-
-       if ((pid = fork()) < 0) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Failed to fork to background: %s",
-                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               return errno;
-       }
-       else if (pid != 0) {
-               /* parent */
-               exit(0);
-       }
-
-       if (chdir("/")) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Failed to change working directory to "
-                               "the root directory: %s",
-                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               return errno;
-       }
-
-       /* detach from session */
-       setsid();
-
-       close(0);
-       if (open("/dev/null", O_RDWR)) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Failed to connect stdin to '/dev/null': %s",
-                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               return errno;
-       }
-
-       close(1);
-       if (dup(0) != 1) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Could not connect stdout to '/dev/null': %s",
-                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               return errno;
-       }
-
-       close(2);
-       if (dup(0) != 2) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Could not connect stderr to '/dev/null': %s",
-                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               return errno;
-       }
-       return 0;
-} /* daemonize */
-
-static void *
-backend_handler(void __attribute__((unused)) *data)
-{
-       sdb_plugin_collector_loop(&plugin_main_loop);
-       sdb_log(SDB_LOG_INFO, "Shutting down backend thread");
-       return NULL;
-} /* backend_handler */
-
-int
-main(int argc, char **argv)
-{
-       char *config_filename = NULL;
-       _Bool do_daemonize = 1;
-
-       pthread_t backend_thread;
-
-       struct sigaction sa_intterm;
-       int status;
-
-       sdb_error_set_logger(sdb_plugin_log);
-
-       while (42) {
-               int opt = getopt(argc, argv, "C:DhV");
-
-               if (-1 == opt)
-                       break;
-
-               switch (opt) {
-                       case 'C':
-                               config_filename = optarg;
-                               break;
-                       case 'D':
-                               do_daemonize = 0;
-                               break;
-
-                       case 'h':
-                               exit_usage(argv[0], 0);
-                               break;
-                       case 'V':
-                               exit_version();
-                               break;
-                       default:
-                               exit_usage(argv[0], 1);
-               }
-       }
-
-       if (optind < argc)
-               exit_usage(argv[0], 1);
-
-       if (! config_filename)
-               config_filename = CONFIGFILE;
-
-       if ((status = daemon_parse_config(config_filename))) {
-               if (status > 0)
-                       sdb_log(SDB_LOG_ERR, "Failed to parse configuration file.");
-               else
-                       sdb_log(SDB_LOG_ERR, "Failed to load configuration file.\n"
-                                       "\tCheck other error messages for details.");
-               exit(1);
-       }
-
-       if (! listen_addresses) {
-               listen_addresses = default_listen_addresses;
-               listen_addresses_num = SDB_STATIC_ARRAY_LEN(default_listen_addresses);
-       }
-
-       memset(&sa_intterm, 0, sizeof(sa_intterm));
-       sa_intterm.sa_handler = sigintterm_handler;
-       sa_intterm.sa_flags = 0;
-
-       if (sigaction(SIGINT, &sa_intterm, /* old action */ NULL)) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Failed to install signal handler for "
-                               "SIGINT: %s", sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               exit(1);
-       }
-       if (sigaction(SIGTERM, &sa_intterm, /* old action */ NULL)) {
-               char errbuf[1024];
-               sdb_log(SDB_LOG_ERR, "Failed to install signal handler for "
-                               "SIGTERM: %s", sdb_strerror(errno, errbuf, sizeof(errbuf)));
-               exit(1);
-       }
-
-       if (do_daemonize)
-               if (daemonize())
-                       exit(1);
-
-       sdb_log(SDB_LOG_INFO, "SysDB daemon "SDB_VERSION_STRING
-                       SDB_VERSION_EXTRA " (pid %i) initialized successfully",
-                       (int)getpid());
-
-       sdb_plugin_init_all();
-       plugin_main_loop.default_interval = SECS_TO_SDB_TIME(60);
-
-       memset(&backend_thread, 0, sizeof(backend_thread));
-       if (pthread_create(&backend_thread, /* attr = */ NULL,
-                               backend_handler, /* arg = */ NULL)) {
-               char buf[1024];
-               sdb_log(SDB_LOG_ERR, "Failed to create backend handler thread: %s",
-                               sdb_strerror(errno, buf, sizeof(buf)));
-
-               plugin_main_loop.do_loop = 0;
-       }
-       else {
-               size_t i;
-
-               sdb_fe_socket_t *sock = sdb_fe_sock_create();
-               for (i = 0; i < listen_addresses_num; ++i)
-                       if (sdb_fe_sock_add_listener(sock, listen_addresses[i]))
-                               break;
-
-               /* break on error */
-               if (i >= listen_addresses_num)
-                       sdb_fe_sock_listen_and_serve(sock, &frontend_main_loop);
-
-               sdb_log(SDB_LOG_INFO, "Waiting for backend thread to terminate");
-               plugin_main_loop.do_loop = 0;
-               pthread_kill(backend_thread, SIGINT);
-               pthread_join(backend_thread, NULL);
-               sdb_fe_sock_destroy(sock);
-       }
-
-       sdb_log(SDB_LOG_INFO, "Shutting down SysDB daemon "SDB_VERSION_STRING
-                       SDB_VERSION_EXTRA" (pid %i)", (int)getpid());
-       return 0;
-} /* main */
-
-/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
-
diff --git a/src/daemon/sysdbd.conf.sample b/src/daemon/sysdbd.conf.sample
deleted file mode 100644 (file)
index 0976e80..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# Sample configuration file for the System DataBase daemon (SysDBd).
-#
-
-#============================================================================#
-# Global options:                                                            #
-# This section defines global settings and default values for the daemon.    #
-#============================================================================#
-
-# default interval used for actively polling plugins
-Interval 300
-
-#============================================================================#
-# Logging settings:                                                          #
-# These plugins should be loaded first. Else, any log messages will be       #
-# written to the standard error channel which is closed after the daemon has #
-# started.                                                                   #
-#============================================================================#
-LoadPlugin "syslog"
-
-#============================================================================#
-# Plugins:                                                                   #
-# Plugins are the working horses of SysDB. Load any of the following plugins #
-# to active the respective feature.                                          #
-#============================================================================#
-
-#----------------------------------------------------------------------------#
-# "cname" plugins canonicalize hostnames before actually storing them. All   #
-# cname callbacks are applied to an hostname in the order in which they have #
-# been loaded, each receiving the result of the previous call.               #
-#----------------------------------------------------------------------------#
-LoadPlugin "cname::dns"
-
-#----------------------------------------------------------------------------#
-# "Backends" are plugins which collect information to be stored in SysDB.    #
-# Each backend may use its own custom query interval by specifying the       #
-# 'Interval' option:                                                         #
-#   <LoadBackend "foo">                                                      #
-#       Interval 60                                                          #
-#   </LoadPlugin>                                                            #
-#----------------------------------------------------------------------------#
-LoadBackend "collectd::unixsock"
-LoadBackend "mk-livestatus"
-LoadBackend "puppet::store-configs"
-
-#----------------------------------------------------------------------------#
-# Plugin configuration:                                                      #
-#----------------------------------------------------------------------------#
-
-<Backend "collectd::unixsock">
-       <Instance "central-collector">
-               Socket "/var/run/collectd-unixsock"
-       </Instance>
-</Backend>
-
-<Backend "mk-livestatus">
-       <Instance "nagios4-master">
-               Socket "/var/lib/nagios4/rw/live"
-       </Instance>
-</Backend>
-
-<Backend "puppet::store-configs">
-       <Connection "puppet">
-               DBAdapter "pgsql"
-               DBName "puppet"
-               DBServer "puppet.domain.tld"
-               DBPort "5432"
-               DBUser "puppet"
-               DBPassword "secret1"
-               DBIOption "name" "value"
-       </Connection>
-</Backend>
-
diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h
new file mode 100644 (file)
index 0000000..6cf7395
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * SysDB - src/include/frontend/connection-private.h
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * private data structures used by frontend modules
+ */
+
+#ifndef SDB_FRONTEND_CONNECTION_PRIVATE_H
+#define SDB_FRONTEND_CONNECTION_PRIVATE_H 1
+
+#include "core/object.h"
+#include "utils/strbuf.h"
+#include "frontend/connection.h"
+
+#include <inttypes.h>
+#include <arpa/inet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sdb_conn {
+       sdb_object_t super;
+
+       /* file-descriptor of the open connection */
+       int fd;
+
+       /* connection and client information */
+       struct sockaddr_storage client_addr;
+       socklen_t client_addr_len;
+
+       /* read buffer */
+       sdb_strbuf_t *buf;
+
+       /* connection / protocol state information */
+       uint32_t cmd;
+       uint32_t cmd_len;
+
+       sdb_strbuf_t *errbuf;
+
+       /* user information */
+       char *username; /* NULL if the user has not been authenticated */
+};
+#define CONN(obj) ((sdb_conn_t *)(obj))
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ! SDB_FRONTEND_CONNECTION_H */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/include/daemon/config.h b/src/include/daemon/config.h
deleted file mode 100644 (file)
index 0fe278d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * SysDB - src/daemon/config.h
- * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DAEMON_CONFIG_H
-#define DAEMON_CONFIG_H 1
-
-/*
- * parse result values
- */
-
-extern char **listen_addresses;
-extern size_t listen_addresses_num;
-
-/*
- * daemon_parse_config:
- * Parse the specified configuration file.
- *
- * Returns:
- *  - 0 on success
- *  - a negative value when loading the configuration failed because of errors
- *    in the daemon or libsysdb
- *  - a positive value on parser errors
- */
-int
-daemon_parse_config(const char *filename);
-
-#endif /* ! DAEMON_CONFIG_H */
-
-/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
-
diff --git a/src/include/frontend/connection-private.h b/src/include/frontend/connection-private.h
deleted file mode 100644 (file)
index 6cf7395..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SysDB - src/include/frontend/connection-private.h
- * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * private data structures used by frontend modules
- */
-
-#ifndef SDB_FRONTEND_CONNECTION_PRIVATE_H
-#define SDB_FRONTEND_CONNECTION_PRIVATE_H 1
-
-#include "core/object.h"
-#include "utils/strbuf.h"
-#include "frontend/connection.h"
-
-#include <inttypes.h>
-#include <arpa/inet.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct sdb_conn {
-       sdb_object_t super;
-
-       /* file-descriptor of the open connection */
-       int fd;
-
-       /* connection and client information */
-       struct sockaddr_storage client_addr;
-       socklen_t client_addr_len;
-
-       /* read buffer */
-       sdb_strbuf_t *buf;
-
-       /* connection / protocol state information */
-       uint32_t cmd;
-       uint32_t cmd_len;
-
-       sdb_strbuf_t *errbuf;
-
-       /* user information */
-       char *username; /* NULL if the user has not been authenticated */
-};
-#define CONN(obj) ((sdb_conn_t *)(obj))
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ! SDB_FRONTEND_CONNECTION_H */
-
-/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
-
index 900a4530511020ae9c5d8374b065c943922c23ad..96b4f86bee3aa8937899a9af08314f9fa5866860 100644 (file)
@@ -144,6 +144,13 @@ sdb_strbuf_chomp(sdb_strbuf_t *strbuf);
 void
 sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t offset, size_t n);
 
+/*
+ * sdb_strbuf_clear:
+ * Clear the buffer but do not deallocate memory.
+ */
+void
+sdb_strbuf_clear(sdb_strbuf_t *strbuf);
+
 /*
  * sdb_strbuf_string:
  * Returns the content of the string buffer. The caller may not modify the
diff --git a/src/tools/sysdb/main.c b/src/tools/sysdb/main.c
new file mode 100644 (file)
index 0000000..0639e5f
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * SysDB - src/tools/sysdb/main.c
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#      include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "client/sysdb.h"
+#include "client/sock.h"
+#include "utils/error.h"
+#include "utils/strbuf.h"
+
+#include <errno.h>
+
+#if HAVE_LIBGEN_H
+#      include <libgen.h>
+#else /* HAVE_LIBGEN_H */
+#      define basename(path) (path)
+#endif /* ! HAVE_LIBGEN_H */
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <sys/types.h>
+
+#include <pwd.h>
+
+#if HAVE_EDITLINE_READLINE_H
+#      include <editline/readline.h>
+#      if HAVE_EDITLINE_HISTORY_H
+#              include <editline/history.h>
+#      endif
+#elif HAVE_READLINE_READLINE_H
+#      include <readline/readline.h>
+#      if HAVE_READLINE_HISTORY_H
+#              include <readline/history.h>
+#      endif
+#elif HAVE_READLINE_H
+#      include <readline.h>
+#      if HAVE_HISTORY_H
+#              include <history.h>
+#      endif
+#endif /* READLINEs */
+
+#ifndef DEFAULT_SOCKET
+#      define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock"
+#endif
+
+static void
+exit_usage(char *name, int status)
+{
+       printf(
+"Usage: %s <options>\n"
+
+"\nOptions:\n"
+"  -h        display this help and exit\n"
+"  -V        display the version number and copyright\n"
+
+"\nSysDB client "SDB_CLIENT_VERSION_STRING SDB_CLIENT_VERSION_EXTRA", "
+PACKAGE_URL"\n", basename(name));
+       exit(status);
+} /* exit_usage */
+
+static void
+exit_version(void)
+{
+       printf("SysDB version "SDB_CLIENT_VERSION_STRING
+                       SDB_CLIENT_VERSION_EXTRA", built "BUILD_DATE"\n"
+                       "using libsysdbclient version %s%s\n"
+                       "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n"
+
+                       "\nThis is free software under the terms of the BSD license, see "
+                       "the source for\ncopying conditions. There is NO WARRANTY; not "
+                       "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
+                       "PURPOSE.\n", sdb_client_version_string(),
+                       sdb_client_version_extra());
+       exit(0);
+} /* exit_version */
+
+static const char *
+get_current_user(void)
+{
+       struct passwd pw_entry;
+       struct passwd *result = NULL;
+
+       uid_t uid;
+
+       /* needs to be static because we return a pointer into this buffer
+        * to the caller */
+       static char buf[1024];
+
+       int status;
+
+       uid = geteuid();
+
+       memset(&pw_entry, 0, sizeof(pw_entry));
+       status = getpwuid_r(uid, &pw_entry, buf, sizeof(buf), &result);
+
+       if (status || (! result)) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Failed to determine current username: %s",
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               return NULL;
+       }
+       return result->pw_name;
+} /* get_current_user */
+
+static const char *
+get_homedir(const char *username)
+{
+       struct passwd pw_entry;
+       struct passwd *result = NULL;
+
+       /* needs to be static because we return a pointer into this buffer
+        * to the caller */
+       static char buf[1024];
+
+       int status;
+
+       memset(&pw_entry, 0, sizeof(pw_entry));
+       status = getpwnam_r(username, &pw_entry, buf, sizeof(buf), &result);
+
+       if (status || (! result)) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_WARNING, "Failed to determine home directory "
+                               "for user %s: %s", username,
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               return NULL;
+       }
+       return result->pw_dir;
+} /* get_homedir */
+
+int
+main(int argc, char **argv)
+{
+       sdb_client_t *client;
+
+       const char *host = NULL;
+       const char *user = NULL;
+
+       const char *homedir;
+       char hist_file[1024] = "";
+
+       sdb_strbuf_t *buf;
+
+       while (42) {
+               int opt = getopt(argc, argv, "H:U:hV");
+
+               if (-1 == opt)
+                       break;
+
+               switch (opt) {
+                       case 'H':
+                               host = optarg;
+                               break;
+                       case 'U':
+                               user = optarg;
+                               break;
+
+                       case 'h':
+                               exit_usage(argv[0], 0);
+                               break;
+                       case 'V':
+                               exit_version();
+                               break;
+                       default:
+                               exit_usage(argv[0], 1);
+               }
+       }
+
+       if (optind < argc)
+               exit_usage(argv[0], 1);
+
+       if (! host)
+               host = DEFAULT_SOCKET;
+       if (! user) {
+               user = get_current_user();
+               if (! user)
+                       exit(1);
+       }
+
+       client = sdb_client_create(host);
+       if (! client) {
+               sdb_log(SDB_LOG_ERR, "Failed to create client object");
+               exit(1);
+       }
+       if (sdb_client_connect(client, user)) {
+               sdb_log(SDB_LOG_ERR, "Failed to connect to SysDBd");
+               sdb_client_destroy(client);
+               exit(1);
+       }
+
+       sdb_log(SDB_LOG_INFO, "SysDB client "SDB_CLIENT_VERSION_STRING
+                       SDB_CLIENT_VERSION_EXTRA"\n");
+
+       using_history();
+
+       if ((homedir = get_homedir(user))) {
+               snprintf(hist_file, sizeof(hist_file) - 1,
+                               "%s/.sysdb_history", homedir);
+               hist_file[sizeof(hist_file) - 1] = '\0';
+
+               errno = 0;
+               if (read_history(hist_file) && (errno != ENOENT)) {
+                       char errbuf[1024];
+                       sdb_log(SDB_LOG_WARNING, "Failed to load history (%s): %s",
+                                       hist_file, sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               }
+       }
+
+       buf = sdb_strbuf_create(1024);
+
+       while (42) {
+               const char *prompt = "sysdb=> ";
+               const char *query;
+               char *input;
+
+               if (sdb_strbuf_len(buf))
+                       prompt = "sysdb-> ";
+
+               input = readline(prompt);
+
+               if (! input)
+                       break;
+
+               sdb_strbuf_append(buf, input);
+               free(input);
+
+               query = sdb_strbuf_string(buf);
+               if (! strchr(query, (int)';'))
+                       continue;
+
+               /* XXX */
+               sdb_strbuf_clear(buf);
+       }
+
+       if (hist_file[0] != '\0') {
+               errno = 0;
+               if (write_history(hist_file)) {
+                       char errbuf[1024];
+                       sdb_log(SDB_LOG_WARNING, "Failed to store history (%s): %s",
+                                       hist_file, sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               }
+       }
+
+       sdb_client_destroy(client);
+       return 0;
+} /* main */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/tools/sysdbd/configfile.c b/src/tools/sysdbd/configfile.c
new file mode 100644 (file)
index 0000000..9527626
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * SysDB - src/tools/sysdbd/configfile.c
+ * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tools/sysdbd/configfile.h"
+
+#include "sysdb.h"
+#include "core/plugin.h"
+#include "core/time.h"
+#include "utils/error.h"
+
+#include "liboconfig/oconfig.h"
+#include "liboconfig/utils.h"
+
+#include <assert.h>
+#include <errno.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+/*
+ * Parser error values:
+ *  - Values less than zero indicate an error in the daemon or libsysdb.
+ *  - Zero indicates success.
+ *  - Any other values indicate parsing errors.
+ */
+
+enum {
+       ERR_UNKNOWN_OPTION = 1,
+       ERR_UNKNOWN_ARG    = 2,
+       ERR_INVALID_ARG    = 3,
+       ERR_PARSE_FAILED   = 4,
+};
+
+/*
+ * private variables
+ */
+
+static sdb_time_t default_interval = 0;
+
+/*
+ * private helper functions
+ */
+
+static int
+config_get_interval(oconfig_item_t *ci, sdb_time_t *interval)
+{
+       double interval_dbl = 0.0;
+
+       assert(ci && interval);
+
+       if (oconfig_get_number(ci, &interval_dbl)) {
+               sdb_log(SDB_LOG_ERR, "config: Interval requires "
+                               "a single numeric argument\n"
+                               "\tUsage: Interval SECONDS");
+               return ERR_INVALID_ARG;
+       }
+
+       if (interval_dbl <= 0.0) {
+               sdb_log(SDB_LOG_ERR, "config: Invalid interval: %f\n"
+                               "\tInterval may not be less than or equal to zero.",
+                               interval_dbl);
+               return ERR_INVALID_ARG;
+       }
+
+       *interval = DOUBLE_TO_SDB_TIME(interval_dbl);
+       return 0;
+} /* config_get_interval */
+
+/*
+ * public parse results
+ */
+
+char **listen_addresses = NULL;
+size_t listen_addresses_num = 0;
+
+/*
+ * token parser
+ */
+
+typedef struct {
+       char *name;
+       int (*dispatcher)(oconfig_item_t *);
+} token_parser_t;
+
+static int
+daemon_add_listener(oconfig_item_t *ci)
+{
+       char **tmp;
+       char *address;
+
+       if (oconfig_get_string(ci, &address)) {
+               sdb_log(SDB_LOG_ERR, "config: Listen requires a single "
+                               "string argument\n"
+                               "\tUsage: Listen ADDRESS");
+               return ERR_INVALID_ARG;
+       }
+
+       tmp = realloc(listen_addresses,
+                       (listen_addresses_num + 1) * sizeof(*listen_addresses));
+       if (! tmp) {
+               char buf[1024];
+               sdb_log(SDB_LOG_ERR, "config: Failed to allocate memory: %s",
+                               sdb_strerror(errno, buf, sizeof(buf)));
+               return -1;
+       }
+
+       tmp[listen_addresses_num] = strdup(address);
+       if (! tmp[listen_addresses_num]) {
+               char buf[1024];
+               sdb_log(SDB_LOG_ERR, "config: Failed to allocate memory: %s",
+                               sdb_strerror(errno, buf, sizeof(buf)));
+               return -1;
+       }
+
+       listen_addresses = tmp;
+       ++listen_addresses_num;
+       return 0;
+} /* daemon_add_listener */
+
+static int
+daemon_set_interval(oconfig_item_t *ci)
+{
+       return config_get_interval(ci, &default_interval);
+} /* daemon_set_interval */
+
+static int
+daemon_load_plugin(oconfig_item_t *ci)
+{
+       char *name;
+       int i;
+
+       if (oconfig_get_string(ci, &name)) {
+               sdb_log(SDB_LOG_ERR, "config: LoadPlugin requires a single "
+                               "string argument\n"
+                               "\tUsage: LoadPlugin PLUGIN");
+               return ERR_INVALID_ARG;
+       }
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *child = ci->children + i;
+
+               /* we don't currently support any options */
+               sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
+                               "inside 'LoadPlugin' -- see the documentation for "
+                               "details.", child->key);
+               continue;
+       }
+
+       /* returns a negative value on error */
+       return sdb_plugin_load(name, NULL);
+} /* daemon_load_plugin */
+
+static int
+daemon_load_backend(oconfig_item_t *ci)
+{
+       sdb_plugin_ctx_t ctx = SDB_PLUGIN_CTX_INIT;
+
+       char  plugin_name[1024];
+       char *name;
+
+       int i;
+
+       ctx.interval = default_interval;
+
+       if (oconfig_get_string(ci, &name)) {
+               sdb_log(SDB_LOG_ERR, "config: LoadBackend requires a single "
+                               "string argument\n"
+                               "\tUsage: LoadBackend BACKEND");
+               return ERR_INVALID_ARG;
+       }
+
+       snprintf(plugin_name, sizeof(plugin_name), "backend::%s", name);
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *child = ci->children + i;
+
+               if (! strcasecmp(child->key, "Interval")) {
+                       if (config_get_interval(child, &ctx.interval))
+                               return ERR_INVALID_ARG;
+               }
+               else {
+                       sdb_log(SDB_LOG_WARNING, "config: Unknown option '%s' "
+                                       "inside 'LoadBackend' -- see the documentation for "
+                                       "details.", child->key);
+                       continue;
+               }
+       }
+
+       return sdb_plugin_load(plugin_name, &ctx);
+} /* daemon_load_backend */
+
+static int
+daemon_configure_plugin(oconfig_item_t *ci)
+{
+       char *name;
+
+       assert(ci);
+
+       if (oconfig_get_string(ci, &name)) {
+               sdb_log(SDB_LOG_ERR, "config: %s requires a single "
+                               "string argument\n"
+                               "\tUsage: LoadBackend BACKEND",
+                               ci->key);
+               return ERR_INVALID_ARG;
+       }
+
+       return sdb_plugin_configure(name, ci);
+} /* daemon_configure_backend */
+
+static token_parser_t token_parser_list[] = {
+       { "Listen", daemon_add_listener },
+       { "Interval", daemon_set_interval },
+       { "LoadPlugin", daemon_load_plugin },
+       { "LoadBackend", daemon_load_backend },
+       { "Backend", daemon_configure_plugin },
+       { "Plugin", daemon_configure_plugin },
+       { NULL, NULL },
+};
+
+/*
+ * public API
+ */
+
+int
+daemon_parse_config(const char *filename)
+{
+       oconfig_item_t *ci;
+       int retval = 0, i;
+
+       ci = oconfig_parse_file(filename);
+       if (! ci)
+               return ERR_PARSE_FAILED;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *child = ci->children + i;
+               int status = ERR_UNKNOWN_OPTION, j;
+
+               for (j = 0; token_parser_list[j].name; ++j) {
+                       if (! strcasecmp(token_parser_list[j].name, child->key))
+                               status = token_parser_list[j].dispatcher(child);
+               }
+
+               if (status) {
+                       sdb_error_set("config: Failed to parse option '%s'\n",
+                                       child->key);
+                       if (status == ERR_UNKNOWN_OPTION)
+                               sdb_error_append("\tUnknown option '%s' -- "
+                                               "see the documentation for details\n",
+                                               child->key);
+                       sdb_error_chomp();
+                       sdb_error_log(SDB_LOG_ERR);
+                       retval = status;
+               }
+       }
+       return retval;
+} /* daemon_parse_config */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/tools/sysdbd/configfile.h b/src/tools/sysdbd/configfile.h
new file mode 100644 (file)
index 0000000..19abe9a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SysDB - src/tools/sysdbd/configfile.h
+ * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+
+#ifndef DAEMON_CONFIG_H
+#define DAEMON_CONFIG_H 1
+
+/*
+ * parse result values
+ */
+
+extern char **listen_addresses;
+extern size_t listen_addresses_num;
+
+/*
+ * daemon_parse_config:
+ * Parse the specified configuration file.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - a negative value when loading the configuration failed because of errors
+ *    in the daemon or libsysdb
+ *  - a positive value on parser errors
+ */
+int
+daemon_parse_config(const char *filename);
+
+#endif /* ! DAEMON_CONFIG_H */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/tools/sysdbd/main.c b/src/tools/sysdbd/main.c
new file mode 100644 (file)
index 0000000..195d494
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * SysDB - src/tools/sysdbd/main.c
+ * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#      include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "sysdb.h"
+#include "core/plugin.h"
+#include "core/store.h"
+#include "utils/error.h"
+
+#include "frontend/sock.h"
+
+#include "tools/sysdbd/configfile.h"
+
+#if HAVE_LIBGEN_H
+#      include <libgen.h>
+#else /* HAVE_LIBGEN_H */
+#      define basename(path) (path)
+#endif /* ! HAVE_LIBGEN_H */
+
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <signal.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <pthread.h>
+
+#ifndef CONFIGFILE
+#      define CONFIGFILE SYSCONFDIR"/sysdb/sysdbd.conf"
+#endif
+
+#ifndef DEFAULT_SOCKET
+#      define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock"
+#endif
+
+static sdb_plugin_loop_t plugin_main_loop = SDB_PLUGIN_LOOP_INIT;
+static sdb_fe_loop_t frontend_main_loop = SDB_FE_LOOP_INIT;
+
+static char *default_listen_addresses[] = {
+       DEFAULT_SOCKET,
+};
+
+static void
+sigintterm_handler(int __attribute__((unused)) signo)
+{
+       frontend_main_loop.do_loop = 0;
+} /* sigintterm_handler */
+
+static void
+exit_usage(char *name, int status)
+{
+       printf(
+"Usage: %s <options>\n"
+
+"\nOptions:\n"
+"  -C FILE   the main configuration file\n"
+"            default: "CONFIGFILE"\n"
+"  -D        do not run in background (daemonize)\n"
+"\n"
+"  -h        display this help and exit\n"
+"  -V        display the version number and copyright\n"
+
+"\nSysDB daemon "SDB_VERSION_STRING SDB_VERSION_EXTRA", "PACKAGE_URL"\n",
+basename(name));
+       exit(status);
+} /* exit_usage */
+
+static void
+exit_version(void)
+{
+       printf("SysDBd version "SDB_VERSION_STRING SDB_VERSION_EXTRA", "
+                       "built "BUILD_DATE"\n"
+                       "using libsysdb version %s%s\n"
+                       "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n"
+
+                       "\nThis is free software under the terms of the BSD license, see "
+                       "the source for\ncopying conditions. There is NO WARRANTY; not "
+                       "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
+                       "PURPOSE.\n", sdb_version_string(), sdb_version_extra());
+       exit(0);
+} /* exit_version */
+
+static int
+daemonize(void)
+{
+       pid_t pid;
+
+       if ((pid = fork()) < 0) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Failed to fork to background: %s",
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               return errno;
+       }
+       else if (pid != 0) {
+               /* parent */
+               exit(0);
+       }
+
+       if (chdir("/")) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Failed to change working directory to "
+                               "the root directory: %s",
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               return errno;
+       }
+
+       /* detach from session */
+       setsid();
+
+       close(0);
+       if (open("/dev/null", O_RDWR)) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Failed to connect stdin to '/dev/null': %s",
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               return errno;
+       }
+
+       close(1);
+       if (dup(0) != 1) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Could not connect stdout to '/dev/null': %s",
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               return errno;
+       }
+
+       close(2);
+       if (dup(0) != 2) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Could not connect stderr to '/dev/null': %s",
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               return errno;
+       }
+       return 0;
+} /* daemonize */
+
+static void *
+backend_handler(void __attribute__((unused)) *data)
+{
+       sdb_plugin_collector_loop(&plugin_main_loop);
+       sdb_log(SDB_LOG_INFO, "Shutting down backend thread");
+       return NULL;
+} /* backend_handler */
+
+int
+main(int argc, char **argv)
+{
+       char *config_filename = NULL;
+       _Bool do_daemonize = 1;
+
+       pthread_t backend_thread;
+
+       struct sigaction sa_intterm;
+       int status;
+
+       sdb_error_set_logger(sdb_plugin_log);
+
+       while (42) {
+               int opt = getopt(argc, argv, "C:DhV");
+
+               if (-1 == opt)
+                       break;
+
+               switch (opt) {
+                       case 'C':
+                               config_filename = optarg;
+                               break;
+                       case 'D':
+                               do_daemonize = 0;
+                               break;
+
+                       case 'h':
+                               exit_usage(argv[0], 0);
+                               break;
+                       case 'V':
+                               exit_version();
+                               break;
+                       default:
+                               exit_usage(argv[0], 1);
+               }
+       }
+
+       if (optind < argc)
+               exit_usage(argv[0], 1);
+
+       if (! config_filename)
+               config_filename = CONFIGFILE;
+
+       if ((status = daemon_parse_config(config_filename))) {
+               if (status > 0)
+                       sdb_log(SDB_LOG_ERR, "Failed to parse configuration file.");
+               else
+                       sdb_log(SDB_LOG_ERR, "Failed to load configuration file.\n"
+                                       "\tCheck other error messages for details.");
+               exit(1);
+       }
+
+       if (! listen_addresses) {
+               listen_addresses = default_listen_addresses;
+               listen_addresses_num = SDB_STATIC_ARRAY_LEN(default_listen_addresses);
+       }
+
+       memset(&sa_intterm, 0, sizeof(sa_intterm));
+       sa_intterm.sa_handler = sigintterm_handler;
+       sa_intterm.sa_flags = 0;
+
+       if (sigaction(SIGINT, &sa_intterm, /* old action */ NULL)) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Failed to install signal handler for "
+                               "SIGINT: %s", sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               exit(1);
+       }
+       if (sigaction(SIGTERM, &sa_intterm, /* old action */ NULL)) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "Failed to install signal handler for "
+                               "SIGTERM: %s", sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               exit(1);
+       }
+
+       if (do_daemonize)
+               if (daemonize())
+                       exit(1);
+
+       sdb_log(SDB_LOG_INFO, "SysDB daemon "SDB_VERSION_STRING
+                       SDB_VERSION_EXTRA " (pid %i) initialized successfully",
+                       (int)getpid());
+
+       sdb_plugin_init_all();
+       plugin_main_loop.default_interval = SECS_TO_SDB_TIME(60);
+
+       memset(&backend_thread, 0, sizeof(backend_thread));
+       if (pthread_create(&backend_thread, /* attr = */ NULL,
+                               backend_handler, /* arg = */ NULL)) {
+               char buf[1024];
+               sdb_log(SDB_LOG_ERR, "Failed to create backend handler thread: %s",
+                               sdb_strerror(errno, buf, sizeof(buf)));
+
+               plugin_main_loop.do_loop = 0;
+       }
+       else {
+               size_t i;
+
+               sdb_fe_socket_t *sock = sdb_fe_sock_create();
+               for (i = 0; i < listen_addresses_num; ++i)
+                       if (sdb_fe_sock_add_listener(sock, listen_addresses[i]))
+                               break;
+
+               /* break on error */
+               if (i >= listen_addresses_num)
+                       sdb_fe_sock_listen_and_serve(sock, &frontend_main_loop);
+
+               sdb_log(SDB_LOG_INFO, "Waiting for backend thread to terminate");
+               plugin_main_loop.do_loop = 0;
+               pthread_kill(backend_thread, SIGINT);
+               pthread_join(backend_thread, NULL);
+               sdb_fe_sock_destroy(sock);
+       }
+
+       sdb_log(SDB_LOG_INFO, "Shutting down SysDB daemon "SDB_VERSION_STRING
+                       SDB_VERSION_EXTRA" (pid %i)", (int)getpid());
+       return 0;
+} /* main */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/tools/sysdbd/sysdbd.conf.sample b/src/tools/sysdbd/sysdbd.conf.sample
new file mode 100644 (file)
index 0000000..0976e80
--- /dev/null
@@ -0,0 +1,73 @@
+#
+# Sample configuration file for the System DataBase daemon (SysDBd).
+#
+
+#============================================================================#
+# Global options:                                                            #
+# This section defines global settings and default values for the daemon.    #
+#============================================================================#
+
+# default interval used for actively polling plugins
+Interval 300
+
+#============================================================================#
+# Logging settings:                                                          #
+# These plugins should be loaded first. Else, any log messages will be       #
+# written to the standard error channel which is closed after the daemon has #
+# started.                                                                   #
+#============================================================================#
+LoadPlugin "syslog"
+
+#============================================================================#
+# Plugins:                                                                   #
+# Plugins are the working horses of SysDB. Load any of the following plugins #
+# to active the respective feature.                                          #
+#============================================================================#
+
+#----------------------------------------------------------------------------#
+# "cname" plugins canonicalize hostnames before actually storing them. All   #
+# cname callbacks are applied to an hostname in the order in which they have #
+# been loaded, each receiving the result of the previous call.               #
+#----------------------------------------------------------------------------#
+LoadPlugin "cname::dns"
+
+#----------------------------------------------------------------------------#
+# "Backends" are plugins which collect information to be stored in SysDB.    #
+# Each backend may use its own custom query interval by specifying the       #
+# 'Interval' option:                                                         #
+#   <LoadBackend "foo">                                                      #
+#       Interval 60                                                          #
+#   </LoadPlugin>                                                            #
+#----------------------------------------------------------------------------#
+LoadBackend "collectd::unixsock"
+LoadBackend "mk-livestatus"
+LoadBackend "puppet::store-configs"
+
+#----------------------------------------------------------------------------#
+# Plugin configuration:                                                      #
+#----------------------------------------------------------------------------#
+
+<Backend "collectd::unixsock">
+       <Instance "central-collector">
+               Socket "/var/run/collectd-unixsock"
+       </Instance>
+</Backend>
+
+<Backend "mk-livestatus">
+       <Instance "nagios4-master">
+               Socket "/var/lib/nagios4/rw/live"
+       </Instance>
+</Backend>
+
+<Backend "puppet::store-configs">
+       <Connection "puppet">
+               DBAdapter "pgsql"
+               DBName "puppet"
+               DBServer "puppet.domain.tld"
+               DBPort "5432"
+               DBUser "puppet"
+               DBPassword "secret1"
+               DBIOption "name" "value"
+       </Connection>
+</Backend>
+
index 26926183e4528a71dd0d495c10377d0c6adbfa67..d9bd3691391ad80a0728a2f9ac88c03033627fa4 100644 (file)
@@ -284,8 +284,10 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client)
        if ((! client) || (! client->driver) || (! client->database))
                return -1;
 
-       if (client->conn)
+       if (client->conn) {
                dbi_conn_close(client->conn);
+               client->conn = NULL;
+       }
 
        driver = dbi_driver_open(client->driver);
        if (! driver) {
@@ -332,6 +334,7 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client)
                        sdb_error_log(SDB_LOG_ERR);
 
                        dbi_conn_close(client->conn);
+                       client->conn = NULL;
                        return -1;
                }
        }
@@ -340,6 +343,7 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client)
                sdb_log(SDB_LOG_ERR, "dbi: failed to set option 'dbname': %s",
                                sdb_dbi_strerror(client->conn));
                dbi_conn_close(client->conn);
+               client->conn = NULL;
                return -1;
        }
 
@@ -347,6 +351,7 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client)
                sdb_log(SDB_LOG_ERR, "dbi: failed to connect to database '%s': %s",
                                client->database, sdb_dbi_strerror(client->conn));
                dbi_conn_close(client->conn);
+               client->conn = NULL;
                return -1;
        }
        return 0;
@@ -467,6 +472,7 @@ sdb_dbi_client_destroy(sdb_dbi_client_t *client)
 
        if (client->conn)
                dbi_conn_close(client->conn);
+       client->conn = NULL;
 
        if (client->options)
                sdb_dbi_options_destroy(client->options);
index 6190e3a8a045a650c26067a0d637003bf321ded9..ee419b7ea20994efaeeaac3d6ae1d246c402dcb0 100644 (file)
@@ -311,6 +311,16 @@ sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t offset, size_t n)
        strbuf->string[strbuf->pos] = '\0';
 } /* sdb_strbuf_skip */
 
+void
+sdb_strbuf_clear(sdb_strbuf_t *strbuf)
+{
+       if ((! strbuf) || (! strbuf->size))
+               return;
+
+       strbuf->string[0] = '\0';
+       strbuf->pos = 0;
+} /* sdb_strbuf_clear */
+
 const char *
 sdb_strbuf_string(sdb_strbuf_t *strbuf)
 {
index c68a23efcf22df1157d2ac4adb02ceaf5f3b7f38..0acb1de0521849d6533a347fd8a8858a106ce72b 100644 (file)
@@ -55,7 +55,7 @@ teardown(void)
  * tests
  */
 
-START_TEST(test_empty)
+START_TEST(test_null)
 {
        sdb_strbuf_t *b = NULL;
        va_list ap;
@@ -65,6 +65,7 @@ START_TEST(test_empty)
        sdb_strbuf_skip(b, 0, 0);
        sdb_strbuf_skip(b, 0, 10);
        sdb_strbuf_skip(b, 10, 10);
+       sdb_strbuf_clear(b);
 
        /* check that methods return an error */
        fail_unless(sdb_strbuf_vappend(b, "test", ap) < 0,
@@ -86,6 +87,28 @@ START_TEST(test_empty)
 }
 END_TEST
 
+START_TEST(test_empty)
+{
+       sdb_strbuf_t *b = sdb_strbuf_create(0);
+       const char *data;
+       size_t len;
+
+       /* check that methods don't crash */
+       sdb_strbuf_skip(b, 1, 1);
+       sdb_strbuf_clear(b);
+       sdb_strbuf_chomp(b);
+
+       data = sdb_strbuf_string(b);
+       fail_unless(data && (*data == '\0'),
+                       "sdb_strbuf_string(<empty>) = '%s'; expected: ''", data);
+       len = sdb_strbuf_len(b);
+       fail_unless(len == 0,
+                       "sdb_strbuf_len(<empty>) = %zu; expected: 0", len);
+
+       sdb_strbuf_destroy(b);
+}
+END_TEST
+
 START_TEST(test_sdb_strbuf_create)
 {
        sdb_strbuf_t *s;
@@ -424,6 +447,27 @@ START_TEST(test_sdb_strbuf_skip)
 }
 END_TEST
 
+START_TEST(test_sdb_strbuf_clear)
+{
+       const char *data;
+       size_t len;
+
+       sdb_strbuf_append(buf, "abc");
+       len = sdb_strbuf_len(buf);
+       fail_unless(len != 0,
+                       "sdb_strbuf_len() = %zu; expected: != 0", len);
+
+       sdb_strbuf_clear(buf);
+       len = sdb_strbuf_len(buf);
+       fail_unless(len == 0,
+                       "sdb_strbuf_len() = %zu (after clear); expected: 0", len);
+
+       data = sdb_strbuf_string(buf);
+       fail_unless(*data == '\0',
+                       "sdb_strbuf_string() = '%s' (after clear); expected: ''", data);
+}
+END_TEST
+
 static struct {
        const char *input;
        const char *expected;
@@ -483,6 +527,7 @@ util_strbuf_suite(void)
        TCase *tc;
 
        tc = tcase_create("empty");
+       tcase_add_test(tc, test_null);
        tcase_add_test(tc, test_empty);
        suite_add_tcase(s, tc);
 
@@ -496,6 +541,7 @@ util_strbuf_suite(void)
        tcase_add_test(tc, test_sdb_strbuf_memappend);
        tcase_add_test(tc, test_sdb_strbuf_chomp);
        tcase_add_test(tc, test_sdb_strbuf_skip);
+       tcase_add_test(tc, test_sdb_strbuf_clear);
        tcase_add_test(tc, test_sdb_strbuf_string);
        tcase_add_test(tc, test_sdb_strbuf_len);
        suite_add_tcase(s, tc);