bmf

bmf (Bayesian Mail Filter) 0.9.4 fork + patches
git clone git://git.codemadness.org/bmf
Log | Files | Refs | README | LICENSE

commit e805a804b42a190f0b06d8c495fd0f29011b1329
parent 4857ceba2cfedeafd8971a8e6e3db4ce2ea7f1b6
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Sat, 22 Sep 2018 17:57:54 +0200

changes

- remove -i option: reading from file.
- remove -f format option and db formats.
- initial pledge(2) support.
- remove bmfconv. only text "database" is supported.

Diffstat:
A.gitignore | 4++++
AMakefile | 45+++++++++++++++++++++++++++++++++++++++++++++
DMakefile.in | 81-------------------------------------------------------------------------------
Mbmf.1 | 13+------------
Mbmf.c | 37+++++++------------------------------
Dbmfconv.1 | 81-------------------------------------------------------------------------------
Dbmfconv.c | 169-------------------------------------------------------------------------------
Mconfig.h | 2++
Dconfigure | 354-------------------------------------------------------------------------------
Mdbdb.c | 614-------------------------------------------------------------------------------
Mdbdb.h | 48------------------------------------------------
Mdbh.c | 7-------
Mdbh.h | 4+---
Ddbmysql.c | 545-------------------------------------------------------------------------------
Ddbmysql.h | 60------------------------------------------------------------
15 files changed, 60 insertions(+), 2004 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.core +bmf +bmfconv diff --git a/Makefile b/Makefile @@ -0,0 +1,45 @@ +# Makefile for bmf + +BINDIR=/usr/bin +MANDIR=/usr/share/man + +VERSION=0.9.4 + +CFLAGS+=-DNDEBUG -D_UNIX -D_BSD=40 -Wall +LDFLAGS+= +SYSLIBS= + +all: bmf + +bmf: bmf.o filt.o dbdb.o dbtext.o dbh.o lex.o vec.o str.o dbg.o + $(CC) -o $@ bmf.o filt.o dbdb.o dbtext.o dbh.o lex.o vec.o str.o dbg.o $(LDFLAGS) $(SYSLIBS) + +bmf.o: bmf.c + $(CC) $(CFLAGS) -DPACKAGE=\"bmf\" -DVERSION=\"$(VERSION)\" -c $< + +install: checkroot bmf bmf.1 + [ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR) + [ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1 + cp bmf $(DESTDIR)$(BINDIR) + cp bmf.1 $(DESTDIR)$(MANDIR)/man1 + +uninstall: checkroot + rm -f $(DESTDIR)$(BINDIR)/bmf + rm -f $(DESTDIR)$(MANDIR)/man1/bmf.1 + +clean: + rm -f core *.o bmf + +distclean: clean + rm -f Makefile + +dist: tarball + +tarball: distclean + (cd ..; \ + cp -ar bmf bmf-$(VERSION); \ + tar czvf bmf-$(VERSION).tar.gz `find bmf-$(VERSION) -type f | egrep -v "CVS|debian"`; \ + rm -rf bmf-$(VERSION); \ + cd $(PWD)) + +checkroot: diff --git a/Makefile.in b/Makefile.in @@ -1,81 +0,0 @@ -# Makefile for bmf - -BINDIR=/usr/bin -MANDIR=/usr/share/man - -VERSION=0.9.4 - -CC=@CC@ -CFLAGS=@CFLAGS@ -LDFLAGS=@LDFLAGS@ -SYSLIBS=@SYSLIBS@ - -# For creating rpm packages -RPMROOT=/usr/src/rpm -RPM = rpm -RPMFLAGS = -ba -ARCH=`arch|sed 's/i[4-9]86/i386/'` - -all: bmf bmfconv - -bmf: bmf.o filt.o dbmysql.o dbdb.o dbtext.o dbh.o lex.o vec.o str.o dbg.o - $(CC) -o $@ bmf.o filt.o dbmysql.o dbdb.o dbtext.o dbh.o lex.o vec.o str.o dbg.o $(LDFLAGS) $(SYSLIBS) - -bmf.o: bmf.c - $(CC) $(CFLAGS) -DPACKAGE=\"bmf\" -DVERSION=\"$(VERSION)\" -c $< - -bmfconv: bmfconv.o dbmysql.o dbdb.o dbtext.o dbh.o vec.o str.o dbg.o - $(CC) -o $@ bmfconv.o dbmysql.o dbdb.o dbtext.o dbh.o vec.o str.o dbg.o $(LDFLAGS) $(SYSLIBS) - -bmfconv.o: bmfconv.c - $(CC) $(CFLAGS) -DPACKAGE=\"bmfconv\" -DVERSION=\"$(VERSION)\" -c $< - -install: checkroot bmf bmf.1 bmfconv bmfconv.1 - [ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR) - [ -d $(DESTDIR)$(MANDIR)/man1 ] || mkdir -p $(DESTDIR)$(MANDIR)/man1 - cp bmf $(DESTDIR)$(BINDIR) - cp bmf.1 $(DESTDIR)$(MANDIR)/man1 - cp bmfconv $(DESTDIR)$(BINDIR) - cp bmfconv.1 $(DESTDIR)$(MANDIR)/man1 - -uninstall: checkroot - rm -f $(DESTDIR)$(BINDIR)/bmf - rm -f $(DESTDIR)$(MANDIR)/man1/bmf.1 - rm -f $(DESTDIR)$(BINDIR)/bmfconv - rm -f $(DESTDIR)$(MANDIR)/man1/bmfconv.1 - -clean: - rm -f core *.o bmf bmfconv - -distclean: clean - rm -f Makefile - -dist: tarball rpmpkg debpkg - -tarball: distclean - (cd ..; \ - cp -ar bmf bmf-$(VERSION); \ - tar czvf bmf-$(VERSION).tar.gz `find bmf-$(VERSION) -type f | egrep -v "CVS|debian"`; \ - rm -rf bmf-$(VERSION); \ - cd $(PWD)) - -debpkg: checkroot - debian/rules binary - rm -rf debian/tmp - -rpmpkg: checkroot - (mkdir -p $(RPMROOT); \ - mkdir -p $(RPMROOT)/SOURCES; \ - mkdir -p $(RPMROOT)/SPECS; \ - mkdir -p $(RPMROOT)/RPMS; \ - mkdir -p $(RPMROOT)/SRPMS; \ - cp ../bmf-$(VERSION).tar.gz $(RPMROOT)/SOURCES; \ - cat bmf.spec.in | sed 's/VERSION/$(VERSION)/' > $(RPMROOT)/SPECS/bmf.spec; \ - cd $(RPMROOT)/SPECS; \ - $(RPM) $(RPMFLAGS) bmf.spec; \ - cp $(RPMROOT)/RPMS/$(ARCH)/bmf-$(VERSION)-*.rpm $(PWD)/..; \ - cp $(RPMROOT)/SRPMS/bmf-$(VERSION)-*.src.rpm $(PWD)/..; \ - cd $(PWD)) - -checkroot: - [ "`whoami`" = root ] || (echo Need root; exit 1) diff --git a/bmf.1 b/bmf.1 @@ -23,7 +23,7 @@ bmf \- efficient Bayesian mail filter .SH "SYNOPSIS" .nf -\fBbmf\fR [-t] [-n] [-s] [-N] [-S] [-f fmt] [-d db] [-i file] [-k n] [-m type] [-p] +\fBbmf\fR [-t] [-n] [-s] [-N] [-S] [-d db] [-k n] [-m type] [-p] [-v] [-V] [-h] .fi @@ -62,9 +62,6 @@ Without command-line options, bmf processes the input, registers it as either "g \fB-d db\fR Specify database or directory for loading and saving word lists. The default is \fI~/.bmf\fR in text mode. .PP -\fB-i file\fR Use file for input instead of stdin. - -.PP \fB-k n\fR Specify the number of extrema (keepers) to use in the Bayes calculation. The default is 15. .PP @@ -119,14 +116,6 @@ List of good tokens for text mode. \fI~/.bmf/spamlist.txt\fR List of bad tokens for text mode. -.TP -\fI~/.bmf/goodlist.db\fR -List of good tokens for libdb mode. - -.TP -\fI~/.bmf/spamlist.db\fR -List of bad tokens for libdb mode. - .SH "BUGS" .PP diff --git a/bmf.c b/bmf.c @@ -72,7 +72,7 @@ static void version( void ) int main( int argc, char** argv ) { int ch; - dbfmt_t dbfmt = db_db; + dbfmt_t dbfmt = db_text; char* dbname = NULL; bool_t rdonly; @@ -93,17 +93,14 @@ int main( int argc, char** argv ) int fd = STDIN_FILENO; char* infile = NULL; + if (pledge("stdio rpath wpath cpath tmppath", NULL) == -1) + err(1, "pledge"); + srand(time(NULL)); atexit( dump_alloc_heap ); -#ifdef HAVE_LIBDB - dbfmt = db_db; -#else - dbfmt = db_text; -#endif - stats.keepers = DEF_KEEPERS; - while( (ch = getopt( argc, argv, "NSVd:f:i:hk:m:npstv" )) != EOF ) + while( (ch = getopt( argc, argv, "NSVd:hk:m:npstv" )) != EOF ) { switch( ch ) { @@ -120,31 +117,9 @@ int main( int argc, char** argv ) free( dbname ); dbname = strdup( optarg ); break; - case 'f': - if( strcasecmp( optarg, "text" ) == 0 ) - { - dbfmt = db_text; - } - else if( strcasecmp( optarg, "db" ) == 0 ) - { - dbfmt = db_db; - } - else if( strcasecmp( optarg, "mysql" ) == 0 ) - { - dbfmt = db_mysql; - } - else - { - usage(); - } - break; case 'h': usage(); break; /* notreached */ - case 'i': - free( infile ); - infile = strdup( optarg ); - break; case 'k': stats.keepers = atoi( optarg ); break; @@ -173,6 +148,8 @@ int main( int argc, char** argv ) break; case 't': mode = mode_test; + if (pledge("stdio rpath", NULL) == -1) + err(1, "pledge"); break; case 'v': g_verbose++; diff --git a/bmfconv.1 b/bmfconv.1 @@ -1,81 +0,0 @@ -.\"Generated by db2man.xsl. Don't modify this, modify the source. -.de Sh \" Subsection -.br -.if t .Sp -.ne 5 -.PP -\fB\\$1\fR -.PP -.. -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Ip \" List item -.br -.ie \\n(.$>=3 .ne \\$3 -.el .ne 3 -.IP "\\$1" \\$2 -.. -.TH "BMFCONV" 1 "" "" "" -.SH NAME -bmfconv \- Database converter for bmf -.SH "SYNOPSIS" - -.nf -\fBbmfconv\fR [-f fmt] [-d db] [-e] [-i] [-v] [-h] -.fi - -.SH "DESCRIPTION" - -.PP -bmfconv converts bmf token databases between the supported formats. It can import flat text files into databases and export databases into flat text files. - -.PP -PLEASE NOTE that the text files used in import and export operations are read and written in the current directory. - -.SH "OPTIONS" - -.PP -\fB-f fmt\fR Specify database format. Supported formats are "db" for libdb and "mysql" for MySQL. - -.PP -\fB-d db\fR Specify database name. - -.PP -\fB-e\fR Export the database to text files. - -.PP -\fB-i\fR Import the database from text files. - -.PP -\fB-v\fR Display version information. - -.PP -\fB-h\fR Display usage information. - -.SH "RETURN VALUES" - -.PP -0 if conversion succeeds, nonzero if conversion fails. - -.SH "FILES" - -.TP -\fIgoodlist.txt\fR -Text file for import or export of good tokens. - -.TP -\fIspamlist.txt\fR -Text file for import or export of spam tokens. - -.SH "BUGS" - -.PP -Should be more robust. - -.SH "AUTHOR" - -.PP -Tom Marshall <tommy@tig-grr.com>. bmfconv is a part of the bmf package. - diff --git a/bmfconv.c b/bmfconv.c @@ -1,169 +0,0 @@ -/* $Id: bmfconv.c,v 1.9 2002/10/20 18:19:17 tommy Exp $ */ - -/* - * Copyright (c) 2002 Tom Marshall <tommy@tig-grr.com> - * - * This program is free software. It may be distributed under the terms - * in the file LICENSE, found in the top level of the distribution. - * - * bmfconv.c: bmf database converter - */ - -#include "config.h" -#include "dbg.h" -#include "str.h" -#include "vec.h" -#include "dbh.h" - -typedef enum -{ - none, - db2text, - text2db -} dir_t; - -static void usage( void ) -{ - printf( "\n" - "Usage: " PACKAGE " [options]\n" - "\t-f fmt\tSpecify database format (db|mysql).\n" - "\t-d db\tSpecify database or directory name.\n" - "\t-e\tExport to text files goodlist.txt and spamlist.txt.\n" - "\t-i\tImport from text files goodlist.txt and spamlist.txt.\n" - "\t-v\tShow version information and exit\n" - "\t-h\tShow this message and exit\n" - "\n" ); - exit( 2 ); -} - -static void version( void ) -{ - printf( "\n" - PACKAGE " version " VERSION " - a Bayesian mail filter\n" - "Copyright (c) 2002 Tom Marshall\n" - "\n" - PACKAGE " comes with ABSOLUTELY NO WARRANTY.\n" - "This is free software. You are welcome to redistribute it under the terms\n" - "of the GNU General Public License. See the file LICENSE in the source\n" - "distribution, or visit http://www.gnu.org/licenses/gpl.html\n" - "\n" ); - exit( 2 ); -} - -int main( int argc, char** argv ) -{ - int ch; - dbfmt_t dbfmt = db_db; - char* dbname = NULL; - bool_t rdonly; - - dbh_t* pdb; - dbt_t* ptable; - dir_t dir = none; - - while( (ch = getopt( argc, argv, "d:ef:ihv" )) != EOF ) - { - switch( ch ) - { - case 'd': - free( dbname ); - dbname = strdup( optarg ); - break; - case 'e': - dir = db2text; - break; - case 'f': - if( strcasecmp( optarg, "db" ) == 0 ) - { - dbfmt = db_db; - } - else if( strcasecmp( optarg, "mysql" ) == 0 ) - { - dbfmt = db_mysql; - } - else - { - usage(); - } - break; - case 'h': - usage(); - break; /* notreached */ - case 'i': - dir = text2db; - break; - case 'v': - version(); - break; /* notreached */ - default: - usage(); - } - } - if( dir == none ) - { - usage(); - } - - pdb = dbh_open( dbfmt, "localhost", dbname, DB_USER, DB_PASS ); - if( pdb == NULL ) - { - fprintf( stderr, "cannot open database\n" ); - exit( 1 ); - } - rdonly = (dir == db2text ? true : false); - - ptable = pdb->opentable( pdb, "spamlist", rdonly ); - if( ptable == NULL ) - { - fprintf( stderr, "cannot open spamlist\n" ); - exit( 1 ); - } - if( dir == db2text ) - { - if( !ptable->export( ptable, "spamlist.txt" ) ) - { - fprintf( stderr, "cannot export spamlist\n" ); - exit( 1 ); - } - } - else - { - if( !ptable->import( ptable, "spamlist.txt" ) ) - { - fprintf( stderr, "cannot import spamlist\n" ); - exit( 1 ); - } - } - ptable->close( ptable ); - free( ptable ); - - ptable = pdb->opentable( pdb, "goodlist", rdonly ); - if( ptable == NULL ) - { - fprintf( stderr, "cannot open goodlist\n" ); - exit( 1 ); - } - if( dir == db2text ) - { - if( !ptable->export( ptable, "goodlist.txt" ) ) - { - fprintf( stderr, "cannot export goodlist\n" ); - exit( 1 ); - } - } - else - { - if( !ptable->import( ptable, "goodlist.txt" ) ) - { - fprintf( stderr, "cannot import goodlist\n" ); - exit( 1 ); - } - } - ptable->close( ptable ); - free( ptable ); - - pdb->close( pdb ); - free( pdb ); - - return 0; -} diff --git a/config.h b/config.h @@ -10,6 +10,8 @@ #ifndef _CONFIG_H #define _CONFIG_H +#include <err.h> + /************************************** * Standard headers */ diff --git a/configure b/configure @@ -1,354 +0,0 @@ -#!/bin/sh - -echo "" - -# defaults -DEBUG=no -with_libdb=test -with_mysql=test - -# parse options -# --with/--without parsing copied from autoconf's output -while [ $# -gt 0 ]; do - case $1 in - --with-*) - ac_option=$1 - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^A-Za-z0-9_-]" >/dev/null && - { echo "error: invalid package name: $ac_package"; exit 1; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - case $ac_option in - *=*) - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - ;; - *) - ac_optarg=yes - ;; - esac - eval "with_$ac_package='$ac_optarg'" - ;; - --without-*) - ac_option=$1 - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - ac_package=`expr "x$ac_option" : 'x-*without-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^A-Za-z0-9_-]" >/dev/null && - { echo "error: invalid package name: $ac_package"; exit 1; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - eval "with_$ac_package=no" - ;; - --debug=yes|--debug|-d) - echo "Debug mode enabled." - with_debug=yes - ;; - --debug=no) - echo "Debug mode disabled." - with_debug=no - ;; - --help|-help|-h) - echo "usage: $0 [ options ]" - echo "available options:" - echo " --debug=yes (or -d) Enable debugging support." - echo " --debug=no Disable debugging support." - echo " --with-package Enable support for package in default location." - echo " --with-package=path Enable support for package installed in path." - echo " --without-package Disable support for package." - echo " --help (or -h) Show this message." - echo "" - echo "relevant packages:" - echo " libdb = BerkeleyDB" - echo " mysql = MySQL database" - exit 1 - ;; - *) - echo "Unknown option '$1', try -h for help" - exit 1 - ;; - esac - shift -done - -echo "Examining system setup..." - -# Some known configs: -# -# uname -s uname -r uname -m uname -p -# ======== =========== ======== ======== -# SunOS 5.6 sun4u sparc -# Linux 2.2.17 i686 unknown -# FreeBSD 4.1-RELEASE i386 i386 - -UNAME_S=`uname -s` -UNAME_R=`uname -r` - -case "$UNAME_S" in - Linux) - if [ "$with_debug" = "yes" ]; then - CCDBG="-g" - LDDBG="-g" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=gcc - CFLAGS="$CCDBG -D_UNIX -D_LINUX -Wall" - CXX=g++ - CXXFLAGS=${CFLAGS} - AR=ar - ARFLAGS="-rc" - LD=gcc - LDFLAGS="$LDDBG" - SYSLIBS="" - LIBDB_LIB="-ldb" - MYSQL_LIB="-lmysqlclient" - ;; - FreeBSD) - case "$UNAME_R" in - 2.*) - OSVER=20 - ;; - 3.*) - OSVER=30 - ;; - 4.*) - OSVER=40 - ;; - *) - # Assume 5.0 + - OSVER=50 - ;; - esac - if [ "$with_debug" = "yes" ]; then - CCDBG="-g" - LDDBG="-g" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=gcc - CFLAGS="$CCDBG -D_UNIX -D_BSD=$OSVER -Wall" - CXX=g++ - CXXFLAGS=${CFLAGS} - AR=ar - ARFLAGS="-rc" - LD=gcc - LDFLAGS="$LDDBG" - SYSLIBS="" - LIBDB_LIB="" - MYSQL_LIB="-lmysqlclient" - ;; - OpenBSD) - # I'm guessing OpenBSD looks mostly like FreeBSD 4.x - OSVER=40 - if [ "$with_debug" = "yes" ]; then - CCDBG="-g" - LDDBG="-g" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=gcc - CFLAGS="$CCDBG -D_UNIX -D_BSD=$OSVER -Wall" - CXX=g++ - CXXFLAGS=${CFLAGS} - AR=ar - ARFLAGS="-rc" - LD=gcc - LDFLAGS="$LDDBG" - SYSLIBS="" - LIBDB_LIB="" - MYSQL_LIB="-lmysqlclient" - ;; - Darwin) - # I'm guessing Darwin looks mostly like FreeBSD 4.x - OSVER=40 - if [ "$with_debug" = "yes" ]; then - CCDBG="-g" - LDDBG="-g" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=cc - CFLAGS="$CCDBG -D_UNIX -D_BSD=$OSVER -DNOLOCK -Wall" - CXX=c++ - CXXFLAGS=${CFLAGS} - AR=ar - ARFLAGS="-rc" - LD=cc - LDFLAGS="$LDDBG" - SYSLIBS="" - LIBDB_LIB="" - MYSQL_LIB="-lmysqlclient" - ;; - SunOS) - case "$UNAME_R" in - 5.6) - OSVER=56 - ;; - 5.7) - OSVER=57 - ;; - 5.8) - OSVER=58 - ;; - *) - # Assume 9.0+ - OSVER=59 - ;; - esac - # Prefer gcc to the native cc here because I haven't tested with the - # native compiler yet. - type gcc >/dev/null 2>&1 - if [ $? -eq 0 ]; then - if [ "$with_debug" = "yes" ]; then - CCDBG="-g" - LDDBG="-g" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=gcc - CFLAGS="$CCDBG -D_UNIX -D_SOLARIS=$OSVER -Wall" - CXX=g++ - CXXFLAGS=${CFLAGS} - LD=gcc - LDFLAGS="$LDDBG" - else - if [ "$with_debug" = "yes" ]; then - CCDBG="-g" - LDDBG="-g" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=cc - CFLAGS="-DNDEBUG -D_UNIX -D_SOLARIS=$OSVER" - CXX=c++ - CXXFLAGS=${CFLAGS} - LD=ld - LDFLAGS="" - fi - AR=ar - ARFLAGS="-rc" - SYSLIBS="" - LIBDB_LIB="-ldb" - MYSQL_LIB="-lmysqlclient" - ;; - OSF1) - if [ "$with_debug" = "yes" ]; then - CCDBG="-g2" - LDDBG="-g2" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=cc - CFLAGS="$CCDBG -D_UNIX -D_OSF" - CXX=cxx - CXXFLAGS="-noexceptions ${CFLAGS}" - AR=ar - ARFLAGS="-rc" - LD=ld - LDFLAGS="" - SYSLIBS="-lm" - LIBDB_LIB="-ldb" - MYSQL_LIB="-lmysqlclient" - ;; - *) - if [ "$with_debug" = "yes" ]; then - CCDBG="-g" - LDDBG="-g" - else - CCDBG="-DNDEBUG" - LDDBG="" - fi - CC=cc - CFLAGS="$CCDBG -DNDEBUG -D_UNIX" - CXX=c++ - CXXFLAGS=${CFLAGS} - AR=ar - ARFLAGS="-rc" - LD=ld - LDFLAGS="$LDDBG" - SYSLIBS="" - LIBDB_LIB="-ldb" - MYSQL_LIB="-lmysqlclient" - ;; -esac - -echo -n "Looking for compiler... " -type $CC >/dev/null 2>&1 -if [ $? -ne 0 ]; then - echo "compiler '$CC' not found!" - exit 1 -else - echo "$CC is executable." -fi - -echo -n "Checking for BerkeleyDB... " -if [ "$with_libdb" = "test" ]; then - if [ -e /usr/local/BerkeleyDB.4.1/include/db.h ]; then - with_libdb=/usr/local/BerkeleyDB.4.1 - LIBDB_LIB="-ldb" - elif [ -e /usr/include/db.h -o \ - -e /usr/local/include/db.h ]; then - with_libdb=yes - else - with_libdb=no - fi -fi -if [ "$with_libdb" = "no" ]; then - echo "disabled." -else - if [ "$with_libdb" != "yes" ]; then - CFLAGS="$CFLAGS -I$with_libdb/include" - LDFLAGS="$LDFLAGS -L$with_libdb/lib" - fi - CFLAGS="$CFLAGS -DHAVE_LIBDB" - LDFLAGS="$LDFLAGS $LIBDB_LIB" - echo "enabled." -fi - -echo -n "Checking for MySQL... " -if [ "$with_mysql" = "test" ]; then - type mysql_config >/dev/null 2>&1 - if [ $? -eq 0 ]; then - with_mysql=yes - CFLAGS="$CFLAGS `mysql_config --cflags`" - LDFLAGS="$LDFLAGS `mysql_config --libs`" - # mysql_config will add -lmysqlclient, don't add it twice - MYSQL_LIB="" - else - with_mysql=no - fi -fi -if [ "$with_mysql" = "no" ]; then - echo "disabled." -else - if [ "$with_mysql" != "yes" ]; then - CFLAGS="$CFLAGS -I$with_mysql/include" - LDFLAGS="$LDFLAGS -L$with_mysql/lib" - fi - CFLAGS="$CFLAGS -DHAVE_MYSQL" - LDFLAGS="$LDFLAGS $MYSQL_LIB" - echo "enabled." -fi - -for D in .; do - cat $D/Makefile.in | sed "s%@CC@%${CC}%g - s%@CXX@%${CXX}%g - s%@AR@%${AR}%g - s%@LD@%${LD}%g - s%@CFLAGS@%${CFLAGS}%g - s%@CXXFLAGS@%${CXXFLAGS}%g - s%@ARFLAGS@%${ARFLAGS}%g - s%@LDFLAGS@%${LDFLAGS}%g - s%@SYSLIBS@%${SYSLIBS}%" > $D/Makefile || exit 1 -done - -echo "Configuration successful." -echo "Now run 'make all' and 'make install'." -echo "" diff --git a/dbdb.c b/dbdb.c @@ -18,625 +18,11 @@ #include "dbh.h" #include "dbdb.h" -#ifdef HAVE_LIBDB - -#define DBT_init( pdbt ) memset( pdbt, 0, sizeof(DBT) ) - -#if !defined(DB_VERSION_MAJOR) /* v1 */ -#define dbx_get(dbp,kp,vp) dbp->get( dbp, kp, vp, 0 ) -#define dbx_put(dbp,kp,vp) dbp->put( dbp, kp, vp, 0 ) -#define dbx_fd(dbp,fd) fd = dbp->fd( dbp ) -#else /* v2+ */ -#define dbx_get(dbp,kp,vp) dbp->get( dbp, NULL, kp, vp, 0 ) -#define dbx_put(dbp,kp,vp) dbp->put( dbp, NULL, kp, vp, 0 ) -#define dbx_fd(dbp,fd) dbp->fd( dbp, &fd ) -#endif /* DB_VERSION_MAJOR */ - -#if !defined(DB_VERSION_MAJOR) /* v1 */ -typedef DB DBC; /* no separate cursor type */ -#define dbx_createcursor(dbp,dbcp) ((dbcp = dbp) ? 0 : -1) -#define dbx_destroycursor(dbcp) (dbcp = NULL) -#define dbx_first(dbcp,kp,vp) dbcp->seq(dbcp,kp,vp,R_FIRST) -#define dbx_next(dbcp,kp,vp) dbcp->seq(dbcp,kp,vp,R_NEXT) -#define dbx_prev(dbcp,kp,vp) dbcp->seq(dbcp,kp,vp,R_PREV) -#define dbx_last(dbcp,kp,vp) dbcp->seq(dbcp,kp,vp,R_LAST) -#elif DB_VERSION_MAJOR == 2 -#define dbx_createcursor(dbp,dbcp) dbp->cursor(dbp,NULL,&csrp) -#define dbx_destroycursor(dbcp) dbcp->c_close(dbcp) -#define dbx_first(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_FIRST) -#define dbx_next(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_NEXT) -#define dbx_prev(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_PREV) -#define dbx_last(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_LAST) -#else /* v3+ */ -#define dbx_createcursor(dbp,dbcp) dbp->cursor(dbp,NULL,&csrp,0) -#define dbx_destroycursor(dbcp) dbcp->c_close(dbcp) -#define dbx_first(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_FIRST) -#define dbx_next(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_NEXT) -#define dbx_prev(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_PREV) -#define dbx_last(dbcp,kp,vp) dbcp->c_get(dbcp,kp,vp,DB_LAST) -#endif /* DB_VERSION_MAJOR */ - -static void char2DBT( DBT* pdbt, char* p ) -{ - pdbt->data = p; - pdbt->size = strlen(p); -} - -static void uint2DBT( DBT* pdbt, uint* p ) -{ - pdbt->data = p; - pdbt->size = sizeof(uint); -} - -static uint DBT2uint( DBT* pdbt ) -{ - uint n; - memcpy( &n, pdbt->data, sizeof(n) ); - return n; -} - -dbh_t* dbdb_db_open( cpchar dbhost, cpchar dbname, cpchar dbuser, cpchar dbpass ) -{ - dbhdb_t* pthis; - - uint dirlen; - cpchar phome; - struct stat st; - - pthis = (dbhdb_t*)malloc( sizeof(dbhdb_t) ); - if( pthis == NULL ) - { - goto bail; - } - pthis->close = dbdb_db_close; - pthis->opentable = dbdb_db_opentable; - if( dbname != NULL && *dbname != '\0' ) - { - dirlen = strlen( dbname ); - pthis->dir = strdup( dbname ); - if( pthis->dir[dirlen-1] == '/' ) - { - pthis->dir[dirlen-1] = '\0'; - } - } - else - { - phome = getenv( "HOME" ); - if( phome == NULL || *phome == '\0' ) - { - phome = "."; - } - pthis->dir = (char*)malloc( strlen(phome)+5+1 ); - if( pthis->dir == NULL ) - { - goto bail; - } - sprintf( pthis->dir, "%s/.bmf", phome ); - } - - /* ensure config directory exists */ - if( stat( pthis->dir, &st ) != 0 ) - { - if( errno == ENOENT ) - { - if( mkdir( pthis->dir, S_IRUSR|S_IWUSR|S_IXUSR ) != 0 ) - { - goto bail; - } - } - else - { - goto bail; - } - } - else - { - if( !S_ISDIR( st.st_mode ) ) - { - goto bail; - } - } - -#if !defined(DB_VERSION_MAJOR) || DB_VERSION_MAJOR < 3 - /* no initialization */ -#else /* DB_VERSION_MAJOR >= 3 */ - if( db_env_create( &pthis->envp, 0 ) != 0 ) - { - goto bail; - } - if( pthis->envp->open( pthis->envp, pthis->dir, DB_INIT_LOCK|DB_INIT_MPOOL|DB_CREATE, 0644 ) != 0 ) - { - goto bail; - } -#endif /* DB_VERSION_MAJOR */ - - return (dbh_t*)pthis; - -bail: - free( pthis ); - return NULL; -} - -bool_t dbdb_db_close( dbhdb_t* pthis ) -{ -#if !defined(DB_VERSION_MAJOR) || DB_VERSION_MAJOR < 3 - /* no cleanup */ -#else /* DB_VERSION_MAJOR >= 3 */ - pthis->envp->close( pthis->envp, 0 ); -#endif /* DB_VERSION_MAJOR */ - - free( pthis->dir ); - pthis->dir = NULL; - - return true; -} - -dbt_t* dbdb_db_opentable( dbhdb_t* pthis, cpchar table, bool_t rdonly ) -{ - dbtdb_t* ptable; - DB* dbp; - DBT key; - DBT val; - - char szpath[PATH_MAX]; - - ptable = (dbtdb_t*)malloc( sizeof(dbtdb_t) ); - if( ptable == NULL ) - { - return NULL; - } - ptable->close = dbdb_table_close; - ptable->mergeclose = dbdb_table_mergeclose; - ptable->unmergeclose = dbdb_table_unmergeclose; - ptable->import = dbdb_table_import; - ptable->export = dbdb_table_export; - ptable->getmsgcount = dbdb_table_getmsgcount; - ptable->getcount = dbdb_table_getcount; - ptable->dbp = NULL; - - sprintf( szpath, "%s/%s.db", pthis->dir, table ); -#if !defined(DB_VERSION_MAJOR) - if( (dbp = dbopen( szpath, O_CREAT|O_RDWR, 0644, DB_BTREE, NULL)) == NULL ) - { - goto bail; - } -#elif DB_VERSION_MAJOR == 2 - if( db_open( szpath, DB_BTREE, DB_CREATE, 0644, NULL, NULL, &dbp ) != 0 ) - { - goto bail; - } -#elif (DB_VERSION_MAJOR == 3) || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0) - ptable->envp = pthis->envp; - if( db_create( &dbp, NULL, 0 ) != 0 ) - { - goto bail; - } - if( dbp->open( dbp, szpath, NULL, DB_BTREE, DB_CREATE, 0644 ) != 0 ) - { - goto bail; - } -#else /* v4.1+ */ - ptable->envp = pthis->envp; - if( db_create( &dbp, NULL, 0 ) != 0 ) - { - goto bail; - } - if( dbp->open( dbp, NULL, szpath, NULL, DB_BTREE, DB_CREATE, 0644 ) != 0 ) - { - goto bail; - } -#endif /* DB_VERSION_MAJOR */ - ptable->dbp = dbp; - - DBT_init( &key ); - DBT_init( &val ); - ptable->nmsgs = 0; - char2DBT( &key, MSGCOUNT_KEY ); - if( dbx_get( dbp, &key, &val ) == 0 ) - { - ptable->nmsgs = DBT2uint( &val ); - } - - return (dbt_t*)ptable; - -bail: - free( ptable ); - return NULL; -} - -static bool_t dbdb_table_lock( dbtdb_t* pthis ) -{ -#ifndef NOLOCK - struct flock lock; - int fd; - - dbx_fd( pthis->dbp, fd ); - memset( &lock, 0, sizeof(lock) ); - lock.l_type = F_WRLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - if( fcntl( fd, F_SETLKW, &lock ) != 0 ) - { - return false; - } -#endif /* ndef NOLOCK */ - return true; -} - -static bool_t dbdb_table_unlock( dbtdb_t* pthis ) -{ -#ifndef NOLOCK - struct flock lock; - int fd; - - dbx_fd( pthis->dbp, fd ); - memset( &lock, 0, sizeof(lock) ); - lock.l_type = F_UNLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - if( fcntl( fd, F_SETLK, &lock ) != 0 ) - { - return false; - } -#endif /* ndef NOLOCK */ - return true; -} - -bool_t dbdb_table_close( dbtdb_t* pthis ) -{ - DB* dbp = pthis->dbp; - - if( dbp != NULL ) - { -#if !defined(DB_VERSION_MAJOR) /* v1 */ - dbp->close( dbp ); -#else /* v2+ */ - dbp->close( dbp, 0 ); -#endif /* DB_VERSION_MAJOR */ - pthis->dbp = NULL; - } - - return true; -} - -bool_t dbdb_table_mergeclose( dbtdb_t* pthis, vec_t* pmsg ) -{ - DB* dbp = pthis->dbp; - DBT key; - DBT val; - - char szword[MAXWORDLEN+1]; - uint count; - veciter_t msgiter; - str_t* pmsgstr; - - if( pthis->dbp == NULL ) - { - return false; - } - - if( !dbdb_table_lock( pthis ) ) - { - return false; - } - - pthis->nmsgs++; - - DBT_init( &key ); - DBT_init( &val ); - - char2DBT( &key, MSGCOUNT_KEY ); - uint2DBT( &val, &pthis->nmsgs ); - dbx_put( dbp, &key, &val ); - - vec_first( pmsg, &msgiter ); - pmsgstr = veciter_get( &msgiter ); - - while( pmsgstr != NULL ) - { - assert( pmsgstr->len <= MAXWORDLEN ); - strncpylwr( szword, pmsgstr->p, pmsgstr->len ); - szword[pmsgstr->len] = '\0'; - count = db_getnewcount( &msgiter ); - - char2DBT( &key, szword ); - if( dbx_get( dbp, &key, &val ) == 0 ) - { - count += DBT2uint( &val ); - } - char2DBT( &key, szword ); - uint2DBT( &val, &count ); - if( dbx_put( dbp, &key, &val ) != 0 ) - { - goto bail; - } - - veciter_next( &msgiter ); - pmsgstr = veciter_get( &msgiter ); - } - - veciter_destroy( &msgiter ); - dbdb_table_unlock( pthis ); - return dbdb_table_close( pthis ); - -bail: - return false; -} - -bool_t dbdb_table_unmergeclose( dbtdb_t* pthis, vec_t* pmsg ) -{ - DB* dbp = pthis->dbp; - DBT key; - DBT val; - - char szword[MAXWORDLEN+1]; - uint count; - veciter_t msgiter; - str_t* pmsgstr; - - if( pthis->dbp == NULL ) - { - return false; - } - - if( pthis->nmsgs > 0 ) - { - pthis->nmsgs--; - } - - if( !dbdb_table_lock( pthis ) ) - { - return false; - } - - DBT_init( &key ); - DBT_init( &val ); - - char2DBT( &key, MSGCOUNT_KEY ); - uint2DBT( &val, &pthis->nmsgs ); - dbx_put( dbp, &key, &val ); - - vec_first( pmsg, &msgiter ); - pmsgstr = veciter_get( &msgiter ); - - while( pmsgstr != NULL ) - { - assert( pmsgstr->len <= MAXWORDLEN ); - strncpylwr( szword, pmsgstr->p, pmsgstr->len ); - szword[pmsgstr->len] = '\0'; - count = db_getnewcount( &msgiter ); - - char2DBT( &key, szword ); - if( dbx_get( dbp, &key, &val ) == 0 ) - { - uint n = DBT2uint( &val ); - n = (n > count) ? (n - count) : 0; - char2DBT( &key, szword ); - uint2DBT( &val, &n ); - if( dbx_put( dbp, &key, &val ) != 0 ) - { - goto bail; - } - } - - veciter_next( &msgiter ); - pmsgstr = veciter_get( &msgiter ); - } - - veciter_destroy( &msgiter ); - dbdb_table_unlock( pthis ); - return dbdb_table_close( pthis ); - -bail: - return false; -} - -bool_t dbdb_table_import( dbtdb_t* pthis, cpchar filename ) -{ - DB* dbp = pthis->dbp; - int fd; - struct stat st; - char* pbuf; - char* pbegin; - char* pend; - rec_t r; - DBT key; - DBT val; - char szword[MAXWORDLEN+1]; - - if( pthis->dbp == NULL ) - { - return false; - } - if( (fd = open( filename, O_RDONLY, 0644 )) < 0 ) - { - return false; - } - if( fstat( fd, &st ) != 0 ) - { - goto bail; - } - if( st.st_size == 0 ) - { - goto bail; - } - pbuf = (char*)malloc( st.st_size ); - if( pbuf == NULL ) - { - goto bail; - } - if( read( fd, pbuf, st.st_size ) != st.st_size ) - { - goto bail; - } - - DBT_init( &key ); - DBT_init( &val ); - - if( sscanf( pbuf, BOGOFILTER_HEADER, &pthis->nmsgs ) != 1 ) - { - goto bail; - } - pbegin = pbuf; - while( *pbegin != '\n' ) pbegin++; - pbegin++; - - char2DBT( &key, MSGCOUNT_KEY ); - uint2DBT( &val, &pthis->nmsgs ); - if( dbx_put( dbp, &key, &val ) != 0 ) - { - goto bail; - } - - while( pbegin < pbuf + st.st_size ) - { - pend = pbegin; - r.w.p = pbegin; - r.w.len = 0; - r.n = 0; - - while( *pend != '\n' ) - { - if( pend >= pbuf + st.st_size ) - { - goto bail; - } - *pend = tolower(*pend); - if( *pend == ' ' ) - { - r.w.len = (pend-pbegin); - r.n = strtol( pend+1, NULL, 10 ); - } - pend++; - } - if( pend > pbegin && *pbegin != '#' && *pbegin != ';' ) - { - if( r.w.len == 0 || r.w.len > MAXWORDLEN ) - { - fprintf( stderr, "dbh_loadfile: bad file format\n" ); - goto bail; - } - strncpylwr( szword, r.w.p, r.w.len ); - szword[r.w.len] = '\0'; - char2DBT( &key, szword ); - uint2DBT( &val, &r.n ); - if( dbx_put( dbp, &key, &val ) != 0 ) - { - goto bail; - } - } - pbegin = pend+1; - } - - free( pbuf ); - close( fd ); - - return true; - -bail: - return false; -} - -bool_t dbdb_table_export( dbtdb_t* pthis, cpchar filename ) -{ - DB* dbp = pthis->dbp; - int fd; - char iobuf[IOBUFSIZE]; - char* p; - - DBC* csrp; - int rc; - DBT key; - DBT val; - - if( (fd = open( filename, O_CREAT|O_WRONLY|O_TRUNC, 0644 )) < 0 ) - { - goto bail; - } - if( dbx_createcursor( dbp, csrp ) != 0 ) - { - goto bail; - } - - DBT_init( &key ); - DBT_init( &val ); - - p = iobuf; - p += sprintf( p, BOGOFILTER_HEADER, pthis->nmsgs ); - - rc = dbx_first( csrp, &key, &val ); - while( rc == 0 ) - { - assert( key.data != NULL && key.size <= MAXWORDLEN ); - assert( val.data != NULL && val.size == sizeof(uint) ); - if( key.size != MSGCOUNT_KEY_LEN || - memcmp( key.data, MSGCOUNT_KEY, MSGCOUNT_KEY_LEN ) != 0 ) - { - memcpy( p, key.data, key.size ); p += key.size; - *p++ = ' '; - p += sprintf( p, "%u\n", DBT2uint(&val) ); - if( p+TEXTDB_MAXLINELEN > (iobuf+1) ) - { - write( fd, iobuf, p-iobuf ); - p = iobuf; - } - } - rc = dbx_next( csrp, &key, &val ); - } - dbx_destroycursor( csrp ); - if( p != iobuf ) - { - write( fd, iobuf, p-iobuf ); - } - close( fd ); - return true; - -bail: - return false; -} - -uint dbdb_table_getmsgcount( dbtdb_t* pthis ) -{ - return pthis->nmsgs; -} - -uint dbdb_table_getcount( dbtdb_t* pthis, str_t* pword ) -{ - DB* dbp = pthis->dbp; - DBT key; - DBT val; - - char szword[MAXWORDLEN+1]; - uint count = 0; - - assert( pword->len <= MAXWORDLEN ); - strncpylwr( szword, pword->p, pword->len ); - szword[pword->len] = '\0'; - count = 0; - - DBT_init( &key ); - DBT_init( &val ); - - char2DBT( &key, szword ); - if( dbx_get( dbp, &key, &val ) == 0 ) - { - count = DBT2uint( &val ); - } - - return count; -} - -#else /* def HAVE_LIBDB */ - dbh_t* dbdb_db_open( cpchar dbhost, cpchar dbname, cpchar dbuser, cpchar dbpass ) { return NULL; } -#endif /* def HAVE_LIBDB */ - #ifdef UNIT_TEST int main( int argc, char** argv ) { diff --git a/dbdb.h b/dbdb.h @@ -10,52 +10,4 @@ #ifndef _DBDB_H #define _DBDB_H -#ifdef HAVE_LIBDB - -#include <db.h> - -typedef struct _dbtdb dbtdb_t; -struct _dbtdb -{ - bool_t (*close)(dbtdb_t*); - bool_t (*mergeclose)(dbtdb_t*,vec_t*); - bool_t (*unmergeclose)(dbtdb_t*,vec_t*); - bool_t (*import)(dbtdb_t*,cpchar); - bool_t (*export)(dbtdb_t*,cpchar); - uint (*getmsgcount)(dbtdb_t*); - uint (*getcount)(dbtdb_t*,str_t*); - - DB* dbp; /* db handle */ -#if defined(DB_VERSION_MAJOR) && DB_VERSION_MAJOR >= 3 - DB_ENV* envp; /* we don't own this */ -#endif /* DB_VERSION_MAJOR */ - uint nmsgs; /* number of messages in table (cached) */ -}; - -typedef struct _dbhdb dbhdb_t; -struct _dbhdb -{ - bool_t (*close)(dbhdb_t*); - dbt_t* (*opentable)(dbhdb_t*,cpchar,bool_t); - - char* dir; /* directory for db files */ -#if defined(DB_VERSION_MAJOR) && DB_VERSION_MAJOR >= 3 - DB_ENV* envp; /* db environment */ -#endif /* DB_VERSION_MAJOR */ -}; - -dbh_t* dbdb_db_open( cpchar dbhost, cpchar dbname, cpchar dbuser, cpchar dbpass ); -bool_t dbdb_db_close( dbhdb_t* pthis ); -dbt_t* dbdb_db_opentable( dbhdb_t* pthis, cpchar table, bool_t rdonly ); - -bool_t dbdb_table_close( dbtdb_t* pthis ); -bool_t dbdb_table_mergeclose( dbtdb_t* pthis, vec_t* pmsg ); -bool_t dbdb_table_unmergeclose( dbtdb_t* pthis, vec_t* pmsg ); -bool_t dbdb_table_import( dbtdb_t* pthis, cpchar filename ); -bool_t dbdb_table_export( dbtdb_t* pthis, cpchar filename ); -uint dbdb_table_getmsgcount( dbtdb_t* pthis ); -uint dbdb_table_getcount( dbtdb_t* pthis, str_t* pword ); - -#endif /* def HAVE_LIBDB */ - #endif /* ndef _DBDB_H */ diff --git a/dbh.c b/dbh.c @@ -18,7 +18,6 @@ #include "dbh.h" #include "dbtext.h" #include "dbdb.h" -#include "dbmysql.h" /* * get count for new (incoming) word. there may be duplicate entries for the @@ -60,12 +59,6 @@ dbh_t* dbh_open( dbfmt_t dbfmt, cpchar dbhost, cpchar dbname, cpchar dbuser, cpc case db_text: pdb = (dbh_t*)dbtext_db_open( dbhost, dbname, dbuser, dbpass ); break; - case db_db: - pdb = (dbh_t*)dbdb_db_open( dbhost, dbname, dbuser, dbpass ); - break; - case db_mysql: - pdb = (dbh_t*) dbmysql_db_open( dbhost, dbname, dbuser, dbpass ); - break; default: assert(false); } diff --git a/dbh.h b/dbh.h @@ -13,9 +13,7 @@ /* database formats */ typedef enum { - db_text, /* flat text */ - db_db, /* libdb */ - db_mysql /* mysql */ + db_text /* flat text */ } dbfmt_t; /* record/field structure */ diff --git a/dbmysql.c b/dbmysql.c @@ -1,545 +0,0 @@ -/* $Id: dbmysql.c,v 1.9 2002/10/14 07:09:51 tommy Exp $ */ - -/* - * Copyright (c) 2002 Tom Marshall <tommy@tig-grr.com> - * - * This program is free software. It may be distributed under the terms - * in the file LICENSE, found in the top level of the distribution. - * - * dbmysql.c: mysql database handler - */ - -#include "config.h" -#include "dbg.h" -#include "str.h" -#include "lex.h" -#include "vec.h" - -#include "dbh.h" -#include "dbmysql.h" - -#ifdef HAVE_MYSQL - -#define MAXQUERY 256 - -static MYSQL* g_mysql = NULL; - -static void sql_escape( char* d, const char* s ) -{ - while( *s != '\0' ) - { - if( *s == '\'' ) - { - *d++ = '\''; - } - *d++ = tolower(*s++); - } -} - -dbh_t* dbmysql_db_open( cpchar dbhost, cpchar dbname, cpchar dbuser, cpchar dbpass ) -{ - dbhmysql_t* pthis; - - if( g_mysql == NULL ) - { - g_mysql = mysql_init( NULL ); - if( g_mysql == NULL ) - { - return NULL; - } - } - - pthis = (dbhmysql_t*)malloc( sizeof(dbhmysql_t) ); - if( pthis == NULL ) - { - perror( "malloc()" ); - goto bail; - } - pthis->close = dbmysql_db_close; - pthis->opentable = dbmysql_db_opentable; - - pthis->dbh = mysql_real_connect( g_mysql, dbhost, dbuser, dbpass, dbname, 0, NULL, 0 ); - if( pthis->dbh == NULL ) - { - goto bail; - } - - - return (dbh_t*)pthis; - -bail: - fprintf( stderr, "cannot open mysql database '%s': %s\n", dbname, mysql_error(g_mysql) ); - free( pthis ); - return NULL; -} - -bool_t dbmysql_db_close( dbhmysql_t* pthis ) -{ - if( pthis->dbh != NULL ) - { - mysql_close( pthis->dbh ); - pthis->dbh = NULL; - } - return true; -} - -dbt_t* dbmysql_db_opentable( dbhmysql_t* pthis, cpchar table, bool_t rdonly ) -{ - dbtmysql_t* ptable; - - char query[MAXQUERY]; - MYSQL_RES* res; - MYSQL_ROW row; - - ptable = (dbtmysql_t*)malloc( sizeof(dbtmysql_t) ); - if( ptable == NULL ) - { - return NULL; - } - ptable->close = dbmysql_table_close; - ptable->mergeclose = dbmysql_table_mergeclose; - ptable->unmergeclose = dbmysql_table_unmergeclose; - ptable->import = dbmysql_table_import; - ptable->export = dbmysql_table_export; - ptable->getmsgcount = dbmysql_table_getmsgcount; - ptable->getcount = dbmysql_table_getcount; - ptable->pdb = pthis; - ptable->table = strdup( table ); - ptable->nmsgs = 0; - - sprintf( query, "SELECT count FROM %s WHERE name='%s'", - table, MSGCOUNT_KEY ); - if( mysql_query( pthis->dbh, query ) != 0 ) - { - goto bail; - } - if( (res = mysql_store_result( pthis->dbh )) == NULL ) - { - goto bail; - } - while( (row = mysql_fetch_row( res )) ) - { - ptable->nmsgs = atoi( row[0] ); - } - - return (dbt_t*)ptable; - -bail: - free( ptable->table ); - free( ptable ); - return NULL; -} - -bool_t dbmysql_table_close( dbtmysql_t* pthis ) -{ - if( pthis->pdb != NULL ) - { - free( pthis->table ); - pthis->table = NULL; - pthis->pdb = NULL; - } - return true; -} - -bool_t dbmysql_table_mergeclose( dbtmysql_t* pthis, vec_t* pmsg ) -{ - char szword[MAXWORDLEN+1]; - char szsqlword[MAXWORDLEN*2+1]; - veciter_t msgiter; - str_t* pmsgstr; - - char query[MAXQUERY]; - uint count; - - if( pthis->pdb == NULL || pthis->pdb->dbh == NULL ) - { - assert( false ); - return false; - } - - pthis->nmsgs++; - - sprintf( query, "UPDATE %s SET count=%u WHERE name='%s'", - pthis->table, pthis->nmsgs, MSGCOUNT_KEY ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - sprintf( query, "INSERT INTO %s ( name, count ) VALUES ( '%s', %u )", - pthis->table, MSGCOUNT_KEY, pthis->nmsgs ); - mysql_query( pthis->pdb->dbh, query ); - } - - vec_first( pmsg, &msgiter ); - pmsgstr = veciter_get( &msgiter ); - - while( pmsgstr != NULL ) - { - assert( pmsgstr->len <= MAXWORDLEN ); - strncpylwr( szword, pmsgstr->p, pmsgstr->len ); - szword[pmsgstr->len] = '\0'; - sql_escape( szsqlword, szword ); - count = db_getnewcount( &msgiter ); - - sprintf( query, "UPDATE %s SET count=count+%u WHERE name='%s'", - pthis->table, count, szsqlword ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - sprintf( query, "INSERT INTO %s ( name, count ) VALUES ( '%s', %u )", - pthis->table, szsqlword, count ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - goto bail; - } - } - - veciter_next( &msgiter ); - pmsgstr = veciter_get( &msgiter ); - } - - veciter_destroy( &msgiter ); - return dbmysql_table_close( pthis ); - -bail: - return false; -} - -bool_t dbmysql_table_unmergeclose( dbtmysql_t* pthis, vec_t* pmsg ) -{ - char szword[MAXWORDLEN+1]; - char szsqlword[MAXWORDLEN*2+1]; - veciter_t msgiter; - str_t* pmsgstr; - - char query[MAXQUERY]; - uint count; - - if( pthis->pdb == NULL || pthis->pdb->dbh == NULL ) - { - assert( false ); - return false; - } - - if( pthis->nmsgs > 0 ) - { - pthis->nmsgs--; - } - - sprintf( query, "UPDATE %s SET count=%u WHERE name='%s'", - pthis->table, pthis->nmsgs, MSGCOUNT_KEY ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - sprintf( query, "INSERT INTO %s ( name, count ) VALUES ( '%s', %u )", - pthis->table, MSGCOUNT_KEY, pthis->nmsgs ); - mysql_query( pthis->pdb->dbh, query ); - } - - vec_first( pmsg, &msgiter ); - pmsgstr = veciter_get( &msgiter ); - - while( pmsgstr != NULL ) - { - assert( pmsgstr->len <= MAXWORDLEN ); - strncpylwr( szword, pmsgstr->p, pmsgstr->len ); - szword[pmsgstr->len] = '\0'; - sql_escape( szsqlword, szword ); - count = db_getnewcount( &msgiter ); - - sprintf( query, "UPDATE %s SET count=GREATEST(0,count-%u) WHERE name='%s'", - pthis->table, count, szsqlword ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - /* this should not happen, so write with count=0 */ - sprintf( query, "INSERT INTO %s ( name, count ) VALUES ( '%s', 0 )", - pthis->table, szsqlword ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - goto bail; - } - } - - veciter_next( &msgiter ); - pmsgstr = veciter_get( &msgiter ); - } - - veciter_destroy( &msgiter ); - return dbmysql_table_close( pthis ); - -bail: - return false; -} - -bool_t dbmysql_table_import( dbtmysql_t* pthis, cpchar filename ) -{ - int fd; - struct stat st; - char* pbuf; - char* pbegin; - char* pend; - rec_t r; - char szword[MAXWORDLEN+1]; - char szsqlword[MAXWORDLEN*2+1]; - char query[MAXQUERY]; - - if( pthis->pdb == NULL || pthis->pdb->dbh == NULL ) - { - return false; - } - if( (fd = open( filename, O_RDONLY, 0644 )) < 0 ) - { - return false; - } - if( fstat( fd, &st ) != 0 ) - { - goto bail; - } - if( st.st_size == 0 ) - { - goto bail; - } - pbuf = (char*)malloc( st.st_size ); - if( pbuf == NULL ) - { - goto bail; - } - if( read( fd, pbuf, st.st_size ) != st.st_size ) - { - goto bail; - } - - if( sscanf( pbuf, BOGOFILTER_HEADER, &pthis->nmsgs ) != 1 ) - { - goto bail; - } - pbegin = pbuf; - while( *pbegin != '\n' ) pbegin++; - pbegin++; - - sprintf( query, "INSERT INTO %s ( name, count ) VALUES ( '%s', %u )", - pthis->table, MSGCOUNT_KEY, pthis->nmsgs ); - mysql_query( pthis->pdb->dbh, query ); - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - goto bail; - } - - while( pbegin < pbuf + st.st_size ) - { - pend = pbegin; - r.w.p = pbegin; - r.w.len = 0; - r.n = 0; - - while( *pend != '\n' ) - { - if( pend >= pbuf + st.st_size ) - { - goto bail; - } - *pend = tolower(*pend); - if( *pend == ' ' ) - { - r.w.len = (pend-pbegin); - r.n = strtol( pend+1, NULL, 10 ); - } - pend++; - } - if( pend > pbegin && *pbegin != '#' && *pbegin != ';' ) - { - if( r.w.len == 0 || r.w.len > MAXWORDLEN ) - { - fprintf( stderr, "dbh_loadfile: bad file format\n" ); - goto bail; - } - strncpylwr( szword, r.w.p, r.w.len ); - szword[r.w.len] = '\0'; - sql_escape( szsqlword, szword ); - - sprintf( query, "INSERT INTO %s ( name, count ) VALUES ( '%s', %u )", - pthis->table, szsqlword, r.n ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - goto bail; - } - } - pbegin = pend+1; - } - - return true; - -bail: - return false; -} - -bool_t dbmysql_table_export( dbtmysql_t* pthis, cpchar filename ) -{ - int fd; - char iobuf[IOBUFSIZE]; - char* p; - - char query[MAXQUERY]; - MYSQL_RES* res; - MYSQL_ROW row; - - if( (fd = open( filename, O_CREAT|O_WRONLY|O_TRUNC, 0644 )) < 0 ) - { - return false; - } - - p += sprintf( p, BOGOFILTER_HEADER, pthis->nmsgs ); - - sprintf( query, "SELECT name, count FROM %s", - pthis->table ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( mysql_affected_rows( pthis->pdb->dbh ) == 0 ) - { - goto bail; - } - - while( (row = mysql_fetch_row( res )) ) - { - if( strcmp( row[0], MSGCOUNT_KEY ) == 0 ) - { - continue; - } - - p += sprintf( p, "%s %s\n", row[0], row[1] ); - if( p+TEXTDB_MAXLINELEN > (iobuf+1) ) - { - write( fd, iobuf, p-iobuf ); - p = iobuf; - } - } - if( p != iobuf ) - { - write( fd, iobuf, p-iobuf ); - } - close( fd ); - - return true; - -bail: - return false; -} - -uint dbmysql_table_getmsgcount( dbtmysql_t* pthis ) -{ - return pthis->nmsgs; -} - -uint dbmysql_table_getcount( dbtmysql_t* pthis, str_t* pword ) -{ - uint count = 0; - char szword[MAXWORDLEN+1]; - char szsqlword[MAXWORDLEN*2+1]; - - char query[MAXQUERY]; - MYSQL_RES* res; - MYSQL_ROW row; - - assert( pword->len <= MAXWORDLEN ); - strncpylwr( szword, pword->p, pword->len ); - szword[pword->len] = '\0'; - sql_escape( szsqlword, szword ); - sprintf( query, "SELECT count FROM %s WHERE name='%s'", - pthis->table, szsqlword ); - if( mysql_query( pthis->pdb->dbh, query ) != 0 ) - { - goto bail; - } - if( (res = mysql_store_result( pthis->pdb->dbh )) == NULL ) - { - goto bail; - } - while( (row = mysql_fetch_row( res )) ) - { - count = atoi( row[0] ); - } - -bail: - return count; -} - -#else /* def HAVE_MYSQL */ - -dbh_t* dbmysql_db_open( cpchar dbhost, cpchar dbname, cpchar dbuser, cpchar dbpass ) -{ - return NULL; -} - -#endif /* def HAVE_MYSQL */ - -#ifdef UNIT_TEST -int main( int argc, char** argv ) -{ - dbh_t* pdb; - veciter_t iter; - str_t* pstr; - uint n; - - if( argc != 2 ) - { - fprintf( stderr, "usage: %s <file>\n", argv[0] ); - return 1; - } - - for( n = 0; n < 100; n++ ) - { - pdb = dbh_open( "testlist", true ); - - vec_first( &db, &iter ); - while( (pstr = veciter_get( &iter )) != NULL ) - { - char buf[MAXWORDLEN+32]; - char* p; - if( pstr->len > 200 ) - { - fprintf( stderr, "str too long: %u chars\n", pstr->len ); - break; - } - p = buf; - strcpy( buf, "str: " ); - p += 6; - memcpy( p, pstr->p, pstr->len ); - p += pstr->len; - sprintf( p, " %u", pstr->count ); - puts( buf ); - - veciter_next( &iter ); - } - - dbh_close( &db ); - } - - return 0; -} -#endif /* def UNIT_TEST */ diff --git a/dbmysql.h b/dbmysql.h @@ -1,60 +0,0 @@ -/* $Id: dbmysql.h,v 1.4 2002/10/06 06:46:53 tommy Exp $ */ - -/* - * Copyright (c) 2002 Tom Marshall <tommy@tig-grr.com> - * - * This program is free software. It may be distributed under the terms - * in the file LICENSE, found in the top level of the distribution. - */ - -#ifndef _DBMYSQL_H -#define _DBMYSQL_H - -#ifdef HAVE_MYSQL - -#include "mysql.h" - -typedef struct _dbtmysql dbtmysql_t; -struct _dbtmysql -{ - bool_t (*close)(dbtmysql_t*); - bool_t (*mergeclose)(dbtmysql_t*,vec_t*); - bool_t (*unmergeclose)(dbtmysql_t*,vec_t*); - bool_t (*import)(dbtmysql_t*,cpchar); - bool_t (*export)(dbtmysql_t*,cpchar); - uint (*getmsgcount)(dbtmysql_t*); - uint (*getcount)(dbtmysql_t*,str_t*); - - struct _dbhmysql* pdb; - char* table; /* table name */ - uint nmsgs; /* number of messages in table (cached) */ -}; - -typedef struct _dbhmysql dbhmysql_t; -struct _dbhmysql -{ - bool_t (*close)(dbhmysql_t*); - dbt_t* (*opentable)(dbhmysql_t*,cpchar,bool_t); - - MYSQL* dbh; /* database handle, if currently open */ -}; - -dbh_t* dbmysql_db_open( cpchar dbhost, cpchar dbname, cpchar dbuser, cpchar dbpass ); -bool_t dbmysql_db_close( dbhmysql_t* pthis ); -dbt_t* dbmysql_db_opentable( dbhmysql_t* pthis, cpchar table, bool_t rdonly ); - -bool_t dbmysql_table_close( dbtmysql_t* pthis ); -bool_t dbmysql_table_mergeclose( dbtmysql_t* pthis, vec_t* pmsg ); -bool_t dbmysql_table_unmergeclose( dbtmysql_t* pthis, vec_t* pmsg ); -bool_t dbmysql_table_import( dbtmysql_t* pthis, cpchar filename ); -bool_t dbmysql_table_export( dbtmysql_t* pthis, cpchar filename ); -uint dbmysql_table_getmsgcount( dbtmysql_t* pthis ); -uint dbmysql_table_getcount( dbtmysql_t* pthis, str_t* pword ); - -#else /* def HAVE_MYSQL */ - -dbh_t* dbmysql_db_open( cpchar dbhost, cpchar dbname, cpchar dbuser, cpchar dbpass ); - -#endif /* def HAVE_MYSQL */ - -#endif /* ndef _DBMYSQL_H */