summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2011-11-09 22:21:13 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2011-11-09 22:52:54 (GMT)
commit4926ea635ee23341615c351db3e4949553ca4dfb (patch) (side-by-side diff)
treea1a8c4aede69cf55b5e27fa1dc1630aeeda70329
parent7e4d54bd39368b36e8451d52975052c00e745f7a (diff)
downloadmailfromd-4926ea635ee23341615c351db3e4949553ca4dfb.tar.gz
mailfromd-4926ea635ee23341615c351db3e4949553ca4dfb.tar.bz2
Switch to libmu_dbm for DBM support.
* configure.ac (DEFAULT_DB_TYPE): New variable. Use mu info to determine which DBM is supported. * lib/Makefile.am (noinst_LIBRARIES): Remove libdbm.a * lib/mf-dbm.c: remove. * lib/mf-dbm.h: remove. * lib/cache.c: Use libmu_dbm functions. * lib/db.c: Likewise. * lib/dbcfg.c: Likewise. * lib/greylist.c: Likewise. * lib/rate.c: Likewise. * lib/tbf_rate.c: Likewise. * src/builtin/db.bi: Likewise. * src/savsrv.c: Likewise. * src/srvcfg.c (srv_cfg_param) <database-type>: New statement. * lib/libmf.h (config_cb_ignore): New proto. * lib/mfdb.h (db_item_printer_t): Change signature. * lib/utils.c (config_cb_ignore): New function. * po/POTFILES.in: Update. * src/Makefile.am (mailfromd_LDADD) (calloutd_LDADD): Remove libdbm.a. * src/calloutd.c: Update. * src/main.c (mf_cfg_param): lock-retry-count and lock-retry-timeout are no-op now. * src/mfdbtool.c: Likewise.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac199
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/cache.c106
-rw-r--r--lib/db.c294
-rw-r--r--lib/dbcfg.c15
-rw-r--r--lib/greylist.c12
-rw-r--r--lib/libmf.h1
-rw-r--r--lib/mf-dbm.c658
-rw-r--r--lib/mf-dbm.h75
-rw-r--r--lib/mfdb.h9
-rw-r--r--lib/rate.c67
-rw-r--r--lib/tbf_rate.c60
-rw-r--r--lib/utils.c9
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/Makefile.am3
-rw-r--r--src/builtin/db.bi410
-rw-r--r--src/calloutd.c2
-rw-r--r--src/main.c52
-rw-r--r--src/mfdbtool.c76
-rw-r--r--src/savsrv.c1
-rw-r--r--src/srvcfg.c19
21 files changed, 670 insertions, 1403 deletions
diff --git a/configure.ac b/configure.ac
index 0e975fc..136e037 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,7 +108,7 @@ AH_BOTTOM([
])
# Check for GNU Mailutils
-AM_GNU_MAILUTILS([2.99.94], [all auth sieve cfg argp], [:])
+AM_GNU_MAILUTILS([2.99.94], [all auth dbm sieve cfg argp], [:])
AC_CHECK_TYPES([struct mu_argp_node_list],,,[#include <mailutils/libargp.h>])
### Check for Emacs site-lisp directory
@@ -145,194 +145,41 @@ if test $syslog_async = "yes"; then
AC_DEFINE([USE_SYSLOG_ASYNC], [1], [Define if syslog-async is being used])
fi
-# Check for DBM flavor
-AH_TEMPLATE(BDB2_CURSOR_LASTARG,
- [Last argument to the cursor member of Berkeley 2 DB structure])
-
-dnl The cursor member of DB structure used to take three arguments in older
-dnl implementations of Berkeley DB. Newer versions (>= 4.0) declare
-dnl it as taking four arguments.
-dnl This macro checks which of the variants we have.
-AC_DEFUN([MU_DB2_CURSOR],
- [AC_CACHE_CHECK([whether db->cursor takes 4 arguments],
- [mu_cv_bdb2_cursor_four_args],
- [AC_TRY_COMPILE([#include <db.h>],
- [
-DB *db;
-db->cursor(NULL, NULL, NULL, 0)
- ],
- [mu_cv_bdb2_cursor_four_args=yes],
- [mu_cv_bdb2_cursor_four_args=no])])
- if test $mu_cv_bdb2_cursor_four_args = yes; then
- AC_DEFINE(BDB2_CURSOR_LASTARG,[,0])
- else
- AC_DEFINE(BDB2_CURSOR_LASTARG,[])
- fi])
-
-AH_TEMPLATE([WITH_BDB],
- [Define to the major version of Berkeley DB library to use])
-
-use_dbm=no
-status_dbm=no
-
+AC_ARG_VAR([DEFAULT_DB_TYPE],[Set default database type])
+
AC_ARG_WITH([gdbm],
- AC_HELP_STRING([--with-gdbm],
- [use GNU DBM]),
+ AC_HELP_STRING([--with-gdbm],
+ [use GNU DBM by default]),
[
case "${withval}" in
- yes) use_dbm=GDBM ;;
- no) use_dbm=no ;;
+ yes) DEFAULT_DB_TYPE=gdbm;;
+ no) ;;
*) AC_MSG_ERROR(bad value ${withval} for --with-gdbm) ;;
esac])
-## Support --with-db2 for backward compatibility
-if test "${with_db2+set}" = set; then
- case "${with_db2}" in
- yes) use_dbm=BDB2 ;;
- no) use_dbm=no ;;
- *) AC_MSG_ERROR(bad value ${with_db2} for --with-db2) ;;
- esac
-fi
-
AC_ARG_WITH([berkeley-db],
- AC_HELP_STRING([--with-berkeley-db@<:@=version@:>@],
- [use Berkeley DB]),
+ AC_HELP_STRING([--with-berkeley-db],
+ [use Berkeley DB by default]),
[
case "${withval}" in
- yes) use_dbm=BDB ;;
- no) use_dbm=no ;;
- *) use_dbm=BDB="${withval}";;
+ no) ;;
+ *) DEFAULT_DB_TYPE=bdb;;
esac])
-## Set the variable status_dbm to $1 if:
-##
-## 1. Function $3 is defined in the library $2
-## 2. Header file db.h is available
-##
-## Then check if the major version, minor version and patchlevel of the
-## library matches those from the header. If so, define WITH_BDB
-## to the version (i.e. $1 with all dots removed). Otherwise, report
-## an error and stop.
-##
-check_bdb() {
- ver=`echo $1 | tr -d '.'`
- major=`expr $ver : '\(.\).*'`
- AC_CHECK_LIB($2, $3,
- [AC_CHECK_HEADERS(db.h)
- if test $ac_cv_header_db_h = yes; then
- LIBS="$LIBS -l$2"
- MU_DB2_CURSOR
- status_dbm=$1
- fi])
- if test $status_dbm = no; then
- :
- else
- AC_RUN_IFELSE(
- [AC_LANG_PROGRAM([#include "db.h"],
- [int v_major, v_minor, v_patch;
- db_version(&v_major, &v_minor, &v_patch);
- return !(DB_VERSION_MAJOR == $major
- && v_major == DB_VERSION_MAJOR
- && v_minor == DB_VERSION_MINOR
- && v_patch == DB_VERSION_PATCH);
- ])],
- [AC_DEFINE_UNQUOTED(WITH_BDB,$ver)],
- [status_dbm=no])
- fi
-}
-
-AC_SUBST(MU_COMMON_INCLUDES)
-
-## Check for the Berkeley DB library version $1, assuming Slackware-like
-## installation layout (header files in /usr/incude/db$vn and library named
-## libdb-$version.so, where $version is the library version and $vn is
-## $version with all dots removed.
-##
-check_slackware_bdb() {
- dir=db`echo $1|tr -d '.'`
- save_CPPFLAGS=$CPPFLAGS
- while test -n "$dir"
- do
- if test -d /usr/include/$dir; then
- CPPFLAGS="$CPPFLAGS -I/usr/include/$dir"
- break
- elif test -d /usr/local/include/$dir; then
- CPPFLAGS="$CPPFLAGS -I/usr/local/include/$dir"
- break
- fi
- dir=`expr "$dir" : '\(.*\)[[0-9]]$'`
- done
- check_bdb $1 db-$1 db_create
- CPPFLAGS=$save_CPPFLAGS
- if test $status_dbm = "$1"; then
- MU_COMMON_INCLUDES="$MU_COMMON_INCLUDES -I/usr/include/$dir"
- fi
-}
-
-try_dbm() {
- case "$1" in
- GDBM)
- AC_CHECK_LIB(gdbm, gdbm_open,
- [AC_CHECK_HEADERS(gdbm.h,
- AC_DEFINE(WITH_GDBM,1,
- [Enable use of GNU DBM library]))
- LIBS="$LIBS -lgdbm"
- POPAUTH='popauth$(EXEEXT)'
- status_dbm=GDBM]);;
-
- BDB2) check_bdb 2 db db_open
- test "$status_dbm" != "no" && status_dbm="Berkeley DB v. $status_dbm";;
-
- BDB) for version in 4 3 2
- do
- case $version in
- 4|3) func=db_create;;
- 2) func=db_open;;
- esac
- check_bdb $version db $func
- if test "$status_dbm" != no; then
- status_dbm="Berkeley DB v. $status_dbm"
- break;
- fi
- done;;
-
- BDB=*)
- name=`expr $1 : 'BDB=\(.*\)'`
- case $name in
- [[0-9]]*) check_slackware_bdb $name;;
- *) for version in 4 3 2
- do
- case $version in
- 4|3) func=db_create;;
- 2) func=db_open;;
- esac
- check_bdb $version $name $func
- if test "$status_dbm" != no; then
- break;
- fi
- done
- ;;
- esac
- test "$status_dbm" != "no" && status_dbm="Berkeley DB v. $status_dbm"
- ;;
- esac
-}
-
-if test $use_dbm = no; then
- # Try all possible DBM values
- for use_dbm in BDB GDBM
- do
- try_dbm $use_dbm
- if test "$status_dbm" != no; then
- break
- fi
- done
+AH_TEMPLATE([DEFAULT_DB_TYPE], [Define default database type])
+if test -n "$DEFAULT_DB_TYPE"; then
+ if mu info $DEFAULT_DB_TYPE >/dev/null; then
+ AC_MSG_ERROR([requested DBM type $DEFAULT_DB_TYPE not supported by Mailutils])
+ fi
else
- try_dbm $use_dbm
+ # Traditionally Mailfromd preferred Berkeley DB over GDBM
+ DEFAULT_DB_TYPE=`mu info bdb gdbm | head -n 1 | sed 's/WITH_//' | tr A-Z a-z`
fi
-
-if test "$status_dbm" = "no"; then
- AC_MSG_ERROR([Cannot find DBM library to link with.])
+if test -n "$DEFAULT_DB_TYPE"; then
+ AC_DEFINE_UNQUOTED([DEFAULT_DB_TYPE], "$DEFAULT_DB_TYPE")
+ status_dbm=$DEFAULT_DB_TYPE
+else
+ AC_DEFINE_UNQUOTED([DEFAULT_DB_TYPE], NULL)
fi
## Preprocessor
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d385453..4202594 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-noinst_LIBRARIES=libmf.a libdbm.a libmfdb.a
+noinst_LIBRARIES=libmf.a libmfdb.a
noinst_HEADERS = \
libmf.h\
@@ -55,8 +55,6 @@ libmf_a_SOURCES=\
libmf_a_LIBADD=$(LIBOBJS) $(BUILD_SYSLOG_ASYNC)
libmf_a_DEPENDENCIES=$(BUILD_SYSLOG_ASYNC)
-libdbm_a_SOURCES = mf-dbm.c mf-dbm.h
-
libmfdb_a_SOURCES = \
db.c\
dbcfg.c\
diff --git a/lib/cache.c b/lib/cache.c
index 0abd714..b15cbf9 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -22,15 +22,14 @@
#include <mailutils/mailutils.h>
#include "libmf.h"
#include "mfdb.h"
-#include "mf-dbm.h"
#include "filenames.h"
time_t negative_expire_interval;//FIXME
time_t tempfail_expire_interval = 37*60;/* FIXME: Equals to the sum of the
``hard'' timeouts */
-static void cache_print_item(const char *email, size_t size,
- const void *content, size_t contsize);
+static void cache_print_item(struct mu_dbm_datum const *key,
+ struct mu_dbm_datum const *val);
static int cache_expire_item(const void *content);
static struct db_format cache_format_struct = {
@@ -69,36 +68,33 @@ mf_status
cache_get(const char *email)
{
mf_status rc;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
+ int result;
int readonly = 0;
- int res;
-
+
if (!cache_format->enabled)
return mf_failure;
-
+
mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE5,
("getting cache info for %s", email));
- if (mf_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR, 0600,
- &readonly)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), cache_format->dbname,
- mf_dbm_strerror());
- return mf_failure;
+ db = mf_dbm_open(cache_format->dbname, MU_STREAM_RDWR, 0600);
+ if (!db) {
+ db = mf_dbm_open(cache_format->dbname, MU_STREAM_READ, 0600);
+ if (!db)
+ return mf_failure;
+ readonly = 1;
}
- if (readonly)
- mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE0,
- ("cannot lock %s: switching to read-only mode",
- cache_format->dbname));
memset (&key, 0, sizeof key);
memset (&contents, 0, sizeof contents);
- MF_DATUM_PTR (key) = (void*) email;
- MF_DATUM_SIZE (key) = strlen (email) + 1;
- if ((res = mf_dbm_fetch(&db, key, &contents)) == 0) {
+ key.mu_dptr = (void*) email;
+ key.mu_dsize = strlen (email) + 1;
+ if ((result = mu_dbm_fetch(db, &key, &contents)) == 0) {
char timebuf[80];
struct cache_result *res = (struct cache_result *)
- MF_DATUM_PTR(contents);
+ contents.mu_dptr;
time_t t = time(NULL);
mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE5,
("found status: %s (%d), time: %s",
@@ -112,34 +108,40 @@ cache_get(const char *email)
MU_DEBUG_TRACE5,
("removing expired entry for %s",
email));
- if (mf_dbm_delete(&db, key))
+ result = mu_dbm_delete(db, &key);
+ if (result)
mu_error(_("cannot remove record `%s' from `%s': %s"),
- email, db.name,
- mf_dbm_strerror());
+ email, cache_format->dbname,
+ result == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) :
+ mu_strerror(result));
+
}
rc = mf_failure;
} else {
rc = res->status;
}
} else {
- if (res != MU_ERR_NOENT)
+ if (result == MU_ERR_FAILURE)
mu_error(_("cannot fetch record `%s' from `%s': %s"),
- email, db.name, mf_dbm_strerror());
+ email, cache_format->dbname,
+ mu_dbm_strerror(db));
rc = mf_failure;
}
- mf_dbm_datum_free(&contents);
- mf_dbm_close(&db);
+ mu_dbm_datum_free(&contents);
+ mu_dbm_destroy(&db);
return rc;
}
void
cache_insert(const char *email, mf_status rc)
{
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
struct cache_result res;
char timebuf[80];
+ int result;
if (!cache_format->enabled)
return;
@@ -150,34 +152,34 @@ cache_insert(const char *email, mf_status rc)
("inserting cache info for %s. status=%s (%d), time=%s",
email, mf_status_str(rc), rc,
format_timestr(res.timestamp, timebuf, sizeof timebuf)));
- if (mf_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR,
- 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), cache_format->dbname,
- mf_dbm_strerror());
+ db = mf_dbm_open(cache_format->dbname, MU_STREAM_RDWR, 0600);
+ if (!db)
return;
- }
-
+
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(key) = (void*) email;
- MF_DATUM_SIZE(key) = strlen (email) + 1;
- MF_DATUM_PTR(contents) = (void*)&res;
- MF_DATUM_SIZE(contents) = sizeof(res);
- if (mf_dbm_insert(&db, key, contents, 1))
- mu_error(_("cannot insert datum `%s' into `%s': %s"),
- email, db.name, mf_dbm_strerror());
+ key.mu_dptr = (void*) email;
+ key.mu_dsize = strlen (email) + 1;
+ contents.mu_dptr = (void*)&res;
+ contents.mu_dsize = sizeof(res);
+ result = mu_dbm_store(db, &key, &contents, 1);
+ if (result)
+ mu_error(_("cannot store datum `%s' into `%s': %s"),
+ email, cache_format->dbname,
+ result == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) : mu_strerror(result));
- mf_dbm_close(&db);
+ mu_dbm_destroy(&db);
}
static void
-cache_print_item(const char *email, size_t size, const void *content,
- size_t contsize)
+cache_print_item(struct mu_dbm_datum const *key,
+ struct mu_dbm_datum const *val)
{
- const struct cache_result *res = content;
-
- size--; /* Size includes the trailing nul */
- printf("%*.*s", size, size, email);
+ const struct cache_result *res = (const struct cache_result *)
+ val->mu_dptr;
+ int size = key->mu_dsize - 1; /* Size includes the trailing nul */
+ printf("%*.*s", size, size, key->mu_dptr);
printf(" %10.10s ", mf_status_str(res->status));
format_time_str(stdout, res->timestamp);
putchar('\n');
diff --git a/lib/db.c b/lib/db.c
index ffcab16..944dc3d 100644
--- a/lib/db.c
+++ b/lib/db.c
@@ -28,7 +28,6 @@
#include "libmf.h"
#include "mfdb.h"
-#include "mf-dbm.h"
int ignore_failed_reads_option;//FIXME;
@@ -88,98 +87,141 @@ db_format_setup()
greylist_format = db_format_install(greylist_format);
}
+int
+mf_file_mode_to_safety_criteria(int mode)
+{
+ int fl = 0;
+
+ if (!(mode & 0002))
+ fl |= MU_FILE_SAFETY_WORLD_WRITABLE;
+ if (!(mode & 0004))
+ fl |= MU_FILE_SAFETY_WORLD_READABLE;
+ if (!(mode & 0020))
+ fl |= MU_FILE_SAFETY_GROUP_WRITABLE;
+ if (!(mode & 0040))
+ fl |= MU_FILE_SAFETY_GROUP_READABLE;
+ return fl;
+}
+
+mu_dbm_file_t
+mf_dbm_open(char *dbname, int access, int mode)
+{
+ mu_dbm_file_t db;
+ int rc;
+ int sflg = MU_FILE_SAFETY_LINKED_WRDIR |
+ MU_FILE_SAFETY_DIR_IWOTH;
+
+ rc = mu_dbm_create(dbname, &db);
+ if (rc) {
+ mu_error(_("unable to create database %s: %s"),
+ dbname, mu_strerror (rc));
+ return NULL;
+ }
+
+ mu_dbm_safety_set_flags (db,
+ sflg | mf_file_mode_to_safety_criteria(mode));
+ rc = mu_dbm_safety_check (db);
+ if (rc && rc != ENOENT) {
+ mu_error(_("%s fails safety check: %s"),
+ dbname, mu_strerror(rc));
+ mu_dbm_destroy(&db);
+ return NULL;
+ }
+
+ rc = mu_dbm_open(db, access, mode);
+ if (rc) {
+ mu_error(_("mu_dbm_open(%s) failed: %s (%s)"), dbname,
+ mu_strerror (rc), mu_strerror (errno));
+ return NULL;
+ }
+ return db;
+}
int
db_list_item(char *dbname, char *email, db_item_printer_t fun)
{
- MF_DBM_FILE db;
- MF_DBM_DATUM key, contents;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key, contents;
int rc = 1;
- int res;
-
- if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), dbname,
- mf_dbm_strerror());
+
+ db = mf_dbm_open(dbname, MU_STREAM_READ, 0600);
+ if (!db)
return 1;
- }
- memset (&contents, 0, sizeof contents);
+ memset(&contents, 0, sizeof contents);
memset(&key, 0, sizeof key);
- MF_DATUM_PTR(key) = email;
- MF_DATUM_SIZE(key) = strlen (email) + 1;
- if ((res = mf_dbm_fetch(&db, key, &contents)) == 0) {
- fun(MF_DATUM_PTR(key),
- MF_DATUM_SIZE(key),
- MF_DATUM_PTR(contents),
- MF_DATUM_SIZE(contents));
- rc = 0;
- } else if (res != MU_ERR_NOENT)
+ key.mu_dptr = email;
+ key.mu_dsize = strlen (email) + 1;
+ rc = mu_dbm_fetch(db, &key, &contents);
+ if (rc == 0) {
+ fun(&key, &contents);
+ } else if (rc != MU_ERR_NOENT) {
mu_error(_("cannot fetch record `%s' from `%s': %s"),
- email, db.name, mf_dbm_strerror());
-
- mf_dbm_close(&db);
+ email, dbname, mu_dbm_strerror(db));
+ rc = 0;
+ }
+ mu_dbm_destroy(&db);
return rc;
}
-typedef int (*db_enum_func)(MF_DBM_DATUM key, MF_DBM_DATUM cnt, void *data);
+typedef int (*db_enum_func)(struct mu_dbm_datum *key,
+ struct mu_dbm_datum *cnt, void *data);
int
-db_enumerate(MF_DBM_FILE *db, db_enum_func fun, void *data)
+db_enumerate(mu_dbm_file_t db, db_enum_func fun, void *data)
{
int rc = 0;
- int res;
- MF_DBM_DATUM key, prev, contents;
-
- for (res = mf_dbm_firstkey (db, &key); res == 0;
- prev = key,
- res = mf_dbm_nextkey (db, prev, &key),
- mf_dbm_datum_free(&prev)) {
- memset (&contents, 0, sizeof contents);
- if (mf_dbm_fetch (db, key, &contents) == 0) {
- int fr = fun(key, contents, data);
- mf_dbm_datum_free(&contents);
- if (fr) {
- mf_dbm_datum_free(&key);
+ int ret = 0;
+ struct mu_dbm_datum key, contents;
+ const char *name = "";
+
+ mu_dbm_get_name(db, &name);
+
+ memset(&key, 0, sizeof key);
+ memset(&contents, 0, sizeof contents);
+ for (rc = mu_dbm_firstkey(db, &key); rc == 0;
+ rc = mu_dbm_nextkey(db, &key)) {
+ int res = mu_dbm_fetch(db, &key, &contents);
+ if (res == 0) {
+ res = fun(&key, &contents, data);
+ if (res) {
+ mu_dbm_datum_free(&key);
break;
}
+ mu_dbm_datum_free(&contents);
} else {
mu_error(_("cannot fetch data `%*.*s' from `%s': %s"),
- MF_DATUM_SIZE(key), MF_DATUM_SIZE(key),
- (char*) MF_DATUM_PTR(key),
- db->name,
- mf_dbm_strerror());
- rc = 1;
+ key.mu_dsize, key.mu_dsize, key.mu_dptr,
+ name,
+ mu_dbm_strerror(db));
+ ret = 1;
}
}
- if (res != MU_ERR_NOENT) {
+ if (rc != MU_ERR_NOENT) {
mu_error(_("unexpected error scanning database %s: %s"),
- db->name, mf_dbm_strerror());
- rc = 1;
+ name, mu_dbm_strerror(db));
+ ret = 1;
}
- return rc;
+ return ret;
}
static int
-db_list_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data)
+db_list_func(struct mu_dbm_datum *key, struct mu_dbm_datum *contents,
+ void *data)
{
db_item_printer_t fun = data;
- fun(MF_DATUM_PTR(key), MF_DATUM_SIZE(key),
- MF_DATUM_PTR(contents), MF_DATUM_SIZE(contents));
+ fun(key, contents);
return 0;
}
int
db_list(char *dbname, db_item_printer_t fun)
{
- MF_DBM_FILE db;
-
- if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), dbname,
- mf_dbm_strerror());
+ mu_dbm_file_t db = mf_dbm_open(dbname, MU_STREAM_READ, 0600);
+ if (!db)
return 1;
- }
- db_enumerate(&db, db_list_func, fun);
- mf_dbm_close(&db);
+ db_enumerate(db, db_list_func, fun);
+ mu_dbm_destroy(&db);
return 1;
}
@@ -190,13 +232,14 @@ struct expire_data {
};
static int
-db_expire_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data)
+db_expire_func(struct mu_dbm_datum *key, struct mu_dbm_datum *contents,
+ void *data)
{
struct expire_data *dp = data;
- if (dp->fun(MF_DATUM_PTR(contents))) {
- size_t size = MF_DATUM_SIZE(key);
- obstack_grow(&dp->stk, &size, sizeof size);
- obstack_grow(&dp->stk, MF_DATUM_PTR(key), size);
+ if (dp->fun(contents)) {
+ obstack_grow(&dp->stk, &contents->mu_dsize,
+ sizeof contents->mu_dsize);
+ obstack_grow(&dp->stk, key->mu_dptr, key->mu_dsize);
dp->key_count++;
}
return 0;
@@ -205,26 +248,24 @@ db_expire_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data)
int
db_expire(char *dbname, db_expire_t fun)
{
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
struct expire_data ed;
size_t size;
char *base, *p;
size_t i;
int rc = 0;
-
- if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), dbname,
- mf_dbm_strerror());
+
+ db = mf_dbm_open(dbname, MU_STREAM_RDWR, 0600);
+ if (!db)
return 1;
- }
ed.fun = fun;
obstack_init(&ed.stk);
ed.key_count = 0;
mu_debug(debug_handle, MU_DEBUG_TRACE0,
("Expiring %s: mark phase", dbname));
- if (db_enumerate(&db, db_expire_func, &ed))
+ if (db_enumerate(db, db_expire_func, &ed))
rc = !ignore_failed_reads_option;
size = 0;
@@ -239,17 +280,19 @@ db_expire(char *dbname, db_expire_t fun)
("Expiring %s: sweep phase", dbname));
base = obstack_finish(&ed.stk);
+ memset(&key, 0, sizeof key);
for (i = 0, p = base; i < ed.key_count; i++) {
size = *(size_t*)p;
p += sizeof(size_t);
mu_debug(debug_handle, MU_DEBUG_TRACE5,
("Remove: %*.*s", size, size, p));
- MF_DATUM_PTR(key) = p;
- MF_DATUM_SIZE(key) = size;
- if (mf_dbm_delete(&db, key)) {
+ key.mu_dptr = p;
+ key.mu_dsize = size;
+ rc = mu_dbm_delete(db, &key);
+ if (rc && rc != MU_ERR_NOENT) {
mu_error (_("cannot remove record `%*.*s' from `%s': %s"),
- size, size, p, db.name, mf_dbm_strerror());
+ size, size, p, dbname, mu_dbm_strerror(db));
rc = 1;
}
p += size;
@@ -258,32 +301,29 @@ db_expire(char *dbname, db_expire_t fun)
mu_debug(debug_handle, MU_DEBUG_TRACE0,
("Finished expiring %s", dbname));
obstack_free(&ed.stk, NULL);
- mf_dbm_close(&db);
+ mu_dbm_destroy(&db);
return rc;
}
int
db_delete(char *dbname, char *id)
{
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
int rc;
- if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), dbname,
- mf_dbm_strerror());
+ db = mf_dbm_open(dbname, MU_STREAM_RDWR, 0600);
+ if (!db)
return 1;
- }
memset(&key, 0, sizeof key);
- MF_DATUM_PTR(key) = id;
- MF_DATUM_SIZE(key) = strlen (id) + 1;
- if (mf_dbm_delete(&db, key)) {
+ key.mu_dptr = id;
+ key.mu_dsize = strlen (id) + 1;
+ rc = mu_dbm_delete(db, &key);
+ if (rc) {
mu_error(_("cannot remove record `%s' from `%s': %s"), id,
- dbname, mf_dbm_strerror());
- rc = 1;
- } else
- rc = 0;
- mf_dbm_close(&db);
+ dbname, mu_dbm_strerror(db));
+ }
+ mu_dbm_destroy(&db);
return rc;
}
@@ -313,46 +353,54 @@ make_tmp_name(char *dbname)
struct compact_data {
int rc;
db_expire_t fun;
- MF_DBM_FILE ndb;
+ mu_dbm_file_t ndb;
};
static int
-db_compact_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data)
+db_compact_func(struct mu_dbm_datum *key, struct mu_dbm_datum *contents,
+ void *data)
{
struct compact_data *dp = data;
-
- if (!dp->fun || dp->fun(MF_DATUM_PTR(contents)) == 0) {
- if (((char*)MF_DATUM_PTR(key))[MF_DATUM_SIZE(key) - 1]) {
+ int rc;
+ const char *name;
+
+ mu_dbm_get_name(dp->ndb, &name);
+
+ if (!dp->fun || dp->fun(contents) == 0) {
+ if (((char*)key->mu_dptr)[key->mu_dsize - 1]) {
/* Old database format. Convert. */
- size_t size;
char *p;
- MF_DBM_DATUM newkey;
-
- size = MF_DATUM_SIZE(key);
- p = malloc(size+1);
- if (!MF_DATUM_PTR(newkey)) {
+ struct mu_dbm_datum newkey;
+
+ p = malloc(key->mu_dsize + 1);
+ if (!p) {
mu_error(_("not enough memory"));
return 1;
}
- memcpy(p, MF_DATUM_PTR(key), size);
- p[size] = 0;
-
+ memcpy(p, key->mu_dptr, key->mu_dsize);
+ p[key->mu_dsize] = 0;
+
memset(&newkey, 0, sizeof newkey);
- MF_DATUM_SIZE(newkey) = size+1;
- MF_DATUM_PTR(newkey) = p;
- if (mf_dbm_insert(&dp->ndb, newkey, contents, 1)) {
+ newkey.mu_dptr = p;
+ newkey.mu_dsize = key->mu_dsize + 1;
+ rc = mu_dbm_store(dp->ndb, &newkey, contents, 1);
+ if (rc) {
mu_error(_("cannot insert datum `%s' into `%s': %s"),
- p, dp->ndb.name,
- mf_dbm_strerror());
+ p, name,
+ rc == MU_ERR_FAILURE ?
+ mu_dbm_strerror(dp->ndb) :
+ mu_strerror(rc));
dp->rc = 1;
}
free(p);
- } else if (mf_dbm_insert(&dp->ndb, key, contents, 1)) {
+ } else if ((rc = mu_dbm_store(dp->ndb, key, contents, 1))) {
mu_error(_("cannot insert datum `%*.*s' into `%s': %s"),
- MF_DATUM_SIZE(key), MF_DATUM_SIZE(key),
- (char*) MF_DATUM_PTR(key),
- dp->ndb.name,
- mf_dbm_strerror());
+ key->mu_dsize, key->mu_dsize,
+ (char*) key->mu_dsize,
+ name,
+ rc == MU_ERR_FAILURE ?
+ mu_dbm_strerror(dp->ndb) :
+ mu_strerror(rc));
dp->rc = 1;
}
}
@@ -362,7 +410,7 @@ db_compact_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data)
int
db_compact(char *dbname, db_expire_t fun)
{
- MF_DBM_FILE odb;
+ mu_dbm_file_t odb;
char *tmpname;
struct compact_data dat;
@@ -371,24 +419,18 @@ db_compact(char *dbname, db_expire_t fun)
tmpname = make_tmp_name(dbname);
- if (mf_dbm_open(dbname, &odb, MU_STREAM_READ, 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), dbname,
- mf_dbm_strerror());
- return 1;
- }
+ odb = mf_dbm_open(dbname, MU_STREAM_READ, 0600);
dat.rc = 0;
dat.fun = fun;
- if (mf_dbm_open(tmpname, &dat.ndb, MU_STREAM_CREAT, 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), tmpname,
- mf_dbm_strerror());
+ dat.ndb = mf_dbm_open(tmpname, MU_STREAM_CREAT, 0600);
+ if (!dat.ndb)
return 1;
- }
- db_enumerate(&odb, db_compact_func, &dat);
+ db_enumerate(odb, db_compact_func, &dat);
- mf_dbm_close(&dat.ndb);
- mf_dbm_close(&odb);
+ mu_dbm_destroy(&dat.ndb);
+ mu_dbm_destroy(&odb);
if (dat.rc == 0) {
if (unlink(dbname)) {
diff --git a/lib/dbcfg.c b/lib/dbcfg.c
index 96700e6..39daee5 100644
--- a/lib/dbcfg.c
+++ b/lib/dbcfg.c
@@ -61,13 +61,13 @@ cb_db_negative_expire_interval(void *data, mu_config_value_t *arg)
{
struct db_format *fmt = data;
struct timeval tv;
- int rc = config_cb_timeout (&tv, arg);
+ int rc = config_cb_timeout(&tv, arg);
if (fmt == cache_format)
negative_expire_interval = tv.tv_sec;
else
- mu_error (_("negative-expire-interval is valid only "
- "for cache database"));
+ mu_error(_("negative-expire-interval is valid only "
+ "for cache database"));
return rc;
}
@@ -109,21 +109,20 @@ database_section_parser (enum mu_cfg_section_stage stage,
mu_cfg_tree_t *tree)
{
switch (stage) {
- case mu_cfg_section_start:
- {
+ case mu_cfg_section_start: {
struct db_format *fmt;
if (mu_cfg_assert_value_type(node->label, MU_CFG_STRING))
return 0;
fmt = db_format_lookup(node->label->v.string);
if (fmt == NULL) {
- mu_error (_("unknown database format: %s"),
- node->label->v.string);
+ mu_error(_("unknown database format: %s"),
+ node->label->v.string);
return 0;
}
*section_data = fmt;
}
- break;
+ break;
case mu_cfg_section_end:
break;
diff --git a/lib/greylist.c b/lib/greylist.c
index 708e21c..e0a1478 100644
--- a/lib/greylist.c
+++ b/lib/greylist.c
@@ -22,16 +22,16 @@
#include <mailutils/mailutils.h>
#include "libmf.h"
#include "mfdb.h"
-#include "mf-dbm.h"
#include "filenames.h"
static void
-greylist_print_item(const char *key, size_t size,
- const void *content, size_t contsize)
+greylist_print_item(struct mu_dbm_datum const *key,
+ struct mu_dbm_datum const *val)
{
- time_t timestamp = *(time_t*) content;
- size--; /* Size includes the trailing nul */
- printf("%*.*s ", size, size, key);
+ time_t timestamp = *(time_t*) val->mu_dptr;
+ int size = key->mu_dsize - 1; /* Size includes the trailing nul */
+
+ printf("%*.*s ", size, size, key->mu_dptr);
format_time_str(stdout, timestamp);
putchar('\n');
}
diff --git a/lib/libmf.h b/lib/libmf.h
index 55adb59..4d71483 100644
--- a/lib/libmf.h
+++ b/lib/libmf.h
@@ -130,6 +130,7 @@ char *config_array_to_string (mu_config_value_t *val);
int config_cb_timeout (struct timeval *pt, mu_config_value_t *val);
int config_cb_time_t(void *data, mu_config_value_t *arg);
+int config_cb_ignore(void *data, mu_config_value_t *val);
void mf_proctitle_init (int argc, char *argv[], char *env[]);
void mf_proctitle_format (const char *fmt, ...);
diff --git a/lib/mf-dbm.c b/lib/mf-dbm.c
deleted file mode 100644
index a42c96f..0000000
--- a/lib/mf-dbm.c
+++ b/dev/null
@@ -1,658 +0,0 @@
-/* This file is part of Mailfromd.
- Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
-
- 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 3, 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, see <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#include <errno.h>
-#include <mailutils/error.h>
-#include <mailutils/errno.h>
-#include <mf-dbm.h>
-#include "libmf.h"
-
-#ifndef MU_ERR_EXISTS
-# define MU_ERR_EXISTS EEXIST
-#endif
-
-size_t lock_retry_count_option = 3;
-time_t lock_retry_timeout_option = 1;
-static mu_debug_handle_t debug_handle;
-
-void
-libdbm_init()
-{
- debug_handle = mu_debug_register_category("dbm");
-}
-
-int
-mf_fcheck_perm(int fd, int mode)
-{
- struct stat st;
-
- if (fstat (fd, &st) == -1) {
- if (errno == ENOENT)
- return ENOENT;
- else
- return MU_ERR_FAILURE;
- }
- if ((st.st_mode & 0777) != mode)
- return errno = EACCES;
- return 0;
-}
-
-int
-mf_check_perm(const char *name, int mode)
-{
- struct stat st;
-
- if (mode == 0)
- return 0;
- if (stat(name, &st) == -1) {
- if (errno == ENOENT)
- return ENOENT;
- else
- return MU_ERR_FAILURE;
- }
- if ((st.st_mode & 0777) != mode)
- return errno = EACCES;
-
- return 0;
-}
-
-#if defined(WITH_GDBM)
-
-int
-mf_dbm_open(char *name, MF_DBM_FILE *db, int flags, int mode, int *ro)
-{
- int rc;
- int f;
- size_t i;
- GDBM_FILE gdbm;
-
- rc = mf_check_perm(name, mode);
- if (rc && rc != ENOENT)
- return MU_ERR_UNSAFE_PERMS;
-
- if (ro)
- *ro = 0;
-
- switch (flags) {
- case MU_STREAM_CREAT:
- f = GDBM_NEWDB;
- break;
-
- case MU_STREAM_READ:
- f = GDBM_READER;
- break;
-
- case MU_STREAM_RDWR:
- f = GDBM_WRCREAT;
- break;
-
- default:
- errno = EINVAL;
- return 1;
- }
-
- for (i = 0; i < lock_retry_count_option; i++) {
- gdbm = gdbm_open(name, 512, f, mode, NULL);
- if (gdbm || errno != EAGAIN)
- break;
- sleep(lock_retry_timeout_option);
- }
-
- if (!gdbm) {
- if (ro) {
- gdbm = gdbm_open(name, 512, GDBM_READER, mode, NULL);
- if (gdbm)
- *ro = 1;
- }
- }
-
- rc = (gdbm == NULL) ? MU_ERR_FAILURE : 0;
-
- if (rc == 0) {
- db->db = gdbm;
- db->name = strdup(name);
- }
-
- return rc;
-}
-
-int
-mf_dbm_close(MF_DBM_FILE *db)
-{
- gdbm_close(db->db);
- free(db->name);
- return 0;
-}
-
-int
-mf_dbm_fetch(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM *ret)
-{
- *ret = gdbm_fetch(db->db, key);
- if (ret->dptr == NULL)
- return MU_ERR_NOENT;
- return 0;
-}
-
-int
-mf_dbm_delete(MF_DBM_FILE *db, MF_DBM_DATUM key)
-{
- return gdbm_delete(db->db, key) ? MU_ERR_FAILURE : 0;
-}
-
-int
-mf_dbm_insert(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM contents, int replace)
-{
- switch (gdbm_store(db->db, key, contents,
- replace ? GDBM_REPLACE : GDBM_INSERT)) {
- case -1:
- return MU_ERR_FAILURE;
-
- case 0:
- return 0;
-
- case 1:
- return MU_ERR_EXISTS;
- }
- return MU_ERR_FAILURE;
-}
-
-int
-mf_dbm_firstkey(MF_DBM_FILE *db, MF_DBM_DATUM *pkey)
-{
- *pkey = gdbm_firstkey(db->db);
- return (pkey->dptr == NULL) ? MU_ERR_NOENT : 0;
-}
-
-int
-mf_dbm_nextkey(MF_DBM_FILE *db, MF_DBM_DATUM prevkey, MF_DBM_DATUM *pkey)
-{
- *pkey = gdbm_nextkey(db->db, prevkey);
- return (pkey->dptr == NULL) ? MU_ERR_NOENT : 0;
-}
-
-void
-mf_dbm_datum_free(MF_DBM_DATUM *datum)
-{
- void *ptr = MF_DATUM_PTR(*datum);
- if (ptr)
- free(ptr);
- MF_DATUM_PTR(*datum) = 0;
-}
-
-const char *
-mf_dbm_strerror()
-{
- if (errno == MU_ERR_UNSAFE_PERMS)
- return mu_strerror(errno);
- return gdbm_strerror(gdbm_errno);
-}
-
-#elif defined(WITH_BDB)
-
-int mf_dbm_errno;
-
-static int
-try_lock(int fd, int type, struct flock *fl)
-{
- int i, rc;
-
- for (i = 0; i < lock_retry_count_option; i++) {
- alarm(lock_retry_timeout_option);
- rc = fcntl(fd, F_SETLKW, fl);
- alarm(0);
- if (rc == 0)
- return 0;
- }
- return errno;
-}
-
-static int
-lock_file(const char *name, int fd, int type)
-{
- int rc = 0;
- struct flock fl;
-
- if (type == F_UNLCK)
- mu_debug(debug_handle, MU_DEBUG_TRACE1,
- ("unlocking %s", name));
- else
- mu_debug(debug_handle, MU_DEBUG_TRACE1,
- ("locking %s for %s",
- name,
- (type == F_RDLCK) ? "reading" : "writing"));
-
- memset(&fl, 0, sizeof fl);
- fl.l_whence = SEEK_SET;
- fl.l_type = type;
-
- rc = try_lock(fd, type, &fl);
- if (!rc)
- return 0;
-
- fl.l_pid = 0;
- if (fcntl(fd, F_GETLK, &fl) != -1) {
- if (fl.l_type == F_UNLCK) {
- memset (&fl, 0, sizeof fl);
- fl.l_whence = SEEK_SET;
- fl.l_type = type;
- rc = try_lock (fd, type, &fl);
- if (rc)
- mu_error(_("%s: cannot acquire lock: %s"),
- name, mu_strerror (rc));
- } else if (fl.l_pid) {
- if (kill(fl.l_pid, 0) == 0)
- mu_error(_("%s is locked (%d) "
- "by process ID %lu"),
- name,
- fl.l_type,
- (unsigned long) fl.l_pid);
- else if (errno == ESRCH) {
- mu_error (_("%s is locked by "
- "nonexisting process "
- "ID %lu; "
- "retrying"),
- name,
- (unsigned long) fl.l_pid);
- if (unlink(name))
- mu_error (_("cannot unlink "
- "file %s: %s"),
- name,
- mu_strerror(errno));
- else {
- rc = try_lock(fd, type, &fl);
- if (rc)
- mu_error (_("%s: cannot acquire lock: %s"),
- name,
- mu_strerror(rc));
- }
- } else
- mu_error (_("%s seems locked "
- "by process ID %lu, "
- "but its validity cannot "
- "be verified: %s"),
- name,
- (unsigned long) fl.l_pid,
- mu_strerror(errno));
- } else
- mu_error (_("%s: cannot acquire lock: %s"),
- name, mu_strerror(rc));
- } else
- mu_error (_("cannot obtain locker info for %s: %s"),
- name, mu_strerror (errno));
- return rc;
-}
-
-#ifndef DB_FCNTL_LOCKING
-#define LOCK_SUFFIX ".lock"
-
-static int
-make_lockfile(char *name, int lktype, int *pfd, char **plockname)
-{
- int rc;
- int fd;
- char *p, *lockname;
- size_t size, namesize;
-
- size = strlen(mailfromd_state_dir);
- if (strlen(name) > size
- && memcmp(name, mailfromd_state_dir, size) == 0
- && name[size] == '/')
- p = name + size + 1;
- else
- p = name;
-
- namesize = size + 1 + strlen(p) + sizeof LOCK_SUFFIX;
- lockname = malloc(namesize);
- if (!lockname)
- return errno;
- strcpy(lockname, mailfromd_state_dir);
- strcat(lockname, "/");
- strcat(lockname, p);
- strcat(lockname, LOCK_SUFFIX);
- for (p = lockname + size + 1; *p; p++)
- if (*p == '/')
- *p = '-';
-
- fd = open(lockname, O_CREAT|O_RDWR, 0600);
- if (fd == -1) {
- free(lockname);
- return errno;
- }
-
- rc = lock_file(lockname, fd, lktype);
- if (rc) {
- free(lockname);
- return rc;
- }
-
- *plockname = lockname;
- *pfd = fd;
- return 0;
-}
-#endif
-
-static void
-mf_dbm_errcall_fcn
-#if DB_VERSION_MAJOR == 3
- (const char *errpfx, char *msg)
-#elif DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 2
- (const char *errpfx, char *msg)
-#else
- (const DB_ENV *env, const char *errpfx, const char *msg)
-#endif
-{
- if (errpfx)
- mu_error("%s: %s: %s", errpfx, _("Berkeley DB error"), msg);
- else
- mu_error("%s: %s", _("Berkeley DB error"), msg);
-}
-
-#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
-# define DB_TXN_NULL NULL,
-#else
-# define DB_TXN_NULL
-#endif
-
-int
-mf_dbm_open(char *name, MF_DBM_FILE *dbm, int flags, int mode, int *ro)
-{
- int f = 0;
- DB *db = NULL;
- int oflags;
-# define LKTYPE(o) (((o) & O_RDWR) ? F_WRLCK : F_RDLCK)
-
- mu_debug(debug_handle, MU_DEBUG_TRACE2, ("opening database %s", name));
- mf_dbm_errno = mf_check_perm(name, mode);
-
- if (mf_dbm_errno && mf_dbm_errno != ENOENT)
- return EACCES;
-
- if (ro)
- *ro = 0;
-
- switch (flags) {
- case MU_STREAM_CREAT:
- f = DB_CREATE | DB_TRUNCATE;
- oflags = O_CREAT | O_TRUNC | O_RDWR;
- break;
-
- case MU_STREAM_READ:
- if (mf_dbm_errno == ENOENT)
- return MU_ERR_FAILURE;
- f = DB_RDONLY;
- oflags = O_RDONLY;
- break;
-
- case MU_STREAM_RDWR:
- f = DB_CREATE;
- oflags = O_CREAT | O_RDWR;
- if (mf_dbm_errno == ENOENT)
- f |= DB_TRUNCATE;
- break;
-
- default:
- mf_dbm_errno = EINVAL;
- return MU_ERR_FAILURE;
- }
-
- dbm->lockname = NULL;
-#ifdef DB_FCNTL_LOCKING
- f |= DB_FCNTL_LOCKING;
-
- dbm->lockfd = open(name, oflags, mode);
- if (dbm->lockfd == -1) {
- mf_dbm_errno = errno;
- return MU_ERR_FAILURE;
- }
- mf_dbm_errno = lock_file(name, dbm->lockfd, LKTYPE(oflags));
- if (mf_dbm_errno) {
- mu_error(_("cannot lock file %s: %s"),
- name, mu_strerror(mf_dbm_errno));
- close(dbm->lockfd);
- return MU_ERR_FAILURE;
- }
-#else
- mf_dbm_errno = make_lockfile(name, LKTYPE(oflags), &dbm->lockfd,
- &dbm->lockname);
- if (mf_dbm_errno) {
- mu_error(_("cannot lock file %s: %s"),
- name, mu_strerror(mf_dbm_errno));
- return MU_ERR_FAILURE;
- }
-#endif
-
-#if DB_VERSION_MAJOR == 2
- mf_dbm_errno = db_open(name, DB_HASH, f, mode, NULL, NULL, &db);
-#else
- mf_dbm_errno = db_create(&db, NULL, 0);
- if (mf_dbm_errno != 0 || db == NULL)
- return MU_ERR_FAILURE;
-# if DB_VERSION_MAJOR == 3
- mf_dbm_errno = db->open(db, name, NULL, DB_HASH, f, mode);
-# else
- mf_dbm_errno = db->open(db, DB_TXN_NULL name, NULL, DB_HASH, f, mode);
-# endif
-#endif
- if (mf_dbm_errno) {
- if (dbm->lockname) {
- unlink(dbm->lockname);
- free(dbm->lockname);
- }
- close(dbm->lockfd);
- return MU_ERR_FAILURE;
- }
-
- db->sync(db, 0);
-
-#if DB_VERSION_MAJOR > 2
- if (mu_debug_level_p(debug_handle, MU_DEBUG_TRACE0))
- db->set_errcall (db, mf_dbm_errcall_fcn);
-#endif
-
- dbm->name = strdup(name);
- dbm->db = db;
- dbm->dbc = NULL;
-
- return 0;
-}
-
-int
-mf_dbm_close(MF_DBM_FILE *db)
-{
- mu_debug(debug_handle, MU_DEBUG_TRACE2,
- ("closing database %s", db->name));
- if (db->dbc) {
- mf_dbm_errno = db->dbc->c_close(db->dbc);
- db->dbc = NULL;
- if (mf_dbm_errno)
- return MU_ERR_FAILURE;
- }
-
- db->db->sync(db->db, 0);
- mf_dbm_errno = db->db->close(db->db, 0);
- if (db->lockname) {
- mu_debug(debug_handle, MU_DEBUG_TRACE2,
- ("removing lock file %s", db->lockname));
- unlink(db->lockname);
- free(db->lockname);
- }
- close(db->lockfd);
-
- free(db->name);
- return (mf_dbm_errno == 0) ? 0 : MU_ERR_FAILURE;
-}
-
-int
-mf_dbm_fetch(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM *ret)
-{
- mf_dbm_errno = db->db->get(db->db, NULL, &key, ret, 0);
- switch (mf_dbm_errno) {
- case 0:
- return 0;
-
- case DB_NOTFOUND:
- return MU_ERR_NOENT;
-
- default:
- return MU_ERR_FAILURE;
- }
-}
-
-int
-mf_dbm_delete(MF_DBM_FILE *dbm, MF_DBM_DATUM key)
-{
- mf_dbm_errno = dbm->db->del(dbm->db, NULL, &key, 0);
- return mf_dbm_errno ? MU_ERR_FAILURE : 0;
-}
-
-int
-mf_dbm_insert(MF_DBM_FILE *dbm, MF_DBM_DATUM key, MF_DBM_DATUM contents, int replace)
-{
- int flags = replace ? 0 : DB_NOOVERWRITE;
- int rc = 0;
-
- mf_dbm_errno = dbm->db->put(dbm->db, NULL, &key, &contents, flags);
- switch (mf_dbm_errno) {
- case 0:
- break;
-
- case DB_KEYEXIST:
- rc = MU_ERR_EXISTS;
- break;
-
- default:
- rc = MU_ERR_FAILURE;
- }
- return rc;
-}
-
-int
-mf_dbm_firstkey(MF_DBM_FILE *db, MF_DBM_DATUM *pkey)
-{
- DBT data;
-
- memset(pkey, 0, sizeof *pkey);
- memset(&data, 0, sizeof data);
-
- if (!db->dbc) {
- mf_dbm_errno = db->db->cursor(db->db, NULL, &db->dbc
- BDB2_CURSOR_LASTARG);
- if (mf_dbm_errno)
- return MU_ERR_FAILURE;
- }
-
- mf_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_FIRST);
- switch (mf_dbm_errno) {
- case 0:
- return 0;
-
- case DB_NOTFOUND:
- return MU_ERR_NOENT;
-
- default:
- return MU_ERR_FAILURE;
- }
-}
-
-int
-mf_dbm_nextkey(MF_DBM_FILE *db, MF_DBM_DATUM prevkey /*unused*/,
- MF_DBM_DATUM *pkey)
-{
- DBT data;
-
- memset(pkey, 0, sizeof *pkey);
- memset(&data, 0, sizeof data);
-
- if (!db->dbc) {
- mf_dbm_errno = EINVAL;
- return MU_ERR_FAILURE;
- }
-
- mf_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_NEXT);
-
- switch (mf_dbm_errno) {
- case 0:
- return 0;
-
- case DB_NOTFOUND:
- return MU_ERR_NOENT;
-
- default:
- return MU_ERR_FAILURE;
- }
-}
-
-void
-mf_dbm_datum_free(MF_DBM_DATUM *datum)
-{
- /* empty */
-}
-
-const char *
-mf_dbm_strerror()
-{
-#if DB_VERSION_MAJOR == 2
- switch (mf_dbm_errno) {
- case DB_INCOMPLETE:
- return "Sync didn't finish";
-
- case DB_KEYEMPTY:
- return "The key/data pair was deleted or "
- "was never created by the user";
- break;
-
- case DB_KEYEXIST:
- return "The key/data pair already exists";
-
- case DB_LOCK_DEADLOCK:
- return "Locker killed to resolve deadlock";
-
- case DB_LOCK_NOTGRANTED:
- return "Lock unavailable, no-wait set";
-
- case DB_LOCK_NOTHELD:
- return "Lock not held by locker";
-
- case DB_NOTFOUND:
- return "Key/data pair not found (EOF)";
-
- default:
- return mu_strerror(mf_dbm_errno);
- }
-#else
- if (mf_dbm_errno < 0)
- return db_strerror(mf_dbm_errno);
- else
- return mu_strerror(mf_dbm_errno);
-#endif
-}
-
-#endif
diff --git a/lib/mf-dbm.h b/lib/mf-dbm.h
deleted file mode 100644
index 415e010..0000000
--- a/lib/mf-dbm.h
+++ b/dev/null
@@ -1,75 +0,0 @@
-/* This file is part of Mailfromd.
- Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
-
- 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 3, 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, see <http://www.gnu.org/licenses/>. */
-
-#include <mailutils/stream.h>
-
-typedef struct mf_dbm_file MF_DBM_FILE;
-
-#if defined(WITH_GDBM)
-
-#include <gdbm.h>
-#define USE_DBM
-struct mf_dbm_file {
- char *name;
- GDBM_FILE db;
-};
-typedef datum MF_DBM_DATUM;
-#define MF_DATUM_SIZE(d) (d).dsize
-#define MF_DATUM_PTR(d) (d).dptr
-
-#elif defined(WITH_BDB)
-
-#include <db.h>
-#define USE_DBM
-
-struct mf_dbm_file {
- char *name;
- int lockfd;
- char *lockname;
- DB *db;
- DBC *dbc;
-};
-
-typedef DBT MF_DBM_DATUM;
-#define MF_DATUM_SIZE(d) (d).size
-#define MF_DATUM_PTR(d) (d).data
-
-#endif
-
-#ifdef USE_DBM
-struct stat;
-int mf_dbm_stat(char *name, struct stat *sb);
-int mf_dbm_open(char *name, MF_DBM_FILE *db, int flags, int mode, int *ro);
-int mf_dbm_close(MF_DBM_FILE *db);
-int mf_dbm_fetch(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM *ret);
-int mf_dbm_insert(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM contents, int replace);
-int mf_dbm_delete(MF_DBM_FILE *db, MF_DBM_DATUM key);
-int mf_dbm_firstkey(MF_DBM_FILE *db, MF_DBM_DATUM *pkey);
-int mf_dbm_nextkey(MF_DBM_FILE *db, MF_DBM_DATUM key, MF_DBM_DATUM *pkey);
-void mf_dbm_datum_free(MF_DBM_DATUM *datum);
-const char *mf_dbm_strerror(void);
-#else
-# define mf_dbm_datum_free(datum)
-#endif
-
-int mf_fcheck_perm(int fd, int mode);
-int mf_check_perm(const char *name, int mode);
-
-void libdbm_init(void);
-
-extern size_t lock_retry_count_option;
-extern time_t lock_retry_timeout_option;
diff --git a/lib/mfdb.h b/lib/mfdb.h
index 9bb611b..926b4a5 100644
--- a/lib/mfdb.h
+++ b/lib/mfdb.h
@@ -15,8 +15,10 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-typedef void (*db_item_printer_t)(const char *key, size_t keysize,
- const void *content, size_t contsize);
+#include <mailutils/dbm.h>
+
+typedef void (*db_item_printer_t)(struct mu_dbm_datum const *,
+ struct mu_dbm_datum const *);
typedef int (*db_expire_t)(const void *content);
struct db_format {
@@ -39,6 +41,9 @@ struct db_format *rate_format;
struct db_format *tbf_rate_format;
struct db_format *greylist_format;
+mu_dbm_file_t mf_dbm_open(char *dbname, int access, int mode);
+int mf_file_mode_to_safety_criteria(int mode);
+
void db_format_setup(void);
void db_format_enumerate(dbfmt_enumerator_t fp, void *data);
diff --git a/lib/rate.c b/lib/rate.c
index a7a6c8d..0e5ebb2 100644
--- a/lib/rate.c
+++ b/lib/rate.c
@@ -22,14 +22,13 @@
#include <mailutils/mailutils.h>
#include "libmf.h"
#include "mfdb.h"
-#include "mf-dbm.h"
#include "filenames.h"
int predict_next_option;//FIXME
double predict_rate;//FIXME
-static void rate_print_item(const char *email, size_t size,
- const void *content, size_t contsize);
+static void rate_print_item(struct mu_dbm_datum const *key,
+ struct mu_dbm_datum const *val);
static int rate_expire_item(const void *content);
static struct db_format rate_format_struct = {
@@ -55,10 +54,9 @@ mf_status
get_rate(char *email, long *ret, unsigned long interval, size_t mincount,
size_t threshold)
{
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
- int local_contents = 0;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
struct rate_result *rp, rate;
long result;
time_t t;
@@ -67,20 +65,17 @@ get_rate(char *email, long *ret, unsigned long interval, size_t mincount,
mu_debug(rate_format->debug_handle, MU_DEBUG_TRACE5,
("getting rate info for %s", email));
- if (mf_dbm_open(rate_format->dbname, &db, MU_STREAM_RDWR,
- 0600, NULL)) {
- mu_error(_("mf_dbm_open(%s) failed: %s"), rate_format->dbname,
- mf_dbm_strerror());
+ db = mf_dbm_open(rate_format->dbname, MU_STREAM_RDWR, 0600);
+ if (!db)
return mf_failure;
- }
- memset (&key, 0, sizeof key);
- memset (&contents, 0, sizeof contents);
- MF_DATUM_PTR (key) = email;
- MF_DATUM_SIZE (key) = strlen (email) + 1;
+ memset(&key, 0, sizeof key);
+ memset(&contents, 0, sizeof contents);
+ key.mu_dptr = email;
+ key.mu_dsize = strlen (email) + 1;
t = time(NULL);
- if ((res = mf_dbm_fetch(&db, key, &contents)) == 0) {
- rp = (struct rate_result *) MF_DATUM_PTR(contents);
+ if ((res = mu_dbm_fetch(db, &key, &contents)) == 0) {
+ rp = (struct rate_result *) contents.mu_dptr;
mu_debug(rate_format->debug_handle, MU_DEBUG_TRACE5,
("found time: %lu, interval: %lu, count: %lu, "
"rate: %g",
@@ -91,13 +86,13 @@ get_rate(char *email, long *ret, unsigned long interval, size_t mincount,
} else {
if (res != MU_ERR_NOENT)
mu_error(_("cannot fetch `%s' from `%s': %s"),
- email, db.name, mf_dbm_strerror());
+ email, rate_format->dbname,
+ mu_dbm_strerror(db));
/* Initialize the structure */
rate.timestamp = t;
rate.interval = 0;
rate.count = 0;
rp = &rate;
- local_contents = 1;
}
/* Update the structure */
@@ -116,8 +111,10 @@ get_rate(char *email, long *ret, unsigned long interval, size_t mincount,
/* Update the db */
if (threshold && result > threshold)
mu_debug(rate_format->debug_handle, MU_DEBUG_TRACE5,
- ("not updating %s rates", email));
+ ("not updating %s rates", email));
else {
+ struct mu_dbm_datum dat;
+
if (obsolete
|| (rate_format->expire_interval
&& rp->interval > rate_format->expire_interval)) {
@@ -129,30 +126,34 @@ get_rate(char *email, long *ret, unsigned long interval, size_t mincount,
mu_debug(rate_format->debug_handle, MU_DEBUG_TRACE5,
("updating %s rates", email));
- MF_DATUM_PTR(contents) = (void*)rp;
- MF_DATUM_SIZE(contents) = sizeof(*rp);
- if (mf_dbm_insert(&db, key, contents, 1))
+ dat.mu_dptr = (void*)rp;
+ dat.mu_dsize = sizeof(*rp);
+ res = mu_dbm_store(db, &key, &dat, 1);
+ if (res)
mu_error (_("cannot insert datum `%s' into `%s': %s"),
- email, db.name, mf_dbm_strerror());
+ email, rate_format->dbname,
+ res == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) :
+ mu_strerror(res));
}
- if (!local_contents)
- mf_dbm_datum_free(&contents);
+ mu_dbm_datum_free(&contents);
- mf_dbm_close(&db);
+ mu_dbm_destroy(&db);
*ret = result;
return mf_success;
}
static void
-rate_print_item(const char *email, size_t size, const void *content,
- size_t contsize)
+rate_print_item(struct mu_dbm_datum const *key,
+ struct mu_dbm_datum const *val)
{
- const struct rate_result *res = content;
+ const struct rate_result *res = (const struct rate_result *)
+ val->mu_dptr;
double rate, exp_rate;
+ int size = key->mu_dsize - 1; /* Size includes the trailing nul */
- size--; /* compensate for trailing zero */
- printf("%*.*s ", size, size, email);
+ printf("%*.*s ", size, size, key->mu_dptr);
if (res->interval) {
rate = (double)res->count / res->interval;
exp_rate = (double)(res->count + 1) /
diff --git a/lib/tbf_rate.c b/lib/tbf_rate.c
index 0c24f20..5a71470 100644
--- a/lib/tbf_rate.c
+++ b/lib/tbf_rate.c
@@ -23,12 +23,11 @@
#include <mailutils/mailutils.h>
#include "libmf.h"
#include "mfdb.h"
-#include "mf-dbm.h"
#include "filenames.h"
#include "inttypes.h"
-static void tbf_rate_print_item(const char *email, size_t size,
- const void *content, size_t contsize);
+static void tbf_rate_print_item(struct mu_dbm_datum const *key,
+ struct mu_dbm_datum const *val);
static int tbf_rate_expire_item(const void *content);
static struct db_format tbf_rate_format_struct = {
@@ -80,9 +79,9 @@ mf_status
check_tbf_rate(char *email, int *ret,
size_t cost, size_t interval, size_t burst_size)
{
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
int local_contents = 0;
struct tbf_rate_result *rp, tbf_rate;
struct timeval tv;
@@ -106,34 +105,34 @@ check_tbf_rate(char *email, int *ret,
mu_debug(tbf_rate_format->debug_handle, MU_DEBUG_TRACE5,
("getting TBF rate info for %s", email));
- if (mf_dbm_open(tbf_rate_format->dbname, &db, MU_STREAM_RDWR,
- 0600, NULL)) {
+ db = mf_dbm_open(tbf_rate_format->dbname, MU_STREAM_RDWR, 0600);\
+ if (!db) {
mu_error(_("mf_dbm_open(%s) failed: %s"),
tbf_rate_format->dbname,
- mf_dbm_strerror());
+ mu_dbm_strerror(db));
return mf_failure;
}
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(key) = email;
- MF_DATUM_SIZE(key) = strlen(email) + 1;
+ key.mu_dptr = email;
+ key.mu_dsize = strlen(email) + 1;
gettimeofday(&tv,NULL);
now = (uint64_t)tv.tv_sec * USEC_PER_SEC + (uint64_t)tv.tv_usec;
- if ((res = mf_dbm_fetch(&db, key, &contents)) == 0) {
+ if ((res = mu_dbm_fetch(db, &key, &contents)) == 0) {
uint64_t elapsed;
uint64_t tokens;
-
- rp = (struct tbf_rate_result *) MF_DATUM_PTR(contents);
+
+ rp = (struct tbf_rate_result *) contents.mu_dptr;
/* calculate elapsed time and number of new tokens since
last add */;
elapsed = now - rp->timestamp;
tokens = elapsed / interval; /* partial tokens ignored */
/* timestamp set to time of most recent token */
rp->timestamp += tokens * interval;
-
+
/* add existing tokens to 64bit counter to prevent overflow
in range check */
tokens += rp->tokens;
@@ -149,7 +148,8 @@ check_tbf_rate(char *email, int *ret,
} else {
if (res != MU_ERR_NOENT)
mu_error(_("cannot fetch `%s' from `%s': %s"),
- email, db.name, mf_dbm_strerror());
+ email, tbf_rate_format->dbname,
+ mu_dbm_strerror(db));
/* Initialize the structure */
tbf_rate.timestamp = now;
tbf_rate.tokens = burst_size;
@@ -177,27 +177,31 @@ check_tbf_rate(char *email, int *ret,
rp->timestamp) / USEC_PER_SEC) + 1;
/* Update the db */
- MF_DATUM_PTR(contents) = (void*)rp;
- MF_DATUM_SIZE(contents) = sizeof(*rp);
- if (mf_dbm_insert(&db, key, contents, 1))
- mu_error (_("cannot insert datum `%s' into `%s': %s"),
- email, db.name, mf_dbm_strerror());
+ contents.mu_dptr = (void*)rp;
+ contents.mu_dsize = sizeof(*rp);
+ res = mu_dbm_store(db, &key, &contents, 1);
+ if (res)
+ mu_error (_("cannot store datum `%s' into `%s': %s"),
+ email, tbf_rate_format->dbname,
+ res == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) : mu_strerror(res));
if (!local_contents)
- mf_dbm_datum_free(&contents);
+ mu_dbm_datum_free(&contents);
- mf_dbm_close(&db);
+ mu_dbm_close(db);
return mf_success;
}
static void
-tbf_rate_print_item(const char *email, size_t size, const void *content,
- size_t contsize)
+tbf_rate_print_item(struct mu_dbm_datum const *key,
+ struct mu_dbm_datum const *val)
{
- const struct tbf_rate_result *res = content;
+ const struct tbf_rate_result *res = (const struct tbf_rate_result *)
+ val->mu_dptr;
+ int size = key->mu_dsize - 1; /* Size includes the trailing nul */
- size--; /* compensate for trailing zero */
- printf("%*.*s tok:%lu@", size, size, email,
+ printf("%*.*s tok:%lu@", size, size, key->mu_dptr,
(unsigned long) res->tokens);
format_time_str(stdout, (time_t) (res->timestamp / USEC_PER_SEC));
printf(" exp:");
diff --git a/lib/utils.c b/lib/utils.c
index a5a7c8a..d618a02 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -121,6 +121,15 @@ config_cb_time_t(void *data, mu_config_value_t *arg)
return rc;
}
+int
+config_cb_ignore(void *data, mu_config_value_t *val)
+{
+ mu_diag_output (MU_DIAG_WARNING,
+ _("this statement has no effect in %s"),
+ PACKAGE_STRING);
+ return 0;
+}
+
int
stderr_closed_p()
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ca56920..e51b196 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -37,7 +37,6 @@ lib/db.c
lib/dbcfg.c
lib/dns.c
lib/logger.c
-lib/mf-dbm.c
lib/optcache.c
lib/proctitle.c
lib/rate.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 4400f8d..af404ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -48,7 +48,6 @@ mailfromd_LDADD = \
builtin/libbuiltin.a\
../lib/libmfdb.a\
../lib/libmf.a\
- ../lib/libdbm.a\
../gnu/libgnu.a\
$(MAILUTILS_LIBS)\
$(MILTER)\
@@ -71,7 +70,6 @@ calloutd_LDADD = \
./libcallout.a\
../lib/libmfdb.a\
../lib/libmf.a\
- ../lib/libdbm.a\
../gnu/libgnu.a\
$(MAILUTILS_LIBS)\
$(MILTER)
@@ -82,7 +80,6 @@ mfdbtool_SOURCES = \
mfdbtool_LDADD = \
../lib/libmfdb.a\
../lib/libmf.a\
- ../lib/libdbm.a\
../gnu/libgnu.a\
$(MAILUTILS_LIBS)
diff --git a/src/builtin/db.bi b/src/builtin/db.bi
index a734dc1..90d926e 100644
--- a/src/builtin/db.bi
+++ b/src/builtin/db.bi
@@ -16,7 +16,6 @@
#define DEFAULT_DB_MODE 0640
#include <fnmatch.h>
-#include "mf-dbm.h"
struct db_prop { /* Database properties */
char *pat; /* Database name pattern */
@@ -143,6 +142,35 @@ db_prop_lookup(const char *name)
}
return found;
}
+
+int
+_mf_dbm_open(mu_dbm_file_t *pdb, char *dbname, int access, int mode)
+{
+ mu_dbm_file_t db;
+ int rc;
+ int sflg = MU_FILE_SAFETY_LINKED_WRDIR |
+ MU_FILE_SAFETY_DIR_IWOTH;
+
+ rc = mu_dbm_create(dbname, &db);
+ if (rc)
+ return rc;
+
+ mu_dbm_safety_set_flags(db,
+ sflg | mf_file_mode_to_safety_criteria(mode));
+ rc = mu_dbm_safety_check(db);
+ if (rc && rc != ENOENT) {
+ mu_error(_("%s fails safety check: %s"),
+ dbname, mu_strerror(rc));
+ mu_dbm_destroy(&db);
+ return rc;
+ }
+ /* FIXME: Safety checking */
+ rc = mu_dbm_open(db, access, mode);
+ if (rc)
+ return rc;
+ *pdb = db;
+ return rc;
+}
#define LOOKUP_NULL_BYTE 0x1
@@ -154,27 +182,34 @@ dbmap_lookup(eval_environ_t env, char *dbname, const char *keystr,
const char *defval, int flags)
{
int rc;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
if (!defval)
defval = "";
- if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0, NULL))
+ rc = _mf_dbm_open(&db, dbname, MU_STREAM_READ, 0);
+ if (rc)
MF_THROW(mfe_dbfailure,
_("mf_dbm_open(%s) failed: %s"),
dbname,
- mf_dbm_strerror());
+ mu_strerror(rc));
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(key) = (void*) keystr;
- MF_DATUM_SIZE(key) = strlen(keystr);
+ key.mu_dptr = (void*) keystr;
+ key.mu_dsize = strlen(keystr);
if (flags & LOOKUP_NULL_BYTE)
- MF_DATUM_SIZE(key)++;
- rc = mf_dbm_fetch(&db, key, &contents) == 0;
+ key.mu_dsize++;
+ rc = mu_dbm_fetch(db, &key, &contents);
+ if (rc && rc != MU_ERR_NOENT) {
+ mu_dbm_destroy(&db);
+ MF_THROW(mfe_dbfailure,
+ _("cannot fetch data: %s"),
+ mu_dbm_strerror(db));
+ }
MF_DEBUG(MU_DEBUG_TRACE5,
- ("Looking up %s: %s", keystr, rc ? "true" : "false"));
+ ("Looking up %s: %s", keystr, rc ? "false" : "true"));
if (flags & LOOKUP_TEST_ONLY)
push(env, (STKVAL)rc);
else {
@@ -183,18 +218,18 @@ dbmap_lookup(eval_environ_t env, char *dbname, const char *keystr,
pushs(env, (STKVAL)defval);
else
push(env, 0);
- } else if (((char*)MF_DATUM_PTR(contents))[MF_DATUM_SIZE(contents)-1]) {
+ } else if (((char*)contents.mu_dptr)[contents.mu_dsize-1]) {
size_t off;
- size_t len = MF_DATUM_SIZE(contents);
+ size_t len = contents.mu_dsize;
char *s = MF_ALLOC_HEAP(off, len + 1);
- memcpy(s, MF_DATUM_PTR(contents), len);
+ memcpy(s, contents.mu_dptr, len);
s[len] = 0;
push(env, (STKVAL) off);
} else
- pushs(env, MF_DATUM_PTR(contents));
+ pushs(env, contents.mu_dptr);
}
- mf_dbm_datum_free(&contents);
- mf_dbm_close(&db);
+ mu_dbm_datum_free(&contents);
+ mu_dbm_destroy(&db);
return rc;
}
>])
@@ -225,37 +260,41 @@ MF_DEFUN(dbput, VOID, STRING dbname, STRING keystr, STRING value,
OPTIONAL, NUMBER null, NUMBER mode)
{
int rc;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
const struct db_prop *prop = db_prop_lookup(dbname);
- if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR,
- MF_OPTVAL(mode, (prop ? prop->mode : DEFAULT_DB_MODE)),
- NULL))
+ rc = _mf_dbm_open(&db, dbname, MU_STREAM_RDWR,
+ MF_OPTVAL(mode,
+ (prop ? prop->mode : DEFAULT_DB_MODE)));
+ if (rc)
MF_THROW(mfe_dbfailure,
_("mf_dbm_open(%s) failed: %s"),
dbname,
- mf_dbm_strerror());
+ mu_strerror(rc));
memset(&key, 0, sizeof key);
- MF_DATUM_PTR(key) = keystr;
- MF_DATUM_SIZE(key) = strlen(keystr);
+ key.mu_dptr = keystr;
+ key.mu_dsize = strlen(keystr);
if (MF_OPTVAL(null, prop && prop->null))
- MF_DATUM_SIZE(key)++;
+ key.mu_dsize++;
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(contents) = value;
- MF_DATUM_SIZE(contents) = strlen(value) + 1;
+ contents.mu_dptr = value;
+ contents.mu_dsize = strlen(value) + 1;
- rc = mf_dbm_insert(&db, key, contents, 1);
- mf_dbm_close(&db);
- MF_ASSERT(rc == 0,
- mfe_dbfailure,
- _("failed to insert data to %s: %s %s: %s"),
- dbname,
- keystr,
- value,
- mf_dbm_strerror());
+ rc = mu_dbm_store(db, &key, &contents, 1);
+ if (rc) {
+ const char *errstr = mu_dbm_strerror(db);
+ mu_dbm_destroy(&db);
+ MF_THROW(mfe_dbfailure,
+ _("failed to insert data to %s: %s %s: %s"),
+ dbname,
+ keystr,
+ value,
+ errstr);
+ }
+ mu_dbm_destroy(&db);
}
END
@@ -263,30 +302,34 @@ MF_DEFUN(dbinsert, VOID, STRING dbname, STRING keystr, STRING value,
OPTIONAL, NUMBER replace, NUMBER null, NUMBER mode)
{
int rc;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
const struct db_prop *prop = db_prop_lookup(dbname);
+ const char *errstr;
- if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR,
- MF_OPTVAL(mode, (prop ? prop->mode : DEFAULT_DB_MODE)),
- NULL))
+ rc = _mf_dbm_open(&db, dbname, MU_STREAM_RDWR,
+ MF_OPTVAL(mode,
+ (prop ? prop->mode : DEFAULT_DB_MODE)));
+ if (rc)
MF_THROW(mfe_dbfailure,
_("mf_dbm_open(%s) failed: %s"),
dbname,
- mf_dbm_strerror());
+ mu_strerror(rc));
memset(&key, 0, sizeof key);
- MF_DATUM_PTR(key) = keystr;
- MF_DATUM_SIZE(key) = strlen(keystr);
+ key.mu_dptr = keystr;
+ key.mu_dsize = strlen(keystr);
if (MF_OPTVAL(null, prop && prop->null))
- MF_DATUM_SIZE(key)++;
+ key.mu_dsize++;
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(contents) = value;
- MF_DATUM_SIZE(contents) = strlen(value) + 1;
+ contents.mu_dptr = value;
+ contents.mu_dsize = strlen(value) + 1;
- rc = mf_dbm_insert(&db, key, contents, MF_OPTVAL(replace));
- mf_dbm_close(&db);
+ rc = mu_dbm_store(db, &key, &contents, MF_OPTVAL(replace));
+ if (rc && rc != MU_ERR_EXISTS)
+ errstr = mu_dbm_strerror(db);
+ mu_dbm_destroy(&db);
if (rc == MU_ERR_EXISTS)
MF_THROW(mfe_exists, _("record already exists"));
@@ -296,38 +339,42 @@ MF_DEFUN(dbinsert, VOID, STRING dbname, STRING keystr, STRING value,
dbname,
keystr,
value,
- mf_dbm_strerror());
+ errstr);
}
END
MF_DEFUN(dbdel, VOID, STRING dbname, STRING keystr, OPTIONAL, NUMBER null,
NUMBER mode)
{
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
int rc;
const struct db_prop *prop = db_prop_lookup(dbname);
- if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR,
- MF_OPTVAL(mode, (prop ? prop->mode : DEFAULT_DB_MODE)),
- NULL))
- MF_THROW(mfe_dbfailure,
- _("mf_dbm_open(%s) failed: %s"),
- dbname,
- mf_dbm_strerror());
+ rc = _mf_dbm_open(&db, dbname, MU_STREAM_RDWR,
+ MF_OPTVAL(mode,
+ (prop ? prop->mode : DEFAULT_DB_MODE)));
+ MF_ASSERT(rc == 0,
+ mfe_dbfailure,
+ _("mf_dbm_open(%s) failed: %s"),
+ dbname,
+ mu_strerror(rc));
memset(&key, 0, sizeof key);
- MF_DATUM_PTR(key) = keystr;
- MF_DATUM_SIZE(key) = strlen(keystr);
+ key.mu_dptr = keystr;
+ key.mu_dsize = strlen(keystr);
if (MF_OPTVAL(null, prop && prop->null))
- MF_DATUM_SIZE(key)++;
- rc = mf_dbm_delete(&db, key);
- mf_dbm_close(&db);
+ key.mu_dsize++;
+ rc = mu_dbm_delete(db, &key);
+ if (rc && rc != MU_ERR_FAILURE)
+ mu_error(_("error deleting %s from %s: %s"),
+ keystr, dbname, mu_dbm_strerror(db));
+ mu_dbm_destroy(&db);
MF_ASSERT(rc == 0,
mfe_dbfailure,
_("failed to delete data `%s' from `%s': %s"),
keystr,
dbname,
- mf_dbm_strerror());
+ mu_strerror(rc));
}
END
@@ -336,8 +383,8 @@ END
struct db_tab {
int used;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
};
static void *
@@ -350,8 +397,8 @@ static void
close_db_tab(struct db_tab *dbt)
{
if (dbt->used) {
- mf_dbm_datum_free(&dbt->key);
- mf_dbm_close(&dbt->db);
+ mu_dbm_datum_free(&dbt->key);
+ mu_dbm_destroy(&dbt->db);
dbt->used = 0;
}
}
@@ -387,18 +434,28 @@ MF_DEFUN(dbfirst, NUMBER, STRING dbname)
int rc;
int n;
struct db_tab *dbt = MF_GET_DATA;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
-
- if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0, NULL))
- MF_THROW(mfe_dbfailure,
- _("mf_dbm_open(%s) failed: %s"),
- dbname,
- mf_dbm_strerror());
- rc = mf_dbm_firstkey(&db, &key);
- MF_ASSERT(rc == 0, mfe_dbfailure,
- _("mf_dbm_firstkey failed: %s"),
- mf_dbm_strerror());
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+
+ rc = _mf_dbm_open(&db, dbname, MU_STREAM_READ, 0);
+ MF_ASSERT(rc == 0,
+ mfe_dbfailure,
+ _("mf_dbm_open(%s) failed: %s"),
+ dbname,
+ mu_strerror(rc));
+ memset(&key, 0, sizeof key);
+ rc = mu_dbm_firstkey(db, &key);
+ if (rc) {
+ if (rc == MU_ERR_NOENT) {
+ mu_dbm_destroy(&db);
+ MF_RETURN(0);
+ } else if (rc) {
+ mu_dbm_destroy(&db);
+ MF_THROW(mfe_dbfailure,
+ _("mf_dbm_firstkey failed: %s"),
+ mu_strerror(rc));
+ }
+ }
n = new_db_tab(dbt);
MF_ASSERT(n >= 0,
mfe_failure,
@@ -413,19 +470,22 @@ END
MF_DEFUN(dbnext, NUMBER, NUMBER dn)
{
struct db_tab *dbt = MF_GET_DATA + dn;
- MF_DBM_DATUM nextkey;
+ struct mu_dbm_datum nextkey;
int rc;
MF_ASSERT(dn >= 0 && dn < NUMDB && dbt->used,
mfe_range,
_("invalid database descriptor"));
- rc = mf_dbm_nextkey(&dbt->db, dbt->key, &nextkey);
+ rc = mu_dbm_nextkey(dbt->db, &nextkey);
if (rc) {
+ if (rc == MU_ERR_FAILURE)
+ mu_error(_("mu_dbm_nextkey: %s"),
+ mu_dbm_strerror(dbt->db));
close_db_tab(dbt);
MF_RETURN(0);
}
- mf_dbm_datum_free(&dbt->key);
+ mu_dbm_datum_free(&nextkey);
dbt->key = nextkey;
MF_RETURN(1);
}
@@ -441,9 +501,9 @@ MF_DEFUN(dbkey, STRING, NUMBER dn)
mfe_range,
_("invalid database descriptor"));
- len = MF_DATUM_SIZE(dbt->key);
+ len = dbt->key.mu_dsize;
s = MF_ALLOC_HEAP(off, len + 1);
- memcpy(s, MF_DATUM_PTR(dbt->key), len);
+ memcpy(s, dbt->key.mu_dptr, len);
s[len] = 0;
MF_RETURN(off);
}
@@ -455,24 +515,25 @@ MF_DEFUN(dbvalue, STRING, NUMBER dn)
size_t off, len;
char *s;
struct db_tab *dbt = MF_GET_DATA + dn;
- MF_DBM_DATUM contents;
+ struct mu_dbm_datum contents;
MF_ASSERT(dn >= 0 && dn < NUMDB && dbt->used,
mfe_range,
_("invalid database descriptor"));
memset(&contents, 0, sizeof contents);
- rc = mf_dbm_fetch(&dbt->db, dbt->key, &contents);
+ rc = mu_dbm_fetch(dbt->db, &dbt->key, &contents);
MF_ASSERT(rc == 0,
mfe_dbfailure,
- _("key not found: %s"),
- mf_dbm_strerror());
+ _("cannot fetch key: %s"),
+ rc == MU_ERR_FAILURE ?
+ mu_dbm_strerror(dbt->db) : mu_strerror (rc));
- len = MF_DATUM_SIZE(contents);
+ len = contents.mu_dsize;
s = MF_ALLOC_HEAP(off, len + 1);
- memcpy(s, MF_DATUM_PTR(contents), len);
+ memcpy(s, contents.mu_dptr, len);
s[len] = 0;
- mf_dbm_datum_free(&contents);
+ mu_dbm_datum_free(&contents);
MF_RETURN(off);
}
END
@@ -522,32 +583,37 @@ static int
do_greylist_traditional(eval_environ_t env, char *email, long interval)
{
int rc;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
- int readonly;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
+ int readonly = 0;
time_t now;
- rc = mf_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600,
- &readonly);
+ rc = _mf_dbm_open(&db, greylist_format->dbname, MU_STREAM_RDWR, 0600);
+ if (rc) {
+ rc = _mf_dbm_open(&db, greylist_format->dbname,
+ MU_STREAM_READ, 0);
+ readonly = 1;
+ }
MF_ASSERT(rc == 0, mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"),
- greylist_format->dbname, mf_dbm_strerror());
+ greylist_format->dbname, mu_strerror(rc));
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(key) = email;
- MF_DATUM_SIZE(key) = strlen(email)+1;
+ key.mu_dptr = email;
+ key.mu_dsize = strlen(email)+1;
time(&now);
- if (mf_dbm_fetch(&db, key, &contents) == 0) {
+ rc = mu_dbm_fetch(db, &key, &contents);
+ if (rc == 0) {
time_t timestamp, diff;
- MF_ASSERT(MF_DATUM_SIZE(contents) == sizeof timestamp,
+ MF_ASSERT(contents.mu_dsize == sizeof timestamp,
mfe_dbfailure,
_("greylist database %s has wrong data size"),
- greylist_format->dbname);
+ greylist_format->dbname);
- timestamp = *(time_t*) MF_DATUM_PTR(contents);
+ timestamp = *(time_t*) contents.mu_dptr;
diff = now - timestamp;
if (mu_debug_level_p(debug_handle, MU_DEBUG_TRACE5)) {
@@ -559,10 +625,10 @@ do_greylist_traditional(eval_environ_t env, char *email, long interval)
sizeof timebuf),
(long) diff);
}
-
+
if (diff < interval) {
diff = interval - diff;
-
+
MF_VAR_REF(greylist_seconds_left, diff);
MF_DEBUG(MU_DEBUG_TRACE6,
@@ -575,15 +641,17 @@ do_greylist_traditional(eval_environ_t env, char *email, long interval)
("greylist record for %s expired", email));
MF_VAR_REF(greylist_seconds_left, interval);
if (!readonly) {
- memcpy(MF_DATUM_PTR(contents),
- &now, sizeof now);
- if (mf_dbm_insert(&db, key, contents, 1))
+ memcpy(contents.mu_dptr, &now, sizeof now);
+ rc = mu_dbm_store(db, &key, &contents, 1);
+ if (rc)
mu_error(_("cannot insert datum `%-.*s' in "
"greylist database %s: %s"),
- MF_DATUM_SIZE(key),
- (char*)MF_DATUM_PTR(key),
+ key.mu_dsize,
+ (char*)key.mu_dptr,
greylist_format->dbname,
- mf_dbm_strerror());
+ rc == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) :
+ mu_strerror(rc));
} else
MF_DEBUG(MU_DEBUG_TRACE6,
("database opened in readonly mode: "
@@ -594,23 +662,25 @@ do_greylist_traditional(eval_environ_t env, char *email, long interval)
("%s finished greylisting period", email));
rc = 0;
}
- mf_dbm_datum_free(&contents);
+ mu_dbm_datum_free(&contents);
} else if (!readonly) {
MF_DEBUG(MU_DEBUG_TRACE6, ("greylisting %s", email));
MF_VAR_REF(greylist_seconds_left, interval);
- MF_DATUM_PTR(contents) = (void*)&now;
- MF_DATUM_SIZE(contents) = sizeof now;
- if (mf_dbm_insert(&db, key, contents, 1))
+ contents.mu_dptr = (void*)&now;
+ contents.mu_dsize = sizeof now;
+ rc = mu_dbm_store(db, &key, &contents, 1);
+ if (rc)
mu_error(_("Cannot insert datum `%-.*s' in greylist "
"database %s: %s"),
- MF_DATUM_SIZE(key), (char*)MF_DATUM_PTR(key),
+ key.mu_dsize, (char*)key.mu_dptr,
greylist_format->dbname,
- mf_dbm_strerror());
+ rc == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) : mu_strerror(rc));
rc = 1;
} else
rc = 0;
- mf_dbm_close(&db);
+ mu_dbm_destroy(&db);
return rc;
}
@@ -638,32 +708,37 @@ static int
do_greylist_ct(eval_environ_t env, char *email, long interval)
{
int rc;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
- int readonly;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
+ int readonly = 0;
time_t now;
- rc = mf_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600,
- &readonly);
+ rc = _mf_dbm_open(&db, greylist_format->dbname, MU_STREAM_RDWR, 0600);
+ if (rc) {
+ rc = _mf_dbm_open(&db, greylist_format->dbname,
+ MU_STREAM_READ, 0);
+ readonly = 1;
+ }
MF_ASSERT(rc == 0, mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"),
- greylist_format->dbname, mf_dbm_strerror());
+ greylist_format->dbname, mu_strerror(rc));
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(key) = email;
- MF_DATUM_SIZE(key) = strlen(email)+1;
+ key.mu_dptr = email;
+ key.mu_dsize = strlen(email) + 1;
time(&now);
- if (mf_dbm_fetch(&db, key, &contents) == 0) {
+ rc = mu_dbm_fetch(db, &key, &contents);
+ if (rc == 0) {
time_t timestamp;
- MF_ASSERT(MF_DATUM_SIZE(contents) == sizeof timestamp,
+ MF_ASSERT(contents.mu_dsize == sizeof timestamp,
mfe_dbfailure,
_("greylist database %s has wrong data size"),
greylist_format->dbname);
- timestamp = *(time_t*) MF_DATUM_PTR(contents);
+ timestamp = *(time_t*) contents.mu_dptr;
if (now < timestamp) {
time_t diff = timestamp - now;
@@ -681,16 +756,18 @@ do_greylist_ct(eval_environ_t env, char *email, long interval)
MF_VAR_REF(greylist_seconds_left, interval);
if (!readonly) {
now += interval;
- memcpy(MF_DATUM_PTR(contents),
- &now, sizeof now);
- if (mf_dbm_insert(&db, key, contents, 1))
+ memcpy(contents.mu_dptr, &now, sizeof now);
+ rc = mu_dbm_store(db, &key, &contents, 1);
+ if (rc)
mu_error(_("Cannot insert datum "
"`%-.*s' in greylist "
"database %s: %s"),
- MF_DATUM_SIZE(key),
- (char*)MF_DATUM_PTR(key),
+ key.mu_dsize,
+ (char*)key.mu_dptr,
greylist_format->dbname,
- mf_dbm_strerror());
+ rc == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) :
+ mu_strerror(rc));
} else
MF_DEBUG(MU_DEBUG_TRACE6,
("database opened in readonly mode: "
@@ -701,24 +778,26 @@ do_greylist_ct(eval_environ_t env, char *email, long interval)
("%s finished greylisting period", email));
rc = 0;
}
- mf_dbm_datum_free(&contents);
+ mu_dbm_datum_free(&contents);
} else if (!readonly) {
MF_DEBUG(MU_DEBUG_TRACE6, ("greylisting %s", email));
MF_VAR_REF(greylist_seconds_left, interval);
now += interval;
- MF_DATUM_PTR(contents) = (void*)&now;
- MF_DATUM_SIZE(contents) = sizeof now;
- if (mf_dbm_insert(&db, key, contents, 1))
+ contents.mu_dptr = (void*)&now;
+ contents.mu_dsize = sizeof now;
+ rc = mu_dbm_store(db, &key, &contents, 1);
+ if (rc)
mu_error(_("Cannot insert datum `%-.*s' in greylist "
"database %s: %s"),
- MF_DATUM_SIZE(key), (char*)MF_DATUM_PTR(key),
+ key.mu_dsize, (char*)key.mu_dptr,
greylist_format->dbname,
- mf_dbm_strerror());
+ rc == MU_ERR_FAILURE ?
+ mu_dbm_strerror(db) : mu_strerror(rc));
rc = 1;
} else
rc = 0;
- mf_dbm_close(&db);
+ mu_dbm_destroy(&db);
return rc;
}
@@ -728,42 +807,47 @@ static int
is_greylisted_ct(eval_environ_t env, char *email)
{
int rc;
- MF_DBM_FILE db;
- MF_DBM_DATUM key;
- MF_DBM_DATUM contents;
- int readonly;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
+ struct mu_dbm_datum contents;
+ int readonly = 0;
time_t now;
- rc = mf_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600,
- &readonly);
+ rc = _mf_dbm_open(&db, greylist_format->dbname, MU_STREAM_RDWR, 0600);
+ if (rc) {
+ rc = _mf_dbm_open(&db, greylist_format->dbname,
+ MU_STREAM_READ, 0);
+ readonly = 1;
+ }
MF_ASSERT(rc == 0, mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"),
- greylist_format->dbname, mf_dbm_strerror());
+ greylist_format->dbname, mu_strerror(rc));
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
- MF_DATUM_PTR(key) = email;
- MF_DATUM_SIZE(key) = strlen(email) + 1;
+ key.mu_dptr = email;
+ key.mu_dsize = strlen(email) + 1;
time(&now);
- if (mf_dbm_fetch(&db, key, &contents) == 0) {
+ rc = mu_dbm_fetch(db, &key, &contents);
+ if (rc == 0) {
time_t timestamp;
- MF_ASSERT(MF_DATUM_SIZE(contents) == sizeof timestamp,
+ MF_ASSERT(contents.mu_dsize == sizeof timestamp,
mfe_dbfailure,
_("greylist database %s has wrong data size"),
greylist_format->dbname);
- timestamp = *(time_t*) MF_DATUM_PTR(contents);
+ timestamp = *(time_t*) contents.mu_dptr;
rc = timestamp > now;
if (rc)
MF_VAR_REF(greylist_seconds_left, timestamp - now);
- mf_dbm_datum_free(&contents);
+ mu_dbm_datum_free(&contents);
} else
rc = 0;
- mf_dbm_close(&db);
+ mu_dbm_destroy(&db);
return rc;
}
diff --git a/src/calloutd.c b/src/calloutd.c
index cd05412..c375359 100644
--- a/src/calloutd.c
+++ b/src/calloutd.c
@@ -39,7 +39,6 @@
#include "srvman.h"
#include "srvcfg.h"
#include "mfdb.h"
-#include "mf-dbm.h"
void
xalloc_die()
@@ -125,7 +124,6 @@ main(int argc, char **argv)
mf_srvcfg_log_setup(stderr_closed_p() ? "syslog" : "stderr");
libcallout_init();
- libdbm_init();
db_format_setup();
mf_server_save_cmdline(argc, argv);
diff --git a/src/main.c b/src/main.c
index c277aa4..ba0c0f5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -37,6 +37,7 @@
#include <mailutils/server.h>
#include <mailutils/syslog.h>
#include <mailutils/libargp.h>
+#include <mailutils/dbm.h>
#include "mailfromd.h"
#include "callout.h"
@@ -44,7 +45,6 @@
#include "inttostr.h"
#include "srvcfg.h"
#include "filenames.h"
-#include "mf-dbm.h"
#include "builtin.h"
#include "prog.h"
@@ -918,11 +918,10 @@ struct mu_cfg_param mf_cfg_param[] = {
{ "database", mu_cfg_section, NULL },
- { "lock-retry-count", mu_cfg_size, &lock_retry_count_option, 0, NULL,
- N_("Retry acquiring DBM file lock this number of times.") },
- { "lock-retry-timeout", mu_cfg_callback, &lock_retry_timeout_option, 0,
- config_cb_time_t,
- N_("Set the time span between the two DBM locking attempts."),
+ { "lock-retry-count", mu_cfg_callback, 0, 0, config_cb_ignore,
+ N_("Ignored for backward compatibility.") },
+ { "lock-retry-timeout", mu_cfg_callback, 0,0, config_cb_ignore,
+ N_("Ignored for backward compatibility."),
N_("time") },
{ "max-match-mx", mu_cfg_size, &max_match_mx, 0, NULL,
@@ -1003,6 +1002,37 @@ db_format_enumerator(struct db_format *fmt, void *data)
return 0;
}
+static void
+list_db_formats(const char *pfx)
+{
+ mu_iterator_t itr;
+ int rc;
+ const char *defdb = DEFAULT_DB_TYPE;
+ printf("%s", pfx);
+
+ rc = mu_dbm_impl_iterator(&itr);
+ if (rc) {
+ printf("%s\n", _("unknown"));
+ mu_error("%s", mu_strerror(rc));
+ } else {
+ int i;
+ for (mu_iterator_first(itr), i = 0; !mu_iterator_is_done(itr);
+ mu_iterator_next(itr), i++) {
+ struct mu_dbm_impl *impl;
+
+ mu_iterator_current(itr, (void**)&impl);
+ if (i)
+ printf(", ");
+ else if (!defdb)
+ defdb = impl->_dbm_name;
+ printf("%s", impl->_dbm_name);
+ }
+ putchar('\n');
+ mu_iterator_destroy(&itr);
+ }
+ printf("default database type: %s\n", defdb);
+}
+
void
mailfromd_show_defaults()
{
@@ -1020,14 +1050,7 @@ mailfromd_show_defaults()
printf("default syslog: blocking\n");
#endif
#endif
- printf("database format: ");
-#if defined WITH_GDBM
- printf("GDBM");
-#elif defined WITH_BDB
- printf("Berkeley DB %d.x", WITH_BDB);
-#endif
- printf("\n");
-
+ list_db_formats("supported databases: ");
printf("Optional features: ");
#if defined WITH_GEOIP
printf(" GeoIP");
@@ -1193,7 +1216,6 @@ main(int argc, char **argv)
init_symbols();
builtin_setup();
mf_runtime_param_finish();
- libdbm_init();
db_format_setup();
include_path_setup();
pragma_setup();
diff --git a/src/mfdbtool.c b/src/mfdbtool.c
index 991bbdf..98e87ac 100644
--- a/src/mfdbtool.c
+++ b/src/mfdbtool.c
@@ -31,7 +31,6 @@
#include "libmf.h"
#include "mfdb.h"
-#include "mf-dbm.h"
char *state_dir = DEFAULT_STATE_DIR;
char *file_option; /* File name for DB management commands */
@@ -41,8 +40,9 @@ time_t expire_interval = 0; /* When set, overrides the expire interval
int all_option; /* Process all databases */
int predict_next_option;
double predict_rate; /* Prediction rate for --list --format=rates*/
-void (*run)(int argc, char **argv) = NULL;
+char *db_type_str = DEFAULT_DB_TYPE;
+void (*run)(int argc, char **argv) = NULL;
void
assert_db_format()
@@ -184,8 +184,6 @@ enum {
OPTION_COMPACT,
OPTION_IGNORE_FAILED_READS,
OPTION_PREDICT_NEXT,
- OPTION_LOCK_RETRY_COUNT,
- OPTION_LOCK_RETRY_TIMEOUT,
OPTION_ALL,
OPTION_TIME_FORMAT
};
@@ -228,10 +226,6 @@ static struct argp_option options[] = {
#define GRP 30
{ NULL, 0, NULL, 0,
N_("Configuration modifiers"), GRP },
- { "lock-retry-count", OPTION_LOCK_RETRY_COUNT, N_("NUMBER"), 0,
- N_("set maximum number of attempts to acquire the lock"), GRP+1 },
- { "lock-retry-timeout", OPTION_LOCK_RETRY_TIMEOUT, N_("TIME"), 0,
- N_("set timeout for acquiring the lockfile"), GRP+1 },
{ "state-directory", OPTION_STATE_DIRECTORY, N_("DIR"), 0,
N_("set new program state directory"), GRP+1 },
{ "expire-interval", 'e', N_("NUMBER"), 0,
@@ -254,20 +248,6 @@ parse_opt(int key, char *arg, struct argp_state *state)
case OPTION_STATE_DIRECTORY:
mf_optcache_set_option("state-directory", arg);
break;
- case OPTION_LOCK_RETRY_COUNT:
- mf_optcache_set_option("lock-retry-count", arg);
- break;
- case OPTION_LOCK_RETRY_TIMEOUT: {
- const char *endp;
- time_t t;
-
- if (parse_time_interval(arg, &t, &endp))
- argp_error(state,
- _("unrecognized time format (near `%s')"),
- endp);
- mf_optcache_set_option("lock-retry-timeout", (void*)&t);
- break;
- }
case 'd':
mf_optcache_set_option("debug", arg);
@@ -351,6 +331,9 @@ cb_debug(void *data, mu_config_value_t *arg)
struct mu_cfg_param mfdbtool_cfg_param[] = {
+ { "database-type", mu_cfg_string, &db_type_str, 0, NULL,
+ N_("Default database type"),
+ N_("type") },
{ "database", mu_cfg_section, NULL, 0, NULL, NULL },
{ "state-directory", mu_cfg_string, &state_dir, 0, NULL,
N_("Set program state directory."),
@@ -363,12 +346,13 @@ struct mu_cfg_param mfdbtool_cfg_param[] = {
"where <module> is the name of a Mailfromd module, and <level> "
"is the desired verbosity level for that module."),
N_("spec: list") },
- { "lock-retry-count", mu_cfg_size, &lock_retry_count_option, 0, NULL,
- N_("Retry acquiring DBM file lock this number of times.") },
- { "lock-retry-timeout", mu_cfg_callback, &lock_retry_timeout_option, 0,
- config_cb_time_t,
- N_("Set the time span between the two DBM locking attempts."),
+
+ { "lock-retry-count", mu_cfg_callback, 0, 0, config_cb_ignore,
+ N_("Ignored for backward compatibility.") },
+ { "lock-retry-timeout", mu_cfg_callback, 0,0, config_cb_ignore,
+ N_("Ignored for backward compatibility."),
N_("time") },
+
{ NULL }
};
@@ -384,32 +368,10 @@ set_debug(void *value)
mu_debug_parse_spec(value);
}
-static void
-set_lock_retry_count(void *value)
-{
- char *p;
-
- lock_retry_count_option = strtoul(value, &p, 10);
- if (*p) {
- mu_error(_("invalid value for lock-retry-count: %s"),
- (char*)value);
- exit(EX_USAGE);
- }
- free(value);
-}
-
-static void
-set_lock_retry_timeout(void *value)
-{
- lock_retry_timeout_option = *(time_t*) value;
- free(value);
-}
-
static struct mf_option_cache option_cache[] = {
{ "state-directory", NULL, mf_option_string, set_state_directory },
{ "debug", NULL, mf_option_string, set_debug },
- { "lock-retry-count", NULL, mf_option_string, set_lock_retry_count },
- { "lock-retry-timeout", NULL, mf_option_time_t, set_lock_retry_timeout },
+
{ NULL }
};
@@ -452,7 +414,6 @@ main(int argc, char **argv)
program_invocation_short_name = argv[0];
argp_program_version_hook = version;
- libdbm_init();
db_format_setup();
database_cfg_init();
@@ -465,6 +426,19 @@ main(int argc, char **argv)
0, &index, NULL);
if (rc)
exit(EX_CONFIG);
+
+ if (db_type_str) {
+ mu_url_t dbhint;
+
+ if ((rc = mu_url_create_null(&dbhint)) ||
+ (rc = mu_url_set_scheme(dbhint, db_type_str))) {
+ mu_error(_("cannot initialize DBM hint: %s"),
+ mu_strerror(rc));
+ exit(EX_SOFTWARE);
+ }
+ mu_url_destroy(&mu_dbm_hint);
+ mu_dbm_hint = dbhint;
+ }
if (!run) {
mu_error(_("you must specify one of --list, --delete,"
diff --git a/src/savsrv.c b/src/savsrv.c
index be1aa75..a987a46 100644
--- a/src/savsrv.c
+++ b/src/savsrv.c
@@ -38,7 +38,6 @@
#include "srvcfg.h"
#include "callout.h"
#include "mfdb.h"
-#include "mf-dbm.h"
#include "callout-dbgmod.h"
char *ehlo_domain;
diff --git a/src/srvcfg.c b/src/srvcfg.c
index 0afb7f6..4030a4e 100644
--- a/src/srvcfg.c
+++ b/src/srvcfg.c
@@ -21,6 +21,7 @@
#include <mailutils/mailutils.h>
#include <mailutils/libargp.h>
+#include <mailutils/dbm.h>
#include <argp.h>
#include <sysexits.h>
#include "xalloc.h"
@@ -41,6 +42,7 @@ int smtp_transcript;
static int transcript_option;
struct mu_sockaddr *source_address; /* Source address for TCP connections */
int mtasim_option; /* mtasim compatibility mode */
+char *db_type_str = DEFAULT_DB_TYPE;
size_t max_callout_mx = MAXMXCOUNT;
@@ -614,6 +616,9 @@ static struct mu_cfg_param srv_cfg_param[] = {
{ "state-directory", mu_cfg_callback, NULL, 0, cb_state_directory,
N_("Set program state directory."),
N_("dir") },
+ { "database-type", mu_cfg_string, &db_type_str, 0, NULL,
+ N_("Default database type"),
+ N_("type") },
{ "database", mu_cfg_section, NULL, 0, NULL, NULL },
{ "ehlo-domain", mu_cfg_string, &ehlo_domain, 0, NULL,
N_("Set the domain name for EHLO command.") },
@@ -861,6 +866,20 @@ mf_srvcfg_flush()
if (!ehlo_domain)
init_ehlo_domain();
+
+ if (db_type_str) {
+ mu_url_t dbhint;
+ int rc;
+
+ if ((rc = mu_url_create_null(&dbhint)) ||
+ (rc = mu_url_set_scheme(dbhint, db_type_str))) {
+ mu_error(_("cannot initialize DBM hint: %s"),
+ mu_strerror(rc));
+ exit(EX_SOFTWARE);
+ }
+ mu_url_destroy(&mu_dbm_hint);
+ mu_dbm_hint = dbhint;
+ }
}
void

Return to:

Send suggestions and report system problems to the System administrator.