[Exim] Using native gdbm

Top Page
Delete this message
Reply to this message
Author: Pierre A. Humblet
Date:  
To: exim-users
Subject: [Exim] Using native gdbm
I am trying to port Exim to Cygwin, a Unix emulation layer
running of top of Windows on ordinary PCs. I have seen the
recent mails from Gerrit Haase but have separate issues.

In particular ndbm emulation under gdbm does not work on FAT
partitions (Win95, 98 and Me). I have thus modified dbfn.h to
use native gdbm. It works (as far as test_dbfn can tell) and a
diff file is attached. Perhaps native gdbm support could be
made part of the standard distribution.

By the way, the time, scan and delete commands are missing from the
help output in test_dbfn.

Pierre
--- dbfn.h.org    Wed Aug 15 07:09:08 2001
+++ dbfn.h    Sun Dec  2 22:16:00 2001
@@ -343,9 +343,95 @@
 #define EXIM_DATUM_FREE(datum)


#endif /* DB_VERSION_STRING */
-#else /* USE_DB */

-/* If neither USE_DB nor USE_TDB is set, the default is the NDBM interface */
+/********************* gdbm interface definitions **********************/
+#elif defined USE_GDBM
+#include <gdbm.h>
+
+/* Basic DB type */
+typedef struct {
+    GDBM_FILE gdbm; /* Database */
+    datum lkey;     /* Last key, for scans */
+} EXIM_DB;
+
+/* Cursor type, not used with gdbm: just set up a dummy */
+#define EXIM_CURSOR int
+
+/* The datum type used for queries */
+#define EXIM_DATUM datum
+
+/* Some text for messages */
+
+#define EXIM_DBTYPE "gdbm"
+
+/* Access functions */
+
+/* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
+#define EXIM_DBOPEN(name, flags, mode, dbpp) \
+     { (*(dbpp)) = (EXIM_DB *) malloc(sizeof(EXIM_DB));\
+       if (*(dbpp) != NULL) { \
+         (*(dbpp))->lkey.dptr = NULL;\
+         (*(dbpp))->gdbm = gdbm_open(name, 0, (((flags) & O_CREAT))?GDBM_WRCREAT:(((flags) & (O_RDWR|O_WRONLY))?GDBM_WRITER:GDBM_READER), mode, 0);\
+          if ((*(dbpp))->gdbm == NULL) {\
+              free(*(dbpp));\
+              *(dbpp) = NULL;\
+          }\
+       }\
+     }
+
+/* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
+#define EXIM_DBGET(db, key, data)      \
+       (data = gdbm_fetch(db->gdbm, key), data.dptr != NULL)
+
+/* EXIM_DBPUT - returns nothing useful, assumes replace mode */
+#define EXIM_DBPUT(db, key, data)      \
+       gdbm_store(db->gdbm, key, data, GDBM_REPLACE)
+
+/* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
+#define EXIM_DBPUTB(db, key, data)      \
+       gdbm_store(db->gdbm, key, data, GDBM_INSERT)
+
+/* Returns from EXIM_DBPUTB */
+
+#define EXIM_DBPUTB_OK  0
+#define EXIM_DBPUTB_DUP 1
+
+/* EXIM_DBDEL */
+#define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key)
+
+/* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
+#define EXIM_DBCREATE_CURSOR(db, cursor) {}
+
+/* EXIM_DBSCAN */
+#define EXIM_DBSCAN(db, key, data, first, cursor)      \
+  ( key = ((first)? gdbm_firstkey(db->gdbm) : gdbm_nextkey(db->gdbm, db->lkey)), \
+    (((db)->lkey.dptr != NULL)? free((db)->lkey.dptr):1),\
+    db->lkey = key, key.dptr != NULL)
+
+/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
+refer to cursor, to keep picky compilers happy. */
+#define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
+
+/* EXIM_DBCLOSE */
+#define EXIM_DBCLOSE(db) \
+{ gdbm_close(db->gdbm);\
+  if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\
+  free(db); }
+
+/* Datum access types - these are intended to be assignable */
+
+#define EXIM_DATUM_SIZE(datum) (datum).dsize
+#define EXIM_DATUM_DATA(datum) (datum).dptr
+
+/* There's no clearing required before use, but we have to free the dptr
+after reading data. */
+
+#define EXIM_DATUM_INIT(datum)
+#define EXIM_DATUM_FREE(datum) free(datum.dptr)
+
+
+#else
+/* If neither USE_DB nor USE_TDB nor USE_GDBM is set, the default is the NDBM interface */



/********************* ndbm interface definitions **********************/