xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 60207)
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*60207Seric static char sccsid[] = "@(#)map.c	6.15 (Berkeley) 05/21/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 **
3560089Seric **	char *map_lookup(MAP *map, char buf[], int bufsize,
3660089Seric **			 char **args, int *pstat)
3760089Seric **		Look up the key given in buf in the given map.  If found,
3860089Seric **		do any rewriting the map wants (including "args" if desired)
3960089Seric **		and return the value.  Set *pstat to the appropriate status
4060089Seric **		on error and return NULL.
4160089Seric **
4260089Seric **	void map_store(MAP *map, char *key, char *value)
4360089Seric **		Store the key:value pair in the map.
4460089Seric **
4560089Seric **	bool map_open(MAP *map, int mode)
4660089Seric **		Open the map for the indicated mode.  Return TRUE if it
4760089Seric **		was opened successfully, FALSE otherwise.
4860089Seric **
4960089Seric **	void map_close(MAP *map)
5060089Seric **		Close the map.
5160089Seric */
5260089Seric 
5360089Seric #define DBMMODE		0644
5460089Seric /*
5560089Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
5660089Seric **
5760089Seric **	This is a generic version of the map_parse method.
5860089Seric **
5956822Seric **	Parameters:
6060089Seric **		map -- the map being initialized.
6160089Seric **		ap -- a pointer to the args on the config line.
6256822Seric **
6356822Seric **	Returns:
6460089Seric **		TRUE -- if everything parsed OK.
6556822Seric **		FALSE -- otherwise.
6656822Seric **
6756822Seric **	Side Effects:
6860089Seric **		null terminates the filename; stores it in map
6956822Seric */
7056822Seric 
7156822Seric bool
7260089Seric map_parseargs(map, ap)
7356822Seric 	MAP *map;
7460089Seric 	char *ap;
7556822Seric {
7660089Seric 	register char *p = ap;
7756822Seric 
7860089Seric 	for (;;)
7960089Seric 	{
8060089Seric 		while (isascii(*p) && isspace(*p))
8160089Seric 			p++;
8260089Seric 		if (*p != '-')
8360089Seric 			break;
8460089Seric 		switch (*++p)
8560089Seric 		{
8660089Seric 		  case 'N':
87*60207Seric 			map->map_mflags |= MF_INCLNULL;
8860089Seric 			break;
8960089Seric 
9060089Seric 		  case 'o':
91*60207Seric 			map->map_mflags |= MF_OPTIONAL;
9260089Seric 			break;
9360089Seric 
9460089Seric 		  case 'f':
95*60207Seric 			map->map_mflags |= MF_NOFOLDCASE;
9660089Seric 			break;
9760089Seric 
9860089Seric 		  case 'm':
99*60207Seric 			map->map_mflags |= MF_MATCHONLY;
10060089Seric 			break;
10160089Seric 
10260089Seric 		  case 'a':
10360089Seric 			map->map_app = ++p;
10460089Seric 			break;
10560089Seric 
10660089Seric 		  case 'd':
10760089Seric 			map->map_domain = ++p;
10860089Seric 			break;
10960089Seric 		}
11060089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
11160089Seric 			p++;
11260089Seric 		if (*p != '\0')
11360089Seric 			*p++ = '\0';
11460089Seric 	}
11560089Seric 	if (map->map_app != NULL)
11660089Seric 		map->map_app = newstr(map->map_app);
11760089Seric 	if (map->map_domain != NULL)
11860089Seric 		map->map_domain = newstr(map->map_domain);
11960089Seric 
12060089Seric 	if (*p != '\0')
12160089Seric 	{
12260089Seric 		map->map_file = p;
12360089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
12460089Seric 			p++;
12560089Seric 		if (*p != '\0')
12660089Seric 			*p++ = '\0';
12760089Seric 		map->map_file = newstr(map->map_file);
12860089Seric 	}
12960089Seric 
13060089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
13160089Seric 		p++;
13260089Seric 	if (*p != '\0')
13360089Seric 		map->map_rebuild = newstr(p);
13460089Seric 
13556822Seric 	if (map->map_file == NULL)
13657208Seric 	{
13760089Seric 		syserr("No file name for %s map %s",
13860089Seric 			map->map_class->map_cname, map->map_mname);
13956822Seric 		return FALSE;
14057208Seric 	}
14160089Seric 	return TRUE;
14260089Seric }
14360089Seric /*
14460089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
14560089Seric **
14660089Seric **	It also adds the map_app string.  It can be used as a utility
14760089Seric **	in the map_lookup method.
14860089Seric **
14960089Seric **	Parameters:
15060089Seric **		map -- the map that causes this.
15160089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
15260089Seric **		slen -- the length of s.
15360089Seric **		av -- arguments to interpolate into buf.
15460089Seric **
15560089Seric **	Returns:
15660089Seric **		Pointer to rewritten result.
15760089Seric **
15860089Seric **	Side Effects:
15960089Seric **		none.
16060089Seric */
16160089Seric 
16260089Seric char *
16360089Seric map_rewrite(map, s, slen, av)
16460089Seric 	register MAP *map;
16560089Seric 	register char *s;
16660089Seric 	int slen;
16760089Seric 	char **av;
16860089Seric {
16960089Seric 	register char *bp;
17060089Seric 	register char c;
17160089Seric 	char **avp;
17260089Seric 	register char *ap;
17360089Seric 	int i;
17460089Seric 	int len;
17560089Seric 	static int buflen = -1;
17660089Seric 	static char *buf = NULL;
17760089Seric 
17860089Seric 	if (tTd(23, 1))
17960089Seric 	{
18060089Seric 		printf("map_rewrite(%.*s), av =\n", slen, s);
18160089Seric 		for (avp = av; *avp != NULL; avp++)
18260089Seric 			printf("\t%s\n", *avp);
18360089Seric 	}
18460089Seric 
18560089Seric 	/* count expected size of output (can safely overestimate) */
18660089Seric 	i = len = slen;
18760089Seric 	if (av != NULL)
18860089Seric 	{
18960089Seric 		bp = s;
19060089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
19160089Seric 		{
19260089Seric 			if (c != '%')
19360089Seric 				continue;
19460089Seric 			if (--i < 0)
19560089Seric 				break;
19660089Seric 			c = *bp++;
19760089Seric 			if (!(isascii(c) && isdigit(c)))
19860089Seric 				continue;
19960089Seric 			c -= 0;
20060089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
20160089Seric 				continue;
20260089Seric 			if (*avp == NULL)
20360089Seric 				continue;
20460089Seric 			len += strlen(*avp);
20560089Seric 		}
20660089Seric 	}
20760089Seric 	if (map->map_app != NULL)
20860089Seric 		len += strlen(map->map_app);
20960089Seric 	if (buflen < ++len)
21060089Seric 	{
21160089Seric 		/* need to malloc additional space */
21260089Seric 		buflen = len;
21360089Seric 		if (buf != NULL)
21460089Seric 			free(buf);
21560089Seric 		buf = xalloc(buflen);
21660089Seric 	}
21760089Seric 
21860089Seric 	bp = buf;
21960089Seric 	if (av == NULL)
22060089Seric 	{
22160089Seric 		bcopy(s, bp, slen);
22260089Seric 		bp += slen;
22360089Seric 	}
22460089Seric 	else
22560089Seric 	{
22660089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
22760089Seric 		{
22860089Seric 			if (c != '%')
22960089Seric 			{
23060089Seric   pushc:
23160089Seric 				*bp++ = c;
23260089Seric 				continue;
23360089Seric 			}
23460089Seric 			if (--slen < 0 || (c = *s++) == '\0')
23560089Seric 				c = '%';
23660089Seric 			if (c == '%')
23760089Seric 				goto pushc;
23860089Seric 			if (!(isascii(c) && isdigit(c)))
23960089Seric 			{
24060089Seric 				*bp++ = '%';
24160089Seric 				goto pushc;
24260089Seric 			}
24360089Seric 			c -= '0';
24460089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
24560089Seric 				continue;
24660089Seric 			if (*avp == NULL)
24760089Seric 				continue;
24860089Seric 
24960089Seric 			/* transliterate argument into output string */
25060089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
25160089Seric 				*bp++ = c;
25260089Seric 		}
25360089Seric 	}
25460089Seric 	if (map->map_app != NULL)
25560089Seric 		strcpy(bp, map->map_app);
25660089Seric 	else
25760089Seric 		*bp = '\0';
25860089Seric 	if (tTd(23, 1))
25960089Seric 		printf("map_rewrite => %s\n", buf);
26060089Seric 	return buf;
26160089Seric }
26260089Seric /*
26360089Seric **  NDBM modules
26460089Seric */
26560089Seric 
26660089Seric #ifdef NDBM
26760089Seric 
26860089Seric /*
26960089Seric **  DBM_MAP_OPEN -- DBM-style map open
27060089Seric */
27160089Seric 
27260089Seric bool
27360089Seric ndbm_map_open(map, mode)
27460089Seric 	MAP *map;
27560089Seric 	int mode;
27660089Seric {
27760089Seric 	DBM *dbm;
27860089Seric 
27960089Seric 	if (tTd(27, 2))
28060089Seric 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
28160089Seric 
282*60207Seric 	if (mode == O_RDWR)
283*60207Seric 		mode |= O_CREAT|O_TRUNC;
284*60207Seric 
28560089Seric 	/* open the database */
28660089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
28756822Seric 	if (dbm == NULL)
28856822Seric 	{
289*60207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
29056836Seric 			syserr("Cannot open DBM database %s", map->map_file);
29156822Seric 		return FALSE;
29256822Seric 	}
29360089Seric 	map->map_db1 = (void *) dbm;
294*60207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
295*60207Seric 		aliaswait(map, ".dir");
29656822Seric 	return TRUE;
29756822Seric }
29860089Seric 
29960089Seric 
30060089Seric /*
30156822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
30256822Seric */
30356822Seric 
30456822Seric char *
30560089Seric ndbm_map_lookup(map, name, av, statp)
30656822Seric 	MAP *map;
30760089Seric 	char *name;
30856822Seric 	char **av;
30959084Seric 	int *statp;
31056822Seric {
31156822Seric 	datum key, val;
31260089Seric 	char keybuf[MAXNAME + 1];
31356822Seric 
31460089Seric 	if (tTd(27, 20))
31560089Seric 		printf("ndbm_map_lookup(%s)\n", name);
31660089Seric 
31760089Seric 	key.dptr = name;
31860089Seric 	key.dsize = strlen(name);
319*60207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
32057014Seric 	{
32160089Seric 		if (key.dsize > sizeof keybuf - 1)
32260089Seric 			key.dsize = sizeof keybuf - 1;
32360089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
32460089Seric 		makelower(keybuf);
32560089Seric 		key.dptr = keybuf;
32657014Seric 	}
327*60207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
32856822Seric 		key.dsize++;
32960089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
33060089Seric 	val = dbm_fetch((DBM *) map->map_db1, key);
33160089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
33256822Seric 	if (val.dptr == NULL)
33356822Seric 		return NULL;
334*60207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
33560089Seric 		av = NULL;
33660089Seric 	return map_rewrite(map, val.dptr, val.dsize, av);
33756822Seric }
33856822Seric 
33956822Seric 
34056822Seric /*
34160089Seric **  DBM_MAP_STORE -- store a datum in the database
34256822Seric */
34356822Seric 
34460089Seric void
34560089Seric ndbm_map_store(map, lhs, rhs)
34660089Seric 	register MAP *map;
34760089Seric 	char *lhs;
34860089Seric 	char *rhs;
34960089Seric {
35060089Seric 	datum key;
35160089Seric 	datum data;
35260089Seric 	int stat;
35360089Seric 
35460089Seric 	if (tTd(27, 12))
35560089Seric 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
35660089Seric 
35760089Seric 	key.dsize = strlen(lhs);
35860089Seric 	key.dptr = lhs;
35960089Seric 
36060089Seric 	data.dsize = strlen(rhs);
36160089Seric 	data.dptr = rhs;
36260089Seric 
363*60207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
36460089Seric 	{
36560089Seric 		key.dsize++;
36660089Seric 		data.dsize++;
36760089Seric 	}
36860089Seric 
36960089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
37060089Seric 	if (stat > 0)
37160089Seric 	{
37260089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
37360089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
37460089Seric 	}
37560089Seric 	if (stat != 0)
37660089Seric 		syserr("readaliases: dbm put (%s)", lhs);
37760089Seric }
37860089Seric 
37960089Seric 
38060089Seric /*
381*60207Seric **  NDBM_MAP_CLOSE -- close the database
38260089Seric */
38360089Seric 
38460089Seric void
38560089Seric ndbm_map_close(map)
38660089Seric 	register MAP  *map;
38760089Seric {
388*60207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
38960089Seric 	{
39060089Seric #ifdef YPCOMPAT
39160089Seric 		char buf[200];
39260089Seric 
39360089Seric 		(void) sprintf(buf, "%010ld", curtime());
39460089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
39560089Seric 
39660089Seric 		(void) myhostname(buf, sizeof buf);
39760089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
39860089Seric #endif
39960089Seric 
40060089Seric 		/* write out the distinguished alias */
40160089Seric 		ndbm_map_store(map, "@", "@");
40260089Seric 	}
40360089Seric 	dbm_close((DBM *) map->map_db1);
40460089Seric }
40560089Seric 
40660089Seric #endif
40760089Seric /*
40860089Seric **  HASH (NEWDB) Modules
40960089Seric */
41060089Seric 
41160089Seric #ifdef NEWDB
41260089Seric 
41360089Seric /*
41460089Seric **  BTREE_MAP_PARSE -- BTREE-style map initialization
41560089Seric */
41660089Seric 
41756822Seric bool
41860089Seric bt_map_open(map, mode)
41956822Seric 	MAP *map;
42060089Seric 	int mode;
42156822Seric {
42256822Seric 	DB *db;
42360089Seric 	char buf[MAXNAME];
42456822Seric 
42560089Seric 	if (tTd(27, 2))
42660089Seric 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
42760089Seric 
428*60207Seric 	if (mode == O_RDWR)
429*60207Seric 		mode |= O_CREAT|O_TRUNC;
430*60207Seric 
43160089Seric 	(void) sprintf(buf, "%s.db", map->map_file);
43260089Seric 	db = dbopen(buf, mode, 0644, DB_BTREE, NULL);
43356822Seric 	if (db == NULL)
43456822Seric 	{
435*60207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
43656836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
43756822Seric 		return FALSE;
43856822Seric 	}
43960089Seric 	map->map_db2 = (void *) db;
440*60207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
441*60207Seric 		aliaswait(map, ".db");
44256822Seric 	return TRUE;
44356822Seric }
44456822Seric 
44556822Seric 
44656822Seric /*
44756822Seric **  HASH_MAP_INIT -- HASH-style map initialization
44856822Seric */
44956822Seric 
45056822Seric bool
45160089Seric hash_map_open(map, mode)
45256822Seric 	MAP *map;
45360089Seric 	int mode;
45456822Seric {
45556822Seric 	DB *db;
45660089Seric 	char buf[MAXNAME];
45756822Seric 
45860089Seric 	if (tTd(27, 2))
45960089Seric 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
46060089Seric 
461*60207Seric 	if (mode == O_RDWR)
462*60207Seric 		mode |= O_CREAT|O_TRUNC;
463*60207Seric 
46460089Seric 	(void) sprintf(buf, "%s.db", map->map_file);
46560089Seric 	db = dbopen(buf, mode, 0644, DB_HASH, NULL);
46656822Seric 	if (db == NULL)
46756822Seric 	{
468*60207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
46956836Seric 			syserr("Cannot open HASH database %s", map->map_file);
47056822Seric 		return FALSE;
47156822Seric 	}
47260089Seric 	map->map_db2 = (void *) db;
473*60207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
474*60207Seric 		aliaswait(map, ".db");
47556822Seric 	return TRUE;
47656822Seric }
47756822Seric 
47856822Seric 
47956822Seric /*
48056822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
48156822Seric */
48256822Seric 
48356822Seric char *
48460089Seric db_map_lookup(map, name, av, statp)
48556822Seric 	MAP *map;
48660089Seric 	char *name;
48756822Seric 	char **av;
48859084Seric 	int *statp;
48956822Seric {
49056822Seric 	DBT key, val;
49160089Seric 	char keybuf[MAXNAME + 1];
49256822Seric 
49360089Seric 	if (tTd(27, 20))
49460089Seric 		printf("db_map_lookup(%s)\n", name);
49560089Seric 
49660089Seric 	key.size = strlen(name);
49760089Seric 	if (key.size > sizeof keybuf - 1)
49860089Seric 		key.size = sizeof keybuf - 1;
49960089Seric 	key.data = keybuf;
50060089Seric 	bcopy(name, keybuf, key.size + 1);
501*60207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
50260089Seric 		makelower(keybuf);
503*60207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
50456822Seric 		key.size++;
50560089Seric 	if (((DB *) map->map_db2)->get((DB *) map->map_db2, &key, &val, 0) != 0)
50656822Seric 		return NULL;
507*60207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
50860089Seric 		av = NULL;
50960089Seric 	return map_rewrite(map, val.data, val.size, av);
51056822Seric }
51156822Seric 
51260089Seric 
51360089Seric /*
51460089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
51556822Seric */
51656822Seric 
51760089Seric void
51860089Seric db_map_store(map, lhs, rhs)
51960089Seric 	register MAP *map;
52060089Seric 	char *lhs;
52160089Seric 	char *rhs;
52256822Seric {
52360089Seric 	int stat;
52460089Seric 	DBT key;
52560089Seric 	DBT data;
52660089Seric 	register DB *db = map->map_db2;
52756822Seric 
52860089Seric 	if (tTd(27, 20))
52960089Seric 		printf("db_map_store(%s, %s)\n", lhs, rhs);
53060089Seric 
53160089Seric 	key.size = strlen(lhs);
53260089Seric 	key.data = lhs;
53360089Seric 
53460089Seric 	data.size = strlen(rhs);
53560089Seric 	data.data = rhs;
53660089Seric 
537*60207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
53856822Seric 	{
53960089Seric 		key.size++;
54060089Seric 		data.size++;
54160089Seric 	}
54256836Seric 
54360089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
54460089Seric 	if (stat > 0)
54560089Seric 	{
54660089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
54760089Seric 		stat = db->put(db, &key, &data, 0);
54860089Seric 	}
54960089Seric 	if (stat != 0)
55060089Seric 		syserr("readaliases: db put (%s)", lhs);
55160089Seric }
55256836Seric 
55356847Seric 
55460089Seric /*
55560089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
55660089Seric */
55760089Seric 
55860089Seric void
55960089Seric db_map_close(map)
56060089Seric 	MAP *map;
56160089Seric {
56260089Seric 	register DB *db = map->map_db2;
56360089Seric 
56460089Seric 	if (tTd(27, 9))
565*60207Seric 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
56660089Seric 
567*60207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
56858804Seric 	{
56960089Seric 		/* write out the distinguished alias */
57060089Seric 		db_map_store(map, "@", "@");
57158804Seric 	}
57258963Seric 
57360089Seric 	if (db->close(db) != 0)
57460089Seric 		syserr("readaliases: db close failure");
57556822Seric }
57657208Seric 
57760089Seric #endif
57860089Seric /*
57960089Seric **  NIS Modules
58060089Seric */
58160089Seric 
58260089Seric # ifdef NIS
58360089Seric 
58457208Seric /*
58560089Seric **  NIS_MAP_OPEN -- open DBM map
58657208Seric */
58757208Seric 
58857208Seric bool
58960089Seric nis_map_open(map, mode)
59057208Seric 	MAP *map;
59160089Seric 	int mode;
59257208Seric {
59357216Seric 	int yperr;
59457216Seric 	char *master;
59557216Seric 
59660089Seric 	if (tTd(27, 2))
59760089Seric 		printf("nis_map_open(%s)\n", map->map_file);
59860089Seric 
599*60207Seric 	if (mode != O_RDONLY)
600*60207Seric 	{
601*60207Seric 		errno = ENODEV;
602*60207Seric 		return FALSE;
603*60207Seric 	}
604*60207Seric 
60557208Seric 	if (map->map_domain == NULL)
60657208Seric 		yp_get_default_domain(&map->map_domain);
60757216Seric 
60857216Seric 	/* check to see if this map actually exists */
60957216Seric 	yperr = yp_master(map->map_domain, map->map_file, &master);
61057216Seric 	if (yperr == 0)
61157216Seric 		return TRUE;
612*60207Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
61357216Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
61457216Seric 			yperr_string(yperr));
61557216Seric 	return FALSE;
61657208Seric }
61760089Seric 
61860089Seric bool
61960089Seric nis_map_open(map, mode)
62060089Seric 	MAP *map;
62160089Seric 	int mode;
62260089Seric {
62360089Seric 	register char *p;
62460089Seric 	int yperr;
62560089Seric 	auto char *vp;
62660089Seric 	auto int vsize;
62760089Seric 
62860089Seric 	p = strchr(map->map_file, '@');
62960089Seric 	if (p != NULL)
63060089Seric 	{
63160089Seric 		*p++ = '\0';
63260089Seric 		if (*p != '\0')
63360089Seric 			map->map_domain = p;
63460089Seric 	}
63560089Seric 	if (map->map_domain == NULL)
63660089Seric 		yp_get_default_domain(&map->map_domain);
63760089Seric 
63860089Seric 	if (*map->map_file == '\0')
63960089Seric 		map->map_file = "mail.aliases";
64060089Seric 
64160089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
64260089Seric 			&vp, &vsize);
64360089Seric 	if (tTd(27, 10))
64460089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
64560089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
64660089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
64760089Seric 		return TRUE;
64860089Seric 	return FALSE;
64960089Seric }
65060089Seric 
65160089Seric 
65260089Seric /*
65357208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
65457208Seric */
65557208Seric 
65657208Seric char *
65760089Seric nis_map_lookup(map, name, av, statp)
65857208Seric 	MAP *map;
65960089Seric 	char *name;
66057208Seric 	char **av;
66159084Seric 	int *statp;
66257208Seric {
66357208Seric 	char *vp;
66457642Seric 	auto int vsize;
66559274Seric 	int buflen;
66660089Seric 	char keybuf[MAXNAME + 1];
66757208Seric 
66860089Seric 	if (tTd(27, 20))
66960089Seric 		printf("nis_map_lookup(%s)\n", name);
67060089Seric 
67160089Seric 	buflen = strlen(name);
67260089Seric 	if (buflen > sizeof keybuf - 1)
67360089Seric 		buflen = sizeof keybuf - 1;
67460089Seric 	bcopy(name, keybuf, buflen + 1);
675*60207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
67660089Seric 		makelower(keybuf);
677*60207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
67859274Seric 		buflen++;
67960089Seric 	yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
68060089Seric 		     &vp, &vsize);
68160089Seric 	if (yperr != 0)
68260089Seric 	{
68360089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
684*60207Seric 			map->map_mflags &= ~MF_VALID;
68557208Seric 		return NULL;
68660089Seric 	}
687*60207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
68860089Seric 		av = NULL;
68960089Seric 	return map_rewrite(map, val.dptr, val.dsize, av);
69057208Seric }
69157208Seric 
69260089Seric 
69360089Seric /*
694*60207Seric **  NIS_MAP_STORE
69560089Seric */
69660089Seric 
69760089Seric void
69860089Seric nis_map_store(map, lhs, rhs)
69960089Seric 	MAP *map;
70060089Seric 	char *lhs;
70160089Seric 	char *rhs;
70260089Seric {
70360089Seric 	/* nothing */
70460089Seric }
70560089Seric 
70660089Seric 
70760089Seric /*
708*60207Seric **  NIS_MAP_CLOSE
70960089Seric */
71060089Seric 
71160089Seric void
71260089Seric nis_map_close(map)
71360089Seric 	MAP *map;
71460089Seric {
71560089Seric 	/* nothing */
71660089Seric }
71760089Seric 
71860089Seric #endif /* NIS */
71957208Seric /*
72060089Seric **  STAB (Symbol Table) Modules
72160089Seric */
72260089Seric 
72360089Seric 
72460089Seric /*
725*60207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
72660089Seric */
72760089Seric 
72860089Seric char *
72960089Seric stab_map_lookup(map, name)
73060089Seric 	register MAP *map;
73160089Seric 	char *name;
73260089Seric {
73360089Seric 	register STAB *s;
73460089Seric 
73560089Seric 	if (tTd(27, 20))
73660089Seric 		printf("stab_lookup(%s)\n", name);
73760089Seric 
73860089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
73960089Seric 	if (s != NULL)
74060089Seric 		return (s->s_alias);
74160089Seric 	return (NULL);
74260089Seric }
74360089Seric 
74460089Seric 
74560089Seric /*
746*60207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
74760089Seric */
74860089Seric 
74960089Seric void
75060089Seric stab_map_store(map, lhs, rhs)
75160089Seric 	register MAP *map;
75260089Seric 	char *lhs;
75360089Seric 	char *rhs;
75460089Seric {
75560089Seric 	register STAB *s;
75660089Seric 
75760089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
75860089Seric 	s->s_alias = newstr(rhs);
75960089Seric }
76060089Seric 
76160089Seric 
76260089Seric /*
763*60207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
764*60207Seric **
765*60207Seric **	This is a wierd case -- it is only intended as a fallback for
766*60207Seric **	aliases.  For this reason, opens for write (only during a
767*60207Seric **	"newaliases") always fails, and opens for read open the
768*60207Seric **	actual underlying text file instead of the database.
76960089Seric */
77060089Seric 
77160089Seric bool
77260089Seric stab_map_open(map, mode)
77360089Seric 	register MAP *map;
77460089Seric 	int mode;
77560089Seric {
77660089Seric 	FILE *af;
77760089Seric 
77860089Seric 	if (tTd(27, 2))
77960089Seric 		printf("stab_map_open(%s)\n", map->map_file);
78060089Seric 
78160089Seric 	if (mode != O_RDONLY)
782*60207Seric 	{
783*60207Seric 		errno = ENODEV;
78460089Seric 		return FALSE;
785*60207Seric 	}
78660089Seric 
78760089Seric 	return TRUE;
78860089Seric }
78960089Seric 
79060089Seric 
79160089Seric /*
792*60207Seric **  STAB_MAP_CLOSE -- close symbol table (???)
79360089Seric */
79460089Seric 
79560089Seric void
79660089Seric stab_map_close(map)
79760089Seric 	MAP *map;
79860089Seric {
79960089Seric 	/* ignore it */
80060089Seric }
80160089Seric /*
80260089Seric **  Implicit Modules
80356822Seric **
80460089Seric **	Tries several types.  For back compatibility of aliases.
80556822Seric */
80656822Seric 
80760089Seric 
80860089Seric /*
809*60207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
81060089Seric */
81160089Seric 
81260089Seric char *
81360089Seric impl_map_lookup(map, name, av, pstat)
81460089Seric 	MAP *map;
81560089Seric 	char *name;
81656822Seric 	char **av;
81760089Seric 	int *pstat;
81856822Seric {
81960089Seric 	if (tTd(27, 20))
82060089Seric 		printf("impl_map_lookup(%s)\n", name);
82156822Seric 
82260089Seric #ifdef NEWDB
823*60207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
82460089Seric 		return db_map_lookup(map, name, av, pstat);
82560089Seric #endif
82660089Seric #ifdef NDBM
827*60207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
82860089Seric 		return ndbm_map_lookup(map, name, av, pstat);
82960089Seric #endif
83060089Seric 	return stab_map_lookup(map, name, av, pstat);
83160089Seric }
83260089Seric 
83360089Seric /*
834*60207Seric **  IMPL_MAP_STORE -- store in open databases
83560089Seric */
83660089Seric 
83760089Seric void
83860089Seric impl_map_store(map, lhs, rhs)
83960089Seric 	MAP *map;
84060089Seric 	char *lhs;
84160089Seric 	char *rhs;
84260089Seric {
84360089Seric #ifdef NEWDB
844*60207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
84560089Seric 		db_map_store(map, lhs, rhs);
84660089Seric #endif
84760089Seric #ifdef NDBM
848*60207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
84960089Seric 		ndbm_map_store(map, lhs, rhs);
85060089Seric #endif
85160089Seric 	stab_map_store(map, lhs, rhs);
85260089Seric }
85360089Seric 
85460089Seric /*
85560089Seric **  IMPL_MAP_OPEN -- implicit database open
85660089Seric */
85760089Seric 
85860089Seric bool
85960089Seric impl_map_open(map, mode)
86060089Seric 	MAP *map;
86160089Seric 	int mode;
86260089Seric {
86360089Seric 	struct stat stb;
86460089Seric 
86560089Seric 	if (tTd(27, 2))
86660089Seric 		printf("impl_map_open(%s)\n", map->map_file);
86760089Seric 
86860089Seric 	if (stat(map->map_file, &stb) < 0)
86956822Seric 	{
87060089Seric 		/* no alias file at all */
87160089Seric 		return FALSE;
87256822Seric 	}
87356822Seric 
87460089Seric #ifdef NEWDB
875*60207Seric 	map->map_mflags |= MF_IMPL_HASH;
87660089Seric 	if (hash_map_open(map, mode))
87756822Seric 	{
878*60207Seric #if defined(NDBM) && defined(YPCOMPAT)
879*60207Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) == 0)
880*60207Seric #endif
881*60207Seric 			return TRUE;
88260089Seric 	}
883*60207Seric 	else
884*60207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
88560089Seric #endif
88660089Seric #ifdef NDBM
887*60207Seric 	map->map_mflags |= MF_IMPL_NDBM;
88860089Seric 	if (ndbm_map_open(map, mode))
88960089Seric 	{
89060089Seric 		return TRUE;
89160089Seric 	}
892*60207Seric 	else
893*60207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
89460089Seric #endif
89556822Seric 
896*60207Seric #if !defined(NEWDB) && !defined(NDBM)
89760089Seric 	if (Verbose)
89860089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
899*60207Seric #endif
90060089Seric 
901*60207Seric 	return stab_map_open(map, mode);
90256822Seric }
90360089Seric 
904*60207Seric 
90560089Seric /*
906*60207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
90760089Seric */
90860089Seric 
90960089Seric void
910*60207Seric impl_map_close(map)
91160089Seric 	MAP *map;
91260089Seric {
91360089Seric #ifdef NEWDB
914*60207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
91560089Seric 	{
916*60207Seric 		db_map_close(map);
917*60207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
91860089Seric 	}
91960089Seric #endif
92060089Seric 
92160089Seric #ifdef NDBM
922*60207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
92360089Seric 	{
924*60207Seric 		ndbm_map_close(map);
925*60207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
92660089Seric 	}
92760089Seric #endif
92860089Seric }
929*60207Seric /*
930*60207Seric **  NULL stubs
93160089Seric */
93260089Seric 
933*60207Seric bool
934*60207Seric null_map_open(map, mode)
93560089Seric 	MAP *map;
936*60207Seric 	int mode;
93760089Seric {
938*60207Seric 	return TRUE;
93960089Seric }
94060089Seric 
941*60207Seric void
942*60207Seric null_map_close(map)
943*60207Seric 	MAP *map;
94460089Seric {
945*60207Seric 	return;
946*60207Seric }
94760089Seric 
948*60207Seric void
949*60207Seric null_map_store(map, key, val)
950*60207Seric 	MAP *map;
951*60207Seric 	char *key;
952*60207Seric 	char *val;
95360089Seric {
954*60207Seric 	return;
95560089Seric }
956