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