A new wish about header modification handling in unseen routers.
[users/jgh/exim.git] / src / src / dbstuff.h
1 /* $Cambridge: exim/src/src/dbstuff.h,v 1.2 2005/01/04 10:00:42 ph10 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2005 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
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.
16
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. */
20
21
22 # ifdef USE_TDB
23
24 /* ************************* tdb interface ************************ */
25
26 #include <tdb.h>
27
28 /* Basic DB type */
29 #define EXIM_DB TDB_CONTEXT
30
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
34
35 /* The datum type used for queries */
36 #define EXIM_DATUM TDB_DATA
37
38 /* Some text for messages */
39 #define EXIM_DBTYPE "tdb"
40
41 /* Access functions */
42
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)
46
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)
50
51 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
52 #define EXIM_DBPUT(db, key, data)      \
53        tdb_store(db, key, data, TDB_REPLACE)
54
55 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
56 #define EXIM_DBPUTB(db, key, data)      \
57        tdb_store(db, key, data, TDB_INSERT)
58
59 /* Returns from EXIM_DBPUTB */
60
61 #define EXIM_DBPUTB_OK  0
62 #define EXIM_DBPUTB_DUP (-1)
63
64 /* EXIM_DBDEL */
65 #define EXIM_DBDEL(db, key) tdb_delete(db, key)
66
67 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
68 #define EXIM_DBCREATE_CURSOR(db, cursor) { \
69    *(cursor) = malloc(sizeof(TDB_DATA)); (*(cursor))->dptr = NULL; }
70
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, \
76         key.dptr != NULL)
77
78 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
79 #define EXIM_DBDELETE_CURSOR(cursor) free(cursor)
80
81 /* EXIM_DBCLOSE */
82 #define EXIM_DBCLOSE(db)        tdb_close(db)
83
84 /* Datum access types - these are intended to be assignable */
85
86 #define EXIM_DATUM_SIZE(datum)  (datum).dsize
87 #define EXIM_DATUM_DATA(datum)  (datum).dptr
88
89 /* Free the stuff inside the datum. */
90
91 #define EXIM_DATUM_FREE(datum)  (free((datum).dptr), (datum).dptr = NULL)
92
93 /* No initialization is needed. */
94
95 #define EXIM_DATUM_INIT(datum)
96
97
98
99 /********************* Berkeley db native definitions **********************/
100
101 #elif defined USE_DB
102
103 #include <db.h>
104
105
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. */
108
109 #ifdef DB_VERSION_STRING
110
111 /* The API changed (again!) between the 2.x and 3.x versions */
112
113 #if DB_VERSION_MAJOR >= 3
114
115 /***************** Berkeley db 3.x/4.x native definitions ******************/
116
117 /* Basic DB type */
118 #define EXIM_DB       DB
119
120 /* Cursor type, for scanning */
121 #define EXIM_CURSOR   DBC
122
123 /* The datum type used for queries */
124 #define EXIM_DATUM    DBT
125
126 /* Some text for messages */
127 #define EXIM_DBTYPE   "db (v3/4)"
128
129 /* Access functions */
130
131 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. The
132 API changed for DB 4.1. */
133
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
142 #else
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
150 #endif
151
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)
155
156 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
157 #define EXIM_DBPUT(db, key, data)      \
158        (db)->put(db, NULL, &key, &data, 0)
159
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)
163
164 /* Return values from EXIM_DBPUTB */
165
166 #define EXIM_DBPUTB_OK  0
167 #define EXIM_DBPUTB_DUP DB_KEYEXIST
168
169 /* EXIM_DBDEL */
170 #define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
171
172 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
173
174 #define EXIM_DBCREATE_CURSOR(db, cursor) \
175        (db)->cursor(db, NULL, cursor, 0)
176
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)
181
182 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
183 #define EXIM_DBDELETE_CURSOR(cursor) \
184        (cursor)->c_close(cursor)
185
186 /* EXIM_DBCLOSE */
187 #define EXIM_DBCLOSE(db)        (db)->close(db, 0)
188
189 /* Datum access types - these are intended to be assignable. */
190
191 #define EXIM_DATUM_SIZE(datum)  (datum).size
192 #define EXIM_DATUM_DATA(datum)  (datum).data
193
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. */
196
197 #define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
198 #define EXIM_DATUM_FREE(datum)
199
200
201 #else /* DB_VERSION_MAJOR >= 3 */
202
203 /******************* Berkeley db 2.x native definitions ********************/
204
205 /* Basic DB type */
206 #define EXIM_DB       DB
207
208 /* Cursor type, for scanning */
209 #define EXIM_CURSOR   DBC
210
211 /* The datum type used for queries */
212 #define EXIM_DATUM    DBT
213
214 /* Some text for messages */
215 #define EXIM_DBTYPE   "db (v2)"
216
217 /* Access functions */
218
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
224
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)
228
229 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
230 #define EXIM_DBPUT(db, key, data)      \
231        (db)->put(db, NULL, &key, &data, 0)
232
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)
236
237 /* Return values from EXIM_DBPUTB */
238
239 #define EXIM_DBPUTB_OK  0
240 #define EXIM_DBPUTB_DUP DB_KEYEXIST
241
242 /* EXIM_DBDEL */
243 #define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
244
245 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
246
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. */
250
251 #if DB_VERSION_MINOR >= 5
252 #define EXIM_DBCREATE_CURSOR(db, cursor) \
253        (db)->cursor(db, NULL, cursor, 0)
254 #else
255 #define EXIM_DBCREATE_CURSOR(db, cursor) \
256        (db)->cursor(db, NULL, cursor)
257 #endif
258
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)
263
264 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
265 #define EXIM_DBDELETE_CURSOR(cursor) \
266        (cursor)->c_close(cursor)
267
268 /* EXIM_DBCLOSE */
269 #define EXIM_DBCLOSE(db)        (db)->close(db, 0)
270
271 /* Datum access types - these are intended to be assignable. */
272
273 #define EXIM_DATUM_SIZE(datum)  (datum).size
274 #define EXIM_DATUM_DATA(datum)  (datum).data
275
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. */
278
279 #define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
280 #define EXIM_DATUM_FREE(datum)
281
282 #endif /* DB_VERSION_MAJOR >= 3 */
283
284
285 /* If DB_VERSION_TYPE is not defined, we have version 1.x */
286
287 #else  /* DB_VERSION_TYPE */
288
289 /******************* Berkeley db 1.x native definitions ********************/
290
291 /* Basic DB type */
292 #define EXIM_DB       DB
293
294 /* Cursor type, not used with DB 1.x: just set up a dummy */
295 #define EXIM_CURSOR   int
296
297 /* The datum type used for queries */
298 #define EXIM_DATUM    DBT
299
300 /* Some text for messages */
301 #define EXIM_DBTYPE   "db (v1)"
302
303 /* Access functions */
304
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)
308
309 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
310 #define EXIM_DBGET(db, key, data)      \
311        ((db)->get(db, &key, &data, 0) == 0)
312
313 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
314 #define EXIM_DBPUT(db, key, data)      \
315        (db)->put(db, &key, &data, 0)
316
317 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
318 #define EXIM_DBPUTB(db, key, data)      \
319        (db)->put(db, &key, &data, R_NOOVERWRITE)
320
321 /* Returns from EXIM_DBPUTB */
322
323 #define EXIM_DBPUTB_OK  0
324 #define EXIM_DBPUTB_DUP 1
325
326 /* EXIM_DBDEL */
327 #define EXIM_DBDEL(db, key)     (db)->del(db, &key, 0)
328
329 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
330 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
331
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)
335
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; }
339
340 /* EXIM_DBCLOSE */
341 #define EXIM_DBCLOSE(db)        (db)->close(db)
342
343 /* Datum access types - these are intended to be assignable */
344
345 #define EXIM_DATUM_SIZE(datum)  (datum).size
346 #define EXIM_DATUM_DATA(datum)  (datum).data
347
348 /* There's no clearing required before use, and we don't have to free anything
349 after reading data. */
350
351 #define EXIM_DATUM_INIT(datum)
352 #define EXIM_DATUM_FREE(datum)
353
354 #endif /* DB_VERSION_STRING */
355
356
357
358 /********************* gdbm interface definitions **********************/
359
360 #elif defined USE_GDBM
361
362 #include <gdbm.h>
363
364 /* Basic DB type */
365 typedef struct {
366        GDBM_FILE gdbm;  /* Database */
367        datum lkey;      /* Last key, for scans */
368 } EXIM_DB;
369
370 /* Cursor type, not used with gdbm: just set up a dummy */
371 #define EXIM_CURSOR int
372
373 /* The datum type used for queries */
374 #define EXIM_DATUM datum
375
376 /* Some text for messages */
377
378 #define EXIM_DBTYPE "gdbm"
379
380 /* Access functions */
381
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) {\
389               free(*(dbpp));\
390               *(dbpp) = NULL;\
391           }\
392        }\
393      }
394
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)
398
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)
402
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)
406
407 /* Returns from EXIM_DBPUTB */
408
409 #define EXIM_DBPUTB_OK  0
410 #define EXIM_DBPUTB_DUP 1
411
412 /* EXIM_DBDEL */
413 #define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key)
414
415 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
416 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
417
418 /* EXIM_DBSCAN */
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)
423
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; }
427
428 /* EXIM_DBCLOSE */
429 #define EXIM_DBCLOSE(db) \
430 { gdbm_close((db)->gdbm);\
431   if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\
432   free(db); }
433
434 /* Datum access types - these are intended to be assignable */
435
436 #define EXIM_DATUM_SIZE(datum) (datum).dsize
437 #define EXIM_DATUM_DATA(datum) (datum).dptr
438
439 /* There's no clearing required before use, but we have to free the dptr
440 after reading data. */
441
442 #define EXIM_DATUM_INIT(datum)
443 #define EXIM_DATUM_FREE(datum) free(datum.dptr)
444
445 #else  /* USE_GDBM */
446
447
448 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
449 interface */
450
451
452 /********************* ndbm interface definitions **********************/
453
454 #include <ndbm.h>
455
456 /* Basic DB type */
457 #define EXIM_DB DBM
458
459 /* Cursor type, not used with ndbm: just set up a dummy */
460 #define EXIM_CURSOR int
461
462 /* The datum type used for queries */
463 #define EXIM_DATUM datum
464
465 /* Some text for messages */
466
467 #define EXIM_DBTYPE "ndbm"
468
469 /* Access functions */
470
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)
474
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)
478
479 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
480 #define EXIM_DBPUT(db, key, data)      \
481        dbm_store(db, key, data, DBM_REPLACE)
482
483 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
484 #define EXIM_DBPUTB(db, key, data)      \
485        dbm_store(db, key, data, DBM_INSERT)
486
487 /* Returns from EXIM_DBPUTB */
488
489 #define EXIM_DBPUTB_OK  0
490 #define EXIM_DBPUTB_DUP 1
491
492 /* EXIM_DBDEL */
493 #define EXIM_DBDEL(db, key) dbm_delete(db, key)
494
495 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
496 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
497
498 /* EXIM_DBSCAN */
499 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
500        (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL)
501
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; }
505
506 /* EXIM_DBCLOSE */
507 #define EXIM_DBCLOSE(db) dbm_close(db)
508
509 /* Datum access types - these are intended to be assignable */
510
511 #define EXIM_DATUM_SIZE(datum) (datum).dsize
512 #define EXIM_DATUM_DATA(datum) (datum).dptr
513
514 /* There's no clearing required before use, and we don't have to free anything
515 after reading data. */
516
517 #define EXIM_DATUM_INIT(datum)
518 #define EXIM_DATUM_FREE(datum)
519
520 #endif /* USE_GDBM */
521
522 /********************* End of dbm library definitions **********************/
523
524
525 /* Structure for carrying around an open DBM file, and an open locking file
526 that relates to it. */
527
528 typedef struct {
529   EXIM_DB *dbptr;
530   int lockfd;
531 } open_db;
532
533
534 /* Structures for records stored in exim database dbm files. They all
535 start with the same fields, described in the generic type. */
536
537
538 typedef struct {
539   time_t time_stamp;      /* Timestamp of writing */
540 } dbdata_generic;
541
542
543 /* This structure keeps track of retry information for a host or a local
544 address. */
545
546 typedef struct {
547   time_t time_stamp;
548   /*************/
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 */
556 } dbdata_retry;
557
558 /* These structures keep track of addresses that have had callout verification
559 performed on them. There are two groups of records:
560
561 1. keyed by localpart@domain -
562      Full address was tested and record holds result
563
564 2. keyed by domain -
565      Domain response upto MAIL FROM:<>, postmaster, random local part;
566
567 If a record exists, the result field is either ccache_accept or ccache_reject.
568 The other fields, however, (which are only relevant to domain records) may also
569 contain ccache_unknown if that particular test has not been done.
570
571 Originally, there was only one structure, used for both types. However, it got
572 expanded for domain records, so it got split. To make it possible for Exim to
573 handle the old type of record, we retain the old definition. The different
574 kinds of record can be distinguised by their different lengths. */
575
576 typedef struct {
577   time_t time_stamp;
578   /*************/
579   int   result;
580   int   postmaster_result; /* Postmaster is accepted */
581   int   random_result;     /* Random local part was accepted */
582 } dbdata_callout_cache_obs;
583
584 typedef struct {
585   time_t time_stamp;       /* Timestamp of last address check */
586   /*************/
587   int   result;            /* accept or reject */
588 } dbdata_callout_cache_address;
589
590 /* For this new layout, we put the additional fields (the timestamps)
591 last so that if somebody reverts to an older Exim, the new records will
592 still make sense because they match the old layout. */
593
594 typedef struct {
595   time_t time_stamp;       /* Time stamp of last connection */
596   /*************/
597   int   result;            /* Domain reject or accept */
598   int   postmaster_result; /* Postmaster result */
599   int   random_result;     /* Random result */
600   time_t postmaster_stamp; /* Timestamp of postmaster check */
601   time_t random_stamp;     /* Timestamp of random check */
602 } dbdata_callout_cache;
603
604 /* This structure keeps track of messages that are waiting for a particular
605 host for a particular transport. */
606
607 typedef struct {
608   time_t time_stamp;
609   /*************/
610   int    count;           /* Count of message ids */
611   int    sequence;        /* Sequence for continued records */
612   uschar text[1];         /* One long character string */
613 } dbdata_wait;
614
615
616 /* The contents of the "misc" database are a mixture of different kinds of
617 record, as defined below. The keys used for a specific type all start with a
618 given string such as "etrn-" or "host-serialize-". */
619
620
621 /* This structure records a connection to a particular host, for the
622 purpose of serializing access to certain hosts. For possible future extension,
623 a field is defined for holding the count of connections, but it is not
624 at present in use. The same structure is used for recording a running ETRN
625 process. */
626
627 typedef struct {
628   time_t time_stamp;
629   /*************/
630   int    count;           /* Reserved for possible connection count */
631 } dbdata_serialize;
632
633
634 /* End of dbstuff.h */