# include <wordexp.h>
#endif /* HAVE_WORDEXP_H */
+#if HAVE_FNMATCH_H
+# include <fnmatch.h>
+#endif /* HAVE_FNMATCH_H */
+
+#if HAVE_LIBGEN_H
+# include <libgen.h>
+#endif /* HAVE_LIBGEN_H */
+
#define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
/*
{"PluginDir", dispatch_value_plugindir},
{"LoadPlugin", dispatch_loadplugin}
};
-static int cf_value_map_num = STATIC_ARRAY_LEN (cf_value_map);
+static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map);
static cf_global_option_t cf_global_options[] =
{
{"FQDNLookup", NULL, "true"},
{"Interval", NULL, NULL},
{"ReadThreads", NULL, "5"},
+ {"WriteThreads", NULL, "5"},
{"Timeout", NULL, "2"},
{"PreCacheChain", NULL, "PreCache"},
{"PostCacheChain", NULL, "PostCache"}
};
-static int cf_global_options_num = STATIC_ARRAY_LEN (cf_global_options);
+static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
static int cf_default_typesdb = 1;
} /* int cf_ci_append_children */
#define CF_MAX_DEPTH 8
-static oconfig_item_t *cf_read_generic (const char *path, int depth);
+static oconfig_item_t *cf_read_generic (const char *path,
+ const char *pattern, int depth);
static int cf_include_all (oconfig_item_t *root, int depth)
{
oconfig_item_t *new;
oconfig_item_t *old;
- /* Ignore all blocks, including `Include' blocks. */
- if (root->children[i].children_num != 0)
- continue;
+ char *pattern = NULL;
+
+ int j;
if (strcasecmp (root->children[i].key, "Include") != 0)
continue;
continue;
}
- new = cf_read_generic (old->values[0].value.string, depth + 1);
+ for (j = 0; j < old->children_num; ++j)
+ {
+ oconfig_item_t *child = old->children + j;
+
+ if (strcasecmp (child->key, "Filter") == 0)
+ cf_util_get_string (child, &pattern);
+ else
+ ERROR ("configfile: Option `%s' not allowed in <Include> block.",
+ child->key);
+ }
+
+ new = cf_read_generic (old->values[0].value.string, pattern, depth + 1);
+ sfree (pattern);
+
if (new == NULL)
- continue;
+ return (-1);
/* Now replace the i'th child in `root' with `new'. */
cf_ci_replace_child (root, new, i);
return (0);
} /* int cf_include_all */
-static oconfig_item_t *cf_read_file (const char *file, int depth)
+static oconfig_item_t *cf_read_file (const char *file,
+ const char *pattern, int depth)
{
oconfig_item_t *root;
+ int status;
assert (depth < CF_MAX_DEPTH);
+ if (pattern != NULL) {
+#if HAVE_FNMATCH_H && HAVE_LIBGEN_H
+ char *tmp = sstrdup (file);
+ char *filename = basename (tmp);
+
+ if ((filename != NULL) && (fnmatch (pattern, filename, 0) != 0)) {
+ DEBUG ("configfile: Not including `%s' because it "
+ "does not match pattern `%s'.",
+ filename, pattern);
+ free (tmp);
+ return (NULL);
+ }
+
+ free (tmp);
+#else
+ ERROR ("configfile: Cannot apply pattern filter '%s' "
+ "to file '%s': functions basename() and / or "
+ "fnmatch() not available.", pattern, file);
+#endif /* HAVE_FNMATCH_H && HAVE_LIBGEN_H */
+ }
+
root = oconfig_parse_file (file);
if (root == NULL)
{
return (NULL);
}
- cf_include_all (root, depth);
+ status = cf_include_all (root, depth);
+ if (status != 0)
+ {
+ oconfig_free (root);
+ return (NULL);
+ }
return (root);
} /* oconfig_item_t *cf_read_file */
return strcmp (*(const char **) p1, *(const char **) p2);
}
-static oconfig_item_t *cf_read_dir (const char *dir, int depth)
+static oconfig_item_t *cf_read_dir (const char *dir,
+ const char *pattern, int depth)
{
oconfig_item_t *root = NULL;
DIR *dh;
oconfig_item_t *temp;
char *name = filenames[i];
- temp = cf_read_generic (name, depth);
+ temp = cf_read_generic (name, pattern, depth);
if (temp == NULL)
{
/* An error should already have been reported. */
* simpler function is used which does not do any such expansion.
*/
#if HAVE_WORDEXP_H
-static oconfig_item_t *cf_read_generic (const char *path, int depth)
+static oconfig_item_t *cf_read_generic (const char *path,
+ const char *pattern, int depth)
{
oconfig_item_t *root = NULL;
int status;
}
if (S_ISREG (statbuf.st_mode))
- temp = cf_read_file (path_ptr, depth);
+ temp = cf_read_file (path_ptr, pattern, depth);
else if (S_ISDIR (statbuf.st_mode))
- temp = cf_read_dir (path_ptr, depth);
+ temp = cf_read_dir (path_ptr, pattern, depth);
else
{
WARNING ("configfile: %s is neither a file nor a "
wordfree (&we);
- if (root->children == NULL)
- {
- oconfig_free (root);
- return (NULL);
- }
-
return (root);
} /* oconfig_item_t *cf_read_generic */
/* #endif HAVE_WORDEXP_H */
#else /* if !HAVE_WORDEXP_H */
-static oconfig_item_t *cf_read_generic (const char *path, int depth)
+static oconfig_item_t *cf_read_generic (const char *path,
+ const char *pattern, int depth)
{
struct stat statbuf;
int status;
}
if (S_ISREG (statbuf.st_mode))
- return (cf_read_file (path, depth));
+ return (cf_read_file (path, pattern, depth));
else if (S_ISDIR (statbuf.st_mode))
- return (cf_read_dir (path, depth));
+ return (cf_read_dir (path, pattern, depth));
ERROR ("configfile: %s is neither a file nor a directory.", path);
return (NULL);
oconfig_item_t *conf;
int i;
- conf = cf_read_generic (filename, 0 /* depth */);
+ conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0);
if (conf == NULL)
{
ERROR ("Unable to read config file %s.", filename);
return (-1);
}
+ else if (conf->children_num == 0)
+ {
+ ERROR ("Configuration file %s is empty.", filename);
+ oconfig_free (conf);
+ return (-1);
+ }
for (i = 0; i < conf->children_num; i++)
{