X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fconfigfile.c;h=c929d0097aef6279db09c61411442cf3ddef99aa;hb=3f391479bfc45d0ff6e0c7b87c899e41a192f392;hp=ce4e7747c95af39aee1f55c9bf1479c2c3917da9;hpb=bdd0b82cf6d2113e5f36c8ef91ac8844069956fb;p=collectd.git diff --git a/src/configfile.c b/src/configfile.c index ce4e7747..c929d009 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -1,6 +1,6 @@ /** * collectd - src/configfile.c - * Copyright (C) 2005-2008 Florian octo Forster + * Copyright (C) 2005-2009 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 @@ -18,6 +18,7 @@ * * Authors: * Florian octo Forster + * Sebastian tokkee Harl **/ #include "collectd.h" @@ -29,6 +30,7 @@ #include "configfile.h" #include "types_list.h" #include "utils_threshold.h" +#include "filter_chain.h" #if HAVE_WORDEXP_H # include @@ -96,7 +98,9 @@ static cf_global_option_t cf_global_options[] = {"Hostname", NULL, NULL}, {"FQDNLookup", NULL, "false"}, {"Interval", NULL, "10"}, - {"ReadThreads", NULL, "5"} + {"ReadThreads", NULL, "5"}, + {"PreCacheChain", NULL, "PreCache"}, + {"PostCacheChain", NULL, "PostCache"} }; static int cf_global_options_num = STATIC_ARRAY_LEN (cf_global_options); @@ -154,7 +158,8 @@ static int cf_dispatch (const char *type, const char *orig_key, for (i = 0; i < cf_cb->keys_num; i++) { - if (strcasecmp (cf_cb->keys[i], key) == 0) + if ((cf_cb->keys[i] != NULL) + && (strcasecmp (cf_cb->keys[i], key) == 0)) { ret = (*cf_cb->callback) (key, value); break; @@ -181,8 +186,7 @@ static int dispatch_global_option (const oconfig_item_t *ci) else if (ci->values[0].type == OCONFIG_TYPE_NUMBER) { char tmp[128]; - snprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number); - tmp[127] = '\0'; + ssnprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number); return (global_option_set (ci->key, tmp)); } else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN) @@ -204,13 +208,18 @@ static int dispatch_value_typesdb (const oconfig_item_t *ci) cf_default_typesdb = 0; - if (ci->values_num < 1) + if (ci->values_num < 1) { + ERROR ("configfile: `TypesDB' needs at least one argument."); return (-1); + } for (i = 0; i < ci->values_num; ++i) { - if (OCONFIG_TYPE_STRING != ci->values[i].type) + if (OCONFIG_TYPE_STRING != ci->values[i].type) { + WARNING ("configfile: TypesDB: Skipping %i. argument which " + "is not a string.", i + 1); continue; + } read_types_list (ci->values[i].value.string); } @@ -257,13 +266,13 @@ static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci) int status = -1; if (ci->values[i].type == OCONFIG_TYPE_STRING) - status = snprintf (buffer_ptr, buffer_free, " %s", + status = ssnprintf (buffer_ptr, buffer_free, " %s", ci->values[i].value.string); else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) - status = snprintf (buffer_ptr, buffer_free, " %lf", + status = ssnprintf (buffer_ptr, buffer_free, " %lf", ci->values[i].value.number); else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) - status = snprintf (buffer_ptr, buffer_free, " %s", + status = ssnprintf (buffer_ptr, buffer_free, " %s", ci->values[i].value.boolean ? "true" : "false"); @@ -276,7 +285,7 @@ static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci) buffer_ptr = buffer + 1; return (cf_dispatch (plugin, ci->key, buffer_ptr)); -} /* int plugin_conf_dispatch */ +} /* int dispatch_value_plugin */ static int dispatch_value (const oconfig_item_t *ci) { @@ -327,7 +336,7 @@ static int dispatch_block_plugin (oconfig_item_t *ci) if (ci->children[i].children == NULL) dispatch_value_plugin (name, ci->children + i); else - {DEBUG ("No nested config blocks allow for this plugin.");} + {DEBUG ("No nested config blocks allowed for this plugin.");} } return (0); @@ -340,6 +349,8 @@ static int dispatch_block (oconfig_item_t *ci) return (dispatch_block_plugin (ci)); else if (strcasecmp (ci->key, "Threshold") == 0) return (ut_config (ci)); + else if (strcasecmp (ci->key, "Chain") == 0) + return (fc_configure (ci)); return (0); } @@ -423,6 +434,9 @@ static int cf_ci_append_children (oconfig_item_t *dst, oconfig_item_t *src) { oconfig_item_t *temp; + if ((src == NULL) || (src->children_num == 0)) + return (0); + temp = (oconfig_item_t *) realloc (dst->children, sizeof (oconfig_item_t) * (dst->children_num + src->children_num)); @@ -502,13 +516,20 @@ static oconfig_item_t *cf_read_file (const char *file, int depth) return (root); } /* oconfig_item_t *cf_read_file */ +static int cf_compare_string (const void *p1, const void *p2) +{ + return strcmp (*(const char **) p1, *(const char **) p2); +} + static oconfig_item_t *cf_read_dir (const char *dir, int depth) { oconfig_item_t *root = NULL; DIR *dh; struct dirent *de; - char name[1024]; + char **filenames = NULL; + int filenames_num = 0; int status; + int i; assert (depth < CF_MAX_DEPTH); @@ -531,30 +552,68 @@ static oconfig_item_t *cf_read_dir (const char *dir, int depth) while ((de = readdir (dh)) != NULL) { - oconfig_item_t *temp; + char name[1024]; + char **tmp; if ((de->d_name[0] == '.') || (de->d_name[0] == '\0')) continue; - status = snprintf (name, sizeof (name), "%s/%s", + status = ssnprintf (name, sizeof (name), "%s/%s", dir, de->d_name); - if (status >= sizeof (name)) + if ((status < 0) || ((size_t) status >= sizeof (name))) { ERROR ("configfile: Not including `%s/%s' because its" " name is too long.", dir, de->d_name); - continue; + for (i = 0; i < filenames_num; ++i) + free (filenames[i]); + free (filenames); + free (root); + return (NULL); + } + + ++filenames_num; + tmp = (char **) realloc (filenames, + filenames_num * sizeof (*filenames)); + if (tmp == NULL) { + ERROR ("configfile: realloc failed."); + for (i = 0; i < filenames_num - 1; ++i) + free (filenames[i]); + free (filenames); + free (root); + return (NULL); } + filenames = tmp; + + filenames[filenames_num - 1] = sstrdup (name); + } + + qsort ((void *) filenames, filenames_num, sizeof (*filenames), + cf_compare_string); + + for (i = 0; i < filenames_num; ++i) + { + oconfig_item_t *temp; + char *name = filenames[i]; temp = cf_read_generic (name, depth); - if (temp == NULL) - continue; + if (temp == NULL) { + int j; + for (j = i; j < filenames_num; ++j) + free (filenames[j]); + free (filenames); + oconfig_free (root); + return (NULL); + } cf_ci_append_children (root, temp); sfree (temp->children); sfree (temp); + + free (name); } + free(filenames); return (root); } /* oconfig_item_t *cf_read_dir */ @@ -576,7 +635,7 @@ static oconfig_item_t *cf_read_generic (const char *path, int depth) int status; const char *path_ptr; wordexp_t we; - int i; + size_t i; if (depth >= CF_MAX_DEPTH) { @@ -600,6 +659,11 @@ static oconfig_item_t *cf_read_generic (const char *path, int depth) } memset (root, '\0', sizeof (oconfig_item_t)); + /* wordexp() might return a sorted list already. That's not + * documented though, so let's make sure we get what we want. */ + qsort ((void *) we.we_wordv, we.we_wordc, sizeof (*we.we_wordv), + cf_compare_string); + for (i = 0; i < we.we_wordc; i++) { oconfig_item_t *temp; @@ -614,6 +678,7 @@ static oconfig_item_t *cf_read_generic (const char *path, int depth) ERROR ("configfile: stat (%s) failed: %s", path_ptr, sstrerror (errno, errbuf, sizeof (errbuf))); + oconfig_free (root); return (NULL); } @@ -628,6 +693,11 @@ static oconfig_item_t *cf_read_generic (const char *path, int depth) continue; } + if (temp == NULL) { + oconfig_free (root); + return (NULL); + } + cf_ci_append_children (root, temp); sfree (temp->children); sfree (temp); @@ -828,7 +898,11 @@ int cf_read (char *filename) dispatch_block (conf->children + i); } + oconfig_free (conf); + + /* Read the default types.db if no `TypesDB' option was given. */ if (cf_default_typesdb) - read_types_list (PLUGINDIR"/types.db"); /* FIXME: Configure path */ + read_types_list (PKGDATADIR"/types.db"); + return (0); } /* int cf_read */