%{ /* getoption.c */ #pragma alloca /* For AIX */ #include #include "emil.h" #ifndef NO_FNMATCH #include #ifndef FNM_NOMATCH #define FNM_NOMATCH 1 /* This MAY work! 941223/TW */ #endif #else static int ematch(char * p, char * s) { /* Returns 0 if match, 1 else. '*' is a wildcard */ /* Suggest that you install fnmatch instead... */ #ifdef DEBUG if (edebug) fprintf(stderr, "- ematch (no fnmatch).\n"); #endif for (;*p;p++) if (*p == '*') { p++; if (*p=='\0') return 0; while (*s != '\0') { if (ematch(p, s) == 0) return 0; else s++; } return 1; } else if (*p != *(s++)) return 1; return *s; } #endif static int line_count; static int error_count; /* used in lex */ static int should_load_config_file = 1; extern FILE * conf_fd; void * Yalloc(int siz) { void * Y; static off_t len = 0, /* Of allocated segment */ offset = 0; /* Amount used thereof */ static char * where; char ebuf[256]; alloc_total += siz; assert(siz > 0); siz = ((siz + 3) / 4) * 4; /* Word align */ if ((len - offset) < siz) { if (len==0) len = pz; else len += pz; if (len < siz) len = siz; /* sprintf(ebuf,"Yalloc: len=%d offset=%d l-d=%d siz=%d", len, offset, len-offset, siz); logger(LOG_DEBUG,ebuf); */ where = malloc(len); if (where == NULL) { sprintf(ebuf,"getoption cannot get memory (%d) %m",len); logger(LOG_ERR,ebuf); fprintf(stderr, "Emil: Yalloc cannot get memory\n"); exit(EX_OSERR); } Y = where; offset = siz; } else { Y = &where[offset]; offset += siz; } bzero(Y,siz); return Y; } #define N_CONTEXT_TYPES 4 /* Mime, UUencode, Applefile */ struct member_struct { struct member_struct * mm; /* Points to next */ char * name; /* Of the config group */ char * r; /* Receiver selection criteria */ char * s; /* Sender selection criteria */ char * rmx; /* Receiver MX criteria */ }; struct lookup_struct { struct lookup_struct * ll; char * matchstring; char * out; }; struct mailer_struct { char *name; char *mailer[15]; struct mailer_struct *next; }; struct lookup_struct * table_start[N_CONTEXT_TYPES], * table_end[N_CONTEXT_TYPES]; static struct config_struct * g_start, /* Points to first group structure */ * g_end, /* Points to the last group structure */ * gtmp; static struct member_struct * m_start, /* first member in chain */ * m_end, /* Last member in chain */ * mtmp; static int ma_count; static struct mailer_struct * ma_start, * ma_end, * matmp; static char * group_name; static int Ycmp(char * pattern, char * string) { char p[255], s[255]; char * c, *d, *t; int i; int cc; /* Copy / fold */ for (c=pattern,d=p,i=(sizeof(p)-2); *c && i > 0; c++,d++,i--) *d = tolower(*c); *d = 0; for (c=string, d=s,i=(sizeof(s)-2); *c && i > 0; c++,d++,i--) *d = tolower(*c); *d = 0; /* Compare */ #ifndef NO_FNMATCH cc = fnmatch(p, s, 0) != FNM_NOMATCH; /* 941223/TW */ #else cc = ematch(p, s) == 0; #endif #ifdef DEBUG if (edebug) { if (cc) fprintf(stderr, "+ Ycmp: %s matches %s.\n", string, pattern); else fprintf(stderr, "+ Ycmp: %s does not match %s.\n", string, pattern); } #endif return cc; } extern char * yytext; /* defined by flex */ /* static int yywrap() { return 1; } */ #define yywrap() 1 static void yyerror(char * msg) { char ebuf[2048]; sprintf(ebuf,"Config file: %s at line %d around '%s'\n",msg,line_count+1, yytext); logger(LOG_ERR,ebuf); error_count++; } %} %union { char * string; int val; } %token APPLETYPE COLON COMMA EQUALS CHARSET TEXTENC HENC FORMAT BIN GROUP MAILER MEMBER EOR MATCH HOSTNAME %token STRING QSTRING %start expressions %% expressions : /* Empty */ | expressions expression ; expression : GROUP STRING COLON { /* this backward method is becase we want to look at first hit */ gtmp = g_end; g_end = Yalloc(sizeof(struct config_struct)); if (g_start == NULL) g_start = g_end; else gtmp->gg= g_end; strcpy((g_end->name=Yalloc(strlen($2)+1)),$2); } varvals EOR | HOSTNAME COLON STRING EOR { hostname = (char *)NEWSTR($3); } | MEMBER STRING COLON { strcpy((group_name=Yalloc(strlen($2)+1)),$2); } users EOR | MAILER STRING COLON { matmp = ma_end; ma_end = (struct mailer_struct *)Yalloc(sizeof(struct mailer_struct)); ma_end->name = NEWSTR($2); if (ma_start == NULL) ma_start = ma_end; else matmp->next = ma_end; ma_count = 0; } mailers EOR | MATCH STRING QSTRING STRING EOR { /* Add a entry to match table */ int ctyp; struct lookup_struct * ttmp, ** ts, ** te; if (strcasecmp($2,"MIME")==0) ctyp = 0; else if (strcasecmp($2,"UUENCODE")==0) ctyp = 1; else if (strcasecmp($2,"APPLEFILE")==0) ctyp = 2; else if (strcasecmp($2,"MAILTOOL")==0) ctyp = 3; else { yyerror("Wrong context type for match"); YYERROR; } ts = &table_start[ctyp]; te = &table_end[ctyp]; ttmp = *te; *te = Yalloc(sizeof(struct lookup_struct)); if (*ts == NULL) *ts = *te; else ttmp->ll= *te; strcpy(((*te)->matchstring=Yalloc(strlen($3)+1)),$3); strcpy(((*te)->out=Yalloc(strlen($4)+1)),$4); } ; varvals : varval | varval COMMA varvals ; varval : CHARSET EQUALS STRING { strcpy((g_end->charset = Yalloc(strlen($3)+1)),$3); } | FORMAT EQUALS STRING { strcpy((g_end->format = Yalloc(strlen($3)+1)),$3); } | BIN EQUALS STRING { strcpy((g_end->bin = Yalloc(strlen($3)+1)),$3); } | TEXTENC EQUALS STRING { strcpy((g_end->text = Yalloc(strlen($3)+1)),$3); } | HENC EQUALS STRING { strcpy((g_end->header = Yalloc(strlen($3)+1)),$3); } | APPLETYPE EQUALS STRING { strcpy((g_end->appletype = Yalloc(strlen($3)+1)),$3); } ; mailers : mailera | mailera COMMA mailers ; mailera : STRING { ma_end->mailer[ma_count] = NEWSTR($1); ma_count++; } ; users : user_definition | users COMMA user_definition ; /* R S RMX */ user_definition : STRING STRING STRING { mtmp = m_end; m_end = Yalloc(sizeof(struct member_struct)); if (m_start == NULL) m_start = m_end; else mtmp->mm= m_end; m_end->name = group_name; strcpy((m_end->r = Yalloc(strlen($1)+1)),$1); strcpy((m_end->s = Yalloc(strlen($2)+1)),$2); strcpy((m_end->rmx = Yalloc(strlen($3)+1)),$3); } ; %% #include "lex.yy.c" struct config_struct * getoption(char * r, char * s, char * rmx) { struct member_struct * mm; struct config_struct * gg; #ifdef YYDEBUG extern int yydebug; yydebug = 1; #endif if (should_load_config_file) { should_load_config_file = 0; if ((yyin = conf_fd) == NULL) if ((yyin = fopen(MAINCF,"r")) == NULL) { char ebuf[512]; strcpy(ebuf,"Cannot open '"); strcat(ebuf,MAINCF); strcat(ebuf,"' "); logger(LOG_ALERT,ebuf); return NULL; } if (yyparse()) return NULL; fclose(yyin); } /* Look for member */ for (mm = m_start; mm; mm = mm->mm) /* Lookup member */ if (Ycmp(mm->r,r) && Ycmp(mm->s,s) && Ycmp(mm->rmx,rmx)) for (gg = g_start; gg; gg = gg->gg) /* Lookup group */ if (strcasecmp(gg->name,mm->name)==0) return gg; return NULL; /* group or member not found */ } struct config_struct * getmember(char * name) { struct config_struct * gg; #ifdef YYDEBUG extern int yydebug; yydebug = 1; #endif if (should_load_config_file) { should_load_config_file = 0; if ((yyin = conf_fd) == NULL) if ((yyin = fopen(MAINCF,"r")) == NULL) { char ebuf[512]; strcpy(ebuf,"Cannot open '"); strcat(ebuf,MAINCF); strcat(ebuf,"' "); logger(LOG_ALERT,ebuf); return NULL; } if (yyparse()) return NULL; fclose(yyin); } for (gg = g_start; gg; gg = gg->gg) /* Lookup group */ if (strcasecmp(gg->name,name)==0) return gg; return NULL; /* group or member not found */ } static void confextr_error(int level, char * txt, char * context, char * match, char * output) { char buf[255]; strcpy(buf,txt); strcat(buf," confextr(\""); if (context) strcat(buf,context); else strcat(buf,""); strcat(buf,"\", \""); if (match) strcat(buf,match); else strcat(buf,""); strcat(buf,"\", \""); if (output) strcat(buf,output); else strcat(buf,""); strcat(buf,"\")"); logger(level,buf); } char * confextr(char * context, char * match, char * output) { int context_type; struct lookup_struct * l; if (should_load_config_file) { should_load_config_file = 0; if ((yyin = conf_fd) == NULL && (yyin = fopen(MAINCF,"r"))==NULL) { perror("cannot open config file"); return NULL; } if (yyparse()) return NULL; fclose(yyin); } if (context == NULL || (match == NULL && output == NULL) || (match != NULL && output != NULL)) { confextr_error(LOG_ERR, "Confextr: Invalid parameter combination", context,match,output); return NULL; } if (strcasecmp(context,"MIME")==0) context_type = 0; else if (strcasecmp(context,"UUENCODE")==0) context_type = 1; else if (strcasecmp(context,"APPLEFILE")==0) context_type = 2; else if (strcasecmp(context,"MAILTOOL")==0) context_type = 3; else { confextr_error(LOG_ERR, "Confextr: invalid context", context, match, output); return NULL; } if (match == NULL) { if (output == NULL) return NULL; for (l = table_start[context_type]; l; l = l->ll) if (strcasecmp(l->out,output)==0) return l->matchstring; confextr_error(LOG_DEBUG, "Confextr: Info: Match not found", context, match, output); return NULL; } else if (output == NULL) { if (match == NULL) return NULL; for (l = table_start[context_type]; l; l = l->ll) if (strcasecmp(l->matchstring,match)==0) return l->out; confextr_error(LOG_DEBUG, "Confextr: Info: Output not found", context, match, output); return NULL; } else { confextr_error(LOG_ERR, "Confextr: both match & output set", context, match, output); return NULL; } } char ** get_mailer(char * mailer) { struct mailer_struct * mm; #ifdef YYDEBUG extern int yydebug; yydebug = 1; #endif if (should_load_config_file) { should_load_config_file = 0; if ((yyin = conf_fd) == NULL && (yyin = fopen(MAINCF,"r"))==NULL) { char ebuf[512]; strcpy(ebuf,"Cannot open '"); strcat(ebuf,MAINCF); strcat(ebuf,"' "); logger(LOG_ALERT,ebuf); return NULL; } if (yyparse()) return NULL; fclose(yyin); } /* Look for member */ for (mm = ma_start; mm != NULL; mm = mm->next) /* Lookup mailer */ { if (cmatch(mm->name, mailer)) { char *c; int i; for (i = 0; mm->mailer[i] != NULL; i++) { c = mm->mailer[i]; if (*c == '$') { c++; switch (*c) { case 's': case 'S': mm->mailer[i] = sender; break; case 'r': case 'R': mm->mailer[i] = recipient; break; case 'x': case 'X': mm->mailer[i] = rmx; break; default: break; } } } return(mm->mailer); } } return NULL; }