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