summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 084367e)
raw | patch | inline | side by side (parent: 084367e)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 15 Dec 2013 15:36:41 +0000 (16:36 +0100) | ||
committer | Sebastian 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.
Renamed some files for greater consistency.
src/Makefile.am | patch | blob | history | |
src/client/sysdb.c | [deleted file] | patch | blob | history |
src/daemon/config.c | [deleted file] | patch | blob | history |
src/daemon/sysdbd.c | [deleted file] | patch | blob | history |
src/daemon/sysdbd.conf.sample | [deleted file] | patch | blob | history |
src/include/daemon/config.h | [deleted file] | patch | blob | history |
src/tools/sysdb/main.c | [new file with mode: 0644] | patch | blob |
src/tools/sysdbd/configfile.c | [new file with mode: 0644] | patch | blob |
src/tools/sysdbd/configfile.h | [new file with mode: 0644] | patch | blob |
src/tools/sysdbd/main.c | [new file with mode: 0644] | patch | blob |
src/tools/sysdbd/sysdbd.conf.sample | [new file with mode: 0644] | patch | blob |
diff --git a/src/Makefile.am b/src/Makefile.am
index 3b1de0aeb797532ee20615482151dda044a28542..3f5a0071081afd13a71189fb87b6900d20bf9e5e 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
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
--- a/src/client/sysdb.c
+++ /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
--- a/src/daemon/config.c
+++ /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
--- a/src/daemon/sysdbd.c
+++ /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
+++ /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
+++ /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
--- /dev/null
+++ b/src/tools/sysdb/main.c
@@ -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
--- /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
--- /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
--- /dev/null
+++ b/src/tools/sysdbd/main.c
@@ -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
--- /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>
+