From: Florian Forster Date: Mon, 17 Sep 2007 07:32:23 +0000 (+0200) Subject: collectd: Add the config option `Include' which includes other files. X-Git-Tag: collectd-4.2.0~58 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=2ac31da827a2823c70ee8ec2058047435de9a3d7;p=collectd.git collectd: Add the config option `Include' which includes other files. This is done recursively so that you can have a depth of up to `n' (currently eight). --- diff --git a/ChangeLog b/ChangeLog index 259f40c3..49e6c31b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ yyyy-mm-dd, Version 4.2.0 + * collectd: The new config option `Include' lets you include other + configfiles and thus split up your config into smaller parts. This + may be especially interresting for the snmp plugin to keep the data + definitions seperate from the host definitions. * snmp plugin: Added the options `Scale' and `Shift' to Data-blocks to correct the values returned by SNMP-agents. diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 29e26af4..27c50656 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -47,6 +47,15 @@ directory for the daemon. Loads the plugin I. There must be at least one such line or B will be mostly useless. +=item B I + +Includes the file I as if it was copy and pasted here. To prevent loops +and shooting yourself in the foot in interesting ways the nesting is limited to +a depth of 8Elevels, which should be sufficient for most uses. + +It is no problem to have a block like CPlugin fooE> in more than one +file, but you cannot include files from within blocks. + =item B I Sets where to write the PID file to. This file is overwritten when it exists diff --git a/src/configfile.c b/src/configfile.c index f4e9c604..0310ca8a 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -302,6 +302,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 +565,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);