Hints DB interface: convert from macros to inlinable functions.
[exim.git] / src / src / hintsdb.h
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
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
10 libraries can be used by Exim. Nigel Metheringham provided the original set for
11 Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
12 2.x and 3.x were added. Later still, support for tdb was added, courtesy of
13 James Antill. Most recently, support for native mode gdbm was added, with code
14 from Pierre A. Humblet, so Exim could be made to work with Cygwin.
15
16 For convenience, the definitions of the structures used in the various hints
17 databases are also kept in this file, which is used by the maintenance
18 utilities as well as the main Exim binary. */
19
20 #ifndef HINTSDB_H
21 #define HINTSDB_H
22
23
24 #if defined(USE_TDB)
25
26 /* ************************* tdb interface ************************ */
27 /*XXX https://manpages.org/tdb/3 mentions concurrent writes.
28 Could we lose the file lock? */
29
30 # include <tdb.h>
31
32 /* Basic DB type */
33 # define EXIM_DB TDB_CONTEXT
34
35 /* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
36 tdb_traverse to be called) */
37 # define EXIM_CURSOR TDB_DATA
38
39 /* The datum type used for queries */
40 # define EXIM_DATUM TDB_DATA
41
42 /* Some text for messages */
43 # define EXIM_DBTYPE "tdb"
44
45 /* Access functions */
46
47 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
48 static EXIM_DB *
49 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
50   unsigned mode)
51 {
52 return tdb_open(CS name, 0, TDB_DEFAULT, flags, mode);
53 }
54
55 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
56 static BOOL
57 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
58 {
59 *res = tdb_fetch(dbp, *key);    /* A struct arg and return!! */
60 return res->dptr != NULL;
61 }
62
63 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
64 static int
65 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
66 { return tdb_store(dbp, *key, *data, TDB_REPLACE); }
67
68 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
69 static int
70 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
71 { return tdb_store(dbp, *key, *data, TDB_INSERT); }
72
73 /* Returns from EXIM_DBPUTB */
74
75 # define EXIM_DBPUTB_OK  0
76 # define EXIM_DBPUTB_DUP (-1)
77
78 /* EXIM_DBDEL */
79 static int
80 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
81 { return tdb_delete(dbp, *key); }
82
83 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
84 static EXIM_CURSOR *
85 exim_dbcreate_cursor(EXIM_DB * dbp)
86 {
87 EXIM_CURSOR * c = store_malloc(sizeof(TDB_DATA));
88 c->dptr = NULL;
89 return c;
90 }
91
92 /* EXIM_DBSCAN - This is complicated because we have to free the last datum
93 free() must not die when passed NULL */
94
95 static BOOL
96 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res, BOOL first,
97   EXIM_CURSOR * cursor)
98 {
99 *key = first ? tdb_firstkey(dbp) : tdb_nextkey(dbp, *cursor);
100 free(cursor->dptr);
101 *cursor = *key;
102 return key->dptr != NULL;
103 }
104
105 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
106 static void
107 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
108 { store_free(cursor); }
109
110 /* EXIM_DBCLOSE */
111 static void
112 exim_dbclose__(EXIM_DB * db)
113 { tdb_close(db); }
114
115 /* Datum access */
116
117 static uschar *
118 exim_datum_data_get(EXIM_DATUM * dp)
119 { return US dp->dptr; }
120 static void
121 exim_datum_data_set(EXIM_DATUM * dp, void * s)
122 { dp->dptr = s; }
123
124 static unsigned
125 exim_datum_size_get(EXIM_DATUM * dp)
126 { return dp->dsize; }
127 static void
128 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
129 { dp->dsize = n; }
130
131 /* No initialization is needed. */
132
133 static void
134 exim_datum_init(EXIM_DATUM * d)
135 { }
136
137 /* Free the stuff inside the datum. */
138
139 static void
140 exim_datum_free(EXIM_DATUM * d)
141 {
142 free(d->dptr);
143 d->dptr = NULL;
144 }
145
146 /* size limit */
147
148 # define EXIM_DB_RLIMIT 150
149
150
151
152
153
154
155 /********************* Berkeley db native definitions **********************/
156
157 #elif defined USE_DB
158
159 # include <db.h>
160
161 /* 1.x did no locking
162    2.x had facilities, but exim does it's own
163    3.x+ unknown
164 */
165
166 /* We can distinguish between versions 1.x and 2.x/3.x by looking for a
167 definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
168
169 # ifdef DB_VERSION_STRING
170
171 #  if DB_VERSION_MAJOR >= 6
172 #   error Version 6 and later BDB API is not supported
173 #  endif
174
175 /* The API changed (again!) between the 2.x and 3.x versions */
176
177 # if DB_VERSION_MAJOR >= 3
178
179 /***************** Berkeley db 3.x/4.x native definitions ******************/
180
181 /* Basic DB type */
182 #  if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
183 #   define EXIM_DB       DB_ENV
184 /* Cursor type, for scanning */
185 #   define EXIM_CURSOR   DBC
186
187 /* The datum type used for queries */
188 #   define EXIM_DATUM    DBT
189
190 /* Some text for messages */
191 #   define EXIM_DBTYPE   "db (v4.1+)"
192
193 /* Only more-recent versions.  5+ ? */
194 #   ifndef DB_FORCESYNC
195 #    define DB_FORCESYNC 0
196 #   endif
197
198 /* Error callback */
199 /* For Berkeley DB >= 2, we can define a function to be called in case of DB
200 errors. This should help with debugging strange DB problems, e.g. getting "File
201 exists" when you try to open a db file. The API for this function was changed
202 at DB release 4.3. */
203
204 static void
205 dbfn_bdb_error_callback(const DB_ENV * dbenv, const char * pfx, const char * msg)
206 { log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg); }
207
208
209
210 /* Access functions */
211
212 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
213 /* The API changed for DB 4.1. - and we also starting using the "env" with a
214 specified working dir, to avoid the DBCONFIG file trap. */
215
216 #   define ENV_TO_DB(env) ((DB *)(((EXIM_DB *)env)->app_private))
217
218 static EXIM_DB *
219 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
220   unsigned mode)
221 {
222 EXIM_DB * dbp;
223 DB * b;
224 if (  db_env_create(&dbp, 0) != 0
225    || (dbp->set_errcall(dbp, dbfn_bdb_error_callback), 0)
226    || dbp->open(dbp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0
227    )
228   return NULL;
229 if (db_create(&b, dbp, 0) == 0)
230   {
231   dbp->app_private = b;
232   if (b->open(b, NULL, CS name, NULL,
233               flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
234               flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
235               mode) == 0
236           )
237     return dbp;
238
239   b->close(b, 0);
240   }
241 dbp->close(dbp, 0);
242 return NULL;
243 }
244
245 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
246 static BOOL
247 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
248 {
249 DB * b = ENV_TO_DB(dbp);
250 return b->get(b, NULL, key, res, 0) == 0;
251 }
252
253 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
254 static int
255 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
256 {
257 DB * b = ENV_TO_DB(dbp);
258 return b->put(b, NULL, key, data, 0);
259 }
260
261 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
262 static int
263 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
264 {
265 DB * b = ENV_TO_DB(dbp);
266 return b->put(b, NULL, key, data, DB_NOOVERWRITE);
267 }
268
269 /* Return values from EXIM_DBPUTB */
270
271 #   define EXIM_DBPUTB_OK  0
272 #   define EXIM_DBPUTB_DUP DB_KEYEXIST
273
274 /* EXIM_DBDEL */
275 static int
276 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
277 {
278 DB * b = ENV_TO_DB(dbp);
279 return b->del(b, NULL, key, 0);
280 }
281
282 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
283
284 static EXIM_CURSOR *
285 exim_dbcreate_cursor(EXIM_DB * dbp)
286 {
287 DB * b = ENV_TO_DB(dbp);
288 EXIM_CURSOR * c;
289 b->cursor(b, NULL, &c, 0);
290 return c;
291 }
292
293 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
294 static BOOL
295 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
296   EXIM_CURSOR * cursor)
297 {
298 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
299 }
300
301 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
302 static void
303 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
304 { cursor->c_close(cursor); }
305
306 /* EXIM_DBCLOSE */
307 static void
308 exim_dbclose__(EXIM_DB * dbp_o)
309 {
310 DB_ENV * dbp = dbp_o;
311 DB * b = ENV_TO_DB(dbp);
312 b->close(b, 0);
313 dbp->close(dbp, DB_FORCESYNC);
314 }
315
316 /* Datum access */
317
318 static uschar *
319 exim_datum_data_get(EXIM_DATUM * dp)
320 { return dp->data; }
321 static void
322 exim_datum_data_set(EXIM_DATUM * dp, void * s)
323 { dp->data = s; }
324
325 static unsigned
326 exim_datum_size_get(EXIM_DATUM * dp)
327 { return dp->size; }
328 static void
329 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
330 { dp->size = n; }
331
332 /* The whole datum structure contains other fields that must be cleared
333 before use, but we don't have to free anything after reading data. */
334
335 static void
336 exim_datum_init(EXIM_DATUM * d)
337 { memset(d, 0, sizeof(*d)); }
338
339 static void
340 exim_datum_free(EXIM_DATUM * d)
341 { }
342
343 #  else /* pre- 4.1 */
344
345 #   define EXIM_DB       DB
346
347 /* Cursor type, for scanning */
348 #   define EXIM_CURSOR   DBC
349
350 /* The datum type used for queries */
351 #   define EXIM_DATUM    DBT
352
353 /* Some text for messages */
354 #   define EXIM_DBTYPE   "db (v3/4)"
355
356 /* Access functions */
357
358 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
359 static EXIM_DB *
360 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
361   unsigned mode)
362 {
363 EXIM_DB * dbp;
364 return db_create(&dbp, NULL, 0) == 0
365   && (  dbp->set_errcall(dbp, dbfn_bdb_error_callback),
366         dbp->open(dbp, CS name, NULL,
367           flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
368           flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
369           mode)
370      ) == 0
371   ? dbp : NULL;
372 }
373
374 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
375 static BOOL
376 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
377 { return dbp->get(dbp, NULL, key, res, 0) == 0; }
378
379 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
380 static int
381 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
382 { return dbp->put(dbp, NULL, key, data, 0); }
383
384 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
385 static int
386 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
387 { return dbp->put(dbp, NULL, key, data, DB_NOOVERWRITE); }
388
389 /* Return values from EXIM_DBPUTB */
390
391 #   define EXIM_DBPUTB_OK  0
392 #   define EXIM_DBPUTB_DUP DB_KEYEXIST
393
394 /* EXIM_DBDEL */
395 static int
396 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
397 { return dbp->del(dbp, NULL, key, 0); }
398
399 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
400
401 static EXIM_CURSOR *
402 exim_dbcreate_cursor(EXIM_DB * dbp)
403 {
404 EXIM_CURSOR * c;
405 dbp->cursor(dbp, NULL, &c, 0);
406 return c;
407 }
408
409 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
410 static BOOL
411 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
412   EXIM_CURSOR * cursor)
413 {
414 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
415 }
416
417 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
418 static void
419 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
420 { cursor->c_close(cursor); }
421
422 /* EXIM_DBCLOSE */
423 static void
424 exim_dbclose__(EXIM_DB * dbp)
425 { dbp->close(dbp, 0); }
426
427 /* Datum access */
428
429 static uschar *
430 exim_datum_data_get(EXIM_DATUM * dp)
431 { return US dp->dptr; }
432 static void
433 exim_datum_data_set(EXIM_DATUM * dp, void * s)
434 { dp->dptr = s; }
435
436 static uschar *
437 exim_datum_size_get(EXIM_DATUM * dp)
438 { return US dp->size; }
439 static void
440 exim_datum_size_set(EXIM_DATUM * dp, uschar * s)
441 { dp->size = CS s; }
442
443 /* The whole datum structure contains other fields that must be cleared
444 before use, but we don't have to free anything after reading data. */
445
446 static void
447 exim_datum_init(EXIM_DATUM * d)
448 { memset(d, 0, sizeof(*d)); }
449
450 static void
451 exim_datum_free(EXIM_DATUM * d)
452 { }
453
454 #  endif
455
456
457 #  else /* DB_VERSION_MAJOR >= 3 */
458 #   error Berkeley DB versions earlier than 3 are not supported */
459 #  endif /* DB_VERSION_MAJOR */
460 # else
461 #  error Berkeley DB version 1 is no longer supported
462 # endif /* DB_VERSION_STRING */
463
464
465 /* all BDB versions */
466 /* size limit */
467
468 # define EXIM_DB_RLIMIT 150
469
470
471
472
473
474
475 /********************* gdbm interface definitions **********************/
476
477 #elif defined USE_GDBM
478 /*XXX TODO: exim's locfile not needed */
479
480 # include <gdbm.h>
481
482 /* Basic DB type */
483 typedef struct {
484        GDBM_FILE gdbm;  /* Database */
485        datum lkey;      /* Last key, for scans */
486 } EXIM_DB;
487
488 /* Cursor type, not used with gdbm: just set up a dummy */
489 # define EXIM_CURSOR int
490
491 /* The datum type used for queries */
492 # define EXIM_DATUM datum
493
494 /* Some text for messages */
495
496 # define EXIM_DBTYPE "gdbm"
497
498 /* Access functions */
499
500 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
501 static EXIM_DB *
502 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
503   unsigned mode)
504 {
505 EXIM_DB * dbp = malloc(sizeof(EXIM_DB));        /*XXX why not exim mem-mgmt? */
506 if (dbp)
507   {
508   dbp->lkey.dptr = NULL;
509   dbp->gdbm = gdbm_open(CS name, 0,
510     flags & O_CREAT ? GDBM_WRCREAT
511     : flags & (O_RDWR|O_WRONLY) ? GDBM_WRITER
512     : GDBM_READER,
513     mode, 0);
514   if (dbp->gdbm) return dbp;
515   free(dbp);
516   }
517 return NULL;
518 }
519
520 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
521 static BOOL
522 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
523 {
524 *res = gdbm_fetch(dbp->gdbm, *key);     /* A struct arg & return! */
525 return res->dptr != NULL;
526 }
527
528 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
529 static int
530 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
531 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_REPLACE); }
532
533 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
534 static int
535 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
536 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_INSERT); }
537
538 /* Returns from EXIM_DBPUTB */
539
540 # define EXIM_DBPUTB_OK  0
541 # define EXIM_DBPUTB_DUP 1
542
543 /* EXIM_DBDEL */
544 static int
545 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
546 { return gdbm_delete(dbp->gdbm, *key); }
547
548 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
549 static EXIM_CURSOR *
550 exim_dbcreate_cursor(EXIM_DB * dbp)
551 { return NULL; }
552
553 /* EXIM_DBSCAN */
554 static BOOL
555 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
556   EXIM_CURSOR * cursor)
557 {
558 char * s;
559 *key = first ? gdbm_firstkey(dbp->gdbm) : gdbm_nextkey(dbp->gdbm, dbp->lkey);
560 if ((s = dbp->lkey.dptr)) free(s);
561 dbp->lkey = *key;
562 return key->dptr != NULL;
563 }
564
565 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
566 static void
567 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
568 { }
569
570 /* EXIM_DBCLOSE */
571 static void
572 exim_dbclose__(EXIM_DB * dbp)
573 {
574 char * s;
575 gdbm_close(dbp->gdbm);
576 if ((s = dbp->lkey.dptr)) free(s);
577 free(dbp);
578 }
579
580 /* Datum access types */
581
582 static uschar *
583 exim_datum_data_get(EXIM_DATUM * dp)
584 { return US dp->dptr; }
585 static void
586 exim_datum_data_set(EXIM_DATUM * dp, void * s)
587 { dp->dptr = s; }
588
589 static unsigned
590 exim_datum_size_get(EXIM_DATUM * dp)
591 { return dp->dsize; }
592 static void
593 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
594 { dp->dsize = n; }
595
596 /* There's no clearing required before use, but we have to free the dptr
597 after reading data. */
598
599 static void
600 exim_datum_init(EXIM_DATUM * d)
601 { }
602
603 static void
604 exim_datum_free(EXIM_DATUM * d)
605 { free(d->dptr); }
606
607 /* size limit */
608
609 # define EXIM_DB_RLIMIT 150
610
611 #else  /* USE_GDBM */
612
613
614
615
616
617
618 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
619 interface */
620
621
622 /********************* ndbm interface definitions **********************/
623
624 # include <ndbm.h>
625
626 /* Basic DB type */
627 # define EXIM_DB DBM
628
629 /* Cursor type, not used with ndbm: just set up a dummy */
630 # define EXIM_CURSOR int
631
632 /* The datum type used for queries */
633 # define EXIM_DATUM datum
634
635 /* Some text for messages */
636
637 # define EXIM_DBTYPE "ndbm"
638
639 /* Access functions */
640
641 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
642 /* Check that the name given is not present. This catches
643 a directory name; otherwise we would create the name.pag and
644 name.dir files in the directory's parent. */
645
646 static EXIM_DB *
647 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
648   unsigned mode)
649 {
650 struct stat st;
651 if (!(flags & O_CREAT) || lstat(CCS name, &st) != 0 && errno == ENOENT)
652   return dbm_open(CS name, flags, mode);
653 #ifndef COMPILE_UTILITY
654 debug_printf("%s %d errno %s\n", __FUNCTION__, __LINE__, strerror(errno));
655 #endif
656 errno = (st.st_mode & S_IFMT) == S_IFDIR ? EISDIR : EEXIST;
657 return NULL;
658 }
659
660 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
661 static BOOL
662 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
663 {
664 *res = dbm_fetch(dbp, *key);    /* A struct arg & return! */
665 return res->dptr != NULL;
666 }
667
668 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
669 static int
670 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
671 { return dbm_store(dbp, *key, *data, DBM_REPLACE); }
672
673 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
674 static int
675 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
676 { return dbm_store(dbp, *key, *data, DBM_INSERT); }
677
678 /* Returns from EXIM_DBPUTB */
679
680 # define EXIM_DBPUTB_OK  0
681 # define EXIM_DBPUTB_DUP 1
682
683 /* EXIM_DBDEL */
684 static int
685 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
686 { return dbm_delete(dbp, *key); }
687
688 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
689 static EXIM_CURSOR *
690 exim_dbcreate_cursor(EXIM_DB * dbp)
691 { return NULL; }
692
693 /* EXIM_DBSCAN */
694 static BOOL
695 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
696   EXIM_CURSOR * cursor)
697 {
698 *key = first ? dbm_firstkey(dbp) : dbm_nextkey(dbp);
699 return key->dptr != NULL;
700 }
701
702 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
703 static void
704 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
705 { }
706
707 /* EXIM_DBCLOSE */
708 static void
709 exim_dbclose__(EXIM_DB * dbp)
710 { dbm_close(dbp); }
711
712 /* Datum access types */
713
714 static uschar *
715 exim_datum_data_get(EXIM_DATUM * dp)
716 { return US dp->dptr; }
717 static void
718 exim_datum_data_set(EXIM_DATUM * dp, void * s)
719 { dp->dptr = s; }
720
721 static unsigned
722 exim_datum_size_get(EXIM_DATUM * dp)
723 { return dp->dsize; }
724 static void
725 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
726 { dp->dsize = n; }
727
728 /* There's no clearing required before use, and we don't have to free anything
729 after reading data. */
730
731 static void
732 exim_datum_init(EXIM_DATUM * d)
733 { }
734
735 static void
736 exim_datum_free(EXIM_DATUM * d)
737 { }
738
739 /* size limit */
740
741 # define EXIM_DB_RLIMIT 150
742
743 #endif /* USE_GDBM */
744
745
746
747
748
749 #if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF)
750
751 static EXIM_DB *
752 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
753   unsigned mode)
754 {
755 return exim_dbopen__(name, dirname, flags, mode);
756 }
757
758 static void
759 exim_dbclose(EXIM_DB * dbp)
760 { exim_dbclose__(dbp); }
761
762 #else
763 /* Wrappers for open/close with debug tracing */
764
765 extern void debug_printf_indent(const char *, ...);
766 static BOOL is_tainted(const void *);
767
768 static EXIM_DB *
769 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
770   unsigned mode)
771 {
772 void * dbp;
773 DEBUG(D_hints_lookup)
774   debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n",
775     name, dirname,
776     flags == O_RDONLY ? "O_RDONLY"
777     : flags == O_RDWR ? "O_RDWR"
778     : flags == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT"
779     : "??");
780 if (is_tainted(name) || is_tainted(dirname))
781   {
782   log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted");
783   dbp = NULL;
784   }
785 else
786   dbp = exim_dbopen__(name, dirname, flags, mode);
787
788 DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", dbp);
789 return dbp;
790 }
791
792 static void
793 exim_dbclose(EXIM_DB * dbp)
794 {
795 DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", dbp);
796 exim_dbclose__(dbp);
797 }
798
799 # endif
800
801 /********************* End of dbm library definitions **********************/
802
803
804 #endif  /* whole file */
805 /* End of hintsdb.h */