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
@@ -45,13 +45,12 @@ mailfromd_SOURCES = \
mailfromd_LDADD = \
./libcallout.a\
builtin/libbuiltin.a\
../lib/libmfdb.a\
../lib/libmf.a\
- ../lib/libdbm.a\
../gnu/libgnu.a\
$(MAILUTILS_LIBS)\
$(MILTER)\
$(GEOIP_LIBS)\
$(DSPAM_LIBS)
@@ -68,24 +67,22 @@ calloutd_SOURCES = \
calloutd.c
calloutd_LDADD = \
./libcallout.a\
../lib/libmfdb.a\
../lib/libmf.a\
- ../lib/libdbm.a\
../gnu/libgnu.a\
$(MAILUTILS_LIBS)\
$(MILTER)
mfdbtool_SOURCES = \
mfdbtool.c
mfdbtool_LDADD = \
../lib/libmfdb.a\
../lib/libmf.a\
- ../lib/libdbm.a\
../gnu/libgnu.a\
$(MAILUTILS_LIBS)
EXTRA_DIST = \
dbgmod.awk\
drv.awk\
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
@@ -13,13 +13,12 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#define DEFAULT_DB_MODE 0640
#include <fnmatch.h>
-#include "mf-dbm.h"
struct db_prop { /* Database properties */
char *pat; /* Database name pattern */
mode_t mode; /* File mode */
int null; /* Null byte */
};
@@ -141,63 +140,99 @@ db_prop_lookup(const char *name)
}
mu_iterator_destroy(&itr);
}
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
MF_DSEXP_SUPPRESS([<dbmap_lookup>],[<
static int
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 {
if (!rc) {
if (defval)
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;
}
>])
MF_DSEXP
MF_DEFUN(dbmap, NUMBER, STRING dbname, STRING key, OPTIONAL, NUMBER null)
@@ -222,139 +257,151 @@ MF_DEFUN(dbget, STRING, STRING dbname, STRING key, OPTIONAL,
END
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
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"));
MF_ASSERT(rc == 0,
mfe_dbfailure,
_("failed to insert data to %s: %s %s: %s"),
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
#define NUMDB 128
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 *
alloc_db_tab()
{
return xcalloc(NUMDB, sizeof(struct db_tab));
}
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;
}
}
static void
destroy_db_tab(void *data)
@@ -384,24 +431,34 @@ new_db_tab(struct db_tab *dbt)
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,
_("no more database entries available"));
dbt += n;
dbt->db = db;
@@ -410,25 +467,28 @@ MF_DEFUN(dbfirst, NUMBER, STRING dbname)
}
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);
}
END
MF_DEFUN(dbkey, STRING, NUMBER dn)
@@ -438,44 +498,45 @@ MF_DEFUN(dbkey, STRING, NUMBER dn)
struct db_tab *dbt = MF_GET_DATA + dn;
MF_ASSERT(dn >= 0 && dn < NUMDB && dbt->used,
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);
}
END
MF_DEFUN(dbvalue, STRING, NUMBER dn)
{
int rc;
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
enum greylist_semantics
@@ -519,38 +580,43 @@ MF_VAR(greylist_seconds_left, NUMBER);
database keeps the time the greylisting was activated.
*/
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)) {
char timebuf[32];
mu_debug_log("%s entered greylist database on %s, "
"%ld seconds ago",
@@ -572,48 +638,52 @@ do_greylist_traditional(eval_environ_t env, char *email, long interval)
rc = 1;
} else if (diff > greylist_format->expire_interval) {
MF_DEBUG(MU_DEBUG_TRACE6,
("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: "
"not updating"));
rc = 1;
} else {
MF_DEBUG(MU_DEBUG_TRACE6,
("%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;
}
/* Implementation of the is_greylisted predicate has no sense for
traditional greylist databases, because greylisting interval is
@@ -635,38 +705,43 @@ is_greylisted_traditional(eval_environ_t env, char *email)
from now)
*/
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;
MF_VAR_REF(greylist_seconds_left, diff);
MF_DEBUG(MU_DEBUG_TRACE6,
@@ -678,95 +753,104 @@ do_greylist_ct(eval_environ_t env, char *email, long interval)
greylist_format->expire_interval) {
MF_DEBUG(MU_DEBUG_TRACE6,
("greylist record for %s expired", email));
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: "
"not updating"));
rc = 1;
} else {
MF_DEBUG(MU_DEBUG_TRACE6,
("%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;
}
/* The `is_greylisted' predicate for new databases */
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;
}
struct greylist_class {
int (*gl_fun)(eval_environ_t, char *, long);
diff --git a/src/calloutd.c b/src/calloutd.c
index cd054125..c3753593 100644
--- a/src/calloutd.c
+++ b/src/calloutd.c
@@ -36,13 +36,12 @@
#include "libmf.h"
#include "callout.h"
#include "srvman.h"
#include "srvcfg.h"
#include "mfdb.h"
-#include "mf-dbm.h"
void
xalloc_die()
{
mu_error(_("not enough memory"));
abort();
@@ -122,13 +121,12 @@ main(int argc, char **argv)
/* Set default logging */
mu_log_facility = DEFAULT_LOG_FACILITY;
mu_stdstream_setup(MU_STDSTREAM_RESET_NONE);
mf_srvcfg_log_setup(stderr_closed_p() ? "syslog" : "stderr");
libcallout_init();
- libdbm_init();
db_format_setup();
mf_server_save_cmdline(argc, argv);
dnsbase_init();
database_cfg_init();
mu_acl_cfg_init();
diff --git a/src/main.c b/src/main.c
index c277aa45..ba0c0f56 100644
--- a/src/main.c
+++ b/src/main.c
@@ -34,20 +34,20 @@
#include <netdb.h>
#include <mailutils/mailutils.h>
#include <mailutils/server.h>
#include <mailutils/syslog.h>
#include <mailutils/libargp.h>
+#include <mailutils/dbm.h>
#include "mailfromd.h"
#include "callout.h"
#include "srvman.h"
#include "inttostr.h"
#include "srvcfg.h"
#include "filenames.h"
-#include "mf-dbm.h"
#include "builtin.h"
#include "prog.h"
/* Configurable options */
@@ -915,17 +915,16 @@ struct mu_cfg_param mf_cfg_param[] = {
cb_relayed_domain_file,
N_("Read relayed domain names from the file"),
N_("file: string") },
{ "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,
N_("Maximum number of MXs used by MFL \"mx match\" operation.") },
{ "runtime", mu_cfg_section, NULL },
@@ -1000,12 +999,43 @@ db_format_enumerator(struct db_format *fmt, void *data)
} else
printf("%s expiration: %lu\n", fmt->name,
fmt->expire_interval);
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()
{
printf("version: %s\n", VERSION);
printf("script file: %s\n", script_file);
printf("preprocessor: %s\n", ext_pp ? ext_pp : "none");
@@ -1017,20 +1047,13 @@ mailfromd_show_defaults()
#if DEFAULT_SYSLOG_ASYNC == 1
printf("default syslog: non-blocking\n");
#else
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");
#endif
#if defined WITH_DSPAM
printf(" DSPAM");
@@ -1190,13 +1213,12 @@ main(int argc, char **argv)
debug_init(modnames);
libcallout_init();
init_string_space();
init_symbols();
builtin_setup();
mf_runtime_param_finish();
- libdbm_init();
db_format_setup();
include_path_setup();
pragma_setup();
mf_optcache_add(option_cache, 0, MF_OCF_NULL|MF_OCF_STATIC);
mf_server_save_cmdline(argc, argv);
diff --git a/src/mfdbtool.c b/src/mfdbtool.c
index 991bbdfc..98e87acc 100644
--- a/src/mfdbtool.c
+++ b/src/mfdbtool.c
@@ -28,24 +28,24 @@
#include <mailutils/libcfg.h>
#include <mailutils/libargp.h>
#include <mailutils/daemon.h>
#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 */
struct db_format *format_option;
time_t expire_interval = 0; /* When set, overrides the expire interval
for the selected database */
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()
{
if (!format_option) {
mu_error(_("operation is not applicable"));
@@ -181,14 +181,12 @@ enum {
OPTION_DELETE,
OPTION_LIST,
OPTION_EXPIRE,
OPTION_COMPACT,
OPTION_IGNORE_FAILED_READS,
OPTION_PREDICT_NEXT,
- OPTION_LOCK_RETRY_COUNT,
- OPTION_LOCK_RETRY_TIMEOUT,
OPTION_ALL,
OPTION_TIME_FORMAT
};
static struct argp_option options[] = {
#define GRP 10
@@ -225,16 +223,12 @@ static struct argp_option options[] = {
N_("set debugging level"), GRP+1 },
#undef GRP
#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,
N_("set database expiration interval to NUMBER seconds"), GRP+1 },
#undef GRP
{ NULL }
@@ -251,26 +245,12 @@ static error_t
parse_opt(int key, char *arg, struct argp_state *state)
{
switch (key) {
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;