1 /*:ts=8*/
2 /*****************************************************************************
3  * FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail
4  *
5  * $Id: rematch.c,v 4.10 2004/08/22 20:19:11 n0ll Exp $
6  *
7  * Regular expression (POSIX functions) handling for FIDOGATE
8  *
9  *****************************************************************************
10  * Copyright (C) 1990-2004
11  *  _____ _____
12  * |     |___  |   Martin Junius             <mj.at.n0ll.dot.net>
13  * | | | |   | |   Radiumstr. 18
14  * |_|_|_|@home|   D-51069 Koeln, Germany
15  *
16  * This file is part of FIDOGATE.
17  *
18  * FIDOGATE is free software; you can redistribute it and/or modify it
19  * under the terms of the GNU General Public License as published by the
20  * Free Software Foundation; either version 2, or (at your option) any
21  * later version.
22  *
23  * FIDOGATE is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with FIDOGATE; see the file COPYING.  If not, write to the Free
30  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31  *****************************************************************************/
32 
33 #include "fidogate.h"
34 
35 
36 #ifdef HAS_POSIX_REGEX /******************************************************/
37 
38 #include <regex.h>
39 
40 
41 
42 /*
43  * List of regular expressions
44  */
45 typedef struct st_regex {
46     struct st_regex *next;
47     char            *re_s;
48     regex_t          re_c;
49 } Regex;
50 
51 
52 static Regex *regex_list = NULL;
53 static Regex *regex_last = NULL;
54 
55 
56 
57 /*
58  * Alloc and init new Regex struct
59  */
regex_new(void)60 static Regex *regex_new(void)
61 {
62     Regex *p;
63 
64     p = (Regex *)xmalloc(sizeof(Regex));
65 
66     /* Init */
67     p->next  = NULL;
68     p->re_s  = NULL;
69 
70     return p;
71 }
72 
73 
74 
75 /*
76  * Create new Regex struct for string
77  */
regex_parse_line(char * s)78 static Regex *regex_parse_line(char *s)
79 {
80     Regex *p;
81     int err;
82 
83     /* New regex entry */
84     p = regex_new();
85 
86     p->re_s = strsave(s);
87     err = regcomp(&p->re_c, p->re_s, REG_EXTENDED|REG_ICASE);
88     if(err) {
89 	logit("WARNING: error compiling regex %s", p->re_s);
90 	xfree(p);
91 	return NULL;
92     }
93 
94     debug(15, "regex: pattern=%s", p->re_s);
95 
96     return p;
97 }
98 
99 
100 
101 /*
102  * Put regex into linked list
103  */
regex_do_entry(char * s)104 static int regex_do_entry(char *s)
105 {
106     Regex *p;
107 
108     p = regex_parse_line(s);
109     if(!p)
110 	return ERROR;
111 
112     /* Put into linked list */
113     if(regex_list)
114 	regex_last->next = p;
115     else
116 	regex_list       = p;
117     regex_last       = p;
118 
119     return OK;
120 }
121 
122 
123 
124 /*
125  * Match string against regex list
126  */
127 #define MAXREGMATCH	10
128 
129 static regmatch_t regex_pmatch[MAXREGMATCH];
130 
131 
regex_match(const char * s)132 int regex_match(const char *s)
133 {
134     Regex *p;
135 
136     for(p=regex_list; p; p=p->next)
137     {
138 	if(regexec(&p->re_c, s, MAXREGMATCH, regex_pmatch, 0) == OK)
139 	    return TRUE;
140     }
141     return FALSE;
142 }
143 
144 
145 
146 /*
147  * Get i'th sub-expression from regex match
148  */
regex_match_sub(int i)149 static regmatch_t *regex_match_sub(int i)
150 {
151     return i<0 || i>=MAXREGMATCH ? NULL : &regex_pmatch[i];
152 }
153 
154 
155 
156 /*
157  * Copy i'th sub-expression to string buffer
158  */
str_regex_match_sub(char * buf,size_t len,int idx,const char * s)159 char *str_regex_match_sub(char *buf, size_t len, int idx, const char *s)
160 {
161     regmatch_t *p;
162     int i, j;
163 
164     p = regex_match_sub(idx);
165     if(p == NULL)
166     {
167 	buf[0] = 0;
168 	return NULL;
169     }
170 
171     for(i=0, j=p->rm_so; i<len-1 && j<p->rm_eo; i++, j++)
172 	buf[i] = s[j];
173     buf[i] = 0;
174 
175     return buf;
176 }
177 
178 
179 
180 /*
181  * Initialize regex list
182  */
regex_init(void)183 void regex_init(void)
184 {
185     char *s;
186 
187     /* regex patterns from fidogate.conf */
188     for(s = cf_get_string("Regex1stLine",TRUE);
189 	s;
190 	s = cf_get_string("Regex1stLine",FALSE) )
191 	regex_do_entry(s);
192 }
193 
194 
195 #endif /**HAS_POSIX_REGEX*****************************************************/
196 
197 
198 
199 
200 /***** TEST ******************************************************************/
201 
202 #ifdef TEST
203 
204 #ifdef HAS_POSIX_REGEX
debug_subs(void)205 void debug_subs(void)
206 {
207     int i;
208 
209     printf("pmatch[]:");
210     for(i=0; i<MAXREGMATCH; i++)
211 	if(regex_pmatch[i].rm_so != -1)
212 	    printf(" %d-%d", regex_pmatch[i].rm_so, regex_pmatch[i].rm_eo);
213     printf("\n");
214 }
215 #endif
216 
217 
218 /*
219  * Function test
220  */
main(int argc,char * argv[])221 int main(int argc, char *argv[])
222 {
223 #ifdef HAS_POSIX_REGEX
224     char buf[MAXINETADDR];
225 
226     regex_init();
227 
228 # if 0
229     do
230     {
231 	printf("Enter regex pattern [ENTER=end of list]: ");
232 	fflush(stdout);
233 	fgets(buffer, sizeof(buffer), stdin);
234 	strip_crlf(buffer);
235 	if(buffer[0])
236 	    regex_do_entry(buffer);
237     }
238     while(buffer[0]);
239 
240     printf("\n");
241 # endif
242 
243     /* Read strings to match */
244     do
245     {
246 	printf("Enter string [ENTER=end]: ");
247 	fflush(stdout);
248 	fgets(buffer, sizeof(buffer), stdin);
249 	strip_crlf(buffer);
250 	if(buffer[0])
251 	{
252 	    if(regex_match(buffer))
253 	    {
254 		printf("MATCH, ");
255 		debug_subs();
256 		str_regex_match_sub(buf, sizeof(buf), 1, buffer);
257 		printf("       (1) = \"%s\"\n", buf);
258 	    }
259 	    else
260 	    {
261 		printf("NO MATCH\n");
262 	    }
263 	}
264     }
265     while(buffer[0]);
266 #endif
267 
268     exit(0);
269 }
270 
271 #endif /**TEST**/
272