xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 69780)
156822Seric /*
268839Seric  * Copyright (c) 1992, 1995 Eric P. Allman.
362526Sbostic  * Copyright (c) 1992, 1993
462526Sbostic  *	The Regents of the University of California.  All rights reserved.
556822Seric  *
656822Seric  * %sccs.include.redist.c%
756822Seric  */
856822Seric 
956822Seric #ifndef lint
10*69780Seric static char sccsid[] = "@(#)map.c	8.71 (Berkeley) 05/30/95";
1156822Seric #endif /* not lint */
1256822Seric 
1356822Seric #include "sendmail.h"
1456822Seric 
1560089Seric #ifdef NDBM
1668509Seric # include <ndbm.h>
1756822Seric #endif
1860089Seric #ifdef NEWDB
1968509Seric # include <db.h>
2056822Seric #endif
2160089Seric #ifdef NIS
2269651Seric   struct dom_binding;	/* forward reference needed on IRIX */
2368509Seric # include <rpcsvc/ypclnt.h>
2457208Seric #endif
2556822Seric 
2656822Seric /*
2760089Seric **  MAP.C -- implementations for various map classes.
2856822Seric **
2960089Seric **	Each map class implements a series of functions:
3060089Seric **
3160089Seric **	bool map_parse(MAP *map, char *args)
3260089Seric **		Parse the arguments from the config file.  Return TRUE
3360089Seric **		if they were ok, FALSE otherwise.  Fill in map with the
3460089Seric **		values.
3560089Seric **
3660222Seric **	char *map_lookup(MAP *map, char *key, char **args, int *pstat)
3760222Seric **		Look up the key in the given map.  If found, do any
3860222Seric **		rewriting the map wants (including "args" if desired)
3960089Seric **		and return the value.  Set *pstat to the appropriate status
4060222Seric **		on error and return NULL.  Args will be NULL if called
4160222Seric **		from the alias routines, although this should probably
4260222Seric **		not be relied upon.  It is suggested you call map_rewrite
4360222Seric **		to return the results -- it takes care of null termination
4460222Seric **		and uses a dynamically expanded buffer as needed.
4560089Seric **
4660089Seric **	void map_store(MAP *map, char *key, char *value)
4760089Seric **		Store the key:value pair in the map.
4860089Seric **
4960089Seric **	bool map_open(MAP *map, int mode)
5060222Seric **		Open the map for the indicated mode.  Mode should
5160222Seric **		be either O_RDONLY or O_RDWR.  Return TRUE if it
5260222Seric **		was opened successfully, FALSE otherwise.  If the open
5360222Seric **		failed an the MF_OPTIONAL flag is not set, it should
5460222Seric **		also print an error.  If the MF_ALIAS bit is set
5560222Seric **		and this map class understands the @:@ convention, it
5660222Seric **		should call aliaswait() before returning.
5760089Seric **
5860089Seric **	void map_close(MAP *map)
5960089Seric **		Close the map.
6069401Seric **
6169401Seric **	This file also includes the implementation for getcanonname.
6269401Seric **	It is currently implemented in a pretty ad-hoc manner; it ought
6369401Seric **	to be more properly integrated into the map structure.
6460089Seric */
6560089Seric 
6660089Seric #define DBMMODE		0644
6764718Seric 
6864718Seric extern bool	aliaswait __P((MAP *, char *, int));
6960089Seric /*
7060089Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
7160089Seric **
7260089Seric **	This is a generic version of the map_parse method.
7360089Seric **
7456822Seric **	Parameters:
7560089Seric **		map -- the map being initialized.
7660089Seric **		ap -- a pointer to the args on the config line.
7756822Seric **
7856822Seric **	Returns:
7960089Seric **		TRUE -- if everything parsed OK.
8056822Seric **		FALSE -- otherwise.
8156822Seric **
8256822Seric **	Side Effects:
8360089Seric **		null terminates the filename; stores it in map
8456822Seric */
8556822Seric 
8656822Seric bool
8760089Seric map_parseargs(map, ap)
8856822Seric 	MAP *map;
8960089Seric 	char *ap;
9056822Seric {
9160089Seric 	register char *p = ap;
9256822Seric 
9363753Seric 	map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
9460089Seric 	for (;;)
9560089Seric 	{
9660089Seric 		while (isascii(*p) && isspace(*p))
9760089Seric 			p++;
9860089Seric 		if (*p != '-')
9960089Seric 			break;
10060089Seric 		switch (*++p)
10160089Seric 		{
10260089Seric 		  case 'N':
10360207Seric 			map->map_mflags |= MF_INCLNULL;
10463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
10560089Seric 			break;
10660089Seric 
10763753Seric 		  case 'O':
10863753Seric 			map->map_mflags &= ~MF_TRY1NULL;
10963753Seric 			break;
11063753Seric 
11160089Seric 		  case 'o':
11260207Seric 			map->map_mflags |= MF_OPTIONAL;
11360089Seric 			break;
11460089Seric 
11560089Seric 		  case 'f':
11660207Seric 			map->map_mflags |= MF_NOFOLDCASE;
11760089Seric 			break;
11860089Seric 
11960089Seric 		  case 'm':
12060207Seric 			map->map_mflags |= MF_MATCHONLY;
12160089Seric 			break;
12260089Seric 
12368497Seric 		  case 'A':
12468497Seric 			map->map_mflags |= MF_APPEND;
12568497Seric 			break;
12668497Seric 
12769703Seric 		  case 'q':
12869703Seric 			map->map_mflags |= MF_KEEPQUOTES;
12969703Seric 			break;
13069703Seric 
13160089Seric 		  case 'a':
13260089Seric 			map->map_app = ++p;
13360089Seric 			break;
13468350Seric 
13568350Seric 		  case 'k':
13668350Seric 			while (isascii(*++p) && isspace(*p))
13768350Seric 				continue;
13868350Seric 			map->map_keycolnm = p;
13968350Seric 			break;
14068350Seric 
14168350Seric 		  case 'v':
14268350Seric 			while (isascii(*++p) && isspace(*p))
14368350Seric 				continue;
14468350Seric 			map->map_valcolnm = p;
14568350Seric 			break;
14668350Seric 
14768350Seric 		  case 'z':
14868350Seric 			if (*++p != '\\')
14968350Seric 				map->map_coldelim = *p;
15068350Seric 			else
15168350Seric 			{
15268350Seric 				switch (*++p)
15368350Seric 				{
15468350Seric 				  case 'n':
15568350Seric 					map->map_coldelim = '\n';
15668350Seric 					break;
15768350Seric 
15868350Seric 				  case 't':
15968350Seric 					map->map_coldelim = '\t';
16068350Seric 					break;
16168350Seric 
16268350Seric 				  default:
16368350Seric 					map->map_coldelim = '\\';
16468350Seric 				}
16568350Seric 			}
16668350Seric 			break;
16768497Seric #ifdef RESERVED_FOR_SUN
16868497Seric 		  case 'd':
16968497Seric 			map->map_mflags |= MF_DOMAIN_WIDE;
17068497Seric 			break;
17168497Seric 
17268497Seric 		  case 's':
17368497Seric 			/* info type */
17468497Seric 			break;
17568497Seric #endif
17660089Seric 		}
17760089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
17860089Seric 			p++;
17960089Seric 		if (*p != '\0')
18060089Seric 			*p++ = '\0';
18160089Seric 	}
18260089Seric 	if (map->map_app != NULL)
18360089Seric 		map->map_app = newstr(map->map_app);
18468350Seric 	if (map->map_keycolnm != NULL)
18568350Seric 		map->map_keycolnm = newstr(map->map_keycolnm);
18668350Seric 	if (map->map_valcolnm != NULL)
18768350Seric 		map->map_valcolnm = newstr(map->map_valcolnm);
18860089Seric 
18960089Seric 	if (*p != '\0')
19060089Seric 	{
19160089Seric 		map->map_file = p;
19260089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
19360089Seric 			p++;
19460089Seric 		if (*p != '\0')
19560089Seric 			*p++ = '\0';
19660089Seric 		map->map_file = newstr(map->map_file);
19760089Seric 	}
19860089Seric 
19960089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
20060089Seric 		p++;
20160089Seric 	if (*p != '\0')
20260089Seric 		map->map_rebuild = newstr(p);
20360089Seric 
20468350Seric 	if (map->map_file == NULL &&
20568350Seric 	    !bitset(MCF_OPTFILE, map->map_class->map_cflags))
20657208Seric 	{
20760089Seric 		syserr("No file name for %s map %s",
20860089Seric 			map->map_class->map_cname, map->map_mname);
20956822Seric 		return FALSE;
21057208Seric 	}
21160089Seric 	return TRUE;
21260089Seric }
21360089Seric /*
21460089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
21560089Seric **
21660089Seric **	It also adds the map_app string.  It can be used as a utility
21760089Seric **	in the map_lookup method.
21860089Seric **
21960089Seric **	Parameters:
22060089Seric **		map -- the map that causes this.
22160089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
22260089Seric **		slen -- the length of s.
22360089Seric **		av -- arguments to interpolate into buf.
22460089Seric **
22560089Seric **	Returns:
22667895Seric **		Pointer to rewritten result.  This is static data that
22767895Seric **		should be copied if it is to be saved!
22860089Seric **
22960089Seric **	Side Effects:
23060089Seric **		none.
23160089Seric */
23260089Seric 
23360089Seric char *
23460089Seric map_rewrite(map, s, slen, av)
23560089Seric 	register MAP *map;
23660089Seric 	register char *s;
23760089Seric 	int slen;
23860089Seric 	char **av;
23960089Seric {
24060089Seric 	register char *bp;
24160089Seric 	register char c;
24260089Seric 	char **avp;
24360089Seric 	register char *ap;
24460089Seric 	int i;
24560089Seric 	int len;
24667895Seric 	static int buflen = -1;
24767895Seric 	static char *buf = NULL;
24860089Seric 
24960537Seric 	if (tTd(39, 1))
25060089Seric 	{
25160256Seric 		printf("map_rewrite(%.*s), av =", slen, s);
25260256Seric 		if (av == NULL)
25360256Seric 			printf(" (nullv)");
25460256Seric 		else
25560256Seric 		{
25660256Seric 			for (avp = av; *avp != NULL; avp++)
25760256Seric 				printf("\n\t%s", *avp);
25860256Seric 		}
25960256Seric 		printf("\n");
26060089Seric 	}
26160089Seric 
26260089Seric 	/* count expected size of output (can safely overestimate) */
26360089Seric 	i = len = slen;
26460089Seric 	if (av != NULL)
26560089Seric 	{
26660089Seric 		bp = s;
26760089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
26860089Seric 		{
26960089Seric 			if (c != '%')
27060089Seric 				continue;
27160089Seric 			if (--i < 0)
27260089Seric 				break;
27360089Seric 			c = *bp++;
27460089Seric 			if (!(isascii(c) && isdigit(c)))
27560089Seric 				continue;
27663937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
27760089Seric 				continue;
27860089Seric 			if (*avp == NULL)
27960089Seric 				continue;
28060089Seric 			len += strlen(*avp);
28160089Seric 		}
28260089Seric 	}
28360089Seric 	if (map->map_app != NULL)
28460089Seric 		len += strlen(map->map_app);
28567895Seric 	if (buflen < ++len)
28660089Seric 	{
28760089Seric 		/* need to malloc additional space */
28867895Seric 		buflen = len;
28967895Seric 		if (buf != NULL)
29067895Seric 			free(buf);
29167895Seric 		buf = xalloc(buflen);
29260089Seric 	}
29360089Seric 
29467895Seric 	bp = buf;
29560089Seric 	if (av == NULL)
29660089Seric 	{
29760089Seric 		bcopy(s, bp, slen);
29860089Seric 		bp += slen;
29960089Seric 	}
30060089Seric 	else
30160089Seric 	{
30260089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
30360089Seric 		{
30460089Seric 			if (c != '%')
30560089Seric 			{
30660089Seric   pushc:
30760089Seric 				*bp++ = c;
30860089Seric 				continue;
30960089Seric 			}
31060089Seric 			if (--slen < 0 || (c = *s++) == '\0')
31160089Seric 				c = '%';
31260089Seric 			if (c == '%')
31360089Seric 				goto pushc;
31460089Seric 			if (!(isascii(c) && isdigit(c)))
31560089Seric 			{
31660089Seric 				*bp++ = '%';
31760089Seric 				goto pushc;
31860089Seric 			}
31963937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
32060089Seric 				continue;
32160089Seric 			if (*avp == NULL)
32260089Seric 				continue;
32360089Seric 
32460089Seric 			/* transliterate argument into output string */
32560089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
32660089Seric 				*bp++ = c;
32760089Seric 		}
32860089Seric 	}
32960089Seric 	if (map->map_app != NULL)
33060089Seric 		strcpy(bp, map->map_app);
33160089Seric 	else
33260089Seric 		*bp = '\0';
33360537Seric 	if (tTd(39, 1))
33467895Seric 		printf("map_rewrite => %s\n", buf);
33567895Seric 	return buf;
33660089Seric }
33760089Seric /*
33860537Seric **  INITMAPS -- initialize for aliasing
33960537Seric **
34060537Seric **	Parameters:
34160537Seric **		rebuild -- if TRUE, this rebuilds the cached versions.
34260537Seric **		e -- current envelope.
34360537Seric **
34460537Seric **	Returns:
34560537Seric **		none.
34660537Seric **
34760537Seric **	Side Effects:
34860537Seric **		initializes aliases:
34960537Seric **		if NDBM:  opens the database.
35060537Seric **		if ~NDBM: reads the aliases into the symbol table.
35160537Seric */
35260537Seric 
35369748Seric void
35460537Seric initmaps(rebuild, e)
35560537Seric 	bool rebuild;
35660537Seric 	register ENVELOPE *e;
35760537Seric {
35860537Seric 	extern void map_init();
35960537Seric 
36064671Seric #ifdef XDEBUG
36164671Seric 	checkfd012("entering initmaps");
36264671Seric #endif
36360537Seric 	CurEnv = e;
36465085Seric 	if (rebuild)
36565085Seric 	{
36665085Seric 		stabapply(map_init, 1);
36765085Seric 		stabapply(map_init, 2);
36865085Seric 	}
36965085Seric 	else
37065085Seric 	{
37165085Seric 		stabapply(map_init, 0);
37265085Seric 	}
37364671Seric #ifdef XDEBUG
37464671Seric 	checkfd012("exiting initmaps");
37564671Seric #endif
37660537Seric }
37760537Seric 
37860537Seric void
37960537Seric map_init(s, rebuild)
38060537Seric 	register STAB *s;
38160537Seric 	int rebuild;
38260537Seric {
38360537Seric 	register MAP *map;
38460537Seric 
38560537Seric 	/* has to be a map */
38660537Seric 	if (s->s_type != ST_MAP)
38760537Seric 		return;
38860537Seric 
38960537Seric 	map = &s->s_map;
39060537Seric 	if (!bitset(MF_VALID, map->map_mflags))
39160537Seric 		return;
39260537Seric 
39360537Seric 	if (tTd(38, 2))
39468350Seric 		printf("map_init(%s:%s, %s, %d)\n",
39564690Seric 			map->map_class->map_cname == NULL ? "NULL" :
39664690Seric 				map->map_class->map_cname,
39768350Seric 			map->map_mname == NULL ? "NULL" : map->map_mname,
39865085Seric 			map->map_file == NULL ? "NULL" : map->map_file,
39965085Seric 			rebuild);
40060537Seric 
40165085Seric 	if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&
40265085Seric 		    bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))
40365085Seric 	{
40465085Seric 		if (tTd(38, 3))
40565085Seric 			printf("\twrong pass\n");
40665085Seric 		return;
40765085Seric 	}
40865085Seric 
40960537Seric 	/* if already open, close it (for nested open) */
41060537Seric 	if (bitset(MF_OPEN, map->map_mflags))
41160537Seric 	{
41260537Seric 		map->map_class->map_close(map);
41360537Seric 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
41460537Seric 	}
41560537Seric 
41665085Seric 	if (rebuild == 2)
41760537Seric 	{
41865085Seric 		rebuildaliases(map, FALSE);
41960537Seric 	}
42060537Seric 	else
42160537Seric 	{
42260537Seric 		if (map->map_class->map_open(map, O_RDONLY))
42360537Seric 		{
42460537Seric 			if (tTd(38, 4))
42568350Seric 				printf("\t%s:%s %s: valid\n",
42664690Seric 					map->map_class->map_cname == NULL ? "NULL" :
42764690Seric 						map->map_class->map_cname,
42868350Seric 					map->map_mname == NULL ? "NULL" :
42968350Seric 						map->map_mname,
43064690Seric 					map->map_file == NULL ? "NULL" :
43164690Seric 						map->map_file);
43260537Seric 			map->map_mflags |= MF_OPEN;
43360537Seric 		}
43468350Seric 		else
43568350Seric 		{
43668350Seric 			if (tTd(38, 4))
43768350Seric 				printf("\t%s:%s %s: invalid: %s\n",
43868350Seric 					map->map_class->map_cname == NULL ? "NULL" :
43968350Seric 						map->map_class->map_cname,
44068350Seric 					map->map_mname == NULL ? "NULL" :
44168350Seric 						map->map_mname,
44268350Seric 					map->map_file == NULL ? "NULL" :
44368350Seric 						map->map_file,
44468350Seric 					errstring(errno));
44568350Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
44668350Seric 			{
44768350Seric 				extern MAPCLASS BogusMapClass;
44868350Seric 
44968350Seric 				map->map_class = &BogusMapClass;
45068350Seric 				map->map_mflags |= MF_OPEN;
45168350Seric 			}
45268350Seric 		}
45360537Seric 	}
45460537Seric }
45560537Seric /*
45660089Seric **  NDBM modules
45760089Seric */
45860089Seric 
45960089Seric #ifdef NDBM
46060089Seric 
46160089Seric /*
46260089Seric **  DBM_MAP_OPEN -- DBM-style map open
46360089Seric */
46460089Seric 
46560089Seric bool
46660089Seric ndbm_map_open(map, mode)
46760089Seric 	MAP *map;
46860089Seric 	int mode;
46960089Seric {
47064284Seric 	register DBM *dbm;
47164284Seric 	struct stat st;
47260089Seric 
47360537Seric 	if (tTd(38, 2))
47468350Seric 		printf("ndbm_map_open(%s, %s, %d)\n",
47568350Seric 			map->map_mname, map->map_file, mode);
47660089Seric 
47760207Seric 	if (mode == O_RDWR)
47860207Seric 		mode |= O_CREAT|O_TRUNC;
47960207Seric 
48060089Seric 	/* open the database */
48160089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
48256822Seric 	if (dbm == NULL)
48356822Seric 	{
48464718Seric 		if (aliaswait(map, ".pag", FALSE))
48564718Seric 			return TRUE;
48660207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
48756836Seric 			syserr("Cannot open DBM database %s", map->map_file);
48856822Seric 		return FALSE;
48956822Seric 	}
49060089Seric 	map->map_db1 = (void *) dbm;
49164964Seric 	if (mode == O_RDONLY)
49264964Seric 	{
49364964Seric 		if (bitset(MF_ALIAS, map->map_mflags) &&
49464964Seric 		    !aliaswait(map, ".pag", TRUE))
49564718Seric 			return FALSE;
49664964Seric 	}
49764964Seric 	else
49864964Seric 	{
49964964Seric 		int fd;
50064964Seric 
50164964Seric 		/* exclusive lock for duration of rebuild */
50264964Seric 		fd = dbm_dirfno((DBM *) map->map_db1);
50364964Seric 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
50464964Seric 		    lockfile(fd, map->map_file, ".dir", LOCK_EX))
50564964Seric 			map->map_mflags |= MF_LOCKED;
50664964Seric 	}
50764718Seric 	if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
50864284Seric 		map->map_mtime = st.st_mtime;
50956822Seric 	return TRUE;
51056822Seric }
51160089Seric 
51260089Seric 
51360089Seric /*
51456822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
51556822Seric */
51656822Seric 
51756822Seric char *
51860089Seric ndbm_map_lookup(map, name, av, statp)
51956822Seric 	MAP *map;
52060089Seric 	char *name;
52156822Seric 	char **av;
52259084Seric 	int *statp;
52356822Seric {
52456822Seric 	datum key, val;
52564373Seric 	int fd;
52660089Seric 	char keybuf[MAXNAME + 1];
52756822Seric 
52860537Seric 	if (tTd(38, 20))
52968350Seric 		printf("ndbm_map_lookup(%s, %s)\n",
53068350Seric 			map->map_mname, name);
53160089Seric 
53260089Seric 	key.dptr = name;
53360089Seric 	key.dsize = strlen(name);
53460207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
53557014Seric 	{
53660089Seric 		if (key.dsize > sizeof keybuf - 1)
53760089Seric 			key.dsize = sizeof keybuf - 1;
53860089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
53960089Seric 		makelower(keybuf);
54060089Seric 		key.dptr = keybuf;
54157014Seric 	}
54264373Seric 	fd = dbm_dirfno((DBM *) map->map_db1);
54364388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
54464373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
54563753Seric 	val.dptr = NULL;
54663753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
54763753Seric 	{
54863753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
54963753Seric 		if (val.dptr != NULL)
55063753Seric 			map->map_mflags &= ~MF_TRY1NULL;
55163753Seric 	}
55263753Seric 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
55363753Seric 	{
55456822Seric 		key.dsize++;
55563753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
55663753Seric 		if (val.dptr != NULL)
55763753Seric 			map->map_mflags &= ~MF_TRY0NULL;
55863753Seric 	}
55964388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
56064373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
56156822Seric 	if (val.dptr == NULL)
56256822Seric 		return NULL;
56360207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
56463753Seric 		return map_rewrite(map, name, strlen(name), NULL);
56563753Seric 	else
56663753Seric 		return map_rewrite(map, val.dptr, val.dsize, av);
56756822Seric }
56856822Seric 
56956822Seric 
57056822Seric /*
57160089Seric **  DBM_MAP_STORE -- store a datum in the database
57256822Seric */
57356822Seric 
57460089Seric void
57560089Seric ndbm_map_store(map, lhs, rhs)
57660089Seric 	register MAP *map;
57760089Seric 	char *lhs;
57860089Seric 	char *rhs;
57960089Seric {
58060089Seric 	datum key;
58160089Seric 	datum data;
58260089Seric 	int stat;
58360089Seric 
58460537Seric 	if (tTd(38, 12))
58568350Seric 		printf("ndbm_map_store(%s, %s, %s)\n",
58668350Seric 			map->map_mname, lhs, rhs);
58760089Seric 
58860089Seric 	key.dsize = strlen(lhs);
58960089Seric 	key.dptr = lhs;
59060089Seric 
59160089Seric 	data.dsize = strlen(rhs);
59260089Seric 	data.dptr = rhs;
59360089Seric 
59460207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
59560089Seric 	{
59660089Seric 		key.dsize++;
59760089Seric 		data.dsize++;
59860089Seric 	}
59960089Seric 
60060089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
60160089Seric 	if (stat > 0)
60260089Seric 	{
60368497Seric 		if (!bitset(MF_APPEND, map->map_mflags))
60468497Seric 			usrerr("050 Warning: duplicate alias name %s", lhs);
60568497Seric 		else
60668497Seric 		{
60768497Seric 			static char *buf = NULL;
60868497Seric 			static int bufsiz = 0;
60968879Seric 			auto int xstat;
61068497Seric 			datum old;
61168497Seric 
61268879Seric 			old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat);
61368497Seric 			if (old.dptr != NULL && *old.dptr != '\0')
61468497Seric 			{
61568497Seric 				old.dsize = strlen(old.dptr);
61668497Seric 				if (data.dsize + old.dsize + 2 > bufsiz)
61768497Seric 				{
61868497Seric 					if (buf != NULL)
61968497Seric 						(void) free(buf);
62068497Seric 					bufsiz = data.dsize + old.dsize + 2;
62168497Seric 					buf = xalloc(bufsiz);
62268497Seric 				}
62368497Seric 				sprintf(buf, "%s,%s", data.dptr, old.dptr);
62468497Seric 				data.dsize = data.dsize + old.dsize + 1;
62568497Seric 				data.dptr = buf;
62668497Seric 				if (tTd(38, 9))
62768497Seric 					printf("ndbm_map_store append=%s\n", data.dptr);
62868497Seric 			}
62968497Seric 		}
63060089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
63160089Seric 	}
63260089Seric 	if (stat != 0)
63360089Seric 		syserr("readaliases: dbm put (%s)", lhs);
63460089Seric }
63560089Seric 
63660089Seric 
63760089Seric /*
63860207Seric **  NDBM_MAP_CLOSE -- close the database
63960089Seric */
64060089Seric 
64160089Seric void
64260089Seric ndbm_map_close(map)
64360089Seric 	register MAP  *map;
64460089Seric {
64566773Seric 	if (tTd(38, 9))
64668350Seric 		printf("ndbm_map_close(%s, %s, %x)\n",
64768350Seric 			map->map_mname, map->map_file, map->map_mflags);
64866773Seric 
64960207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
65060089Seric 	{
65164250Seric #ifdef NIS
65264075Seric 		bool inclnull;
65360089Seric 		char buf[200];
65460089Seric 
65564075Seric 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
65664075Seric 		map->map_mflags &= ~MF_INCLNULL;
65764075Seric 
65869651Seric 		if (strstr(map->map_file, "/yp/") != NULL)
65969651Seric 		{
66069651Seric 			(void) sprintf(buf, "%010ld", curtime());
66169651Seric 			ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
66260089Seric 
66369651Seric 			(void) gethostname(buf, sizeof buf);
66469651Seric 			ndbm_map_store(map, "YP_MASTER_NAME", buf);
66569651Seric 		}
66664075Seric 
66764075Seric 		if (inclnull)
66864075Seric 			map->map_mflags |= MF_INCLNULL;
66960089Seric #endif
67060089Seric 
67160089Seric 		/* write out the distinguished alias */
67260089Seric 		ndbm_map_store(map, "@", "@");
67360089Seric 	}
67460089Seric 	dbm_close((DBM *) map->map_db1);
67560089Seric }
67660089Seric 
67760089Seric #endif
67860089Seric /*
67960582Seric **  NEWDB (Hash and BTree) Modules
68060089Seric */
68160089Seric 
68260089Seric #ifdef NEWDB
68360089Seric 
68460089Seric /*
68560582Seric **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
68660582Seric **
68760582Seric **	These do rather bizarre locking.  If you can lock on open,
68860582Seric **	do that to avoid the condition of opening a database that
68960582Seric **	is being rebuilt.  If you don't, we'll try to fake it, but
69060582Seric **	there will be a race condition.  If opening for read-only,
69160582Seric **	we immediately release the lock to avoid freezing things up.
69260582Seric **	We really ought to hold the lock, but guarantee that we won't
69360582Seric **	be pokey about it.  That's hard to do.
69460089Seric */
69560089Seric 
69656822Seric bool
69760089Seric bt_map_open(map, mode)
69856822Seric 	MAP *map;
69960089Seric 	int mode;
70056822Seric {
70156822Seric 	DB *db;
70260228Seric 	int i;
70360582Seric 	int omode;
70464373Seric 	int fd;
70564284Seric 	struct stat st;
70668528Seric 	char buf[MAXNAME + 1];
70756822Seric 
70860537Seric 	if (tTd(38, 2))
70968350Seric 		printf("bt_map_open(%s, %s, %d)\n",
71068350Seric 			map->map_mname, map->map_file, mode);
71160089Seric 
71260582Seric 	omode = mode;
71360582Seric 	if (omode == O_RDWR)
71460582Seric 	{
71560582Seric 		omode |= O_CREAT|O_TRUNC;
71665830Seric #if defined(O_EXLOCK) && HASFLOCK
71760582Seric 		omode |= O_EXLOCK;
71866843Seric # if !OLD_NEWDB
71960582Seric 	}
72060582Seric 	else
72160582Seric 	{
72260582Seric 		omode |= O_SHLOCK;
72360582Seric # endif
72460582Seric #endif
72560582Seric 	}
72660207Seric 
72760228Seric 	(void) strcpy(buf, map->map_file);
72860228Seric 	i = strlen(buf);
72960228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
73060228Seric 		(void) strcat(buf, ".db");
73160582Seric 	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
73256822Seric 	if (db == NULL)
73356822Seric 	{
73464718Seric #ifdef MAYBENEXTRELEASE
73564718Seric 		if (aliaswait(map, ".db", FALSE))
73664718Seric 			return TRUE;
73764718Seric #endif
73860207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
73956836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
74056822Seric 		return FALSE;
74156822Seric 	}
74268350Seric #if !OLD_NEWDB
74364373Seric 	fd = db->fd(db);
74468778Seric # if defined(O_EXLOCK) && HASFLOCK
74568778Seric 	if (fd >= 0)
74668778Seric 	{
74768778Seric 		if (mode == O_RDONLY)
74868778Seric 			(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
74968778Seric 		else
75068778Seric 			map->map_mflags |= MF_LOCKED;
75168778Seric 	}
75268778Seric # else
75364373Seric 	if (mode == O_RDWR && fd >= 0)
75464388Seric 	{
75564388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
75664388Seric 			map->map_mflags |= MF_LOCKED;
75764388Seric 	}
75860582Seric # endif
75960582Seric #endif
76060585Seric 
76160585Seric 	/* try to make sure that at least the database header is on disk */
76260585Seric 	if (mode == O_RDWR)
76366843Seric #if OLD_NEWDB
76464373Seric 		(void) db->sync(db);
76564373Seric #else
76660585Seric 		(void) db->sync(db, 0);
76760585Seric 
76864373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
76964284Seric 		map->map_mtime = st.st_mtime;
77064284Seric #endif
77164284Seric 
77260089Seric 	map->map_db2 = (void *) db;
77360207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
77464718Seric 		if (!aliaswait(map, ".db", TRUE))
77564718Seric 			return FALSE;
77656822Seric 	return TRUE;
77756822Seric }
77856822Seric 
77956822Seric 
78056822Seric /*
78156822Seric **  HASH_MAP_INIT -- HASH-style map initialization
78256822Seric */
78356822Seric 
78456822Seric bool
78560089Seric hash_map_open(map, mode)
78656822Seric 	MAP *map;
78760089Seric 	int mode;
78856822Seric {
78956822Seric 	DB *db;
79060228Seric 	int i;
79160582Seric 	int omode;
79264373Seric 	int fd;
79364284Seric 	struct stat st;
79468528Seric 	char buf[MAXNAME + 1];
79556822Seric 
79660537Seric 	if (tTd(38, 2))
79768350Seric 		printf("hash_map_open(%s, %s, %d)\n",
79868350Seric 			map->map_mname, map->map_file, mode);
79960089Seric 
80060582Seric 	omode = mode;
80160582Seric 	if (omode == O_RDWR)
80260582Seric 	{
80360582Seric 		omode |= O_CREAT|O_TRUNC;
80465830Seric #if defined(O_EXLOCK) && HASFLOCK
80560582Seric 		omode |= O_EXLOCK;
80666843Seric # if !OLD_NEWDB
80760582Seric 	}
80860582Seric 	else
80960582Seric 	{
81060582Seric 		omode |= O_SHLOCK;
81160582Seric # endif
81260582Seric #endif
81360582Seric 	}
81460207Seric 
81560228Seric 	(void) strcpy(buf, map->map_file);
81660228Seric 	i = strlen(buf);
81760228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
81860228Seric 		(void) strcat(buf, ".db");
81960582Seric 	db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
82056822Seric 	if (db == NULL)
82156822Seric 	{
82264718Seric #ifdef MAYBENEXTRELEASE
82364718Seric 		if (aliaswait(map, ".db", FALSE))
82464718Seric 			return TRUE;
82564718Seric #endif
82660207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
82756836Seric 			syserr("Cannot open HASH database %s", map->map_file);
82856822Seric 		return FALSE;
82956822Seric 	}
83068350Seric #if !OLD_NEWDB
83164373Seric 	fd = db->fd(db);
83268778Seric # if defined(O_EXLOCK) && HASFLOCK
83368778Seric 	if (fd >= 0)
83468778Seric 	{
83568778Seric 		if (mode == O_RDONLY)
83668778Seric 			(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
83768778Seric 		else
83868778Seric 			map->map_mflags |= MF_LOCKED;
83968778Seric 	}
84068778Seric # else
84164373Seric 	if (mode == O_RDWR && fd >= 0)
84264388Seric 	{
84364388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
84464388Seric 			map->map_mflags |= MF_LOCKED;
84564388Seric 	}
84660582Seric # endif
84760582Seric #endif
84860585Seric 
84960585Seric 	/* try to make sure that at least the database header is on disk */
85060585Seric 	if (mode == O_RDWR)
85166843Seric #if OLD_NEWDB
85264373Seric 		(void) db->sync(db);
85364373Seric #else
85460585Seric 		(void) db->sync(db, 0);
85560585Seric 
85664373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
85764284Seric 		map->map_mtime = st.st_mtime;
85864284Seric #endif
85964284Seric 
86060089Seric 	map->map_db2 = (void *) db;
86160207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
86264718Seric 		if (!aliaswait(map, ".db", TRUE))
86364718Seric 			return FALSE;
86456822Seric 	return TRUE;
86556822Seric }
86656822Seric 
86756822Seric 
86856822Seric /*
86956822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
87056822Seric */
87156822Seric 
87256822Seric char *
87360089Seric db_map_lookup(map, name, av, statp)
87456822Seric 	MAP *map;
87560089Seric 	char *name;
87656822Seric 	char **av;
87759084Seric 	int *statp;
87856822Seric {
87956822Seric 	DBT key, val;
88060422Seric 	register DB *db = (DB *) map->map_db2;
88160422Seric 	int st;
88260422Seric 	int saveerrno;
88364373Seric 	int fd;
88460089Seric 	char keybuf[MAXNAME + 1];
88556822Seric 
88660537Seric 	if (tTd(38, 20))
88768350Seric 		printf("db_map_lookup(%s, %s)\n",
88868350Seric 			map->map_mname, name);
88960089Seric 
89060089Seric 	key.size = strlen(name);
89160089Seric 	if (key.size > sizeof keybuf - 1)
89260089Seric 		key.size = sizeof keybuf - 1;
89360089Seric 	key.data = keybuf;
89460089Seric 	bcopy(name, keybuf, key.size + 1);
89560207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
89660089Seric 		makelower(keybuf);
89766843Seric #if !OLD_NEWDB
89864388Seric 	fd = db->fd(db);
89964388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
90064388Seric 		(void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
90160422Seric #endif
90263753Seric 	st = 1;
90363753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
90463753Seric 	{
90563753Seric 		st = db->get(db, &key, &val, 0);
90663753Seric 		if (st == 0)
90763753Seric 			map->map_mflags &= ~MF_TRY1NULL;
90863753Seric 	}
90963753Seric 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
91063753Seric 	{
91163753Seric 		key.size++;
91263753Seric 		st = db->get(db, &key, &val, 0);
91363753Seric 		if (st == 0)
91463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
91563753Seric 	}
91660422Seric 	saveerrno = errno;
91766843Seric #if !OLD_NEWDB
91864388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
91964373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
92060422Seric #endif
92160422Seric 	if (st != 0)
92260422Seric 	{
92360422Seric 		errno = saveerrno;
92460422Seric 		if (st < 0)
92560422Seric 			syserr("db_map_lookup: get (%s)", name);
92656822Seric 		return NULL;
92760422Seric 	}
92860207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
92963753Seric 		return map_rewrite(map, name, strlen(name), NULL);
93063753Seric 	else
93163753Seric 		return map_rewrite(map, val.data, val.size, av);
93256822Seric }
93356822Seric 
93460089Seric 
93560089Seric /*
93660089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
93756822Seric */
93856822Seric 
93960089Seric void
94060089Seric db_map_store(map, lhs, rhs)
94160089Seric 	register MAP *map;
94260089Seric 	char *lhs;
94360089Seric 	char *rhs;
94456822Seric {
94560089Seric 	int stat;
94660089Seric 	DBT key;
94760089Seric 	DBT data;
94860089Seric 	register DB *db = map->map_db2;
94956822Seric 
95060537Seric 	if (tTd(38, 20))
95168350Seric 		printf("db_map_store(%s, %s, %s)\n",
95268350Seric 			map->map_mname, lhs, rhs);
95360089Seric 
95460089Seric 	key.size = strlen(lhs);
95560089Seric 	key.data = lhs;
95660089Seric 
95760089Seric 	data.size = strlen(rhs);
95860089Seric 	data.data = rhs;
95960089Seric 
96060207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
96156822Seric 	{
96260089Seric 		key.size++;
96360089Seric 		data.size++;
96460089Seric 	}
96556836Seric 
96660089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
96760089Seric 	if (stat > 0)
96860089Seric 	{
96968497Seric 		if (!bitset(MF_APPEND, map->map_mflags))
97068497Seric 			usrerr("050 Warning: duplicate alias name %s", lhs);
97168497Seric 		else
97268497Seric 		{
97368497Seric 			static char *buf = NULL;
97468497Seric 			static int bufsiz = 0;
97568497Seric 			DBT old;
97668497Seric 
97768497Seric 			old.data = db_map_lookup(map, key.data, NULL, &stat);
97868497Seric 			if (old.data != NULL)
97968497Seric 			{
98068497Seric 				old.size = strlen(old.data);
98168497Seric 				if (data.size + old.size + 2 > bufsiz)
98268497Seric 				{
98368497Seric 					if (buf != NULL)
98468497Seric 						(void) free(buf);
98568497Seric 					bufsiz = data.size + old.size + 2;
98668497Seric 					buf = xalloc(bufsiz);
98768497Seric 				}
98868497Seric 				sprintf(buf, "%s,%s", data.data, old.data);
98968497Seric 				data.size = data.size + old.size + 1;
99068497Seric 				data.data = buf;
99168497Seric 				if (tTd(38, 9))
99268497Seric 					printf("db_map_store append=%s\n", data.data);
99368497Seric 			}
99468497Seric 		}
99560089Seric 		stat = db->put(db, &key, &data, 0);
99660089Seric 	}
99760089Seric 	if (stat != 0)
99860089Seric 		syserr("readaliases: db put (%s)", lhs);
99960089Seric }
100056836Seric 
100156847Seric 
100260089Seric /*
100360089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
100460089Seric */
100560089Seric 
100660089Seric void
100760089Seric db_map_close(map)
100860089Seric 	MAP *map;
100960089Seric {
101060089Seric 	register DB *db = map->map_db2;
101160089Seric 
101260537Seric 	if (tTd(38, 9))
101368350Seric 		printf("db_map_close(%s, %s, %x)\n",
101468350Seric 			map->map_mname, map->map_file, map->map_mflags);
101560089Seric 
101660207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
101758804Seric 	{
101860089Seric 		/* write out the distinguished alias */
101960089Seric 		db_map_store(map, "@", "@");
102058804Seric 	}
102158963Seric 
102260089Seric 	if (db->close(db) != 0)
102360089Seric 		syserr("readaliases: db close failure");
102456822Seric }
102557208Seric 
102660089Seric #endif
102760089Seric /*
102860089Seric **  NIS Modules
102960089Seric */
103060089Seric 
103160089Seric # ifdef NIS
103260089Seric 
103364369Seric # ifndef YPERR_BUSY
103464369Seric #  define YPERR_BUSY	16
103564369Seric # endif
103664369Seric 
103757208Seric /*
103860089Seric **  NIS_MAP_OPEN -- open DBM map
103957208Seric */
104057208Seric 
104157208Seric bool
104260089Seric nis_map_open(map, mode)
104357208Seric 	MAP *map;
104460089Seric 	int mode;
104557208Seric {
104657216Seric 	int yperr;
104760215Seric 	register char *p;
104860215Seric 	auto char *vp;
104960215Seric 	auto int vsize;
105057216Seric 
105160537Seric 	if (tTd(38, 2))
105268350Seric 		printf("nis_map_open(%s, %s)\n",
105368350Seric 			map->map_mname, map->map_file);
105460089Seric 
105560207Seric 	if (mode != O_RDONLY)
105660207Seric 	{
105764650Seric 		/* issue a pseudo-error message */
105864650Seric #ifdef ENOSYS
105964650Seric 		errno = ENOSYS;
106064650Seric #else
106164650Seric # ifdef EFTYPE
106264650Seric 		errno = EFTYPE;
106364650Seric # else
106464650Seric 		errno = ENXIO;
106564650Seric # endif
106664650Seric #endif
106760207Seric 		return FALSE;
106860207Seric 	}
106960207Seric 
107060089Seric 	p = strchr(map->map_file, '@');
107160089Seric 	if (p != NULL)
107260089Seric 	{
107360089Seric 		*p++ = '\0';
107460089Seric 		if (*p != '\0')
107560089Seric 			map->map_domain = p;
107660089Seric 	}
107760215Seric 
107860089Seric 	if (*map->map_file == '\0')
107960089Seric 		map->map_file = "mail.aliases";
108060089Seric 
108166157Seric 	if (map->map_domain == NULL)
108266157Seric 	{
108366157Seric 		yperr = yp_get_default_domain(&map->map_domain);
108466157Seric 		if (yperr != 0)
108566157Seric 		{
108666744Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
108768350Seric 				syserr("421 NIS map %s specified, but NIS not running\n",
108866744Seric 					map->map_file);
108966157Seric 			return FALSE;
109066157Seric 		}
109166157Seric 	}
109266157Seric 
109360215Seric 	/* check to see if this map actually exists */
109460089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
109560089Seric 			&vp, &vsize);
109660537Seric 	if (tTd(38, 10))
109760089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
109860089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
109960089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
110068350Seric 	{
110168350Seric 		if (!bitset(MF_ALIAS, map->map_mflags) ||
110268350Seric 		    aliaswait(map, NULL, TRUE))
110368350Seric 			return TRUE;
110468350Seric 	}
110560215Seric 
110660215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
110768735Seric 	{
110868735Seric 		syserr("421 Cannot bind to map %s in domain %s: %s",
110968735Seric 			map->map_file, map->map_domain, yperr_string(yperr));
111068735Seric 	}
111160215Seric 
111260089Seric 	return FALSE;
111360089Seric }
111460089Seric 
111560089Seric 
111660089Seric /*
111757208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
111857208Seric */
111957208Seric 
112057208Seric char *
112160089Seric nis_map_lookup(map, name, av, statp)
112257208Seric 	MAP *map;
112360089Seric 	char *name;
112457208Seric 	char **av;
112559084Seric 	int *statp;
112657208Seric {
112757208Seric 	char *vp;
112857642Seric 	auto int vsize;
112959274Seric 	int buflen;
113060215Seric 	int yperr;
113160089Seric 	char keybuf[MAXNAME + 1];
113257208Seric 
113360537Seric 	if (tTd(38, 20))
113468350Seric 		printf("nis_map_lookup(%s, %s)\n",
113568350Seric 			map->map_mname, name);
113660089Seric 
113760089Seric 	buflen = strlen(name);
113860089Seric 	if (buflen > sizeof keybuf - 1)
113960089Seric 		buflen = sizeof keybuf - 1;
114060089Seric 	bcopy(name, keybuf, buflen + 1);
114160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
114260089Seric 		makelower(keybuf);
114363753Seric 	yperr = YPERR_KEY;
114463753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
114563753Seric 	{
114663753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
114763753Seric 			     &vp, &vsize);
114863753Seric 		if (yperr == 0)
114963753Seric 			map->map_mflags &= ~MF_TRY1NULL;
115063753Seric 	}
115163753Seric 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
115263753Seric 	{
115359274Seric 		buflen++;
115463753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
115563753Seric 			     &vp, &vsize);
115663753Seric 		if (yperr == 0)
115763753Seric 			map->map_mflags &= ~MF_TRY0NULL;
115863753Seric 	}
115960089Seric 	if (yperr != 0)
116060089Seric 	{
116160089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
116260215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
116357208Seric 		return NULL;
116460089Seric 	}
116560207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
116663753Seric 		return map_rewrite(map, name, strlen(name), NULL);
116763753Seric 	else
116863753Seric 		return map_rewrite(map, vp, vsize, av);
116957208Seric }
117057208Seric 
117169401Seric 
117269401Seric /*
117369401Seric **  NIS_GETCANONNAME -- look up canonical name in NIS
117469401Seric */
117569401Seric 
117669401Seric bool
117769401Seric nis_getcanonname(name, hbsize, statp)
117869401Seric 	char *name;
117969401Seric 	int hbsize;
118069401Seric 	int *statp;
118169401Seric {
118269401Seric 	char *vp;
118369401Seric 	auto int vsize;
118469401Seric 	int keylen;
118569401Seric 	int yperr;
118669401Seric 	static bool try0null = TRUE;
118769401Seric 	static bool try1null = TRUE;
118869401Seric 	static char *yp_domain = NULL;
118969748Seric 	char *domain;
1190*69780Seric 	char *cname;
119169401Seric 	char host_record[MAXLINE];
1192*69780Seric 	char fbuf[MAXNAME];
1193*69780Seric 	char nbuf[MAXNAME + 1];
119469401Seric 	extern char *get_column();
119569401Seric 
119669401Seric 	if (tTd(38, 20))
119769401Seric 		printf("nis_getcanonname(%s)\n", name);
119869401Seric 
1199*69780Seric 	if (strlen(name) >= sizeof nbuf)
1200*69780Seric 	{
1201*69780Seric 		*statp = EX_UNAVAILABLE;
1202*69780Seric 		return FALSE;
1203*69780Seric 	}
1204*69780Seric 	(void) strcpy(nbuf, name);
1205*69780Seric 	shorten_hostname(nbuf);
120669401Seric 
120769401Seric 	/* we only accept single token search key */
1208*69780Seric 	if (strchr(nbuf, '.'))
120969401Seric 	{
121069401Seric 		*statp = EX_NOHOST;
121169401Seric 		return FALSE;
121269401Seric 	}
121369401Seric 
1214*69780Seric 	keylen = strlen(nbuf);
121569401Seric 
121669401Seric 	if (yp_domain == NULL)
121769401Seric 		yp_get_default_domain(&yp_domain);
1218*69780Seric 	makelower(nbuf);
121969401Seric 	yperr = YPERR_KEY;
122069401Seric 	if (try0null)
122169401Seric 	{
1222*69780Seric 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
122369401Seric 			     &vp, &vsize);
122469401Seric 		if (yperr == 0)
122569401Seric 			try1null = FALSE;
122669401Seric 	}
122769401Seric 	if (yperr == YPERR_KEY && try1null)
122869401Seric 	{
122969401Seric 		keylen++;
1230*69780Seric 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
123169401Seric 			     &vp, &vsize);
123269401Seric 		if (yperr == 0)
123369401Seric 			try0null = FALSE;
123469401Seric 	}
123569401Seric 	if (yperr != 0)
123669401Seric 	{
123769401Seric 		if (yperr == YPERR_KEY)
123869401Seric 			*statp = EX_NOHOST;
123969401Seric 		else if (yperr == YPERR_BUSY)
124069401Seric 			*statp = EX_TEMPFAIL;
124169401Seric 		else
124269401Seric 			*statp = EX_UNAVAILABLE;
124369401Seric 		return FALSE;
124469401Seric 	}
124569401Seric 	strncpy(host_record, vp, vsize);
124669401Seric 	host_record[vsize] = '\0';
124769663Seric 	if (tTd(38, 44))
124869663Seric 		printf("got record `%s'\n", host_record);
1249*69780Seric 	cname = get_column(host_record, 1, '\0', fbuf);
125069401Seric 	if (cname == NULL)
125169401Seric 	{
125269401Seric 		/* this should not happen, but.... */
125369401Seric 		*statp = EX_NOHOST;
125469401Seric 		return FALSE;
125569401Seric 	}
125669401Seric 
125769703Seric 	if (strchr(cname, '.') != NULL)
125869401Seric 	{
125969703Seric 		domain = "";
126069703Seric 	}
126169703Seric 	else
126269703Seric 	{
126369703Seric 		domain = macvalue('m', CurEnv);
126469703Seric 		if (domain == NULL)
126569703Seric 			domain = "";
126669703Seric 	}
126769703Seric 	if (hbsize >= strlen(cname) + strlen(domain) + 1)
126869703Seric 	{
126969703Seric 		if (domain[0] == '\0')
127069703Seric 			strcpy(name, vp);
127169703Seric 		else
127269703Seric 			sprintf(name, "%s.%s", vp, domain);
127369401Seric 		*statp = EX_OK;
127469401Seric 		return TRUE;
127569401Seric 	}
127669401Seric 	*statp = EX_UNAVAILABLE;
127769401Seric 	return FALSE;
127869401Seric }
127969401Seric 
128068350Seric #endif
128168350Seric /*
128268350Seric **  NISPLUS Modules
128368350Seric **
128468350Seric **	This code donated by Sun Microsystems.
128568350Seric */
128667848Seric 
128768350Seric #ifdef NISPLUS
128868350Seric 
128968350Seric #undef NIS /* symbol conflict in nis.h */
129068350Seric #include <rpcsvc/nis.h>
129168350Seric #include <rpcsvc/nislib.h>
129268350Seric 
129368350Seric #define EN_col(col)	zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
129468350Seric #define COL_NAME(res,i)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
129568350Seric #define COL_MAX(res)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
129668350Seric #define PARTIAL_NAME(x)	((x)[strlen(x) - 1] != '.')
129768350Seric 
129867848Seric /*
129968350Seric **  NISPLUS_MAP_OPEN -- open nisplus table
130067848Seric */
130167848Seric 
130268350Seric bool
130368350Seric nisplus_map_open(map, mode)
130467848Seric 	MAP *map;
130568350Seric 	int mode;
130667848Seric {
130768350Seric 	register char *p;
130868350Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
130968350Seric 	nis_result *res = NULL;
131068350Seric 	u_int objs_len;
131168350Seric 	nis_object *obj_ptr;
131268350Seric 	int retry_cnt, max_col, i;
131368350Seric 
131468350Seric 	if (tTd(38, 2))
131568350Seric 		printf("nisplus_map_open(%s, %s, %d)\n",
131668350Seric 			map->map_mname, map->map_file, mode);
131768350Seric 
131868350Seric 	if (mode != O_RDONLY)
131968350Seric 	{
132068350Seric 		errno = ENODEV;
132168350Seric 		return FALSE;
132268350Seric 	}
132368350Seric 
132468350Seric 	if (*map->map_file == '\0')
132568350Seric 		map->map_file = "mail_aliases.org_dir";
132668350Seric 
132768350Seric 	if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
132868350Seric 	{
132968350Seric 		/* set default NISPLUS Domain to $m */
133068350Seric 		extern char *nisplus_default_domain();
133168350Seric 
133268350Seric 		map->map_domain = newstr(nisplus_default_domain());
133368350Seric 		if (tTd(38, 2))
133468350Seric 			printf("nisplus_map_open(%s): using domain %s\n",
133568350Seric 				 map->map_file, map->map_domain);
133668350Seric 	}
133768350Seric 	if (!PARTIAL_NAME(map->map_file))
133868350Seric 		map->map_domain = newstr("");
133968350Seric 
134068350Seric 	/* check to see if this map actually exists */
134168350Seric 	if (PARTIAL_NAME(map->map_file))
134268350Seric 		sprintf(qbuf, "%s.%s", map->map_file, map->map_domain);
134368350Seric 	else
134468350Seric 		strcpy(qbuf, map->map_file);
134568350Seric 
134668350Seric 	retry_cnt = 0;
134768350Seric 	while (res == NULL || res->status != NIS_SUCCESS)
134868350Seric 	{
134968350Seric 		res = nis_lookup(qbuf, FOLLOW_LINKS);
135068350Seric 		switch (res->status)
135168350Seric 		{
135268350Seric 		  case NIS_SUCCESS:
135368350Seric 		  case NIS_TRYAGAIN:
135468350Seric 		  case NIS_RPCERROR:
135568350Seric 		  case NIS_NAMEUNREACHABLE:
135668350Seric 			break;
135768350Seric 
135868350Seric 		  default:		/* all other nisplus errors */
135968350Seric #if 0
136068350Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
136168350Seric 				syserr("421 Cannot find table %s.%s: %s",
136268350Seric 					map->map_file, map->map_domain,
136368350Seric 					nis_sperrno(res->status));
136468350Seric #endif
136568350Seric 			errno = EBADR;
136668350Seric 			return FALSE;
136768350Seric 		}
136868350Seric 		sleep(2);		/* try not to overwhelm hosed server */
136968350Seric 		if (retry_cnt++ > 4)
137068350Seric 		{
137168350Seric 			errno = EBADR;
137268350Seric 			return FALSE;
137368350Seric 		}
137468350Seric 	}
137568350Seric 
137668350Seric 	if (NIS_RES_NUMOBJ(res) != 1 ||
137768350Seric 	    (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
137868350Seric 	{
137968350Seric 		if (tTd(38, 10))
138068350Seric 			printf("nisplus_map_open: %s is not a table\n", qbuf);
138168350Seric #if 0
138268350Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
138368350Seric 			syserr("421 %s.%s: %s is not a table",
138468350Seric 				map->map_file, map->map_domain,
138568350Seric 				nis_sperrno(res->status));
138668350Seric #endif
138768350Seric 		errno = EBADR;
138868350Seric 		return FALSE;
138968350Seric 	}
139068350Seric 	/* default key column is column 0 */
139168350Seric 	if (map->map_keycolnm == NULL)
139268350Seric 		map->map_keycolnm = newstr(COL_NAME(res,0));
139368350Seric 
139468350Seric 	max_col = COL_MAX(res);
139568350Seric 
139668350Seric 	/* verify the key column exist */
139768350Seric 	for (i=0; i< max_col; i++)
139868350Seric 	{
139968350Seric 		if (!strcmp(map->map_keycolnm, COL_NAME(res,i)))
140068350Seric 			break;
140168350Seric 	}
140268350Seric 	if (i == max_col)
140368350Seric 	{
140468350Seric 		if (tTd(38, 2))
140568350Seric 			printf("nisplus_map_open(%s): can not find key column %s\n",
140668350Seric 				map->map_file, map->map_keycolnm);
140768350Seric 		errno = EBADR;
140868350Seric 		return FALSE;
140968350Seric 	}
141068350Seric 
141168350Seric 	/* default value column is the last column */
141268350Seric 	if (map->map_valcolnm == NULL)
141368350Seric 	{
141468350Seric 		map->map_valcolno = max_col - 1;
141568350Seric 		return TRUE;
141668350Seric 	}
141768350Seric 
141868350Seric 	for (i=0; i< max_col; i++)
141968350Seric 	{
142068350Seric 		if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
142168350Seric 		{
142268350Seric 			map->map_valcolno = i;
142368350Seric 			return TRUE;
142468350Seric 		}
142568350Seric 	}
142668350Seric 
142768350Seric 	if (tTd(38, 2))
142868350Seric 		printf("nisplus_map_open(%s): can not find column %s\n",
142968350Seric 			 map->map_file, map->map_keycolnm);
143068350Seric 	errno = EBADR;
143168350Seric 	return FALSE;
143267848Seric }
143367848Seric 
143467848Seric 
143567848Seric /*
143668350Seric **  NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
143767848Seric */
143867848Seric 
143968350Seric char *
144068350Seric nisplus_map_lookup(map, name, av, statp)
144167848Seric 	MAP *map;
144268350Seric 	char *name;
144368350Seric 	char **av;
144468350Seric 	int *statp;
144567848Seric {
144668350Seric 	char *vp;
144768350Seric 	auto int vsize;
144868350Seric 	int buflen;
144968350Seric 	char search_key[MAXNAME + 1];
145068350Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
145168350Seric 	nis_result *result;
145268350Seric 
145368350Seric 	if (tTd(38, 20))
145468350Seric 		printf("nisplus_map_lookup(%s, %s)\n",
145568350Seric 			map->map_mname, name);
145668350Seric 
145768350Seric 	if (!bitset(MF_OPEN, map->map_mflags))
145868350Seric 	{
145968350Seric 		if (nisplus_map_open(map, O_RDONLY))
146068350Seric 			map->map_mflags |= MF_OPEN;
146168350Seric 		else
146268350Seric 		{
146368350Seric 			*statp = EX_UNAVAILABLE;
146468350Seric 			return NULL;
146568350Seric 		}
146668350Seric 	}
146768350Seric 
146868350Seric 	buflen = strlen(name);
146968350Seric 	if (buflen > sizeof search_key - 1)
147068350Seric 		buflen = sizeof search_key - 1;
147168350Seric 	bcopy(name, search_key, buflen + 1);
147268350Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
147368350Seric 		makelower(search_key);
147468350Seric 
147568350Seric 	/* construct the query */
147668350Seric 	if (PARTIAL_NAME(map->map_file))
147768350Seric 		sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm,
147868350Seric 			search_key, map->map_file, map->map_domain);
147968350Seric 	else
148068350Seric 		sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm,
148168350Seric 			search_key, map->map_file);
148268350Seric 
148368350Seric 	if (tTd(38, 20))
148468350Seric 		printf("qbuf=%s\n", qbuf);
148568350Seric 	result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
148668350Seric 	if (result->status == NIS_SUCCESS)
148768350Seric 	{
148868350Seric 		int count;
148968350Seric 		char *str;
149068350Seric 
149168350Seric 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
149268350Seric 		{
149368350Seric 			if (LogLevel > 10)
149468350Seric 				syslog(LOG_WARNING,
149568350Seric 				  "%s:Lookup error, expected 1 entry, got (%d)",
149668350Seric 				    map->map_file, count);
149768350Seric 
149868350Seric 			/* ignore second entry */
149968350Seric 			if (tTd(38, 20))
150068350Seric 				printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
150168350Seric 					name, count);
150268350Seric 		}
150368350Seric 
150468350Seric 		vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
150568350Seric 		/* set the length of the result */
150668350Seric 		if (vp == NULL)
150768350Seric 			vp = "";
150868350Seric 		vsize = strlen(vp);
150968350Seric 		if (tTd(38, 20))
151068350Seric 			printf("nisplus_map_lookup(%s), found %s\n",
151168350Seric 				name, vp);
151268350Seric 		if (bitset(MF_MATCHONLY, map->map_mflags))
151368350Seric 			str = map_rewrite(map, name, strlen(name), NULL);
151468350Seric 		else
151568350Seric 			str = map_rewrite(map, vp, vsize, av);
151668350Seric 		nis_freeresult(result);
151768350Seric #ifdef MAP_EXIT_STAT
151868350Seric 		*statp = EX_OK;
151968350Seric #endif
152068350Seric 		return str;
152168350Seric 	}
152268350Seric 	else
152368350Seric 	{
152468350Seric #ifdef MAP_EXIT_STAT
152568350Seric 		if (result->status == NIS_NOTFOUND)
152668350Seric 			*statp = EX_NOTFOUND;
152768350Seric 		else if (result->status == NIS_TRYAGAIN)
152868350Seric 			*statp = EX_TEMPFAIL;
152968350Seric 		else
153068350Seric 		{
153168350Seric 			*statp = EX_UNAVAILABLE;
153268350Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
153368350Seric 		}
153468350Seric #else
153568350Seric 		if ((result->status != NIS_NOTFOUND) &&
153668350Seric 		    (result->status != NIS_TRYAGAIN))
153768350Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
153868350Seric #endif
153968350Seric 	}
154068350Seric 	if (tTd(38, 20))
154168350Seric 		printf("nisplus_map_lookup(%s), failed\n", name);
154268350Seric 	nis_freeresult(result);
154368350Seric 	return NULL;
154467848Seric }
154567848Seric 
154668350Seric 
154769401Seric 
154869401Seric /*
154969401Seric **  NISPLUS_GETCANONNAME -- look up canonical name in NIS+
155069401Seric */
155169401Seric 
155269401Seric bool
155369401Seric nisplus_getcanonname(name, hbsize, statp)
155469401Seric 	char *name;
155569401Seric 	int hbsize;
155669401Seric 	int *statp;
155769401Seric {
155869401Seric 	char *vp;
155969401Seric 	auto int vsize;
156069401Seric 	int buflen;
156169401Seric 	nis_result *result;
156269401Seric 	char *p;
156369401Seric 	int len;
1564*69780Seric 	char nbuf[MAXNAME + 1];
1565*69780Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
156669401Seric 
1567*69780Seric 	if (strlen(name) >= sizeof nbuf)
1568*69780Seric 	{
1569*69780Seric 		*statp = EX_UNAVAILABLE;
1570*69780Seric 		return FALSE;
1571*69780Seric 	}
1572*69780Seric 	(void) strcpy(nbuf, name);
1573*69780Seric 	shorten_hostname(nbuf);
157469401Seric 
1575*69780Seric 	p = strchr(nbuf, '.');
157669401Seric 	if (p == NULL)
157769401Seric 	{
157869401Seric 		/* single token */
1579*69780Seric 		sprintf(qbuf, "[name=%s],hosts.org_dir", nbuf);
158069401Seric 	}
158169401Seric 	else if (p[1] != '\0')
158269401Seric 	{
1583*69780Seric 		/* multi token -- take only first token in nbuf */
158469401Seric 		*p = '\0';
1585*69780Seric 		sprintf(qbuf, "[name=%s],hosts.org_dir.%s", nbuf, &p[1]);
158669401Seric 	}
158769401Seric 	else
158869401Seric 	{
158969401Seric 		*statp = EX_NOHOST;
159069401Seric 		return FALSE;
159169401Seric 	}
159269401Seric 
159369401Seric 	if (tTd(38, 20))
159469478Seric 		printf("\nnisplus_getcanoname(%s), qbuf=%s\n",
1595*69780Seric 			 name, qbuf);
159669401Seric 
1597*69780Seric 	result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH,
159869401Seric 		NULL, NULL);
159969401Seric 
160069401Seric 	if (result->status == NIS_SUCCESS)
160169401Seric 	{
160269401Seric 		int count;
160369401Seric 		char *str;
160469401Seric 		char *domain;
160569401Seric 
160669401Seric 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
160769401Seric 		{
160869401Seric #ifdef LOG
160969401Seric 			if (LogLevel > 10)
161069401Seric 				syslog(LOG_WARNING,
161169401Seric 				       "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)",
161269401Seric 				       count);
161369401Seric #endif
161469401Seric 
161569401Seric 			/* ignore second entry */
161669401Seric 			if (tTd(38, 20))
161769401Seric 				printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name);
161869401Seric 		}
161969401Seric 
162069401Seric 		if (tTd(38, 20))
162169401Seric 			printf("nisplus_getcanoname(%s), found in directory \"%s\"\n",
162269401Seric 			       name, (NIS_RES_OBJECT(result))->zo_domain);
162369401Seric 
162469401Seric 
162569401Seric 		vp = ((NIS_RES_OBJECT(result))->EN_col(0));
162669401Seric 		vsize = strlen(vp);
162769401Seric 		if (tTd(38, 20))
162869401Seric 			printf("nisplus_getcanonname(%s), found %s\n",
162969401Seric 				name, vp);
163069703Seric 		if (strchr(vp, '.') != NULL)
163169703Seric 		{
163269636Seric 			domain = "";
163369703Seric 		}
163469703Seric 		else
163569703Seric 		{
163669703Seric 			domain = macvalue('m', CurEnv);
163769703Seric 			if (domain == NULL)
163869703Seric 				domain = "";
163969703Seric 		}
164069636Seric 		if (hbsize > vsize + (int) strlen(domain) + 1)
164169401Seric 		{
164269636Seric 			if (domain[0] == '\0')
164369636Seric 				strcpy(name, vp);
164469636Seric 			else
164569636Seric 				sprintf(name, "%s.%s", vp, domain);
164669401Seric 			*statp = EX_OK;
164769401Seric 		}
164869401Seric 		else
164969401Seric 			*statp = EX_NOHOST;
165069401Seric 		nis_freeresult(result);
165169401Seric 		return TRUE;
165269401Seric 	}
165369401Seric 	else
165469401Seric 	{
165569401Seric 		if (result->status == NIS_NOTFOUND)
165669401Seric 			*statp = EX_NOHOST;
165769401Seric 		else if (result->status == NIS_TRYAGAIN)
165869401Seric 			*statp = EX_TEMPFAIL;
165969401Seric 		else
166069401Seric 			*statp = EX_UNAVAILABLE;
166169401Seric 	}
166269401Seric 	if (tTd(38, 20))
166369401Seric 		printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
166469401Seric 			name, result->status, *statp);
166569401Seric 	nis_freeresult(result);
166669401Seric 	return FALSE;
166769401Seric }
166869401Seric 
166969401Seric 
167068350Seric char *
167168350Seric nisplus_default_domain()
167268350Seric {
167368528Seric 	static char default_domain[MAXNAME + 1] = "";
167468350Seric 	char *p;
167568350Seric 
167668350Seric 	if (default_domain[0] != '\0')
167768350Seric 		return(default_domain);
167868350Seric 
167968458Seric 	p = nis_local_directory();
168068350Seric 	strcpy(default_domain, p);
168168458Seric 	return default_domain;
168268350Seric }
168368350Seric 
168468350Seric #endif /* NISPLUS */
168567848Seric /*
168668350Seric **  HESIOD Modules
168768350Seric */
168868350Seric 
168968350Seric #ifdef HESIOD
169068350Seric 
169168350Seric #include <hesiod.h>
169268350Seric 
169368350Seric char *
169468350Seric hes_map_lookup(map, name, av, statp)
169568350Seric         MAP *map;
169668350Seric         char *name;
169768350Seric         char **av;
169868350Seric         int *statp;
169968350Seric {
170068350Seric 	char **hp;
170168350Seric 
170268350Seric 	if (tTd(38, 20))
170368350Seric 		printf("hes_map_lookup(%s, %s)\n", map->map_file, name);
170468350Seric 
170569688Seric 	if (name[0] == '\\')
170669688Seric 	{
170769688Seric 		char *np;
170869688Seric 		int nl;
170969688Seric 		char nbuf[MAXNAME];
171069688Seric 
171169688Seric 		nl = strlen(name);
171269688Seric 		if (nl < sizeof nbuf - 1)
171369688Seric 			np = nbuf;
171469688Seric 		else
171569688Seric 			np = xalloc(strlen(name) + 2);
171669688Seric 		np[0] = '\\';
171769688Seric 		strcpy(&np[1], name);
171869688Seric 		hp = hes_resolve(np, map->map_file);
171969688Seric 		if (np != nbuf)
172069688Seric 			free(np);
172169688Seric 	}
172269688Seric 	else
172369688Seric 	{
172469688Seric 		hp = hes_resolve(name, map->map_file);
172569688Seric 	}
172669623Seric 	if (hp == NULL || hp[0] == NULL)
172768350Seric 		return NULL;
172868350Seric 
172969623Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
173069623Seric 		return map_rewrite(map, name, strlen(name), NULL);
173169623Seric 	else
173269623Seric 		return map_rewrite(map, hp[0], strlen(hp[0]), av);
173368350Seric }
173468350Seric 
173568350Seric #endif
173668350Seric /*
173768350Seric **  NeXT NETINFO Modules
173868350Seric */
173968350Seric 
174068350Seric #ifdef NETINFO
174168350Seric 
174268350Seric #define NETINFO_DEFAULT_DIR		"/aliases"
174368350Seric #define NETINFO_DEFAULT_PROPERTY	"members"
174468350Seric 
174568350Seric 
174668350Seric /*
174768350Seric **  NI_MAP_OPEN -- open NetInfo Aliases
174868350Seric */
174968350Seric 
175068350Seric bool
175168350Seric ni_map_open(map, mode)
175268350Seric 	MAP *map;
175368350Seric 	int mode;
175468350Seric {
175568350Seric 	char *p;
175668350Seric 
175768350Seric 	if (tTd(38, 20))
175868350Seric 		printf("ni_map_open: %s\n", map->map_file);
175968350Seric 
176068350Seric 	if (*map->map_file == '\0')
176168350Seric 		map->map_file = NETINFO_DEFAULT_DIR;
176268350Seric 
176368350Seric 	if (map->map_valcolnm == NULL)
176468350Seric 		map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
176568350Seric 
176668350Seric 	if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags))
176768350Seric 		map->map_coldelim = ',';
176868350Seric 
176968350Seric 	return TRUE;
177068350Seric }
177168350Seric 
177268350Seric 
177368350Seric /*
177468350Seric **  NI_MAP_LOOKUP -- look up a datum in NetInfo
177568350Seric */
177668350Seric 
177768350Seric char *
177868350Seric ni_map_lookup(map, name, av, statp)
177968350Seric 	MAP *map;
178068350Seric 	char *name;
178168350Seric 	char **av;
178268350Seric 	int *statp;
178368350Seric {
178468350Seric 	char *res;
178568350Seric 	char *propval;
178668350Seric 	extern char *ni_propval();
178768350Seric 
178868350Seric 	if (tTd(38, 20))
178968350Seric 		printf("ni_map_lookup(%s, %s)\n",
179068350Seric 			map->map_mname, name);
179168350Seric 
179268350Seric 	propval = ni_propval(map->map_file, map->map_keycolnm, name,
179368350Seric 			     map->map_valcolnm, map->map_coldelim);
179468350Seric 
179568350Seric 	if (propval == NULL)
179668350Seric 		return NULL;
179768350Seric 
179868350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
179968350Seric 		res = map_rewrite(map, name, strlen(name), NULL);
180068350Seric 	else
180168350Seric 		res = map_rewrite(map, propval, strlen(propval), av);
180268350Seric 	free(propval);
180368350Seric 	return res;
180468350Seric }
180568350Seric 
180668350Seric #endif
180768350Seric /*
180868350Seric **  TEXT (unindexed text file) Modules
180968350Seric **
181068350Seric **	This code donated by Sun Microsystems.
181168350Seric */
181268350Seric 
181368350Seric 
181468350Seric /*
181568350Seric **  TEXT_MAP_OPEN -- open text table
181668350Seric */
181768350Seric 
181868350Seric bool
181968350Seric text_map_open(map, mode)
182068350Seric 	MAP *map;
182168350Seric 	int mode;
182268350Seric {
182368350Seric 	struct stat sbuf;
182468350Seric 
182568350Seric 	if (tTd(38, 2))
182668350Seric 		printf("text_map_open(%s, %s, %d)\n",
182768350Seric 			map->map_mname, map->map_file, mode);
182868350Seric 
182968350Seric 	if (mode != O_RDONLY)
183068350Seric 	{
183168350Seric 		errno = ENODEV;
183268350Seric 		return FALSE;
183368350Seric 	}
183468350Seric 
183568350Seric 	if (*map->map_file == '\0')
183668350Seric 	{
183768350Seric 		if (tTd(38, 2))
183868350Seric 			printf("text_map_open: file name required\n");
183968350Seric 		return FALSE;
184068350Seric 	}
184168350Seric 
184268350Seric 	if (map->map_file[0] != '/')
184368350Seric 	{
184468350Seric 		if (tTd(38, 2))
184568350Seric 			printf("text_map_open(%s): file name must be fully qualified\n",
184668350Seric 				map->map_file);
184768350Seric 		return FALSE;
184868350Seric 	}
184968350Seric 	/* check to see if this map actually accessable */
185068350Seric 	if (access(map->map_file, R_OK) <0)
185168350Seric 		return FALSE;
185268350Seric 
185368350Seric 	/* check to see if this map actually exist */
185468350Seric 	if (stat(map->map_file, &sbuf) <0)
185568350Seric 	{
185668350Seric 		if (tTd(38, 2))
185768350Seric 			printf("text_map_open(%s): can not stat %s\n",
185868350Seric 				map->map_file, map->map_file);
185968350Seric 		return FALSE;
186068350Seric 	}
186168350Seric 
186268350Seric 	if (!S_ISREG(sbuf.st_mode))
186368350Seric 	{
186468350Seric 		if (tTd(38, 2))
186568350Seric 			printf("text_map_open(%s): %s is not a file\n",
186668350Seric 				map->map_file, map->map_file);
186768350Seric 		return FALSE;
186868350Seric 	}
186968350Seric 
187068350Seric 	if (map->map_keycolnm == NULL)
187168350Seric 		map->map_keycolno = 0;
187268350Seric 	else
187368350Seric 	{
187468350Seric 		if (!isdigit(*map->map_keycolnm))
187568350Seric 		{
187668350Seric 			if (tTd(38, 2))
187768350Seric 				printf("text_map_open(%s): -k should specify a number, not %s\n",
187868350Seric 					map->map_file, map->map_keycolnm);
187968350Seric 			return FALSE;
188068350Seric 		}
188168350Seric 		map->map_keycolno = atoi(map->map_keycolnm);
188268350Seric 	}
188368350Seric 
188468350Seric 	if (map->map_valcolnm == NULL)
188568350Seric 		map->map_valcolno = 0;
188668350Seric 	else
188768350Seric 	{
188868350Seric 		if (!isdigit(*map->map_valcolnm))
188968350Seric 		{
189068350Seric 			if (tTd(38, 2))
189168350Seric 				printf("text_map_open(%s): -v should specify a number, not %s\n",
189268350Seric 					map->map_file, map->map_valcolnm);
189368350Seric 			return FALSE;
189468350Seric 		}
189568350Seric 		map->map_valcolno = atoi(map->map_valcolnm);
189668350Seric 	}
189768350Seric 
189868350Seric 	if (tTd(38, 2))
189968350Seric 	{
190068520Seric 		printf("text_map_open(%s): delimiter = ",
190168520Seric 			map->map_file);
190268520Seric 		if (map->map_coldelim == '\0')
190368520Seric 			printf("(white space)\n");
190468520Seric 		else
190568520Seric 			printf("%c\n", map->map_coldelim);
190668350Seric 	}
190768350Seric 
190868350Seric 	return TRUE;
190968350Seric }
191068350Seric 
191168350Seric 
191268350Seric /*
191368350Seric **  TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
191468350Seric */
191568350Seric 
191668350Seric char *
191768350Seric text_map_lookup(map, name, av, statp)
191868350Seric 	MAP *map;
191968350Seric 	char *name;
192068350Seric 	char **av;
192168350Seric 	int *statp;
192268350Seric {
192368350Seric 	char *vp;
192468350Seric 	auto int vsize;
192568350Seric 	int buflen;
192668350Seric 	char search_key[MAXNAME + 1];
192768350Seric 	char linebuf[MAXLINE];
192868350Seric 	FILE *f;
192968528Seric 	char buf[MAXNAME + 1];
193068350Seric 	char delim;
193168350Seric 	int key_idx;
193268350Seric 	bool found_it;
193368350Seric 	extern char *get_column();
193468350Seric 
193568350Seric 
193668350Seric 	found_it = FALSE;
193768350Seric 	if (tTd(38, 20))
193868350Seric 		printf("text_map_lookup(%s)\n", name);
193968350Seric 
194068350Seric 	buflen = strlen(name);
194168350Seric 	if (buflen > sizeof search_key - 1)
194268350Seric 		buflen = sizeof search_key - 1;
194368350Seric 	bcopy(name, search_key, buflen + 1);
194468350Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
194568350Seric 		makelower(search_key);
194668350Seric 
194768350Seric 	f = fopen(map->map_file, "r");
194868350Seric 	if (f == NULL)
194968350Seric 	{
195068350Seric 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
195168350Seric 		*statp = EX_UNAVAILABLE;
195268350Seric 		return NULL;
195368350Seric 	}
195468350Seric 	key_idx = map->map_keycolno;
195568350Seric 	delim = map->map_coldelim;
195668350Seric 	while (fgets(linebuf, MAXLINE, f))
195768350Seric 	{
195868350Seric 		char *lf;
195968350Seric 		if (linebuf[0] == '#')
196068350Seric 			continue; /* skip comment line */
196168350Seric 		if (lf = strchr(linebuf, '\n'))
196268350Seric 			*lf = '\0';
196368350Seric 		if (!strcasecmp(search_key,
196468350Seric 				get_column(linebuf, key_idx, delim, buf)))
196568350Seric 		{
196668350Seric 			found_it = TRUE;
196768350Seric 			break;
196868350Seric 		}
196968350Seric 	}
197068350Seric 	fclose(f);
197168350Seric 	if (!found_it)
197268350Seric 	{
197368350Seric #ifdef MAP_EXIT_STAT
197468350Seric 		*statp = EX_NOTFOUND;
197568350Seric #endif
197668350Seric 		return(NULL);
197768350Seric 	}
197868350Seric 	vp = get_column(linebuf, map->map_valcolno, delim, buf);
197968350Seric 	vsize = strlen(vp);
198068350Seric #ifdef MAP_EXIT_STAT
198168350Seric 	*statp = EX_OK;
198268350Seric #endif
198368350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
198468350Seric 		return map_rewrite(map, name, strlen(name), NULL);
198568350Seric 	else
198668350Seric 		return map_rewrite(map, vp, vsize, av);
198768350Seric }
198869401Seric 
198969401Seric 
199069401Seric /*
199169401Seric **  TEXT_GETCANONNAME -- look up canonical name in hosts file
199269401Seric */
199369401Seric 
199469401Seric bool
199569401Seric text_getcanonname(name, hbsize, statp)
199669401Seric 	char *name;
199769401Seric 	int hbsize;
199869401Seric 	int *statp;
199969401Seric {
200069401Seric 	int key_idx;
200169401Seric 	char *cname;
200269401Seric 	bool found;
200369401Seric 	FILE *f;
200469401Seric 	char linebuf[MAXLINE];
200569401Seric 	char cbuf[MAXNAME + 1];
2006*69780Seric 	char fbuf[MAXNAME + 1];
2007*69780Seric 	char nbuf[MAXNAME + 1];
200869401Seric 	extern char *get_column();
200969401Seric 
2010*69780Seric 	if (strlen(name) >= sizeof nbuf)
2011*69780Seric 	{
2012*69780Seric 		*statp = EX_UNAVAILABLE;
2013*69780Seric 		return FALSE;
2014*69780Seric 	}
2015*69780Seric 	(void) strcpy(nbuf, name);
2016*69780Seric 	shorten_hostname(nbuf);
201769401Seric 
201869401Seric 	/* we only accept single token search key */
2019*69780Seric 	if (strchr(nbuf, '.') != NULL)
202069401Seric 	{
202169401Seric 		*statp = EX_NOHOST;
202269401Seric 		return FALSE;
202369401Seric 	}
202469401Seric 
202569401Seric 	found = FALSE;
202669401Seric 
202769401Seric 	f = fopen(HostsFile, "r");
202869401Seric 	if (f == NULL)
202969401Seric 	{
203069401Seric #ifdef MAP_EXIT_STAT
203169401Seric 		*statp = EX_UNAVAILABLE;
203269401Seric #endif
203369401Seric 		return FALSE;
203469401Seric 	}
203569401Seric 	while (!found && fgets(linebuf, MAXLINE, f) != NULL)
203669401Seric 	{
203769401Seric 		char *p;
203869401Seric 
203969401Seric 		if (linebuf[0] == '#')
204069401Seric 			continue;
204169401Seric 		if ((p = strchr(linebuf, '\n')) != NULL)
204269401Seric 			*p = '\0';
204369663Seric 		cname = get_column(linebuf, 1, '\0', cbuf);
2044*69780Seric 		if (cname != NULL && strcasecmp(nbuf,  cname) == 0)
204569401Seric 		{
204669401Seric 			found = TRUE;
204769401Seric 			break;
204869401Seric 		}
204969401Seric 
205069401Seric 		key_idx = 2;
2051*69780Seric 		while ((p = get_column(linebuf, key_idx, '\0', fbuf)) != NULL)
205269401Seric 		{
2053*69780Seric 			if (strcasecmp(nbuf, p) == 0)
205469401Seric 			{
205569401Seric 				found = TRUE;
205669401Seric 				break;
205769401Seric 			}
205869401Seric 			key_idx++;
205969401Seric 		}
206069401Seric 	}
206169401Seric 	fclose(f);
206269401Seric 	if (!found)
206369401Seric 	{
206469401Seric 		*statp = EX_NOHOST;
206569401Seric 		return FALSE;
206669401Seric 	}
206769401Seric 
206869401Seric 	if (hbsize >= strlen(cname))
206969401Seric 	{
207069401Seric 		strcpy(name, cname);
207169401Seric 		*statp = EX_OK;
207269401Seric 		return TRUE;
207369401Seric 	}
207469401Seric 	*statp = EX_UNAVAILABLE;
207569401Seric 	return FALSE;
207669401Seric }
207768350Seric /*
207860089Seric **  STAB (Symbol Table) Modules
207960089Seric */
208060089Seric 
208160089Seric 
208260089Seric /*
208360207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
208460089Seric */
208560089Seric 
208660089Seric char *
208761707Seric stab_map_lookup(map, name, av, pstat)
208860089Seric 	register MAP *map;
208960089Seric 	char *name;
209061707Seric 	char **av;
209161707Seric 	int *pstat;
209260089Seric {
209360089Seric 	register STAB *s;
209460089Seric 
209560537Seric 	if (tTd(38, 20))
209668350Seric 		printf("stab_lookup(%s, %s)\n",
209768350Seric 			map->map_mname, name);
209860089Seric 
209960089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
210060089Seric 	if (s != NULL)
210160089Seric 		return (s->s_alias);
210260089Seric 	return (NULL);
210360089Seric }
210460089Seric 
210560089Seric 
210660089Seric /*
210760207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
210860089Seric */
210960089Seric 
211060089Seric void
211160089Seric stab_map_store(map, lhs, rhs)
211260089Seric 	register MAP *map;
211360089Seric 	char *lhs;
211460089Seric 	char *rhs;
211560089Seric {
211660089Seric 	register STAB *s;
211760089Seric 
211860089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
211960089Seric 	s->s_alias = newstr(rhs);
212060089Seric }
212160089Seric 
212260089Seric 
212360089Seric /*
212460207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
212560207Seric **
212660207Seric **	This is a wierd case -- it is only intended as a fallback for
212760207Seric **	aliases.  For this reason, opens for write (only during a
212860207Seric **	"newaliases") always fails, and opens for read open the
212960207Seric **	actual underlying text file instead of the database.
213060089Seric */
213160089Seric 
213260089Seric bool
213360089Seric stab_map_open(map, mode)
213460089Seric 	register MAP *map;
213560089Seric 	int mode;
213660089Seric {
213763835Seric 	FILE *af;
213864284Seric 	struct stat st;
213963835Seric 
214060537Seric 	if (tTd(38, 2))
214168350Seric 		printf("stab_map_open(%s, %s)\n",
214268350Seric 			map->map_mname, map->map_file);
214360089Seric 
214460089Seric 	if (mode != O_RDONLY)
214560207Seric 	{
214660207Seric 		errno = ENODEV;
214760089Seric 		return FALSE;
214860207Seric 	}
214960089Seric 
215063835Seric 	af = fopen(map->map_file, "r");
215163835Seric 	if (af == NULL)
215263835Seric 		return FALSE;
215368350Seric 	readaliases(map, af, FALSE, FALSE);
215464284Seric 
215564284Seric 	if (fstat(fileno(af), &st) >= 0)
215664284Seric 		map->map_mtime = st.st_mtime;
215763835Seric 	fclose(af);
215863835Seric 
215960089Seric 	return TRUE;
216060089Seric }
216160089Seric /*
216260089Seric **  Implicit Modules
216356822Seric **
216460089Seric **	Tries several types.  For back compatibility of aliases.
216556822Seric */
216656822Seric 
216760089Seric 
216860089Seric /*
216960207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
217060089Seric */
217160089Seric 
217260089Seric char *
217360089Seric impl_map_lookup(map, name, av, pstat)
217460089Seric 	MAP *map;
217560089Seric 	char *name;
217656822Seric 	char **av;
217760089Seric 	int *pstat;
217856822Seric {
217960537Seric 	if (tTd(38, 20))
218068350Seric 		printf("impl_map_lookup(%s, %s)\n",
218168350Seric 			map->map_mname, name);
218256822Seric 
218360089Seric #ifdef NEWDB
218460207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
218560089Seric 		return db_map_lookup(map, name, av, pstat);
218660089Seric #endif
218760089Seric #ifdef NDBM
218860207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
218960089Seric 		return ndbm_map_lookup(map, name, av, pstat);
219060089Seric #endif
219160089Seric 	return stab_map_lookup(map, name, av, pstat);
219260089Seric }
219360089Seric 
219460089Seric /*
219560207Seric **  IMPL_MAP_STORE -- store in open databases
219660089Seric */
219760089Seric 
219860089Seric void
219960089Seric impl_map_store(map, lhs, rhs)
220060089Seric 	MAP *map;
220160089Seric 	char *lhs;
220260089Seric 	char *rhs;
220360089Seric {
220460089Seric #ifdef NEWDB
220560207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
220660089Seric 		db_map_store(map, lhs, rhs);
220760089Seric #endif
220860089Seric #ifdef NDBM
220960207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
221060089Seric 		ndbm_map_store(map, lhs, rhs);
221160089Seric #endif
221260089Seric 	stab_map_store(map, lhs, rhs);
221360089Seric }
221460089Seric 
221560089Seric /*
221660089Seric **  IMPL_MAP_OPEN -- implicit database open
221760089Seric */
221860089Seric 
221960089Seric bool
222060089Seric impl_map_open(map, mode)
222160089Seric 	MAP *map;
222260089Seric 	int mode;
222360089Seric {
222460089Seric 	struct stat stb;
222560089Seric 
222660537Seric 	if (tTd(38, 2))
222768350Seric 		printf("impl_map_open(%s, %s, %d)\n",
222868350Seric 			map->map_mname, map->map_file, mode);
222960089Seric 
223060089Seric 	if (stat(map->map_file, &stb) < 0)
223156822Seric 	{
223260089Seric 		/* no alias file at all */
223364718Seric 		if (tTd(38, 3))
223464718Seric 			printf("no map file\n");
223560089Seric 		return FALSE;
223656822Seric 	}
223756822Seric 
223860089Seric #ifdef NEWDB
223960207Seric 	map->map_mflags |= MF_IMPL_HASH;
224060089Seric 	if (hash_map_open(map, mode))
224156822Seric 	{
224264250Seric #if defined(NDBM) && defined(NIS)
224369651Seric 		if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
224460207Seric #endif
224560207Seric 			return TRUE;
224660089Seric 	}
224760207Seric 	else
224860207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
224960089Seric #endif
225060089Seric #ifdef NDBM
225160207Seric 	map->map_mflags |= MF_IMPL_NDBM;
225260089Seric 	if (ndbm_map_open(map, mode))
225360089Seric 	{
225460089Seric 		return TRUE;
225560089Seric 	}
225660207Seric 	else
225760207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
225860089Seric #endif
225956822Seric 
226064650Seric #if defined(NEWDB) || defined(NDBM)
226160089Seric 	if (Verbose)
226260089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
226364964Seric #else
226464964Seric 	if (mode != O_RDONLY)
226564964Seric 		usrerr("Cannot rebuild aliases: no database format defined");
226660207Seric #endif
226760089Seric 
226860207Seric 	return stab_map_open(map, mode);
226956822Seric }
227060089Seric 
227160207Seric 
227260089Seric /*
227360207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
227460089Seric */
227560089Seric 
227660089Seric void
227760207Seric impl_map_close(map)
227860089Seric 	MAP *map;
227960089Seric {
228068350Seric 	if (tTd(38, 20))
228168350Seric 		printf("impl_map_close(%s, %s, %x)\n",
228268350Seric 			map->map_mname, map->map_file, map->map_mflags);
228360089Seric #ifdef NEWDB
228460207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
228560089Seric 	{
228660207Seric 		db_map_close(map);
228760207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
228860089Seric 	}
228960089Seric #endif
229060089Seric 
229160089Seric #ifdef NDBM
229260207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
229360089Seric 	{
229460207Seric 		ndbm_map_close(map);
229560207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
229660089Seric 	}
229760089Seric #endif
229860089Seric }
229960207Seric /*
230068350Seric **  User map class.
230168350Seric **
230268350Seric **	Provides access to the system password file.
230368350Seric */
230468350Seric 
230568350Seric /*
230668350Seric **  USER_MAP_OPEN -- open user map
230768350Seric **
230868350Seric **	Really just binds field names to field numbers.
230968350Seric */
231068350Seric 
231168350Seric bool
231268350Seric user_map_open(map, mode)
231368350Seric 	MAP *map;
231468350Seric 	int mode;
231568350Seric {
231668350Seric 	if (tTd(38, 2))
231768350Seric 		printf("user_map_open(%s)\n", map->map_mname);
231868350Seric 
231968350Seric 	if (mode != O_RDONLY)
232068350Seric 	{
232168350Seric 		/* issue a pseudo-error message */
232268350Seric #ifdef ENOSYS
232368350Seric 		errno = ENOSYS;
232468350Seric #else
232568350Seric # ifdef EFTYPE
232668350Seric 		errno = EFTYPE;
232768350Seric # else
232868350Seric 		errno = ENXIO;
232968350Seric # endif
233068350Seric #endif
233168350Seric 		return FALSE;
233268350Seric 	}
233368350Seric 	if (map->map_valcolnm == NULL)
233468350Seric 		/* nothing */ ;
233568350Seric 	else if (strcasecmp(map->map_valcolnm, "name") == 0)
233668350Seric 		map->map_valcolno = 1;
233768350Seric 	else if (strcasecmp(map->map_valcolnm, "passwd") == 0)
233868350Seric 		map->map_valcolno = 2;
233968350Seric 	else if (strcasecmp(map->map_valcolnm, "uid") == 0)
234068350Seric 		map->map_valcolno = 3;
234168350Seric 	else if (strcasecmp(map->map_valcolnm, "gid") == 0)
234268350Seric 		map->map_valcolno = 4;
234368350Seric 	else if (strcasecmp(map->map_valcolnm, "gecos") == 0)
234468350Seric 		map->map_valcolno = 5;
234568350Seric 	else if (strcasecmp(map->map_valcolnm, "dir") == 0)
234668350Seric 		map->map_valcolno = 6;
234768350Seric 	else if (strcasecmp(map->map_valcolnm, "shell") == 0)
234868350Seric 		map->map_valcolno = 7;
234968350Seric 	else
235068350Seric 	{
235168350Seric 		syserr("User map %s: unknown column name %s",
235268350Seric 			map->map_mname, map->map_valcolnm);
235368350Seric 		return FALSE;
235468350Seric 	}
235568350Seric 	return TRUE;
235668350Seric }
235768350Seric 
235868350Seric 
235968350Seric /*
236068350Seric **  USER_MAP_LOOKUP -- look up a user in the passwd file.
236168350Seric */
236268350Seric 
236368350Seric char *
236468350Seric user_map_lookup(map, key, av, statp)
236568350Seric 	MAP *map;
236668350Seric 	char *key;
236768350Seric 	char **av;
236868350Seric 	int *statp;
236968350Seric {
237068350Seric 	struct passwd *pw;
237168350Seric 
237268350Seric 	if (tTd(38, 20))
237368350Seric 		printf("user_map_lookup(%s, %s)\n",
237468350Seric 			map->map_mname, key);
237568350Seric 
237668693Seric 	pw = sm_getpwnam(key);
237768350Seric 	if (pw == NULL)
237868350Seric 		return NULL;
237968350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
238068350Seric 		return map_rewrite(map, key, strlen(key), NULL);
238168350Seric 	else
238268350Seric 	{
238368433Seric 		char *rwval = NULL;
238468350Seric 		char buf[30];
238568350Seric 
238668350Seric 		switch (map->map_valcolno)
238768350Seric 		{
238868350Seric 		  case 0:
238968350Seric 		  case 1:
239068350Seric 			rwval = pw->pw_name;
239168350Seric 			break;
239268350Seric 
239368350Seric 		  case 2:
239468350Seric 			rwval = pw->pw_passwd;
239568350Seric 			break;
239668350Seric 
239768350Seric 		  case 3:
239868350Seric 			sprintf(buf, "%d", pw->pw_uid);
239968350Seric 			rwval = buf;
240068350Seric 			break;
240168350Seric 
240268350Seric 		  case 4:
240368350Seric 			sprintf(buf, "%d", pw->pw_gid);
240468350Seric 			rwval = buf;
240568350Seric 			break;
240668350Seric 
240768350Seric 		  case 5:
240868350Seric 			rwval = pw->pw_gecos;
240968350Seric 			break;
241068350Seric 
241168350Seric 		  case 6:
241268350Seric 			rwval = pw->pw_dir;
241368350Seric 			break;
241468350Seric 
241568350Seric 		  case 7:
241668350Seric 			rwval = pw->pw_shell;
241768350Seric 			break;
241868350Seric 		}
241968350Seric 		return map_rewrite(map, rwval, strlen(rwval), av);
242068350Seric 	}
242168350Seric }
242268350Seric /*
242368350Seric **  BESTMX -- find the best MX for a name
242468350Seric **
242568350Seric **	This is really a hack, but I don't see any obvious way
242668350Seric **	to generalize it at the moment.
242768350Seric */
242868350Seric 
242968350Seric #if NAMED_BIND
243068350Seric 
243168350Seric char *
243268350Seric bestmx_map_lookup(map, name, av, statp)
243368350Seric 	MAP *map;
243468350Seric 	char *name;
243568350Seric 	char **av;
243668350Seric 	int *statp;
243768350Seric {
243868350Seric         int nmx;
243968350Seric         auto int rcode;
244068350Seric         char *mxhosts[MAXMXHOSTS + 1];
244168350Seric 
244268350Seric 	nmx = getmxrr(name, mxhosts, FALSE, &rcode);
244368350Seric 	if (nmx <= 0)
244468350Seric 		return NULL;
244568350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
244668350Seric 		return map_rewrite(map, name, strlen(name), NULL);
244768350Seric 	else
244868350Seric 		return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av);
244968350Seric }
245068350Seric 
245168350Seric #endif
245268350Seric /*
245369453Seric **  Program map type.
245469453Seric **
245569453Seric **	This provides access to arbitrary programs.  It should be used
245669453Seric **	only very sparingly, since there is no way to bound the cost
245769453Seric **	of invoking an arbitrary program.
245869453Seric */
245969453Seric 
246069453Seric char *
246169453Seric prog_map_lookup(map, name, av, statp)
246269453Seric 	MAP *map;
246369453Seric 	char *name;
246469453Seric 	char **av;
246569453Seric 	int *statp;
246669453Seric {
246769453Seric 	int i;
246869453Seric 	register char *p;
246969453Seric 	int fd;
247069453Seric 	auto pid_t pid;
247169453Seric 	char *argv[MAXPV + 1];
247269453Seric 	char buf[MAXLINE];
247369453Seric 
247469453Seric 	if (tTd(38, 20))
247569453Seric 		printf("prog_map_lookup(%s, %s) %s\n",
247669453Seric 			map->map_mname, name, map->map_file);
247769453Seric 
247869453Seric 	i = 0;
247969453Seric 	argv[i++] = map->map_file;
248069453Seric 	strcpy(buf, map->map_rebuild);
248169453Seric 	for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t"))
248269453Seric 	{
248369453Seric 		if (i >= MAXPV - 1)
248469453Seric 			break;
248569453Seric 		argv[i++] = p;
248669453Seric 	}
248769453Seric 	argv[i++] = name;
248869453Seric 	argv[i] = NULL;
248969453Seric 	pid = prog_open(argv, &fd, CurEnv);
249069453Seric 	if (pid < 0)
249169453Seric 	{
249269453Seric 		if (tTd(38, 9))
249369453Seric 			printf("prog_map_lookup(%s) failed (%s) -- closing",
249469453Seric 				map->map_mname, errstring(errno));
249569453Seric 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
249669453Seric 		return NULL;
249769453Seric 	}
249869453Seric 	i = read(fd, buf, sizeof buf - 1);
249969453Seric 	if (i <= 0 && tTd(38, 2))
250069453Seric 		printf("prog_map_lookup(%s): read error %s\n",
250169562Seric 			map->map_mname, errstring(errno));
250269453Seric 	if (i > 0)
250369453Seric 	{
250469453Seric 		char *rval;
250569453Seric 
250669453Seric 		buf[i] = '\0';
250769453Seric 		p = strchr(buf, '\n');
250869453Seric 		if (p != NULL)
250969453Seric 			*p = '\0';
251069453Seric 
251169453Seric 		/* collect the return value */
251269453Seric 		if (bitset(MF_MATCHONLY, map->map_mflags))
251369453Seric 			rval = map_rewrite(map, name, strlen(name), NULL);
251469453Seric 		else
251569453Seric 			rval = map_rewrite(map, buf, strlen(buf), NULL);
251669453Seric 
251769453Seric 		/* now flush any additional output */
251869453Seric 		while ((i = read(fd, buf, sizeof buf)) > 0)
251969453Seric 			continue;
252069453Seric 		close(fd);
252169453Seric 
252269453Seric 		/* and wait for the process to terminate */
252369453Seric 		*statp = waitfor(pid);
252469453Seric 
252569453Seric 		return rval;
252669453Seric 	}
252769453Seric 
252869453Seric 	close(fd);
252969453Seric 	*statp = waitfor(pid);
253069453Seric 	return NULL;
253169453Seric }
253269453Seric /*
253368350Seric **  Sequenced map type.
253468350Seric **
253568350Seric **	Tries each map in order until something matches, much like
253668350Seric **	implicit.  Stores go to the first map in the list that can
253768350Seric **	support storing.
253868350Seric **
253968350Seric **	This is slightly unusual in that there are two interfaces.
254068350Seric **	The "sequence" interface lets you stack maps arbitrarily.
254168350Seric **	The "switch" interface builds a sequence map by looking
254268350Seric **	at a system-dependent configuration file such as
254368350Seric **	/etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
254468350Seric **
254568350Seric **	We don't need an explicit open, since all maps are
254668350Seric **	opened during startup, including underlying maps.
254768350Seric */
254868350Seric 
254968350Seric /*
255068350Seric **  SEQ_MAP_PARSE -- Sequenced map parsing
255168350Seric */
255268350Seric 
255368350Seric bool
255468350Seric seq_map_parse(map, ap)
255568350Seric 	MAP *map;
255668350Seric 	char *ap;
255768350Seric {
255868350Seric 	int maxmap;
255968350Seric 
256068350Seric 	if (tTd(38, 2))
256168350Seric 		printf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
256268350Seric 	maxmap = 0;
256368350Seric 	while (*ap != '\0')
256468350Seric 	{
256568350Seric 		register char *p;
256668350Seric 		STAB *s;
256768350Seric 
256868350Seric 		/* find beginning of map name */
256968350Seric 		while (isascii(*ap) && isspace(*ap))
257068350Seric 			ap++;
257168350Seric 		for (p = ap; isascii(*p) && isalnum(*p); p++)
257268350Seric 			continue;
257368350Seric 		if (*p != '\0')
257468350Seric 			*p++ = '\0';
257568350Seric 		while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
257668350Seric 			p++;
257768350Seric 		if (*ap == '\0')
257868350Seric 		{
257968350Seric 			ap = p;
258068350Seric 			continue;
258168350Seric 		}
258268350Seric 		s = stab(ap, ST_MAP, ST_FIND);
258368350Seric 		if (s == NULL)
258468350Seric 		{
258568350Seric 			syserr("Sequence map %s: unknown member map %s",
258668350Seric 				map->map_mname, ap);
258768350Seric 		}
258868350Seric 		else if (maxmap == MAXMAPSTACK)
258968350Seric 		{
259068350Seric 			syserr("Sequence map %s: too many member maps (%d max)",
259168350Seric 				map->map_mname, MAXMAPSTACK);
259268350Seric 			maxmap++;
259368350Seric 		}
259468350Seric 		else if (maxmap < MAXMAPSTACK)
259568350Seric 		{
259668350Seric 			map->map_stack[maxmap++] = &s->s_map;
259768350Seric 		}
259868350Seric 		ap = p;
259968350Seric 	}
260068350Seric 	return TRUE;
260168350Seric }
260268350Seric 
260368350Seric 
260468350Seric /*
260568350Seric **  SWITCH_MAP_OPEN -- open a switched map
260668350Seric **
260768350Seric **	This looks at the system-dependent configuration and builds
260868350Seric **	a sequence map that does the same thing.
260968350Seric **
261068350Seric **	Every system must define a switch_map_find routine in conf.c
261168350Seric **	that will return the list of service types associated with a
261268350Seric **	given service class.
261368350Seric */
261468350Seric 
261568350Seric bool
261668350Seric switch_map_open(map, mode)
261768350Seric 	MAP *map;
261868350Seric 	int mode;
261968350Seric {
262068350Seric 	int mapno;
262168350Seric 	int nmaps;
262268350Seric 	char *maptype[MAXMAPSTACK];
262368350Seric 
262468350Seric 	if (tTd(38, 2))
262568350Seric 		printf("switch_map_open(%s, %s, %d)\n",
262668350Seric 			map->map_mname, map->map_file, mode);
262768350Seric 
262868350Seric 	nmaps = switch_map_find(map->map_file, maptype, map->map_return);
262968350Seric 	if (tTd(38, 19))
263068350Seric 	{
263168350Seric 		printf("\tswitch_map_find => %d\n", nmaps);
263268350Seric 		for (mapno = 0; mapno < nmaps; mapno++)
263368350Seric 			printf("\t\t%s\n", maptype[mapno]);
263468350Seric 	}
263568350Seric 	if (nmaps <= 0 || nmaps > MAXMAPSTACK)
263668350Seric 		return FALSE;
263768350Seric 
263868350Seric 	for (mapno = 0; mapno < nmaps; mapno++)
263968350Seric 	{
264068350Seric 		register STAB *s;
264168350Seric 		char nbuf[MAXNAME + 1];
264268350Seric 
264368350Seric 		if (maptype[mapno] == NULL)
264468350Seric 			continue;
264568350Seric 		(void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]);
264668350Seric 		s = stab(nbuf, ST_MAP, ST_FIND);
264768350Seric 		if (s == NULL)
264868350Seric 		{
264968350Seric 			syserr("Switch map %s: unknown member map %s",
265068350Seric 				map->map_mname, nbuf);
265168350Seric 		}
265268350Seric 		else
265368350Seric 		{
265468350Seric 			map->map_stack[mapno] = &s->s_map;
265568350Seric 			if (tTd(38, 4))
265668350Seric 				printf("\tmap_stack[%d] = %s:%s\n",
265768350Seric 					mapno, s->s_map.map_class->map_cname,
265868350Seric 					nbuf);
265968350Seric 		}
266068350Seric 	}
266168350Seric 	return TRUE;
266268350Seric }
266368350Seric 
266468350Seric 
266568350Seric /*
266668350Seric **  SEQ_MAP_CLOSE -- close all underlying maps
266768350Seric */
266868350Seric 
266969748Seric void
267068350Seric seq_map_close(map)
267168350Seric 	MAP *map;
267268350Seric {
267368350Seric 	int mapno;
267468350Seric 
267568350Seric 	if (tTd(38, 20))
267668350Seric 		printf("seq_map_close(%s)\n", map->map_mname);
267768350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
267868350Seric 	{
267968350Seric 		MAP *mm = map->map_stack[mapno];
268068350Seric 
268168350Seric 		if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
268268350Seric 			continue;
268368350Seric 		mm->map_class->map_close(mm);
268468798Seric 		mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
268568350Seric 	}
268668350Seric }
268768350Seric 
268868350Seric 
268968350Seric /*
269068350Seric **  SEQ_MAP_LOOKUP -- sequenced map lookup
269168350Seric */
269268350Seric 
269368350Seric char *
269468350Seric seq_map_lookup(map, key, args, pstat)
269568350Seric 	MAP *map;
269668350Seric 	char *key;
269768350Seric 	char **args;
269868350Seric 	int *pstat;
269968350Seric {
270068350Seric 	int mapno;
270168350Seric 	int mapbit = 0x01;
270268350Seric 
270368350Seric 	if (tTd(38, 20))
270468350Seric 		printf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
270568350Seric 
270668350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
270768350Seric 	{
270868350Seric 		MAP *mm = map->map_stack[mapno];
270968350Seric 		int stat = 0;
271068350Seric 		char *rv;
271168350Seric 
271268350Seric 		if (mm == NULL)
271368350Seric 			continue;
271468350Seric 		if (!bitset(MF_OPEN, mm->map_mflags))
271568350Seric 		{
271668350Seric 			if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
271768350Seric 			{
271868350Seric 				*pstat = EX_UNAVAILABLE;
271968350Seric 				return NULL;
272068350Seric 			}
272168350Seric 			continue;
272268350Seric 		}
272368350Seric 		rv = mm->map_class->map_lookup(mm, key, args, &stat);
272468350Seric 		if (rv != NULL)
272568350Seric 			return rv;
272668350Seric 		if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND]))
272768350Seric 			return NULL;
272868350Seric 		if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN]))
272968350Seric 		{
273068350Seric 			*pstat = stat;
273168350Seric 			return NULL;
273268350Seric 		}
273368350Seric 	}
273468350Seric 	return NULL;
273568350Seric }
273668350Seric 
273768350Seric 
273868350Seric /*
273968350Seric **  SEQ_MAP_STORE -- sequenced map store
274068350Seric */
274168350Seric 
274268350Seric void
274368350Seric seq_map_store(map, key, val)
274468350Seric 	MAP *map;
274568350Seric 	char *key;
274668350Seric 	char *val;
274768350Seric {
274868350Seric 	int mapno;
274968350Seric 
275068350Seric 	if (tTd(38, 12))
275168350Seric 		printf("seq_map_store(%s, %s, %s)\n",
275268350Seric 			map->map_mname, key, val);
275368350Seric 
275468350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
275568350Seric 	{
275668350Seric 		MAP *mm = map->map_stack[mapno];
275768350Seric 
275868350Seric 		if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
275968350Seric 			continue;
276068350Seric 
276168350Seric 		mm->map_class->map_store(mm, key, val);
276268350Seric 		return;
276368350Seric 	}
276468350Seric 	syserr("seq_map_store(%s, %s, %s): no writable map",
276568350Seric 		map->map_mname, key, val);
276668350Seric }
276768350Seric /*
276869401Seric **  GETCANONNAME -- look up name using service switch
276969401Seric **
277069401Seric **	Parameters:
277169401Seric **		host -- the host name to look up.
277269401Seric **		hbsize -- the size of the host buffer.
277369401Seric **		trymx -- if set, try MX records.
277469401Seric **
277569401Seric **	Returns:
277669401Seric **		TRUE -- if the host was found.
277769401Seric **		FALSE -- otherwise.
277869401Seric */
277969401Seric 
278069401Seric bool
278169401Seric getcanonname(host, hbsize, trymx)
278269401Seric 	char *host;
278369401Seric 	int hbsize;
278469401Seric 	bool trymx;
278569401Seric {
278669401Seric 	int nmaps;
278769401Seric 	int mapno;
278869401Seric 	bool found = FALSE;
278969401Seric 	auto int stat;
279069401Seric 	char *maptype[MAXMAPSTACK];
279169401Seric 	short mapreturn[MAXMAPACTIONS];
279269401Seric 	extern int h_errno;
279369401Seric 
279469401Seric 	nmaps = switch_map_find("hosts", maptype, mapreturn);
279569401Seric 	for (mapno = 0; mapno < nmaps; mapno++)
279669401Seric 	{
279769401Seric 		int i;
279869401Seric 
279969401Seric 		if (tTd(38, 20))
280069401Seric 			printf("getcanonname(%s), trying %s\n",
280169401Seric 				host, maptype[mapno]);
280269401Seric 		if (strcmp("files", maptype[mapno]) == 0)
280369401Seric 			found = text_getcanonname(host, hbsize, &stat);
280469401Seric #ifdef NIS
280569401Seric 		else if (strcmp("nis", maptype[mapno]) == 0)
280669401Seric 			found = nis_getcanonname(host, hbsize, &stat);
280769401Seric #endif
280869401Seric #ifdef NISPLUS
280969401Seric 		else if (strcmp("nisplus", maptype[mapno]) == 0)
281069401Seric 			found = nisplus_getcanonname(host, hbsize, &stat);
281169401Seric #endif
281269401Seric #if NAMED_BIND
281369401Seric 		else if (strcmp("dns", maptype[mapno]) == 0)
281469401Seric 			found = dns_getcanonname(host, hbsize, trymx, &stat);
281569401Seric #endif
281669401Seric 		else
281769401Seric 		{
281869401Seric 			found = FALSE;
281969401Seric 			stat = EX_UNAVAILABLE;
282069401Seric 		}
282169401Seric 		if (found)
282269401Seric 			break;
282369401Seric 
282469401Seric 		/* see if we should continue */
282569401Seric 		if (stat == EX_TEMPFAIL)
282669401Seric 			i = MA_TRYAGAIN;
282769401Seric 		else if (stat == EX_NOHOST)
282869401Seric 			i = MA_NOTFOUND;
282969401Seric 		else
283069401Seric 			i = MA_UNAVAIL;
283169401Seric 		if (bitset(1 << mapno, mapreturn[i]))
283269401Seric 			break;
283369401Seric 	}
283469401Seric 
283569401Seric 	if (found)
283669401Seric 	{
283769401Seric 		char *d;
283869401Seric 
283969401Seric 		if (tTd(38, 20))
284069401Seric 			printf("getcanonname(%s), found\n", host);
284169401Seric 
284269401Seric 		/*
284369401Seric 		**  If returned name is still single token, compensate
284469401Seric 		**  by tagging on $m.  This is because some sites set
284569401Seric 		**  up their DNS or NIS databases wrong.
284669401Seric 		*/
284769401Seric 
284869401Seric 		if ((d = strchr(host, '.')) == NULL || d[1] == '\0')
284969401Seric 		{
285069401Seric 			d = macvalue('m', CurEnv);
285169401Seric 			if (d != NULL &&
285269401Seric 			    hbsize > (int) (strlen(host) + strlen(d) + 1))
285369401Seric 			{
285469401Seric 				if (host[strlen(host) - 1] != '.')
285569401Seric 					strcat(host, ".");
285669401Seric 				strcat(host, d);
285769401Seric 			}
285869401Seric 			else
285969401Seric 			{
286069401Seric 				return FALSE;
286169401Seric 			}
286269401Seric 		}
286369401Seric 		return TRUE;
286469401Seric 	}
286569401Seric 
286669401Seric 	if (tTd(38, 20))
286769401Seric 		printf("getcanonname(%s), failed, stat=%d\n", host, stat);
286869401Seric 
286969401Seric #if NAMED_BIND
287069401Seric 	if (stat == EX_NOHOST)
287169401Seric 		h_errno = HOST_NOT_FOUND;
287269401Seric 	else
287369401Seric 		h_errno = TRY_AGAIN;
287469401Seric #endif
287569401Seric 
287669401Seric 	return FALSE;
287769401Seric }
287869401Seric /*
287960207Seric **  NULL stubs
288060089Seric */
288160089Seric 
288260207Seric bool
288360207Seric null_map_open(map, mode)
288460089Seric 	MAP *map;
288560207Seric 	int mode;
288660089Seric {
288760207Seric 	return TRUE;
288860089Seric }
288960089Seric 
289060207Seric void
289160207Seric null_map_close(map)
289260207Seric 	MAP *map;
289360089Seric {
289460207Seric 	return;
289560207Seric }
289660089Seric 
289760207Seric void
289860207Seric null_map_store(map, key, val)
289960207Seric 	MAP *map;
290060207Seric 	char *key;
290160207Seric 	char *val;
290260089Seric {
290360207Seric 	return;
290460089Seric }
290568350Seric 
290668350Seric 
290768350Seric /*
290868350Seric **  BOGUS stubs
290968350Seric */
291068350Seric 
291168350Seric char *
291268350Seric bogus_map_lookup(map, key, args, pstat)
291368350Seric 	MAP *map;
291468350Seric 	char *key;
291568350Seric 	char **args;
291668350Seric 	int *pstat;
291768350Seric {
291868350Seric 	*pstat = EX_TEMPFAIL;
291968350Seric 	return NULL;
292068350Seric }
292168350Seric 
292268350Seric MAPCLASS	BogusMapClass =
292368350Seric {
292468350Seric 	"bogus-map",		NULL,		0,
292568350Seric 	NULL,		bogus_map_lookup,	null_map_store,
292668350Seric 	null_map_open,	null_map_close,
292768350Seric };
2928