Code

Moved sysdb and sysdbd sources to src/tools/.
authorSebastian Harl <sh@tokkee.org>
Sun, 15 Dec 2013 15:36:41 +0000 (16:36 +0100)
committerSebastian Harl <sh@tokkee.org>
Sun, 15 Dec 2013 15:36:41 +0000 (16:36 +0100)
Also, moved all purely private headers to that directory as well.
Renamed some files for greater consistency.

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/include/daemon/config.h [deleted file]
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]

index 3b1de0aeb797532ee20615482151dda044a28542..3f5a0071081afd13a71189fb87b6900d20bf9e5e 100644 (file)
@@ -83,20 +83,20 @@ bin_PROGRAMS = sysdbd
 if BUILD_CLIENT
 bin_PROGRAMS += sysdb
 
-sysdb_SOURCES = client/sysdb.c include/client/sysdb.h
+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 ecadb4c..0000000
+++ /dev/null
@@ -1,281 +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 "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/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/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/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>
+