X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fconfigfile.c;h=e6b8ce821465cc008cfc21a1c7320fabc2078c7c;hb=915950cfc280a2fdaac92f839bf5fa66db96a433;hp=f4e9c604fe26cafd75ee04620158b11f5aed6726;hpb=7ff716579c6ed159366ef3dfd3132efb6f744ce0;p=collectd.git diff --git a/src/configfile.c b/src/configfile.c index f4e9c604..e6b8ce82 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -1,6 +1,6 @@ /** * collectd - src/configfile.c - * Copyright (C) 2005,2006 Florian octo Forster + * Copyright (C) 2005-2008 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 @@ -126,7 +126,9 @@ static int cf_dispatch (const char *type, const char *orig_key, if ((cf_cb = cf_search (type)) == NULL) { - WARNING ("Plugin `%s' did not register a callback.", type); + WARNING ("Found a configuration for the `%s' plugin, but " + "the plugin isn't loaded or didn't register " + "a configuration callback.", type); return (-1); } @@ -302,6 +304,128 @@ static int dispatch_block (oconfig_item_t *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 */ @@ -443,7 +567,7 @@ 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);