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