Commit | Line | Data |
---|---|---|
6f14531a RG |
1 | /* |
2 | * Copyright (c) 1992 Eric P. Allman. | |
3 | * Copyright (c) 1992, 1993 | |
4 | * The Regents of the University of California. All rights reserved. | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. All advertising materials mentioning features or use of this software | |
15 | * must display the following acknowledgement: | |
16 | * This product includes software developed by the University of | |
17 | * California, Berkeley and its contributors. | |
18 | * 4. Neither the name of the University nor the names of its contributors | |
19 | * may be used to endorse or promote products derived from this software | |
20 | * without specific prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | |
33 | */ | |
34 | ||
35 | #ifndef lint | |
d747e748 | 36 | static char sccsid[] = "@(#)map.c 8.17 (Berkeley) 10/15/93"; |
6f14531a RG |
37 | #endif /* not lint */ |
38 | ||
39 | #include "sendmail.h" | |
40 | ||
41 | #ifdef NDBM | |
42 | #include <ndbm.h> | |
43 | #endif | |
44 | #ifdef NEWDB | |
45 | #include <db.h> | |
46 | #endif | |
47 | #ifdef NIS | |
48 | #include <rpcsvc/ypclnt.h> | |
49 | #endif | |
50 | ||
51 | /* | |
52 | ** MAP.C -- implementations for various map classes. | |
53 | ** | |
54 | ** Each map class implements a series of functions: | |
55 | ** | |
56 | ** bool map_parse(MAP *map, char *args) | |
57 | ** Parse the arguments from the config file. Return TRUE | |
58 | ** if they were ok, FALSE otherwise. Fill in map with the | |
59 | ** values. | |
60 | ** | |
61 | ** char *map_lookup(MAP *map, char *key, char **args, int *pstat) | |
62 | ** Look up the key in the given map. If found, do any | |
63 | ** rewriting the map wants (including "args" if desired) | |
64 | ** and return the value. Set *pstat to the appropriate status | |
65 | ** on error and return NULL. Args will be NULL if called | |
66 | ** from the alias routines, although this should probably | |
67 | ** not be relied upon. It is suggested you call map_rewrite | |
68 | ** to return the results -- it takes care of null termination | |
69 | ** and uses a dynamically expanded buffer as needed. | |
70 | ** | |
71 | ** void map_store(MAP *map, char *key, char *value) | |
72 | ** Store the key:value pair in the map. | |
73 | ** | |
74 | ** bool map_open(MAP *map, int mode) | |
75 | ** Open the map for the indicated mode. Mode should | |
76 | ** be either O_RDONLY or O_RDWR. Return TRUE if it | |
77 | ** was opened successfully, FALSE otherwise. If the open | |
78 | ** failed an the MF_OPTIONAL flag is not set, it should | |
79 | ** also print an error. If the MF_ALIAS bit is set | |
80 | ** and this map class understands the @:@ convention, it | |
81 | ** should call aliaswait() before returning. | |
82 | ** | |
83 | ** void map_close(MAP *map) | |
84 | ** Close the map. | |
85 | */ | |
86 | ||
87 | #define DBMMODE 0644 | |
d747e748 JH |
88 | |
89 | extern bool aliaswait __P((MAP *, char *, int)); | |
6f14531a RG |
90 | \f/* |
91 | ** MAP_PARSEARGS -- parse config line arguments for database lookup | |
92 | ** | |
93 | ** This is a generic version of the map_parse method. | |
94 | ** | |
95 | ** Parameters: | |
96 | ** map -- the map being initialized. | |
97 | ** ap -- a pointer to the args on the config line. | |
98 | ** | |
99 | ** Returns: | |
100 | ** TRUE -- if everything parsed OK. | |
101 | ** FALSE -- otherwise. | |
102 | ** | |
103 | ** Side Effects: | |
104 | ** null terminates the filename; stores it in map | |
105 | */ | |
106 | ||
107 | bool | |
108 | map_parseargs(map, ap) | |
109 | MAP *map; | |
110 | char *ap; | |
111 | { | |
112 | register char *p = ap; | |
113 | ||
3a363396 | 114 | map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; |
6f14531a RG |
115 | for (;;) |
116 | { | |
117 | while (isascii(*p) && isspace(*p)) | |
118 | p++; | |
119 | if (*p != '-') | |
120 | break; | |
121 | switch (*++p) | |
122 | { | |
123 | case 'N': | |
124 | map->map_mflags |= MF_INCLNULL; | |
3a363396 NW |
125 | map->map_mflags &= ~MF_TRY0NULL; |
126 | break; | |
127 | ||
128 | case 'O': | |
129 | map->map_mflags &= ~MF_TRY1NULL; | |
6f14531a RG |
130 | break; |
131 | ||
132 | case 'o': | |
133 | map->map_mflags |= MF_OPTIONAL; | |
134 | break; | |
135 | ||
136 | case 'f': | |
137 | map->map_mflags |= MF_NOFOLDCASE; | |
138 | break; | |
139 | ||
140 | case 'm': | |
141 | map->map_mflags |= MF_MATCHONLY; | |
142 | break; | |
143 | ||
144 | case 'a': | |
145 | map->map_app = ++p; | |
146 | break; | |
147 | } | |
148 | while (*p != '\0' && !(isascii(*p) && isspace(*p))) | |
149 | p++; | |
150 | if (*p != '\0') | |
151 | *p++ = '\0'; | |
152 | } | |
153 | if (map->map_app != NULL) | |
154 | map->map_app = newstr(map->map_app); | |
155 | ||
156 | if (*p != '\0') | |
157 | { | |
158 | map->map_file = p; | |
159 | while (*p != '\0' && !(isascii(*p) && isspace(*p))) | |
160 | p++; | |
161 | if (*p != '\0') | |
162 | *p++ = '\0'; | |
163 | map->map_file = newstr(map->map_file); | |
164 | } | |
165 | ||
166 | while (*p != '\0' && isascii(*p) && isspace(*p)) | |
167 | p++; | |
168 | if (*p != '\0') | |
169 | map->map_rebuild = newstr(p); | |
170 | ||
171 | if (map->map_file == NULL) | |
172 | { | |
173 | syserr("No file name for %s map %s", | |
174 | map->map_class->map_cname, map->map_mname); | |
175 | return FALSE; | |
176 | } | |
177 | return TRUE; | |
178 | } | |
179 | \f/* | |
180 | ** MAP_REWRITE -- rewrite a database key, interpolating %n indications. | |
181 | ** | |
182 | ** It also adds the map_app string. It can be used as a utility | |
183 | ** in the map_lookup method. | |
184 | ** | |
185 | ** Parameters: | |
186 | ** map -- the map that causes this. | |
187 | ** s -- the string to rewrite, NOT necessarily null terminated. | |
188 | ** slen -- the length of s. | |
189 | ** av -- arguments to interpolate into buf. | |
190 | ** | |
191 | ** Returns: | |
192 | ** Pointer to rewritten result. | |
193 | ** | |
194 | ** Side Effects: | |
195 | ** none. | |
196 | */ | |
197 | ||
198 | struct rwbuf | |
199 | { | |
200 | int rwb_len; /* size of buffer */ | |
201 | char *rwb_buf; /* ptr to buffer */ | |
202 | }; | |
203 | ||
204 | struct rwbuf RwBufs[2]; /* buffers for rewriting output */ | |
205 | ||
206 | char * | |
207 | map_rewrite(map, s, slen, av) | |
208 | register MAP *map; | |
209 | register char *s; | |
210 | int slen; | |
211 | char **av; | |
212 | { | |
213 | register char *bp; | |
214 | register char c; | |
215 | char **avp; | |
216 | register char *ap; | |
217 | register struct rwbuf *rwb; | |
218 | int i; | |
219 | int len; | |
220 | ||
221 | if (tTd(39, 1)) | |
222 | { | |
223 | printf("map_rewrite(%.*s), av =", slen, s); | |
224 | if (av == NULL) | |
225 | printf(" (nullv)"); | |
226 | else | |
227 | { | |
228 | for (avp = av; *avp != NULL; avp++) | |
229 | printf("\n\t%s", *avp); | |
230 | } | |
231 | printf("\n"); | |
232 | } | |
233 | ||
234 | rwb = RwBufs; | |
235 | if (av == NULL) | |
236 | rwb++; | |
237 | ||
238 | /* count expected size of output (can safely overestimate) */ | |
239 | i = len = slen; | |
240 | if (av != NULL) | |
241 | { | |
242 | bp = s; | |
243 | for (i = slen; --i >= 0 && (c = *bp++) != 0; ) | |
244 | { | |
245 | if (c != '%') | |
246 | continue; | |
247 | if (--i < 0) | |
248 | break; | |
249 | c = *bp++; | |
250 | if (!(isascii(c) && isdigit(c))) | |
251 | continue; | |
d747e748 | 252 | for (avp = av; --c >= '0' && *avp != NULL; avp++) |
6f14531a RG |
253 | continue; |
254 | if (*avp == NULL) | |
255 | continue; | |
256 | len += strlen(*avp); | |
257 | } | |
258 | } | |
259 | if (map->map_app != NULL) | |
260 | len += strlen(map->map_app); | |
261 | if (rwb->rwb_len < ++len) | |
262 | { | |
263 | /* need to malloc additional space */ | |
264 | rwb->rwb_len = len; | |
265 | if (rwb->rwb_buf != NULL) | |
266 | free(rwb->rwb_buf); | |
267 | rwb->rwb_buf = xalloc(rwb->rwb_len); | |
268 | } | |
269 | ||
270 | bp = rwb->rwb_buf; | |
271 | if (av == NULL) | |
272 | { | |
273 | bcopy(s, bp, slen); | |
274 | bp += slen; | |
275 | } | |
276 | else | |
277 | { | |
278 | while (--slen >= 0 && (c = *s++) != '\0') | |
279 | { | |
280 | if (c != '%') | |
281 | { | |
282 | pushc: | |
283 | *bp++ = c; | |
284 | continue; | |
285 | } | |
286 | if (--slen < 0 || (c = *s++) == '\0') | |
287 | c = '%'; | |
288 | if (c == '%') | |
289 | goto pushc; | |
290 | if (!(isascii(c) && isdigit(c))) | |
291 | { | |
292 | *bp++ = '%'; | |
293 | goto pushc; | |
294 | } | |
d747e748 | 295 | for (avp = av; --c >= '0' && *avp != NULL; avp++) |
6f14531a RG |
296 | continue; |
297 | if (*avp == NULL) | |
298 | continue; | |
299 | ||
300 | /* transliterate argument into output string */ | |
301 | for (ap = *avp; (c = *ap++) != '\0'; ) | |
302 | *bp++ = c; | |
303 | } | |
304 | } | |
305 | if (map->map_app != NULL) | |
306 | strcpy(bp, map->map_app); | |
307 | else | |
308 | *bp = '\0'; | |
309 | if (tTd(39, 1)) | |
310 | printf("map_rewrite => %s\n", rwb->rwb_buf); | |
311 | return rwb->rwb_buf; | |
312 | } | |
313 | \f/* | |
314 | ** INITMAPS -- initialize for aliasing | |
315 | ** | |
316 | ** Parameters: | |
317 | ** rebuild -- if TRUE, this rebuilds the cached versions. | |
318 | ** e -- current envelope. | |
319 | ** | |
320 | ** Returns: | |
321 | ** none. | |
322 | ** | |
323 | ** Side Effects: | |
324 | ** initializes aliases: | |
325 | ** if NDBM: opens the database. | |
326 | ** if ~NDBM: reads the aliases into the symbol table. | |
327 | */ | |
328 | ||
329 | initmaps(rebuild, e) | |
330 | bool rebuild; | |
331 | register ENVELOPE *e; | |
332 | { | |
333 | extern void map_init(); | |
334 | ||
d747e748 JH |
335 | #ifdef XDEBUG |
336 | checkfd012("entering initmaps"); | |
337 | #endif | |
6f14531a RG |
338 | CurEnv = e; |
339 | stabapply(map_init, rebuild); | |
d747e748 JH |
340 | #ifdef XDEBUG |
341 | checkfd012("exiting initmaps"); | |
342 | #endif | |
6f14531a RG |
343 | } |
344 | ||
345 | void | |
346 | map_init(s, rebuild) | |
347 | register STAB *s; | |
348 | int rebuild; | |
349 | { | |
350 | register MAP *map; | |
351 | ||
352 | /* has to be a map */ | |
353 | if (s->s_type != ST_MAP) | |
354 | return; | |
355 | ||
356 | map = &s->s_map; | |
357 | if (!bitset(MF_VALID, map->map_mflags)) | |
358 | return; | |
359 | ||
360 | if (tTd(38, 2)) | |
361 | printf("map_init(%s:%s)\n", | |
d747e748 JH |
362 | map->map_class->map_cname == NULL ? "NULL" : |
363 | map->map_class->map_cname, | |
364 | map->map_file == NULL ? "NULL" : map->map_file); | |
6f14531a RG |
365 | |
366 | /* if already open, close it (for nested open) */ | |
367 | if (bitset(MF_OPEN, map->map_mflags)) | |
368 | { | |
369 | map->map_class->map_close(map); | |
370 | map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); | |
371 | } | |
372 | ||
373 | if (rebuild) | |
374 | { | |
375 | if (bitset(MF_ALIAS, map->map_mflags) && | |
376 | bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) | |
377 | rebuildaliases(map, FALSE); | |
378 | } | |
379 | else | |
380 | { | |
381 | if (map->map_class->map_open(map, O_RDONLY)) | |
382 | { | |
383 | if (tTd(38, 4)) | |
384 | printf("%s:%s: valid\n", | |
d747e748 JH |
385 | map->map_class->map_cname == NULL ? "NULL" : |
386 | map->map_class->map_cname, | |
387 | map->map_file == NULL ? "NULL" : | |
388 | map->map_file); | |
6f14531a RG |
389 | map->map_mflags |= MF_OPEN; |
390 | } | |
391 | else if (tTd(38, 4)) | |
392 | printf("%s:%s: invalid: %s\n", | |
d747e748 JH |
393 | map->map_class->map_cname == NULL ? "NULL" : |
394 | map->map_class->map_cname, | |
395 | map->map_file == NULL ? "NULL" : | |
396 | map->map_file, | |
6f14531a RG |
397 | errstring(errno)); |
398 | } | |
399 | } | |
400 | \f/* | |
401 | ** NDBM modules | |
402 | */ | |
403 | ||
404 | #ifdef NDBM | |
405 | ||
406 | /* | |
407 | ** DBM_MAP_OPEN -- DBM-style map open | |
408 | */ | |
409 | ||
410 | bool | |
411 | ndbm_map_open(map, mode) | |
412 | MAP *map; | |
413 | int mode; | |
414 | { | |
d747e748 JH |
415 | register DBM *dbm; |
416 | struct stat st; | |
6f14531a RG |
417 | |
418 | if (tTd(38, 2)) | |
419 | printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); | |
420 | ||
421 | if (mode == O_RDWR) | |
422 | mode |= O_CREAT|O_TRUNC; | |
423 | ||
424 | /* open the database */ | |
425 | dbm = dbm_open(map->map_file, mode, DBMMODE); | |
426 | if (dbm == NULL) | |
427 | { | |
d747e748 JH |
428 | #ifdef MAYBENEXTRELEASE |
429 | if (aliaswait(map, ".pag", FALSE)) | |
430 | return TRUE; | |
431 | #endif | |
6f14531a RG |
432 | if (!bitset(MF_OPTIONAL, map->map_mflags)) |
433 | syserr("Cannot open DBM database %s", map->map_file); | |
434 | return FALSE; | |
435 | } | |
436 | map->map_db1 = (void *) dbm; | |
437 | if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) | |
d747e748 JH |
438 | if (!aliaswait(map, ".pag", TRUE)) |
439 | return FALSE; | |
440 | if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0) | |
441 | map->map_mtime = st.st_mtime; | |
6f14531a RG |
442 | return TRUE; |
443 | } | |
444 | ||
445 | ||
446 | /* | |
447 | ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map | |
448 | */ | |
449 | ||
450 | char * | |
451 | ndbm_map_lookup(map, name, av, statp) | |
452 | MAP *map; | |
453 | char *name; | |
454 | char **av; | |
455 | int *statp; | |
456 | { | |
457 | datum key, val; | |
d747e748 | 458 | int fd; |
6f14531a RG |
459 | char keybuf[MAXNAME + 1]; |
460 | ||
461 | if (tTd(38, 20)) | |
462 | printf("ndbm_map_lookup(%s)\n", name); | |
463 | ||
464 | key.dptr = name; | |
465 | key.dsize = strlen(name); | |
466 | if (!bitset(MF_NOFOLDCASE, map->map_mflags)) | |
467 | { | |
468 | if (key.dsize > sizeof keybuf - 1) | |
469 | key.dsize = sizeof keybuf - 1; | |
470 | bcopy(key.dptr, keybuf, key.dsize + 1); | |
471 | makelower(keybuf); | |
472 | key.dptr = keybuf; | |
473 | } | |
d747e748 JH |
474 | fd = dbm_dirfno((DBM *) map->map_db1); |
475 | if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) | |
476 | (void) lockfile(fd, map->map_file, ".dir", LOCK_SH); | |
3a363396 NW |
477 | val.dptr = NULL; |
478 | if (bitset(MF_TRY0NULL, map->map_mflags)) | |
479 | { | |
480 | val = dbm_fetch((DBM *) map->map_db1, key); | |
481 | if (val.dptr != NULL) | |
482 | map->map_mflags &= ~MF_TRY1NULL; | |
483 | } | |
484 | if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags)) | |
485 | { | |
486 | key.dsize++; | |
487 | val = dbm_fetch((DBM *) map->map_db1, key); | |
488 | if (val.dptr != NULL) | |
489 | map->map_mflags &= ~MF_TRY0NULL; | |
490 | } | |
d747e748 JH |
491 | if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) |
492 | (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); | |
6f14531a RG |
493 | if (val.dptr == NULL) |
494 | return NULL; | |
495 | if (bitset(MF_MATCHONLY, map->map_mflags)) | |
3a363396 NW |
496 | return map_rewrite(map, name, strlen(name), NULL); |
497 | else | |
498 | return map_rewrite(map, val.dptr, val.dsize, av); | |
6f14531a RG |
499 | } |
500 | ||
501 | ||
502 | /* | |
503 | ** DBM_MAP_STORE -- store a datum in the database | |
504 | */ | |
505 | ||
506 | void | |
507 | ndbm_map_store(map, lhs, rhs) | |
508 | register MAP *map; | |
509 | char *lhs; | |
510 | char *rhs; | |
511 | { | |
512 | datum key; | |
513 | datum data; | |
514 | int stat; | |
515 | ||
516 | if (tTd(38, 12)) | |
517 | printf("ndbm_map_store(%s, %s)\n", lhs, rhs); | |
518 | ||
519 | key.dsize = strlen(lhs); | |
520 | key.dptr = lhs; | |
521 | ||
522 | data.dsize = strlen(rhs); | |
523 | data.dptr = rhs; | |
524 | ||
525 | if (bitset(MF_INCLNULL, map->map_mflags)) | |
526 | { | |
527 | key.dsize++; | |
528 | data.dsize++; | |
529 | } | |
530 | ||
531 | stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); | |
532 | if (stat > 0) | |
533 | { | |
534 | usrerr("050 Warning: duplicate alias name %s", lhs); | |
535 | stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); | |
536 | } | |
537 | if (stat != 0) | |
538 | syserr("readaliases: dbm put (%s)", lhs); | |
539 | } | |
540 | ||
541 | ||
542 | /* | |
543 | ** NDBM_MAP_CLOSE -- close the database | |
544 | */ | |
545 | ||
546 | void | |
547 | ndbm_map_close(map) | |
548 | register MAP *map; | |
549 | { | |
550 | if (bitset(MF_WRITABLE, map->map_mflags)) | |
551 | { | |
d747e748 JH |
552 | #ifdef NIS |
553 | bool inclnull; | |
6f14531a RG |
554 | char buf[200]; |
555 | ||
d747e748 JH |
556 | inclnull = bitset(MF_INCLNULL, map->map_mflags); |
557 | map->map_mflags &= ~MF_INCLNULL; | |
558 | ||
6f14531a RG |
559 | (void) sprintf(buf, "%010ld", curtime()); |
560 | ndbm_map_store(map, "YP_LAST_MODIFIED", buf); | |
561 | ||
562 | (void) myhostname(buf, sizeof buf); | |
563 | ndbm_map_store(map, "YP_MASTER_NAME", buf); | |
d747e748 JH |
564 | |
565 | if (inclnull) | |
566 | map->map_mflags |= MF_INCLNULL; | |
6f14531a RG |
567 | #endif |
568 | ||
569 | /* write out the distinguished alias */ | |
570 | ndbm_map_store(map, "@", "@"); | |
571 | } | |
572 | dbm_close((DBM *) map->map_db1); | |
573 | } | |
574 | ||
575 | #endif | |
576 | \f/* | |
577 | ** NEWDB (Hash and BTree) Modules | |
578 | */ | |
579 | ||
580 | #ifdef NEWDB | |
581 | ||
582 | /* | |
583 | ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. | |
584 | ** | |
585 | ** These do rather bizarre locking. If you can lock on open, | |
586 | ** do that to avoid the condition of opening a database that | |
587 | ** is being rebuilt. If you don't, we'll try to fake it, but | |
588 | ** there will be a race condition. If opening for read-only, | |
589 | ** we immediately release the lock to avoid freezing things up. | |
590 | ** We really ought to hold the lock, but guarantee that we won't | |
591 | ** be pokey about it. That's hard to do. | |
592 | */ | |
593 | ||
594 | bool | |
595 | bt_map_open(map, mode) | |
596 | MAP *map; | |
597 | int mode; | |
598 | { | |
599 | DB *db; | |
600 | int i; | |
601 | int omode; | |
d747e748 JH |
602 | int fd; |
603 | struct stat st; | |
6f14531a RG |
604 | char buf[MAXNAME]; |
605 | ||
606 | if (tTd(38, 2)) | |
607 | printf("bt_map_open(%s, %d)\n", map->map_file, mode); | |
608 | ||
609 | omode = mode; | |
610 | if (omode == O_RDWR) | |
611 | { | |
612 | omode |= O_CREAT|O_TRUNC; | |
d747e748 | 613 | #if defined(O_EXLOCK) && defined(HASFLOCK) |
6f14531a RG |
614 | omode |= O_EXLOCK; |
615 | # if !defined(OLD_NEWDB) | |
616 | } | |
617 | else | |
618 | { | |
619 | omode |= O_SHLOCK; | |
620 | # endif | |
621 | #endif | |
622 | } | |
623 | ||
624 | (void) strcpy(buf, map->map_file); | |
625 | i = strlen(buf); | |
626 | if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) | |
627 | (void) strcat(buf, ".db"); | |
628 | db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); | |
629 | if (db == NULL) | |
630 | { | |
d747e748 JH |
631 | #ifdef MAYBENEXTRELEASE |
632 | if (aliaswait(map, ".db", FALSE)) | |
633 | return TRUE; | |
634 | #endif | |
6f14531a RG |
635 | if (!bitset(MF_OPTIONAL, map->map_mflags)) |
636 | syserr("Cannot open BTREE database %s", map->map_file); | |
637 | return FALSE; | |
638 | } | |
d747e748 JH |
639 | #if !defined(OLD_NEWDB) && defined(HASFLOCK) |
640 | fd = db->fd(db); | |
6f14531a | 641 | # if !defined(O_EXLOCK) |
d747e748 JH |
642 | if (mode == O_RDWR && fd >= 0) |
643 | { | |
644 | if (lockfile(fd, map->map_file, ".db", LOCK_EX)) | |
645 | map->map_mflags |= MF_LOCKED; | |
646 | } | |
6f14531a | 647 | # else |
d747e748 JH |
648 | if (mode == O_RDONLY && fd >= 0) |
649 | (void) lockfile(fd, map->map_file, ".db", LOCK_UN); | |
650 | else | |
651 | map->map_mflags |= MF_LOCKED; | |
6f14531a RG |
652 | # endif |
653 | #endif | |
654 | ||
655 | /* try to make sure that at least the database header is on disk */ | |
656 | if (mode == O_RDWR) | |
d747e748 JH |
657 | #ifdef OLD_NEWDB |
658 | (void) db->sync(db); | |
659 | #else | |
6f14531a RG |
660 | (void) db->sync(db, 0); |
661 | ||
d747e748 JH |
662 | if (fd >= 0 && fstat(fd, &st) >= 0) |
663 | map->map_mtime = st.st_mtime; | |
664 | #endif | |
665 | ||
6f14531a RG |
666 | map->map_db2 = (void *) db; |
667 | if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) | |
d747e748 JH |
668 | if (!aliaswait(map, ".db", TRUE)) |
669 | return FALSE; | |
6f14531a RG |
670 | return TRUE; |
671 | } | |
672 | ||
673 | ||
674 | /* | |
675 | ** HASH_MAP_INIT -- HASH-style map initialization | |
676 | */ | |
677 | ||
678 | bool | |
679 | hash_map_open(map, mode) | |
680 | MAP *map; | |
681 | int mode; | |
682 | { | |
683 | DB *db; | |
684 | int i; | |
685 | int omode; | |
d747e748 JH |
686 | int fd; |
687 | struct stat st; | |
6f14531a RG |
688 | char buf[MAXNAME]; |
689 | ||
690 | if (tTd(38, 2)) | |
691 | printf("hash_map_open(%s, %d)\n", map->map_file, mode); | |
692 | ||
693 | omode = mode; | |
694 | if (omode == O_RDWR) | |
695 | { | |
696 | omode |= O_CREAT|O_TRUNC; | |
d747e748 | 697 | #if defined(O_EXLOCK) && defined(HASFLOCK) |
6f14531a RG |
698 | omode |= O_EXLOCK; |
699 | # if !defined(OLD_NEWDB) | |
700 | } | |
701 | else | |
702 | { | |
703 | omode |= O_SHLOCK; | |
704 | # endif | |
705 | #endif | |
706 | } | |
707 | ||
708 | (void) strcpy(buf, map->map_file); | |
709 | i = strlen(buf); | |
710 | if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) | |
711 | (void) strcat(buf, ".db"); | |
712 | db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); | |
713 | if (db == NULL) | |
714 | { | |
d747e748 JH |
715 | #ifdef MAYBENEXTRELEASE |
716 | if (aliaswait(map, ".db", FALSE)) | |
717 | return TRUE; | |
718 | #endif | |
6f14531a RG |
719 | if (!bitset(MF_OPTIONAL, map->map_mflags)) |
720 | syserr("Cannot open HASH database %s", map->map_file); | |
721 | return FALSE; | |
722 | } | |
d747e748 JH |
723 | #if !defined(OLD_NEWDB) && defined(HASFLOCK) |
724 | fd = db->fd(db); | |
6f14531a | 725 | # if !defined(O_EXLOCK) |
d747e748 JH |
726 | if (mode == O_RDWR && fd >= 0) |
727 | { | |
728 | if (lockfile(fd, map->map_file, ".db", LOCK_EX)) | |
729 | map->map_mflags |= MF_LOCKED; | |
730 | } | |
6f14531a | 731 | # else |
d747e748 JH |
732 | if (mode == O_RDONLY && fd >= 0) |
733 | (void) lockfile(fd, map->map_file, ".db", LOCK_UN); | |
734 | else | |
735 | map->map_mflags |= MF_LOCKED; | |
6f14531a RG |
736 | # endif |
737 | #endif | |
738 | ||
739 | /* try to make sure that at least the database header is on disk */ | |
740 | if (mode == O_RDWR) | |
d747e748 JH |
741 | #ifdef OLD_NEWDB |
742 | (void) db->sync(db); | |
743 | #else | |
6f14531a RG |
744 | (void) db->sync(db, 0); |
745 | ||
d747e748 JH |
746 | if (fd >= 0 && fstat(fd, &st) >= 0) |
747 | map->map_mtime = st.st_mtime; | |
748 | #endif | |
749 | ||
6f14531a RG |
750 | map->map_db2 = (void *) db; |
751 | if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) | |
d747e748 JH |
752 | if (!aliaswait(map, ".db", TRUE)) |
753 | return FALSE; | |
6f14531a RG |
754 | return TRUE; |
755 | } | |
756 | ||
757 | ||
758 | /* | |
759 | ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map | |
760 | */ | |
761 | ||
762 | char * | |
763 | db_map_lookup(map, name, av, statp) | |
764 | MAP *map; | |
765 | char *name; | |
766 | char **av; | |
767 | int *statp; | |
768 | { | |
769 | DBT key, val; | |
770 | register DB *db = (DB *) map->map_db2; | |
771 | int st; | |
772 | int saveerrno; | |
d747e748 | 773 | int fd; |
6f14531a RG |
774 | char keybuf[MAXNAME + 1]; |
775 | ||
776 | if (tTd(38, 20)) | |
777 | printf("db_map_lookup(%s)\n", name); | |
778 | ||
779 | key.size = strlen(name); | |
780 | if (key.size > sizeof keybuf - 1) | |
781 | key.size = sizeof keybuf - 1; | |
782 | key.data = keybuf; | |
783 | bcopy(name, keybuf, key.size + 1); | |
784 | if (!bitset(MF_NOFOLDCASE, map->map_mflags)) | |
785 | makelower(keybuf); | |
6f14531a | 786 | #ifndef OLD_NEWDB |
d747e748 JH |
787 | fd = db->fd(db); |
788 | if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) | |
789 | (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH); | |
6f14531a | 790 | #endif |
3a363396 NW |
791 | st = 1; |
792 | if (bitset(MF_TRY0NULL, map->map_mflags)) | |
793 | { | |
794 | st = db->get(db, &key, &val, 0); | |
795 | if (st == 0) | |
796 | map->map_mflags &= ~MF_TRY1NULL; | |
797 | } | |
798 | if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) | |
799 | { | |
800 | key.size++; | |
801 | st = db->get(db, &key, &val, 0); | |
802 | if (st == 0) | |
803 | map->map_mflags &= ~MF_TRY0NULL; | |
804 | } | |
6f14531a RG |
805 | saveerrno = errno; |
806 | #ifndef OLD_NEWDB | |
d747e748 JH |
807 | if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) |
808 | (void) lockfile(fd, map->map_file, ".db", LOCK_UN); | |
6f14531a RG |
809 | #endif |
810 | if (st != 0) | |
811 | { | |
812 | errno = saveerrno; | |
813 | if (st < 0) | |
814 | syserr("db_map_lookup: get (%s)", name); | |
815 | return NULL; | |
816 | } | |
817 | if (bitset(MF_MATCHONLY, map->map_mflags)) | |
3a363396 NW |
818 | return map_rewrite(map, name, strlen(name), NULL); |
819 | else | |
820 | return map_rewrite(map, val.data, val.size, av); | |
6f14531a RG |
821 | } |
822 | ||
823 | ||
824 | /* | |
825 | ** DB_MAP_STORE -- store a datum in the NEWDB database | |
826 | */ | |
827 | ||
828 | void | |
829 | db_map_store(map, lhs, rhs) | |
830 | register MAP *map; | |
831 | char *lhs; | |
832 | char *rhs; | |
833 | { | |
834 | int stat; | |
835 | DBT key; | |
836 | DBT data; | |
837 | register DB *db = map->map_db2; | |
838 | ||
839 | if (tTd(38, 20)) | |
840 | printf("db_map_store(%s, %s)\n", lhs, rhs); | |
841 | ||
842 | key.size = strlen(lhs); | |
843 | key.data = lhs; | |
844 | ||
845 | data.size = strlen(rhs); | |
846 | data.data = rhs; | |
847 | ||
848 | if (bitset(MF_INCLNULL, map->map_mflags)) | |
849 | { | |
850 | key.size++; | |
851 | data.size++; | |
852 | } | |
853 | ||
854 | stat = db->put(db, &key, &data, R_NOOVERWRITE); | |
855 | if (stat > 0) | |
856 | { | |
857 | usrerr("050 Warning: duplicate alias name %s", lhs); | |
858 | stat = db->put(db, &key, &data, 0); | |
859 | } | |
860 | if (stat != 0) | |
861 | syserr("readaliases: db put (%s)", lhs); | |
862 | } | |
863 | ||
864 | ||
865 | /* | |
866 | ** DB_MAP_CLOSE -- add distinguished entries and close the database | |
867 | */ | |
868 | ||
869 | void | |
870 | db_map_close(map) | |
871 | MAP *map; | |
872 | { | |
873 | register DB *db = map->map_db2; | |
874 | ||
875 | if (tTd(38, 9)) | |
876 | printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); | |
877 | ||
878 | if (bitset(MF_WRITABLE, map->map_mflags)) | |
879 | { | |
880 | /* write out the distinguished alias */ | |
881 | db_map_store(map, "@", "@"); | |
882 | } | |
883 | ||
884 | if (db->close(db) != 0) | |
885 | syserr("readaliases: db close failure"); | |
886 | } | |
887 | ||
888 | #endif | |
889 | \f/* | |
890 | ** NIS Modules | |
891 | */ | |
892 | ||
893 | # ifdef NIS | |
894 | ||
d747e748 JH |
895 | # ifndef YPERR_BUSY |
896 | # define YPERR_BUSY 16 | |
897 | # endif | |
898 | ||
6f14531a RG |
899 | /* |
900 | ** NIS_MAP_OPEN -- open DBM map | |
901 | */ | |
902 | ||
903 | bool | |
904 | nis_map_open(map, mode) | |
905 | MAP *map; | |
906 | int mode; | |
907 | { | |
908 | int yperr; | |
909 | register char *p; | |
910 | auto char *vp; | |
911 | auto int vsize; | |
912 | char *master; | |
913 | ||
914 | if (tTd(38, 2)) | |
915 | printf("nis_map_open(%s)\n", map->map_file); | |
916 | ||
917 | if (mode != O_RDONLY) | |
918 | { | |
d747e748 JH |
919 | /* issue a pseudo-error message */ |
920 | #ifdef ENOSYS | |
921 | errno = ENOSYS; | |
922 | #else | |
923 | # ifdef EFTYPE | |
924 | errno = EFTYPE; | |
925 | # else | |
926 | errno = ENXIO; | |
927 | # endif | |
928 | #endif | |
6f14531a RG |
929 | return FALSE; |
930 | } | |
931 | ||
932 | p = strchr(map->map_file, '@'); | |
933 | if (p != NULL) | |
934 | { | |
935 | *p++ = '\0'; | |
936 | if (*p != '\0') | |
937 | map->map_domain = p; | |
938 | } | |
939 | ||
940 | if (map->map_domain == NULL) | |
941 | yp_get_default_domain(&map->map_domain); | |
942 | ||
943 | if (*map->map_file == '\0') | |
944 | map->map_file = "mail.aliases"; | |
945 | ||
946 | /* check to see if this map actually exists */ | |
947 | yperr = yp_match(map->map_domain, map->map_file, "@", 1, | |
948 | &vp, &vsize); | |
949 | if (tTd(38, 10)) | |
950 | printf("nis_map_open: yp_match(%s, %s) => %s\n", | |
951 | map->map_domain, map->map_file, yperr_string(yperr)); | |
952 | if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) | |
953 | return TRUE; | |
954 | ||
955 | if (!bitset(MF_OPTIONAL, map->map_mflags)) | |
956 | syserr("Cannot bind to domain %s: %s", map->map_domain, | |
957 | yperr_string(yperr)); | |
958 | ||
959 | return FALSE; | |
960 | } | |
961 | ||
962 | ||
963 | /* | |
964 | ** NIS_MAP_LOOKUP -- look up a datum in a NIS map | |
965 | */ | |
966 | ||
967 | char * | |
968 | nis_map_lookup(map, name, av, statp) | |
969 | MAP *map; | |
970 | char *name; | |
971 | char **av; | |
972 | int *statp; | |
973 | { | |
974 | char *vp; | |
975 | auto int vsize; | |
976 | int buflen; | |
977 | int yperr; | |
978 | char keybuf[MAXNAME + 1]; | |
979 | ||
980 | if (tTd(38, 20)) | |
981 | printf("nis_map_lookup(%s)\n", name); | |
982 | ||
983 | buflen = strlen(name); | |
984 | if (buflen > sizeof keybuf - 1) | |
985 | buflen = sizeof keybuf - 1; | |
986 | bcopy(name, keybuf, buflen + 1); | |
987 | if (!bitset(MF_NOFOLDCASE, map->map_mflags)) | |
988 | makelower(keybuf); | |
3a363396 NW |
989 | yperr = YPERR_KEY; |
990 | if (bitset(MF_TRY0NULL, map->map_mflags)) | |
991 | { | |
992 | yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, | |
993 | &vp, &vsize); | |
994 | if (yperr == 0) | |
995 | map->map_mflags &= ~MF_TRY1NULL; | |
996 | } | |
997 | if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) | |
998 | { | |
6f14531a | 999 | buflen++; |
3a363396 NW |
1000 | yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, |
1001 | &vp, &vsize); | |
1002 | if (yperr == 0) | |
1003 | map->map_mflags &= ~MF_TRY0NULL; | |
1004 | } | |
6f14531a RG |
1005 | if (yperr != 0) |
1006 | { | |
1007 | if (yperr != YPERR_KEY && yperr != YPERR_BUSY) | |
1008 | map->map_mflags &= ~(MF_VALID|MF_OPEN); | |
1009 | return NULL; | |
1010 | } | |
1011 | if (bitset(MF_MATCHONLY, map->map_mflags)) | |
3a363396 NW |
1012 | return map_rewrite(map, name, strlen(name), NULL); |
1013 | else | |
1014 | return map_rewrite(map, vp, vsize, av); | |
6f14531a RG |
1015 | } |
1016 | ||
1017 | ||
1018 | /* | |
1019 | ** NIS_MAP_STORE | |
1020 | */ | |
1021 | ||
1022 | void | |
1023 | nis_map_store(map, lhs, rhs) | |
1024 | MAP *map; | |
1025 | char *lhs; | |
1026 | char *rhs; | |
1027 | { | |
1028 | /* nothing */ | |
1029 | } | |
1030 | ||
1031 | ||
1032 | /* | |
1033 | ** NIS_MAP_CLOSE | |
1034 | */ | |
1035 | ||
1036 | void | |
1037 | nis_map_close(map) | |
1038 | MAP *map; | |
1039 | { | |
1040 | /* nothing */ | |
1041 | } | |
1042 | ||
1043 | #endif /* NIS */ | |
1044 | \f/* | |
1045 | ** STAB (Symbol Table) Modules | |
1046 | */ | |
1047 | ||
1048 | ||
1049 | /* | |
1050 | ** STAB_MAP_LOOKUP -- look up alias in symbol table | |
1051 | */ | |
1052 | ||
1053 | char * | |
1054 | stab_map_lookup(map, name, av, pstat) | |
1055 | register MAP *map; | |
1056 | char *name; | |
1057 | char **av; | |
1058 | int *pstat; | |
1059 | { | |
1060 | register STAB *s; | |
1061 | ||
1062 | if (tTd(38, 20)) | |
1063 | printf("stab_lookup(%s)\n", name); | |
1064 | ||
1065 | s = stab(name, ST_ALIAS, ST_FIND); | |
1066 | if (s != NULL) | |
1067 | return (s->s_alias); | |
1068 | return (NULL); | |
1069 | } | |
1070 | ||
1071 | ||
1072 | /* | |
1073 | ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) | |
1074 | */ | |
1075 | ||
1076 | void | |
1077 | stab_map_store(map, lhs, rhs) | |
1078 | register MAP *map; | |
1079 | char *lhs; | |
1080 | char *rhs; | |
1081 | { | |
1082 | register STAB *s; | |
1083 | ||
1084 | s = stab(lhs, ST_ALIAS, ST_ENTER); | |
1085 | s->s_alias = newstr(rhs); | |
1086 | } | |
1087 | ||
1088 | ||
1089 | /* | |
1090 | ** STAB_MAP_OPEN -- initialize (reads data file) | |
1091 | ** | |
1092 | ** This is a wierd case -- it is only intended as a fallback for | |
1093 | ** aliases. For this reason, opens for write (only during a | |
1094 | ** "newaliases") always fails, and opens for read open the | |
1095 | ** actual underlying text file instead of the database. | |
1096 | */ | |
1097 | ||
1098 | bool | |
1099 | stab_map_open(map, mode) | |
1100 | register MAP *map; | |
1101 | int mode; | |
1102 | { | |
d747e748 JH |
1103 | FILE *af; |
1104 | struct stat st; | |
1105 | ||
6f14531a RG |
1106 | if (tTd(38, 2)) |
1107 | printf("stab_map_open(%s)\n", map->map_file); | |
1108 | ||
1109 | if (mode != O_RDONLY) | |
1110 | { | |
1111 | errno = ENODEV; | |
1112 | return FALSE; | |
1113 | } | |
1114 | ||
d747e748 JH |
1115 | af = fopen(map->map_file, "r"); |
1116 | if (af == NULL) | |
1117 | return FALSE; | |
1118 | readaliases(map, af, TRUE); | |
1119 | ||
1120 | if (fstat(fileno(af), &st) >= 0) | |
1121 | map->map_mtime = st.st_mtime; | |
1122 | fclose(af); | |
1123 | ||
6f14531a RG |
1124 | return TRUE; |
1125 | } | |
1126 | ||
1127 | ||
1128 | /* | |
d747e748 JH |
1129 | ** STAB_MAP_CLOSE -- close symbol table. |
1130 | ** | |
1131 | ** Since this is in memory, there is nothing to do. | |
6f14531a RG |
1132 | */ |
1133 | ||
1134 | void | |
1135 | stab_map_close(map) | |
1136 | MAP *map; | |
1137 | { | |
1138 | /* ignore it */ | |
1139 | } | |
1140 | \f/* | |
1141 | ** Implicit Modules | |
1142 | ** | |
1143 | ** Tries several types. For back compatibility of aliases. | |
1144 | */ | |
1145 | ||
1146 | ||
1147 | /* | |
1148 | ** IMPL_MAP_LOOKUP -- lookup in best open database | |
1149 | */ | |
1150 | ||
1151 | char * | |
1152 | impl_map_lookup(map, name, av, pstat) | |
1153 | MAP *map; | |
1154 | char *name; | |
1155 | char **av; | |
1156 | int *pstat; | |
1157 | { | |
1158 | if (tTd(38, 20)) | |
1159 | printf("impl_map_lookup(%s)\n", name); | |
1160 | ||
1161 | #ifdef NEWDB | |
1162 | if (bitset(MF_IMPL_HASH, map->map_mflags)) | |
1163 | return db_map_lookup(map, name, av, pstat); | |
1164 | #endif | |
1165 | #ifdef NDBM | |
1166 | if (bitset(MF_IMPL_NDBM, map->map_mflags)) | |
1167 | return ndbm_map_lookup(map, name, av, pstat); | |
1168 | #endif | |
1169 | return stab_map_lookup(map, name, av, pstat); | |
1170 | } | |
1171 | ||
1172 | /* | |
1173 | ** IMPL_MAP_STORE -- store in open databases | |
1174 | */ | |
1175 | ||
1176 | void | |
1177 | impl_map_store(map, lhs, rhs) | |
1178 | MAP *map; | |
1179 | char *lhs; | |
1180 | char *rhs; | |
1181 | { | |
1182 | #ifdef NEWDB | |
1183 | if (bitset(MF_IMPL_HASH, map->map_mflags)) | |
1184 | db_map_store(map, lhs, rhs); | |
1185 | #endif | |
1186 | #ifdef NDBM | |
1187 | if (bitset(MF_IMPL_NDBM, map->map_mflags)) | |
1188 | ndbm_map_store(map, lhs, rhs); | |
1189 | #endif | |
1190 | stab_map_store(map, lhs, rhs); | |
1191 | } | |
1192 | ||
1193 | /* | |
1194 | ** IMPL_MAP_OPEN -- implicit database open | |
1195 | */ | |
1196 | ||
1197 | bool | |
1198 | impl_map_open(map, mode) | |
1199 | MAP *map; | |
1200 | int mode; | |
1201 | { | |
1202 | struct stat stb; | |
1203 | ||
1204 | if (tTd(38, 2)) | |
d747e748 | 1205 | printf("impl_map_open(%s, %d)\n", map->map_file, mode); |
6f14531a RG |
1206 | |
1207 | if (stat(map->map_file, &stb) < 0) | |
1208 | { | |
1209 | /* no alias file at all */ | |
d747e748 JH |
1210 | if (tTd(38, 3)) |
1211 | printf("no map file\n"); | |
6f14531a RG |
1212 | return FALSE; |
1213 | } | |
1214 | ||
1215 | #ifdef NEWDB | |
1216 | map->map_mflags |= MF_IMPL_HASH; | |
1217 | if (hash_map_open(map, mode)) | |
1218 | { | |
d747e748 | 1219 | #if defined(NDBM) && defined(NIS) |
6f14531a RG |
1220 | if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) |
1221 | #endif | |
1222 | return TRUE; | |
1223 | } | |
1224 | else | |
1225 | map->map_mflags &= ~MF_IMPL_HASH; | |
1226 | #endif | |
1227 | #ifdef NDBM | |
1228 | map->map_mflags |= MF_IMPL_NDBM; | |
1229 | if (ndbm_map_open(map, mode)) | |
1230 | { | |
1231 | return TRUE; | |
1232 | } | |
1233 | else | |
1234 | map->map_mflags &= ~MF_IMPL_NDBM; | |
1235 | #endif | |
1236 | ||
d747e748 | 1237 | #if defined(NEWDB) || defined(NDBM) |
6f14531a RG |
1238 | if (Verbose) |
1239 | message("WARNING: cannot open alias database %s", map->map_file); | |
1240 | #endif | |
1241 | ||
1242 | return stab_map_open(map, mode); | |
1243 | } | |
1244 | ||
1245 | ||
1246 | /* | |
1247 | ** IMPL_MAP_CLOSE -- close any open database(s) | |
1248 | */ | |
1249 | ||
1250 | void | |
1251 | impl_map_close(map) | |
1252 | MAP *map; | |
1253 | { | |
1254 | #ifdef NEWDB | |
1255 | if (bitset(MF_IMPL_HASH, map->map_mflags)) | |
1256 | { | |
1257 | db_map_close(map); | |
1258 | map->map_mflags &= ~MF_IMPL_HASH; | |
1259 | } | |
1260 | #endif | |
1261 | ||
1262 | #ifdef NDBM | |
1263 | if (bitset(MF_IMPL_NDBM, map->map_mflags)) | |
1264 | { | |
1265 | ndbm_map_close(map); | |
1266 | map->map_mflags &= ~MF_IMPL_NDBM; | |
1267 | } | |
1268 | #endif | |
1269 | } | |
1270 | \f/* | |
1271 | ** NULL stubs | |
1272 | */ | |
1273 | ||
1274 | bool | |
1275 | null_map_open(map, mode) | |
1276 | MAP *map; | |
1277 | int mode; | |
1278 | { | |
1279 | return TRUE; | |
1280 | } | |
1281 | ||
1282 | void | |
1283 | null_map_close(map) | |
1284 | MAP *map; | |
1285 | { | |
1286 | return; | |
1287 | } | |
1288 | ||
1289 | void | |
1290 | null_map_store(map, key, val) | |
1291 | MAP *map; | |
1292 | char *key; | |
1293 | char *val; | |
1294 | { | |
1295 | return; | |
1296 | } |