X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fconfigfile.c;h=e6b8ce821465cc008cfc21a1c7320fabc2078c7c;hb=8ea1756522f94af8e0bb7d06c800d94874f13549;hp=a5cdb1a6fdac84a09894be37e7f493ee72cc5237;hpb=79f871e0c04262f4769d23324236ce75d0b04d3f;p=collectd.git diff --git a/src/configfile.c b/src/configfile.c index a5cdb1a6..e6b8ce82 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -304,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 */ @@ -445,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);