diff --git a/src/configfile.c b/src/configfile.c
index 1d3b8954b546030e1bec7c574db455380486518f..4702e7aba131bfaa79dd48418a80cc82be18172f 100644 (file)
--- a/src/configfile.c
+++ b/src/configfile.c
#include "common.h"
#include "plugin.h"
#include "configfile.h"
-#include "network.h"
+#include "utils_threshold.h"
#define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
struct cf_callback *next;
} cf_callback_t;
+typedef struct cf_complex_callback_s
+{
+ char *type;
+ int (*callback) (oconfig_item_t *);
+ struct cf_complex_callback_s *next;
+} cf_complex_callback_t;
+
typedef struct cf_value_map_s
{
char *key;
* Private variables
*/
static cf_callback_t *first_callback = NULL;
+static cf_complex_callback_t *complex_callback_head = NULL;
static cf_value_map_t cf_value_map[] =
{
{"PIDFile", NULL, PIDFILE},
{"Hostname", NULL, NULL},
{"Interval", NULL, "10"},
- {"ReadThreads", NULL, "5"}
+ {"ReadThreads", NULL, "5"},
+ {"TypesDB", NULL, PLUGINDIR"/types.db"} /* FIXME: Configure path */
};
static int cf_global_options_num = STATIC_ARRAY_LEN (cf_global_options);
int i;
char *name;
+ cf_complex_callback_t *cb;
+
if (strcasecmp (ci->key, "Plugin") != 0)
return (-1);
- if (ci->values_num != 1)
+ if (ci->values_num < 1)
return (-1);
if (ci->values[0].type != OCONFIG_TYPE_STRING)
return (-1);
name = ci->values[0].value.string;
+ /* Check for a complex callback first */
+ for (cb = complex_callback_head; cb != NULL; cb = cb->next)
+ if (strcasecmp (name, cb->type) == 0)
+ return (cb->callback (ci));
+
+ /* Hm, no complex plugin found. Dispatch the values one by one */
for (i = 0; i < ci->children_num; i++)
{
if (ci->children[i].children == NULL)
dispatch_value_plugin (name, ci->children + i);
else
- {DEBUG ("No nested config blocks allow for plugins. Yet.");}
+ {DEBUG ("No nested config blocks allow for this plugin.");}
}
return (0);
{
if (strcasecmp (ci->key, "Plugin") == 0)
return (dispatch_block_plugin (ci));
+ else if (strcasecmp (ci->key, "Threshold") == 0)
+ return (ut_config (ci));
return (0);
}
+#define CF_MAX_DEPTH 8
+static oconfig_item_t *cf_read_file (const char *file, int depth);
+
+static int cf_include_all (oconfig_item_t *root, int depth)
+{
+ int i;
+
+ for (i = 0; i < root->children_num; i++)
+ {
+ oconfig_item_t *new;
+ oconfig_item_t *old;
+
+ /* Ignore all blocks, including `Include' blocks. */
+ if (root->children[i].children_num != 0)
+ continue;
+
+ if (strcasecmp (root->children[i].key, "Include") != 0)
+ continue;
+
+ old = root->children + i;
+
+ if ((old->values_num != 1)
+ || (old->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ ERROR ("configfile: `Include' needs exactly one string argument.");
+ continue;
+ }
+
+ new = cf_read_file (old->values[0].value.string, depth + 1);
+ if (new == NULL)
+ continue;
+
+ /* There are more children now. We need to expand
+ * root->children. */
+ if (new->children_num > 1)
+ {
+ oconfig_item_t *temp;
+
+ DEBUG ("configfile: Resizing root-children from %i to %i elements.",
+ root->children_num,
+ root->children_num + new->children_num - 1);
+
+ temp = (oconfig_item_t *) realloc (root->children,
+ sizeof (oconfig_item_t)
+ * (root->children_num + new->children_num - 1));
+ if (temp == NULL)
+ {
+ ERROR ("configfile: realloc failed.");
+ oconfig_free (new);
+ continue;
+ }
+ root->children = temp;
+ }
+
+ /* Clean up the old include directive while we still have a
+ * valid pointer */
+ DEBUG ("configfile: Cleaning up `old'");
+ /* sfree (old->values[0].value.string); */
+ sfree (old->values);
+
+ /* If there are trailing children and the number of children
+ * changes, we need to move the trailing ones either one to the
+ * front or (new->num - 1) to the back */
+ if (((root->children_num - i) > 1)
+ && (new->children_num != 1))
+ {
+ DEBUG ("configfile: Moving trailing children.");
+ memmove (root->children + i + new->children_num,
+ root->children + i + 1,
+ sizeof (oconfig_item_t)
+ * (root->children_num - (i + 1)));
+ }
+
+ /* Now copy the new children to where the include statement was */
+ if (new->children_num > 0)
+ {
+ DEBUG ("configfile: Copying new children.");
+ memcpy (root->children + i,
+ new->children,
+ sizeof (oconfig_item_t)
+ * new->children_num);
+ }
+
+ /* Adjust the number of children and the position in the list. */
+ root->children_num = root->children_num + new->children_num - 1;
+ i = i + new->children_num - 1;
+
+ /* Clean up the `new' struct. We set `new->children' to NULL so
+ * the stuff we've just copied pointers to isn't freed by
+ * `oconfig_free' */
+ DEBUG ("configfile: Cleaning up `new'");
+ sfree (new->values); /* should be NULL anyway */
+ sfree (new);
+ new = NULL;
+ } /* for (i = 0; i < root->children_num; i++) */
+
+ return (0);
+} /* int cf_include_all */
+
+static oconfig_item_t *cf_read_file (const char *file, int depth)
+{
+ oconfig_item_t *root;
+
+ if (depth >= CF_MAX_DEPTH)
+ {
+ ERROR ("configfile: Not including `%s' because the maximum nesting depth has been reached.",
+ file);
+ return (NULL);
+ }
+
+ root = oconfig_parse_file (file);
+ if (root == NULL)
+ {
+ ERROR ("configfile: Cannot read file `%s'.", file);
+ return (NULL);
+ }
+
+ cf_include_all (root, depth);
+
+ return (root);
+} /* oconfig_item_t *cf_read_file */
+
/*
* Public functions
*/
}
} /* void cf_unregister */
+void cf_unregister_complex (const char *type)
+{
+ cf_complex_callback_t *this, *prev;
+
+ for (prev = NULL, this = complex_callback_head;
+ this != NULL;
+ prev = this, this = this->next)
+ if (strcasecmp (this->type, type) == 0)
+ {
+ if (prev == NULL)
+ complex_callback_head = this->next;
+ else
+ prev->next = this->next;
+
+ sfree (this->type);
+ sfree (this);
+ break;
+ }
+} /* void cf_unregister */
+
void cf_register (const char *type,
int (*callback) (const char *, const char *),
const char **keys, int keys_num)
first_callback = cf_cb;
} /* void cf_register */
+int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
+{
+ cf_complex_callback_t *new;
+
+ new = (cf_complex_callback_t *) malloc (sizeof (cf_complex_callback_t));
+ if (new == NULL)
+ return (-1);
+
+ new->type = strdup (type);
+ if (new->type == NULL)
+ {
+ sfree (new);
+ return (-1);
+ }
+
+ new->callback = callback;
+ new->next = NULL;
+
+ if (complex_callback_head == NULL)
+ {
+ complex_callback_head = new;
+ }
+ else
+ {
+ cf_complex_callback_t *last = complex_callback_head;
+ while (last->next != NULL)
+ last = last->next;
+ last->next = new;
+ }
+
+ return (0);
+} /* int cf_register_complex */
+
int cf_read (char *filename)
{
oconfig_item_t *conf;
int i;
- conf = oconfig_parse_file (filename);
+ conf = cf_read_file (filename, 0 /* depth */);
if (conf == NULL)
{
ERROR ("Unable to read config file %s.", filename);