1 5cdb1798 2005-10-29 devnull #include <u.h>
2 5cdb1798 2005-10-29 devnull #include <libc.h>
3 5cdb1798 2005-10-29 devnull #include <regexp.h>
4 5cdb1798 2005-10-29 devnull #include <libsec.h>
5 b5f65921 2006-02-11 devnull #include <libString.h>
6 5cdb1798 2005-10-29 devnull #include <bio.h>
7 5cdb1798 2005-10-29 devnull #include "dat.h"
9 5cdb1798 2005-10-29 devnull int debug;
13 5cdb1798 2005-10-29 devnull Tregexp= (1<<0), /* ~ */
14 5cdb1798 2005-10-29 devnull Texact= (1<<1), /* = */
17 5cdb1798 2005-10-29 devnull typedef struct Pattern Pattern;
18 5cdb1798 2005-10-29 devnull struct Pattern
20 5cdb1798 2005-10-29 devnull Pattern *next;
21 5cdb1798 2005-10-29 devnull int type;
22 5cdb1798 2005-10-29 devnull char *arg;
23 5cdb1798 2005-10-29 devnull int bang;
26 5cdb1798 2005-10-29 devnull String *patternpath;
27 5cdb1798 2005-10-29 devnull Pattern *patterns;
28 5cdb1798 2005-10-29 devnull String *mbox;
30 5cdb1798 2005-10-29 devnull static void
31 5cdb1798 2005-10-29 devnull usage(void)
33 5cdb1798 2005-10-29 devnull fprint(2, "usage: %s 'check|add' patternfile addr [addr*]\n", argv0);
34 5cdb1798 2005-10-29 devnull exits("usage");
38 5cdb1798 2005-10-29 devnull * convert string to lower case
40 5cdb1798 2005-10-29 devnull static void
41 5cdb1798 2005-10-29 devnull mklower(char *p)
45 5cdb1798 2005-10-29 devnull for(; *p; p++){
47 5cdb1798 2005-10-29 devnull if(c <= 'Z' && c >= 'A')
48 5cdb1798 2005-10-29 devnull *p = c - 'A' + 'a';
53 5cdb1798 2005-10-29 devnull * simplify an address, reduce to a domain
55 5cdb1798 2005-10-29 devnull static String*
56 5cdb1798 2005-10-29 devnull simplify(char *addr)
58 5cdb1798 2005-10-29 devnull int dots;
59 5cdb1798 2005-10-29 devnull char *p, *at;
60 5cdb1798 2005-10-29 devnull String *s;
62 5cdb1798 2005-10-29 devnull mklower(addr);
63 5cdb1798 2005-10-29 devnull at = strchr(addr, '@');
64 5cdb1798 2005-10-29 devnull if(at == nil){
65 5cdb1798 2005-10-29 devnull /* local address, make it an exact match */
66 5cdb1798 2005-10-29 devnull s = s_copy("=");
67 5cdb1798 2005-10-29 devnull s_append(s, addr);
68 5cdb1798 2005-10-29 devnull return s;
71 5cdb1798 2005-10-29 devnull /* copy up to the '@' sign */
73 5cdb1798 2005-10-29 devnull s = s_copy("~");
74 5cdb1798 2005-10-29 devnull for(p = addr; p < at; p++){
75 5cdb1798 2005-10-29 devnull if(strchr(".*+?(|)\\[]^$", *p))
76 5cdb1798 2005-10-29 devnull s_putc(s, '\\');
77 5cdb1798 2005-10-29 devnull s_putc(s, *p);
80 5cdb1798 2005-10-29 devnull /* just any address matching the two most significant domain elements */
81 5cdb1798 2005-10-29 devnull s_append(s, "(.*\\.)?");
82 5cdb1798 2005-10-29 devnull p = addr+strlen(addr);
83 5cdb1798 2005-10-29 devnull dots = 0;
84 5cdb1798 2005-10-29 devnull for(; p > at; p--){
85 5cdb1798 2005-10-29 devnull if(*p != '.')
86 5cdb1798 2005-10-29 devnull continue;
87 5cdb1798 2005-10-29 devnull if(dots++ > 0){
92 5cdb1798 2005-10-29 devnull for(; *p; p++){
93 5cdb1798 2005-10-29 devnull if(strchr(".*+?(|)\\[]^$", *p) != 0)
94 5cdb1798 2005-10-29 devnull s_putc(s, '\\');
95 5cdb1798 2005-10-29 devnull s_putc(s, *p);
97 5cdb1798 2005-10-29 devnull s_terminate(s);
99 5cdb1798 2005-10-29 devnull return s;
103 5cdb1798 2005-10-29 devnull * link patterns in order
105 5cdb1798 2005-10-29 devnull static int
106 5cdb1798 2005-10-29 devnull newpattern(int type, char *arg, int bang)
108 5cdb1798 2005-10-29 devnull Pattern *p;
109 5cdb1798 2005-10-29 devnull static Pattern *last;
111 5cdb1798 2005-10-29 devnull mklower(arg);
113 5cdb1798 2005-10-29 devnull p = mallocz(sizeof *p, 1);
114 5cdb1798 2005-10-29 devnull if(p == nil)
115 5cdb1798 2005-10-29 devnull return -1;
116 5cdb1798 2005-10-29 devnull if(type == Tregexp){
117 5cdb1798 2005-10-29 devnull p->arg = malloc(strlen(arg)+3);
118 5cdb1798 2005-10-29 devnull if(p->arg == nil){
119 5cdb1798 2005-10-29 devnull free(p);
120 5cdb1798 2005-10-29 devnull return -1;
122 5cdb1798 2005-10-29 devnull p->arg[0] = 0;
123 5cdb1798 2005-10-29 devnull strcat(p->arg, "^");
124 5cdb1798 2005-10-29 devnull strcat(p->arg, arg);
125 5cdb1798 2005-10-29 devnull strcat(p->arg, "$");
126 5cdb1798 2005-10-29 devnull } else {
127 5cdb1798 2005-10-29 devnull p->arg = strdup(arg);
128 5cdb1798 2005-10-29 devnull if(p->arg == nil){
129 5cdb1798 2005-10-29 devnull free(p);
130 5cdb1798 2005-10-29 devnull return -1;
133 5cdb1798 2005-10-29 devnull p->type = type;
134 5cdb1798 2005-10-29 devnull p->bang = bang;
135 5cdb1798 2005-10-29 devnull if(last == nil)
136 5cdb1798 2005-10-29 devnull patterns = p;
138 5cdb1798 2005-10-29 devnull last->next = p;
139 5cdb1798 2005-10-29 devnull last = p;
141 5cdb1798 2005-10-29 devnull return 0;
145 5cdb1798 2005-10-29 devnull * patterns are either
146 5cdb1798 2005-10-29 devnull * ~ regular expression
147 5cdb1798 2005-10-29 devnull * = exact match string
149 5cdb1798 2005-10-29 devnull * all comparisons are case insensitive
151 5cdb1798 2005-10-29 devnull static int
152 5cdb1798 2005-10-29 devnull readpatterns(char *path)
154 5cdb1798 2005-10-29 devnull Biobuf *b;
155 5cdb1798 2005-10-29 devnull char *p;
156 5cdb1798 2005-10-29 devnull char *token[2];
158 5cdb1798 2005-10-29 devnull int bang;
160 5cdb1798 2005-10-29 devnull b = Bopen(path, OREAD);
161 5cdb1798 2005-10-29 devnull if(b == nil)
162 5cdb1798 2005-10-29 devnull return -1;
163 5cdb1798 2005-10-29 devnull while((p = Brdline(b, '\n')) != nil){
164 5cdb1798 2005-10-29 devnull p[Blinelen(b)-1] = 0;
165 5cdb1798 2005-10-29 devnull n = tokenize(p, token, 2);
166 5cdb1798 2005-10-29 devnull if(n == 0)
167 5cdb1798 2005-10-29 devnull continue;
169 5cdb1798 2005-10-29 devnull mklower(token[0]);
170 5cdb1798 2005-10-29 devnull p = token[0];
171 5cdb1798 2005-10-29 devnull if(*p == '!'){
173 5cdb1798 2005-10-29 devnull bang = 1;
175 5cdb1798 2005-10-29 devnull bang = 0;
177 5cdb1798 2005-10-29 devnull if(*p == '='){
178 5cdb1798 2005-10-29 devnull if(newpattern(Texact, p+1, bang) < 0)
179 5cdb1798 2005-10-29 devnull return -1;
180 5cdb1798 2005-10-29 devnull } else if(*p == '~'){
181 5cdb1798 2005-10-29 devnull if(newpattern(Tregexp, p+1, bang) < 0)
182 5cdb1798 2005-10-29 devnull return -1;
183 5cdb1798 2005-10-29 devnull } else if(strcmp(token[0], "#include") == 0 && n == 2)
184 5cdb1798 2005-10-29 devnull readpatterns(token[1]);
186 5cdb1798 2005-10-29 devnull Bterm(b);
187 5cdb1798 2005-10-29 devnull return 0;
190 5cdb1798 2005-10-29 devnull /* fuck, shit, bugger, damn */
191 b5f65921 2006-02-11 devnull void regerror(char *err)
193 b5f65921 2006-02-11 devnull USED(err);
197 5cdb1798 2005-10-29 devnull * check lower case version of address agains patterns
199 5cdb1798 2005-10-29 devnull static Pattern*
200 5cdb1798 2005-10-29 devnull checkaddr(char *arg)
202 5cdb1798 2005-10-29 devnull Pattern *p;
203 5cdb1798 2005-10-29 devnull Reprog *rp;
204 5cdb1798 2005-10-29 devnull String *s;
206 5cdb1798 2005-10-29 devnull s = s_copy(arg);
207 5cdb1798 2005-10-29 devnull mklower(s_to_c(s));
209 5cdb1798 2005-10-29 devnull for(p = patterns; p != nil; p = p->next)
210 5cdb1798 2005-10-29 devnull switch(p->type){
211 5cdb1798 2005-10-29 devnull case Texact:
212 5cdb1798 2005-10-29 devnull if(strcmp(p->arg, s_to_c(s)) == 0){
213 5cdb1798 2005-10-29 devnull free(s);
214 5cdb1798 2005-10-29 devnull return p;
217 5cdb1798 2005-10-29 devnull case Tregexp:
218 5cdb1798 2005-10-29 devnull rp = regcomp(p->arg);
219 5cdb1798 2005-10-29 devnull if(rp == nil)
220 5cdb1798 2005-10-29 devnull continue;
221 5cdb1798 2005-10-29 devnull if(regexec(rp, s_to_c(s), nil, 0)){
222 5cdb1798 2005-10-29 devnull free(rp);
223 5cdb1798 2005-10-29 devnull free(s);
224 5cdb1798 2005-10-29 devnull return p;
226 5cdb1798 2005-10-29 devnull free(rp);
229 5cdb1798 2005-10-29 devnull s_free(s);
230 5cdb1798 2005-10-29 devnull return 0;
232 5cdb1798 2005-10-29 devnull static char*
233 5cdb1798 2005-10-29 devnull check(int argc, char **argv)
236 5cdb1798 2005-10-29 devnull Addr *a;
237 5cdb1798 2005-10-29 devnull Pattern *p;
238 5cdb1798 2005-10-29 devnull int matchedbang;
240 5cdb1798 2005-10-29 devnull matchedbang = 0;
241 5cdb1798 2005-10-29 devnull for(i = 0; i < argc; i++){
242 5cdb1798 2005-10-29 devnull a = readaddrs(argv[i], nil);
243 5cdb1798 2005-10-29 devnull for(; a != nil; a = a->next){
244 5cdb1798 2005-10-29 devnull p = checkaddr(a->val);
245 5cdb1798 2005-10-29 devnull if(p == nil)
246 5cdb1798 2005-10-29 devnull continue;
247 5cdb1798 2005-10-29 devnull if(p->bang)
248 5cdb1798 2005-10-29 devnull matchedbang = 1;
250 5cdb1798 2005-10-29 devnull return nil;
253 5cdb1798 2005-10-29 devnull if(matchedbang)
254 5cdb1798 2005-10-29 devnull return "!match";
256 5cdb1798 2005-10-29 devnull return "no match";
260 5cdb1798 2005-10-29 devnull * add anything that isn't already matched, all matches are lower case
262 5cdb1798 2005-10-29 devnull static char*
263 5cdb1798 2005-10-29 devnull add(char *pp, int argc, char **argv)
265 5cdb1798 2005-10-29 devnull int fd, i;
266 5cdb1798 2005-10-29 devnull String *s;
267 5cdb1798 2005-10-29 devnull char *cp;
268 5cdb1798 2005-10-29 devnull Addr *a;
270 5cdb1798 2005-10-29 devnull a = nil;
271 5cdb1798 2005-10-29 devnull for(i = 0; i < argc; i++)
272 5cdb1798 2005-10-29 devnull a = readaddrs(argv[i], a);
274 5cdb1798 2005-10-29 devnull fd = open(pp, OWRITE);
275 5cdb1798 2005-10-29 devnull seek(fd, 0, 2);
276 5cdb1798 2005-10-29 devnull for(; a != nil; a = a->next){
277 5cdb1798 2005-10-29 devnull if(checkaddr(a->val))
278 5cdb1798 2005-10-29 devnull continue;
279 5cdb1798 2005-10-29 devnull s = simplify(a->val);
280 5cdb1798 2005-10-29 devnull cp = s_to_c(s);
281 5cdb1798 2005-10-29 devnull fprint(fd, "%q\t%q\n", cp, a->val);
282 5cdb1798 2005-10-29 devnull if(*cp == '=')
283 5cdb1798 2005-10-29 devnull newpattern(Texact, cp+1, 0);
284 5cdb1798 2005-10-29 devnull else if(*cp == '~')
285 5cdb1798 2005-10-29 devnull newpattern(Tregexp, cp+1, 0);
286 5cdb1798 2005-10-29 devnull s_free(s);
288 5cdb1798 2005-10-29 devnull close(fd);
289 5cdb1798 2005-10-29 devnull return nil;
293 5cdb1798 2005-10-29 devnull main(int argc, char **argv)
295 5cdb1798 2005-10-29 devnull char *patternpath;
297 5cdb1798 2005-10-29 devnull ARGBEGIN {
298 5cdb1798 2005-10-29 devnull case 'd':
299 5cdb1798 2005-10-29 devnull debug++;
301 5cdb1798 2005-10-29 devnull } ARGEND;
303 5cdb1798 2005-10-29 devnull quotefmtinstall();
305 5cdb1798 2005-10-29 devnull if(argc < 3)
306 5cdb1798 2005-10-29 devnull usage();
308 5cdb1798 2005-10-29 devnull patternpath = argv[1];
309 5cdb1798 2005-10-29 devnull readpatterns(patternpath);
310 5cdb1798 2005-10-29 devnull if(strcmp(argv[0], "add") == 0)
311 5cdb1798 2005-10-29 devnull exits(add(patternpath, argc-2, argv+2));
312 5cdb1798 2005-10-29 devnull else if(strcmp(argv[0], "check") == 0)
313 5cdb1798 2005-10-29 devnull exits(check(argc-2, argv+2));
315 5cdb1798 2005-10-29 devnull usage();