From: Sebastian Harl Date: Fri, 20 Dec 2013 19:09:48 +0000 (+0100) Subject: Merged branch 'master' of git://git.tokkee.org/sysdb. X-Git-Tag: sysdb-0.1.0~300 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=edba65afec8c547fb6c02346eda68595ce9a5839;hp=6e7b1987b6a571c0f2815b8507ec9373981f058e Merged branch 'master' of git://git.tokkee.org/sysdb. --- diff --git a/.gitignore b/.gitignore index 63813b0..e7c950e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ src/config.h* Makefile Makefile.in aclocal.m4 +ar-lib autom4te.cache compile /config.* @@ -31,13 +32,13 @@ ltmain.sh src/liboconfig/parser.c src/liboconfig/parser.h src/liboconfig/scanner.c +src/sysdb +src/sysdbd .dirstamp .libs *.la *.lo *.o -sysdb -sysdbd sysdbd.1 sysdbd.conf.5 sysdb.h diff --git a/configure.ac b/configure.ac index dde7727..b7a07e6 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ AC_CONFIG_SRCDIR([src/sysdb.c]) AC_CONFIG_HEADERS([src/config.h]) AC_PREFIX_DEFAULT([/opt/sysdb]) -AM_INIT_AUTOMAKE([foreign -Wall]) +AM_INIT_AUTOMAKE([foreign subdir-objects -Wall]) AC_LANG(C) @@ -48,6 +48,7 @@ AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET +AM_PROG_AR AM_PROG_CC_C_O AM_PROG_LEX @@ -184,6 +185,9 @@ if test "x$enable_strict_checks" = "xyes"; then fi AC_SUBST([STRICT_CFLAGS]) +m4_divert_once([HELP_ENABLE], [ +Build dependencies:]) + dnl Testing. PKG_CHECK_MODULES([CHECK], [check >= 0.9.4], [build_testing="yes"], [build_testing="no"]) @@ -219,6 +223,82 @@ if test "x$have_fopencookie" = "xyes"; then AC_DEFINE([HAVE_FOPENCOOKIE], 1) fi +dnl readline support +AC_ARG_WITH([readline], + [AS_HELP_STRING([--with-readline], + [readline support (libedit/libreadline) (default: auto, prefer libedit)])], + [readline_support="$withval"], + [readline_support="auto"]) + +if test "x$readline_support" = "xyes"; then + readline_support="auto" +fi + +have_libedit="no" +if test "x$readline_support" = "xauto" \ + || test "x$readline_support" = "xlibedit"; then + PKG_CHECK_MODULES([LIBEDIT], [libedit], + [have_libedit="yes"], [have_libedit="no"]) + if test "x$have_libedit" = "xyes"; then + AC_CHECK_HEADERS([editline/readline.h], [], + [AC_CHECK_HEADERS([readline.h], [], + [have_libedit="no (readline header not found"])]) + fi + if test "x$have_libedit" = "xyes"; then + AC_CHECK_HEADERS([editline/history.h], [], + [AC_CHECK_HEADERS([history.h], [], + [have_libedit="no (history header not found"])]) + fi +else + have_libedit="disabled on command-line" +fi + +have_libreadline="no" +if test "x$have_libedit" = "xno"; then + if test "x$readline_support" = "xauto" \ + || test "x$readline_support" = "xlibreadline"; then + AC_CHECK_LIB([readline], [readline], + [have_libreadline="yes"], + [have_libreadline="no (libreadline or symbol 'readline' not found)"]) + fi + if test "x$have_libreadline" = "xyes"; then + AC_CHECK_HEADERS([readline/readline.h], [], + [AC_CHECK_HEADERS([readline.h], [], + [have_libreadline="no (readline header not found"])]) + fi + if test "x$have_libreadline" = "xyes"; then + AC_CHECK_HEADERS([readline/history.h], [], + [AC_CHECK_HEADERS([history.h], [], + [have_libreadline="no (history header not found"])]) + fi +else + have_libreadline="unchecked (prefer libedit)" +fi + +if test "x$have_libedit" = "xyes"; then + READLINE_LIBS="$LIBEDIT_LIBS" + READLINE_CFLAGS="$LIBEDIT_CFLAGS" + readline_support="libedit" +else if test "x$have_libreadline" = "xyes"; then + READLINE_LIBS="-lreadline -lhistory" + READLINE_CFLAGS="" + readline_support="libreadline" +else + READLINE_LIBS="" + READLINE_CFLAGS="" + if test "x$readline_support" = "xno"; then + AC_MSG_WARN([*** readline support disabled; disabling SysDB client]) + else if test "x$readline_support" = "xauto"; then + AC_MSG_WARN([*** readline not found; disabling SysDB client]) + else + AC_MSG_ERROR([readline not found]) + fi; fi + readline_support="no" +fi; fi +AC_SUBST([READLINE_LIBS]) +AC_SUBST([READLINE_CFLAGS]) +AM_CONDITIONAL([BUILD_CLIENT], test "x$readline_support" != "no") + dnl Feature checks. build_documentation="yes" @@ -296,6 +376,8 @@ AC_MSG_RESULT([ stdio mocking: . . . . . $have_fopencookie]) AC_MSG_RESULT() AC_MSG_RESULT([ Libraries:]) AC_MSG_RESULT([ libdbi: . . . . . . . . . . $with_libdbi]) +AC_MSG_RESULT([ libedit: . . . . . . . . . $have_libedit]) +AC_MSG_RESULT([ libreadline: . . . . . . . $have_libreadline]) AC_MSG_RESULT() AC_MSG_RESULT([ Backends:]) AC_MSG_RESULT([ collectd: . . . . . . . . . $enable_collectd]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 35c3a4a..a89ea25 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,3 +1,5 @@ +SUFFIXES = .1 .5 .1.txt .5.txt + EXTRA_DIST = \ sysdbd.1.txt \ sysdbd.conf.5.txt @@ -13,13 +15,13 @@ sysdbd.1: sysdbd.1.txt ../version sysdbd.conf.5: sysdbd.conf.5.txt ../version -%.1: %.1.txt +.1.txt.1: @A2X@ -d manpage -f manpage \ -apackage_version=$(PACKAGE_VERSION) \ -abuild_date="$$( date --utc '+%F' )" \ $< -%.5: %.5.txt +.5.txt.5: @A2X@ -d manpage -f manpage \ -apackage_version=$(PACKAGE_VERSION) \ -abuild_date="$$( date --utc '+%F' )" \ diff --git a/src/Makefile.am b/src/Makefile.am index e547fa4..3f5a007 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -79,20 +79,24 @@ libsysdb_la_SOURCES += \ libsysdb_la_LIBADD += -ldbi endif -bin_PROGRAMS = sysdb sysdbd - -sysdb_SOURCES = client/sysdb.c include/client/sysdb.h -sysdb_CFLAGS = $(AM_CFLAGS) -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\"" -sysdb_LDADD = libsysdbclient.la +bin_PROGRAMS = sysdbd +if BUILD_CLIENT +bin_PROGRAMS += sysdb + +sysdb_SOURCES = tools/sysdb/main.c include/client/sysdb.h +sysdb_CFLAGS = -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\"" \ + $(AM_CFLAGS) @READLINE_CFLAGS@ +sysdb_LDADD = libsysdbclient.la @READLINE_LIBS@ +endif -sysdbd_SOURCES = daemon/sysdbd.c include/sysdb.h \ - daemon/config.c include/daemon/config.h +sysdbd_SOURCES = tools/sysdbd/main.c include/sysdb.h \ + tools/sysdbd/configfile.c tools/sysdbd/configfile.h sysdbd_CFLAGS = $(AM_CFLAGS) -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\"" sysdbd_LDADD = libsysdb.la liboconfig/liboconfig.la sysdbd_DEPENDENCIES = liboconfig/liboconfig.la sdbconfdir = $(sysconfdir)/sysdb -dist_sdbconf_DATA = daemon/sysdbd.conf.sample +dist_sdbconf_DATA = tools/sysdbd/sysdbd.conf.sample pkgbackendlibdir = $(pkglibdir)/backend pkgbackendcollectdlibdir = $(pkgbackendlibdir)/collectd diff --git a/src/client/sysdb.c b/src/client/sysdb.c deleted file mode 100644 index c2b542d..0000000 --- a/src/client/sysdb.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * SysDB - src/client/sysdb.c - * Copyright (C) 2013 Sebastian 'tokkee' Harl - * 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 - -#if HAVE_LIBGEN_H -# include -#else /* HAVE_LIBGEN_H */ -# define basename(path) (path) -#endif /* ! HAVE_LIBGEN_H */ - -#include -#include - -#include -#include -#include - -#include - -#include - -#include - -#ifndef DEFAULT_SOCKET -# define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock" -#endif - -static void -exit_usage(char *name, int status) -{ - printf( -"Usage: %s \n" - -"\nOptions:\n" -" -h display this help and exit\n" -" -V display the version number and copyright\n" - -"\nSysDB client "SDB_CLIENT_VERSION_STRING SDB_CLIENT_VERSION_EXTRA", " -PACKAGE_URL"\n", basename(name)); - exit(status); -} /* exit_usage */ - -static void -exit_version(void) -{ - printf("SysDB version "SDB_CLIENT_VERSION_STRING - SDB_CLIENT_VERSION_EXTRA", built "BUILD_DATE"\n" - "using libsysdbclient version %s%s\n" - "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n" - - "\nThis is free software under the terms of the BSD license, see " - "the source for\ncopying conditions. There is NO WARRANTY; not " - "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR " - "PURPOSE.\n", sdb_client_version_string(), - sdb_client_version_extra()); - exit(0); -} /* exit_version */ - -static const char * -get_current_user(void) -{ - struct passwd pw_entry; - struct passwd *result = NULL; - - uid_t uid; - - /* needs to be static because we return a pointer into this buffer - * to the caller */ - static char buf[1024]; - - int status; - - uid = geteuid(); - - memset(&pw_entry, 0, sizeof(pw_entry)); - status = getpwuid_r(uid, &pw_entry, buf, sizeof(buf), &result); - - if (status || (! result)) { - char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "Failed to determine current username: %s", - sdb_strerror(errno, errbuf, sizeof(errbuf))); - return NULL; - } - return result->pw_name; -} /* get_current_user */ - -int -main(int argc, char **argv) -{ - sdb_client_t *client; - - const char *host = NULL; - const char *user = NULL; - - while (42) { - int opt = getopt(argc, argv, "H:U:hV"); - - if (-1 == opt) - break; - - switch (opt) { - case 'H': - host = optarg; - break; - case 'U': - user = optarg; - break; - - case 'h': - exit_usage(argv[0], 0); - break; - case 'V': - exit_version(); - break; - default: - exit_usage(argv[0], 1); - } - } - - if (optind < argc) - exit_usage(argv[0], 1); - - if (! host) - host = DEFAULT_SOCKET; - if (! user) { - user = get_current_user(); - if (! user) - exit(1); - } - - client = sdb_client_create(host); - if (! client) { - sdb_log(SDB_LOG_ERR, "Failed to create client object"); - exit(1); - } - if (sdb_client_connect(client, user)) { - sdb_log(SDB_LOG_ERR, "Failed to connect to SysDBd"); - sdb_client_destroy(client); - exit(1); - } - - sdb_log(SDB_LOG_INFO, "SysDB client "SDB_CLIENT_VERSION_STRING - SDB_CLIENT_VERSION_EXTRA"\n"); - - sdb_client_destroy(client); - return 0; -} /* main */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/src/daemon/config.c b/src/daemon/config.c deleted file mode 100644 index 906f4c5..0000000 --- a/src/daemon/config.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * SysDB - src/daemon/config.c - * Copyright (C) 2012 Sebastian 'tokkee' Harl - * 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 -#include - -#include -#include -#include - -/* - * 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 index 21350f3..0000000 --- a/src/daemon/sysdbd.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * SysDB - src/sysdbd.c - * Copyright (C) 2012 Sebastian 'tokkee' Harl - * 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 -#else /* HAVE_LIBGEN_H */ -# define basename(path) (path) -#endif /* ! HAVE_LIBGEN_H */ - -#include - -#include -#include - -#include - -#include -#include -#include - -#include - -#include - -#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 \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 index 0976e80..0000000 --- a/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: # -# # -# Interval 60 # -# # -#----------------------------------------------------------------------------# -LoadBackend "collectd::unixsock" -LoadBackend "mk-livestatus" -LoadBackend "puppet::store-configs" - -#----------------------------------------------------------------------------# -# Plugin configuration: # -#----------------------------------------------------------------------------# - - - - Socket "/var/run/collectd-unixsock" - - - - - - Socket "/var/lib/nagios4/rw/live" - - - - - - DBAdapter "pgsql" - DBName "puppet" - DBServer "puppet.domain.tld" - DBPort "5432" - DBUser "puppet" - DBPassword "secret1" - DBIOption "name" "value" - - - diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h new file mode 100644 index 0000000..6cf7395 --- /dev/null +++ b/src/frontend/connection-private.h @@ -0,0 +1,77 @@ +/* + * SysDB - src/include/frontend/connection-private.h + * Copyright (C) 2013 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * private data structures used by frontend modules + */ + +#ifndef SDB_FRONTEND_CONNECTION_PRIVATE_H +#define SDB_FRONTEND_CONNECTION_PRIVATE_H 1 + +#include "core/object.h" +#include "utils/strbuf.h" +#include "frontend/connection.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sdb_conn { + sdb_object_t super; + + /* file-descriptor of the open connection */ + int fd; + + /* connection and client information */ + struct sockaddr_storage client_addr; + socklen_t client_addr_len; + + /* read buffer */ + sdb_strbuf_t *buf; + + /* connection / protocol state information */ + uint32_t cmd; + uint32_t cmd_len; + + sdb_strbuf_t *errbuf; + + /* user information */ + char *username; /* NULL if the user has not been authenticated */ +}; +#define CONN(obj) ((sdb_conn_t *)(obj)) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ! SDB_FRONTEND_CONNECTION_H */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/include/daemon/config.h b/src/include/daemon/config.h deleted file mode 100644 index 0fe278d..0000000 --- a/src/include/daemon/config.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SysDB - src/daemon/config.h - * Copyright (C) 2012 Sebastian 'tokkee' Harl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DAEMON_CONFIG_H -#define DAEMON_CONFIG_H 1 - -/* - * parse result values - */ - -extern char **listen_addresses; -extern size_t listen_addresses_num; - -/* - * daemon_parse_config: - * Parse the specified configuration file. - * - * Returns: - * - 0 on success - * - a negative value when loading the configuration failed because of errors - * in the daemon or libsysdb - * - a positive value on parser errors - */ -int -daemon_parse_config(const char *filename); - -#endif /* ! DAEMON_CONFIG_H */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/src/include/frontend/connection-private.h b/src/include/frontend/connection-private.h deleted file mode 100644 index 6cf7395..0000000 --- a/src/include/frontend/connection-private.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SysDB - src/include/frontend/connection-private.h - * Copyright (C) 2013 Sebastian 'tokkee' Harl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * private data structures used by frontend modules - */ - -#ifndef SDB_FRONTEND_CONNECTION_PRIVATE_H -#define SDB_FRONTEND_CONNECTION_PRIVATE_H 1 - -#include "core/object.h" -#include "utils/strbuf.h" -#include "frontend/connection.h" - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct sdb_conn { - sdb_object_t super; - - /* file-descriptor of the open connection */ - int fd; - - /* connection and client information */ - struct sockaddr_storage client_addr; - socklen_t client_addr_len; - - /* read buffer */ - sdb_strbuf_t *buf; - - /* connection / protocol state information */ - uint32_t cmd; - uint32_t cmd_len; - - sdb_strbuf_t *errbuf; - - /* user information */ - char *username; /* NULL if the user has not been authenticated */ -}; -#define CONN(obj) ((sdb_conn_t *)(obj)) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* ! SDB_FRONTEND_CONNECTION_H */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/src/include/utils/strbuf.h b/src/include/utils/strbuf.h index 900a453..96b4f86 100644 --- a/src/include/utils/strbuf.h +++ b/src/include/utils/strbuf.h @@ -144,6 +144,13 @@ sdb_strbuf_chomp(sdb_strbuf_t *strbuf); void sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t offset, size_t n); +/* + * sdb_strbuf_clear: + * Clear the buffer but do not deallocate memory. + */ +void +sdb_strbuf_clear(sdb_strbuf_t *strbuf); + /* * sdb_strbuf_string: * Returns the content of the string buffer. The caller may not modify the diff --git a/src/tools/sysdb/main.c b/src/tools/sysdb/main.c new file mode 100644 index 0000000..0639e5f --- /dev/null +++ b/src/tools/sysdb/main.c @@ -0,0 +1,281 @@ +/* + * SysDB - src/tools/sysdb/main.c + * Copyright (C) 2013 Sebastian 'tokkee' Harl + * 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 + +#if HAVE_LIBGEN_H +# include +#else /* HAVE_LIBGEN_H */ +# define basename(path) (path) +#endif /* ! HAVE_LIBGEN_H */ + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#if HAVE_EDITLINE_READLINE_H +# include +# if HAVE_EDITLINE_HISTORY_H +# include +# endif +#elif HAVE_READLINE_READLINE_H +# include +# if HAVE_READLINE_HISTORY_H +# include +# endif +#elif HAVE_READLINE_H +# include +# if HAVE_HISTORY_H +# include +# 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 \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 index 0000000..9527626 --- /dev/null +++ b/src/tools/sysdbd/configfile.c @@ -0,0 +1,284 @@ +/* + * SysDB - src/tools/sysdbd/configfile.c + * Copyright (C) 2012 Sebastian 'tokkee' Harl + * 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 +#include + +#include +#include +#include + +/* + * 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 index 0000000..19abe9a --- /dev/null +++ b/src/tools/sysdbd/configfile.h @@ -0,0 +1,56 @@ +/* + * SysDB - src/tools/sysdbd/configfile.h + * Copyright (C) 2012 Sebastian 'tokkee' Harl + * 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 + +#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 index 0000000..195d494 --- /dev/null +++ b/src/tools/sysdbd/main.c @@ -0,0 +1,298 @@ +/* + * SysDB - src/tools/sysdbd/main.c + * Copyright (C) 2012 Sebastian 'tokkee' Harl + * 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 +#else /* HAVE_LIBGEN_H */ +# define basename(path) (path) +#endif /* ! HAVE_LIBGEN_H */ + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#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 \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 index 0000000..0976e80 --- /dev/null +++ b/src/tools/sysdbd/sysdbd.conf.sample @@ -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: # +# # +# Interval 60 # +# # +#----------------------------------------------------------------------------# +LoadBackend "collectd::unixsock" +LoadBackend "mk-livestatus" +LoadBackend "puppet::store-configs" + +#----------------------------------------------------------------------------# +# Plugin configuration: # +#----------------------------------------------------------------------------# + + + + Socket "/var/run/collectd-unixsock" + + + + + + Socket "/var/lib/nagios4/rw/live" + + + + + + DBAdapter "pgsql" + DBName "puppet" + DBServer "puppet.domain.tld" + DBPort "5432" + DBUser "puppet" + DBPassword "secret1" + DBIOption "name" "value" + + + diff --git a/src/utils/dbi.c b/src/utils/dbi.c index 2692618..d9bd369 100644 --- a/src/utils/dbi.c +++ b/src/utils/dbi.c @@ -284,8 +284,10 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client) if ((! client) || (! client->driver) || (! client->database)) return -1; - if (client->conn) + if (client->conn) { dbi_conn_close(client->conn); + client->conn = NULL; + } driver = dbi_driver_open(client->driver); if (! driver) { @@ -332,6 +334,7 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client) sdb_error_log(SDB_LOG_ERR); dbi_conn_close(client->conn); + client->conn = NULL; return -1; } } @@ -340,6 +343,7 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client) sdb_log(SDB_LOG_ERR, "dbi: failed to set option 'dbname': %s", sdb_dbi_strerror(client->conn)); dbi_conn_close(client->conn); + client->conn = NULL; return -1; } @@ -347,6 +351,7 @@ sdb_dbi_client_connect(sdb_dbi_client_t *client) sdb_log(SDB_LOG_ERR, "dbi: failed to connect to database '%s': %s", client->database, sdb_dbi_strerror(client->conn)); dbi_conn_close(client->conn); + client->conn = NULL; return -1; } return 0; @@ -467,6 +472,7 @@ sdb_dbi_client_destroy(sdb_dbi_client_t *client) if (client->conn) dbi_conn_close(client->conn); + client->conn = NULL; if (client->options) sdb_dbi_options_destroy(client->options); diff --git a/src/utils/strbuf.c b/src/utils/strbuf.c index 6190e3a..ee419b7 100644 --- a/src/utils/strbuf.c +++ b/src/utils/strbuf.c @@ -311,6 +311,16 @@ sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t offset, size_t n) strbuf->string[strbuf->pos] = '\0'; } /* sdb_strbuf_skip */ +void +sdb_strbuf_clear(sdb_strbuf_t *strbuf) +{ + if ((! strbuf) || (! strbuf->size)) + return; + + strbuf->string[0] = '\0'; + strbuf->pos = 0; +} /* sdb_strbuf_clear */ + const char * sdb_strbuf_string(sdb_strbuf_t *strbuf) { diff --git a/t/utils/strbuf_test.c b/t/utils/strbuf_test.c index c68a23e..0acb1de 100644 --- a/t/utils/strbuf_test.c +++ b/t/utils/strbuf_test.c @@ -55,7 +55,7 @@ teardown(void) * tests */ -START_TEST(test_empty) +START_TEST(test_null) { sdb_strbuf_t *b = NULL; va_list ap; @@ -65,6 +65,7 @@ START_TEST(test_empty) sdb_strbuf_skip(b, 0, 0); sdb_strbuf_skip(b, 0, 10); sdb_strbuf_skip(b, 10, 10); + sdb_strbuf_clear(b); /* check that methods return an error */ fail_unless(sdb_strbuf_vappend(b, "test", ap) < 0, @@ -86,6 +87,28 @@ START_TEST(test_empty) } END_TEST +START_TEST(test_empty) +{ + sdb_strbuf_t *b = sdb_strbuf_create(0); + const char *data; + size_t len; + + /* check that methods don't crash */ + sdb_strbuf_skip(b, 1, 1); + sdb_strbuf_clear(b); + sdb_strbuf_chomp(b); + + data = sdb_strbuf_string(b); + fail_unless(data && (*data == '\0'), + "sdb_strbuf_string() = '%s'; expected: ''", data); + len = sdb_strbuf_len(b); + fail_unless(len == 0, + "sdb_strbuf_len() = %zu; expected: 0", len); + + sdb_strbuf_destroy(b); +} +END_TEST + START_TEST(test_sdb_strbuf_create) { sdb_strbuf_t *s; @@ -424,6 +447,27 @@ START_TEST(test_sdb_strbuf_skip) } END_TEST +START_TEST(test_sdb_strbuf_clear) +{ + const char *data; + size_t len; + + sdb_strbuf_append(buf, "abc"); + len = sdb_strbuf_len(buf); + fail_unless(len != 0, + "sdb_strbuf_len() = %zu; expected: != 0", len); + + sdb_strbuf_clear(buf); + len = sdb_strbuf_len(buf); + fail_unless(len == 0, + "sdb_strbuf_len() = %zu (after clear); expected: 0", len); + + data = sdb_strbuf_string(buf); + fail_unless(*data == '\0', + "sdb_strbuf_string() = '%s' (after clear); expected: ''", data); +} +END_TEST + static struct { const char *input; const char *expected; @@ -483,6 +527,7 @@ util_strbuf_suite(void) TCase *tc; tc = tcase_create("empty"); + tcase_add_test(tc, test_null); tcase_add_test(tc, test_empty); suite_add_tcase(s, tc); @@ -496,6 +541,7 @@ util_strbuf_suite(void) tcase_add_test(tc, test_sdb_strbuf_memappend); tcase_add_test(tc, test_sdb_strbuf_chomp); tcase_add_test(tc, test_sdb_strbuf_skip); + tcase_add_test(tc, test_sdb_strbuf_clear); tcase_add_test(tc, test_sdb_strbuf_string); tcase_add_test(tc, test_sdb_strbuf_len); suite_add_tcase(s, tc);