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 | |
73f6752a | 10 | static char sccsid[] = "@(#)map.c 6.12 (Berkeley) %G%"; |
4cb3af58 EA |
11 | #endif /* not lint */ |
12 | ||
13 | #include "sendmail.h" | |
4cb3af58 EA |
14 | |
15 | #ifdef DBM_MAP | |
16 | #include <ndbm.h> | |
17 | #endif | |
18 | #if defined(HASH_MAP) || defined(BTREE_MAP) | |
73f6752a | 19 | #undef __P |
4cb3af58 EA |
20 | #include <db.h> |
21 | #endif | |
33844dcf EA |
22 | #ifdef NIS_MAP |
23 | #include <rpcsvc/ypclnt.h> | |
24 | #endif | |
4cb3af58 EA |
25 | |
26 | ||
27 | #ifdef DBM_MAP | |
28 | ||
29 | /* | |
30 | ** DBM_MAP_INIT -- DBM-style map initialization | |
31 | ** | |
32 | ** Parameters: | |
33 | ** map -- the pointer to the actual map | |
34 | ** mapname -- the name of the map (for error messages) | |
35 | ** args -- a pointer to the config file line arguments | |
36 | ** | |
37 | ** Returns: | |
38 | ** TRUE -- if it could successfully open the map. | |
39 | ** FALSE -- otherwise. | |
40 | ** | |
41 | ** Side Effects: | |
42 | ** Gives an error if it can't open the map. | |
43 | */ | |
44 | ||
45 | bool | |
46 | dbm_map_init(map, mapname, args) | |
47 | MAP *map; | |
48 | char *mapname; | |
49 | char *args; | |
50 | { | |
51 | DBM *dbm; | |
52 | ||
33844dcf | 53 | map_parseargs(map, &args); |
4cb3af58 | 54 | if (map->map_file == NULL) |
33844dcf EA |
55 | { |
56 | syserr("No file name for DBM map %s", mapname); | |
4cb3af58 | 57 | return FALSE; |
33844dcf | 58 | } |
4cb3af58 EA |
59 | dbm = dbm_open(map->map_file, O_RDONLY, 0644); |
60 | if (dbm == NULL) | |
61 | { | |
32fd13db EA |
62 | if (!bitset(MF_OPTIONAL, map->map_flags)) |
63 | syserr("Cannot open DBM database %s", map->map_file); | |
4cb3af58 EA |
64 | return FALSE; |
65 | } | |
66 | map->map_db = (void *) dbm; | |
67 | return TRUE; | |
68 | } | |
69 | \f/* | |
70 | ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map | |
71 | ** | |
72 | ** Parameters: | |
73 | ** map -- the map to look up in. | |
74 | ** buf -- a pointer to to the buffer containing the key. | |
75 | ** This is a null terminated string. | |
76 | ** bufsiz -- the size of buf -- note that this is in general | |
77 | ** larger that strlen(buf), and buf can be changed | |
78 | ** in place if desired. | |
79 | ** av -- arguments from the config file (can be interpolated | |
80 | ** into the final result). | |
d1db7a89 | 81 | ** statp -- pointer to status word (out-parameter). |
4cb3af58 EA |
82 | ** |
83 | ** Returns: | |
84 | ** A pointer to the rewritten result. | |
85 | ** NULL if not found in the map. | |
86 | */ | |
87 | ||
88 | char * | |
d1db7a89 | 89 | dbm_map_lookup(map, buf, bufsiz, av, statp) |
4cb3af58 EA |
90 | MAP *map; |
91 | char buf[]; | |
92 | int bufsiz; | |
93 | char **av; | |
d1db7a89 | 94 | int *statp; |
4cb3af58 EA |
95 | { |
96 | datum key, val; | |
97 | ||
98 | key.dptr = buf; | |
99 | key.dsize = strlen(buf); | |
5dac3bbf | 100 | if (!bitset(MF_NOFOLDCASE, map->map_flags)) |
f22e3888 EA |
101 | { |
102 | register char *p; | |
103 | ||
104 | for (p = buf; *p != '\0'; p++) | |
2bee003d | 105 | if (isascii(*p) && isupper(*p)) |
f22e3888 EA |
106 | *p = tolower(*p); |
107 | } | |
4cb3af58 EA |
108 | if (bitset(MF_INCLNULL, map->map_flags)) |
109 | key.dsize++; | |
73f6752a EA |
110 | (void) lockfile(dbm_dirfno((DBM *) map->map_db), map->map_file, LOCK_SH); |
111 | val = dbm_fetch((DBM *) map->map_db, key); | |
112 | (void) lockfile(dbm_dirfno((DBM *) map->map_db), map->map_file, LOCK_UN); | |
4cb3af58 EA |
113 | if (val.dptr == NULL) |
114 | return NULL; | |
33844dcf EA |
115 | if (!bitset(MF_MATCHONLY, map->map_flags)) |
116 | map_rewrite(val.dptr, val.dsize, buf, bufsiz, av); | |
4cb3af58 EA |
117 | return buf; |
118 | } | |
119 | ||
120 | #endif /* DBM_MAP */ | |
121 | \f | |
122 | #ifdef BTREE_MAP | |
123 | ||
124 | /* | |
125 | ** BTREE_MAP_INIT -- BTREE-style map initialization | |
126 | ** | |
127 | ** Parameters: | |
128 | ** map -- the pointer to the actual map | |
129 | ** mapname -- the name of the map (for error messages) | |
130 | ** args -- a pointer to the config file line arguments | |
131 | ** | |
132 | ** Returns: | |
133 | ** TRUE -- if it could successfully open the map. | |
134 | ** FALSE -- otherwise. | |
135 | ** | |
136 | ** Side Effects: | |
137 | ** Gives an error if it can't open the map. | |
138 | */ | |
139 | ||
140 | bool | |
141 | bt_map_init(map, mapname, args) | |
142 | MAP *map; | |
143 | char *mapname; | |
144 | char *args; | |
145 | { | |
146 | DB *db; | |
147 | ||
33844dcf | 148 | map_parseargs(map, &args); |
4cb3af58 | 149 | if (map->map_file == NULL) |
33844dcf EA |
150 | { |
151 | syserr("No file name for BTREE map %s", mapname); | |
4cb3af58 | 152 | return FALSE; |
33844dcf | 153 | } |
4cb3af58 EA |
154 | db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL); |
155 | if (db == NULL) | |
156 | { | |
32fd13db EA |
157 | if (!bitset(MF_OPTIONAL, map->map_flags)) |
158 | syserr("Cannot open BTREE database %s", map->map_file); | |
4cb3af58 EA |
159 | return FALSE; |
160 | } | |
161 | map->map_db = (void *) db; | |
162 | return TRUE; | |
163 | } | |
164 | ||
165 | #endif /* BTREE_MAP */ | |
166 | \f | |
167 | #ifdef HASH_MAP | |
168 | ||
169 | /* | |
170 | ** HASH_MAP_INIT -- HASH-style map initialization | |
171 | ** | |
172 | ** Parameters: | |
173 | ** map -- the pointer to the actual map | |
174 | ** mapname -- the name of the map (for error messages) | |
175 | ** args -- a pointer to the config file line arguments | |
176 | ** | |
177 | ** Returns: | |
178 | ** TRUE -- if it could successfully open the map. | |
179 | ** FALSE -- otherwise. | |
180 | ** | |
181 | ** Side Effects: | |
182 | ** Gives an error if it can't open the map. | |
183 | */ | |
184 | ||
185 | bool | |
186 | hash_map_init(map, mapname, args) | |
187 | MAP *map; | |
188 | char *mapname; | |
189 | char *args; | |
190 | { | |
191 | DB *db; | |
192 | ||
33844dcf | 193 | map_parseargs(map, &args); |
4cb3af58 | 194 | if (map->map_file == NULL) |
33844dcf EA |
195 | { |
196 | syserr("No file name for HASH map %s", mapname); | |
4cb3af58 | 197 | return FALSE; |
33844dcf | 198 | } |
4cb3af58 EA |
199 | db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL); |
200 | if (db == NULL) | |
201 | { | |
32fd13db EA |
202 | if (!bitset(MF_OPTIONAL, map->map_flags)) |
203 | syserr("Cannot open HASH database %s", map->map_file); | |
4cb3af58 EA |
204 | return FALSE; |
205 | } | |
206 | map->map_db = (void *) db; | |
207 | return TRUE; | |
208 | } | |
209 | ||
210 | #endif /* HASH_MAP */ | |
211 | \f | |
212 | #if defined(BTREE_MAP) || defined(HASH_MAP) | |
213 | ||
214 | /* | |
215 | ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map | |
216 | ** | |
217 | ** Parameters: | |
218 | ** map -- the map to look up in. | |
219 | ** buf -- a pointer to to the buffer containing the key. | |
220 | ** This is a null terminated string. | |
221 | ** bufsiz -- the size of buf -- note that this is in general | |
222 | ** larger that strlen(buf), and buf can be changed | |
223 | ** in place if desired. | |
224 | ** av -- arguments from the config file (can be interpolated | |
225 | ** into the final result). | |
d1db7a89 | 226 | ** statp -- pointer to status word (out-parameter). |
4cb3af58 EA |
227 | ** |
228 | ** Returns: | |
229 | ** A pointer to the rewritten result. | |
230 | ** NULL if not found in the map. | |
231 | */ | |
232 | ||
233 | char * | |
d1db7a89 | 234 | db_map_lookup(map, buf, bufsiz, av, statp) |
4cb3af58 EA |
235 | MAP *map; |
236 | char buf[]; | |
237 | int bufsiz; | |
238 | char **av; | |
d1db7a89 | 239 | int *statp; |
4cb3af58 EA |
240 | { |
241 | DBT key, val; | |
242 | ||
243 | key.data = buf; | |
244 | key.size = strlen(buf); | |
5dac3bbf | 245 | if (!bitset(MF_NOFOLDCASE, map->map_flags)) |
c58eb4cc EA |
246 | { |
247 | register char *p; | |
248 | ||
249 | for (p = buf; *p != '\0'; p++) | |
2bee003d | 250 | if (isascii(*p) && isupper(*p)) |
c58eb4cc EA |
251 | *p = tolower(*p); |
252 | } | |
4cb3af58 EA |
253 | if (bitset(MF_INCLNULL, map->map_flags)) |
254 | key.size++; | |
32fd13db | 255 | if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0) |
4cb3af58 | 256 | return NULL; |
33844dcf EA |
257 | if (!bitset(MF_MATCHONLY, map->map_flags)) |
258 | map_rewrite(val.data, val.size, buf, bufsiz, av); | |
4cb3af58 EA |
259 | return buf; |
260 | } | |
261 | ||
262 | #endif /* BTREE_MAP || HASH_MAP */ | |
263 | \f/* | |
264 | ** MAP_PARSEARGS -- parse config line arguments for database lookup | |
265 | ** | |
266 | ** Parameters: | |
267 | ** map -- the map being initialized. | |
268 | ** pp -- an indirect pointer to the config line. It will | |
269 | ** be replaced with a pointer to the next field | |
270 | ** on the line. | |
4cb3af58 EA |
271 | ** |
272 | ** Returns: | |
273 | ** none | |
274 | ** | |
275 | ** Side Effects: | |
276 | ** null terminates the filename; stores it in map | |
277 | */ | |
278 | ||
33844dcf | 279 | map_parseargs(map, pp) |
4cb3af58 EA |
280 | MAP *map; |
281 | char **pp; | |
4cb3af58 EA |
282 | { |
283 | register char *p = *pp; | |
284 | ||
285 | for (;;) | |
286 | { | |
2bee003d | 287 | while (isascii(*p) && isspace(*p)) |
4cb3af58 EA |
288 | p++; |
289 | if (*p != '-') | |
290 | break; | |
291 | switch (*++p) | |
292 | { | |
293 | case 'N': | |
294 | map->map_flags |= MF_INCLNULL; | |
295 | break; | |
32fd13db EA |
296 | |
297 | case 'o': | |
298 | map->map_flags |= MF_OPTIONAL; | |
299 | break; | |
300 | ||
c58eb4cc | 301 | case 'f': |
5dac3bbf | 302 | map->map_flags |= MF_NOFOLDCASE; |
c58eb4cc EA |
303 | break; |
304 | ||
33844dcf EA |
305 | case 'm': |
306 | map->map_flags |= MF_MATCHONLY; | |
307 | break; | |
308 | ||
32fd13db EA |
309 | case 'a': |
310 | map->map_app = ++p; | |
311 | break; | |
33844dcf EA |
312 | |
313 | case 'd': | |
314 | map->map_domain = ++p; | |
315 | break; | |
4cb3af58 | 316 | } |
2bee003d | 317 | while (*p != '\0' && !(isascii(*p) && isspace(*p))) |
4cb3af58 | 318 | p++; |
32fd13db | 319 | if (*p != '\0') |
4aaafa33 | 320 | *p++ = '\0'; |
4cb3af58 | 321 | } |
32fd13db EA |
322 | if (map->map_app != NULL) |
323 | map->map_app = newstr(map->map_app); | |
33844dcf EA |
324 | if (map->map_domain != NULL) |
325 | map->map_domain = newstr(map->map_domain); | |
4cb3af58 | 326 | |
4cb3af58 | 327 | if (*p != '\0') |
4aaafa33 EA |
328 | { |
329 | map->map_file = p; | |
330 | while (*p != '\0' && !(isascii(*p) && isspace(*p))) | |
331 | p++; | |
332 | if (*p != '\0') | |
333 | *p++ = '\0'; | |
334 | map->map_file = newstr(map->map_file); | |
335 | } | |
cc047d90 EA |
336 | |
337 | while (*p != '\0' && isascii(*p) && isspace(*p)) | |
338 | p++; | |
4cb3af58 | 339 | *pp = p; |
cc047d90 EA |
340 | if (*p != '\0') |
341 | map->map_rebuild = newstr(p); | |
4cb3af58 | 342 | } |
33844dcf EA |
343 | \f |
344 | # ifdef NIS_MAP | |
345 | ||
346 | /* | |
347 | ** NIS_MAP_INIT -- initialize DBM map | |
348 | ** | |
349 | ** Parameters: | |
350 | ** map -- the pointer to the actual map. | |
351 | ** mapname -- the name of the map (for error messages). | |
352 | ** args -- a pointer to the config file line arguments. | |
353 | ** | |
354 | ** Returns: | |
355 | ** TRUE -- if it could successfully open the map. | |
356 | ** FALSE -- otherwise. | |
357 | ** | |
358 | ** Side Effects: | |
359 | ** Prints an error if it can't open the map. | |
360 | */ | |
361 | ||
362 | bool | |
363 | nis_map_init(map, mapname, args) | |
364 | MAP *map; | |
365 | char *mapname; | |
366 | char *args; | |
367 | { | |
0044540e EA |
368 | int yperr; |
369 | char *master; | |
370 | ||
33844dcf EA |
371 | /* parse arguments */ |
372 | map_parseargs(map, &args); | |
373 | if (map->map_file == NULL) | |
374 | { | |
375 | syserr("No NIS map name for map %s", mapname); | |
376 | return FALSE; | |
377 | } | |
378 | if (map->map_domain == NULL) | |
379 | yp_get_default_domain(&map->map_domain); | |
0044540e EA |
380 | |
381 | /* check to see if this map actually exists */ | |
382 | yperr = yp_master(map->map_domain, map->map_file, &master); | |
383 | if (yperr == 0) | |
384 | return TRUE; | |
385 | if (!bitset(MF_OPTIONAL, map->map_flags)) | |
386 | syserr("Cannot bind to domain %s: %s", map->map_domain, | |
387 | yperr_string(yperr)); | |
388 | return FALSE; | |
33844dcf EA |
389 | } |
390 | \f/* | |
391 | ** NIS_MAP_LOOKUP -- look up a datum in a NIS map | |
392 | ** | |
393 | ** Parameters: | |
394 | ** map -- the map to look up in. | |
395 | ** buf -- a pointer to to the buffer containing the key. | |
396 | ** This is a null terminated string. | |
397 | ** bufsiz -- the size of buf -- note that this is in general | |
398 | ** larger that strlen(buf), and buf can be changed | |
399 | ** in place if desired. | |
400 | ** av -- arguments from the config file (can be interpolated | |
401 | ** into the final result). | |
d1db7a89 | 402 | ** statp -- pointer to status word (out-parameter). |
33844dcf EA |
403 | ** |
404 | ** Returns: | |
405 | ** A pointer to the rewritten result. | |
406 | ** NULL if not found in the map. | |
407 | */ | |
408 | ||
409 | char * | |
d1db7a89 | 410 | nis_map_lookup(map, buf, bufsiz, av, statp) |
33844dcf EA |
411 | MAP *map; |
412 | char buf[]; | |
413 | int bufsiz; | |
414 | char **av; | |
d1db7a89 | 415 | int *statp; |
33844dcf EA |
416 | { |
417 | char *vp; | |
6e99f903 | 418 | auto int vsize; |
0753ae18 | 419 | int buflen; |
33844dcf EA |
420 | |
421 | if (!bitset(MF_NOFOLDCASE, map->map_flags)) | |
422 | { | |
423 | register char *p; | |
424 | ||
425 | for (p = buf; *p != '\0'; p++) | |
2bee003d | 426 | if (isascii(*p) && isupper(*p)) |
33844dcf EA |
427 | *p = tolower(*p); |
428 | } | |
0753ae18 EA |
429 | buflen = strlen(buf); |
430 | if (bitset(MF_INCLNULL, map->map_flags)) | |
431 | buflen++; | |
432 | if (yp_match(map->map_domain, map->map_file, buf, buflen, | |
6e99f903 | 433 | &vp, &vsize) != 0) |
33844dcf EA |
434 | return NULL; |
435 | if (!bitset(MF_MATCHONLY, map->map_flags)) | |
436 | map_rewrite(vp, vsize, buf, bufsiz, av); | |
437 | return buf; | |
438 | } | |
439 | ||
440 | #endif /* NIS_MAP */ | |
4cb3af58 EA |
441 | \f/* |
442 | ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. | |
443 | ** | |
444 | ** Parameters: | |
445 | ** s -- the string to rewrite, NOT necessarily null terminated. | |
446 | ** slen -- the length of s. | |
447 | ** buf -- the place to write it. | |
448 | ** buflen -- the length of buf. | |
449 | ** av -- arguments to interpolate into buf. | |
450 | ** | |
451 | ** Returns: | |
452 | ** none. | |
453 | ** | |
454 | ** Side Effects: | |
455 | ** none. | |
456 | */ | |
457 | ||
458 | map_rewrite(s, slen, buf, buflen, av) | |
459 | register char *s; | |
460 | int slen; | |
461 | char buf[]; | |
462 | int buflen; | |
463 | char **av; | |
464 | { | |
465 | register char *bp; | |
466 | char *buflim; | |
467 | register char c; | |
468 | char **avp; | |
469 | register char *ap; | |
470 | ||
471 | if (tTd(23, 1)) | |
472 | { | |
473 | printf("map_rewrite(%.*s), av =\n", slen, s); | |
474 | for (avp = av; *avp != NULL; avp++) | |
475 | printf("\t%s\n", *avp); | |
476 | } | |
477 | ||
478 | bp = buf; | |
479 | buflim = &buf[buflen - 2]; | |
480 | while (--slen >= 0 && (c = *s++) != '\0') | |
481 | { | |
482 | if (c != '%') | |
483 | { | |
484 | pushc: | |
485 | if (bp < buflim) | |
486 | *bp++ = c; | |
487 | continue; | |
488 | } | |
489 | if (--slen < 0 || (c = *s++) == '\0') | |
490 | c = '%'; | |
491 | if (c == '%') | |
492 | goto pushc; | |
2bee003d | 493 | if (!(isascii(c) && isdigit(c))) |
4cb3af58 EA |
494 | { |
495 | *bp++ = '%'; | |
496 | goto pushc; | |
497 | } | |
498 | c -= '0'; | |
499 | for (avp = av; --c >= 0 && *avp != NULL; avp++) | |
500 | continue; | |
501 | if (*avp == NULL) | |
502 | continue; | |
503 | ||
504 | /* transliterate argument into output string */ | |
505 | for (ap = *avp; (c = *ap++) != '\0'; ) | |
506 | { | |
507 | if (bp < buflim) | |
508 | *bp++ = c; | |
509 | } | |
510 | } | |
511 | *bp++ = '\0'; | |
512 | if (tTd(23, 1)) | |
513 | printf("map_rewrite => %s\n", buf); | |
514 | } |