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