From 96aeb227f354885b80c8d6fefb6d31fd93891696 Mon Sep 17 00:00:00 2001 From: octo Date: Wed, 14 Dec 2005 08:56:37 +0000 Subject: [PATCH] Added `configfile.[ch]' to configfile-branch (forgot that yesterday) Added a call to `cf_register' to `ping.c' to test everything --- src/configfile.c | 358 +++++++++++++++++++++++++++++++++++++++++++++++ src/configfile.h | 76 ++++++++++ src/ping.c | 31 ++++ src/plugin.h | 1 + 4 files changed, 466 insertions(+) create mode 100644 src/configfile.c create mode 100644 src/configfile.h diff --git a/src/configfile.c b/src/configfile.c new file mode 100644 index 00000000..f93eda02 --- /dev/null +++ b/src/configfile.c @@ -0,0 +1,358 @@ +/** + * collectd - src/configfile.c + * Copyright (C) 2005 Florian octo Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +/* + * FIXME: + * - remove all (I mean *ALL*) calls to `fprintf': `stderr' will have been + * closed. + */ + +#include "collectd.h" + +#include "libconfig/libconfig.h" + +#include "configfile.h" +#include "utils_debug.h" + +#define SHORTOPT_NONE 0 + +#define ERR_NOT_NESTED "Sections cannot be nested.\n" +#define ERR_SECTION_ONLY "`%s' can only be used as section.\n" +#define ERR_NEEDS_ARG "Section `%s' needs an argument.\n" +#define ERR_NEEDS_SECTION "`%s' can only be used within a section.\n" + +typedef struct cf_callback +{ + char *type; + int (*callback) (char *, char *); + char **keys; + int keys_num; + struct cf_callback *next; +} cf_callback_t; + +static cf_callback_t *first_callback = NULL; + +static int nesting_depth = 0; +static char *current_module = NULL; + +/* cf_register needs this prototype */ +int cf_callback_general (const char *, const char *, const char *, + const char *, lc_flags_t, void *); + +/* + * Functions to handle register/unregister, search, ... + */ +cf_callback_t *cf_search (char *type) +{ + cf_callback_t *cf_cb; + + if (type == NULL) + return (NULL); + + for (cf_cb = first_callback; cf_cb != NULL; cf_cb = cf_cb->next) + if (strcasecmp (cf_cb->type, type) == 0) + break; + + return (cf_cb); +} + +int cf_dispatch (char *type, const char *orig_key, const char *orig_value) +{ + cf_callback_t *cf_cb; + char *key; + char *value; + int ret; + int i; + + if ((cf_cb = cf_search (type)) == NULL) + { + fprintf (stderr, "Plugin `%s' did not register a callback.\n", type); + return (-1); + } + + if ((key = strdup (orig_key)) == NULL) + return (1); + if ((value = strdup (orig_value)) == NULL) + { + free (key); + return (2); + } + + ret = -1; + + for (i = 0; i < cf_cb->keys_num; i++) + { + if (strcasecmp (cf_cb->keys[i], key) == 0) + ret = (*cf_cb->callback) (key, value); + } + + if (i >= cf_cb->keys_num) + fprintf (stderr, "Plugin `%s' did not register for value `%s'.\n", type, key); + + free (key); + free (value); + + return (ret); +} + +void cf_unregister (char *type) +{ + cf_callback_t *this, *prev; + + for (prev = NULL, this = first_callback; + this != NULL; + prev = this, this = this->next) + if (strcasecmp (this->type, type) == 0) + { + if (prev == NULL) + first_callback = this->next; + else + prev->next = this->next; + + free (this); + break; + } +} + +void cf_register (char *type, + int (*callback) (char *, char *), + char **keys, int keys_num) +{ + cf_callback_t *cf_cb; + char buf[64]; + int i; + + /* Remove this module from the list, if it already exists */ + cf_unregister (type); + + /* This pointer will be free'd in `cf_unregister' */ + if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL) + return; + + cf_cb->type = type; + cf_cb->callback = callback; + cf_cb->keys = keys; + cf_cb->keys_num = keys_num; + + cf_cb->next = first_callback; + first_callback = cf_cb; + + for (i = 0; i < keys_num; i++) + { + if (snprintf (buf, 64, "Module.%s", keys[i]) < 64) + { + /* This may be called multiple times for the same + * `key', but apparently `lc_register_*' can handle + * it.. */ + lc_register_callback (buf, SHORTOPT_NONE, + LC_VAR_STRING, cf_callback_general, + NULL); + } + else + { + DBG ("Key was truncated: `%s'", keys[i]); + } + } +} + +/* + * Functions for the actual parsing + */ +int cf_callback_general (const char *shortvar, const char *var, + const char *arguments, const char *value, lc_flags_t flags, + void *extra) +{ + DBG ("shortvar = %s, var = %s, arguments = %s, value = %s, ...", + shortvar, var, arguments, value); + + if ((nesting_depth == 0) || (current_module == NULL)) + { + fprintf (stderr, ERR_NEEDS_SECTION, shortvar); + return (LC_CBRET_ERROR); + } + + /* Send the data to the plugin */ + if (cf_dispatch (current_module, shortvar, value) < 0) + return (LC_CBRET_ERROR); + + return (LC_CBRET_OKAY); +} + +int cf_callback_section_mode (const char *shortvar, const char *var, + const char *arguments, const char *value, lc_flags_t flags, + void *extra) +{ + DBG ("shortvar = %s, var = %s, arguments = %s, value = %s, ...", + shortvar, var, arguments, value); + + if (flags == LC_FLAGS_SECTIONSTART) + { + if (nesting_depth != 0) + { + fprintf (stderr, ERR_NOT_NESTED); + return (LC_CBRET_ERROR); + } + + if (arguments == NULL) + { + fprintf (stderr, ERR_NEEDS_ARG, shortvar); + return (LC_CBRET_ERROR); + } + + nesting_depth++; + + if (((operating_mode == MODE_CLIENT) + && (strcasecmp (arguments, "Client") == 0)) + || ((operating_mode == MODE_SERVER) + && (strcasecmp (arguments, "Server") == 0)) + || ((operating_mode == MODE_LOCAL) + && (strcasecmp (arguments, "Local") == 0))) + { + return (LC_CBRET_OKAY); + } + else + { + return (LC_CBRET_IGNORESECTION); + } + } + else if (flags == LC_FLAGS_SECTIONEND) + { + nesting_depth--; + + return (LC_CBRET_OKAY); + } + else + { + fprintf (stderr, ERR_SECTION_ONLY, shortvar); + return (LC_CBRET_ERROR); + } + +} + +int cf_callback_section_module (const char *shortvar, const char *var, + const char *arguments, const char *value, lc_flags_t flags, + void *extra) +{ + DBG ("shortvar = %s, var = %s, arguments = %s, value = %s, ...", + shortvar, var, arguments, value); + + if (flags == LC_FLAGS_SECTIONSTART) + { + if (nesting_depth != 0) + { + fprintf (stderr, ERR_NOT_NESTED); + return (LC_CBRET_ERROR); + } + + if (arguments == NULL) + { + fprintf (stderr, ERR_NEEDS_ARG, shortvar); + return (LC_CBRET_ERROR); + } + + if ((current_module = strdup (arguments)) == NULL) + { + perror ("strdup"); + return (LC_CBRET_ERROR); + } + + nesting_depth++; + + if (cf_search (current_module) != NULL) + return (LC_CBRET_OKAY); + else + return (LC_CBRET_IGNORESECTION); + } + else if (flags == LC_FLAGS_SECTIONEND) + { + if (current_module != NULL) + { + free (current_module); + current_module == NULL; + } + + nesting_depth--; + + return (LC_CBRET_OKAY); + } + else + { + fprintf (stderr, ERR_SECTION_ONLY, shortvar); + return (LC_CBRET_ERROR); + } +} + +int cf_callback_loadmodule (const char *shortvar, const char *var, + const char *arguments, const char *value, lc_flags_t flags, + void *extra) +{ + DBG ("shortvar = %s, var = %s, arguments = %s, value = %s, ...", + shortvar, var, arguments, value); + + if (nesting_depth == 0) + { + fprintf (stderr, ERR_NEEDS_SECTION, shortvar); + return (LC_CBRET_ERROR); + } + + /* + * TODO: + * - Write wrapper around `plugin_load' to resolve path/filename + * - Call this new, public function here + */ + DBG ("Implement me, idiot!"); + + return (LC_CBRET_OKAY); +} + +int cf_read (char *filename) +{ + if (filename == NULL) + filename = CONFIGFILE; + + lc_register_callback ("Mode", SHORTOPT_NONE, LC_VAR_SECTION, + cf_callback_section_mode, NULL); + lc_register_callback ("Module", SHORTOPT_NONE, LC_VAR_SECTION, + cf_callback_section_module, NULL); + + /* + * TODO: + * - Add more directives, such as `DefaultMode', `DataDir', `PIDFile', ... + */ + + lc_register_callback ("Mode.LoadModule", SHORTOPT_NONE, + LC_VAR_STRING, cf_callback_loadmodule, + NULL); + + if (lc_process_file ("collectd", filename, LC_CONF_APACHE)) + { + /* FIXME: Use syslog here */ + fprintf (stderr, "Error loading config file `%s': %s\n", + filename, lc_geterrstr ()); + return (-1); + } + + /* free memory and stuff */ + lc_cleanup (); + + return (0); +} diff --git a/src/configfile.h b/src/configfile.h new file mode 100644 index 00000000..0802ba5a --- /dev/null +++ b/src/configfile.h @@ -0,0 +1,76 @@ +/** + * collectd - src/configfile.h + * Copyright (C) 2005 Florian octo Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#ifndef CONFIGFILE_H +#define CONFIGFILE_H + +/* + * DESCRIPTION + * Remove a registered plugin from the internal data structures. + * + * PARAMETERS + * `type' Name of the plugin (must be the same as passed to + * `plugin_register' + */ +void cf_unregister (char *type); + +/* + * DESCRIPTION + * `cf_register' is called by plugins that wish to receive config keys. The + * plugin will then receive all keys it registered for if they're found in a + * `' section. + * + * PARAMETERS + * `type' Name of the plugin (must be the same as passed to + * `plugin_register' + * `callback' Pointer to the callback function. The callback must return zero + * upon success, a value smaller than zero if it doesn't know how + * to handle the `key' passed to it (the first argument) or a + * value greater than zero if it knows how to handle the key but + * failed. + * `keys' Array of key values this plugin wished to receive. The last + * element must be a NULL-pointer. + * `keys_num' Number of elements in the array (not counting the last NULL- + * pointer. + * + * NOTES + * `cf_unregister' will be called for `type' to make sure only one record + * exists for each `type' at any time. This means that `cf_register' may be + * called multiple times, but only the last call will have an effect. + */ +void cf_register (char *type, + int (*callback) (char *, char *), + char **keys, int keys_num); + +/* + * DESCRIPTION + * `cf_read' reads the config file `filename' and dispatches the read + * information to functions/variables. Most important: Is calls `plugin_load' + * to load specific plugins, depending on the current mode of operation. + * + * RETURN VALUE + * Returns zero upon success and non-zero otherwise. A error-message will have + * been printed in this case. + */ +int cf_read (char *filename); + +#endif /* defined(CONFIGFILE_H) */ diff --git a/src/ping.c b/src/ping.c index eb35360b..9c318cee 100644 --- a/src/ping.c +++ b/src/ping.c @@ -27,6 +27,7 @@ #include "plugin.h" #include "common.h" +#include "configfile.h" #include #include "libping/ping.h" @@ -44,6 +45,13 @@ static char *ds_def[] = }; static int ds_num = 1; +static char *config_keys[] = +{ + "Host", + NULL +}; +static int config_keys_num = 1; + extern time_t curtime; void ping_init (void) @@ -56,6 +64,28 @@ void ping_init (void) return; } +int ping_config (char *key, char *value) +{ + if (strcasecmp (key, "host")) + { + return (-1); + } + else if (num_pinghosts >= MAX_PINGHOSTS) + { + return (1); + } + else if ((pinghosts[num_pinghosts] = strdup (value)) == NULL) + { + return (2); + } + else + { + pingerrors[num_pinghosts] = 0; + num_pinghosts++; + return (0); + } +} + void ping_write (char *host, char *inst, char *val) { char file[512]; @@ -131,6 +161,7 @@ void ping_read (void) void module_register (void) { plugin_register (MODULE_NAME, ping_init, ping_read, ping_write); + cf_register (MODULE_NAME, ping_config, config_keys, config_keys_num); } #undef MODULE_NAME diff --git a/src/plugin.h b/src/plugin.h index 8dd56ae3..5bf5de67 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -32,6 +32,7 @@ void plugin_register (char *type, void (*init) (void), void (*read) (void), void (*write) (char *, char *, char *)); + #ifdef HAVE_LIBRRD void plugin_write (char *host, char *type, char *inst, char *val); #endif /* HAVE_LIBRRD */ -- 2.30.2