Revert "Build: remove hints-DB interface from macro-predef phase"
[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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline void
107 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
108 { store_free(cursor); }
109
110 /* EXIM_DBCLOSE */
111 static inline void
112 exim_dbclose__(EXIM_DB * db)
113 { tdb_close(db); }
114
115 /* Datum access */
116
117 static inline uschar *
118 exim_datum_data_get(EXIM_DATUM * dp)
119 { return US dp->dptr; }
120 static inline void
121 exim_datum_data_set(EXIM_DATUM * dp, void * s)
122 { dp->dptr = s; }
123
124 static inline unsigned
125 exim_datum_size_get(EXIM_DATUM * dp)
126 { return dp->dsize; }
127 static inline void
128 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
129 { dp->dsize = n; }
130
131 /* No initialization is needed. */
132
133 static inline void
134 exim_datum_init(EXIM_DATUM * d)
135 { }
136
137 /* Free the stuff inside the datum. */
138
139 static inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline void
303 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
304 { cursor->c_close(cursor); }
305
306 /* EXIM_DBCLOSE */
307 static inline 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 inline uschar *
319 exim_datum_data_get(EXIM_DATUM * dp)
320 { return dp->data; }
321 static inline void
322 exim_datum_data_set(EXIM_DATUM * dp, void * s)
323 { dp->data = s; }
324
325 static inline unsigned
326 exim_datum_size_get(EXIM_DATUM * dp)
327 { return dp->size; }
328 static inline 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 inline void
336 exim_datum_init(EXIM_DATUM * d)
337 { memset(d, 0, sizeof(*d)); }
338
339 static inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline void
419 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
420 { cursor->c_close(cursor); }
421
422 /* EXIM_DBCLOSE */
423 static inline void
424 exim_dbclose__(EXIM_DB * dbp)
425 { dbp->close(dbp, 0); }
426
427 /* Datum access */
428
429 static inline uschar *
430 exim_datum_data_get(EXIM_DATUM * dp)
431 { return US dp->dptr; }
432 static inline void
433 exim_datum_data_set(EXIM_DATUM * dp, void * s)
434 { dp->dptr = s; }
435
436 static inline uschar *
437 exim_datum_size_get(EXIM_DATUM * dp)
438 { return US dp->size; }
439 static inline 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 inline void
447 exim_datum_init(EXIM_DATUM * d)
448 { memset(d, 0, sizeof(*d)); }
449
450 static inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline EXIM_CURSOR *
550 exim_dbcreate_cursor(EXIM_DB * dbp)
551 { return NULL; }
552
553 /* EXIM_DBSCAN */
554 static inline 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 inline void
567 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
568 { }
569
570 /* EXIM_DBCLOSE */
571 static inline 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 inline uschar *
583 exim_datum_data_get(EXIM_DATUM * dp)
584 { return US dp->dptr; }
585 static inline void
586 exim_datum_data_set(EXIM_DATUM * dp, void * s)
587 { dp->dptr = s; }
588
589 static inline unsigned
590 exim_datum_size_get(EXIM_DATUM * dp)
591 { return dp->dsize; }
592 static inline 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 inline void
600 exim_datum_init(EXIM_DATUM * d)
601 { }
602
603 static inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline EXIM_CURSOR *
690 exim_dbcreate_cursor(EXIM_DB * dbp)
691 { return NULL; }
692
693 /* EXIM_DBSCAN */
694 static inline 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 inline void
704 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
705 { }
706
707 /* EXIM_DBCLOSE */
708 static inline void
709 exim_dbclose__(EXIM_DB * dbp)
710 { dbm_close(dbp); }
711
712 /* Datum access types */
713
714 static inline uschar *
715 exim_datum_data_get(EXIM_DATUM * dp)
716 { return US dp->dptr; }
717 static inline void
718 exim_datum_data_set(EXIM_DATUM * dp, void * s)
719 { dp->dptr = s; }
720
721 static inline unsigned
722 exim_datum_size_get(EXIM_DATUM * dp)
723 { return dp->dsize; }
724 static inline 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 inline void
732 exim_datum_init(EXIM_DATUM * d)
733 { }
734
735 static inline 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 inline 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 inline void
759 exim_dbclose(EXIM_DB * dbp)
760 { exim_dbclose__(dbp); }
761
762 #else   /*  exim mainline code */
763
764 /* Wrappers for open/close with debug tracing */
765
766 extern void debug_printf_indent(const char *, ...);
767 static inline BOOL is_tainted(const void *);
768
769 static inline EXIM_DB *
770 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
771   unsigned mode)
772 {
773 void * dbp;
774 DEBUG(D_hints_lookup)
775   debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n",
776     name, dirname,
777     flags == O_RDONLY ? "O_RDONLY"
778     : flags == O_RDWR ? "O_RDWR"
779     : flags == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT"
780     : "??");
781 if (is_tainted(name) || is_tainted(dirname))
782   {
783   log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted");
784   dbp = NULL;
785   }
786 else
787   dbp = exim_dbopen__(name, dirname, flags, mode);
788
789 DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", dbp);
790 return dbp;
791 }
792
793 static inline void
794 exim_dbclose(EXIM_DB * dbp)
795 {
796 DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", dbp);
797 exim_dbclose__(dbp);
798 }
799
800 # endif         /* defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) */
801
802 /********************* End of dbm library definitions **********************/
803
804
805 #endif  /* whole file */
806 /* End of hintsdb.h */