Commit | Line | Data |
---|---|---|
4cb3af58 EA |
1 | /* |
2 | * Copyright (c) 1992 Eric P. Allman. | |
3 | * Copyright (c) 1992 Regents of the University of California. | |
4 | * All rights reserved. | |
5 | * | |
6 | * %sccs.include.redist.c% | |
7 | */ | |
8 | ||
9 | #ifndef lint | |
10 | static char sccsid[] = "@(#)map.c 5.1 (Berkeley) %G%"; | |
11 | #endif /* not lint */ | |
12 | ||
13 | #include "sendmail.h" | |
14 | #include <sys/file.h> | |
15 | ||
16 | #ifdef DBM_MAP | |
17 | #include <ndbm.h> | |
18 | #endif | |
19 | #if defined(HASH_MAP) || defined(BTREE_MAP) | |
20 | #include <db.h> | |
21 | #endif | |
22 | ||
23 | ||
24 | #ifdef DBM_MAP | |
25 | ||
26 | /* | |
27 | ** DBM_MAP_INIT -- DBM-style map initialization | |
28 | ** | |
29 | ** Parameters: | |
30 | ** map -- the pointer to the actual map | |
31 | ** mapname -- the name of the map (for error messages) | |
32 | ** args -- a pointer to the config file line arguments | |
33 | ** | |
34 | ** Returns: | |
35 | ** TRUE -- if it could successfully open the map. | |
36 | ** FALSE -- otherwise. | |
37 | ** | |
38 | ** Side Effects: | |
39 | ** Gives an error if it can't open the map. | |
40 | */ | |
41 | ||
42 | bool | |
43 | dbm_map_init(map, mapname, args) | |
44 | MAP *map; | |
45 | char *mapname; | |
46 | char *args; | |
47 | { | |
48 | DBM *dbm; | |
49 | ||
50 | map_parseargs(map, &args, mapname); | |
51 | if (map->map_file == NULL) | |
52 | return FALSE; | |
53 | dbm = dbm_open(map->map_file, O_RDONLY, 0644); | |
54 | if (dbm == NULL) | |
55 | { | |
56 | syserr("Cannot open DBM database %s", map->map_file); | |
57 | return FALSE; | |
58 | } | |
59 | map->map_db = (void *) dbm; | |
60 | return TRUE; | |
61 | } | |
62 | \f/* | |
63 | ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map | |
64 | ** | |
65 | ** Parameters: | |
66 | ** map -- the map to look up in. | |
67 | ** buf -- a pointer to to the buffer containing the key. | |
68 | ** This is a null terminated string. | |
69 | ** bufsiz -- the size of buf -- note that this is in general | |
70 | ** larger that strlen(buf), and buf can be changed | |
71 | ** in place if desired. | |
72 | ** av -- arguments from the config file (can be interpolated | |
73 | ** into the final result). | |
74 | ** | |
75 | ** Returns: | |
76 | ** A pointer to the rewritten result. | |
77 | ** NULL if not found in the map. | |
78 | */ | |
79 | ||
80 | char * | |
81 | dbm_map_lookup(map, buf, bufsiz, av) | |
82 | MAP *map; | |
83 | char buf[]; | |
84 | int bufsiz; | |
85 | char **av; | |
86 | { | |
87 | datum key, val; | |
88 | ||
89 | key.dptr = buf; | |
90 | key.dsize = strlen(buf); | |
91 | if (bitset(MF_INCLNULL, map->map_flags)) | |
92 | key.dsize++; | |
93 | val = dbm_fetch(map->map_db, key); | |
94 | if (val.dptr == NULL) | |
95 | return NULL; | |
96 | map_rewrite(val.dptr, val.dsize, buf, bufsiz, av); | |
97 | return buf; | |
98 | } | |
99 | ||
100 | #endif /* DBM_MAP */ | |
101 | \f | |
102 | #ifdef BTREE_MAP | |
103 | ||
104 | /* | |
105 | ** BTREE_MAP_INIT -- BTREE-style map initialization | |
106 | ** | |
107 | ** Parameters: | |
108 | ** map -- the pointer to the actual map | |
109 | ** mapname -- the name of the map (for error messages) | |
110 | ** args -- a pointer to the config file line arguments | |
111 | ** | |
112 | ** Returns: | |
113 | ** TRUE -- if it could successfully open the map. | |
114 | ** FALSE -- otherwise. | |
115 | ** | |
116 | ** Side Effects: | |
117 | ** Gives an error if it can't open the map. | |
118 | */ | |
119 | ||
120 | bool | |
121 | bt_map_init(map, mapname, args) | |
122 | MAP *map; | |
123 | char *mapname; | |
124 | char *args; | |
125 | { | |
126 | DB *db; | |
127 | ||
128 | map_parseargs(map, &args, mapname); | |
129 | if (map->map_file == NULL) | |
130 | return FALSE; | |
131 | db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL); | |
132 | if (db == NULL) | |
133 | { | |
134 | syserr("Cannot open BTREE database %s", map->map_file); | |
135 | return FALSE; | |
136 | } | |
137 | map->map_db = (void *) db; | |
138 | return TRUE; | |
139 | } | |
140 | ||
141 | #endif /* BTREE_MAP */ | |
142 | \f | |
143 | #ifdef HASH_MAP | |
144 | ||
145 | /* | |
146 | ** HASH_MAP_INIT -- HASH-style map initialization | |
147 | ** | |
148 | ** Parameters: | |
149 | ** map -- the pointer to the actual map | |
150 | ** mapname -- the name of the map (for error messages) | |
151 | ** args -- a pointer to the config file line arguments | |
152 | ** | |
153 | ** Returns: | |
154 | ** TRUE -- if it could successfully open the map. | |
155 | ** FALSE -- otherwise. | |
156 | ** | |
157 | ** Side Effects: | |
158 | ** Gives an error if it can't open the map. | |
159 | */ | |
160 | ||
161 | bool | |
162 | hash_map_init(map, mapname, args) | |
163 | MAP *map; | |
164 | char *mapname; | |
165 | char *args; | |
166 | { | |
167 | DB *db; | |
168 | ||
169 | map_parseargs(map, &args, mapname); | |
170 | if (map->map_file == NULL) | |
171 | return FALSE; | |
172 | db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL); | |
173 | if (db == NULL) | |
174 | { | |
175 | syserr("Cannot open HASH database %s", map->map_file); | |
176 | return FALSE; | |
177 | } | |
178 | map->map_db = (void *) db; | |
179 | return TRUE; | |
180 | } | |
181 | ||
182 | #endif /* HASH_MAP */ | |
183 | \f | |
184 | #if defined(BTREE_MAP) || defined(HASH_MAP) | |
185 | ||
186 | /* | |
187 | ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map | |
188 | ** | |
189 | ** Parameters: | |
190 | ** map -- the map to look up in. | |
191 | ** buf -- a pointer to to the buffer containing the key. | |
192 | ** This is a null terminated string. | |
193 | ** bufsiz -- the size of buf -- note that this is in general | |
194 | ** larger that strlen(buf), and buf can be changed | |
195 | ** in place if desired. | |
196 | ** av -- arguments from the config file (can be interpolated | |
197 | ** into the final result). | |
198 | ** | |
199 | ** Returns: | |
200 | ** A pointer to the rewritten result. | |
201 | ** NULL if not found in the map. | |
202 | */ | |
203 | ||
204 | char * | |
205 | db_map_lookup(map, buf, bufsiz, av) | |
206 | MAP *map; | |
207 | char buf[]; | |
208 | int bufsiz; | |
209 | char **av; | |
210 | { | |
211 | DBT key, val; | |
212 | ||
213 | key.data = buf; | |
214 | key.size = strlen(buf); | |
215 | if (bitset(MF_INCLNULL, map->map_flags)) | |
216 | key.size++; | |
217 | if ((*((DB *) map->map_db)->get)((DB *) map->map_db, &key, &val, 0) != 0) | |
218 | return NULL; | |
219 | map_rewrite(val.data, val.size, buf, bufsiz, av); | |
220 | return buf; | |
221 | } | |
222 | ||
223 | #endif /* BTREE_MAP || HASH_MAP */ | |
224 | \f/* | |
225 | ** MAP_PARSEARGS -- parse config line arguments for database lookup | |
226 | ** | |
227 | ** Parameters: | |
228 | ** map -- the map being initialized. | |
229 | ** pp -- an indirect pointer to the config line. It will | |
230 | ** be replaced with a pointer to the next field | |
231 | ** on the line. | |
232 | ** mapname -- the name of the map (for errors). | |
233 | ** | |
234 | ** Returns: | |
235 | ** none | |
236 | ** | |
237 | ** Side Effects: | |
238 | ** null terminates the filename; stores it in map | |
239 | */ | |
240 | ||
241 | map_parseargs(map, pp, mapname) | |
242 | MAP *map; | |
243 | char **pp; | |
244 | char *mapname; | |
245 | { | |
246 | register char *p = *pp; | |
247 | ||
248 | for (;;) | |
249 | { | |
250 | while (isspace(*p)) | |
251 | p++; | |
252 | if (*p != '-') | |
253 | break; | |
254 | switch (*++p) | |
255 | { | |
256 | case 'N': | |
257 | map->map_flags |= MF_INCLNULL; | |
258 | break; | |
259 | } | |
260 | while (*p != '\0' && !isspace(*p)) | |
261 | p++; | |
262 | } | |
263 | ||
264 | if (*p == '\0') | |
265 | { | |
266 | syserr("No file name for map %s", mapname); | |
267 | return NULL; | |
268 | } | |
269 | map->map_file = p; | |
270 | while (*p != '\0' && !isspace(*p)) | |
271 | p++; | |
272 | if (*p != '\0') | |
273 | *p++ = '\0'; | |
274 | *pp = p; | |
275 | } | |
276 | \f/* | |
277 | ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. | |
278 | ** | |
279 | ** Parameters: | |
280 | ** s -- the string to rewrite, NOT necessarily null terminated. | |
281 | ** slen -- the length of s. | |
282 | ** buf -- the place to write it. | |
283 | ** buflen -- the length of buf. | |
284 | ** av -- arguments to interpolate into buf. | |
285 | ** | |
286 | ** Returns: | |
287 | ** none. | |
288 | ** | |
289 | ** Side Effects: | |
290 | ** none. | |
291 | */ | |
292 | ||
293 | map_rewrite(s, slen, buf, buflen, av) | |
294 | register char *s; | |
295 | int slen; | |
296 | char buf[]; | |
297 | int buflen; | |
298 | char **av; | |
299 | { | |
300 | register char *bp; | |
301 | char *buflim; | |
302 | register char c; | |
303 | char **avp; | |
304 | register char *ap; | |
305 | ||
306 | if (tTd(23, 1)) | |
307 | { | |
308 | printf("map_rewrite(%.*s), av =\n", slen, s); | |
309 | for (avp = av; *avp != NULL; avp++) | |
310 | printf("\t%s\n", *avp); | |
311 | } | |
312 | ||
313 | bp = buf; | |
314 | buflim = &buf[buflen - 2]; | |
315 | while (--slen >= 0 && (c = *s++) != '\0') | |
316 | { | |
317 | if (c != '%') | |
318 | { | |
319 | pushc: | |
320 | if (bp < buflim) | |
321 | *bp++ = c; | |
322 | continue; | |
323 | } | |
324 | if (--slen < 0 || (c = *s++) == '\0') | |
325 | c = '%'; | |
326 | if (c == '%') | |
327 | goto pushc; | |
328 | if (!isdigit(c)) | |
329 | { | |
330 | *bp++ = '%'; | |
331 | goto pushc; | |
332 | } | |
333 | c -= '0'; | |
334 | for (avp = av; --c >= 0 && *avp != NULL; avp++) | |
335 | continue; | |
336 | if (*avp == NULL) | |
337 | continue; | |
338 | ||
339 | /* transliterate argument into output string */ | |
340 | for (ap = *avp; (c = *ap++) != '\0'; ) | |
341 | { | |
342 | if (bp < buflim) | |
343 | *bp++ = c; | |
344 | } | |
345 | } | |
346 | *bp++ = '\0'; | |
347 | if (tTd(23, 1)) | |
348 | printf("map_rewrite => %s\n", buf); | |
349 | } |