xref: /original-bsd/usr.sbin/sendmail/src/map.c (revision 37861f82)
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	6.14 (Berkeley) 05/17/93";
11 #endif /* not lint */
12 
13 #include "sendmail.h"
14 
15 #ifdef NDBM
16 #include <ndbm.h>
17 #endif
18 #ifdef NEWDB
19 #include <db.h>
20 #endif
21 #ifdef NIS
22 #include <rpcsvc/ypclnt.h>
23 #endif
24 
25 /*
26 **  MAP.C -- implementations for various map classes.
27 **
28 **	Each map class implements a series of functions:
29 **
30 **	bool map_parse(MAP *map, char *args)
31 **		Parse the arguments from the config file.  Return TRUE
32 **		if they were ok, FALSE otherwise.  Fill in map with the
33 **		values.
34 **
35 **	char *map_lookup(MAP *map, char buf[], int bufsize,
36 **			 char **args, int *pstat)
37 **		Look up the key given in buf in the given map.  If found,
38 **		do any rewriting the map wants (including "args" if desired)
39 **		and return the value.  Set *pstat to the appropriate status
40 **		on error and return NULL.
41 **
42 **	void map_store(MAP *map, char *key, char *value)
43 **		Store the key:value pair in the map.
44 **
45 **	void map_rebuild(MAP *map, FILE *fp, int automatic)
46 **		Rebuild the map.  If automatic is set, this is an
47 **		auto-rebuild.
48 **
49 **	bool map_open(MAP *map, int mode)
50 **		Open the map for the indicated mode.  Return TRUE if it
51 **		was opened successfully, FALSE otherwise.
52 **
53 **	void map_close(MAP *map)
54 **		Close the map.
55 */
56 
57 #define DBMMODE		0644
58 /*
59 **  MAP_PARSEARGS -- parse config line arguments for database lookup
60 **
61 **	This is a generic version of the map_parse method.
62 **
63 **	Parameters:
64 **		map -- the map being initialized.
65 **		ap -- a pointer to the args on the config line.
66 **
67 **	Returns:
68 **		TRUE -- if everything parsed OK.
69 **		FALSE -- otherwise.
70 **
71 **	Side Effects:
72 **		null terminates the filename; stores it in map
73 */
74 
75 bool
76 map_parseargs(map, ap)
77 	MAP *map;
78 	char *ap;
79 {
80 	register char *p = ap;
81 
82 	for (;;)
83 	{
84 		while (isascii(*p) && isspace(*p))
85 			p++;
86 		if (*p != '-')
87 			break;
88 		switch (*++p)
89 		{
90 		  case 'N':
91 			map->map_flags |= MF_INCLNULL;
92 			break;
93 
94 		  case 'o':
95 			map->map_flags |= MF_OPTIONAL;
96 			break;
97 
98 		  case 'f':
99 			map->map_flags |= MF_NOFOLDCASE;
100 			break;
101 
102 		  case 'm':
103 			map->map_flags |= MF_MATCHONLY;
104 			break;
105 
106 		  case 'a':
107 			map->map_app = ++p;
108 			break;
109 
110 		  case 'd':
111 			map->map_domain = ++p;
112 			break;
113 		}
114 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
115 			p++;
116 		if (*p != '\0')
117 			*p++ = '\0';
118 	}
119 	if (map->map_app != NULL)
120 		map->map_app = newstr(map->map_app);
121 	if (map->map_domain != NULL)
122 		map->map_domain = newstr(map->map_domain);
123 
124 	if (*p != '\0')
125 	{
126 		map->map_file = p;
127 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
128 			p++;
129 		if (*p != '\0')
130 			*p++ = '\0';
131 		map->map_file = newstr(map->map_file);
132 	}
133 
134 	while (*p != '\0' && isascii(*p) && isspace(*p))
135 		p++;
136 	if (*p != '\0')
137 		map->map_rebuild = newstr(p);
138 
139 	if (map->map_file == NULL)
140 	{
141 		syserr("No file name for %s map %s",
142 			map->map_class->map_cname, map->map_mname);
143 		return FALSE;
144 	}
145 	return TRUE;
146 }
147 /*
148 **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
149 **
150 **	It also adds the map_app string.  It can be used as a utility
151 **	in the map_lookup method.
152 **
153 **	Parameters:
154 **		map -- the map that causes this.
155 **		s -- the string to rewrite, NOT necessarily null terminated.
156 **		slen -- the length of s.
157 **		av -- arguments to interpolate into buf.
158 **
159 **	Returns:
160 **		Pointer to rewritten result.
161 **
162 **	Side Effects:
163 **		none.
164 */
165 
166 char *
167 map_rewrite(map, s, slen, av)
168 	register MAP *map;
169 	register char *s;
170 	int slen;
171 	char **av;
172 {
173 	register char *bp;
174 	register char c;
175 	char **avp;
176 	register char *ap;
177 	int i;
178 	int len;
179 	static int buflen = -1;
180 	static char *buf = NULL;
181 
182 	if (tTd(23, 1))
183 	{
184 		printf("map_rewrite(%.*s), av =\n", slen, s);
185 		for (avp = av; *avp != NULL; avp++)
186 			printf("\t%s\n", *avp);
187 	}
188 
189 	/* count expected size of output (can safely overestimate) */
190 	i = len = slen;
191 	if (av != NULL)
192 	{
193 		bp = s;
194 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
195 		{
196 			if (c != '%')
197 				continue;
198 			if (--i < 0)
199 				break;
200 			c = *bp++;
201 			if (!(isascii(c) && isdigit(c)))
202 				continue;
203 			c -= 0;
204 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
205 				continue;
206 			if (*avp == NULL)
207 				continue;
208 			len += strlen(*avp);
209 		}
210 	}
211 	if (map->map_app != NULL)
212 		len += strlen(map->map_app);
213 	if (buflen < ++len)
214 	{
215 		/* need to malloc additional space */
216 		buflen = len;
217 		if (buf != NULL)
218 			free(buf);
219 		buf = xalloc(buflen);
220 	}
221 
222 	bp = buf;
223 	if (av == NULL)
224 	{
225 		bcopy(s, bp, slen);
226 		bp += slen;
227 	}
228 	else
229 	{
230 		while (--slen >= 0 && (c = *s++) != '\0')
231 		{
232 			if (c != '%')
233 			{
234   pushc:
235 				*bp++ = c;
236 				continue;
237 			}
238 			if (--slen < 0 || (c = *s++) == '\0')
239 				c = '%';
240 			if (c == '%')
241 				goto pushc;
242 			if (!(isascii(c) && isdigit(c)))
243 			{
244 				*bp++ = '%';
245 				goto pushc;
246 			}
247 			c -= '0';
248 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
249 				continue;
250 			if (*avp == NULL)
251 				continue;
252 
253 			/* transliterate argument into output string */
254 			for (ap = *avp; (c = *ap++) != '\0'; )
255 				*bp++ = c;
256 		}
257 	}
258 	if (map->map_app != NULL)
259 		strcpy(bp, map->map_app);
260 	else
261 		*bp = '\0';
262 	if (tTd(23, 1))
263 		printf("map_rewrite => %s\n", buf);
264 	return buf;
265 }
266 /*
267 **  NDBM modules
268 */
269 
270 #ifdef NDBM
271 
272 /*
273 **  DBM_MAP_OPEN -- DBM-style map open
274 */
275 
276 bool
277 ndbm_map_open(map, mode)
278 	MAP *map;
279 	int mode;
280 {
281 	DBM *dbm;
282 
283 	if (tTd(27, 2))
284 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
285 
286 	/* open the database */
287 	dbm = dbm_open(map->map_file, mode, DBMMODE);
288 	if (dbm == NULL)
289 	{
290 		if (!bitset(MF_OPTIONAL, map->map_flags))
291 			syserr("Cannot open DBM database %s", map->map_file);
292 		return FALSE;
293 	}
294 	map->map_db1 = (void *) dbm;
295 	return TRUE;
296 }
297 
298 
299 /*
300 **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
301 */
302 
303 char *
304 ndbm_map_lookup(map, name, av, statp)
305 	MAP *map;
306 	char *name;
307 	char **av;
308 	int *statp;
309 {
310 	datum key, val;
311 	char keybuf[MAXNAME + 1];
312 
313 	if (tTd(27, 20))
314 		printf("ndbm_map_lookup(%s)\n", name);
315 
316 	key.dptr = name;
317 	key.dsize = strlen(name);
318 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
319 	{
320 		if (key.dsize > sizeof keybuf - 1)
321 			key.dsize = sizeof keybuf - 1;
322 		bcopy(key.dptr, keybuf, key.dsize + 1);
323 		makelower(keybuf);
324 		key.dptr = keybuf;
325 	}
326 	if (bitset(MF_INCLNULL, map->map_flags))
327 		key.dsize++;
328 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
329 	val = dbm_fetch((DBM *) map->map_db1, key);
330 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
331 	if (val.dptr == NULL)
332 		return NULL;
333 	if (bitset(MF_MATCHONLY, map->map_flags))
334 		av = NULL;
335 	return map_rewrite(map, val.dptr, val.dsize, av);
336 }
337 
338 
339 /*
340 **  DBM_MAP_STORE -- store a datum in the database
341 */
342 
343 void
344 ndbm_map_store(map, lhs, rhs)
345 	register MAP *map;
346 	char *lhs;
347 	char *rhs;
348 {
349 	datum key;
350 	datum data;
351 	int stat;
352 
353 	if (tTd(27, 12))
354 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
355 
356 	key.dsize = strlen(lhs);
357 	key.dptr = lhs;
358 
359 	data.dsize = strlen(rhs);
360 	data.dptr = rhs;
361 
362 	if (bitset(MF_INCLNULL, map->map_flags))
363 	{
364 		key.dsize++;
365 		data.dsize++;
366 	}
367 
368 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
369 	if (stat > 0)
370 	{
371 		usrerr("050 Warning: duplicate alias name %s", lhs);
372 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
373 	}
374 	if (stat != 0)
375 		syserr("readaliases: dbm put (%s)", lhs);
376 }
377 
378 
379 /*
380 **  DBM_MAP_REBUILD -- rebuild DBM database
381 */
382 
383 void
384 ndbm_map_rebuild(map, fp, automatic)
385 	register MAP *map;
386 	FILE *fp;
387 	int automatic;
388 {
389 	register DBM *db;
390 	int i;
391 	char buf[MAXNAME];
392 
393 	if (tTd(27, 2))
394 		printf("ndbm_map_rebuild(%s)\n", map->map_file);
395 
396 	db = dbm_open(map->map_file, O_RDWR|O_CREAT|O_TRUNC, DBMMODE);
397 	if (db == NULL)
398 	{
399 		syserr("ndbm_map_rebuild: cannot create %s", buf);
400 		return;
401 	}
402 	map->map_db1 = (void *) db;
403 	map->map_flags |= MF_WRITABLE|MF_VALID;
404 }
405 
406 /*
407 **  NDBM_ACLOSE -- close the database
408 */
409 
410 void
411 ndbm_map_close(map)
412 	register MAP  *map;
413 {
414 	if (bitset(MF_WRITABLE, map->map_flags))
415 	{
416 #ifdef YPCOMPAT
417 		char buf[200];
418 
419 		(void) sprintf(buf, "%010ld", curtime());
420 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
421 
422 		(void) myhostname(buf, sizeof buf);
423 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
424 #endif
425 
426 		/* write out the distinguished alias */
427 		ndbm_map_store(map, "@", "@");
428 	}
429 	dbm_close((DBM *) map->map_db1);
430 }
431 
432 #endif
433 /*
434 **  HASH (NEWDB) Modules
435 */
436 
437 #ifdef NEWDB
438 
439 /*
440 **  BTREE_MAP_PARSE -- BTREE-style map initialization
441 */
442 
443 bool
444 bt_map_open(map, mode)
445 	MAP *map;
446 	int mode;
447 {
448 	DB *db;
449 	char buf[MAXNAME];
450 
451 	if (tTd(27, 2))
452 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
453 
454 	(void) sprintf(buf, "%s.db", map->map_file);
455 	db = dbopen(buf, mode, 0644, DB_BTREE, NULL);
456 	if (db == NULL)
457 	{
458 		if (!bitset(MF_OPTIONAL, map->map_flags))
459 			syserr("Cannot open BTREE database %s", map->map_file);
460 		return FALSE;
461 	}
462 	map->map_db2 = (void *) db;
463 	return TRUE;
464 }
465 
466 
467 /*
468 **  HASH_MAP_INIT -- HASH-style map initialization
469 */
470 
471 bool
472 hash_map_open(map, mode)
473 	MAP *map;
474 	int mode;
475 {
476 	DB *db;
477 	char buf[MAXNAME];
478 
479 	if (tTd(27, 2))
480 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
481 
482 	(void) sprintf(buf, "%s.db", map->map_file);
483 	db = dbopen(buf, mode, 0644, DB_HASH, NULL);
484 	if (db == NULL)
485 	{
486 		if (!bitset(MF_OPTIONAL, map->map_flags))
487 			syserr("Cannot open HASH database %s", map->map_file);
488 		return FALSE;
489 	}
490 	map->map_db2 = (void *) db;
491 	return TRUE;
492 }
493 
494 
495 /*
496 **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
497 */
498 
499 char *
500 db_map_lookup(map, name, av, statp)
501 	MAP *map;
502 	char *name;
503 	char **av;
504 	int *statp;
505 {
506 	DBT key, val;
507 	char keybuf[MAXNAME + 1];
508 
509 	if (tTd(27, 20))
510 		printf("db_map_lookup(%s)\n", name);
511 
512 	key.size = strlen(name);
513 	if (key.size > sizeof keybuf - 1)
514 		key.size = sizeof keybuf - 1;
515 	key.data = keybuf;
516 	bcopy(name, keybuf, key.size + 1);
517 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
518 		makelower(keybuf);
519 	if (bitset(MF_INCLNULL, map->map_flags))
520 		key.size++;
521 	if (((DB *) map->map_db2)->get((DB *) map->map_db2, &key, &val, 0) != 0)
522 		return NULL;
523 	if (bitset(MF_MATCHONLY, map->map_flags))
524 		av = NULL;
525 	return map_rewrite(map, val.data, val.size, av);
526 }
527 
528 
529 /*
530 **  DB_MAP_STORE -- store a datum in the NEWDB database
531 */
532 
533 void
534 db_map_store(map, lhs, rhs)
535 	register MAP *map;
536 	char *lhs;
537 	char *rhs;
538 {
539 	int stat;
540 	DBT key;
541 	DBT data;
542 	register DB *db = map->map_db2;
543 
544 	if (tTd(27, 20))
545 		printf("db_map_store(%s, %s)\n", lhs, rhs);
546 
547 	key.size = strlen(lhs);
548 	key.data = lhs;
549 
550 	data.size = strlen(rhs);
551 	data.data = rhs;
552 
553 	if (bitset(MF_INCLNULL, map->map_flags))
554 	{
555 		key.size++;
556 		data.size++;
557 	}
558 
559 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
560 	if (stat > 0)
561 	{
562 		usrerr("050 Warning: duplicate alias name %s", lhs);
563 		stat = db->put(db, &key, &data, 0);
564 	}
565 	if (stat != 0)
566 		syserr("readaliases: db put (%s)", lhs);
567 }
568 
569 
570 /*
571 **  HASH_MAP_REBUILD -- rebuild hash database
572 */
573 
574 void
575 db_map_rebuild(map, fp, automatic, e)
576 	register MAP *map;
577 	FILE *fp;
578 	int automatic;
579 	ENVELOPE *e;
580 {
581 	register DB *db;
582 	char buf[MAXNAME];
583 
584 	if (tTd(27, 2))
585 		printf("hash_map_rebuild(%s)\n", map->map_file);
586 
587 	(void) strcpy(buf, map->map_file);
588 	(void) strcat(buf, ".db");
589 	db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL);
590 	if (db == NULL)
591 	{
592 		syserr("hash_map_rebuild: cannot create %s", buf);
593 		return;
594 	}
595 	map->map_db2 = db;
596 	map->map_flags |= MF_WRITABLE|MF_VALID;
597 }
598 
599 
600 /*
601 **  DB_MAP_CLOSE -- add distinguished entries and close the database
602 */
603 
604 void
605 db_map_close(map)
606 	MAP *map;
607 {
608 	register DB *db = map->map_db2;
609 
610 	if (tTd(27, 9))
611 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_flags);
612 
613 	if (bitset(MF_WRITABLE, map->map_flags))
614 	{
615 		/* write out the distinguished alias */
616 		db_map_store(map, "@", "@");
617 	}
618 
619 	if (db->close(db) != 0)
620 		syserr("readaliases: db close failure");
621 }
622 
623 #endif
624 /*
625 **  NIS Modules
626 */
627 
628 # ifdef NIS
629 
630 /*
631 **  NIS_MAP_OPEN -- open DBM map
632 */
633 
634 bool
635 nis_map_open(map, mode)
636 	MAP *map;
637 	int mode;
638 {
639 	int yperr;
640 	char *master;
641 
642 	if (tTd(27, 2))
643 		printf("nis_map_open(%s)\n", map->map_file);
644 
645 	if (map->map_domain == NULL)
646 		yp_get_default_domain(&map->map_domain);
647 
648 	/* check to see if this map actually exists */
649 	yperr = yp_master(map->map_domain, map->map_file, &master);
650 	if (yperr == 0)
651 		return TRUE;
652 	if (!bitset(MF_OPTIONAL, map->map_flags))
653 		syserr("Cannot bind to domain %s: %s", map->map_domain,
654 			yperr_string(yperr));
655 	return FALSE;
656 }
657 
658 bool
659 nis_map_open(map, mode)
660 	MAP *map;
661 	int mode;
662 {
663 	register char *p;
664 	int yperr;
665 	auto char *vp;
666 	auto int vsize;
667 
668 	p = strchr(map->map_file, '@');
669 	if (p != NULL)
670 	{
671 		*p++ = '\0';
672 		if (*p != '\0')
673 			map->map_domain = p;
674 	}
675 	if (map->map_domain == NULL)
676 		yp_get_default_domain(&map->map_domain);
677 
678 	if (*map->map_file == '\0')
679 		map->map_file = "mail.aliases";
680 
681 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
682 			&vp, &vsize);
683 	if (tTd(27, 10))
684 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
685 			map->map_domain, map->map_file, yperr_string(yperr));
686 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
687 		return TRUE;
688 	return FALSE;
689 }
690 
691 
692 /*
693 **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
694 */
695 
696 char *
697 nis_map_lookup(map, name, av, statp)
698 	MAP *map;
699 	char *name;
700 	char **av;
701 	int *statp;
702 {
703 	char *vp;
704 	auto int vsize;
705 	int buflen;
706 	char keybuf[MAXNAME + 1];
707 
708 	if (tTd(27, 20))
709 		printf("nis_map_lookup(%s)\n", name);
710 
711 	buflen = strlen(name);
712 	if (buflen > sizeof keybuf - 1)
713 		buflen = sizeof keybuf - 1;
714 	bcopy(name, keybuf, buflen + 1);
715 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
716 		makelower(keybuf);
717 	if (bitset(MF_INCLNULL, map->map_flags))
718 		buflen++;
719 	yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
720 		     &vp, &vsize);
721 	if (yperr != 0)
722 	{
723 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
724 			map->map_flags &= ~MF_VALID;
725 		return NULL;
726 	}
727 	if (bitset(MF_MATCHONLY, map->map_flags))
728 		av = NULL;
729 	return map_rewrite(map, val.dptr, val.dsize, av);
730 }
731 
732 
733 /*
734 **  NIS_ASTORE
735 */
736 
737 void
738 nis_map_store(map, lhs, rhs)
739 	MAP *map;
740 	char *lhs;
741 	char *rhs;
742 {
743 	/* nothing */
744 }
745 
746 /*
747 **  NIS_AREBUILD
748 */
749 
750 void
751 nis_map_rebuild(map, fp, automatic, e)
752 	MAP *map;
753 	FILE *fp;
754 	int automatic;
755 	ENVELOPE *e;
756 {
757 	if (tTd(27, 2))
758 		printf("nis_map_rebuild(%s)\n", map->map_file);
759 }
760 
761 
762 /*
763 **  NIS_ACLOSE
764 */
765 
766 void
767 nis_map_close(map)
768 	MAP *map;
769 {
770 	/* nothing */
771 }
772 
773 #endif /* NIS */
774 /*
775 **  STAB (Symbol Table) Modules
776 */
777 
778 
779 /*
780 **  STAB_ALOOKUP -- look up alias in symbol table
781 */
782 
783 char *
784 stab_map_lookup(map, name)
785 	register MAP *map;
786 	char *name;
787 {
788 	register STAB *s;
789 
790 	if (tTd(27, 20))
791 		printf("stab_lookup(%s)\n", name);
792 
793 	s = stab(name, ST_ALIAS, ST_FIND);
794 	if (s != NULL)
795 		return (s->s_alias);
796 	return (NULL);
797 }
798 
799 
800 /*
801 **  STAB_ASTORE -- store in symtab (actually using during init, not rebuild)
802 */
803 
804 void
805 stab_map_store(map, lhs, rhs)
806 	register MAP *map;
807 	char *lhs;
808 	char *rhs;
809 {
810 	register STAB *s;
811 
812 	s = stab(lhs, ST_ALIAS, ST_ENTER);
813 	s->s_alias = newstr(rhs);
814 }
815 
816 
817 /*
818 **  STAB_AINIT -- initialize (reads data file)
819 */
820 
821 bool
822 stab_map_open(map, mode)
823 	register MAP *map;
824 	int mode;
825 {
826 	FILE *af;
827 
828 	if (tTd(27, 2))
829 		printf("stab_map_open(%s)\n", map->map_file);
830 
831 	if (mode != O_RDONLY)
832 		return FALSE;
833 
834 	af = fopen(map->map_file, "r");
835 	if (af == NULL)
836 		return FALSE;
837 	return TRUE;
838 }
839 
840 
841 /*
842 **  STAB_AREBUILD -- rebuild alias file
843 */
844 
845 void
846 stab_map_rebuild(map, fp, automatic, e)
847 	MAP *map;
848 	FILE *fp;
849 	int automatic;
850 	ENVELOPE *e;
851 {
852 	if (tTd(27, 2))
853 		printf("stab_map_rebuild(%s)\n", map->map_file);
854 
855 	map->map_flags |= MF_WRITABLE|MF_VALID;
856 }
857 
858 
859 /*
860 **  STAB_ACLOSE -- close symbol table (???)
861 */
862 
863 void
864 stab_map_close(map)
865 	MAP *map;
866 {
867 	/* ignore it */
868 }
869 /*
870 **  Implicit Modules
871 **
872 **	Tries several types.  For back compatibility of aliases.
873 */
874 
875 
876 /*
877 **  IMPL_ALOOKUP -- lookup in best open database
878 */
879 
880 char *
881 impl_map_lookup(map, name, av, pstat)
882 	MAP *map;
883 	char *name;
884 	char **av;
885 	int *pstat;
886 {
887 	if (tTd(27, 20))
888 		printf("impl_map_lookup(%s)\n", name);
889 
890 #ifdef NEWDB
891 	if (bitset(MF_IMPL_HASH, map->map_flags))
892 		return db_map_lookup(map, name, av, pstat);
893 #endif
894 #ifdef NDBM
895 	if (bitset(MF_IMPL_NDBM, map->map_flags))
896 		return ndbm_map_lookup(map, name, av, pstat);
897 #endif
898 	return stab_map_lookup(map, name, av, pstat);
899 }
900 
901 /*
902 **  IMPL_ASTORE -- store in open databases
903 */
904 
905 void
906 impl_map_store(map, lhs, rhs)
907 	MAP *map;
908 	char *lhs;
909 	char *rhs;
910 {
911 #ifdef NEWDB
912 	if (bitset(MF_IMPL_HASH, map->map_flags))
913 		db_map_store(map, lhs, rhs);
914 #endif
915 #ifdef NDBM
916 	if (bitset(MF_IMPL_NDBM, map->map_flags))
917 		ndbm_map_store(map, lhs, rhs);
918 #endif
919 	stab_map_store(map, lhs, rhs);
920 }
921 
922 /*
923 **  IMPL_MAP_OPEN -- implicit database open
924 */
925 
926 bool
927 impl_map_open(map, mode)
928 	MAP *map;
929 	int mode;
930 {
931 	struct stat stb;
932 
933 	if (tTd(27, 2))
934 		printf("impl_map_open(%s)\n", map->map_file);
935 
936 	if (stat(map->map_file, &stb) < 0)
937 	{
938 		/* no alias file at all */
939 		return FALSE;
940 	}
941 
942 #ifdef NEWDB
943 	if (hash_map_open(map, mode))
944 	{
945 		map->map_flags |= MF_IMPL_HASH;
946 		return TRUE;
947 	}
948 #endif
949 #ifdef NDBM
950 	if (ndbm_map_open(map, mode))
951 	{
952 		map->map_flags |= MF_IMPL_NDBM;
953 		return TRUE;
954 	}
955 #endif
956 
957 	if (Verbose)
958 		message("WARNING: cannot open alias database %s", map->map_file);
959 
960 	if (stab_map_open(map, mode))
961 	{
962 		return TRUE;
963 	}
964 
965 	return FALSE;
966 }
967 
968 /*
969 **  IMPL_AREBUILD -- rebuild alias database
970 */
971 
972 void
973 impl_map_rebuild(map, fp, automatic, e)
974 	MAP *map;
975 	FILE *fp;
976 	int automatic;
977 	ENVELOPE *e;
978 {
979 #ifdef NEWDB
980 	DB *ndb;
981 	char buf[MAXNAME];
982 #endif
983 
984 	if (tTd(27, 2))
985 		printf("impl_map_rebuild(%s)\n", map->map_file);
986 
987 #ifdef NEWDB
988 	(void) strcpy(buf, map->map_file);
989 	(void) strcat(buf, ".db");
990 	ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL);
991 	if (ndb == NULL)
992 	{
993 		syserr("rebuildaliases: cannot create %s", buf);
994 	}
995 	else
996 	{
997 		map->map_db2 = ndb;
998 		map->map_flags |= MF_IMPL_HASH;
999 #if defined(NDBM) && defined(YPCOMPAT)
1000 		if (access("/var/yp/Makefile", R_OK) != 0)
1001 #endif
1002 			goto readem;
1003 	}
1004 #endif
1005 
1006 #ifdef NDBM
1007 	map->map_db1 = (void *) dbm_open(map->map_file, O_RDWR|O_CREAT|O_TRUNC, DBMMODE);
1008 	if (map->map_db1 == NULL)
1009 	{
1010 		syserr("rebuildaliases: cannot create %s.{pag,dir}",
1011 			map->map_file);
1012 	}
1013 	else
1014 	{
1015 		map->map_flags |= MF_IMPL_NDBM;
1016 	}
1017 #endif
1018 
1019 	if (!bitset(MF_IMPL_HASH|MF_IMPL_NDBM, map->map_flags))
1020 		return;
1021 
1022   readem:
1023 	map->map_flags |= MF_WRITABLE|MF_VALID;
1024 }
1025 
1026 
1027 /*
1028 **  IMPL_ACLOSE -- close any open database(s)
1029 */
1030 
1031 void
1032 impl_map_close(map, e)
1033 	MAP *map;
1034 	ENVELOPE *e;
1035 {
1036 #ifdef NEWDB
1037 	if (bitset(MF_IMPL_HASH, map->map_flags))
1038 		db_map_close(map, e);
1039 #endif
1040 
1041 #ifdef NDBM
1042 	if (bitset(MF_IMPL_NDBM, map->map_flags))
1043 		ndbm_map_close(map, e);
1044 #endif
1045 }
1046 /*
1047 **  SETUPALIASES -- set up aliases classes
1048 */
1049 
1050 extern bool	host_map_init __P((MAP *, char *));
1051 extern char	*host_map_lookup __P((MAP *, char *, char **, int *));
1052 
1053 extern bool	dequote_init __P((MAP *, char *));
1054 extern char	*dequote_map __P((MAP *, char *, char **, int *));
1055 
1056 #if 0
1057 extern bool	udb_map_parse __P((MAP *, char *));
1058 extern char	*udb_map_lookup __P((MAP *, char *, char **, int *));
1059 #endif
1060 
1061 static MAPCLASS	MapClasses[] =
1062 {
1063 #ifdef NEWDB
1064 	{
1065 		"hash",		".db",	map_parseargs,
1066 		db_map_lookup,		db_map_store,
1067 		db_map_rebuild,		hash_map_open,	db_map_close,
1068 	},
1069 
1070 	{
1071 		"btree",	".db",	map_parseargs,
1072 		db_map_lookup,		db_map_store,
1073 		db_map_rebuild,		bt_map_open,	db_map_close,
1074 	},
1075 #endif
1076 
1077 #ifdef NDBM
1078 	{
1079 		"dbm",		".dir",	map_parseargs,
1080 		ndbm_map_lookup,	ndbm_map_store,
1081 		ndbm_map_rebuild,	ndbm_map_open,	ndbm_map_close,
1082 	},
1083 #endif
1084 
1085 #ifdef NIS
1086 	{
1087 		"nis",		NULL,	map_parseargs,
1088 		nis_map_lookup,		NULL,
1089 		NULL,			nis_map_open,	nis_map_close,
1090 	},
1091 #endif
1092 
1093 	{
1094 		"stab",		NULL,	map_parseargs,
1095 		stab_map_lookup,	stab_map_store,
1096 		NULL,			stab_map_open,	stab_map_close,
1097 	},
1098 
1099 	{
1100 		"implicit",	NULL,	map_parseargs,
1101 		impl_map_lookup,	impl_map_store,
1102 		impl_map_rebuild,	impl_map_open,	impl_map_close,
1103 	},
1104 
1105 	/* host DNS lookup */
1106 	{
1107 		"host",		NULL,	host_map_init,
1108 		host_map_lookup,	NULL,
1109 		NULL,			NULL,		NULL,
1110 	},
1111 
1112 	/* dequote map */
1113 	{
1114 		"dequote",	NULL,	dequote_init,
1115 		dequote_map,		NULL,
1116 		NULL,			NULL,		NULL,
1117 	},
1118 
1119 #if 0
1120 # ifdef USERDB
1121 	/* user database */
1122 	{
1123 		"udb",		".db",	udb_map_parse,
1124 		udb_map_lookup,		NULL,
1125 		NULL,			NULL,		NULL,
1126 	},
1127 # endif
1128 #endif
1129 
1130 	{
1131 		NULL
1132 	}
1133 };
1134 
1135 setupmaps()
1136 {
1137 	register MAPCLASS *mc;
1138 	register STAB *s;
1139 
1140 	for (mc = MapClasses; mc->map_cname != NULL; mc++)
1141 	{
1142 		s = stab(mc->map_cname, ST_MAPCLASS, ST_ENTER);
1143 		s->s_mapclass = mc;
1144 	}
1145 }
1146