+#include "ctdl_module.h"
+#include "control.h"
+#include "citserver.h"
+#include "config.h"
+
+static DB *dbp[MAXCDB]; /* One DB handle for each Citadel database */
+static DB_ENV *dbenv; /* The DB environment (global) */
+
+
+void cdb_abort(void)
+{
+ syslog(LOG_DEBUG, "db: citserver is stopping in order to prevent data loss. uid=%d gid=%d euid=%d egid=%d",
+ getuid(), getgid(), geteuid(), getegid()
+ );
+ exit(CTDLEXIT_DB);
+}
+
+
+/* Verbose logging callback */
+void cdb_verbose_log(const DB_ENV * dbenv, const char *msg)
+{
+ if (!IsEmptyStr(msg)) {
+ syslog(LOG_DEBUG, "db: %s", msg);
+ }
+}
+
+
+/* Verbose logging callback */
+void cdb_verbose_err(const DB_ENV * dbenv, const char *errpfx, const char *msg)
+{
+ syslog(LOG_ERR, "db: %s", msg);
+}
+
+
+/* wrapper for txn_abort() that logs/aborts on error */
+static void txabort(DB_TXN * tid)
+{
+ int ret;
+
+ ret = tid->abort(tid);
+
+ if (ret) {
+ syslog(LOG_ERR, "db: txn_abort: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+
+/* wrapper for txn_commit() that logs/aborts on error */
+static void txcommit(DB_TXN * tid)
+{
+ int ret;
+
+ ret = tid->commit(tid, 0);
+
+ if (ret) {
+ syslog(LOG_ERR, "db: txn_commit: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+
+/* wrapper for txn_begin() that logs/aborts on error */
+static void txbegin(DB_TXN ** tid)
+{
+ int ret;
+
+ ret = dbenv->txn_begin(dbenv, NULL, tid, 0);
+
+ if (ret) {
+ syslog(LOG_ERR, "db: txn_begin: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+
+/* panic callback */
+static void dbpanic(DB_ENV * env, int errval)
+{
+ syslog(LOG_ERR, "db: PANIC: %s", db_strerror(errval));
+}
+
+
+static void cclose(DBC * cursor)
+{
+ int ret;
+
+ if ((ret = cursor->c_close(cursor))) {
+ syslog(LOG_ERR, "db: c_close: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+
+static void bailIfCursor(DBC ** cursors, const char *msg)
+{
+ int i;
+
+ for (i = 0; i < MAXCDB; i++)
+ if (cursors[i] != NULL) {
+ syslog(LOG_ERR, "db: cursor still in progress on cdb %02x: %s", i, msg);
+ cdb_abort();
+ }
+}