diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-11-10 00:21:13 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-11-10 00:52:54 +0200 |
commit | 4926ea635ee23341615c351db3e4949553ca4dfb (patch) | |
tree | a1a8c4aede69cf55b5e27fa1dc1630aeeda70329 /src | |
parent | 7e4d54bd39368b36e8451d52975052c00e745f7a (diff) | |
download | mailfromd-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.am | 3 | ||||
-rw-r--r-- | src/builtin/db.bi | 384 | ||||
-rw-r--r-- | src/calloutd.c | 2 | ||||
-rw-r--r-- | src/main.c | 52 | ||||
-rw-r--r-- | src/mfdbtool.c | 76 | ||||
-rw-r--r-- | src/savsrv.c | 1 | ||||
-rw-r--r-- | src/srvcfg.c | 19 |
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(); @@ -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; |