Fix build with Solaris compiler
[exim.git] / src / src / hintsdb.h
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
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 {
207 #ifndef MACRO_PREDEF 
208 log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg);
209 #endif
210 }
211
212
213
214 /* Access functions */
215
216 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
217 /* The API changed for DB 4.1. - and we also starting using the "env" with a
218 specified working dir, to avoid the DBCONFIG file trap. */
219
220 #   define ENV_TO_DB(env) ((DB *)(((EXIM_DB *)env)->app_private))
221
222 static inline EXIM_DB *
223 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
224   unsigned mode)
225 {
226 EXIM_DB * dbp;
227 DB * b;
228 if (  db_env_create(&dbp, 0) != 0
229    || (dbp->set_errcall(dbp, dbfn_bdb_error_callback), 0)
230    || dbp->open(dbp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0
231    )
232   return NULL;
233 if (db_create(&b, dbp, 0) == 0)
234   {
235   dbp->app_private = b;
236   if (b->open(b, NULL, CS name, NULL,
237               flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
238               flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
239               mode) == 0
240           )
241     return dbp;
242
243   b->close(b, 0);
244   }
245 dbp->close(dbp, 0);
246 return NULL;
247 }
248
249 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
250 static inline BOOL
251 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
252 {
253 DB * b = ENV_TO_DB(dbp);
254 return b->get(b, NULL, key, res, 0) == 0;
255 }
256
257 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
258 static inline int
259 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
260 {
261 DB * b = ENV_TO_DB(dbp);
262 return b->put(b, NULL, key, data, 0);
263 }
264
265 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
266 static inline int
267 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
268 {
269 DB * b = ENV_TO_DB(dbp);
270 return b->put(b, NULL, key, data, DB_NOOVERWRITE);
271 }
272
273 /* Return values from EXIM_DBPUTB */
274
275 #   define EXIM_DBPUTB_OK  0
276 #   define EXIM_DBPUTB_DUP DB_KEYEXIST
277
278 /* EXIM_DBDEL */
279 static inline int
280 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
281 {
282 DB * b = ENV_TO_DB(dbp);
283 return b->del(b, NULL, key, 0);
284 }
285
286 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
287
288 static inline EXIM_CURSOR *
289 exim_dbcreate_cursor(EXIM_DB * dbp)
290 {
291 DB * b = ENV_TO_DB(dbp);
292 EXIM_CURSOR * c;
293 b->cursor(b, NULL, &c, 0);
294 return c;
295 }
296
297 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
298 static inline BOOL
299 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
300   EXIM_CURSOR * cursor)
301 {
302 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
303 }
304
305 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
306 static inline void
307 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
308 { cursor->c_close(cursor); }
309
310 /* EXIM_DBCLOSE */
311 static inline void
312 exim_dbclose__(EXIM_DB * dbp_o)
313 {
314 DB_ENV * dbp = dbp_o;
315 DB * b = ENV_TO_DB(dbp);
316 b->close(b, 0);
317 dbp->close(dbp, DB_FORCESYNC);
318 }
319
320 /* Datum access */
321
322 static inline uschar *
323 exim_datum_data_get(EXIM_DATUM * dp)
324 { return dp->data; }
325 static inline void
326 exim_datum_data_set(EXIM_DATUM * dp, void * s)
327 { dp->data = s; }
328
329 static inline unsigned
330 exim_datum_size_get(EXIM_DATUM * dp)
331 { return dp->size; }
332 static inline void
333 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
334 { dp->size = n; }
335
336 /* The whole datum structure contains other fields that must be cleared
337 before use, but we don't have to free anything after reading data. */
338
339 static inline void
340 exim_datum_init(EXIM_DATUM * d)
341 { memset(d, 0, sizeof(*d)); }
342
343 static inline void
344 exim_datum_free(EXIM_DATUM * d)
345 { }
346
347 #  else /* pre- 4.1 */
348
349 #   define EXIM_DB       DB
350
351 /* Cursor type, for scanning */
352 #   define EXIM_CURSOR   DBC
353
354 /* The datum type used for queries */
355 #   define EXIM_DATUM    DBT
356
357 /* Some text for messages */
358 #   define EXIM_DBTYPE   "db (v3/4)"
359
360 /* Access functions */
361
362 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
363 static inline EXIM_DB *
364 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
365   unsigned mode)
366 {
367 EXIM_DB * dbp;
368 return db_create(&dbp, NULL, 0) == 0
369   && (  dbp->set_errcall(dbp, dbfn_bdb_error_callback),
370         dbp->open(dbp, CS name, NULL,
371           flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
372           flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
373           mode)
374      ) == 0
375   ? dbp : NULL;
376 }
377
378 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
379 static inline BOOL
380 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
381 { return dbp->get(dbp, NULL, key, res, 0) == 0; }
382
383 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
384 static inline int
385 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
386 { return dbp->put(dbp, NULL, key, data, 0); }
387
388 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
389 static inline int
390 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
391 { return dbp->put(dbp, NULL, key, data, DB_NOOVERWRITE); }
392
393 /* Return values from EXIM_DBPUTB */
394
395 #   define EXIM_DBPUTB_OK  0
396 #   define EXIM_DBPUTB_DUP DB_KEYEXIST
397
398 /* EXIM_DBDEL */
399 static inline int
400 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
401 { return dbp->del(dbp, NULL, key, 0); }
402
403 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
404
405 static inline EXIM_CURSOR *
406 exim_dbcreate_cursor(EXIM_DB * dbp)
407 {
408 EXIM_CURSOR * c;
409 dbp->cursor(dbp, NULL, &c, 0);
410 return c;
411 }
412
413 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
414 static inline BOOL
415 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
416   EXIM_CURSOR * cursor)
417 {
418 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
419 }
420
421 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
422 static inline void
423 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
424 { cursor->c_close(cursor); }
425
426 /* EXIM_DBCLOSE */
427 static inline void
428 exim_dbclose__(EXIM_DB * dbp)
429 { dbp->close(dbp, 0); }
430
431 /* Datum access */
432
433 static inline uschar *
434 exim_datum_data_get(EXIM_DATUM * dp)
435 { return US dp->dptr; }
436 static inline void
437 exim_datum_data_set(EXIM_DATUM * dp, void * s)
438 { dp->dptr = s; }
439
440 static inline uschar *
441 exim_datum_size_get(EXIM_DATUM * dp)
442 { return US dp->size; }
443 static inline void
444 exim_datum_size_set(EXIM_DATUM * dp, uschar * s)
445 { dp->size = CS s; }
446
447 /* The whole datum structure contains other fields that must be cleared
448 before use, but we don't have to free anything after reading data. */
449
450 static inline void
451 exim_datum_init(EXIM_DATUM * d)
452 { memset(d, 0, sizeof(*d)); }
453
454 static inline void
455 exim_datum_free(EXIM_DATUM * d)
456 { }
457
458 #  endif
459
460
461 #  else /* DB_VERSION_MAJOR >= 3 */
462 #   error Berkeley DB versions earlier than 3 are not supported */
463 #  endif /* DB_VERSION_MAJOR */
464 # else
465 #  error Berkeley DB version 1 is no longer supported
466 # endif /* DB_VERSION_STRING */
467
468
469 /* all BDB versions */
470 /* size limit */
471
472 # define EXIM_DB_RLIMIT 150
473
474
475
476
477
478
479 /********************* gdbm interface definitions **********************/
480
481 #elif defined USE_GDBM
482 /*XXX TODO: exim's locfile not needed */
483
484 # include <gdbm.h>
485
486 /* Basic DB type */
487 typedef struct {
488        GDBM_FILE gdbm;  /* Database */
489        datum lkey;      /* Last key, for scans */
490 } EXIM_DB;
491
492 /* Cursor type, not used with gdbm: just set up a dummy */
493 # define EXIM_CURSOR int
494
495 /* The datum type used for queries */
496 # define EXIM_DATUM datum
497
498 /* Some text for messages */
499
500 # define EXIM_DBTYPE "gdbm"
501
502 /* Access functions */
503
504 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
505 static inline EXIM_DB *
506 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
507   unsigned mode)
508 {
509 EXIM_DB * dbp = malloc(sizeof(EXIM_DB));        /*XXX why not exim mem-mgmt? */
510 if (dbp)
511   {
512   dbp->lkey.dptr = NULL;
513   dbp->gdbm = gdbm_open(CS name, 0,
514     flags & O_CREAT ? GDBM_WRCREAT
515     : flags & (O_RDWR|O_WRONLY) ? GDBM_WRITER
516     : GDBM_READER,
517     mode, 0);
518   if (dbp->gdbm) return dbp;
519   free(dbp);
520   }
521 return NULL;
522 }
523
524 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
525 static inline BOOL
526 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
527 {
528 *res = gdbm_fetch(dbp->gdbm, *key);     /* A struct arg & return! */
529 return res->dptr != NULL;
530 }
531
532 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
533 static inline int
534 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
535 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_REPLACE); }
536
537 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
538 static inline int
539 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
540 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_INSERT); }
541
542 /* Returns from EXIM_DBPUTB */
543
544 # define EXIM_DBPUTB_OK  0
545 # define EXIM_DBPUTB_DUP 1
546
547 /* EXIM_DBDEL */
548 static inline int
549 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
550 { return gdbm_delete(dbp->gdbm, *key); }
551
552 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
553 static inline EXIM_CURSOR *
554 exim_dbcreate_cursor(EXIM_DB * dbp)
555 { return NULL; }
556
557 /* EXIM_DBSCAN */
558 static inline BOOL
559 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
560   EXIM_CURSOR * cursor)
561 {
562 char * s;
563 *key = first ? gdbm_firstkey(dbp->gdbm) : gdbm_nextkey(dbp->gdbm, dbp->lkey);
564 if ((s = dbp->lkey.dptr)) free(s);
565 dbp->lkey = *key;
566 return key->dptr != NULL;
567 }
568
569 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
570 static inline void
571 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
572 { }
573
574 /* EXIM_DBCLOSE */
575 static inline void
576 exim_dbclose__(EXIM_DB * dbp)
577 {
578 char * s;
579 gdbm_close(dbp->gdbm);
580 if ((s = dbp->lkey.dptr)) free(s);
581 free(dbp);
582 }
583
584 /* Datum access types */
585
586 static inline uschar *
587 exim_datum_data_get(EXIM_DATUM * dp)
588 { return US dp->dptr; }
589 static inline void
590 exim_datum_data_set(EXIM_DATUM * dp, void * s)
591 { dp->dptr = s; }
592
593 static inline unsigned
594 exim_datum_size_get(EXIM_DATUM * dp)
595 { return dp->dsize; }
596 static inline void
597 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
598 { dp->dsize = n; }
599
600 /* There's no clearing required before use, but we have to free the dptr
601 after reading data. */
602
603 static inline void
604 exim_datum_init(EXIM_DATUM * d)
605 { }
606
607 static inline void
608 exim_datum_free(EXIM_DATUM * d)
609 { free(d->dptr); }
610
611 /* size limit */
612
613 # define EXIM_DB_RLIMIT 150
614
615 #else  /* USE_GDBM */
616
617
618
619
620
621
622 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
623 interface */
624
625
626 /********************* ndbm interface definitions **********************/
627
628 # include <ndbm.h>
629
630 /* Basic DB type */
631 # define EXIM_DB DBM
632
633 /* Cursor type, not used with ndbm: just set up a dummy */
634 # define EXIM_CURSOR int
635
636 /* The datum type used for queries */
637 # define EXIM_DATUM datum
638
639 /* Some text for messages */
640
641 # define EXIM_DBTYPE "ndbm"
642
643 /* Access functions */
644
645 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
646 /* Check that the name given is not present. This catches
647 a directory name; otherwise we would create the name.pag and
648 name.dir files in the directory's parent. */
649
650 static inline EXIM_DB *
651 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
652   unsigned mode)
653 {
654 struct stat st;
655 if (!(flags & O_CREAT) || lstat(CCS name, &st) != 0 && errno == ENOENT)
656   return dbm_open(CS name, flags, mode);
657 #ifndef COMPILE_UTILITY
658 debug_printf("%s %d errno %s\n", __FUNCTION__, __LINE__, strerror(errno));
659 #endif
660 errno = (st.st_mode & S_IFMT) == S_IFDIR ? EISDIR : EEXIST;
661 return NULL;
662 }
663
664 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
665 static inline BOOL
666 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
667 {
668 *res = dbm_fetch(dbp, *key);    /* A struct arg & return! */
669 return res->dptr != NULL;
670 }
671
672 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
673 static inline int
674 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
675 { return dbm_store(dbp, *key, *data, DBM_REPLACE); }
676
677 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
678 static inline int
679 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
680 { return dbm_store(dbp, *key, *data, DBM_INSERT); }
681
682 /* Returns from EXIM_DBPUTB */
683
684 # define EXIM_DBPUTB_OK  0
685 # define EXIM_DBPUTB_DUP 1
686
687 /* EXIM_DBDEL */
688 static inline int
689 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
690 { return dbm_delete(dbp, *key); }
691
692 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
693 static inline EXIM_CURSOR *
694 exim_dbcreate_cursor(EXIM_DB * dbp)
695 { return NULL; }
696
697 /* EXIM_DBSCAN */
698 static inline BOOL
699 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
700   EXIM_CURSOR * cursor)
701 {
702 *key = first ? dbm_firstkey(dbp) : dbm_nextkey(dbp);
703 return key->dptr != NULL;
704 }
705
706 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
707 static inline void
708 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
709 { }
710
711 /* EXIM_DBCLOSE */
712 static inline void
713 exim_dbclose__(EXIM_DB * dbp)
714 { dbm_close(dbp); }
715
716 /* Datum access types */
717
718 static inline uschar *
719 exim_datum_data_get(EXIM_DATUM * dp)
720 { return US dp->dptr; }
721 static inline void
722 exim_datum_data_set(EXIM_DATUM * dp, void * s)
723 { dp->dptr = s; }
724
725 static inline unsigned
726 exim_datum_size_get(EXIM_DATUM * dp)
727 { return dp->dsize; }
728 static inline void
729 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
730 { dp->dsize = n; }
731
732 /* There's no clearing required before use, and we don't have to free anything
733 after reading data. */
734
735 static inline void
736 exim_datum_init(EXIM_DATUM * d)
737 { }
738
739 static inline void
740 exim_datum_free(EXIM_DATUM * d)
741 { }
742
743 /* size limit */
744
745 # define EXIM_DB_RLIMIT 150
746
747 #endif /* USE_GDBM */
748
749
750
751
752
753 #if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF)
754
755 static inline EXIM_DB *
756 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
757   unsigned mode)
758 {
759 return exim_dbopen__(name, dirname, flags, mode);
760 }
761
762 static inline void
763 exim_dbclose(EXIM_DB * dbp)
764 { exim_dbclose__(dbp); }
765
766 #else   /*  exim mainline code */
767
768 /* Wrappers for open/close with debug tracing */
769
770 extern void debug_printf_indent(const char *, ...);
771 static inline BOOL is_tainted(const void *);
772
773 static inline EXIM_DB *
774 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
775   unsigned mode)
776 {
777 void * dbp;
778 DEBUG(D_hints_lookup)
779   debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n",
780     name, dirname,
781     flags == O_RDONLY ? "O_RDONLY"
782     : flags == O_RDWR ? "O_RDWR"
783     : flags == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT"
784     : "??");
785 if (is_tainted(name) || is_tainted(dirname))
786   {
787   log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted");
788   dbp = NULL;
789   }
790 else
791   dbp = exim_dbopen__(name, dirname, flags, mode);
792
793 DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", dbp);
794 return dbp;
795 }
796
797 static inline void
798 exim_dbclose(EXIM_DB * dbp)
799 {
800 DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", dbp);
801 exim_dbclose__(dbp);
802 }
803
804 # endif         /* defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) */
805
806 /********************* End of dbm library definitions **********************/
807
808
809 #endif  /* whole file */
810 /* End of hintsdb.h */