xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 60492)
156822Seric /*
256822Seric  * Copyright (c) 1992 Eric P. Allman.
356822Seric  * Copyright (c) 1992 Regents of the University of California.
456822Seric  * All rights reserved.
556822Seric  *
656822Seric  * %sccs.include.redist.c%
756822Seric  */
856822Seric 
956822Seric #ifndef lint
10*60492Seric static char sccsid[] = "@(#)map.c	6.21 (Berkeley) 05/27/93";
1156822Seric #endif /* not lint */
1256822Seric 
1356822Seric #include "sendmail.h"
1456822Seric 
1560089Seric #ifdef NDBM
1656822Seric #include <ndbm.h>
1756822Seric #endif
1860089Seric #ifdef NEWDB
1956822Seric #include <db.h>
2056822Seric #endif
2160089Seric #ifdef NIS
2257208Seric #include <rpcsvc/ypclnt.h>
2357208Seric #endif
2456822Seric 
2556822Seric /*
2660089Seric **  MAP.C -- implementations for various map classes.
2756822Seric **
2860089Seric **	Each map class implements a series of functions:
2960089Seric **
3060089Seric **	bool map_parse(MAP *map, char *args)
3160089Seric **		Parse the arguments from the config file.  Return TRUE
3260089Seric **		if they were ok, FALSE otherwise.  Fill in map with the
3360089Seric **		values.
3460089Seric **
3560222Seric **	char *map_lookup(MAP *map, char *key, char **args, int *pstat)
3660222Seric **		Look up the key in the given map.  If found, do any
3760222Seric **		rewriting the map wants (including "args" if desired)
3860089Seric **		and return the value.  Set *pstat to the appropriate status
3960222Seric **		on error and return NULL.  Args will be NULL if called
4060222Seric **		from the alias routines, although this should probably
4160222Seric **		not be relied upon.  It is suggested you call map_rewrite
4260222Seric **		to return the results -- it takes care of null termination
4360222Seric **		and uses a dynamically expanded buffer as needed.
4460089Seric **
4560089Seric **	void map_store(MAP *map, char *key, char *value)
4660089Seric **		Store the key:value pair in the map.
4760089Seric **
4860089Seric **	bool map_open(MAP *map, int mode)
4960222Seric **		Open the map for the indicated mode.  Mode should
5060222Seric **		be either O_RDONLY or O_RDWR.  Return TRUE if it
5160222Seric **		was opened successfully, FALSE otherwise.  If the open
5260222Seric **		failed an the MF_OPTIONAL flag is not set, it should
5360222Seric **		also print an error.  If the MF_ALIAS bit is set
5460222Seric **		and this map class understands the @:@ convention, it
5560222Seric **		should call aliaswait() before returning.
5660089Seric **
5760089Seric **	void map_close(MAP *map)
5860089Seric **		Close the map.
5960089Seric */
6060089Seric 
6160089Seric #define DBMMODE		0644
6260089Seric /*
6360089Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
6460089Seric **
6560089Seric **	This is a generic version of the map_parse method.
6660089Seric **
6756822Seric **	Parameters:
6860089Seric **		map -- the map being initialized.
6960089Seric **		ap -- a pointer to the args on the config line.
7056822Seric **
7156822Seric **	Returns:
7260089Seric **		TRUE -- if everything parsed OK.
7356822Seric **		FALSE -- otherwise.
7456822Seric **
7556822Seric **	Side Effects:
7660089Seric **		null terminates the filename; stores it in map
7756822Seric */
7856822Seric 
7956822Seric bool
8060089Seric map_parseargs(map, ap)
8156822Seric 	MAP *map;
8260089Seric 	char *ap;
8356822Seric {
8460089Seric 	register char *p = ap;
8556822Seric 
8660089Seric 	for (;;)
8760089Seric 	{
8860089Seric 		while (isascii(*p) && isspace(*p))
8960089Seric 			p++;
9060089Seric 		if (*p != '-')
9160089Seric 			break;
9260089Seric 		switch (*++p)
9360089Seric 		{
9460089Seric 		  case 'N':
9560207Seric 			map->map_mflags |= MF_INCLNULL;
9660089Seric 			break;
9760089Seric 
9860089Seric 		  case 'o':
9960207Seric 			map->map_mflags |= MF_OPTIONAL;
10060089Seric 			break;
10160089Seric 
10260089Seric 		  case 'f':
10360207Seric 			map->map_mflags |= MF_NOFOLDCASE;
10460089Seric 			break;
10560089Seric 
10660089Seric 		  case 'm':
10760207Seric 			map->map_mflags |= MF_MATCHONLY;
10860089Seric 			break;
10960089Seric 
11060089Seric 		  case 'a':
11160089Seric 			map->map_app = ++p;
11260089Seric 			break;
11360089Seric 		}
11460089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
11560089Seric 			p++;
11660089Seric 		if (*p != '\0')
11760089Seric 			*p++ = '\0';
11860089Seric 	}
11960089Seric 	if (map->map_app != NULL)
12060089Seric 		map->map_app = newstr(map->map_app);
12160089Seric 
12260089Seric 	if (*p != '\0')
12360089Seric 	{
12460089Seric 		map->map_file = p;
12560089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
12660089Seric 			p++;
12760089Seric 		if (*p != '\0')
12860089Seric 			*p++ = '\0';
12960089Seric 		map->map_file = newstr(map->map_file);
13060089Seric 	}
13160089Seric 
13260089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
13360089Seric 		p++;
13460089Seric 	if (*p != '\0')
13560089Seric 		map->map_rebuild = newstr(p);
13660089Seric 
13756822Seric 	if (map->map_file == NULL)
13857208Seric 	{
13960089Seric 		syserr("No file name for %s map %s",
14060089Seric 			map->map_class->map_cname, map->map_mname);
14156822Seric 		return FALSE;
14257208Seric 	}
14360089Seric 	return TRUE;
14460089Seric }
14560089Seric /*
14660089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
14760089Seric **
14860089Seric **	It also adds the map_app string.  It can be used as a utility
14960089Seric **	in the map_lookup method.
15060089Seric **
15160089Seric **	Parameters:
15260089Seric **		map -- the map that causes this.
15360089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
15460089Seric **		slen -- the length of s.
15560089Seric **		av -- arguments to interpolate into buf.
15660089Seric **
15760089Seric **	Returns:
15860089Seric **		Pointer to rewritten result.
15960089Seric **
16060089Seric **	Side Effects:
16160089Seric **		none.
16260089Seric */
16360089Seric 
164*60492Seric struct rwbuf
165*60492Seric {
166*60492Seric 	int	rwb_len;	/* size of buffer */
167*60492Seric 	char	*rwb_buf;	/* ptr to buffer */
168*60492Seric };
169*60492Seric 
170*60492Seric struct rwbuf	RwBufs[2];	/* buffers for rewriting output */
171*60492Seric 
17260089Seric char *
17360089Seric map_rewrite(map, s, slen, av)
17460089Seric 	register MAP *map;
17560089Seric 	register char *s;
17660089Seric 	int slen;
17760089Seric 	char **av;
17860089Seric {
17960089Seric 	register char *bp;
18060089Seric 	register char c;
18160089Seric 	char **avp;
18260089Seric 	register char *ap;
183*60492Seric 	register struct rwbuf *rwb;
18460089Seric 	int i;
18560089Seric 	int len;
18660089Seric 
18760089Seric 	if (tTd(23, 1))
18860089Seric 	{
18960256Seric 		printf("map_rewrite(%.*s), av =", slen, s);
19060256Seric 		if (av == NULL)
19160256Seric 			printf(" (nullv)");
19260256Seric 		else
19360256Seric 		{
19460256Seric 			for (avp = av; *avp != NULL; avp++)
19560256Seric 				printf("\n\t%s", *avp);
19660256Seric 		}
19760256Seric 		printf("\n");
19860089Seric 	}
19960089Seric 
200*60492Seric 	rwb = RwBufs;
201*60492Seric 	if (av == NULL)
202*60492Seric 		rwb++;
203*60492Seric 
20460089Seric 	/* count expected size of output (can safely overestimate) */
20560089Seric 	i = len = slen;
20660089Seric 	if (av != NULL)
20760089Seric 	{
20860089Seric 		bp = s;
20960089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
21060089Seric 		{
21160089Seric 			if (c != '%')
21260089Seric 				continue;
21360089Seric 			if (--i < 0)
21460089Seric 				break;
21560089Seric 			c = *bp++;
21660089Seric 			if (!(isascii(c) && isdigit(c)))
21760089Seric 				continue;
21860089Seric 			c -= 0;
21960089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
22060089Seric 				continue;
22160089Seric 			if (*avp == NULL)
22260089Seric 				continue;
22360089Seric 			len += strlen(*avp);
22460089Seric 		}
22560089Seric 	}
22660089Seric 	if (map->map_app != NULL)
22760089Seric 		len += strlen(map->map_app);
228*60492Seric 	if (rwb->rwb_len < ++len)
22960089Seric 	{
23060089Seric 		/* need to malloc additional space */
231*60492Seric 		rwb->rwb_len = len;
232*60492Seric 		if (rwb->rwb_buf != NULL)
233*60492Seric 			free(rwb->rwb_buf);
234*60492Seric 		rwb->rwb_buf = xalloc(rwb->rwb_len);
23560089Seric 	}
23660089Seric 
237*60492Seric 	bp = rwb->rwb_buf;
23860089Seric 	if (av == NULL)
23960089Seric 	{
24060089Seric 		bcopy(s, bp, slen);
24160089Seric 		bp += slen;
24260089Seric 	}
24360089Seric 	else
24460089Seric 	{
24560089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
24660089Seric 		{
24760089Seric 			if (c != '%')
24860089Seric 			{
24960089Seric   pushc:
25060089Seric 				*bp++ = c;
25160089Seric 				continue;
25260089Seric 			}
25360089Seric 			if (--slen < 0 || (c = *s++) == '\0')
25460089Seric 				c = '%';
25560089Seric 			if (c == '%')
25660089Seric 				goto pushc;
25760089Seric 			if (!(isascii(c) && isdigit(c)))
25860089Seric 			{
25960089Seric 				*bp++ = '%';
26060089Seric 				goto pushc;
26160089Seric 			}
26260089Seric 			c -= '0';
26360089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
26460089Seric 				continue;
26560089Seric 			if (*avp == NULL)
26660089Seric 				continue;
26760089Seric 
26860089Seric 			/* transliterate argument into output string */
26960089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
27060089Seric 				*bp++ = c;
27160089Seric 		}
27260089Seric 	}
27360089Seric 	if (map->map_app != NULL)
27460089Seric 		strcpy(bp, map->map_app);
27560089Seric 	else
27660089Seric 		*bp = '\0';
27760089Seric 	if (tTd(23, 1))
278*60492Seric 		printf("map_rewrite => %s\n", rwb->rwb_buf);
279*60492Seric 	return rwb->rwb_buf;
28060089Seric }
28160089Seric /*
28260089Seric **  NDBM modules
28360089Seric */
28460089Seric 
28560089Seric #ifdef NDBM
28660089Seric 
28760089Seric /*
28860089Seric **  DBM_MAP_OPEN -- DBM-style map open
28960089Seric */
29060089Seric 
29160089Seric bool
29260089Seric ndbm_map_open(map, mode)
29360089Seric 	MAP *map;
29460089Seric 	int mode;
29560089Seric {
29660089Seric 	DBM *dbm;
29760089Seric 
29860089Seric 	if (tTd(27, 2))
29960089Seric 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
30060089Seric 
30160207Seric 	if (mode == O_RDWR)
30260207Seric 		mode |= O_CREAT|O_TRUNC;
30360207Seric 
30460089Seric 	/* open the database */
30560089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
30656822Seric 	if (dbm == NULL)
30756822Seric 	{
30860207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
30956836Seric 			syserr("Cannot open DBM database %s", map->map_file);
31056822Seric 		return FALSE;
31156822Seric 	}
31260089Seric 	map->map_db1 = (void *) dbm;
31360207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
31460207Seric 		aliaswait(map, ".dir");
31556822Seric 	return TRUE;
31656822Seric }
31760089Seric 
31860089Seric 
31960089Seric /*
32056822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
32156822Seric */
32256822Seric 
32356822Seric char *
32460089Seric ndbm_map_lookup(map, name, av, statp)
32556822Seric 	MAP *map;
32660089Seric 	char *name;
32756822Seric 	char **av;
32859084Seric 	int *statp;
32956822Seric {
33056822Seric 	datum key, val;
33160089Seric 	char keybuf[MAXNAME + 1];
33256822Seric 
33360089Seric 	if (tTd(27, 20))
33460089Seric 		printf("ndbm_map_lookup(%s)\n", name);
33560089Seric 
33660089Seric 	key.dptr = name;
33760089Seric 	key.dsize = strlen(name);
33860207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
33957014Seric 	{
34060089Seric 		if (key.dsize > sizeof keybuf - 1)
34160089Seric 			key.dsize = sizeof keybuf - 1;
34260089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
34360089Seric 		makelower(keybuf);
34460089Seric 		key.dptr = keybuf;
34557014Seric 	}
34660207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
34756822Seric 		key.dsize++;
34860089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
34960089Seric 	val = dbm_fetch((DBM *) map->map_db1, key);
35060089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
35156822Seric 	if (val.dptr == NULL)
35256822Seric 		return NULL;
35360207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
35460089Seric 		av = NULL;
35560089Seric 	return map_rewrite(map, val.dptr, val.dsize, av);
35656822Seric }
35756822Seric 
35856822Seric 
35956822Seric /*
36060089Seric **  DBM_MAP_STORE -- store a datum in the database
36156822Seric */
36256822Seric 
36360089Seric void
36460089Seric ndbm_map_store(map, lhs, rhs)
36560089Seric 	register MAP *map;
36660089Seric 	char *lhs;
36760089Seric 	char *rhs;
36860089Seric {
36960089Seric 	datum key;
37060089Seric 	datum data;
37160089Seric 	int stat;
37260089Seric 
37360089Seric 	if (tTd(27, 12))
37460089Seric 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
37560089Seric 
37660089Seric 	key.dsize = strlen(lhs);
37760089Seric 	key.dptr = lhs;
37860089Seric 
37960089Seric 	data.dsize = strlen(rhs);
38060089Seric 	data.dptr = rhs;
38160089Seric 
38260207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
38360089Seric 	{
38460089Seric 		key.dsize++;
38560089Seric 		data.dsize++;
38660089Seric 	}
38760089Seric 
38860089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
38960089Seric 	if (stat > 0)
39060089Seric 	{
39160089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
39260089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
39360089Seric 	}
39460089Seric 	if (stat != 0)
39560089Seric 		syserr("readaliases: dbm put (%s)", lhs);
39660089Seric }
39760089Seric 
39860089Seric 
39960089Seric /*
40060207Seric **  NDBM_MAP_CLOSE -- close the database
40160089Seric */
40260089Seric 
40360089Seric void
40460089Seric ndbm_map_close(map)
40560089Seric 	register MAP  *map;
40660089Seric {
40760207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
40860089Seric 	{
40960089Seric #ifdef YPCOMPAT
41060089Seric 		char buf[200];
41160089Seric 
41260089Seric 		(void) sprintf(buf, "%010ld", curtime());
41360089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
41460089Seric 
41560089Seric 		(void) myhostname(buf, sizeof buf);
41660089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
41760089Seric #endif
41860089Seric 
41960089Seric 		/* write out the distinguished alias */
42060089Seric 		ndbm_map_store(map, "@", "@");
42160089Seric 	}
42260089Seric 	dbm_close((DBM *) map->map_db1);
42360089Seric }
42460089Seric 
42560089Seric #endif
42660089Seric /*
42760089Seric **  HASH (NEWDB) Modules
42860089Seric */
42960089Seric 
43060089Seric #ifdef NEWDB
43160089Seric 
43260089Seric /*
43360089Seric **  BTREE_MAP_PARSE -- BTREE-style map initialization
43460089Seric */
43560089Seric 
43656822Seric bool
43760089Seric bt_map_open(map, mode)
43856822Seric 	MAP *map;
43960089Seric 	int mode;
44056822Seric {
44156822Seric 	DB *db;
44260228Seric 	int i;
44360089Seric 	char buf[MAXNAME];
44456822Seric 
44560089Seric 	if (tTd(27, 2))
44660089Seric 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
44760089Seric 
44860207Seric 	if (mode == O_RDWR)
44960207Seric 		mode |= O_CREAT|O_TRUNC;
45060207Seric 
45160228Seric 	(void) strcpy(buf, map->map_file);
45260228Seric 	i = strlen(buf);
45360228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
45460228Seric 		(void) strcat(buf, ".db");
45560222Seric 	db = dbopen(buf, mode, DBMMODE, DB_BTREE, NULL);
45656822Seric 	if (db == NULL)
45756822Seric 	{
45860207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
45956836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
46056822Seric 		return FALSE;
46156822Seric 	}
46260089Seric 	map->map_db2 = (void *) db;
46360207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
46460207Seric 		aliaswait(map, ".db");
46556822Seric 	return TRUE;
46656822Seric }
46756822Seric 
46856822Seric 
46956822Seric /*
47056822Seric **  HASH_MAP_INIT -- HASH-style map initialization
47156822Seric */
47256822Seric 
47356822Seric bool
47460089Seric hash_map_open(map, mode)
47556822Seric 	MAP *map;
47660089Seric 	int mode;
47756822Seric {
47856822Seric 	DB *db;
47960228Seric 	int i;
48060089Seric 	char buf[MAXNAME];
48156822Seric 
48260089Seric 	if (tTd(27, 2))
48360089Seric 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
48460089Seric 
48560207Seric 	if (mode == O_RDWR)
48660207Seric 		mode |= O_CREAT|O_TRUNC;
48760207Seric 
48860228Seric 	(void) strcpy(buf, map->map_file);
48960228Seric 	i = strlen(buf);
49060228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
49160228Seric 		(void) strcat(buf, ".db");
49260222Seric 	db = dbopen(buf, mode, DBMMODE, DB_HASH, NULL);
49356822Seric 	if (db == NULL)
49456822Seric 	{
49560207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
49656836Seric 			syserr("Cannot open HASH database %s", map->map_file);
49756822Seric 		return FALSE;
49856822Seric 	}
49960089Seric 	map->map_db2 = (void *) db;
50060207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
50160207Seric 		aliaswait(map, ".db");
50256822Seric 	return TRUE;
50356822Seric }
50456822Seric 
50556822Seric 
50656822Seric /*
50756822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
50856822Seric */
50956822Seric 
51056822Seric char *
51160089Seric db_map_lookup(map, name, av, statp)
51256822Seric 	MAP *map;
51360089Seric 	char *name;
51456822Seric 	char **av;
51559084Seric 	int *statp;
51656822Seric {
51756822Seric 	DBT key, val;
51860422Seric 	register DB *db = (DB *) map->map_db2;
51960422Seric 	int st;
52060422Seric 	int saveerrno;
52160089Seric 	char keybuf[MAXNAME + 1];
52256822Seric 
52360089Seric 	if (tTd(27, 20))
52460089Seric 		printf("db_map_lookup(%s)\n", name);
52560089Seric 
52660089Seric 	key.size = strlen(name);
52760089Seric 	if (key.size > sizeof keybuf - 1)
52860089Seric 		key.size = sizeof keybuf - 1;
52960089Seric 	key.data = keybuf;
53060089Seric 	bcopy(name, keybuf, key.size + 1);
53160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
53260089Seric 		makelower(keybuf);
53360207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
53456822Seric 		key.size++;
53560422Seric #ifndef OLD_NEWDB
53660422Seric 	(void) lockfile(db->fd(db), map->map_file, LOCK_SH);
53760422Seric #endif
53860422Seric 	st = db->get(db, &key, &val, 0);
53960422Seric 	saveerrno = errno;
54060422Seric #ifndef OLD_NEWDB
54160422Seric 	(void) lockfile(db->fd(db), map->map_file, LOCK_UN);
54260422Seric #endif
54360422Seric 	if (st != 0)
54460422Seric 	{
54560422Seric 		errno = saveerrno;
54660422Seric 		if (st < 0)
54760422Seric 			syserr("db_map_lookup: get (%s)", name);
54856822Seric 		return NULL;
54960422Seric 	}
55060207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
55160089Seric 		av = NULL;
55260089Seric 	return map_rewrite(map, val.data, val.size, av);
55356822Seric }
55456822Seric 
55560089Seric 
55660089Seric /*
55760089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
55856822Seric */
55956822Seric 
56060089Seric void
56160089Seric db_map_store(map, lhs, rhs)
56260089Seric 	register MAP *map;
56360089Seric 	char *lhs;
56460089Seric 	char *rhs;
56556822Seric {
56660089Seric 	int stat;
56760089Seric 	DBT key;
56860089Seric 	DBT data;
56960089Seric 	register DB *db = map->map_db2;
57056822Seric 
57160089Seric 	if (tTd(27, 20))
57260089Seric 		printf("db_map_store(%s, %s)\n", lhs, rhs);
57360089Seric 
57460089Seric 	key.size = strlen(lhs);
57560089Seric 	key.data = lhs;
57660089Seric 
57760089Seric 	data.size = strlen(rhs);
57860089Seric 	data.data = rhs;
57960089Seric 
58060207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
58156822Seric 	{
58260089Seric 		key.size++;
58360089Seric 		data.size++;
58460089Seric 	}
58556836Seric 
58660089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
58760089Seric 	if (stat > 0)
58860089Seric 	{
58960089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
59060089Seric 		stat = db->put(db, &key, &data, 0);
59160089Seric 	}
59260089Seric 	if (stat != 0)
59360089Seric 		syserr("readaliases: db put (%s)", lhs);
59460089Seric }
59556836Seric 
59656847Seric 
59760089Seric /*
59860089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
59960089Seric */
60060089Seric 
60160089Seric void
60260089Seric db_map_close(map)
60360089Seric 	MAP *map;
60460089Seric {
60560089Seric 	register DB *db = map->map_db2;
60660089Seric 
60760089Seric 	if (tTd(27, 9))
60860207Seric 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
60960089Seric 
61060207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
61158804Seric 	{
61260089Seric 		/* write out the distinguished alias */
61360089Seric 		db_map_store(map, "@", "@");
61458804Seric 	}
61558963Seric 
61660089Seric 	if (db->close(db) != 0)
61760089Seric 		syserr("readaliases: db close failure");
61856822Seric }
61957208Seric 
62060089Seric #endif
62160089Seric /*
62260089Seric **  NIS Modules
62360089Seric */
62460089Seric 
62560089Seric # ifdef NIS
62660089Seric 
62757208Seric /*
62860089Seric **  NIS_MAP_OPEN -- open DBM map
62957208Seric */
63057208Seric 
63157208Seric bool
63260089Seric nis_map_open(map, mode)
63357208Seric 	MAP *map;
63460089Seric 	int mode;
63557208Seric {
63657216Seric 	int yperr;
63760215Seric 	register char *p;
63860215Seric 	auto char *vp;
63960215Seric 	auto int vsize;
64057216Seric 	char *master;
64157216Seric 
64260089Seric 	if (tTd(27, 2))
64360089Seric 		printf("nis_map_open(%s)\n", map->map_file);
64460089Seric 
64560207Seric 	if (mode != O_RDONLY)
64660207Seric 	{
64760207Seric 		errno = ENODEV;
64860207Seric 		return FALSE;
64960207Seric 	}
65060207Seric 
65160089Seric 	p = strchr(map->map_file, '@');
65260089Seric 	if (p != NULL)
65360089Seric 	{
65460089Seric 		*p++ = '\0';
65560089Seric 		if (*p != '\0')
65660089Seric 			map->map_domain = p;
65760089Seric 	}
65860215Seric 
65960089Seric 	if (map->map_domain == NULL)
66060089Seric 		yp_get_default_domain(&map->map_domain);
66160089Seric 
66260089Seric 	if (*map->map_file == '\0')
66360089Seric 		map->map_file = "mail.aliases";
66460089Seric 
66560215Seric 	/* check to see if this map actually exists */
66660089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
66760089Seric 			&vp, &vsize);
66860089Seric 	if (tTd(27, 10))
66960089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
67060089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
67160089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
67260089Seric 		return TRUE;
67360215Seric 
67460215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
67560215Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
67660215Seric 			yperr_string(yperr));
67760215Seric 
67860089Seric 	return FALSE;
67960089Seric }
68060089Seric 
68160089Seric 
68260089Seric /*
68357208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
68457208Seric */
68557208Seric 
68657208Seric char *
68760089Seric nis_map_lookup(map, name, av, statp)
68857208Seric 	MAP *map;
68960089Seric 	char *name;
69057208Seric 	char **av;
69159084Seric 	int *statp;
69257208Seric {
69357208Seric 	char *vp;
69457642Seric 	auto int vsize;
69559274Seric 	int buflen;
69660215Seric 	int yperr;
69760089Seric 	char keybuf[MAXNAME + 1];
69857208Seric 
69960089Seric 	if (tTd(27, 20))
70060089Seric 		printf("nis_map_lookup(%s)\n", name);
70160089Seric 
70260089Seric 	buflen = strlen(name);
70360089Seric 	if (buflen > sizeof keybuf - 1)
70460089Seric 		buflen = sizeof keybuf - 1;
70560089Seric 	bcopy(name, keybuf, buflen + 1);
70660207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
70760089Seric 		makelower(keybuf);
70860207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
70959274Seric 		buflen++;
71060089Seric 	yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
71160089Seric 		     &vp, &vsize);
71260089Seric 	if (yperr != 0)
71360089Seric 	{
71460089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
71560215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
71657208Seric 		return NULL;
71760089Seric 	}
71860207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
71960089Seric 		av = NULL;
72060215Seric 	return map_rewrite(map, vp, vsize, av);
72157208Seric }
72257208Seric 
72360089Seric 
72460089Seric /*
72560207Seric **  NIS_MAP_STORE
72660089Seric */
72760089Seric 
72860089Seric void
72960089Seric nis_map_store(map, lhs, rhs)
73060089Seric 	MAP *map;
73160089Seric 	char *lhs;
73260089Seric 	char *rhs;
73360089Seric {
73460089Seric 	/* nothing */
73560089Seric }
73660089Seric 
73760089Seric 
73860089Seric /*
73960207Seric **  NIS_MAP_CLOSE
74060089Seric */
74160089Seric 
74260089Seric void
74360089Seric nis_map_close(map)
74460089Seric 	MAP *map;
74560089Seric {
74660089Seric 	/* nothing */
74760089Seric }
74860089Seric 
74960089Seric #endif /* NIS */
75057208Seric /*
75160089Seric **  STAB (Symbol Table) Modules
75260089Seric */
75360089Seric 
75460089Seric 
75560089Seric /*
75660207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
75760089Seric */
75860089Seric 
75960089Seric char *
76060089Seric stab_map_lookup(map, name)
76160089Seric 	register MAP *map;
76260089Seric 	char *name;
76360089Seric {
76460089Seric 	register STAB *s;
76560089Seric 
76660089Seric 	if (tTd(27, 20))
76760089Seric 		printf("stab_lookup(%s)\n", name);
76860089Seric 
76960089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
77060089Seric 	if (s != NULL)
77160089Seric 		return (s->s_alias);
77260089Seric 	return (NULL);
77360089Seric }
77460089Seric 
77560089Seric 
77660089Seric /*
77760207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
77860089Seric */
77960089Seric 
78060089Seric void
78160089Seric stab_map_store(map, lhs, rhs)
78260089Seric 	register MAP *map;
78360089Seric 	char *lhs;
78460089Seric 	char *rhs;
78560089Seric {
78660089Seric 	register STAB *s;
78760089Seric 
78860089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
78960089Seric 	s->s_alias = newstr(rhs);
79060089Seric }
79160089Seric 
79260089Seric 
79360089Seric /*
79460207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
79560207Seric **
79660207Seric **	This is a wierd case -- it is only intended as a fallback for
79760207Seric **	aliases.  For this reason, opens for write (only during a
79860207Seric **	"newaliases") always fails, and opens for read open the
79960207Seric **	actual underlying text file instead of the database.
80060089Seric */
80160089Seric 
80260089Seric bool
80360089Seric stab_map_open(map, mode)
80460089Seric 	register MAP *map;
80560089Seric 	int mode;
80660089Seric {
80760089Seric 	FILE *af;
80860089Seric 
80960089Seric 	if (tTd(27, 2))
81060089Seric 		printf("stab_map_open(%s)\n", map->map_file);
81160089Seric 
81260089Seric 	if (mode != O_RDONLY)
81360207Seric 	{
81460207Seric 		errno = ENODEV;
81560089Seric 		return FALSE;
81660207Seric 	}
81760089Seric 
81860089Seric 	return TRUE;
81960089Seric }
82060089Seric 
82160089Seric 
82260089Seric /*
82360207Seric **  STAB_MAP_CLOSE -- close symbol table (???)
82460089Seric */
82560089Seric 
82660089Seric void
82760089Seric stab_map_close(map)
82860089Seric 	MAP *map;
82960089Seric {
83060089Seric 	/* ignore it */
83160089Seric }
83260089Seric /*
83360089Seric **  Implicit Modules
83456822Seric **
83560089Seric **	Tries several types.  For back compatibility of aliases.
83656822Seric */
83756822Seric 
83860089Seric 
83960089Seric /*
84060207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
84160089Seric */
84260089Seric 
84360089Seric char *
84460089Seric impl_map_lookup(map, name, av, pstat)
84560089Seric 	MAP *map;
84660089Seric 	char *name;
84756822Seric 	char **av;
84860089Seric 	int *pstat;
84956822Seric {
85060089Seric 	if (tTd(27, 20))
85160089Seric 		printf("impl_map_lookup(%s)\n", name);
85256822Seric 
85360089Seric #ifdef NEWDB
85460207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
85560089Seric 		return db_map_lookup(map, name, av, pstat);
85660089Seric #endif
85760089Seric #ifdef NDBM
85860207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
85960089Seric 		return ndbm_map_lookup(map, name, av, pstat);
86060089Seric #endif
86160089Seric 	return stab_map_lookup(map, name, av, pstat);
86260089Seric }
86360089Seric 
86460089Seric /*
86560207Seric **  IMPL_MAP_STORE -- store in open databases
86660089Seric */
86760089Seric 
86860089Seric void
86960089Seric impl_map_store(map, lhs, rhs)
87060089Seric 	MAP *map;
87160089Seric 	char *lhs;
87260089Seric 	char *rhs;
87360089Seric {
87460089Seric #ifdef NEWDB
87560207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
87660089Seric 		db_map_store(map, lhs, rhs);
87760089Seric #endif
87860089Seric #ifdef NDBM
87960207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
88060089Seric 		ndbm_map_store(map, lhs, rhs);
88160089Seric #endif
88260089Seric 	stab_map_store(map, lhs, rhs);
88360089Seric }
88460089Seric 
88560089Seric /*
88660089Seric **  IMPL_MAP_OPEN -- implicit database open
88760089Seric */
88860089Seric 
88960089Seric bool
89060089Seric impl_map_open(map, mode)
89160089Seric 	MAP *map;
89260089Seric 	int mode;
89360089Seric {
89460089Seric 	struct stat stb;
89560089Seric 
89660089Seric 	if (tTd(27, 2))
89760089Seric 		printf("impl_map_open(%s)\n", map->map_file);
89860089Seric 
89960089Seric 	if (stat(map->map_file, &stb) < 0)
90056822Seric 	{
90160089Seric 		/* no alias file at all */
90260089Seric 		return FALSE;
90356822Seric 	}
90456822Seric 
90560089Seric #ifdef NEWDB
90660207Seric 	map->map_mflags |= MF_IMPL_HASH;
90760089Seric 	if (hash_map_open(map, mode))
90856822Seric 	{
90960207Seric #if defined(NDBM) && defined(YPCOMPAT)
91060207Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) == 0)
91160207Seric #endif
91260207Seric 			return TRUE;
91360089Seric 	}
91460207Seric 	else
91560207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
91660089Seric #endif
91760089Seric #ifdef NDBM
91860207Seric 	map->map_mflags |= MF_IMPL_NDBM;
91960089Seric 	if (ndbm_map_open(map, mode))
92060089Seric 	{
92160089Seric 		return TRUE;
92260089Seric 	}
92360207Seric 	else
92460207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
92560089Seric #endif
92656822Seric 
92760207Seric #if !defined(NEWDB) && !defined(NDBM)
92860089Seric 	if (Verbose)
92960089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
93060207Seric #endif
93160089Seric 
93260207Seric 	return stab_map_open(map, mode);
93356822Seric }
93460089Seric 
93560207Seric 
93660089Seric /*
93760207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
93860089Seric */
93960089Seric 
94060089Seric void
94160207Seric impl_map_close(map)
94260089Seric 	MAP *map;
94360089Seric {
94460089Seric #ifdef NEWDB
94560207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
94660089Seric 	{
94760207Seric 		db_map_close(map);
94860207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
94960089Seric 	}
95060089Seric #endif
95160089Seric 
95260089Seric #ifdef NDBM
95360207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
95460089Seric 	{
95560207Seric 		ndbm_map_close(map);
95660207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
95760089Seric 	}
95860089Seric #endif
95960089Seric }
96060207Seric /*
96160207Seric **  NULL stubs
96260089Seric */
96360089Seric 
96460207Seric bool
96560207Seric null_map_open(map, mode)
96660089Seric 	MAP *map;
96760207Seric 	int mode;
96860089Seric {
96960207Seric 	return TRUE;
97060089Seric }
97160089Seric 
97260207Seric void
97360207Seric null_map_close(map)
97460207Seric 	MAP *map;
97560089Seric {
97660207Seric 	return;
97760207Seric }
97860089Seric 
97960207Seric void
98060207Seric null_map_store(map, key, val)
98160207Seric 	MAP *map;
98260207Seric 	char *key;
98360207Seric 	char *val;
98460089Seric {
98560207Seric 	return;
98660089Seric }
987