2 * collectd - src/match_regex.c
3 * Copyright (C) 2008 Sebastian Harl
4 * Copyright (C) 2008 Florian Forster
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Sebastian Harl <sh at tokkee.org>
26 * Florian Forster <octo at collectd.org>
30 * This module allows to filter and rewrite value lists based on
31 * Perl-compatible regular expressions.
35 #include "filter_chain.h"
37 #include <sys/types.h>
40 #define log_err(...) ERROR ("`regex' match: " __VA_ARGS__)
41 #define log_warn(...) WARNING ("`regex' match: " __VA_ARGS__)
48 typedef struct mr_regex_s mr_regex_t;
58 typedef struct mr_match_s mr_match_t;
63 mr_regex_t *plugin_instance;
65 mr_regex_t *type_instance;
70 * internal helper functions
72 static void mr_free_regex (mr_regex_t *r) /* {{{ */
78 memset (&r->re, 0, sizeof (r->re));
82 mr_free_regex (r->next);
83 } /* }}} void mr_free_regex */
85 static void mr_free_match (mr_match_t *m) /* {{{ */
90 mr_free_regex (m->host);
91 mr_free_regex (m->plugin);
92 mr_free_regex (m->plugin_instance);
93 mr_free_regex (m->type);
94 mr_free_regex (m->type_instance);
97 } /* }}} void mr_free_match */
99 static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */
105 return (FC_MATCH_MATCHES);
107 for (re = re_head; re != NULL; re = re->next)
111 status = regexec (&re->re, string,
112 /* nmatch = */ 0, /* pmatch = */ NULL,
116 DEBUG ("regex match: Regular expression `%s' matches `%s'.",
121 DEBUG ("regex match: Regular expression `%s' does not match `%s'.",
123 return (FC_MATCH_NO_MATCH);
128 return (FC_MATCH_MATCHES);
129 } /* }}} int mr_match_regexen */
131 static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
137 if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
139 log_warn ("`%s' needs exactly one string argument.", ci->key);
143 re = (mr_regex_t *) malloc (sizeof (*re));
146 log_err ("mr_config_add_regex: malloc failed.");
149 memset (re, 0, sizeof (*re));
152 re->re_str = strdup (ci->values[0].value.string);
153 if (re->re_str == NULL)
156 log_err ("mr_config_add_regex: strdup failed.");
160 status = regcomp (&re->re, re->re_str, REG_EXTENDED | REG_NOSUB);
164 regerror (status, &re->re, errmsg, sizeof (errmsg));
165 errmsg[sizeof (errmsg) - 1] = 0;
166 log_err ("Compiling regex `%s' for `%s' failed: %s.",
167 re->re_str, ci->key, errmsg);
173 if (*re_head == NULL)
182 while (ptr->next != NULL)
189 } /* }}} int mr_config_add_regex */
191 static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
197 m = (mr_match_t *) malloc (sizeof (*m));
200 log_err ("mr_create: malloc failed.");
203 memset (m, 0, sizeof (*m));
208 for (i = 0; i < ci->children_num; i++)
210 oconfig_item_t *child = ci->children + i;
212 if ((strcasecmp ("Host", child->key) == 0)
213 || (strcasecmp ("Hostname", child->key) == 0))
214 status = mr_config_add_regex (&m->host, child);
215 else if (strcasecmp ("Plugin", child->key) == 0)
216 status = mr_config_add_regex (&m->plugin, child);
217 else if (strcasecmp ("PluginInstance", child->key) == 0)
218 status = mr_config_add_regex (&m->plugin_instance, child);
219 else if (strcasecmp ("Type", child->key) == 0)
220 status = mr_config_add_regex (&m->type, child);
221 else if (strcasecmp ("TypeInstance", child->key) == 0)
222 status = mr_config_add_regex (&m->type_instance, child);
223 else if (strcasecmp ("Invert", child->key) == 0)
224 status = cf_util_get_boolean(child, &m->invert);
227 log_err ("The `%s' configuration option is not understood and "
228 "will be ignored.", child->key);
236 /* Additional sanity-checking */
239 if ((m->host == NULL)
240 && (m->plugin == NULL)
241 && (m->plugin_instance == NULL)
243 && (m->type_instance == NULL))
245 log_err ("No (valid) regular expressions have been configured. "
246 "This match will be ignored.");
261 } /* }}} int mr_create */
263 static int mr_destroy (void **user_data) /* {{{ */
265 if ((user_data != NULL) && (*user_data != NULL))
266 mr_free_match (*user_data);
268 } /* }}} int mr_destroy */
270 static int mr_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
271 const value_list_t *vl,
272 notification_meta_t __attribute__((unused)) **meta,
276 int match_value = FC_MATCH_MATCHES;
277 int nomatch_value = FC_MATCH_NO_MATCH;
279 if ((user_data == NULL) || (*user_data == NULL))
286 match_value = FC_MATCH_NO_MATCH;
287 nomatch_value = FC_MATCH_MATCHES;
290 if (mr_match_regexen (m->host, vl->host) == FC_MATCH_NO_MATCH)
291 return (nomatch_value);
292 if (mr_match_regexen (m->plugin, vl->plugin) == FC_MATCH_NO_MATCH)
293 return (nomatch_value);
294 if (mr_match_regexen (m->plugin_instance,
295 vl->plugin_instance) == FC_MATCH_NO_MATCH)
296 return (nomatch_value);
297 if (mr_match_regexen (m->type, vl->type) == FC_MATCH_NO_MATCH)
298 return (nomatch_value);
299 if (mr_match_regexen (m->type_instance,
300 vl->type_instance) == FC_MATCH_NO_MATCH)
301 return (nomatch_value);
303 return (match_value);
304 } /* }}} int mr_match */
306 void module_register (void)
310 memset (&mproc, 0, sizeof (mproc));
311 mproc.create = mr_create;
312 mproc.destroy = mr_destroy;
313 mproc.match = mr_match;
314 fc_register_match ("regex", mproc);
315 } /* module_register */
317 /* vim: set sw=4 ts=4 tw=78 noexpandtab fdm=marker : */