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