1 /**********************************************************
2 * expression parser
3 **********************************************************/
4 /*
5 * $Id: flagexp.y,v 1.3 2005/05/06 20:31:58 mitry Exp $
6 *
7 * $Log: flagexp.y,v $
8 * Revision 1.3 2005/05/06 20:31:58 mitry
9 * Changed strtok() to strsep()
10 *
11 * Revision 1.2 2005/03/31 19:40:38 mitry
12 * Update function prototypes and it's duplication
13 *
14 */
15
16 %{
17 #include "headers.h"
18 #include <fnmatch.h>
19
20 #ifdef NEED_DEBUG
21 #define YYERROR_VERBOSE 1
22 #endif
23 #define YYDEBUG 0
24
25 #ifdef YYTEXT_POINTER
26 extern char *yytext;
27 #else
28 extern char yytext[];
29 #endif
30 extern char *yyPTR;
31 extern int yylex();
32 static int logic(int e1,int op,int e2);
33 static int checkflag(void);
34 static int checkconnstr(void);
35 static int checkspeed(int op, int speed, int real);
36 static int checksfree(int op, int sp);
37 static int checkmailer(void);
38 static int checkphone(void);
39 static int checkport(void);
40 static int checkcid(void);
41 static int checkhost(void);
42 static int checkfile(void);
43 static int checkexec(void);
44 static int checkline(int lnum);
45 static int yyerror(char *s);
46 static int flxpres;
47 %}
48
49 %token DATESTR GAPSTR PHSTR TIMESTR ADDRSTR PATHSTR ANYSTR IDENT NUMBER
50 %token AROP LOGOP EQ NE GT GE LT LE AND OR NOT XOR LB RB COMMA
51 %token ADDRESS ITIME CONNSTR SPEED CONNECT PHONE MAILER CID
52 %token FLTIME FLDATE EXEC FLLINE PORT FLFILE HOST SFREE
53 %expect 2
54
55 %%
56 fullline : expression
57 {flxpres=$1;}
58 ;
59 expression : elemexp
60 {$$ = $1;}
61 | NOT expression
62 {$$ = !($2);}
63 | expression LOGOP expression
64 {$$ = logic($1,$2,$3);}
65 | LB expression RB
66 {$$ = $2;}
67 ;
68 elemexp : flag
69 | CONNECT AROP NUMBER
70 {$$ = checkspeed($2,$3,1);}
71 | SPEED AROP NUMBER
72 {$$ = checkspeed($2,$3,0);}
73 | SFREE AROP NUMBER PATHSTR
74 {$$ = checksfree($2,$3);}
75 | CONNSTR CONNSTR
76 {$$ = checkconnstr();}
77 | PHONE PHSTR
78 {$$ = checkphone();}
79 | MAILER IDENT
80 {$$ = checkmailer();}
81 | CID PHSTR
82 {$$ = checkcid();}
83 | HOST IDENT
84 {$$ = checkhost();}
85 | PORT IDENT
86 {$$ = checkport();}
87 | EXEC ANYSTR
88 {$$ = checkexec();}
89 | FLFILE PATHSTR
90 {$$ = checkfile();}
91 | FLLINE NUMBER
92 {$$ = checkline($2);}
93 | ITIME timestring
94 {$$ = $2;}
95 | FLTIME gapstring
96 {$$ = $2;}
97 | FLDATE datestring
98 {$$ = $2;}
99 | ADDRESS ADDRSTR
100 {$$ = $2;}
101 ;
102 flag : IDENT
103 {$$ = checkflag();}
104 ;
105 datestring : DATESTR
106 {$$ = $1;}
107 | DATESTR COMMA datestring
108 {$$ = logic($1,OR,$3);}
109 ;
110 timestring : TIMESTR
111 {$$ = $1;}
112 | TIMESTR COMMA timestring
113 {$$ = logic($1,OR,$3);}
114 ;
115 gapstring : GAPSTR
116 {$$ = $1;}
117 | GAPSTR COMMA gapstring
118 {$$ = logic($1,OR,$3);}
119 ;
120 %%
121
122 static int logic(int e1, int op, int e2)
123 {
124 DEBUG(('Y',2,"Logic: %d (%d,%s) %d",e1,op,
125 (AND==op?"AND":
126 (OR==op?"OR":
127 (XOR==op?"XOR":"???"
128 ))),e2));
129 switch (op)
130 {
131 case AND: return(e1 && e2);
132 case OR: return(e1 || e2);
133 case XOR: return(e1 ^ e2)?1:0;
134 default:
135 DEBUG(('Y',1,"Logic: invalid logical operator %d",op));
136 return 0;
137 }
138 }
139
checkflag(void)140 static int checkflag(void)
141 {
142 int fln;
143 char *p, *q;
144 DEBUG(('Y',2,"checkflag: \"%s\"",yytext));
145 #ifdef WITH_PERL
146 if(!strncasecmp(yytext,"perl",4)) {
147 if((fln=atoi(yytext+4))<0||fln>9) {
148 write_log("error: invalid perl flag: %s",yytext);
149 return 0;
150 }
151 DEBUG(('Y',3,"checkflag: perl%d: %d",fln,(perl_flg&(1<<fln))?1:0));
152 return((perl_flg&(1<<fln))?1:0);
153 }
154 #endif
155 if(!rnode)return 0;
156 if(!strncasecmp(yytext,"list",4)) {
157 DEBUG(('Y',3,"checkflag: listed: %d",rnode->options&O_LST));
158 return rnode->options&O_LST;
159 }
160 if(!strncasecmp(yytext,"prot",4)) {
161 DEBUG(('Y',3,"checkflag: protected: %d",rnode->options&O_PWD));
162 return rnode->options&O_PWD;
163 }
164 if(!strncasecmp(yytext,"in",2)) {
165 DEBUG(('Y',3,"checkflag: inbound: %d",rnode->options&O_INB));
166 return rnode->options&O_INB;
167 }
168 if(!strncasecmp(yytext,"out",3)) {
169 DEBUG(('Y',3,"checkflag: outbound: %d",!(rnode->options&O_INB)));
170 return !(rnode->options&O_INB);
171 }
172 if(!strncasecmp(yytext,"tcp",3)) {
173 DEBUG(('Y',3,"checkflag: tcp/ip: %d",rnode->options&O_TCP));
174 return rnode->options&O_TCP;
175 }
176 if(!strncasecmp(yytext,"binkp",5)) {
177 DEBUG(('Y',3,"checkflag: binkp: %d",bink));
178 return bink;
179 }
180 if(!strncasecmp(yytext,"bad",3)) {
181 DEBUG(('Y',3,"checkflag: bad password: %d",rnode->options&O_BAD));
182 return rnode->options&O_BAD;
183 }
184 if(rnode->flags) {
185 char *r;
186 q = xstrdup(rnode->flags);
187 r = q;;
188 while(( p = strsep( &r, "," ))) {
189 if(!strcasecmp(yytext,p)) {
190 xfree(q);
191 DEBUG(('Y',3,"checkflag: other: 1"));
192 return 1;
193 }
194 }
195 xfree(q);
196 }
197 DEBUG(('Y',3,"checkflag: other: 0"));
198 return 0;
199 }
200
201
checkconnstr(void)202 static int checkconnstr(void)
203 {
204 DEBUG(('Y',2,"checkconnstr: \"%s\"",yytext));
205 if(!connstr||is_ip) return 0;
206 DEBUG(('Y',3,"checkconnstr: \"%s\" <-> \"%s\"",yytext,connstr));
207 if(!strstr(connstr,yytext)) return 1;
208 return 0;
209 }
210
checkspeed(int op,int speed,int real)211 static int checkspeed(int op, int speed, int real)
212 {
213 DEBUG(('Y',2,"checkspeed: \"%s\"",yytext));
214 if(!rnode) return 0;
215 DEBUG(('Y',3,"check%sspeed: %d (%d,%s) %d",real?"real":"",real?rnode->realspeed:rnode->speed,op,
216 (EQ==op?"==":
217 (NE==op?"!=":
218 (GT==op?">":
219 (GE==op?">=":
220 (LT==op?"<":
221 (LE==op?"<=":"???"
222 )))))),speed));
223 switch (op)
224 {
225 case EQ: return(real?rnode->realspeed:rnode->speed == speed);
226 case NE: return(real?rnode->realspeed:rnode->speed != speed);
227 case GT: return(real?rnode->realspeed:rnode->speed > speed);
228 case GE: return(real?rnode->realspeed:rnode->speed >= speed);
229 case LT: return(real?rnode->realspeed:rnode->speed < speed);
230 case LE: return(real?rnode->realspeed:rnode->speed <= speed);
231 default:
232 DEBUG(('Y',1,"Logic: invalid comparsion operator %d",op));
233 return 0;
234 }
235 }
236
checksfree(int op,int sf)237 static int checksfree(int op, int sf)
238 {
239 int fs=getfreespace((const char*)yytext);
240 DEBUG(('Y',2,"checksfree: '%s' %d (%d,%s) %d",yytext,fs,op,
241 (GT==op?">":(GE==op?">=":
242 (LT==op?"<":(LE==op?"<=":"???")))),sf));
243 switch (op) {
244 case GT: return(fs > sf);
245 case GE: return(fs >= sf);
246 case LT: return(fs < sf);
247 case LE: return(fs <= sf);
248 default:
249 DEBUG(('Y',1,"Logic: invalid comparsion operator %d",op));
250 return 0;
251 }
252 }
253
checkphone(void)254 static int checkphone(void)
255 {
256 DEBUG(('Y',2,"checkphone: \"%s\"",yytext));
257 if(!rnode||!rnode->phone) return 0;
258 DEBUG(('Y',3,"checkphone: \"%s\" <-> \"%s\"",yytext,rnode->phone));
259 if(!strncasecmp(yytext,rnode->phone,strlen(yytext))) return 1;
260 return 0;
261 }
262
checkmailer(void)263 static int checkmailer(void)
264 {
265 DEBUG(('Y',2,"checkmailer: \"%s\"",yytext));
266 if(!rnode||!rnode->mailer) return 0;
267 DEBUG(('Y',3,"checkmailer: \"%s\" <-> \"%s\"",yytext,rnode->mailer));
268 if(!strstr(rnode->mailer,yytext)) return 1;
269 return 0;
270 }
271
checkcid(void)272 static int checkcid(void)
273 {
274 char *cid = getenv("CALLER_ID");
275 if(!cid||strlen(cid)<4) cid = "none";
276 DEBUG(('Y',2,"checkcid: \"%s\" <-> \"%s\"",yytext,cid));
277 if(!strncasecmp(yytext,cid,strlen(yytext))) return 1;
278 return 0;
279 }
280
checkhost(void)281 static int checkhost(void)
282 {
283 DEBUG(('Y',2,"checkhost: \"%s\"",yytext));
284 if(!rnode || !rnode->host) return 0;
285 DEBUG(('Y',3,"checkhost: \"%s\" <-> \"%s\"",yytext,rnode->host));
286 if(!strncasecmp(yytext,rnode->host,strlen(yytext)))return 1;
287 return 0;
288 }
289
checkport(void)290 static int checkport(void)
291 {
292 DEBUG(('Y',2,"checkport: \"%s\"",yytext));
293 if(!rnode || !rnode->tty) return 0;
294 DEBUG(('Y',3,"checkport: \"%s\" <-> \"%s\"",yytext,rnode->tty));
295 if(!fnmatch(yytext,rnode->tty,FNM_NOESCAPE|FNM_PATHNAME)) return 1;
296 return 0;
297 }
298
checkfile(void)299 static int checkfile(void)
300 {
301 struct stat sb;
302 DEBUG(('Y',2,"checkfile: \"%s\" -> %d",yytext,!stat(yytext,&sb)));
303 if(!stat(yytext,&sb)) return 1;
304 return 0;
305 }
306
checkexec(void)307 static int checkexec(void)
308 {
309 int rc;
310 char *cmd=xstrdup(yytext);
311 DEBUG(('Y',2,"checkexec: \"%s\"",yytext));
312 strtr(cmd,',',' ');
313 rc=execsh(cmd);
314 DEBUG(('Y',3,"checkexec: \"%s\" -> %d",cmd,!rc));
315 xfree(cmd);
316 return !rc;
317 }
318
checkline(int lnum)319 static int checkline(int lnum)
320 {
321 DEBUG(('Y',2,"checkline: \"%s\"",yytext));
322 if(!rnode) return 0;
323 DEBUG(('Y',3,"checkline: %d <-> %d",lnum,rnode->hidnum));
324 if(rnode->hidnum==lnum)return 1;
325 return 0;
326 }
327
flagexp(slist_t * expr,int strict)328 int flagexp(slist_t *expr, int strict)
329 {
330 char *p;
331 #if YYDEBUG==1
332 yydebug=1;
333 #endif
334 for(;expr;expr=expr->next) {
335 DEBUG(('Y',1,"checkexpression: \"%s\"",expr->str));
336 p=xstrdup(expr->str);
337 yyPTR=p;
338 flxpres=0;
339 if(yyparse()) {
340 DEBUG(('Y',1,"checkexpression: couldn't parse%s",strict?"":", assume 'false'",expr->str));
341 xfree(p);
342 return(strict?-1:0);
343 }
344 #ifdef NEED_DEBUG
345 if(strict!=1)DEBUG(('Y',1,"checkexpression: result is \"%s\"",flxpres?"true":"false"));
346 #endif
347 xfree(p);
348 if(!flxpres)return 0;
349 }
350 return 1;
351 }
352
yyerror(char * s)353 static int yyerror(char *s)
354 {
355 DEBUG(('Y',1,"yyerror: %s at %s",s,(yytext&&*yytext)?yytext:"end of input"));
356 return 0;
357 }
358