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