1 
2 %{
3 	/* getoption.c */
4 
5 #pragma	alloca	/* For AIX */
6 
7 #include	<assert.h>
8 #include	"emil.h"
9 
10 #ifndef	NO_FNMATCH
11 #include	<fnmatch.h>
12 #ifndef	FNM_NOMATCH
13 #define	FNM_NOMATCH	1	/* This MAY work!  941223/TW */
14 #endif
15 #else
16 static	int	ematch(char * p, char * s)
17 {
18 	/* Returns 0 if match, 1 else. '*' is a wildcard */
19 	/* Suggest that you install fnmatch instead...   */
20 #ifdef DEBUG
21   if (edebug)
22     fprintf(stderr, "-   ematch (no fnmatch).\n");
23 #endif
24   for (;*p;p++)
25     if (*p == '*')
26       {
27 	p++;
28 	if (*p=='\0')
29 	  return 0;
30 	while (*s != '\0')
31 	  {
32 	    if (ematch(p, s) == 0)
33 	      return 0;
34 	    else
35 	      s++;
36 	  }
37 	return	1;
38       }
39     else
40       if (*p != *(s++))
41 	return 1;
42   return *s;
43 }
44 #endif
45 
46 static	int	line_count;
47 static	int	error_count;	/* used in lex */
48 static	int	should_load_config_file	= 1;
49 extern	FILE *	conf_fd;
50 
Yalloc(int siz)51 void	* Yalloc(int siz)
52 {
53 	void	* Y;
54 	static	off_t	len	= 0,	/* Of allocated segment */
55 			offset	= 0;	/* Amount used thereof	*/
56 	static	char	* where;
57         char ebuf[256];
58 	alloc_total += siz;
59 	assert(siz > 0); siz     = ((siz + 3) / 4) * 4;	/* Word align */
60 
61 	if ((len - offset) < siz) {
62 
63 		if (len==0)	len	= pz;
64 		else		len	+= pz;
65 		if (len < siz)	len	= siz;
66 		/*
67 		 sprintf(ebuf,"Yalloc: len=%d offset=%d l-d=%d siz=%d",
68 			len, offset, len-offset, siz);
69 		 logger(LOG_DEBUG,ebuf);
70 		*/
71 		where	= malloc(len);
72 		if (where == NULL) {
73 			sprintf(ebuf,"getoption cannot get memory (%d) %m",len);
74 			logger(LOG_ERR,ebuf);
75 			fprintf(stderr, "Emil: Yalloc cannot get memory\n");
76 			exit(EX_OSERR);
77 		}
78 		Y	= where;
79 		offset	= siz;
80 	}
81 	else {
82 		Y	= &where[offset];
83 		offset	+= siz;
84 	}
85 	bzero(Y,siz);
86 	return	Y;
87 }
88 
89 #define	N_CONTEXT_TYPES	4	/* Mime, UUencode, Applefile */
90 
91 struct	member_struct	{
92 	struct	member_struct	* mm;	/* Points to next      */
93 	char	*	name;	/* Of the config group	       */
94 	char	*	r;	/* Receiver selection criteria */
95 	char	*	s;	/* Sender   selection criteria */
96 	char	*	rmx;	/* Receiver MX        criteria */
97 };
98 
99 struct	lookup_struct {
100 	struct	lookup_struct	* ll;
101 	char	* matchstring;
102 	char	* out;
103 };
104 
105 struct mailer_struct {
106   char    *name;
107   char    *mailer[15];
108   struct mailer_struct *next;
109 };
110 
111 
112 struct	lookup_struct	* table_start[N_CONTEXT_TYPES],
113 			* table_end[N_CONTEXT_TYPES];
114 
115 static	struct	config_struct	* g_start, /* Points to first group structure  */
116 				* g_end,   /* Points to the last group structure */
117 				* gtmp;
118 
119 static	struct	member_struct	* m_start, /* first member in chain */
120 				* m_end,   /* Last member in chain  */
121 				* mtmp;
122 static int                      ma_count;
123 static struct   mailer_struct   * ma_start,
124                                 * ma_end,
125                                 * matmp;
126 
127 static	char	* group_name;
128 
Ycmp(char * pattern,char * string)129 static	int	Ycmp(char * pattern, char * string)
130 {
131 	char	p[255], s[255]; char	* c, *d, *t; int i;
132 	int	cc;
133 
134 	/* Copy / fold */
135 
136 	for (c=pattern,d=p,i=(sizeof(p)-2); *c && i > 0; c++,d++,i--)
137 	  *d = tolower(*c);
138 	*d = 0;
139 
140 	for (c=string, d=s,i=(sizeof(s)-2); *c && i > 0; c++,d++,i--)
141 	  *d = tolower(*c);
142 	*d = 0;
143 
144 
145 	/* Compare */
146 
147 #ifndef	NO_FNMATCH
148 	cc = fnmatch(p, s, 0) != FNM_NOMATCH; /* 941223/TW */
149 #else
150 	cc = ematch(p, s) == 0;
151 #endif
152 #ifdef DEBUG
153 	if (edebug)
154 	  {
155 	    if (cc)
156 	      fprintf(stderr, "+   Ycmp: %s matches %s.\n", string, pattern);
157 	    else
158 	      fprintf(stderr, "+   Ycmp: %s does not match %s.\n", string, pattern);
159 	  }
160 #endif
161 	return	cc;
162 }
163 
164 extern 	char	* yytext;	/* defined by flex */
165 
yywrap()166 static	int	yywrap()
167 	{
168 		return	1;
169 	}
170 
yyerror(char * msg)171 static	void	yyerror(char * msg)
172 {
173 	char	ebuf[2048];
174 	sprintf(ebuf,"Config file: %s at line %d around '%s'\n",msg,line_count+1, yytext);
175 	logger(LOG_ERR,ebuf);
176 	error_count++;
177 }
178 %}
179 
180 %union {
181 	char * string;
182 	int	val;
183 }
184 
185 %token	APPLETYPE COLON COMMA EQUALS CHARSET TEXTENC HENC FORMAT BIN GROUP MAILER MEMBER EOR MATCH HOSTNAME
186 %token	<string> STRING QSTRING
187 
188 %start expressions
189 
190 %%
191 
192 expressions	: /* Empty */
193 		| expressions expression
194 		;
195 
196 expression	: GROUP STRING	COLON {
197 			/* this backward method is becase we want to look at first hit */
198 			gtmp	= g_end;
199 			g_end  	= Yalloc(sizeof(struct config_struct));
200 			if (g_start == NULL) 	g_start	= g_end;
201 			else			gtmp->gg= g_end;
202 			strcpy((g_end->name=Yalloc(strlen($2)+1)),$2);
203 		  }
204 		  varvals EOR
205                 | HOSTNAME COLON STRING EOR {
206                         hostname = (char *)NEWSTR($3);
207                   }
208 
209 		| MEMBER STRING COLON {
210 			strcpy((group_name=Yalloc(strlen($2)+1)),$2);
211 		  }
212 		  users	EOR
213 
214                 | MAILER STRING COLON {
215 
216                         matmp = ma_end;
217                         ma_end = (struct mailer_struct *)Yalloc(sizeof(struct mailer_struct));
218                         ma_end->name = NEWSTR($2);
219                         if (ma_start == NULL)  ma_start = ma_end;
220                         else                   matmp->next = ma_end;
221                         ma_count = 0;
222                   }
223                   mailers EOR
224 
225 
226 		| MATCH STRING QSTRING STRING EOR {
227 			/* Add a entry to match table */
228 			int	ctyp;
229 			struct	lookup_struct	* ttmp, ** ts, ** te;
230 			if	(strcasecmp($2,"MIME")==0)	ctyp	= 0;
231 			else if	(strcasecmp($2,"UUENCODE")==0)	ctyp	= 1;
232 			else if	(strcasecmp($2,"APPLEFILE")==0)	ctyp	= 2;
233 			else if	(strcasecmp($2,"MAILTOOL")==0)	ctyp	= 3;
234 			else	{
235 				yyerror("Wrong context type for match");
236 				YYERROR;
237 			}
238 			ts = &table_start[ctyp]; te = &table_end[ctyp];
239 			ttmp		= *te;
240 			*te		= Yalloc(sizeof(struct lookup_struct));
241 			if (*ts == NULL)  *ts	= *te;
242 			else		ttmp->ll= *te;
243 			strcpy(((*te)->matchstring=Yalloc(strlen($3)+1)),$3);
244 			strcpy(((*te)->out=Yalloc(strlen($4)+1)),$4);
245 		}
246 		;
247 
248 varvals		: varval
249 		| varval COMMA varvals
250 		;
251 
252 varval		: CHARSET EQUALS STRING	{
253 			strcpy((g_end->charset	= Yalloc(strlen($3)+1)),$3);
254 		  }
255 		| FORMAT  EQUALS STRING {
256 			strcpy((g_end->format	= Yalloc(strlen($3)+1)),$3);
257 		  }
258 		| BIN     EQUALS STRING {
259 			strcpy((g_end->bin	= Yalloc(strlen($3)+1)),$3);
260 		  }
261 		| TEXTENC EQUALS STRING {
262 			strcpy((g_end->text	= Yalloc(strlen($3)+1)),$3);
263 		  }
264 		| HENC EQUALS STRING {
265 			strcpy((g_end->header	= Yalloc(strlen($3)+1)),$3);
266 		  }
267 		| APPLETYPE EQUALS STRING {
268 			strcpy((g_end->appletype = Yalloc(strlen($3)+1)),$3);
269 		  }
270 		;
271 
272 mailers         : mailera
273                 | mailera COMMA mailers
274                 ;
275 
276 mailera         : STRING {
277                          ma_end->mailer[ma_count] = NEWSTR($1);
278                          ma_count++;
279                 }
280                 ;
281 
282 users		: user_definition
283 		| users COMMA user_definition
284 		;
285 
286 		  /* R      S     RMX  */
287 user_definition	: STRING STRING STRING
288 		  {
289 			mtmp	= m_end;
290 			m_end	= Yalloc(sizeof(struct	member_struct));
291 			if (m_start == NULL)	m_start	= m_end;
292 			else			mtmp->mm= m_end;
293 			m_end->name		= group_name;
294 			strcpy((m_end->r	= Yalloc(strlen($1)+1)),$1);
295 			strcpy((m_end->s	= Yalloc(strlen($2)+1)),$2);
296 			strcpy((m_end->rmx	= Yalloc(strlen($3)+1)),$3);
297 		  }
298 		;
299 
300 %%
301 
302 #include	"lex.yy.c"
303 
304 struct	config_struct *	getoption(char * r, char * s, char * rmx)
305 {
306 	struct	member_struct	* mm;
307 	struct	config_struct	* gg;
308 
309 #if	YYDEBUG
310 	extern	int	yydebug;
311 	yydebug	= 1;
312 #endif
313 
314 	if (should_load_config_file) {
315 		should_load_config_file = 0;
316 		if ((yyin = conf_fd) == NULL)
317 		  if ((yyin = fopen(MAINCF,"r")) == NULL) {
318 			char	ebuf[512];
319 			strcpy(ebuf,"Cannot open '");
320 			strcat(ebuf,MAINCF);
321 			strcat(ebuf,"' ");
322 			logger(LOG_ALERT,ebuf);
323 			return NULL;
324 		}
325 		if (yyparse())	return	NULL;
326 		fclose(yyin);
327 	}
328 
329 	/* Look for member */
330 
331 	for (mm = m_start; mm; mm = mm->mm)		/* Lookup member */
332 		if (Ycmp(mm->r,r) && Ycmp(mm->s,s) && Ycmp(mm->rmx,rmx))
333 			for (gg = g_start; gg; gg = gg->gg) /* Lookup group */
334 				if (strcasecmp(gg->name,mm->name)==0)
335 					return gg;
336 	return	NULL;	/* group or member not found */
337 }
338 
339 
getmember(char * name)340 struct	config_struct *	getmember(char * name)
341 {
342 	struct	config_struct	* gg;
343 
344 #if	YYDEBUG
345 	extern	int	yydebug;
346 	yydebug	= 1;
347 #endif
348 
349 	if (should_load_config_file) {
350 		should_load_config_file = 0;
351 		if ((yyin = conf_fd) == NULL)
352 		  if ((yyin = fopen(MAINCF,"r")) == NULL) {
353 			char	ebuf[512];
354 			strcpy(ebuf,"Cannot open '");
355 			strcat(ebuf,MAINCF);
356 			strcat(ebuf,"' ");
357 			logger(LOG_ALERT,ebuf);
358 			return NULL;
359 		}
360 		if (yyparse())	return	NULL;
361 		fclose(yyin);
362 	}
363 
364 	for (gg = g_start; gg; gg = gg->gg) /* Lookup group */
365 	  if (strcasecmp(gg->name,name)==0)
366 	    return gg;
367 	return	NULL;	/* group or member not found */
368 }
369 
confextr_error(int level,char * txt,char * context,char * match,char * output)370 static	void	confextr_error(int level, char * txt, char * context, char * match, char * output)
371 {
372 	char	buf[255];
373 	strcpy(buf,txt);
374 	strcat(buf," confextr(\"");
375 	if (context) strcat(buf,context); else strcat(buf,"<NULL>");
376 	strcat(buf,"\", \"");
377 	if (match) strcat(buf,match); else strcat(buf,"<NULL>");
378 	strcat(buf,"\", \"");
379 	if (output) strcat(buf,output); else strcat(buf,"<NULL>");
380 	strcat(buf,"\")");
381 	logger(level,buf);
382 }
383 
confextr(char * context,char * match,char * output)384 char	* confextr(char * context, char * match, char * output)
385 {
386 	int	context_type;
387 	struct	lookup_struct	* l;
388 
389 	if (should_load_config_file) {
390 		should_load_config_file = 0;
391 		if ((yyin = conf_fd)          == NULL &&
392 		    (yyin = fopen(MAINCF,"r"))==NULL) {
393 			perror("cannot open config file");
394 			return NULL;
395 		}
396 		if (yyparse())	return	NULL;
397 		fclose(yyin);
398 	}
399 
400 	if 	(context == NULL ||
401 		(match == NULL && output == NULL) ||
402 		(match != NULL && output != NULL))	{
403 		confextr_error(LOG_ERR, "Confextr: Invalid parameter combination",
404 			context,match,output);
405 		return NULL;
406 	}
407 
408 	if	(strcasecmp(context,"MIME")==0)		context_type	= 0;
409 	else if	(strcasecmp(context,"UUENCODE")==0)	context_type	= 1;
410 	else if	(strcasecmp(context,"APPLEFILE")==0)	context_type	= 2;
411 	else if	(strcasecmp(context,"MAILTOOL")==0)	context_type	= 3;
412 	else	{
413 		confextr_error(LOG_ERR, "Confextr: invalid context", context, match, output);
414 		return NULL;
415 	}
416 
417 	if (match == NULL) {
418 		if (output == NULL)	return NULL;
419 		for (l = table_start[context_type]; l; l = l->ll)
420 			if (strcasecmp(l->out,output)==0) return	l->matchstring;
421 		confextr_error(LOG_DEBUG, "Confextr: Info: Match not found", context, match, output);
422 		return	NULL;
423 	}
424 	else if (output == NULL) {
425 		if (match == NULL)	return NULL;
426 		for (l = table_start[context_type]; l; l = l->ll)
427 			if (strcasecmp(l->matchstring,match)==0) return	l->out;
428 		confextr_error(LOG_DEBUG, "Confextr: Info: Output not found", context, match, output);
429 		return	NULL;
430 	}
431 	else	{
432 		confextr_error(LOG_ERR, "Confextr: both match & output set", context, match, output);
433 		return	NULL;
434 	}
435 }
436 
437 
438 
get_mailer(char * mailer)439 char **	get_mailer(char * mailer)
440 {
441 	struct	mailer_struct	* mm;
442 
443 #if	YYDEBUG
444 	extern	int	yydebug;
445 	yydebug	= 1;
446 #endif
447 
448 	if (should_load_config_file) {
449 		should_load_config_file = 0;
450 		if ((yyin = conf_fd)          == NULL &&
451 		    (yyin = fopen(MAINCF,"r"))==NULL) {
452 			char	ebuf[512];
453 			strcpy(ebuf,"Cannot open '");
454 			strcat(ebuf,MAINCF);
455 			strcat(ebuf,"' ");
456 			logger(LOG_ALERT,ebuf);
457 			return NULL;
458 		}
459 		if (yyparse())	return	NULL;
460 		fclose(yyin);
461 	}
462 
463 	/* Look for member */
464 
465 	for (mm = ma_start; mm != NULL; mm = mm->next)		/* Lookup mailer */
466 	  {
467 	    if (cmatch(mm->name, mailer))
468 	      {
469 		char *c;
470 		int i;
471 		for (i = 0; mm->mailer[i] != NULL; i++)
472 		  {
473 		    c = mm->mailer[i];
474 		    if (*c == '$')
475 		      {
476 			c++;
477 			switch (*c) {
478 			case 's':
479 			case 'S':
480 			  mm->mailer[i] = sender;
481 			  break;
482 			case 'r':
483 			case 'R':
484 			  mm->mailer[i] = recipient;
485 			  break;
486 			case 'x':
487 			case 'X':
488 			  mm->mailer[i] = rmx;
489 			  break;
490 			default:
491 			  break;
492 			}
493 		      }
494 		  }
495 		return(mm->mailer);
496 	      }
497 	  }
498 	return NULL;
499 }
500 
501