a4ee603bb9cd45b66c090e935390409ba49fecc7
[exim.git] / src / src / dbstuff.h
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2009 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8 /* This header file contains macro definitions so that a variety of DBM
9 libraries can be used by Exim. Nigel Metheringham provided the original set for
10 Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
11 2.x and 3.x were added. Later still, support for tdb was added, courtesy of
12 James Antill. Most recently, support for native mode gdbm was added, with code
13 from Pierre A. Humblet, so Exim could be made to work with Cygwin.
14
15 For convenience, the definitions of the structures used in the various hints
16 databases are also kept in this file, which is used by the maintenance
17 utilities as well as the main Exim binary. */
18
19
20 # ifdef USE_TDB
21
22 /* ************************* tdb interface ************************ */
23
24 #include <tdb.h>
25
26 /* Basic DB type */
27 #define EXIM_DB TDB_CONTEXT
28
29 /* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
30 tdb_traverse to be called) */
31 #define EXIM_CURSOR TDB_DATA
32
33 /* The datum type used for queries */
34 #define EXIM_DATUM TDB_DATA
35
36 /* Some text for messages */
37 #define EXIM_DBTYPE "tdb"
38
39 /* Access functions */
40
41 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
42 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
43        *(dbpp) = tdb_open(CS name, 0, TDB_DEFAULT, flags, mode)
44
45 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
46 #define EXIM_DBGET(db, key, data)      \
47        (data = tdb_fetch(db, key), data.dptr != NULL)
48
49 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
50 #define EXIM_DBPUT(db, key, data)      \
51        tdb_store(db, key, data, TDB_REPLACE)
52
53 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
54 #define EXIM_DBPUTB(db, key, data)      \
55        tdb_store(db, key, data, TDB_INSERT)
56
57 /* Returns from EXIM_DBPUTB */
58
59 #define EXIM_DBPUTB_OK  0
60 #define EXIM_DBPUTB_DUP (-1)
61
62 /* EXIM_DBDEL */
63 #define EXIM_DBDEL(db, key) tdb_delete(db, key)
64
65 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
66 #define EXIM_DBCREATE_CURSOR(db, cursor) { \
67    *(cursor) = store_malloc(sizeof(TDB_DATA)); (*(cursor))->dptr = NULL; }
68
69 /* EXIM_DBSCAN - This is complicated because we have to free the last datum
70 free() must not die when passed NULL */
71 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
72        (key = (first ? tdb_firstkey(db) : tdb_nextkey(db, *(cursor))), \
73         free((cursor)->dptr), *(cursor) = key, \
74         key.dptr != NULL)
75
76 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
77 #define EXIM_DBDELETE_CURSOR(cursor) free(cursor)
78
79 /* EXIM_DBCLOSE */
80 #define EXIM_DBCLOSE__(db)        tdb_close(db)
81
82 /* Datum access types - these are intended to be assignable */
83
84 #define EXIM_DATUM_SIZE(datum)  (datum).dsize
85 #define EXIM_DATUM_DATA(datum)  (datum).dptr
86
87 /* Free the stuff inside the datum. */
88
89 #define EXIM_DATUM_FREE(datum)  (free((datum).dptr), (datum).dptr = NULL)
90
91 /* No initialization is needed. */
92
93 #define EXIM_DATUM_INIT(datum)
94
95
96
97 /********************* Berkeley db native definitions **********************/
98
99 #elif defined USE_DB
100
101 #include <db.h>
102
103
104 /* We can distinguish between versions 1.x and 2.x/3.x by looking for a
105 definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
106
107 #ifdef DB_VERSION_STRING
108
109 /* The API changed (again!) between the 2.x and 3.x versions */
110
111 #if DB_VERSION_MAJOR >= 3
112
113 /***************** Berkeley db 3.x/4.x native definitions ******************/
114
115 /* Basic DB type */
116 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
117 # define EXIM_DB       DB_ENV
118 /* Cursor type, for scanning */
119 #define EXIM_CURSOR   DBC
120
121 /* The datum type used for queries */
122 #define EXIM_DATUM    DBT
123
124 /* Some text for messages */
125 #define EXIM_DBTYPE   "db (v4.1+)"
126
127 /* Access functions */
128
129 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. The
130 API changed for DB 4.1. - and we also starting using the "env" with a
131 specified working dir, to avoid the DBCONFIG file trap. */
132
133 # define ENV_TO_DB(env) ((DB *)((env)->app_private))
134
135 # define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
136   if (  db_env_create(dbpp, 0) != 0                                             \
137      || ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), 0)               \
138      || (*dbpp)->open(*dbpp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0\
139      )                                                                          \
140     *dbpp = NULL;                                       \
141   else if (db_create((DB **) &((*dbpp)->app_private), *dbpp, 0) != 0)           \
142     {                                                   \
143     ((DB_ENV *)(*dbpp))->close((DB_ENV *)(*dbpp), 0);   \
144     *dbpp = NULL;                                       \
145     }                                                   \
146   else if (ENV_TO_DB(*dbpp)->open(ENV_TO_DB(*dbpp), NULL, CS name, NULL,        \
147               (flags) == O_RDONLY ? DB_UNKNOWN : DB_HASH,                       \
148               (flags) == O_RDONLY ? DB_RDONLY : DB_CREATE,                      \
149               mode) != 0                                                        \
150           )                                                                     \
151     {                                                   \
152     ENV_TO_DB(*dbpp)->close(ENV_TO_DB(*dbpp), 0);       \
153     ((DB_ENV *)(*dbpp))->close((DB_ENV *)(*dbpp), 0);   \
154     *dbpp = NULL;                                       \
155     }
156
157 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
158 # define EXIM_DBGET(db, key, data)      \
159        (ENV_TO_DB(db)->get(ENV_TO_DB(db), NULL, &key, &data, 0) == 0)
160
161 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
162 # define EXIM_DBPUT(db, key, data)      \
163        ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, 0)
164
165 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
166 # define EXIM_DBPUTB(db, key, data)      \
167        ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, DB_NOOVERWRITE)
168
169 /* Return values from EXIM_DBPUTB */
170
171 # define EXIM_DBPUTB_OK  0
172 # define EXIM_DBPUTB_DUP DB_KEYEXIST
173
174 /* EXIM_DBDEL */
175 # define EXIM_DBDEL(db, key)     ENV_TO_DB(db)->del(ENV_TO_DB(db), NULL, &key, 0)
176
177 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
178
179 # define EXIM_DBCREATE_CURSOR(db, cursor) \
180        ENV_TO_DB(db)->cursor(ENV_TO_DB(db), NULL, cursor, 0)
181
182 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
183 # define EXIM_DBSCAN(db, key, data, first, cursor)      \
184        ((cursor)->c_get(cursor, &key, &data,         \
185          (first? DB_FIRST : DB_NEXT)) == 0)
186
187 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
188 # define EXIM_DBDELETE_CURSOR(cursor) \
189        (cursor)->c_close(cursor)
190
191 /* EXIM_DBCLOSE */
192 # define EXIM_DBCLOSE__(db) \
193         (ENV_TO_DB(db)->close(ENV_TO_DB(db), 0) , ((DB_ENV *)(db))->close((DB_ENV *)(db), DB_FORCESYNC))
194
195 /* Datum access types - these are intended to be assignable. */
196
197 # define EXIM_DATUM_SIZE(datum)  (datum).size
198 # define EXIM_DATUM_DATA(datum)  (datum).data
199
200 /* The whole datum structure contains other fields that must be cleared
201 before use, but we don't have to free anything after reading data. */
202
203 # define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
204 # define EXIM_DATUM_FREE(datum)
205
206 #else   /* pre- 4.1 */
207
208 # define EXIM_DB       DB
209
210 /* Cursor type, for scanning */
211 # define EXIM_CURSOR   DBC
212
213 /* The datum type used for queries */
214 # define EXIM_DATUM    DBT
215
216 /* Some text for messages */
217 # define EXIM_DBTYPE   "db (v3/4)"
218
219 /* Access functions */
220
221 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. */
222
223 # define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
224        if (db_create(dbpp, NULL, 0) != 0 || \
225          ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
226          ((*dbpp)->open)(*dbpp, CS name, NULL, \
227          ((flags) == O_RDONLY)? DB_UNKNOWN : DB_HASH, \
228          ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
229          mode)) != 0) *(dbpp) = NULL
230
231 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
232 # define EXIM_DBGET(db, key, data)      \
233        ((db)->get(db, NULL, &key, &data, 0) == 0)
234
235 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
236 # define EXIM_DBPUT(db, key, data)      \
237        (db)->put(db, NULL, &key, &data, 0)
238
239 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
240 # define EXIM_DBPUTB(db, key, data)      \
241        (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
242
243 /* Return values from EXIM_DBPUTB */
244
245 # define EXIM_DBPUTB_OK  0
246 # define EXIM_DBPUTB_DUP DB_KEYEXIST
247
248 /* EXIM_DBDEL */
249 # define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
250
251 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
252
253 # define EXIM_DBCREATE_CURSOR(db, cursor) \
254        (db)->cursor(db, NULL, cursor, 0)
255
256 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
257 # define EXIM_DBSCAN(db, key, data, first, cursor)      \
258        ((cursor)->c_get(cursor, &key, &data,         \
259          (first? DB_FIRST : DB_NEXT)) == 0)
260
261 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
262 # define EXIM_DBDELETE_CURSOR(cursor) \
263        (cursor)->c_close(cursor)
264
265 /* EXIM_DBCLOSE */
266 # define EXIM_DBCLOSE__(db)        (db)->close(db, 0)
267
268 /* Datum access types - these are intended to be assignable. */
269
270 # define EXIM_DATUM_SIZE(datum)  (datum).size
271 # define EXIM_DATUM_DATA(datum)  (datum).data
272
273 /* The whole datum structure contains other fields that must be cleared
274 before use, but we don't have to free anything after reading data. */
275
276 # define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
277 # define EXIM_DATUM_FREE(datum)
278
279 #endif
280
281
282 #else /* DB_VERSION_MAJOR >= 3 */
283
284 /******************* Berkeley db 2.x native definitions ********************/
285
286 /* Basic DB type */
287 #define EXIM_DB       DB
288
289 /* Cursor type, for scanning */
290 #define EXIM_CURSOR   DBC
291
292 /* The datum type used for queries */
293 #define EXIM_DATUM    DBT
294
295 /* Some text for messages */
296 #define EXIM_DBTYPE   "db (v2)"
297
298 /* Access functions */
299
300 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
301 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp)         \
302        if ((errno = db_open(CS name, DB_HASH,           \
303          ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
304          mode, NULL, NULL, dbpp)) != 0) *(dbpp) = NULL
305
306 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
307 #define EXIM_DBGET(db, key, data)      \
308        ((db)->get(db, NULL, &key, &data, 0) == 0)
309
310 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
311 #define EXIM_DBPUT(db, key, data)      \
312        (db)->put(db, NULL, &key, &data, 0)
313
314 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
315 #define EXIM_DBPUTB(db, key, data)      \
316        (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
317
318 /* Return values from EXIM_DBPUTB */
319
320 #define EXIM_DBPUTB_OK  0
321 #define EXIM_DBPUTB_DUP DB_KEYEXIST
322
323 /* EXIM_DBDEL */
324 #define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
325
326 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
327
328 /* The API of this function was changed between releases 2.4.14 and 2.7.3. I do
329 not know exactly where the change happened, but the Change Log for 2.5.9 lists
330 the new option that is available, so I guess that it happened at 2.5.x. */
331
332 #if DB_VERSION_MINOR >= 5
333 #define EXIM_DBCREATE_CURSOR(db, cursor) \
334        (db)->cursor(db, NULL, cursor, 0)
335 #else
336 #define EXIM_DBCREATE_CURSOR(db, cursor) \
337        (db)->cursor(db, NULL, cursor)
338 #endif
339
340 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
341 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
342        ((cursor)->c_get(cursor, &key, &data,         \
343          (first? DB_FIRST : DB_NEXT)) == 0)
344
345 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
346 #define EXIM_DBDELETE_CURSOR(cursor) \
347        (cursor)->c_close(cursor)
348
349 /* EXIM_DBCLOSE */
350 #define EXIM_DBCLOSE__(db)        (db)->close(db, 0)
351
352 /* Datum access types - these are intended to be assignable. */
353
354 #define EXIM_DATUM_SIZE(datum)  (datum).size
355 #define EXIM_DATUM_DATA(datum)  (datum).data
356
357 /* The whole datum structure contains other fields that must be cleared
358 before use, but we don't have to free anything after reading data. */
359
360 #define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
361 #define EXIM_DATUM_FREE(datum)
362
363 #endif /* DB_VERSION_MAJOR >= 3 */
364
365
366 /* If DB_VERSION_TYPE is not defined, we have version 1.x */
367
368 #else  /* DB_VERSION_TYPE */
369
370 /******************* Berkeley db 1.x native definitions ********************/
371
372 /* Basic DB type */
373 #define EXIM_DB       DB
374
375 /* Cursor type, not used with DB 1.x: just set up a dummy */
376 #define EXIM_CURSOR   int
377
378 /* The datum type used for queries */
379 #define EXIM_DATUM    DBT
380
381 /* Some text for messages */
382 #define EXIM_DBTYPE   "db (v1)"
383
384 /* When scanning, for the non-first case we historically just passed 0
385 as the flags field and it worked.  On FreeBSD 8 it no longer works and
386 instead leads to memory exhaustion.  The man-page on FreeBSD says to use
387 R_NEXT, but this 1.x is a historical fallback and I've no idea how portable
388 the use of that flag is; so the solution is to define R_NEXT here if it's not
389 already defined, with a default value of 0 because that's what we've always
390 before been able to pass successfully. */
391 #ifndef R_NEXT
392 #define R_NEXT 0
393 #endif
394
395 /* Access functions */
396
397 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
398 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
399        *(dbpp) = dbopen(CS name, flags, mode, DB_HASH, NULL)
400
401 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
402 #define EXIM_DBGET(db, key, data)      \
403        ((db)->get(db, &key, &data, 0) == 0)
404
405 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
406 #define EXIM_DBPUT(db, key, data)      \
407        (db)->put(db, &key, &data, 0)
408
409 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
410 #define EXIM_DBPUTB(db, key, data)      \
411        (db)->put(db, &key, &data, R_NOOVERWRITE)
412
413 /* Returns from EXIM_DBPUTB */
414
415 #define EXIM_DBPUTB_OK  0
416 #define EXIM_DBPUTB_DUP 1
417
418 /* EXIM_DBDEL */
419 #define EXIM_DBDEL(db, key)     (db)->del(db, &key, 0)
420
421 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
422 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
423
424 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
425 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
426        ((db)->seq(db, &key, &data, (first? R_FIRST : R_NEXT)) == 0)
427
428 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
429 refer to cursor, to keep picky compilers happy. */
430 #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
431
432 /* EXIM_DBCLOSE */
433 #define EXIM_DBCLOSE__(db)        (db)->close(db)
434
435 /* Datum access types - these are intended to be assignable */
436
437 #define EXIM_DATUM_SIZE(datum)  (datum).size
438 #define EXIM_DATUM_DATA(datum)  (datum).data
439
440 /* There's no clearing required before use, and we don't have to free anything
441 after reading data. */
442
443 #define EXIM_DATUM_INIT(datum)
444 #define EXIM_DATUM_FREE(datum)
445
446 #endif /* DB_VERSION_STRING */
447
448
449
450 /********************* gdbm interface definitions **********************/
451
452 #elif defined USE_GDBM
453
454 #include <gdbm.h>
455
456 /* Basic DB type */
457 typedef struct {
458        GDBM_FILE gdbm;  /* Database */
459        datum lkey;      /* Last key, for scans */
460 } EXIM_DB;
461
462 /* Cursor type, not used with gdbm: just set up a dummy */
463 #define EXIM_CURSOR int
464
465 /* The datum type used for queries */
466 #define EXIM_DATUM datum
467
468 /* Some text for messages */
469
470 #define EXIM_DBTYPE "gdbm"
471
472 /* Access functions */
473
474 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
475 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
476      { (*(dbpp)) = (EXIM_DB *) malloc(sizeof(EXIM_DB));\
477        if (*(dbpp) != NULL) { \
478          (*(dbpp))->lkey.dptr = NULL;\
479          (*(dbpp))->gdbm = gdbm_open(CS name, 0, (((flags) & O_CREAT))?GDBM_WRCREAT:(((flags) & (O_RDWR|O_WRONLY))?GDBM_WRITER:GDBM_READER), mode, 0);\
480           if ((*(dbpp))->gdbm == NULL) {\
481               free(*(dbpp));\
482               *(dbpp) = NULL;\
483           }\
484        }\
485      }
486
487 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
488 #define EXIM_DBGET(db, key, data)      \
489        (data = gdbm_fetch(db->gdbm, key), data.dptr != NULL)
490
491 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
492 #define EXIM_DBPUT(db, key, data)      \
493        gdbm_store(db->gdbm, key, data, GDBM_REPLACE)
494
495 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
496 #define EXIM_DBPUTB(db, key, data)      \
497        gdbm_store(db->gdbm, key, data, GDBM_INSERT)
498
499 /* Returns from EXIM_DBPUTB */
500
501 #define EXIM_DBPUTB_OK  0
502 #define EXIM_DBPUTB_DUP 1
503
504 /* EXIM_DBDEL */
505 #define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key)
506
507 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
508 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
509
510 /* EXIM_DBSCAN */
511 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
512   ( key = ((first)? gdbm_firstkey(db->gdbm) : gdbm_nextkey(db->gdbm, db->lkey)), \
513     (((db)->lkey.dptr != NULL)? (free((db)->lkey.dptr),1) : 1),\
514     db->lkey = key, key.dptr != NULL)
515
516 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
517 refer to cursor, to keep picky compilers happy. */
518 #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
519
520 /* EXIM_DBCLOSE */
521 #define EXIM_DBCLOSE__(db) \
522 { gdbm_close((db)->gdbm);\
523   if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\
524   free(db); }
525
526 /* Datum access types - these are intended to be assignable */
527
528 #define EXIM_DATUM_SIZE(datum) (datum).dsize
529 #define EXIM_DATUM_DATA(datum) (datum).dptr
530
531 /* There's no clearing required before use, but we have to free the dptr
532 after reading data. */
533
534 #define EXIM_DATUM_INIT(datum)
535 #define EXIM_DATUM_FREE(datum) free(datum.dptr)
536
537 #else  /* USE_GDBM */
538
539
540 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
541 interface */
542
543
544 /********************* ndbm interface definitions **********************/
545
546 #include <ndbm.h>
547
548 /* Basic DB type */
549 #define EXIM_DB DBM
550
551 /* Cursor type, not used with ndbm: just set up a dummy */
552 #define EXIM_CURSOR int
553
554 /* The datum type used for queries */
555 #define EXIM_DATUM datum
556
557 /* Some text for messages */
558
559 #define EXIM_DBTYPE "ndbm"
560
561 /* Access functions */
562
563 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
564 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
565        *(dbpp) = dbm_open(CS name, flags, mode)
566
567 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
568 #define EXIM_DBGET(db, key, data)      \
569        (data = dbm_fetch(db, key), data.dptr != NULL)
570
571 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
572 #define EXIM_DBPUT(db, key, data)      \
573        dbm_store(db, key, data, DBM_REPLACE)
574
575 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
576 #define EXIM_DBPUTB(db, key, data)      \
577        dbm_store(db, key, data, DBM_INSERT)
578
579 /* Returns from EXIM_DBPUTB */
580
581 #define EXIM_DBPUTB_OK  0
582 #define EXIM_DBPUTB_DUP 1
583
584 /* EXIM_DBDEL */
585 #define EXIM_DBDEL(db, key) dbm_delete(db, key)
586
587 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
588 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
589
590 /* EXIM_DBSCAN */
591 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
592        (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL)
593
594 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
595 refer to cursor, to keep picky compilers happy. */
596 #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
597
598 /* EXIM_DBCLOSE */
599 #define EXIM_DBCLOSE__(db) dbm_close(db)
600
601 /* Datum access types - these are intended to be assignable */
602
603 #define EXIM_DATUM_SIZE(datum) (datum).dsize
604 #define EXIM_DATUM_DATA(datum) (datum).dptr
605
606 /* There's no clearing required before use, and we don't have to free anything
607 after reading data. */
608
609 #define EXIM_DATUM_INIT(datum)
610 #define EXIM_DATUM_FREE(datum)
611
612 #endif /* USE_GDBM */
613
614
615
616
617
618 # ifdef COMPILE_UTILITY
619
620 #  define EXIM_DBOPEN(name, dirname, flags, mode, dbpp) \
621   EXIM_DBOPEN__(name, dirname, flags, mode, dbpp)
622 #  define EXIM_DBCLOSE(db) EXIM_DBCLOSE__(db)
623
624 # else
625
626 #  define EXIM_DBOPEN(name, dirname, flags, mode, dbpp) \
627   do { \
628   DEBUG(D_hints_lookup) \
629     debug_printf("EXIM_DBOPEN: file <%s> dir <%s> flags 0x%x\n", \
630       (name), (dirname), flags); \
631   EXIM_DBOPEN__(name, dirname, flags, mode, dbpp); \
632   DEBUG(D_hints_lookup) debug_printf("returned from EXIM_DBOPEN: %p\n", *dbpp); \
633   } while(0)
634 #  define EXIM_DBCLOSE(db) \
635   do { \
636   DEBUG(D_hints_lookup) debug_printf("EXIM_DBCLOSE(%p)\n", db); \
637   EXIM_DBCLOSE__(db); \
638   } while(0)
639
640 #  endif
641
642 /********************* End of dbm library definitions **********************/
643
644
645 /* Structure for carrying around an open DBM file, and an open locking file
646 that relates to it. */
647
648 typedef struct {
649   EXIM_DB *dbptr;
650   int lockfd;
651 } open_db;
652
653
654 /* Structures for records stored in exim database dbm files. They all
655 start with the same fields, described in the generic type. */
656
657
658 typedef struct {
659   time_t time_stamp;      /* Timestamp of writing */
660 } dbdata_generic;
661
662
663 /* This structure keeps track of retry information for a host or a local
664 address. */
665
666 typedef struct {
667   time_t time_stamp;
668   /*************/
669   time_t first_failed;    /* Time of first failure */
670   time_t last_try;        /* Time of last try */
671   time_t next_try;        /* Time of next try */
672   BOOL   expired;         /* Retry time has expired */
673   int    basic_errno;     /* Errno of last failure */
674   int    more_errno;      /* Additional information */
675   uschar text[1];         /* Text message for last failure */
676 } dbdata_retry;
677
678 /* These structures keep track of addresses that have had callout verification
679 performed on them. There are two groups of records:
680
681 1. keyed by localpart@domain -
682      Full address was tested and record holds result
683
684 2. keyed by domain -
685      Domain response upto MAIL FROM:<>, postmaster, random local part;
686
687 If a record exists, the result field is either ccache_accept or ccache_reject,
688 or, for a domain record only, ccache_reject_mfnull when MAIL FROM:<> was
689 rejected. The other fields, however, (which are only relevant to domain
690 records) may also contain ccache_unknown if that particular test has not been
691 done.
692
693 Originally, there was only one structure, used for both types. However, it got
694 expanded for domain records, so it got split. To make it possible for Exim to
695 handle the old type of record, we retain the old definition. The different
696 kinds of record can be distinguished by their different lengths. */
697
698 typedef struct {
699   time_t time_stamp;
700   /*************/
701   int   result;
702   int   postmaster_result; /* Postmaster is accepted */
703   int   random_result;     /* Random local part was accepted */
704 } dbdata_callout_cache_obs;
705
706 typedef struct {
707   time_t time_stamp;       /* Timestamp of last address check */
708   /*************/
709   int   result;            /* accept or reject */
710 } dbdata_callout_cache_address;
711
712 /* For this new layout, we put the additional fields (the timestamps)
713 last so that if somebody reverts to an older Exim, the new records will
714 still make sense because they match the old layout. */
715
716 typedef struct {
717   time_t time_stamp;       /* Time stamp of last connection */
718   /*************/
719   int   result;            /* Domain reject or accept */
720   int   postmaster_result; /* Postmaster result */
721   int   random_result;     /* Random result */
722   time_t postmaster_stamp; /* Timestamp of postmaster check */
723   time_t random_stamp;     /* Timestamp of random check */
724 } dbdata_callout_cache;
725
726 /* This structure keeps track of messages that are waiting for a particular
727 host for a particular transport. */
728
729 typedef struct {
730   time_t time_stamp;
731   /*************/
732   int    count;           /* Count of message ids */
733   int    sequence;        /* Sequence for continued records */
734   uschar text[1];         /* One long character string */
735 } dbdata_wait;
736
737
738 /* The contents of the "misc" database are a mixture of different kinds of
739 record, as defined below. The keys used for a specific type all start with a
740 given string such as "etrn-" or "host-serialize-". */
741
742
743 /* This structure records a connection to a particular host, for the
744 purpose of serializing access to certain hosts. For possible future extension,
745 a field is defined for holding the count of connections, but it is not
746 at present in use. The same structure is used for recording a running ETRN
747 process. */
748
749 typedef struct {
750   time_t time_stamp;
751   /*************/
752   int    count;           /* Reserved for possible connection count */
753 } dbdata_serialize;
754
755
756 /* This structure records the information required for the ratelimit
757 ACL condition. */
758
759 typedef struct {
760   time_t time_stamp;
761   /*************/
762   int    time_usec;       /* Fractional part of time, from gettimeofday() */
763   double rate;            /* Smoothed sending rate at that time */
764 } dbdata_ratelimit;
765
766 /* Same as above, plus a Bloom filter for uniquifying events. */
767
768 typedef struct {
769   dbdata_ratelimit dbd;
770   time_t   bloom_epoch;   /* When the Bloom filter was last reset */
771   unsigned bloom_size;    /* Number of bytes in the Bloom filter */
772   uschar   bloom[40];     /* Bloom filter which may be larger than this */
773 } dbdata_ratelimit_unique;
774
775
776 /* End of dbstuff.h */