1 /**
2 * collectd - src/config_list.c
3 * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
4 *
5 * This program is free software; you can redistribute it and/
6 * or modify it under the terms of the GNU General Public Li-
7 * cence as published by the Free Software Foundation; either
8 * version 2 of the Licence, or any later version.
9 *
10 * This program is distributed in the hope that it will be use-
11 * ful, but WITHOUT ANY WARRANTY; without even the implied war-
12 * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * Licence along with this program; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
18 * USA.
19 *
20 * Authors:
21 * Lubos Stanek <lubek at users.sourceforge.net>
22 **/
23 /**
24 * ignorelist handles plugin's list of configured collectable
25 * entries with global ignore action
26 **/
27 /**
28 * Usage:
29 *
30 * Define plugin's global pointer variable of type ignorelist_t:
31 * ignorelist_t *myconfig_ignore;
32 * If you know the state of the global ignore (IgnoreSelected),
33 * allocate the variable with:
34 * myconfig_ignore = ignorelist_create (YourKnownIgnore);
35 * If you do not know the state of the global ignore,
36 * initialize the global variable and set the ignore flag later:
37 * myconfig_ignore = ignorelist_init ();
38 * Append single entries in your cf_register'ed callback function:
39 * ignorelist_add (myconfig_ignore, newentry);
40 * When you hit the IgnoreSelected config option,
41 * offer it to the list:
42 * ignorelist_ignore (myconfig_ignore, instantly_got_value_of_ignore);
43 * That is all for the ignorelist initialization.
44 * Later during read and write (plugin's registered functions) get
45 * the information whether this entry would be collected or not:
46 * if (ignorelist_ignored (myconfig_ignore, thisentry))
47 * return;
48 **/
50 #include "common.h"
51 #include "utils_debug.h"
52 #include "utils_ignorelist.h"
54 /*
55 * private prototypes
56 */
57 struct ignorelist_item_s
58 {
59 #if HAVE_REGEX_H
60 regex_t *rmatch; /* regular expression entry identification */
61 #endif
62 char *smatch; /* string entry identification */
63 struct ignorelist_item_s *next;
64 };
65 typedef struct ignorelist_item_s ignorelist_item_t;
67 struct ignorelist_s
68 {
69 int ignore; /* ignore entries */
70 int num; /* number of entries */
71 ignorelist_item_t *next; /* pointer to the first entry */
72 };
74 /* *** *** *** ********************************************* *** *** *** */
75 /* *** *** *** *** *** *** private functions *** *** *** *** *** *** */
76 /* *** *** *** ********************************************* *** *** *** */
78 #if HAVE_REGEX_H
79 static int ignorelist_regappend(ignorelist_t *conflist, const char *entry)
80 {
81 int rcompile;
82 regex_t *regtemp;
83 int errsize;
84 char *regerr = NULL;
85 ignorelist_item_t *new;
87 /* create buffer */
88 if ((regtemp = malloc(sizeof(regex_t))) == NULL)
89 {
90 syslog (LOG_ERR, "cannot allocate new config entry");
91 return (0);
92 }
93 memset (regtemp, '\0', sizeof(regex_t));
95 /* compile regex */
96 if ((rcompile = regcomp (regtemp, entry, REG_EXTENDED)) != 0)
97 {
98 /* prepare message buffer */
99 errsize = regerror(rcompile, regtemp, NULL, 0);
100 if (errsize)
101 regerr = smalloc(errsize);
102 /* get error message */
103 if (regerror(rcompile, regtemp, regerr, errsize))
104 syslog (LOG_ERR, "cannot compile regex %s: %i/%s",
105 entry, rcompile, regerr);
106 else
107 syslog (LOG_ERR, "cannot compile regex %s: %i",
108 entry, rcompile);
109 if (errsize)
110 sfree (regerr);
111 regfree (regtemp);
112 return (0);
113 }
114 DBG("regex compiled: %s - %i", entry, rcompile);
116 /* create new entry */
117 if ((new = malloc(sizeof(ignorelist_item_t))) == NULL)
118 {
119 syslog (LOG_ERR, "cannot allocate new config entry");
120 regfree (regtemp);
121 return (0);
122 }
123 memset (new, '\0', sizeof(ignorelist_item_t));
124 new->rmatch = regtemp;
126 /* append new entry */
127 if (conflist->next == NULL)
128 {
129 conflist->next=new;
130 }
131 else
132 {
133 new->next=conflist->next;
134 conflist->next=new;
135 }
136 conflist->num++;
137 return (1);
138 } /* int ignorelist_regappend(ignorelist_t *conflist, const char *entry) */
139 #endif
141 static int ignorelist_strappend(ignorelist_t *conflist, const char *entry)
142 {
143 ignorelist_item_t *new;
145 /* create new entry */
146 if ((new = malloc(sizeof(ignorelist_item_t))) == NULL )
147 {
148 syslog (LOG_ERR, "cannot allocate new entry");
149 return (0);
150 }
151 memset (new, '\0', sizeof(ignorelist_item_t));
152 new->smatch = sstrdup(entry);
154 /* append new entry */
155 if (conflist->next == NULL)
156 {
157 conflist->next=new;
158 }
159 else
160 {
161 new->next=conflist->next;
162 conflist->next=new;
163 }
164 conflist->num++;
165 return (1);
166 } /* int ignorelist_strappend(ignorelist_t *conflist, const char *entry) */
168 #if HAVE_REGEX_H
169 /*
170 * check list for entry regex match
171 * return 1 if found
172 */
173 static int ignorelist_item_rmatch (ignorelist_item_t *confentry, const char *entry)
174 {
175 if (confentry == NULL)
176 return (0);
178 if (strlen (entry) == 0)
179 return (0);
181 if (confentry->rmatch == NULL)
182 return (0);
184 /* match regex */
185 if (regexec (confentry->rmatch, entry, 0, NULL, 0) == 0)
186 return (1);
188 return (0);
189 } /* int ignorelist_item_rmatch (ignorelist_item_t *confentry, const char *entry) */
190 #endif
192 /*
193 * check list for entry string match
194 * return 1 if found
195 */
196 static int ignorelist_item_smatch (ignorelist_item_t *confentry, const char *entry)
197 {
198 if (confentry == NULL)
199 return (0);
201 if (strlen (entry) == 0)
202 return (0);
204 if ((confentry->smatch != NULL && strcmp (entry, confentry->smatch) == 0))
205 return (1);
207 return (0);
208 } /* int ignorelist_item_smatch (ignorelist_item_t *confentry, const char *entry) */
211 /* *** *** *** ******************************************** *** *** *** */
212 /* *** *** *** *** *** *** public functions *** *** *** *** *** *** */
213 /* *** *** *** ******************************************** *** *** *** */
215 /*
216 * create the ignorelist_t with known ignore state
217 * return pointer to ignorelist_t
218 */
219 ignorelist_t *ignorelist_create (int ignore)
220 {
221 ignorelist_t *conflist;
223 if ((conflist = smalloc (sizeof (ignorelist_t))) == NULL)
224 {
225 syslog(LOG_ERR, "not enough memory to allocate ignorelist");
226 return (NULL);
227 }
228 DBG("ignorelist created 0x%p, ignore %i", (void *) conflist, ignore);
229 memset (conflist, '\0', sizeof (ignorelist_t));
231 if (ignore)
232 conflist->ignore = ignore;
234 return (conflist);
235 } /* ignorelist_t *ignorelist_create (int ignore) */
237 /*
238 * create ignorelist_t and initialize the ignore state to 0
239 * return pointer to ignorelist_t
240 */
241 ignorelist_t *ignorelist_init (void)
242 {
243 return (ignorelist_create (0));
244 } /* ignorelist_t *ignorelist_init (void) */
247 /*
248 * free memory used by ignorelist_t
249 */
250 void ignorelist_free (ignorelist_t *conflist)
251 {
252 ignorelist_item_t *this;
253 ignorelist_item_t *next;
255 DBG ("(conflist = 0x%p)", (void *) conflist);
257 if (conflist == NULL)
258 return;
260 for (this = conflist->next; this != NULL; this = next)
261 {
262 DBG ("free - confentry = 0x%p, numlist %i", (void *) this, conflist->num);
263 next = this->next;
264 conflist->num--;
265 #if HAVE_REGEX_H
266 if (this->rmatch != NULL)
267 {
268 regfree (this->rmatch);
269 this->rmatch = NULL;
270 }
271 #endif
272 if (this->smatch != NULL)
273 {
274 sfree (this->smatch);
275 this->smatch = NULL;
276 }
277 sfree (this);
278 }
279 #if COLLECTD_DEBUG
280 if (conflist->num != 0)
281 DBG ("after free numlist: %i", conflist->num);
282 #endif
283 conflist->num = 0;
284 sfree (conflist);
285 conflist = NULL;
286 } /* void ignorelist_destroy (ignorelist_t *conflist) */
288 /*
289 * set ignore state of the ignorelist_t
290 */
291 void ignorelist_ignore (ignorelist_t *conflist, int ignore)
292 {
293 if (conflist == NULL)
294 {
295 DBG("ignore call with ignorelist_t == NULL");
296 return;
297 }
299 conflist->ignore = ignore;
300 } /* void ignorelist_ignore (ignorelist_t *conflist, int ignore) */
302 /*
303 * get number of entries in the ignorelist_t
304 * return int number
305 */
306 int ignorelist_num (ignorelist_t *conflist)
307 {
308 if (conflist == NULL)
309 {
310 DBG("get num called with ignorelist_t == NULL");
311 return (0);
312 }
314 return (conflist->num);
315 } /* int ignorelist_num (ignorelist_t *conflist) */
317 /*
318 * append entry into ignorelist_t
319 * return 1 for success
320 */
321 int ignorelist_add (ignorelist_t *conflist, const char *entry)
322 {
323 #if HAVE_REGEX_H
324 char *entrytemp;
325 #endif
326 int restemp;
328 if (conflist == NULL)
329 {
330 DBG("add called with ignorelist_t == NULL");
331 return (0);
332 }
334 /* append nothing, report success */
335 if (strlen(entry) == 0)
336 {
337 DBG("not appending: empty entry");
338 return (1);
339 }
341 #if HAVE_REGEX_H
342 /* regex string is enclosed in "/.../" */
343 if (entry[0] == '/' && strlen(entry) > 2 && entry[strlen(entry) - 1] == '/')
344 {
345 entrytemp = smalloc(strlen(entry) - 2);
346 sstrncpy(entrytemp, &entry[1], strlen(entry) - 1);
347 DBG("to add regex entry: %s", entrytemp);
348 restemp = ignorelist_regappend(conflist, entrytemp);
349 sfree (entrytemp);
350 }
351 else
352 #endif
353 {
354 DBG("to add entry: %s", entry);
355 restemp = ignorelist_strappend(conflist, entry);
356 }
357 return (restemp);
358 } /* int ignorelist_add (ignorelist_t *conflist, const char *entry) */
360 /*
361 * check list for entry
362 * return 1 for ignored entry
363 */
364 int ignorelist_ignored (ignorelist_t *conflist, const char *entry)
365 {
366 ignorelist_item_t *traverse;
368 /* if no entries, collect all */
369 if (ignorelist_num(conflist) == 0)
370 return (0);
372 /* traverse list and check entries */
373 traverse = conflist->next;
374 while (traverse != NULL)
375 {
376 #if HAVE_REGEX_H
377 if (traverse->rmatch != NULL)
378 {
379 if (ignorelist_item_rmatch (traverse, entry))
380 return (conflist->ignore);
381 }
382 else
383 #endif
384 {
385 if (ignorelist_item_smatch (traverse, entry))
386 return (conflist->ignore);
387 }
388 traverse = traverse->next;
389 }
391 return (1 - conflist->ignore);
392 } /* int ignorelist_ignored (ignorelist_t *conflist, const char *entry) */