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