1b5e69eeb7200a818acee5507047da44f33cdf98
[users/jgh/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
146
147 /*************************************************
148 *         Version reporting entry point          *
149 *************************************************/
150
151 /* See local README for interface description. */
152
153 #include "../version.h"
154
155 void
156 dbm_version_report(FILE *f)
157 {
158 #ifdef DYNLOOKUP
159 fprintf(f, "Library version: DBM: Exim version %s\n", EXIM_VERSION_STR);
160 #endif
161 }
162
163
164 lookup_info dbm_lookup_info = {
165   US"dbm",                       /* lookup name */
166   lookup_absfile,                /* uses absolute file name */
167   dbmdb_open,                    /* open function */
168   dbmdb_check,                   /* check function */
169   dbmdb_find,                    /* find function */
170   dbmdb_close,                   /* close function */
171   NULL,                          /* no tidy function */
172   NULL,                          /* no quoting function */
173   dbm_version_report             /* version reporting */
174 };
175
176 lookup_info dbmz_lookup_info = {
177   US"dbmnz",                     /* lookup name */
178   lookup_absfile,                /* uses absolute file name */
179   dbmdb_open,      /* sic */     /* open function */
180   dbmdb_check,     /* sic */     /* check function */
181   dbmnz_find,                    /* find function */
182   dbmdb_close,     /* sic */     /* close function */
183   NULL,                          /* no tidy function */
184   NULL,                          /* no quoting function */
185   NULL                           /* no version reporting (redundant) */
186 };
187
188 #ifdef DYNLOOKUP
189 #define dbmdb_lookup_module_info _lookup_module_info
190 #endif
191
192 static lookup_info *_lookup_list[] = { &dbm_lookup_info, &dbmz_lookup_info };
193 lookup_module_info dbmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 2 };
194
195 /* End of lookups/dbmdb.c */