From 787bb7625c9abc6b09efbc6bbe004a19d4b96166 Mon Sep 17 00:00:00 2001 From: Ian C Date: Sun, 7 Dec 2003 01:46:44 +0000 Subject: Made RE compiled once and added memory release --- INSTALL | 7 +-- doc/INSTRUCTION | 9 ++-- src/config.c | 40 ++++++++++++----- src/config.h | 6 +++ src/dbase.c | 136 ++++++++++++++++++++++++++++++++++++++++++-------------- src/dbase.h | 26 ++++++++--- src/kbs.c | 8 +++- src/rexp.c | 33 ++++++++++---- src/rexp.h | 21 +++++---- 9 files changed, 211 insertions(+), 75 deletions(-) diff --git a/INSTALL b/INSTALL index 5674bb7..c0b1b86 100644 --- a/INSTALL +++ b/INSTALL @@ -8,15 +8,16 @@ To build the software, type the following: make depend make -Then copy the kbs executable wherever you want. +Then copy the kbs executable wherever you want (sorry there is no install, +but it does only generate one executable and no other dependencies). Other or broken systems ======================= If the Makefile is not usable on your system, you simply need to compile all -the .c files and produce a single kbs object. E.g. (using the cc command -as an example): +the .c files and produce a single kbs executable. E.g. (using a UNIX-style cc +compiler as an example): cd src cc -o casm *.c diff --git a/doc/INSTRUCTION b/doc/INSTRUCTION index 921d8ee..ef0cdc6 100644 --- a/doc/INSTRUCTION +++ b/doc/INSTRUCTION @@ -16,7 +16,8 @@ a special keyword in a subject header to be used. Config file format ================== -The kbs config file is read from $HOME/.kbsrc and is in the form: +The kbs config file is read from $HOME/.kbsrc and has sections in the suggested +order: [config settings] @@ -34,9 +35,9 @@ includes spaces, simple quote them (with either single or double quotes). Note that escapes aren't used (to make regular expression writing easier), so if you want to include a quote in a string, simply use the other sort of quote. -If you want both, you're stuck! +If you want both, sorry, you're stuck! -To see and example kbsrc file, see kbsrc in the src directory. +To see an example kbsrc file, see kbsrc in the src directory. Config settings @@ -151,4 +152,4 @@ domain. ------------------------------------------------------------------------------- -$Id: INSTRUCTION,v 1.2 2003-12-05 02:33:05 ianc Exp $ +$Id: INSTRUCTION,v 1.3 2003-12-07 01:46:44 ianc Exp $ diff --git a/src/config.c b/src/config.c index 18d7cfd..616fabf 100644 --- a/src/config.c +++ b/src/config.c @@ -81,10 +81,10 @@ typedef struct Command /* ---------------------------------------- GLOBALS */ static DString error; -static char *hostname="localhost"; -static char *username="nobody"; -static char *password=""; -static char *log=""; +static char *hostname=NULL; +static char *username=NULL; +static char *password=NULL; +static char *log=NULL; static int port=110; static int timeout=60; static int casesense=FALSE; @@ -196,6 +196,10 @@ static int DoSet(FILE *fp) case TYPE_STR: cp=vt->ptr; tok=GetToken(fp,&ds); + + if (*cp) + free(*cp); + *cp=CopyStr(ds->text); break; @@ -250,6 +254,7 @@ static int DoDomain(FILE *fp) Token tok; int status=TRUE; Domain *domain; + RE_Expression re; ds=DSInit(); @@ -263,7 +268,7 @@ static int DoDomain(FILE *fp) return FALSE; } - if (RExpSearch(ds->text,"dummy")==RE_BadExpression) + if (!(re=RECompile(ds->text))) { DSAddCP(error,"Bad regular expression: "); DSAddDS(error,ds); @@ -271,7 +276,7 @@ static int DoDomain(FILE *fp) return FALSE; } - domain=DBNewDomain(ds->text); + domain=DBNewDomain(re); tok=GetToken(fp,&ds); @@ -322,7 +327,7 @@ static int DoDomain(FILE *fp) case TOK_AllowSubject: GetToken(fp,&ds); - if (RExpSearch(ds->text,"dummy")==RE_BadExpression) + if (!(re=RECompile(ds->text))) { DSAddCP(error,"Bad regular expression: "); DSAddDS(error,ds); @@ -330,13 +335,13 @@ static int DoDomain(FILE *fp) return FALSE; } - DBAllowSubject(domain,ds->text); + DBAllowSubject(domain,re); break; case TOK_BlockSubject: GetToken(fp,&ds); - if (RExpSearch(ds->text,"dummy")==RE_BadExpression) + if (!(re=RECompile(ds->text))) { DSAddCP(error,"Bad regular expression: "); DSAddDS(error,ds); @@ -344,7 +349,7 @@ static int DoDomain(FILE *fp) return FALSE; } - DBBlockSubject(domain,ds->text); + DBBlockSubject(domain,re); break; default: @@ -631,6 +636,11 @@ int ConfigLoad(void) error=DSInit(); + hostname=CopyStr("localhost"); + username=CopyStr("nobody"); + password=CopyStr(""); + log=CopyStr(""); + if (!getenv("HOME")) return FALSE; @@ -713,4 +723,14 @@ int ConfigInt(ConfigIntVar var) } +void ConfigClose(void) +{ + DSFree(error); + free(hostname); + free(username); + free(password); + free(log); +} + + /* END OF FILE */ diff --git a/src/config.h b/src/config.h index 40140dc..3fec38f 100644 --- a/src/config.h +++ b/src/config.h @@ -75,6 +75,12 @@ const char *ConfigError(void); const char *ConfigString(ConfigStringVar var); int ConfigInt(ConfigIntVar var); + +/* Free any memory allocated +*/ +void ConfigClose(void); + + #endif /* END OF FILE */ diff --git a/src/dbase.c b/src/dbase.c index ce568af..aed142d 100644 --- a/src/dbase.c +++ b/src/dbase.c @@ -35,7 +35,6 @@ static const char id[]="$Id$"; #include "dbase.h" #include "dstring.h" #include "config.h" -#include "rexp.h" #include "util.h" @@ -43,29 +42,31 @@ static const char id[]="$Id$"; */ struct Domain { - char *name; - int def_block; - int no_user; - int no_block; - int no_allow; - char **user; - char **block; - char **allow; - Domain *next; - Domain *prev; + RE_Expression name; + int def_block; + int no_user; + int no_block; + int no_allow; + char **user; + RE_Expression *block; + RE_Expression *allow; + Domain *next; + Domain *prev; }; /* ---------------------------------------- GLOBALS */ -static Domain *head; -static Domain *tail; +static Domain *head; +static Domain *tail; -static int no_trusted_users=0; -static int no_trusted_domains=0; +static int no_trusted_users=0; +static int no_trusted_domains=0; -static char **trusted_user=NULL; -static char **trusted_domain=NULL; +static char **trusted_user=NULL; +static char **trusted_domain=NULL; + +static const char *reason; /* ---------------------------------------- PRVIVATE FUNCTIONS @@ -106,7 +107,7 @@ static const Domain *GetDomain(const char *domain) while(dom) { - if (RExpSearch(dom->name,domain)==RE_Found) + if (RESearch(dom->name,domain)) return dom; dom=dom->next; @@ -144,13 +145,13 @@ static void DeJunk(DString ds, const char *p) /* ---------------------------------------- INTERFACES */ -Domain *DBNewDomain(const char *regexp) +Domain *DBNewDomain(RE_Expression name) { Domain *dom; dom=Malloc(sizeof *dom); - dom->name=CopyStr(regexp); + dom->name=name; dom->def_block=FALSE; dom->no_user=0; @@ -187,19 +188,19 @@ void DBBlockUser(Domain *domain, const char *username) } -void DBAllowSubject(Domain *domain, const char *regexp) +void DBAllowSubject(Domain *domain, RE_Expression re) { domain->no_allow++; - domain->allow=Realloc(domain->allow,sizeof(char *)*domain->no_allow); - domain->allow[domain->no_allow-1]=CopyStr(regexp); + domain->allow=Realloc(domain->allow,sizeof(RE_Expression)*domain->no_allow); + domain->allow[domain->no_allow-1]=re; } -void DBBlockSubject(Domain *domain, const char *regexp) +void DBBlockSubject(Domain *domain, RE_Expression re) { domain->no_block++; - domain->block=Realloc(domain->block,sizeof(char *)*domain->no_block); - domain->block[domain->no_block-1]=CopyStr(regexp); + domain->block=Realloc(domain->block,sizeof(RE_Expression)*domain->no_block); + domain->block[domain->no_block-1]=re; } @@ -226,6 +227,8 @@ int DBBlockMessage(const POP3Message *msg) const Domain *dom; int f; + reason="None"; + if (IsTrustedDomain(msg->from_domain)) return FALSE; @@ -234,22 +237,27 @@ int DBBlockMessage(const POP3Message *msg) if (ConfigInt(CONFIG_BLOCKHTML) && strncmp(msg->content_type,html,strlen(html))==0) + { + reason="HTML message"; return TRUE; + } if (!(dom=GetDomain(msg->from_domain))) return FALSE; for(f=0;fno_user;f++) { + int res; + if (ConfigInt(CONFIG_CASESENSE)) - { - if (strcmp(dom->user[f],msg->from_uname)==0) - return TRUE; - } + res=strcmp(dom->user[f],msg->from_uname); else + res=strcasecmp(dom->user[f],msg->from_uname); + + if (res==0) { - if (strcasecmp(dom->user[f],msg->from_uname)==0) - return TRUE; + reason="disallowed name"; + return TRUE; } } @@ -262,7 +270,7 @@ int DBBlockMessage(const POP3Message *msg) for(f=0;fno_allow;f++) { - if (RExpSearch(dom->allow[f],ds->text)==RE_Found) + if (RESearch(dom->allow[f],ds->text)) { DSFree(ds); return FALSE; @@ -271,16 +279,76 @@ int DBBlockMessage(const POP3Message *msg) for(f=0;fno_block;f++) { - if (RExpSearch(dom->block[f],ds->text)==RE_Found) + if (RESearch(dom->block[f],ds->text)) { + reason="disallowed subject"; DSFree(ds); return TRUE; } } + reason="default"; DSFree(ds); return dom->def_block; } +const char *DBBlockReason(void) +{ + return reason; +} + + +void DBClose(void) +{ + Domain *d; + int f; + + for(f=0;fnext; + + for(f=0;fno_user;f++) + free(t->user[f]); + + free(t->user); + + for(f=0;fno_block;f++) + REFree(t->block[f]); + + free(t->block); + + for(f=0;fno_allow;f++) + free(t->allow[f]); + + free(t->allow); + + free(t); + } + + no_trusted_users=0; + no_trusted_domains=0; + + head=tail=NULL; + trusted_user=NULL; + trusted_domain=NULL; +} + + /* END OF FILE */ diff --git a/src/dbase.h b/src/dbase.h index df64927..c7a98ee 100644 --- a/src/dbase.h +++ b/src/dbase.h @@ -30,6 +30,7 @@ #define KBS_DBASE_H #include "msg.h" +#include "rexp.h" /* ---------------------------------------- TYPES */ @@ -41,9 +42,10 @@ typedef struct Domain Domain; /* ---------------------------------------- INTERFACES */ -/* Add a new domain and define the regular expression that defines it +/* Add a new domain and define the regular expression that defines it. + re will be freed by the database when closed. */ -Domain *DBNewDomain(const char *regexp); +Domain *DBNewDomain(RE_Expression name); /* Define the default mode for a domain @@ -56,14 +58,16 @@ void DBDefault(Domain *domain, int block); void DBBlockUser(Domain *domain, const char *username); -/* Add an allowable subject for a domain +/* Add an allowable subject for a domain. + re will be freed by the database when closed. */ -void DBAllowSubject(Domain *domain, const char *regexp); +void DBAllowSubject(Domain *domain, RE_Expression re); -/* Adds a disallowed subject for a domain +/* Adds a disallowed subject for a domain. + re will be freed by the database when closed. */ -void DBBlockSubject(Domain *domain, const char *regexp); +void DBBlockSubject(Domain *domain, RE_Expression re); /* Adds a trusted username @@ -81,6 +85,16 @@ void DBTrustedDomain(const char *domain); int DBBlockMessage(const POP3Message *msg); +/* Returns reason for last block if message is to be blocked. +*/ +const char *DBBlockReason(void); + + +/* Free up memory allocated to database. +*/ +void DBClose(void); + + #endif /* END OF FILE */ diff --git a/src/kbs.c b/src/kbs.c index f5f3aab..5c978b4 100644 --- a/src/kbs.c +++ b/src/kbs.c @@ -142,10 +142,13 @@ int main(int argc, char *argv[]) Log(fp,"From %s@%s\n",msg[f].from_uname, msg[f].from_domain); Log(fp,"Subject %.40s\n",msg[f].subject); + Log(fp,"Reason %s\n",DBBlockReason()); } else { - Log(fp,"%s@%s\n",msg[f].from_uname,msg[f].from_domain); + Log(fp,"%s@%s (%s)\n",msg[f].from_uname, + msg[f].from_domain, + DBBlockReason()); } if (!ConfigInt(CONFIG_TESTMODE)) @@ -172,6 +175,9 @@ int main(int argc, char *argv[]) fclose(fp); } + DBClose(); + ConfigClose(); + return EXIT_SUCCESS; } diff --git a/src/rexp.c b/src/rexp.c index 0311c44..3e51aa6 100644 --- a/src/rexp.c +++ b/src/rexp.c @@ -31,32 +31,47 @@ static const char id[]="$Id$"; #include "global.h" #include "rexp.h" #include "config.h" +#include "util.h" /* ---------------------------------------- INTERFACES */ -RExpStatus RExpSearch(const char *regexpr, const char *string) +RE_Expression RECompile(const char *regexpr) { - regex_t re; + regex_t *re; int flags; - int res; + + re=Malloc(sizeof *re); flags=REG_EXTENDED|REG_NOSUB; if (!ConfigInt(CONFIG_CASESENSE)) flags|=REG_ICASE; - if (regcomp(&re,regexpr,flags)) - return RE_BadExpression; + if (regcomp(re,regexpr,flags)) + { + free(re); + re=NULL; + } + + return re; +} - res=regexec(&re,string,0,NULL,0); - regfree(&re); +int RESearch(const RE_Expression re, const char *string) +{ + return !regexec(re,string,0,NULL,0); +} - /* printf("RExpSearch(%s,%s)=%d\n",regexpr,string,res); */ - return res ? RE_NotFound : RE_Found; +void REFree(RE_Expression re) +{ + if (re) + { + regfree(re); + free(re); + } } diff --git a/src/rexp.h b/src/rexp.h index 04d1bb6..98d685f 100644 --- a/src/rexp.h +++ b/src/rexp.h @@ -33,18 +33,23 @@ /* ---------------------------------------- INTERFACES */ +typedef void *RE_Expression; -typedef enum - { - RE_Found, - RE_NotFound, - RE_BadExpression, - } RExpStatus; + +/* Compile a regular expression for use. Returns NULL if the expression + cannot be compiled. +*/ +RE_Expression RECompile(const char *regexpr); + + +/* Search string for regexpr. Returns TRUE for match. +*/ +int RESearch(const RE_Expression re, const char *string); -/* Search string for regexpr +/* Free a regular expression */ -RExpStatus RExpSearch(const char *regexpr, const char *string); +void REFree(RE_Expression re); #endif -- cgit v1.2.3