1 /*----------------------------------------------------------------------------*/
2 /* Xymon monitor library. */
3 /* */
4 /* This is a library module, part of libxymon. */
5 /* It contains routines for matching names and expressions */
6 /* */
7 /* Copyright (C) 2002-2011 Henrik Storner <henrik@storner.dk> */
8 /* */
9 /* This program is released under the GNU General Public License (GPL), */
10 /* version 2. See the file "COPYING" for details. */
11 /* */
12 /*----------------------------------------------------------------------------*/
13
14 static char rcsid[] = "$Id: matching.c 7733 2015-11-12 09:24:01Z jccleaver $";
15
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <stdlib.h>
20
21 #include <pcre.h>
22
23 #include "libxymon.h"
24
compileregex_opts(const char * pattern,int flags)25 pcre *compileregex_opts(const char *pattern, int flags)
26 {
27 pcre *result;
28 const char *errmsg;
29 int errofs;
30
31 dbgprintf("Compiling regex %s\n", pattern);
32 result = pcre_compile(pattern, flags, &errmsg, &errofs, NULL);
33 if (result == NULL) {
34 errprintf("pcre compile '%s' failed (offset %d): %s\n", pattern, errofs, errmsg);
35 return NULL;
36 }
37
38 return result;
39 }
40
compileregex(const char * pattern)41 pcre *compileregex(const char *pattern)
42 {
43 return compileregex_opts(pattern, PCRE_CASELESS);
44 }
45
multilineregex(const char * pattern)46 pcre *multilineregex(const char *pattern)
47 {
48 return compileregex_opts(pattern, PCRE_CASELESS|PCRE_MULTILINE);
49 }
50
matchregex(const char * needle,pcre * pcrecode)51 int matchregex(const char *needle, pcre *pcrecode)
52 {
53 int ovector[30];
54 int result;
55
56 if (!needle || !pcrecode) return 0;
57
58 result = pcre_exec(pcrecode, NULL, needle, strlen(needle), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
59 return (result >= 0);
60 }
61
freeregex(pcre * pcrecode)62 void freeregex(pcre *pcrecode)
63 {
64 if (!pcrecode) return;
65
66 pcre_free(pcrecode);
67 }
68
namematch(const char * needle,char * haystack,pcre * pcrecode)69 int namematch(const char *needle, char *haystack, pcre *pcrecode)
70 {
71 char *xhay;
72 char *tokbuf = NULL, *tok;
73 int found = 0;
74 int result = 0;
75 int allneg = 1;
76
77 if ((needle == NULL) || (*needle == '\0')) return 0;
78
79 if (pcrecode) {
80 /* Do regex matching. The regex has already been compiled for us. */
81 return matchregex(needle, pcrecode);
82 }
83
84 if (strcmp(haystack, "*") == 0) {
85 /* Match anything */
86 return 1;
87 }
88
89 /* Implement a simple, no-wildcard match */
90 xhay = strdup(haystack);
91
92 tok = strtok_r(xhay, ",", &tokbuf);
93 while (tok) {
94 allneg = (allneg && (*tok == '!'));
95
96 if (!found) {
97 if (*tok == '!') {
98 found = (strcmp(tok+1, needle) == 0);
99 if (found) result = 0;
100 }
101 else {
102 found = (strcmp(tok, needle) == 0);
103 if (found) result = 1;
104 }
105 }
106
107 /* We must check all of the items in the haystack to see if they are all negative matches */
108 tok = strtok_r(NULL, ",", &tokbuf);
109 }
110 xfree(xhay);
111
112 /*
113 * If we didn't find it, and the list is exclusively negative matches,
114 * we must return a positive result for "no match".
115 */
116 if (!found && allneg) result = 1;
117
118 return result;
119 }
120
patternmatch(char * datatosearch,char * pattern,pcre * pcrecode)121 int patternmatch(char *datatosearch, char *pattern, pcre *pcrecode)
122 {
123 if (pcrecode) {
124 /* Do regex matching. The regex has already been compiled for us. */
125 return matchregex(datatosearch, pcrecode);
126 }
127
128 if (strcmp(pattern, "*") == 0) {
129 /* Match anything */
130 return 1;
131 }
132
133 return (strstr(datatosearch, pattern) != NULL);
134 }
135
compile_exprs(char * id,const char ** patterns,int count)136 pcre **compile_exprs(char *id, const char **patterns, int count)
137 {
138 pcre **result = NULL;
139 int i;
140
141 result = (pcre **)calloc(count, sizeof(pcre *));
142 for (i=0; (i < count); i++) {
143 result[i] = compileregex(patterns[i]);
144 if (!result[i]) {
145 errprintf("Internal error: %s pickdata PCRE-compile failed\n", id);
146 for (i=0; (i < count); i++) if (result[i]) pcre_free(result[i]);
147 xfree(result);
148 return NULL;
149 }
150 }
151
152 return result;
153 }
154
pickdata(char * buf,pcre * expr,int dupok,...)155 int pickdata(char *buf, pcre *expr, int dupok, ...)
156 {
157 int res, i;
158 int ovector[30];
159 va_list ap;
160 char **ptr;
161 char w[100];
162
163 if (!expr) return 0;
164
165 res = pcre_exec(expr, NULL, buf, strlen(buf), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
166 if (res < 0) return 0;
167
168 va_start(ap, dupok);
169
170 for (i=1; (i < res); i++) {
171 *w = '\0';
172 pcre_copy_substring(buf, ovector, res, i, w, sizeof(w));
173 ptr = va_arg(ap, char **);
174 if (dupok) {
175 if (*ptr) xfree(*ptr);
176 *ptr = strdup(w);
177 }
178 else {
179 if (*ptr == NULL) {
180 *ptr = strdup(w);
181 }
182 else {
183 dbgprintf("Internal error: Duplicate match ignored\n");
184 }
185 }
186 }
187
188 va_end(ap);
189
190 return 1;
191 }
192
193
timematch(char * holidaykey,char * tspec)194 int timematch(char *holidaykey, char *tspec)
195 {
196 int result;
197
198 result = within_sla(holidaykey, tspec, 0);
199
200 return result;
201 }
202
203
204