From 8520befe602e9b90d455342068a623f2cf89f631 Mon Sep 17 00:00:00 2001 From: Ian C Date: Thu, 4 Dec 2003 01:54:55 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. --- src/config.c | 715 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 715 insertions(+) create mode 100644 src/config.c (limited to 'src/config.c') diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..af55d58 --- /dev/null +++ b/src/config.c @@ -0,0 +1,715 @@ +/* + + kbs - Simple, easily fooled, POP3 spam filter + + Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.co.uk) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + Config + +*/ +static const char id[]="$Id$"; + +#include +#include +#include +#include +#include + +#include "global.h" +#include "config.h" +#include "dstring.h" +#include "dbase.h" +#include "rexp.h" +#include "util.h" + + +/* ---------------------------------------- TYPES +*/ +typedef enum { + TOK_Expression, + TOK_Set, + TOK_OpenBracket, + TOK_CloseBracket, + TOK_Domain, + TOK_TrustedUsers, + TOK_TrustedDomains, + TOK_Default, + TOK_BlockUser, + TOK_AllowSubject, + TOK_BlockSubject, + TOK_VarHostname, + TOK_VarPort, + TOK_VarUsername, + TOK_VarPassword, + TOK_VarLog, + TOK_VarTimeout, + TOK_VarCasesense, + TOK_VarDejunk, + TOK_VarTestmode, + TOK_VarBlockHTML, + TOK_VarDeletelog, + TOK_ConstOn, + TOK_ConstOff, + TOK_ConstBlock, + TOK_ConstAllow, + TOK_EOF + } Token; + +typedef struct Command + { + const char *cmd; + Token token; + } Command; + + +/* ---------------------------------------- GLOBALS +*/ +static DString error; +static char *hostname="localhost"; +static char *username="nobody"; +static char *password=""; +static char *log=""; +static char *deletelog=""; +static int port=110; +static int timeout=60; +static int casesense=FALSE; +static int dejunk=FALSE; +static int testmode=FALSE; +static int blockhtml=FALSE; + + +/* ---------------------------------------- COMMAND TABLE +*/ +static const Command cmd_table[]= + { + /* Commands and main tokens + */ + {"set", TOK_Set}, + {"trusted_users", TOK_TrustedUsers}, + {"trusted_domains", TOK_TrustedDomains}, + {"{", TOK_OpenBracket}, + {"}", TOK_CloseBracket}, + {"domain", TOK_Domain}, + {"default", TOK_Default}, + {"block_user", TOK_BlockUser}, + {"allow_subject", TOK_AllowSubject}, + {"block_subject", TOK_BlockSubject}, + + /* Variables + */ + {"hostname", TOK_VarHostname}, + {"port", TOK_VarPort}, + {"username", TOK_VarUsername}, + {"password", TOK_VarPassword}, + {"log", TOK_VarLog}, + {"timeout", TOK_VarTimeout}, + {"casesense", TOK_VarCasesense}, + {"dejunk", TOK_VarDejunk}, + {"testmode", TOK_VarTestmode}, + {"blockhtml", TOK_VarBlockHTML}, + + /* Constants + */ + {"on", TOK_ConstOn}, + {"off", TOK_ConstOff}, + {"block", TOK_ConstBlock}, + {"allow", TOK_ConstAllow}, + + /* End of table + */ + {NULL, TOK_EOF} + }; + + +/* ---------------------------------------- REQUIRED PROTOS +*/ +static Token GetToken(FILE *fp, DString ret); + + +/* ---------------------------------------- COMMAND HANDLERS +*/ +static int DoSet(FILE *fp) +{ +# define TYPE_STR 0 +# define TYPE_INT 1 +# define TYPE_ONOFF 2 + + static const struct VarTable + { + Token token; + int type; + void *ptr; + } var_table[]= + { + {TOK_VarHostname, TYPE_STR, (void *)&hostname}, + {TOK_VarPort, TYPE_INT, (void *)&port}, + {TOK_VarUsername, TYPE_STR, (void *)&username}, + {TOK_VarPassword, TYPE_STR, (void *)&password}, + {TOK_VarLog, TYPE_STR, (void *)&log}, + {TOK_VarTimeout, TYPE_INT, (void *)&timeout}, + {TOK_VarCasesense, TYPE_ONOFF, (void *)&casesense}, + {TOK_VarDejunk, TYPE_ONOFF, (void *)&dejunk}, + {TOK_VarTestmode, TYPE_ONOFF, (void *)&testmode}, + {TOK_VarBlockHTML, TYPE_ONOFF, (void *)&blockhtml}, + {TOK_VarDeletelog, TYPE_STR, (void *)&deletelog}, + {TOK_EOF,0,NULL} + }; + + const struct VarTable *vt=NULL; + DString ds; + Token tok; + int status=TRUE; + int f; + + ds=DSInit(); + + tok=GetToken(fp,ds); + + for(f=0;var_table[f].token!=TOK_EOF && !vt;f++) + if (var_table[f].token==tok) + vt=var_table+f; + + if (vt) + { + char **cp; + int *ip; + + switch(vt->type) + { + case TYPE_STR: + cp=vt->ptr; + tok=GetToken(fp,ds); + *cp=CopyStr(ds->text); + break; + + case TYPE_INT: + ip=vt->ptr; + tok=GetToken(fp,ds); + *ip=atoi(ds->text); + break; + + case TYPE_ONOFF: + ip=vt->ptr; + tok=GetToken(fp,ds); + + switch(tok) + { + case TOK_ConstOn: + *ip=TRUE; + break; + + case TOK_ConstOff: + *ip=FALSE; + break; + + default: + status=FALSE; + DSAddCP(error,"Expected on/off. Got: "); + DSAddDS(error,ds); + } + break; + } + } + else + { + status=FALSE; + DSAddCP(error,"Unrecognised variable: "); + DSAddDS(error,ds); + } + + DSFree(ds); + +# undef TYPE_STR +# undef TYPE_INT +# undef TYPE_ONOFF + + return status; +} + + +static int DoDomain(FILE *fp) +{ + DString ds; + Token tok; + int status=TRUE; + Domain *domain; + + ds=DSInit(); + + tok=GetToken(fp,ds); + + if (tok!=TOK_Expression) + { + DSAddCP(error,"Domain must be followed by expression. Got: "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + } + + if (RExpSearch(ds->text,"dummy")==RE_BadExpression) + { + DSAddCP(error,"Bad regular expression: "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + } + + domain=DBNewDomain(ds->text); + + tok=GetToken(fp,ds); + + if (tok!=TOK_OpenBracket) + { + DSAddCP(error,"Missing opening bracket in domain"); + DSFree(ds); + return FALSE; + } + + while((tok=GetToken(fp,ds))!=TOK_CloseBracket) + { + if (tok==TOK_EOF) + { + DSAddCP(error,"Missing close bracket in domain"); + DSFree(ds); + return FALSE; + } + + switch(tok) + { + case TOK_Default: + switch(GetToken(fp,ds)) + { + case TOK_ConstAllow: + DBDefault(domain,FALSE); + break; + + case TOK_ConstBlock: + DBDefault(domain,TRUE); + break; + + default: + DSAddCP(error,"Unexpected value in default command: "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + break; + } + + break; + + case TOK_BlockUser: + GetToken(fp,ds); + DBBlockUser(domain,ds->text); + break; + + case TOK_AllowSubject: + GetToken(fp,ds); + + if (RExpSearch(ds->text,"dummy")==RE_BadExpression) + { + DSAddCP(error,"Bad regular expression: "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + } + + DBAllowSubject(domain,ds->text); + break; + + case TOK_BlockSubject: + GetToken(fp,ds); + + if (RExpSearch(ds->text,"dummy")==RE_BadExpression) + { + DSAddCP(error,"Bad regular expression: "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + } + + DBBlockSubject(domain,ds->text); + break; + + default: + DSAddCP(error,"Unexpected string in domain command: "); + DSAddDS(error,ds); + DSFree(ds); + return FALSE; + break; + } + } + + DSFree(ds); + + return TRUE; +} + + +static int DoTrustedUsers(FILE *fp) +{ + DString ds; + Token tok; + int status=TRUE; + + ds=DSInit(); + + tok=GetToken(fp,ds); + + if (tok!=TOK_OpenBracket) + { + DSAddCP(error,"Missing opening bracket in trusted_users"); + DSFree(ds); + return FALSE; + } + + while((tok=GetToken(fp,ds))!=TOK_CloseBracket) + { + if (tok==TOK_EOF) + { + DSAddCP(error,"Missing close bracket in trusted_users"); + DSFree(ds); + return FALSE; + } + + DBTrustedUser(ds->text); + } + + DSFree(ds); + + return TRUE; +} + + +static int DoTrustedDomains(FILE *fp) +{ + DString ds; + Token tok; + int status=TRUE; + + ds=DSInit(); + + tok=GetToken(fp,ds); + + if (tok!=TOK_OpenBracket) + { + DSAddCP(error,"Missing opening bracket in trusted_domains"); + return FALSE; + } + + while((tok=GetToken(fp,ds))!=TOK_CloseBracket) + { + if (tok==TOK_EOF) + { + DSAddCP(error,"Missing close bracket in trusted_domains"); + return FALSE; + } + + DBTrustedDomain(ds->text); + } + + return TRUE; +} + + +/* ---------------------------------------- PRVIVATE FUNCTIONS +*/ +static int Getc(FILE *fp) +{ + int ch; + + ch=fgetc(fp); + + if (ch=='#') + { + ch=fgetc(fp); + + while(ch!=EOF && ch!='\n') + ch=fgetc(fp); + } + + return ch; +} + + +static int SkipWS(FILE *fp) +{ + int ch; + + ch=Getc(fp); + + while(isspace(ch)) + ch=Getc(fp); + + if (ch==EOF) + return FALSE; + else + { + ungetc(ch,fp); + return TRUE; + } +} + + +static Token FindToken(const char *p) +{ + int f; + + for(f=0;cmd_table[f].cmd;f++) + if (strcmp(cmd_table[f].cmd,p)==0) + return cmd_table[f].token; + + return TOK_Expression; +} + + +static int IsTerm(int ch) +{ + return isspace(ch) || ch=='#'; +} + + +static Token GetToken(FILE *fp, DString ret) +{ + int ch; + int done=FALSE; + int quote=0; + Token tok; + + ret=DSReset(ret); + + if (feof(fp)) + { + DSAddCP(ret,"EOF"); + return TOK_EOF; + } + + if (!SkipWS(fp)) + { + DSAddCP(ret,"EOF"); + return TOK_EOF; + } + + while(!done) + { + ch=fgetc(fp); + + if (quote) + { + if (ch==EOF) + { + done=TRUE; + + DSAddCP(error,"Unexpected EOF in string"); + tok=TOK_EOF; + } + else if (ch==quote) + { + done=TRUE; + tok=FindToken(ret->text); + } + else + { + DSAddChar(ret,ch); + } + } + else + { + if (ch==EOF) + { + done=TRUE; + + if (ret->len) + tok=FindToken(ret->text); + else + tok=TOK_EOF; + } + else if (IsTerm(ch)) + { + ungetc(ch,fp); + done=TRUE; + tok=FindToken(ret->text); + } + else if (ch=='\'' || ch=='"') + { + quote=ch; + } + else + { + DSAddChar(ret,ch); + } + } + } + + return tok; +} + + +static int Parse(FILE *fp) +{ + DString txt; + Token tok; + char *p; + + txt=DSInit(); + + while((tok=GetToken(fp,txt))!=TOK_EOF) + { + int ok=TRUE; + + switch(tok) + { + case TOK_Set: + if (!DoSet(fp)) + ok=FALSE; + break; + + case TOK_Domain: + if (!DoDomain(fp)) + ok=FALSE; + break; + + case TOK_TrustedUsers: + if (!DoTrustedUsers(fp)) + ok=FALSE; + break; + + case TOK_TrustedDomains: + if (!DoTrustedDomains(fp)) + ok=FALSE; + break; + + case TOK_Expression: + DSAddCP(error,"Unknown command in config file: "); + DSAddDS(error,txt); + ok=FALSE; + break; + + default: + DSAddCP(error,"Unexpected token in config file: "); + DSAddDS(error,txt); + ok=FALSE; + break; + } + + if (!ok) + break; + + txt=DSReset(txt); + } + + DSFree(txt); + + return error->len==0; +} + + +/* ---------------------------------------- INTERFACES +*/ + +int ConfigLoad(void) +{ + DString ds; + FILE *fp; + int ret; + + error=DSInit(); + + if (!getenv("HOME")) + return FALSE; + + ds=DSInit(); + + DSAddCP(ds,getenv("HOME")); + DSAddChar(ds,'/'); + DSAddCP(ds,".kbsrc"); + + if ((fp=fopen(ds->text,"r"))) + ret=Parse(fp); + else + ret=FALSE; + + DSFree(ds); + + return ret; +} + + +const char *ConfigError(void) +{ + if (strlen(error->text)) + return error->text; + else + return strerror(errno); +} + + +const char *ConfigString(ConfigStringVar var) +{ + switch(var) + { + case CONFIG_HOSTNAME: + return hostname; + + case CONFIG_USERNAME: + return username; + + case CONFIG_PASSWORD: + return password; + + case CONFIG_LOG: + return log; + + case CONFIG_DELETE_LOG: + return deletelog; + + default: + return ""; + } +} + + +int ConfigInt(ConfigIntVar var) +{ + switch(var) + { + case CONFIG_PORT: + return port; + + case CONFIG_TIMEOUT: + return timeout; + + case CONFIG_CASESENSE: + return casesense; + + case CONFIG_DEJUNK: + return dejunk; + + case CONFIG_TESTMODE: + return testmode; + + case CONFIG_BLOCKHTML: + return blockhtml; + + default: + return 0; + } +} + + +/* END OF FILE */ -- cgit v1.2.3