2 * collectd - src/match_regex.c
3 * Copyright (C) 2008 Sebastian Harl
4 * Copyright (C) 2008 Florian Forster
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; only version 2 of the License is applicable.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Sebastian Harl <sh at tokkee.org>
21 * Florian Forster <octo at verplant.org>
25 * This module allows to filter and rewrite value lists based on
26 * Perl-compatible regular expressions.
30 #include "filter_chain.h"
32 #include <sys/types.h>
35 #define log_err(...) ERROR ("`regex' match: " __VA_ARGS__)
36 #define log_warn(...) WARNING ("`regex' match: " __VA_ARGS__)
43 typedef struct mr_regex_s mr_regex_t;
53 typedef struct mr_match_s mr_match_t;
58 mr_regex_t *plugin_instance;
60 mr_regex_t *type_instance;
65 * internal helper functions
67 static void mr_free_regex (mr_regex_t *r) /* {{{ */
73 memset (&r->re, 0, sizeof (r->re));
77 mr_free_regex (r->next);
78 } /* }}} void mr_free_regex */
80 static void mr_free_match (mr_match_t *m) /* {{{ */
85 mr_free_regex (m->host);
86 mr_free_regex (m->plugin);
87 mr_free_regex (m->plugin_instance);
88 mr_free_regex (m->type);
89 mr_free_regex (m->type_instance);
92 } /* }}} void mr_free_match */
94 static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */
100 return (FC_MATCH_MATCHES);
102 for (re = re_head; re != NULL; re = re->next)
106 status = regexec (&re->re, string,
107 /* nmatch = */ 0, /* pmatch = */ NULL,
111 DEBUG ("regex match: Regular expression `%s' matches `%s'.",
116 DEBUG ("regex match: Regular expression `%s' does not match `%s'.",
118 return (FC_MATCH_NO_MATCH);
123 return (FC_MATCH_MATCHES);
124 } /* }}} int mr_match_regexen */
126 static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
132 if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
134 log_warn ("`%s' needs exactly one string argument.", ci->key);
138 re = (mr_regex_t *) malloc (sizeof (*re));
141 log_err ("mr_config_add_regex: malloc failed.");
144 memset (re, 0, sizeof (*re));
147 re->re_str = strdup (ci->values[0].value.string);
148 if (re->re_str == NULL)
151 log_err ("mr_config_add_regex: strdup failed.");
155 status = regcomp (&re->re, re->re_str, REG_EXTENDED | REG_NOSUB);
159 regerror (status, &re->re, errmsg, sizeof (errmsg));
160 errmsg[sizeof (errmsg) - 1] = 0;
161 log_err ("Compiling regex `%s' for `%s' failed: %s.",
162 re->re_str, ci->key, errmsg);
168 if (*re_head == NULL)
177 while (ptr->next != NULL)
184 } /* }}} int mr_config_add_regex */
186 static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
192 m = (mr_match_t *) malloc (sizeof (*m));
195 log_err ("mr_create: malloc failed.");
198 memset (m, 0, sizeof (*m));
203 for (i = 0; i < ci->children_num; i++)
205 oconfig_item_t *child = ci->children + i;
207 if ((strcasecmp ("Host", child->key) == 0)
208 || (strcasecmp ("Hostname", child->key) == 0))
209 status = mr_config_add_regex (&m->host, child);
210 else if (strcasecmp ("Plugin", child->key) == 0)
211 status = mr_config_add_regex (&m->plugin, child);
212 else if (strcasecmp ("PluginInstance", child->key) == 0)
213 status = mr_config_add_regex (&m->plugin_instance, child);
214 else if (strcasecmp ("Type", child->key) == 0)
215 status = mr_config_add_regex (&m->type, child);
216 else if (strcasecmp ("TypeInstance", child->key) == 0)
217 status = mr_config_add_regex (&m->type_instance, child);
218 else if (strcasecmp ("Invert", child->key) == 0)
219 status = cf_util_get_boolean(child, &m->invert);
222 log_err ("The `%s' configuration option is not understood and "
223 "will be ignored.", child->key);
231 /* Additional sanity-checking */
234 if ((m->host == NULL)
235 && (m->plugin == NULL)
236 && (m->plugin_instance == NULL)
238 && (m->type_instance == NULL))
240 log_err ("No (valid) regular expressions have been configured. "
241 "This match will be ignored.");
256 } /* }}} int mr_create */
258 static int mr_destroy (void **user_data) /* {{{ */
260 if ((user_data != NULL) && (*user_data != NULL))
261 mr_free_match (*user_data);
263 } /* }}} int mr_destroy */
265 static int mr_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
266 const value_list_t *vl,
267 notification_meta_t __attribute__((unused)) **meta,
271 int match_value = FC_MATCH_MATCHES;
272 int nomatch_value = FC_MATCH_NO_MATCH;
274 if ((user_data == NULL) || (*user_data == NULL))
281 match_value = FC_MATCH_NO_MATCH;
282 nomatch_value = FC_MATCH_MATCHES;
285 if (mr_match_regexen (m->host, vl->host) == FC_MATCH_NO_MATCH)
286 return (nomatch_value);
287 if (mr_match_regexen (m->plugin, vl->plugin) == FC_MATCH_NO_MATCH)
288 return (nomatch_value);
289 if (mr_match_regexen (m->plugin_instance,
290 vl->plugin_instance) == FC_MATCH_NO_MATCH)
291 return (nomatch_value);
292 if (mr_match_regexen (m->type, vl->type) == FC_MATCH_NO_MATCH)
293 return (nomatch_value);
294 if (mr_match_regexen (m->type_instance,
295 vl->type_instance) == FC_MATCH_NO_MATCH)
296 return (nomatch_value);
298 return (match_value);
299 } /* }}} int mr_match */
301 void module_register (void)
305 memset (&mproc, 0, sizeof (mproc));
306 mproc.create = mr_create;
307 mproc.destroy = mr_destroy;
308 mproc.match = mr_match;
309 fc_register_match ("regex", mproc);
310 } /* module_register */
312 /* vim: set sw=4 ts=4 tw=78 noexpandtab fdm=marker : */