Commit | Line | Data |
---|---|---|
0a49a7a4 | 1 | /* $Cambridge: exim/src/src/dbstuff.h,v 1.9 2009/11/16 19:50:36 nm4 Exp $ */ |
059ec3d9 PH |
2 | |
3 | /************************************************* | |
4 | * Exim - an Internet mail transport agent * | |
5 | *************************************************/ | |
6 | ||
0a49a7a4 | 7 | /* Copyright (c) University of Cambridge 1995 - 2009 */ |
059ec3d9 PH |
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), \ | |
19897d52 | 138 | ((*dbpp)->open)(*dbpp, NULL, CS name, NULL, \ |
059ec3d9 PH |
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), \ | |
19897d52 | 146 | ((*dbpp)->open)(*dbpp, CS name, NULL, \ |
059ec3d9 PH |
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 | ||
9ad41a42 TK |
303 | /* When scanning, for the non-first case we historically just passed 0 |
304 | as the flags field and it worked. On FreeBSD 8 it no longer works and | |
305 | instead leads to memory exhaustion. The man-page on FreeBSD says to use | |
306 | R_NEXT, but this 1.x is a historical fallback and I've no idea how portable | |
307 | the use of that flag is; so the solution is to define R_NEXT here if it's not | |
308 | already defined, with a default value of 0 because that's what we've always | |
309 | before been able to pass successfully. */ | |
310 | #ifndef R_NEXT | |
311 | #define R_NEXT 0 | |
312 | #endif | |
313 | ||
059ec3d9 PH |
314 | /* Access functions */ |
315 | ||
316 | /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */ | |
317 | #define EXIM_DBOPEN(name, flags, mode, dbpp) \ | |
318 | *(dbpp) = dbopen(CS name, flags, mode, DB_HASH, NULL) | |
319 | ||
320 | /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */ | |
321 | #define EXIM_DBGET(db, key, data) \ | |
322 | ((db)->get(db, &key, &data, 0) == 0) | |
323 | ||
324 | /* EXIM_DBPUT - returns nothing useful, assumes replace mode */ | |
325 | #define EXIM_DBPUT(db, key, data) \ | |
326 | (db)->put(db, &key, &data, 0) | |
327 | ||
328 | /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */ | |
329 | #define EXIM_DBPUTB(db, key, data) \ | |
330 | (db)->put(db, &key, &data, R_NOOVERWRITE) | |
331 | ||
332 | /* Returns from EXIM_DBPUTB */ | |
333 | ||
334 | #define EXIM_DBPUTB_OK 0 | |
335 | #define EXIM_DBPUTB_DUP 1 | |
336 | ||
337 | /* EXIM_DBDEL */ | |
338 | #define EXIM_DBDEL(db, key) (db)->del(db, &key, 0) | |
339 | ||
340 | /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */ | |
341 | #define EXIM_DBCREATE_CURSOR(db, cursor) {} | |
342 | ||
343 | /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */ | |
344 | #define EXIM_DBSCAN(db, key, data, first, cursor) \ | |
9ad41a42 | 345 | ((db)->seq(db, &key, &data, (first? R_FIRST : R_NEXT)) == 0) |
059ec3d9 PH |
346 | |
347 | /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it | |
348 | refer to cursor, to keep picky compilers happy. */ | |
349 | #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; } | |
350 | ||
351 | /* EXIM_DBCLOSE */ | |
352 | #define EXIM_DBCLOSE(db) (db)->close(db) | |
353 | ||
354 | /* Datum access types - these are intended to be assignable */ | |
355 | ||
356 | #define EXIM_DATUM_SIZE(datum) (datum).size | |
357 | #define EXIM_DATUM_DATA(datum) (datum).data | |
358 | ||
359 | /* There's no clearing required before use, and we don't have to free anything | |
360 | after reading data. */ | |
361 | ||
362 | #define EXIM_DATUM_INIT(datum) | |
363 | #define EXIM_DATUM_FREE(datum) | |
364 | ||
365 | #endif /* DB_VERSION_STRING */ | |
366 | ||
367 | ||
368 | ||
369 | /********************* gdbm interface definitions **********************/ | |
370 | ||
371 | #elif defined USE_GDBM | |
372 | ||
373 | #include <gdbm.h> | |
374 | ||
375 | /* Basic DB type */ | |
376 | typedef struct { | |
870f6ba8 TF |
377 | GDBM_FILE gdbm; /* Database */ |
378 | datum lkey; /* Last key, for scans */ | |
059ec3d9 PH |
379 | } EXIM_DB; |
380 | ||
381 | /* Cursor type, not used with gdbm: just set up a dummy */ | |
382 | #define EXIM_CURSOR int | |
383 | ||
384 | /* The datum type used for queries */ | |
385 | #define EXIM_DATUM datum | |
386 | ||
387 | /* Some text for messages */ | |
388 | ||
389 | #define EXIM_DBTYPE "gdbm" | |
390 | ||
391 | /* Access functions */ | |
392 | ||
393 | /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */ | |
394 | #define EXIM_DBOPEN(name, flags, mode, dbpp) \ | |
395 | { (*(dbpp)) = (EXIM_DB *) malloc(sizeof(EXIM_DB));\ | |
396 | if (*(dbpp) != NULL) { \ | |
397 | (*(dbpp))->lkey.dptr = NULL;\ | |
398 | (*(dbpp))->gdbm = gdbm_open(CS name, 0, (((flags) & O_CREAT))?GDBM_WRCREAT:(((flags) & (O_RDWR|O_WRONLY))?GDBM_WRITER:GDBM_READER), mode, 0);\ | |
399 | if ((*(dbpp))->gdbm == NULL) {\ | |
400 | free(*(dbpp));\ | |
401 | *(dbpp) = NULL;\ | |
402 | }\ | |
403 | }\ | |
404 | } | |
405 | ||
406 | /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */ | |
407 | #define EXIM_DBGET(db, key, data) \ | |
408 | (data = gdbm_fetch(db->gdbm, key), data.dptr != NULL) | |
409 | ||
410 | /* EXIM_DBPUT - returns nothing useful, assumes replace mode */ | |
411 | #define EXIM_DBPUT(db, key, data) \ | |
412 | gdbm_store(db->gdbm, key, data, GDBM_REPLACE) | |
413 | ||
414 | /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */ | |
415 | #define EXIM_DBPUTB(db, key, data) \ | |
416 | gdbm_store(db->gdbm, key, data, GDBM_INSERT) | |
417 | ||
418 | /* Returns from EXIM_DBPUTB */ | |
419 | ||
420 | #define EXIM_DBPUTB_OK 0 | |
421 | #define EXIM_DBPUTB_DUP 1 | |
422 | ||
423 | /* EXIM_DBDEL */ | |
424 | #define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key) | |
425 | ||
426 | /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */ | |
427 | #define EXIM_DBCREATE_CURSOR(db, cursor) {} | |
428 | ||
429 | /* EXIM_DBSCAN */ | |
430 | #define EXIM_DBSCAN(db, key, data, first, cursor) \ | |
431 | ( key = ((first)? gdbm_firstkey(db->gdbm) : gdbm_nextkey(db->gdbm, db->lkey)), \ | |
432 | (((db)->lkey.dptr != NULL)? (free((db)->lkey.dptr),1) : 1),\ | |
433 | db->lkey = key, key.dptr != NULL) | |
434 | ||
435 | /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it | |
436 | refer to cursor, to keep picky compilers happy. */ | |
437 | #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; } | |
438 | ||
439 | /* EXIM_DBCLOSE */ | |
440 | #define EXIM_DBCLOSE(db) \ | |
441 | { gdbm_close((db)->gdbm);\ | |
442 | if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\ | |
443 | free(db); } | |
444 | ||
445 | /* Datum access types - these are intended to be assignable */ | |
446 | ||
447 | #define EXIM_DATUM_SIZE(datum) (datum).dsize | |
448 | #define EXIM_DATUM_DATA(datum) (datum).dptr | |
449 | ||
450 | /* There's no clearing required before use, but we have to free the dptr | |
451 | after reading data. */ | |
452 | ||
453 | #define EXIM_DATUM_INIT(datum) | |
454 | #define EXIM_DATUM_FREE(datum) free(datum.dptr) | |
455 | ||
456 | #else /* USE_GDBM */ | |
457 | ||
458 | ||
459 | /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM | |
460 | interface */ | |
461 | ||
462 | ||
463 | /********************* ndbm interface definitions **********************/ | |
464 | ||
465 | #include <ndbm.h> | |
466 | ||
467 | /* Basic DB type */ | |
468 | #define EXIM_DB DBM | |
469 | ||
470 | /* Cursor type, not used with ndbm: just set up a dummy */ | |
471 | #define EXIM_CURSOR int | |
472 | ||
473 | /* The datum type used for queries */ | |
474 | #define EXIM_DATUM datum | |
475 | ||
476 | /* Some text for messages */ | |
477 | ||
478 | #define EXIM_DBTYPE "ndbm" | |
479 | ||
480 | /* Access functions */ | |
481 | ||
482 | /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */ | |
483 | #define EXIM_DBOPEN(name, flags, mode, dbpp) \ | |
484 | *(dbpp) = dbm_open(CS name, flags, mode) | |
485 | ||
486 | /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */ | |
487 | #define EXIM_DBGET(db, key, data) \ | |
488 | (data = dbm_fetch(db, key), data.dptr != NULL) | |
489 | ||
490 | /* EXIM_DBPUT - returns nothing useful, assumes replace mode */ | |
491 | #define EXIM_DBPUT(db, key, data) \ | |
492 | dbm_store(db, key, data, DBM_REPLACE) | |
493 | ||
494 | /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */ | |
495 | #define EXIM_DBPUTB(db, key, data) \ | |
496 | dbm_store(db, key, data, DBM_INSERT) | |
497 | ||
498 | /* Returns from EXIM_DBPUTB */ | |
499 | ||
500 | #define EXIM_DBPUTB_OK 0 | |
501 | #define EXIM_DBPUTB_DUP 1 | |
502 | ||
503 | /* EXIM_DBDEL */ | |
504 | #define EXIM_DBDEL(db, key) dbm_delete(db, key) | |
505 | ||
506 | /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */ | |
507 | #define EXIM_DBCREATE_CURSOR(db, cursor) {} | |
508 | ||
509 | /* EXIM_DBSCAN */ | |
510 | #define EXIM_DBSCAN(db, key, data, first, cursor) \ | |
511 | (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL) | |
512 | ||
513 | /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it | |
514 | refer to cursor, to keep picky compilers happy. */ | |
515 | #define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; } | |
516 | ||
517 | /* EXIM_DBCLOSE */ | |
518 | #define EXIM_DBCLOSE(db) dbm_close(db) | |
519 | ||
520 | /* Datum access types - these are intended to be assignable */ | |
521 | ||
522 | #define EXIM_DATUM_SIZE(datum) (datum).dsize | |
523 | #define EXIM_DATUM_DATA(datum) (datum).dptr | |
524 | ||
525 | /* There's no clearing required before use, and we don't have to free anything | |
526 | after reading data. */ | |
527 | ||
528 | #define EXIM_DATUM_INIT(datum) | |
529 | #define EXIM_DATUM_FREE(datum) | |
530 | ||
531 | #endif /* USE_GDBM */ | |
532 | ||
533 | /********************* End of dbm library definitions **********************/ | |
534 | ||
535 | ||
536 | /* Structure for carrying around an open DBM file, and an open locking file | |
537 | that relates to it. */ | |
538 | ||
539 | typedef struct { | |
540 | EXIM_DB *dbptr; | |
541 | int lockfd; | |
542 | } open_db; | |
543 | ||
544 | ||
545 | /* Structures for records stored in exim database dbm files. They all | |
546 | start with the same fields, described in the generic type. */ | |
547 | ||
548 | ||
549 | typedef struct { | |
550 | time_t time_stamp; /* Timestamp of writing */ | |
551 | } dbdata_generic; | |
552 | ||
553 | ||
554 | /* This structure keeps track of retry information for a host or a local | |
555 | address. */ | |
556 | ||
557 | typedef struct { | |
558 | time_t time_stamp; | |
559 | /*************/ | |
560 | time_t first_failed; /* Time of first failure */ | |
561 | time_t last_try; /* Time of last try */ | |
562 | time_t next_try; /* Time of next try */ | |
563 | BOOL expired; /* Retry time has expired */ | |
564 | int basic_errno; /* Errno of last failure */ | |
565 | int more_errno; /* Additional information */ | |
566 | uschar text[1]; /* Text message for last failure */ | |
567 | } dbdata_retry; | |
568 | ||
569 | /* These structures keep track of addresses that have had callout verification | |
570 | performed on them. There are two groups of records: | |
571 | ||
572 | 1. keyed by localpart@domain - | |
573 | Full address was tested and record holds result | |
574 | ||
575 | 2. keyed by domain - | |
576 | Domain response upto MAIL FROM:<>, postmaster, random local part; | |
577 | ||
2b1c6e3a PH |
578 | If a record exists, the result field is either ccache_accept or ccache_reject, |
579 | or, for a domain record only, ccache_reject_mfnull when MAIL FROM:<> was | |
580 | rejected. The other fields, however, (which are only relevant to domain | |
581 | records) may also contain ccache_unknown if that particular test has not been | |
582 | done. | |
059ec3d9 PH |
583 | |
584 | Originally, there was only one structure, used for both types. However, it got | |
585 | expanded for domain records, so it got split. To make it possible for Exim to | |
586 | handle the old type of record, we retain the old definition. The different | |
587 | kinds of record can be distinguised by their different lengths. */ | |
588 | ||
589 | typedef struct { | |
590 | time_t time_stamp; | |
591 | /*************/ | |
592 | int result; | |
593 | int postmaster_result; /* Postmaster is accepted */ | |
594 | int random_result; /* Random local part was accepted */ | |
595 | } dbdata_callout_cache_obs; | |
596 | ||
597 | typedef struct { | |
598 | time_t time_stamp; /* Timestamp of last address check */ | |
599 | /*************/ | |
600 | int result; /* accept or reject */ | |
601 | } dbdata_callout_cache_address; | |
602 | ||
603 | /* For this new layout, we put the additional fields (the timestamps) | |
604 | last so that if somebody reverts to an older Exim, the new records will | |
605 | still make sense because they match the old layout. */ | |
606 | ||
607 | typedef struct { | |
608 | time_t time_stamp; /* Time stamp of last connection */ | |
609 | /*************/ | |
610 | int result; /* Domain reject or accept */ | |
611 | int postmaster_result; /* Postmaster result */ | |
612 | int random_result; /* Random result */ | |
613 | time_t postmaster_stamp; /* Timestamp of postmaster check */ | |
614 | time_t random_stamp; /* Timestamp of random check */ | |
615 | } dbdata_callout_cache; | |
616 | ||
617 | /* This structure keeps track of messages that are waiting for a particular | |
618 | host for a particular transport. */ | |
619 | ||
620 | typedef struct { | |
621 | time_t time_stamp; | |
622 | /*************/ | |
623 | int count; /* Count of message ids */ | |
624 | int sequence; /* Sequence for continued records */ | |
625 | uschar text[1]; /* One long character string */ | |
626 | } dbdata_wait; | |
627 | ||
628 | ||
629 | /* The contents of the "misc" database are a mixture of different kinds of | |
630 | record, as defined below. The keys used for a specific type all start with a | |
631 | given string such as "etrn-" or "host-serialize-". */ | |
632 | ||
633 | ||
634 | /* This structure records a connection to a particular host, for the | |
635 | purpose of serializing access to certain hosts. For possible future extension, | |
636 | a field is defined for holding the count of connections, but it is not | |
637 | at present in use. The same structure is used for recording a running ETRN | |
638 | process. */ | |
639 | ||
640 | typedef struct { | |
641 | time_t time_stamp; | |
642 | /*************/ | |
643 | int count; /* Reserved for possible connection count */ | |
644 | } dbdata_serialize; | |
645 | ||
646 | ||
870f6ba8 TF |
647 | /* This structure records the information required for the ratelimit |
648 | ACL condition. */ | |
649 | ||
650 | typedef struct { | |
651 | time_t time_stamp; | |
652 | /*************/ | |
653 | int time_usec; /* Fractional part of time, from gettimeofday() */ | |
654 | double rate; /* Smoothed sending rate at that time */ | |
655 | } dbdata_ratelimit; | |
656 | ||
657 | ||
059ec3d9 | 658 | /* End of dbstuff.h */ |