Add dynamic lookup support
[exim.git] / src / src / lookups / dbmdb.c
1 /* $Cambridge: exim/src/src/lookups/dbmdb.c,v 1.6 2009/11/16 19:50:38 nm4 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2009 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
10 #include "../exim.h"
11 #include "lf_functions.h"
12
13
14 /*************************************************
15 *              Open entry point                  *
16 *************************************************/
17
18 /* See local README for interface description */
19
20 static void *
21 dbmdb_open(uschar *filename, uschar **errmsg)
22 {
23 EXIM_DB *yield;
24 EXIM_DBOPEN(filename, O_RDONLY, 0, &yield);
25 if (yield == NULL)
26   {
27   int save_errno = errno;
28   *errmsg = string_open_failed(errno, "%s as a %s file", filename, EXIM_DBTYPE);
29   errno = save_errno;
30   }
31 return yield;
32 }
33
34
35
36 /*************************************************
37 *             Check entry point                  *
38 *************************************************/
39
40 /* This needs to know more about the underlying files than is good for it!
41 We need to know what the real file names are in order to check the owners and
42 modes. If USE_DB is set, we know it is Berkeley DB, which uses an unmodified
43 file name. If USE_TDB or USE_GDBM is set, we know it is tdb or gdbm, which do
44 the same. Otherwise, for safety, we have to check for x.db or x.dir and x.pag.
45 */
46
47 static BOOL
48 dbmdb_check(void *handle, uschar *filename, int modemask, uid_t *owners,
49   gid_t *owngroups, uschar **errmsg)
50 {
51 int rc;
52 handle = handle;    /* Keep picky compilers happy */
53
54 #if defined(USE_DB) || defined(USE_TDB) || defined(USE_GDBM)
55 rc = lf_check_file(-1, filename, S_IFREG, modemask, owners, owngroups,
56   "dbm", errmsg);
57 #else
58   {
59   uschar filebuffer[256];
60   (void)sprintf(CS filebuffer, "%.250s.db", filename);
61   rc = lf_check_file(-1, filebuffer, S_IFREG, modemask, owners, owngroups,
62     "dbm", errmsg);
63   if (rc < 0)        /* stat() failed */
64     {
65     (void)sprintf(CS filebuffer, "%.250s.dir", filename);
66     rc = lf_check_file(-1, filebuffer, S_IFREG, modemask, owners, owngroups,
67       "dbm", errmsg);
68     if (rc == 0)     /* x.dir was OK */
69       {
70       (void)sprintf(CS filebuffer, "%.250s.pag", filename);
71       rc = lf_check_file(-1, filebuffer, S_IFREG, modemask, owners, owngroups,
72         "dbm", errmsg);
73       }
74     }
75   }
76 #endif
77
78 return rc == 0;
79 }
80
81
82
83 /*************************************************
84 *              Find entry point                  *
85 *************************************************/
86
87 /* See local README for interface description. This function adds 1 to
88 the keylength in order to include the terminating zero. */
89
90 static int
91 dbmdb_find(void *handle, uschar *filename, uschar *keystring, int length,
92   uschar **result, uschar **errmsg, BOOL *do_cache)
93 {
94 EXIM_DB *d = (EXIM_DB *)handle;
95 EXIM_DATUM key, data;
96
97 filename = filename;    /* Keep picky compilers happy */
98 errmsg = errmsg;
99 do_cache = do_cache;
100
101 EXIM_DATUM_INIT(key);               /* Some DBM libraries require datums to */
102 EXIM_DATUM_INIT(data);              /* be cleared before use. */
103 EXIM_DATUM_DATA(key) = CS keystring;
104 EXIM_DATUM_SIZE(key) = length + 1;
105
106 if (EXIM_DBGET(d, key, data))
107   {
108   *result = string_copyn(US EXIM_DATUM_DATA(data), EXIM_DATUM_SIZE(data));
109   EXIM_DATUM_FREE(data);            /* Some DBM libraries need a free() call */
110   return OK;
111   }
112 return FAIL;
113 }
114
115
116
117 /*************************************************
118 *      Find entry point - no zero on key         *
119 *************************************************/
120
121 /* See local README for interface description */
122
123 int
124 static dbmnz_find(void *handle, uschar *filename, uschar *keystring, int length,
125   uschar **result, uschar **errmsg, BOOL *do_cache)
126 {
127 return dbmdb_find(handle, filename, keystring, length-1, result, errmsg,
128   do_cache);
129 }
130
131
132
133 /*************************************************
134 *              Close entry point                 *
135 *************************************************/
136
137 /* See local README for interface description */
138
139 void
140 static dbmdb_close(void *handle)
141 {
142 EXIM_DBCLOSE((EXIM_DB *)handle);
143 }
144
145 lookup_info dbm_lookup_info = {
146   US"dbm",                       /* lookup name */
147   lookup_absfile,                /* uses absolute file name */
148   dbmdb_open,                    /* open function */
149   dbmdb_check,                   /* check function */
150   dbmdb_find,                    /* find function */
151   dbmdb_close,                   /* close function */
152   NULL,                          /* no tidy function */
153   NULL                           /* no quoting function */
154 };
155
156 lookup_info dbmz_lookup_info = {
157   US"dbmnz",                     /* lookup name */
158   lookup_absfile,                /* uses absolute file name */
159   dbmdb_open,      /* sic */     /* open function */
160   dbmdb_check,     /* sic */     /* check function */
161   dbmnz_find,                    /* find function */
162   dbmdb_close,     /* sic */     /* close function */
163   NULL,                          /* no tidy function */
164   NULL                           /* no quoting function */
165 };
166
167 #ifdef DYNLOOKUP
168 #define dbmdb_lookup_module_info _lookup_module_info
169 #endif
170
171 static lookup_info *_lookup_list[] = { &dbm_lookup_info, &dbmz_lookup_info };
172 lookup_module_info dbmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 2 };
173
174 /* End of lookups/dbmdb.c */