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