aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-11-10 00:21:13 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2011-11-10 00:52:54 +0200
commit4926ea635ee23341615c351db3e4949553ca4dfb (patch)
treea1a8c4aede69cf55b5e27fa1dc1630aeeda70329 /src
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 (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/builtin/db.bi384
-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
7 files changed, 315 insertions, 222 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 4400f8d4..af404ca5 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 a734dc10..90d926eb 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 */
@@ -144,6 +143,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
#define LOOKUP_TEST_ONLY 0x2
@@ -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,
+ 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,
- mf_dbm_strerror());
+ 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,
+ 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,
- 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)++;
- 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;
+ mu_dbm_file_t db;
+ struct mu_dbm_datum key;
- if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0, NULL))
- MF_THROW(mfe_dbfailure,
+ rc = _mf_dbm_open(&db, dbname, MU_STREAM_READ, 0);
+ MF_ASSERT(rc == 0,
+ mfe_dbfailure,
_("mf_dbm_open(%s) failed: %s"),
dbname,
- mf_dbm_strerror());
- rc = mf_dbm_firstkey(&db, &key);
- MF_ASSERT(rc == 0, mfe_dbfailure,
+ 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"),
- mf_dbm_strerror());
+ 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);
- 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)) {
@@ -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 cd054125..c3753593 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 c277aa45..ba0c0f56 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 991bbdfc..98e87acc 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();
@@ -466,6 +427,19 @@ main(int argc, char **argv)
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,"
" --expire or --compat"));
diff --git a/src/savsrv.c b/src/savsrv.c
index be1aa758..a987a465 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 0afb7f6a..4030a4e6 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_flu