1 /* $Cambridge: exim/src/src/dbstuff.h,v 1.7 2007/08/29 14:02:22 ph10 Exp $ */
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
7 /* Copyright (c) University of Cambridge 1995 - 2007 */
8 /* See the file NOTICE for conditions of use and distribution. */
10 /* This header file contains macro definitions so that a variety of DBM
11 libraries can be used by Exim. Nigel Metheringham provided the original set for
12 Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
13 2.x and 3.x were added. Later still, support for tdb was added, courtesy of
14 James Antill. Most recently, support for native mode gdbm was added, with code
15 from Pierre A. Humblet, so Exim could be made to work with Cygwin.
17 For convenience, the definitions of the structures used in the various hints
18 databases are also kept in this file, which is used by the maintenance
19 utilities as well as the main Exim binary. */
24 /* ************************* tdb interface ************************ */
29 #define EXIM_DB TDB_CONTEXT
31 /* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
32 tdb_traverse to be called) */
33 #define EXIM_CURSOR TDB_DATA
35 /* The datum type used for queries */
36 #define EXIM_DATUM TDB_DATA
38 /* Some text for messages */
39 #define EXIM_DBTYPE "tdb"
41 /* Access functions */
43 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
44 #define EXIM_DBOPEN(name, flags, mode, dbpp) \
45 *(dbpp) = tdb_open(CS name, 0, TDB_DEFAULT, flags, mode)
47 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
48 #define EXIM_DBGET(db, key, data) \
49 (data = tdb_fetch(db, key), data.dptr != NULL)
51 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
52 #define EXIM_DBPUT(db, key, data) \
53 tdb_store(db, key, data, TDB_REPLACE)
55 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
56 #define EXIM_DBPUTB(db, key, data) \
57 tdb_store(db, key, data, TDB_INSERT)
59 /* Returns from EXIM_DBPUTB */
61 #define EXIM_DBPUTB_OK 0
62 #define EXIM_DBPUTB_DUP (-1)
65 #define EXIM_DBDEL(db, key) tdb_delete(db, key)
67 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
68 #define EXIM_DBCREATE_CURSOR(db, cursor) { \
69 *(cursor) = malloc(sizeof(TDB_DATA)); (*(cursor))->dptr = NULL; }
71 /* EXIM_DBSCAN - This is complicated because we have to free the last datum
72 free() must not die when passed NULL */
73 #define EXIM_DBSCAN(db, key, data, first, cursor) \
74 (key = (first ? tdb_firstkey(db) : tdb_nextkey(db, *(cursor))), \
75 free((cursor)->dptr), *(cursor) = key, \
78 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
79 #define EXIM_DBDELETE_CURSOR(cursor) free(cursor)
82 #define EXIM_DBCLOSE(db) tdb_close(db)
84 /* Datum access types - these are intended to be assignable */
86 #define EXIM_DATUM_SIZE(datum) (datum).dsize
87 #define EXIM_DATUM_DATA(datum) (datum).dptr
89 /* Free the stuff inside the datum. */
91 #define EXIM_DATUM_FREE(datum) (free((datum).dptr), (datum).dptr = NULL)
93 /* No initialization is needed. */
95 #define EXIM_DATUM_INIT(datum)
99 /********************* Berkeley db native definitions **********************/
106 /* We can distinguish between versions 1.x and 2.x/3.x by looking for a
107 definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
109 #ifdef DB_VERSION_STRING
111 /* The API changed (again!) between the 2.x and 3.x versions */
113 #if DB_VERSION_MAJOR >= 3
115 /***************** Berkeley db 3.x/4.x native definitions ******************/
120 /* Cursor type, for scanning */
121 #define EXIM_CURSOR DBC
123 /* The datum type used for queries */
124 #define EXIM_DATUM DBT
126 /* Some text for messages */
127 #define EXIM_DBTYPE "db (v3/4)"
129 /* Access functions */
131 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. The
132 API changed for DB 4.1. */
134 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
135 #define EXIM_DBOPEN(name, flags, mode, dbpp) \
136 if (db_create(dbpp, NULL, 0) != 0 || \
137 ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
138 ((*dbpp)->open)(*dbpp, NULL, CS name, NULL, \
139 ((flags) == O_RDONLY)? DB_UNKNOWN : DB_HASH, \
140 ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
141 mode)) != 0) *(dbpp) = NULL
143 #define EXIM_DBOPEN(name, flags, mode, dbpp) \
144 if (db_create(dbpp, NULL, 0) != 0 || \
145 ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
146 ((*dbpp)->open)(*dbpp, CS name, NULL, \
147 ((flags) == O_RDONLY)? DB_UNKNOWN : DB_HASH, \
148 ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
149 mode)) != 0) *(dbpp) = NULL
152 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
153 #define EXIM_DBGET(db, key, data) \
154 ((db)->get(db, NULL, &key, &data, 0) == 0)
156 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
157 #define EXIM_DBPUT(db, key, data) \
158 (db)->put(db, NULL, &key, &data, 0)
160 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
161 #define EXIM_DBPUTB(db, key, data) \
162 (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
164 /* Return values from EXIM_DBPUTB */
166 #define EXIM_DBPUTB_OK 0
167 #define EXIM_DBPUTB_DUP DB_KEYEXIST
170 #define EXIM_DBDEL(db, key) (db)->del(db, NULL, &key, 0)
172 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
174 #define EXIM_DBCREATE_CURSOR(db, cursor) \
175 (db)->cursor(db, NULL, cursor, 0)
177 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
178 #define EXIM_DBSCAN(db, key, data, first, cursor) \
179 ((cursor)->c_get(cursor, &key, &data, \
180 (first? DB_FIRST : DB_NEXT)) == 0)
182 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
183 #define EXIM_DBDELETE_CURSOR(cursor) \
184 (cursor)->c_close(cursor)
187 #define EXIM_DBCLOSE(db) (db)->close(db, 0)
189 /* Datum access types - these are intended to be assignable. */
191 #define EXIM_DATUM_SIZE(datum) (datum).size
192 #define EXIM_DATUM_DATA(datum) (datum).data
194 /* The whole datum structure contains other fields that must be cleared
195 before use, but we don't have to free anything after reading data. */
197 #define EXIM_DATUM_INIT(datum) memset(&datum, 0, sizeof(datum))
198 #define EXIM_DATUM_FREE(datum)
201 #else /* DB_VERSION_MAJOR >= 3 */
203 /******************* Berkeley db 2.x native definitions ********************/
208 /* Cursor type, for scanning */
209 #define EXIM_CURSOR DBC
211 /* The datum type used for queries */
212 #define EXIM_DATUM DBT
214 /* Some text for messages */
215 #define EXIM_DBTYPE "db (v2)"
217 /* Access functions */
219 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
220 #define EXIM_DBOPEN(name, flags, mode, dbpp) \
221 if ((errno = db_open(CS name, DB_HASH, \
222 ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
223 mode, NULL, NULL, dbpp)) != 0) *(dbpp) = NULL
225 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
226 #define EXIM_DBGET(db, key, data) \
227 ((db)->get(db, NULL, &key, &data, 0) == 0)
229 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
230 #define EXIM_DBPUT(db, key, data) \
231 (db)->put(db, NULL, &key, &data, 0)
233 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
234 #define EXIM_DBPUTB(db, key, data) \
235 (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
237 /* Return values from EXIM_DBPUTB */
239 #define EXIM_DBPUTB_OK 0
240 #define EXIM_DBPUTB_DUP DB_KEYEXIST
243 #define EXIM_DBDEL(db, key) (db)->del(db, NULL, &key, 0)
245 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
247 /* The API of this function was changed between releases 2.4.14 and 2.7.3. I do
248 not know exactly where the change happened, but the Change Log for 2.5.9 lists
249 the new option that is available, so I guess that it happened at 2.5.x. */
251 #if DB_VERSION_MINOR >= 5
252 #define EXIM_DBCREATE_CURSOR(db, cursor) \
253 (db)->cursor(db, NULL, cursor, 0)
255 #define EXIM_DBCREATE_CURSOR(db, cursor) \
256 (db)->cursor(db, NULL, cursor)
259 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
260 #define EXIM_DBSCAN(db, key, data, first, cursor) \
261 ((cursor)->c_get(cursor, &key, &data, \
262 (first? DB_FIRST : DB_NEXT)) == 0)
264 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
265 #define EXIM_DBDELETE_CURSOR(cursor) \
266 (cursor)->c_close(cursor)
269 #define EXIM_DBCLOSE(db) (db)->close(db, 0)
271 /* Datum access types - these are intended to be assignable. */
273 #define EXIM_DATUM_SIZE(datum) (datum).size
274 #define EXIM_DATUM_DATA(datum) (datum).data
276 /* The whole datum structure contains other fields that must be cleared
277 before use, but we don't have to free anything after reading data. */
279 #define EXIM_DATUM_INIT(datum) memset(&datum, 0, sizeof(datum))
280 #define EXIM_DATUM_FREE(datum)
282 #endif /* DB_VERSION_MAJOR >= 3 */
285 /* If DB_VERSION_TYPE is not defined, we have version 1.x */
287 #else /* DB_VERSION_TYPE */
289 /******************* Berkeley db 1.x native definitions ********************/
294 /* Cursor type, not used with DB 1.x: just set up a dummy */
295 #define EXIM_CURSOR int
297 /* The datum type used for queries */
298 #define EXIM_DATUM DBT
300 /* Some text for messages */
301 #define EXIM_DBTYPE "db (v1)"
303 /* Access functions */
305 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
306 #define EXIM_DBOPEN(name, flags, mode, dbpp) \
307 *(dbpp) = dbopen(CS name, flags, mode, DB_HASH, NULL)
309 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
310 #define EXIM_DBGET(db, key, data) \
311 ((db)->get(db, &key, &data, 0) == 0)
313 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
314 #define EXIM_DBPUT(db, key, data) \
315 (db)->put(db, &key, &data, 0)
317 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
318 #define EXIM_DBPUTB(db, key, data) \
319 (db)->put(db, &key, &data, R_NOOVERWRITE)
321 /* Returns from EXIM_DBPUTB */
323 #define EXIM_DBPUTB_OK 0
324 #define EXIM_DBPUTB_DUP 1
327 #define EXIM_DBDEL(db, key) (db)->del(db, &key, 0)
329 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
330 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
332 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
333 #define EXIM_DBSCAN(db, key, data, first, cursor) \
334 ((db)->seq(db, &key, &data, (first? R_FIRST : 0)) == 0)
336 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
337 refer to cursor, to keep picky compilers happy. */
338 #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
341 #define EXIM_DBCLOSE(db) (db)->close(db)
343 /* Datum access types - these are intended to be assignable */
345 #define EXIM_DATUM_SIZE(datum) (datum).size
346 #define EXIM_DATUM_DATA(datum) (datum).data
348 /* There's no clearing required before use, and we don't have to free anything
349 after reading data. */
351 #define EXIM_DATUM_INIT(datum)
352 #define EXIM_DATUM_FREE(datum)
354 #endif /* DB_VERSION_STRING */
358 /********************* gdbm interface definitions **********************/
360 #elif defined USE_GDBM
366 GDBM_FILE gdbm; /* Database */
367 datum lkey; /* Last key, for scans */
370 /* Cursor type, not used with gdbm: just set up a dummy */
371 #define EXIM_CURSOR int
373 /* The datum type used for queries */
374 #define EXIM_DATUM datum
376 /* Some text for messages */
378 #define EXIM_DBTYPE "gdbm"
380 /* Access functions */
382 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
383 #define EXIM_DBOPEN(name, flags, mode, dbpp) \
384 { (*(dbpp)) = (EXIM_DB *) malloc(sizeof(EXIM_DB));\
385 if (*(dbpp) != NULL) { \
386 (*(dbpp))->lkey.dptr = NULL;\
387 (*(dbpp))->gdbm = gdbm_open(CS name, 0, (((flags) & O_CREAT))?GDBM_WRCREAT:(((flags) & (O_RDWR|O_WRONLY))?GDBM_WRITER:GDBM_READER), mode, 0);\
388 if ((*(dbpp))->gdbm == NULL) {\
395 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
396 #define EXIM_DBGET(db, key, data) \
397 (data = gdbm_fetch(db->gdbm, key), data.dptr != NULL)
399 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
400 #define EXIM_DBPUT(db, key, data) \
401 gdbm_store(db->gdbm, key, data, GDBM_REPLACE)
403 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
404 #define EXIM_DBPUTB(db, key, data) \
405 gdbm_store(db->gdbm, key, data, GDBM_INSERT)
407 /* Returns from EXIM_DBPUTB */
409 #define EXIM_DBPUTB_OK 0
410 #define EXIM_DBPUTB_DUP 1
413 #define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key)
415 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
416 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
419 #define EXIM_DBSCAN(db, key, data, first, cursor) \
420 ( key = ((first)? gdbm_firstkey(db->gdbm) : gdbm_nextkey(db->gdbm, db->lkey)), \
421 (((db)->lkey.dptr != NULL)? (free((db)->lkey.dptr),1) : 1),\
422 db->lkey = key, key.dptr != NULL)
424 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
425 refer to cursor, to keep picky compilers happy. */
426 #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
429 #define EXIM_DBCLOSE(db) \
430 { gdbm_close((db)->gdbm);\
431 if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\
434 /* Datum access types - these are intended to be assignable */
436 #define EXIM_DATUM_SIZE(datum) (datum).dsize
437 #define EXIM_DATUM_DATA(datum) (datum).dptr
439 /* There's no clearing required before use, but we have to free the dptr
440 after reading data. */
442 #define EXIM_DATUM_INIT(datum)
443 #define EXIM_DATUM_FREE(datum) free(datum.dptr)
448 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
452 /********************* ndbm interface definitions **********************/
459 /* Cursor type, not used with ndbm: just set up a dummy */
460 #define EXIM_CURSOR int
462 /* The datum type used for queries */
463 #define EXIM_DATUM datum
465 /* Some text for messages */
467 #define EXIM_DBTYPE "ndbm"
469 /* Access functions */
471 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
472 #define EXIM_DBOPEN(name, flags, mode, dbpp) \
473 *(dbpp) = dbm_open(CS name, flags, mode)
475 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
476 #define EXIM_DBGET(db, key, data) \
477 (data = dbm_fetch(db, key), data.dptr != NULL)
479 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
480 #define EXIM_DBPUT(db, key, data) \
481 dbm_store(db, key, data, DBM_REPLACE)
483 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
484 #define EXIM_DBPUTB(db, key, data) \
485 dbm_store(db, key, data, DBM_INSERT)
487 /* Returns from EXIM_DBPUTB */
489 #define EXIM_DBPUTB_OK 0
490 #define EXIM_DBPUTB_DUP 1
493 #define EXIM_DBDEL(db, key) dbm_delete(db, key)
495 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
496 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
499 #define EXIM_DBSCAN(db, key, data, first, cursor) \
500 (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL)
502 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
503 refer to cursor, to keep picky compilers happy. */
504 #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
507 #define EXIM_DBCLOSE(db) dbm_close(db)
509 /* Datum access types - these are intended to be assignable */
511 #define EXIM_DATUM_SIZE(datum) (datum).dsize
512 #define EXIM_DATUM_DATA(datum) (datum).dptr
514 /* There's no clearing required before use, and we don't have to free anything
515 after reading data. */
517 #define EXIM_DATUM_INIT(datum)
518 #define EXIM_DATUM_FREE(datum)
520 #endif /* USE_GDBM */
522 /********************* End of dbm library definitions **********************/
525 /* Structure for carrying around an open DBM file, and an open locking file
526 that relates to it. */
534 /* Structures for records stored in exim database dbm files. They all
535 start with the same fields, described in the generic type. */
539 time_t time_stamp; /* Timestamp of writing */
543 /* This structure keeps track of retry information for a host or a local
549 time_t first_failed; /* Time of first failure */
550 time_t last_try; /* Time of last try */
551 time_t next_try; /* Time of next try */
552 BOOL expired; /* Retry time has expired */
553 int basic_errno; /* Errno of last failure */
554 int more_errno; /* Additional information */
555 uschar text[1]; /* Text message for last failure */
558 /* These structures keep track of addresses that have had callout verification
559 performed on them. There are two groups of records:
561 1. keyed by localpart@domain -
562 Full address was tested and record holds result
565 Domain response upto MAIL FROM:<>, postmaster, random local part;
567 If a record exists, the result field is either ccache_accept or ccache_reject,
568 or, for a domain record only, ccache_reject_mfnull when MAIL FROM:<> was
569 rejected. The other fields, however, (which are only relevant to domain
570 records) may also contain ccache_unknown if that particular test has not been
573 Originally, there was only one structure, used for both types. However, it got
574 expanded for domain records, so it got split. To make it possible for Exim to
575 handle the old type of record, we retain the old definition. The different
576 kinds of record can be distinguised by their different lengths. */
582 int postmaster_result; /* Postmaster is accepted */
583 int random_result; /* Random local part was accepted */
584 } dbdata_callout_cache_obs;
587 time_t time_stamp; /* Timestamp of last address check */
589 int result; /* accept or reject */
590 } dbdata_callout_cache_address;
592 /* For this new layout, we put the additional fields (the timestamps)
593 last so that if somebody reverts to an older Exim, the new records will
594 still make sense because they match the old layout. */
597 time_t time_stamp; /* Time stamp of last connection */
599 int result; /* Domain reject or accept */
600 int postmaster_result; /* Postmaster result */
601 int random_result; /* Random result */
602 time_t postmaster_stamp; /* Timestamp of postmaster check */
603 time_t random_stamp; /* Timestamp of random check */
604 } dbdata_callout_cache;
606 /* This structure keeps track of messages that are waiting for a particular
607 host for a particular transport. */
612 int count; /* Count of message ids */
613 int sequence; /* Sequence for continued records */
614 uschar text[1]; /* One long character string */
618 /* The contents of the "misc" database are a mixture of different kinds of
619 record, as defined below. The keys used for a specific type all start with a
620 given string such as "etrn-" or "host-serialize-". */
623 /* This structure records a connection to a particular host, for the
624 purpose of serializing access to certain hosts. For possible future extension,
625 a field is defined for holding the count of connections, but it is not
626 at present in use. The same structure is used for recording a running ETRN
632 int count; /* Reserved for possible connection count */
636 /* This structure records the information required for the ratelimit
642 int time_usec; /* Fractional part of time, from gettimeofday() */
643 double rate; /* Smoothed sending rate at that time */
647 /* End of dbstuff.h */