xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 69802)
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*69802Seric static char sccsid[] = "@(#)map.c	8.72 (Berkeley) 06/05/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 /*
456*69802Seric **  GETCANONNAME -- look up name using service switch
457*69802Seric **
458*69802Seric **	Parameters:
459*69802Seric **		host -- the host name to look up.
460*69802Seric **		hbsize -- the size of the host buffer.
461*69802Seric **		trymx -- if set, try MX records.
462*69802Seric **
463*69802Seric **	Returns:
464*69802Seric **		TRUE -- if the host was found.
465*69802Seric **		FALSE -- otherwise.
466*69802Seric */
467*69802Seric 
468*69802Seric bool
469*69802Seric getcanonname(host, hbsize, trymx)
470*69802Seric 	char *host;
471*69802Seric 	int hbsize;
472*69802Seric 	bool trymx;
473*69802Seric {
474*69802Seric 	int nmaps;
475*69802Seric 	int mapno;
476*69802Seric 	bool found = FALSE;
477*69802Seric 	auto int stat;
478*69802Seric 	char *maptype[MAXMAPSTACK];
479*69802Seric 	short mapreturn[MAXMAPACTIONS];
480*69802Seric 	extern int h_errno;
481*69802Seric 
482*69802Seric 	nmaps = switch_map_find("hosts", maptype, mapreturn);
483*69802Seric 	for (mapno = 0; mapno < nmaps; mapno++)
484*69802Seric 	{
485*69802Seric 		int i;
486*69802Seric 
487*69802Seric 		if (tTd(38, 20))
488*69802Seric 			printf("getcanonname(%s), trying %s\n",
489*69802Seric 				host, maptype[mapno]);
490*69802Seric 		if (strcmp("files", maptype[mapno]) == 0)
491*69802Seric 		{
492*69802Seric 			extern bool text_getcanonname __P((char *, int, int *));
493*69802Seric 
494*69802Seric 			found = text_getcanonname(host, hbsize, &stat);
495*69802Seric 		}
496*69802Seric #ifdef NIS
497*69802Seric 		else if (strcmp("nis", maptype[mapno]) == 0)
498*69802Seric 		{
499*69802Seric 			extern bool nis_getcanonname __P((char *, int, int *));
500*69802Seric 
501*69802Seric 			found = nis_getcanonname(host, hbsize, &stat);
502*69802Seric 		}
503*69802Seric #endif
504*69802Seric #ifdef NISPLUS
505*69802Seric 		else if (strcmp("nisplus", maptype[mapno]) == 0)
506*69802Seric 		{
507*69802Seric 			extern bool nisplus_getcanonname __P((char *, int, int *));
508*69802Seric 
509*69802Seric 			found = nisplus_getcanonname(host, hbsize, &stat);
510*69802Seric 		}
511*69802Seric #endif
512*69802Seric #if NAMED_BIND
513*69802Seric 		else if (strcmp("dns", maptype[mapno]) == 0)
514*69802Seric 		{
515*69802Seric 			extern bool dns_getcanonname __P((char *, int, bool, int *));
516*69802Seric 
517*69802Seric 			found = dns_getcanonname(host, hbsize, trymx, &stat);
518*69802Seric 		}
519*69802Seric #endif
520*69802Seric 		else
521*69802Seric 		{
522*69802Seric 			found = FALSE;
523*69802Seric 			stat = EX_UNAVAILABLE;
524*69802Seric 		}
525*69802Seric 		if (found)
526*69802Seric 			break;
527*69802Seric 
528*69802Seric 		/* see if we should continue */
529*69802Seric 		if (stat == EX_TEMPFAIL)
530*69802Seric 			i = MA_TRYAGAIN;
531*69802Seric 		else if (stat == EX_NOHOST)
532*69802Seric 			i = MA_NOTFOUND;
533*69802Seric 		else
534*69802Seric 			i = MA_UNAVAIL;
535*69802Seric 		if (bitset(1 << mapno, mapreturn[i]))
536*69802Seric 			break;
537*69802Seric 	}
538*69802Seric 
539*69802Seric 	if (found)
540*69802Seric 	{
541*69802Seric 		char *d;
542*69802Seric 
543*69802Seric 		if (tTd(38, 20))
544*69802Seric 			printf("getcanonname(%s), found\n", host);
545*69802Seric 
546*69802Seric 		/*
547*69802Seric 		**  If returned name is still single token, compensate
548*69802Seric 		**  by tagging on $m.  This is because some sites set
549*69802Seric 		**  up their DNS or NIS databases wrong.
550*69802Seric 		*/
551*69802Seric 
552*69802Seric 		if ((d = strchr(host, '.')) == NULL || d[1] == '\0')
553*69802Seric 		{
554*69802Seric 			d = macvalue('m', CurEnv);
555*69802Seric 			if (d != NULL &&
556*69802Seric 			    hbsize > (int) (strlen(host) + strlen(d) + 1))
557*69802Seric 			{
558*69802Seric 				if (host[strlen(host) - 1] != '.')
559*69802Seric 					strcat(host, ".");
560*69802Seric 				strcat(host, d);
561*69802Seric 			}
562*69802Seric 			else
563*69802Seric 			{
564*69802Seric 				return FALSE;
565*69802Seric 			}
566*69802Seric 		}
567*69802Seric 		return TRUE;
568*69802Seric 	}
569*69802Seric 
570*69802Seric 	if (tTd(38, 20))
571*69802Seric 		printf("getcanonname(%s), failed, stat=%d\n", host, stat);
572*69802Seric 
573*69802Seric #if NAMED_BIND
574*69802Seric 	if (stat == EX_NOHOST)
575*69802Seric 		h_errno = HOST_NOT_FOUND;
576*69802Seric 	else
577*69802Seric 		h_errno = TRY_AGAIN;
578*69802Seric #endif
579*69802Seric 
580*69802Seric 	return FALSE;
581*69802Seric }
582*69802Seric /*
58360089Seric **  NDBM modules
58460089Seric */
58560089Seric 
58660089Seric #ifdef NDBM
58760089Seric 
58860089Seric /*
58960089Seric **  DBM_MAP_OPEN -- DBM-style map open
59060089Seric */
59160089Seric 
59260089Seric bool
59360089Seric ndbm_map_open(map, mode)
59460089Seric 	MAP *map;
59560089Seric 	int mode;
59660089Seric {
59764284Seric 	register DBM *dbm;
59864284Seric 	struct stat st;
59960089Seric 
60060537Seric 	if (tTd(38, 2))
60168350Seric 		printf("ndbm_map_open(%s, %s, %d)\n",
60268350Seric 			map->map_mname, map->map_file, mode);
60360089Seric 
60460207Seric 	if (mode == O_RDWR)
60560207Seric 		mode |= O_CREAT|O_TRUNC;
60660207Seric 
60760089Seric 	/* open the database */
60860089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
60956822Seric 	if (dbm == NULL)
61056822Seric 	{
61164718Seric 		if (aliaswait(map, ".pag", FALSE))
61264718Seric 			return TRUE;
61360207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
61456836Seric 			syserr("Cannot open DBM database %s", map->map_file);
61556822Seric 		return FALSE;
61656822Seric 	}
61760089Seric 	map->map_db1 = (void *) dbm;
61864964Seric 	if (mode == O_RDONLY)
61964964Seric 	{
62064964Seric 		if (bitset(MF_ALIAS, map->map_mflags) &&
62164964Seric 		    !aliaswait(map, ".pag", TRUE))
62264718Seric 			return FALSE;
62364964Seric 	}
62464964Seric 	else
62564964Seric 	{
62664964Seric 		int fd;
62764964Seric 
62864964Seric 		/* exclusive lock for duration of rebuild */
62964964Seric 		fd = dbm_dirfno((DBM *) map->map_db1);
63064964Seric 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
63164964Seric 		    lockfile(fd, map->map_file, ".dir", LOCK_EX))
63264964Seric 			map->map_mflags |= MF_LOCKED;
63364964Seric 	}
63464718Seric 	if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
63564284Seric 		map->map_mtime = st.st_mtime;
63656822Seric 	return TRUE;
63756822Seric }
63860089Seric 
63960089Seric 
64060089Seric /*
64156822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
64256822Seric */
64356822Seric 
64456822Seric char *
64560089Seric ndbm_map_lookup(map, name, av, statp)
64656822Seric 	MAP *map;
64760089Seric 	char *name;
64856822Seric 	char **av;
64959084Seric 	int *statp;
65056822Seric {
65156822Seric 	datum key, val;
65264373Seric 	int fd;
65360089Seric 	char keybuf[MAXNAME + 1];
65456822Seric 
65560537Seric 	if (tTd(38, 20))
65668350Seric 		printf("ndbm_map_lookup(%s, %s)\n",
65768350Seric 			map->map_mname, name);
65860089Seric 
65960089Seric 	key.dptr = name;
66060089Seric 	key.dsize = strlen(name);
66160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
66257014Seric 	{
66360089Seric 		if (key.dsize > sizeof keybuf - 1)
66460089Seric 			key.dsize = sizeof keybuf - 1;
66560089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
66660089Seric 		makelower(keybuf);
66760089Seric 		key.dptr = keybuf;
66857014Seric 	}
66964373Seric 	fd = dbm_dirfno((DBM *) map->map_db1);
67064388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
67164373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
67263753Seric 	val.dptr = NULL;
67363753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
67463753Seric 	{
67563753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
67663753Seric 		if (val.dptr != NULL)
67763753Seric 			map->map_mflags &= ~MF_TRY1NULL;
67863753Seric 	}
67963753Seric 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
68063753Seric 	{
68156822Seric 		key.dsize++;
68263753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
68363753Seric 		if (val.dptr != NULL)
68463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
68563753Seric 	}
68664388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
68764373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
68856822Seric 	if (val.dptr == NULL)
68956822Seric 		return NULL;
69060207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
69163753Seric 		return map_rewrite(map, name, strlen(name), NULL);
69263753Seric 	else
69363753Seric 		return map_rewrite(map, val.dptr, val.dsize, av);
69456822Seric }
69556822Seric 
69656822Seric 
69756822Seric /*
69860089Seric **  DBM_MAP_STORE -- store a datum in the database
69956822Seric */
70056822Seric 
70160089Seric void
70260089Seric ndbm_map_store(map, lhs, rhs)
70360089Seric 	register MAP *map;
70460089Seric 	char *lhs;
70560089Seric 	char *rhs;
70660089Seric {
70760089Seric 	datum key;
70860089Seric 	datum data;
70960089Seric 	int stat;
71060089Seric 
71160537Seric 	if (tTd(38, 12))
71268350Seric 		printf("ndbm_map_store(%s, %s, %s)\n",
71368350Seric 			map->map_mname, lhs, rhs);
71460089Seric 
71560089Seric 	key.dsize = strlen(lhs);
71660089Seric 	key.dptr = lhs;
71760089Seric 
71860089Seric 	data.dsize = strlen(rhs);
71960089Seric 	data.dptr = rhs;
72060089Seric 
72160207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
72260089Seric 	{
72360089Seric 		key.dsize++;
72460089Seric 		data.dsize++;
72560089Seric 	}
72660089Seric 
72760089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
72860089Seric 	if (stat > 0)
72960089Seric 	{
73068497Seric 		if (!bitset(MF_APPEND, map->map_mflags))
73168497Seric 			usrerr("050 Warning: duplicate alias name %s", lhs);
73268497Seric 		else
73368497Seric 		{
73468497Seric 			static char *buf = NULL;
73568497Seric 			static int bufsiz = 0;
73668879Seric 			auto int xstat;
73768497Seric 			datum old;
73868497Seric 
73968879Seric 			old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat);
74068497Seric 			if (old.dptr != NULL && *old.dptr != '\0')
74168497Seric 			{
74268497Seric 				old.dsize = strlen(old.dptr);
74368497Seric 				if (data.dsize + old.dsize + 2 > bufsiz)
74468497Seric 				{
74568497Seric 					if (buf != NULL)
74668497Seric 						(void) free(buf);
74768497Seric 					bufsiz = data.dsize + old.dsize + 2;
74868497Seric 					buf = xalloc(bufsiz);
74968497Seric 				}
75068497Seric 				sprintf(buf, "%s,%s", data.dptr, old.dptr);
75168497Seric 				data.dsize = data.dsize + old.dsize + 1;
75268497Seric 				data.dptr = buf;
75368497Seric 				if (tTd(38, 9))
75468497Seric 					printf("ndbm_map_store append=%s\n", data.dptr);
75568497Seric 			}
75668497Seric 		}
75760089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
75860089Seric 	}
75960089Seric 	if (stat != 0)
76060089Seric 		syserr("readaliases: dbm put (%s)", lhs);
76160089Seric }
76260089Seric 
76360089Seric 
76460089Seric /*
76560207Seric **  NDBM_MAP_CLOSE -- close the database
76660089Seric */
76760089Seric 
76860089Seric void
76960089Seric ndbm_map_close(map)
77060089Seric 	register MAP  *map;
77160089Seric {
77266773Seric 	if (tTd(38, 9))
77368350Seric 		printf("ndbm_map_close(%s, %s, %x)\n",
77468350Seric 			map->map_mname, map->map_file, map->map_mflags);
77566773Seric 
77660207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
77760089Seric 	{
77864250Seric #ifdef NIS
77964075Seric 		bool inclnull;
78060089Seric 		char buf[200];
78160089Seric 
78264075Seric 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
78364075Seric 		map->map_mflags &= ~MF_INCLNULL;
78464075Seric 
78569651Seric 		if (strstr(map->map_file, "/yp/") != NULL)
78669651Seric 		{
78769651Seric 			(void) sprintf(buf, "%010ld", curtime());
78869651Seric 			ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
78960089Seric 
79069651Seric 			(void) gethostname(buf, sizeof buf);
79169651Seric 			ndbm_map_store(map, "YP_MASTER_NAME", buf);
79269651Seric 		}
79364075Seric 
79464075Seric 		if (inclnull)
79564075Seric 			map->map_mflags |= MF_INCLNULL;
79660089Seric #endif
79760089Seric 
79860089Seric 		/* write out the distinguished alias */
79960089Seric 		ndbm_map_store(map, "@", "@");
80060089Seric 	}
80160089Seric 	dbm_close((DBM *) map->map_db1);
80260089Seric }
80360089Seric 
80460089Seric #endif
80560089Seric /*
80660582Seric **  NEWDB (Hash and BTree) Modules
80760089Seric */
80860089Seric 
80960089Seric #ifdef NEWDB
81060089Seric 
81160089Seric /*
81260582Seric **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
81360582Seric **
81460582Seric **	These do rather bizarre locking.  If you can lock on open,
81560582Seric **	do that to avoid the condition of opening a database that
81660582Seric **	is being rebuilt.  If you don't, we'll try to fake it, but
81760582Seric **	there will be a race condition.  If opening for read-only,
81860582Seric **	we immediately release the lock to avoid freezing things up.
81960582Seric **	We really ought to hold the lock, but guarantee that we won't
82060582Seric **	be pokey about it.  That's hard to do.
82160089Seric */
82260089Seric 
82356822Seric bool
82460089Seric bt_map_open(map, mode)
82556822Seric 	MAP *map;
82660089Seric 	int mode;
82756822Seric {
82856822Seric 	DB *db;
82960228Seric 	int i;
83060582Seric 	int omode;
83164373Seric 	int fd;
83264284Seric 	struct stat st;
83368528Seric 	char buf[MAXNAME + 1];
83456822Seric 
83560537Seric 	if (tTd(38, 2))
83668350Seric 		printf("bt_map_open(%s, %s, %d)\n",
83768350Seric 			map->map_mname, map->map_file, mode);
83860089Seric 
83960582Seric 	omode = mode;
84060582Seric 	if (omode == O_RDWR)
84160582Seric 	{
84260582Seric 		omode |= O_CREAT|O_TRUNC;
84365830Seric #if defined(O_EXLOCK) && HASFLOCK
84460582Seric 		omode |= O_EXLOCK;
84566843Seric # if !OLD_NEWDB
84660582Seric 	}
84760582Seric 	else
84860582Seric 	{
84960582Seric 		omode |= O_SHLOCK;
85060582Seric # endif
85160582Seric #endif
85260582Seric 	}
85360207Seric 
85460228Seric 	(void) strcpy(buf, map->map_file);
85560228Seric 	i = strlen(buf);
85660228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
85760228Seric 		(void) strcat(buf, ".db");
85860582Seric 	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
85956822Seric 	if (db == NULL)
86056822Seric 	{
86164718Seric #ifdef MAYBENEXTRELEASE
86264718Seric 		if (aliaswait(map, ".db", FALSE))
86364718Seric 			return TRUE;
86464718Seric #endif
86560207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
86656836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
86756822Seric 		return FALSE;
86856822Seric 	}
86968350Seric #if !OLD_NEWDB
87064373Seric 	fd = db->fd(db);
87168778Seric # if defined(O_EXLOCK) && HASFLOCK
87268778Seric 	if (fd >= 0)
87368778Seric 	{
87468778Seric 		if (mode == O_RDONLY)
87568778Seric 			(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
87668778Seric 		else
87768778Seric 			map->map_mflags |= MF_LOCKED;
87868778Seric 	}
87968778Seric # else
88064373Seric 	if (mode == O_RDWR && fd >= 0)
88164388Seric 	{
88264388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
88364388Seric 			map->map_mflags |= MF_LOCKED;
88464388Seric 	}
88560582Seric # endif
88660582Seric #endif
88760585Seric 
88860585Seric 	/* try to make sure that at least the database header is on disk */
88960585Seric 	if (mode == O_RDWR)
89066843Seric #if OLD_NEWDB
89164373Seric 		(void) db->sync(db);
89264373Seric #else
89360585Seric 		(void) db->sync(db, 0);
89460585Seric 
89564373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
89664284Seric 		map->map_mtime = st.st_mtime;
89764284Seric #endif
89864284Seric 
89960089Seric 	map->map_db2 = (void *) db;
90060207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
90164718Seric 		if (!aliaswait(map, ".db", TRUE))
90264718Seric 			return FALSE;
90356822Seric 	return TRUE;
90456822Seric }
90556822Seric 
90656822Seric 
90756822Seric /*
90856822Seric **  HASH_MAP_INIT -- HASH-style map initialization
90956822Seric */
91056822Seric 
91156822Seric bool
91260089Seric hash_map_open(map, mode)
91356822Seric 	MAP *map;
91460089Seric 	int mode;
91556822Seric {
91656822Seric 	DB *db;
91760228Seric 	int i;
91860582Seric 	int omode;
91964373Seric 	int fd;
92064284Seric 	struct stat st;
92168528Seric 	char buf[MAXNAME + 1];
92256822Seric 
92360537Seric 	if (tTd(38, 2))
92468350Seric 		printf("hash_map_open(%s, %s, %d)\n",
92568350Seric 			map->map_mname, map->map_file, mode);
92660089Seric 
92760582Seric 	omode = mode;
92860582Seric 	if (omode == O_RDWR)
92960582Seric 	{
93060582Seric 		omode |= O_CREAT|O_TRUNC;
93165830Seric #if defined(O_EXLOCK) && HASFLOCK
93260582Seric 		omode |= O_EXLOCK;
93366843Seric # if !OLD_NEWDB
93460582Seric 	}
93560582Seric 	else
93660582Seric 	{
93760582Seric 		omode |= O_SHLOCK;
93860582Seric # endif
93960582Seric #endif
94060582Seric 	}
94160207Seric 
94260228Seric 	(void) strcpy(buf, map->map_file);
94360228Seric 	i = strlen(buf);
94460228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
94560228Seric 		(void) strcat(buf, ".db");
94660582Seric 	db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
94756822Seric 	if (db == NULL)
94856822Seric 	{
94964718Seric #ifdef MAYBENEXTRELEASE
95064718Seric 		if (aliaswait(map, ".db", FALSE))
95164718Seric 			return TRUE;
95264718Seric #endif
95360207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
95456836Seric 			syserr("Cannot open HASH database %s", map->map_file);
95556822Seric 		return FALSE;
95656822Seric 	}
95768350Seric #if !OLD_NEWDB
95864373Seric 	fd = db->fd(db);
95968778Seric # if defined(O_EXLOCK) && HASFLOCK
96068778Seric 	if (fd >= 0)
96168778Seric 	{
96268778Seric 		if (mode == O_RDONLY)
96368778Seric 			(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
96468778Seric 		else
96568778Seric 			map->map_mflags |= MF_LOCKED;
96668778Seric 	}
96768778Seric # else
96864373Seric 	if (mode == O_RDWR && fd >= 0)
96964388Seric 	{
97064388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
97164388Seric 			map->map_mflags |= MF_LOCKED;
97264388Seric 	}
97360582Seric # endif
97460582Seric #endif
97560585Seric 
97660585Seric 	/* try to make sure that at least the database header is on disk */
97760585Seric 	if (mode == O_RDWR)
97866843Seric #if OLD_NEWDB
97964373Seric 		(void) db->sync(db);
98064373Seric #else
98160585Seric 		(void) db->sync(db, 0);
98260585Seric 
98364373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
98464284Seric 		map->map_mtime = st.st_mtime;
98564284Seric #endif
98664284Seric 
98760089Seric 	map->map_db2 = (void *) db;
98860207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
98964718Seric 		if (!aliaswait(map, ".db", TRUE))
99064718Seric 			return FALSE;
99156822Seric 	return TRUE;
99256822Seric }
99356822Seric 
99456822Seric 
99556822Seric /*
99656822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
99756822Seric */
99856822Seric 
99956822Seric char *
100060089Seric db_map_lookup(map, name, av, statp)
100156822Seric 	MAP *map;
100260089Seric 	char *name;
100356822Seric 	char **av;
100459084Seric 	int *statp;
100556822Seric {
100656822Seric 	DBT key, val;
100760422Seric 	register DB *db = (DB *) map->map_db2;
100860422Seric 	int st;
100960422Seric 	int saveerrno;
101064373Seric 	int fd;
101160089Seric 	char keybuf[MAXNAME + 1];
101256822Seric 
101360537Seric 	if (tTd(38, 20))
101468350Seric 		printf("db_map_lookup(%s, %s)\n",
101568350Seric 			map->map_mname, name);
101660089Seric 
101760089Seric 	key.size = strlen(name);
101860089Seric 	if (key.size > sizeof keybuf - 1)
101960089Seric 		key.size = sizeof keybuf - 1;
102060089Seric 	key.data = keybuf;
102160089Seric 	bcopy(name, keybuf, key.size + 1);
102260207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
102360089Seric 		makelower(keybuf);
102466843Seric #if !OLD_NEWDB
102564388Seric 	fd = db->fd(db);
102664388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
102764388Seric 		(void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
102860422Seric #endif
102963753Seric 	st = 1;
103063753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
103163753Seric 	{
103263753Seric 		st = db->get(db, &key, &val, 0);
103363753Seric 		if (st == 0)
103463753Seric 			map->map_mflags &= ~MF_TRY1NULL;
103563753Seric 	}
103663753Seric 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
103763753Seric 	{
103863753Seric 		key.size++;
103963753Seric 		st = db->get(db, &key, &val, 0);
104063753Seric 		if (st == 0)
104163753Seric 			map->map_mflags &= ~MF_TRY0NULL;
104263753Seric 	}
104360422Seric 	saveerrno = errno;
104466843Seric #if !OLD_NEWDB
104564388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
104664373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
104760422Seric #endif
104860422Seric 	if (st != 0)
104960422Seric 	{
105060422Seric 		errno = saveerrno;
105160422Seric 		if (st < 0)
105260422Seric 			syserr("db_map_lookup: get (%s)", name);
105356822Seric 		return NULL;
105460422Seric 	}
105560207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
105663753Seric 		return map_rewrite(map, name, strlen(name), NULL);
105763753Seric 	else
105863753Seric 		return map_rewrite(map, val.data, val.size, av);
105956822Seric }
106056822Seric 
106160089Seric 
106260089Seric /*
106360089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
106456822Seric */
106556822Seric 
106660089Seric void
106760089Seric db_map_store(map, lhs, rhs)
106860089Seric 	register MAP *map;
106960089Seric 	char *lhs;
107060089Seric 	char *rhs;
107156822Seric {
107260089Seric 	int stat;
107360089Seric 	DBT key;
107460089Seric 	DBT data;
107560089Seric 	register DB *db = map->map_db2;
107656822Seric 
107760537Seric 	if (tTd(38, 20))
107868350Seric 		printf("db_map_store(%s, %s, %s)\n",
107968350Seric 			map->map_mname, lhs, rhs);
108060089Seric 
108160089Seric 	key.size = strlen(lhs);
108260089Seric 	key.data = lhs;
108360089Seric 
108460089Seric 	data.size = strlen(rhs);
108560089Seric 	data.data = rhs;
108660089Seric 
108760207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
108856822Seric 	{
108960089Seric 		key.size++;
109060089Seric 		data.size++;
109160089Seric 	}
109256836Seric 
109360089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
109460089Seric 	if (stat > 0)
109560089Seric 	{
109668497Seric 		if (!bitset(MF_APPEND, map->map_mflags))
109768497Seric 			usrerr("050 Warning: duplicate alias name %s", lhs);
109868497Seric 		else
109968497Seric 		{
110068497Seric 			static char *buf = NULL;
110168497Seric 			static int bufsiz = 0;
110268497Seric 			DBT old;
110368497Seric 
110468497Seric 			old.data = db_map_lookup(map, key.data, NULL, &stat);
110568497Seric 			if (old.data != NULL)
110668497Seric 			{
110768497Seric 				old.size = strlen(old.data);
110868497Seric 				if (data.size + old.size + 2 > bufsiz)
110968497Seric 				{
111068497Seric 					if (buf != NULL)
111168497Seric 						(void) free(buf);
111268497Seric 					bufsiz = data.size + old.size + 2;
111368497Seric 					buf = xalloc(bufsiz);
111468497Seric 				}
111568497Seric 				sprintf(buf, "%s,%s", data.data, old.data);
111668497Seric 				data.size = data.size + old.size + 1;
111768497Seric 				data.data = buf;
111868497Seric 				if (tTd(38, 9))
111968497Seric 					printf("db_map_store append=%s\n", data.data);
112068497Seric 			}
112168497Seric 		}
112260089Seric 		stat = db->put(db, &key, &data, 0);
112360089Seric 	}
112460089Seric 	if (stat != 0)
112560089Seric 		syserr("readaliases: db put (%s)", lhs);
112660089Seric }
112756836Seric 
112856847Seric 
112960089Seric /*
113060089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
113160089Seric */
113260089Seric 
113360089Seric void
113460089Seric db_map_close(map)
113560089Seric 	MAP *map;
113660089Seric {
113760089Seric 	register DB *db = map->map_db2;
113860089Seric 
113960537Seric 	if (tTd(38, 9))
114068350Seric 		printf("db_map_close(%s, %s, %x)\n",
114168350Seric 			map->map_mname, map->map_file, map->map_mflags);
114260089Seric 
114360207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
114458804Seric 	{
114560089Seric 		/* write out the distinguished alias */
114660089Seric 		db_map_store(map, "@", "@");
114758804Seric 	}
114858963Seric 
114960089Seric 	if (db->close(db) != 0)
115060089Seric 		syserr("readaliases: db close failure");
115156822Seric }
115257208Seric 
115360089Seric #endif
115460089Seric /*
115560089Seric **  NIS Modules
115660089Seric */
115760089Seric 
115860089Seric # ifdef NIS
115960089Seric 
116064369Seric # ifndef YPERR_BUSY
116164369Seric #  define YPERR_BUSY	16
116264369Seric # endif
116364369Seric 
116457208Seric /*
116560089Seric **  NIS_MAP_OPEN -- open DBM map
116657208Seric */
116757208Seric 
116857208Seric bool
116960089Seric nis_map_open(map, mode)
117057208Seric 	MAP *map;
117160089Seric 	int mode;
117257208Seric {
117357216Seric 	int yperr;
117460215Seric 	register char *p;
117560215Seric 	auto char *vp;
117660215Seric 	auto int vsize;
117757216Seric 
117860537Seric 	if (tTd(38, 2))
117968350Seric 		printf("nis_map_open(%s, %s)\n",
118068350Seric 			map->map_mname, map->map_file);
118160089Seric 
118260207Seric 	if (mode != O_RDONLY)
118360207Seric 	{
118464650Seric 		/* issue a pseudo-error message */
118564650Seric #ifdef ENOSYS
118664650Seric 		errno = ENOSYS;
118764650Seric #else
118864650Seric # ifdef EFTYPE
118964650Seric 		errno = EFTYPE;
119064650Seric # else
119164650Seric 		errno = ENXIO;
119264650Seric # endif
119364650Seric #endif
119460207Seric 		return FALSE;
119560207Seric 	}
119660207Seric 
119760089Seric 	p = strchr(map->map_file, '@');
119860089Seric 	if (p != NULL)
119960089Seric 	{
120060089Seric 		*p++ = '\0';
120160089Seric 		if (*p != '\0')
120260089Seric 			map->map_domain = p;
120360089Seric 	}
120460215Seric 
120560089Seric 	if (*map->map_file == '\0')
120660089Seric 		map->map_file = "mail.aliases";
120760089Seric 
120866157Seric 	if (map->map_domain == NULL)
120966157Seric 	{
121066157Seric 		yperr = yp_get_default_domain(&map->map_domain);
121166157Seric 		if (yperr != 0)
121266157Seric 		{
121366744Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
121468350Seric 				syserr("421 NIS map %s specified, but NIS not running\n",
121566744Seric 					map->map_file);
121666157Seric 			return FALSE;
121766157Seric 		}
121866157Seric 	}
121966157Seric 
122060215Seric 	/* check to see if this map actually exists */
122160089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
122260089Seric 			&vp, &vsize);
122360537Seric 	if (tTd(38, 10))
122460089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
122560089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
122660089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
122768350Seric 	{
122868350Seric 		if (!bitset(MF_ALIAS, map->map_mflags) ||
122968350Seric 		    aliaswait(map, NULL, TRUE))
123068350Seric 			return TRUE;
123168350Seric 	}
123260215Seric 
123360215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
123468735Seric 	{
123568735Seric 		syserr("421 Cannot bind to map %s in domain %s: %s",
123668735Seric 			map->map_file, map->map_domain, yperr_string(yperr));
123768735Seric 	}
123860215Seric 
123960089Seric 	return FALSE;
124060089Seric }
124160089Seric 
124260089Seric 
124360089Seric /*
124457208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
124557208Seric */
124657208Seric 
124757208Seric char *
124860089Seric nis_map_lookup(map, name, av, statp)
124957208Seric 	MAP *map;
125060089Seric 	char *name;
125157208Seric 	char **av;
125259084Seric 	int *statp;
125357208Seric {
125457208Seric 	char *vp;
125557642Seric 	auto int vsize;
125659274Seric 	int buflen;
125760215Seric 	int yperr;
125860089Seric 	char keybuf[MAXNAME + 1];
125957208Seric 
126060537Seric 	if (tTd(38, 20))
126168350Seric 		printf("nis_map_lookup(%s, %s)\n",
126268350Seric 			map->map_mname, name);
126360089Seric 
126460089Seric 	buflen = strlen(name);
126560089Seric 	if (buflen > sizeof keybuf - 1)
126660089Seric 		buflen = sizeof keybuf - 1;
126760089Seric 	bcopy(name, keybuf, buflen + 1);
126860207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
126960089Seric 		makelower(keybuf);
127063753Seric 	yperr = YPERR_KEY;
127163753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
127263753Seric 	{
127363753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
127463753Seric 			     &vp, &vsize);
127563753Seric 		if (yperr == 0)
127663753Seric 			map->map_mflags &= ~MF_TRY1NULL;
127763753Seric 	}
127863753Seric 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
127963753Seric 	{
128059274Seric 		buflen++;
128163753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
128263753Seric 			     &vp, &vsize);
128363753Seric 		if (yperr == 0)
128463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
128563753Seric 	}
128660089Seric 	if (yperr != 0)
128760089Seric 	{
128860089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
128960215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
129057208Seric 		return NULL;
129160089Seric 	}
129260207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
129363753Seric 		return map_rewrite(map, name, strlen(name), NULL);
129463753Seric 	else
129563753Seric 		return map_rewrite(map, vp, vsize, av);
129657208Seric }
129757208Seric 
129869401Seric 
129969401Seric /*
130069401Seric **  NIS_GETCANONNAME -- look up canonical name in NIS
130169401Seric */
130269401Seric 
130369401Seric bool
130469401Seric nis_getcanonname(name, hbsize, statp)
130569401Seric 	char *name;
130669401Seric 	int hbsize;
130769401Seric 	int *statp;
130869401Seric {
130969401Seric 	char *vp;
131069401Seric 	auto int vsize;
131169401Seric 	int keylen;
131269401Seric 	int yperr;
131369401Seric 	static bool try0null = TRUE;
131469401Seric 	static bool try1null = TRUE;
131569401Seric 	static char *yp_domain = NULL;
131669748Seric 	char *domain;
131769780Seric 	char *cname;
131869401Seric 	char host_record[MAXLINE];
131969780Seric 	char fbuf[MAXNAME];
132069780Seric 	char nbuf[MAXNAME + 1];
132169401Seric 	extern char *get_column();
132269401Seric 
132369401Seric 	if (tTd(38, 20))
132469401Seric 		printf("nis_getcanonname(%s)\n", name);
132569401Seric 
132669780Seric 	if (strlen(name) >= sizeof nbuf)
132769780Seric 	{
132869780Seric 		*statp = EX_UNAVAILABLE;
132969780Seric 		return FALSE;
133069780Seric 	}
133169780Seric 	(void) strcpy(nbuf, name);
133269780Seric 	shorten_hostname(nbuf);
133369401Seric 
133469401Seric 	/* we only accept single token search key */
133569780Seric 	if (strchr(nbuf, '.'))
133669401Seric 	{
133769401Seric 		*statp = EX_NOHOST;
133869401Seric 		return FALSE;
133969401Seric 	}
134069401Seric 
134169780Seric 	keylen = strlen(nbuf);
134269401Seric 
134369401Seric 	if (yp_domain == NULL)
134469401Seric 		yp_get_default_domain(&yp_domain);
134569780Seric 	makelower(nbuf);
134669401Seric 	yperr = YPERR_KEY;
134769401Seric 	if (try0null)
134869401Seric 	{
134969780Seric 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
135069401Seric 			     &vp, &vsize);
135169401Seric 		if (yperr == 0)
135269401Seric 			try1null = FALSE;
135369401Seric 	}
135469401Seric 	if (yperr == YPERR_KEY && try1null)
135569401Seric 	{
135669401Seric 		keylen++;
135769780Seric 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
135869401Seric 			     &vp, &vsize);
135969401Seric 		if (yperr == 0)
136069401Seric 			try0null = FALSE;
136169401Seric 	}
136269401Seric 	if (yperr != 0)
136369401Seric 	{
136469401Seric 		if (yperr == YPERR_KEY)
136569401Seric 			*statp = EX_NOHOST;
136669401Seric 		else if (yperr == YPERR_BUSY)
136769401Seric 			*statp = EX_TEMPFAIL;
136869401Seric 		else
136969401Seric 			*statp = EX_UNAVAILABLE;
137069401Seric 		return FALSE;
137169401Seric 	}
137269401Seric 	strncpy(host_record, vp, vsize);
137369401Seric 	host_record[vsize] = '\0';
137469663Seric 	if (tTd(38, 44))
137569663Seric 		printf("got record `%s'\n", host_record);
137669780Seric 	cname = get_column(host_record, 1, '\0', fbuf);
137769401Seric 	if (cname == NULL)
137869401Seric 	{
137969401Seric 		/* this should not happen, but.... */
138069401Seric 		*statp = EX_NOHOST;
138169401Seric 		return FALSE;
138269401Seric 	}
138369401Seric 
138469703Seric 	if (strchr(cname, '.') != NULL)
138569401Seric 	{
138669703Seric 		domain = "";
138769703Seric 	}
138869703Seric 	else
138969703Seric 	{
139069703Seric 		domain = macvalue('m', CurEnv);
139169703Seric 		if (domain == NULL)
139269703Seric 			domain = "";
139369703Seric 	}
139469703Seric 	if (hbsize >= strlen(cname) + strlen(domain) + 1)
139569703Seric 	{
139669703Seric 		if (domain[0] == '\0')
139769703Seric 			strcpy(name, vp);
139869703Seric 		else
139969703Seric 			sprintf(name, "%s.%s", vp, domain);
140069401Seric 		*statp = EX_OK;
140169401Seric 		return TRUE;
140269401Seric 	}
140369401Seric 	*statp = EX_UNAVAILABLE;
140469401Seric 	return FALSE;
140569401Seric }
140669401Seric 
140768350Seric #endif
140868350Seric /*
140968350Seric **  NISPLUS Modules
141068350Seric **
141168350Seric **	This code donated by Sun Microsystems.
141268350Seric */
141367848Seric 
141468350Seric #ifdef NISPLUS
141568350Seric 
141668350Seric #undef NIS /* symbol conflict in nis.h */
141768350Seric #include <rpcsvc/nis.h>
141868350Seric #include <rpcsvc/nislib.h>
141968350Seric 
142068350Seric #define EN_col(col)	zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
142168350Seric #define COL_NAME(res,i)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
142268350Seric #define COL_MAX(res)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
142368350Seric #define PARTIAL_NAME(x)	((x)[strlen(x) - 1] != '.')
142468350Seric 
142567848Seric /*
142668350Seric **  NISPLUS_MAP_OPEN -- open nisplus table
142767848Seric */
142867848Seric 
142968350Seric bool
143068350Seric nisplus_map_open(map, mode)
143167848Seric 	MAP *map;
143268350Seric 	int mode;
143367848Seric {
143468350Seric 	register char *p;
143568350Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
143668350Seric 	nis_result *res = NULL;
143768350Seric 	u_int objs_len;
143868350Seric 	nis_object *obj_ptr;
143968350Seric 	int retry_cnt, max_col, i;
144068350Seric 
144168350Seric 	if (tTd(38, 2))
144268350Seric 		printf("nisplus_map_open(%s, %s, %d)\n",
144368350Seric 			map->map_mname, map->map_file, mode);
144468350Seric 
144568350Seric 	if (mode != O_RDONLY)
144668350Seric 	{
144768350Seric 		errno = ENODEV;
144868350Seric 		return FALSE;
144968350Seric 	}
145068350Seric 
145168350Seric 	if (*map->map_file == '\0')
145268350Seric 		map->map_file = "mail_aliases.org_dir";
145368350Seric 
145468350Seric 	if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
145568350Seric 	{
145668350Seric 		/* set default NISPLUS Domain to $m */
145768350Seric 		extern char *nisplus_default_domain();
145868350Seric 
145968350Seric 		map->map_domain = newstr(nisplus_default_domain());
146068350Seric 		if (tTd(38, 2))
146168350Seric 			printf("nisplus_map_open(%s): using domain %s\n",
146268350Seric 				 map->map_file, map->map_domain);
146368350Seric 	}
146468350Seric 	if (!PARTIAL_NAME(map->map_file))
146568350Seric 		map->map_domain = newstr("");
146668350Seric 
146768350Seric 	/* check to see if this map actually exists */
146868350Seric 	if (PARTIAL_NAME(map->map_file))
146968350Seric 		sprintf(qbuf, "%s.%s", map->map_file, map->map_domain);
147068350Seric 	else
147168350Seric 		strcpy(qbuf, map->map_file);
147268350Seric 
147368350Seric 	retry_cnt = 0;
147468350Seric 	while (res == NULL || res->status != NIS_SUCCESS)
147568350Seric 	{
147668350Seric 		res = nis_lookup(qbuf, FOLLOW_LINKS);
147768350Seric 		switch (res->status)
147868350Seric 		{
147968350Seric 		  case NIS_SUCCESS:
148068350Seric 		  case NIS_TRYAGAIN:
148168350Seric 		  case NIS_RPCERROR:
148268350Seric 		  case NIS_NAMEUNREACHABLE:
148368350Seric 			break;
148468350Seric 
148568350Seric 		  default:		/* all other nisplus errors */
148668350Seric #if 0
148768350Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
148868350Seric 				syserr("421 Cannot find table %s.%s: %s",
148968350Seric 					map->map_file, map->map_domain,
149068350Seric 					nis_sperrno(res->status));
149168350Seric #endif
149268350Seric 			errno = EBADR;
149368350Seric 			return FALSE;
149468350Seric 		}
149568350Seric 		sleep(2);		/* try not to overwhelm hosed server */
149668350Seric 		if (retry_cnt++ > 4)
149768350Seric 		{
149868350Seric 			errno = EBADR;
149968350Seric 			return FALSE;
150068350Seric 		}
150168350Seric 	}
150268350Seric 
150368350Seric 	if (NIS_RES_NUMOBJ(res) != 1 ||
150468350Seric 	    (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
150568350Seric 	{
150668350Seric 		if (tTd(38, 10))
150768350Seric 			printf("nisplus_map_open: %s is not a table\n", qbuf);
150868350Seric #if 0
150968350Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
151068350Seric 			syserr("421 %s.%s: %s is not a table",
151168350Seric 				map->map_file, map->map_domain,
151268350Seric 				nis_sperrno(res->status));
151368350Seric #endif
151468350Seric 		errno = EBADR;
151568350Seric 		return FALSE;
151668350Seric 	}
151768350Seric 	/* default key column is column 0 */
151868350Seric 	if (map->map_keycolnm == NULL)
151968350Seric 		map->map_keycolnm = newstr(COL_NAME(res,0));
152068350Seric 
152168350Seric 	max_col = COL_MAX(res);
152268350Seric 
152368350Seric 	/* verify the key column exist */
152468350Seric 	for (i=0; i< max_col; i++)
152568350Seric 	{
152668350Seric 		if (!strcmp(map->map_keycolnm, COL_NAME(res,i)))
152768350Seric 			break;
152868350Seric 	}
152968350Seric 	if (i == max_col)
153068350Seric 	{
153168350Seric 		if (tTd(38, 2))
153268350Seric 			printf("nisplus_map_open(%s): can not find key column %s\n",
153368350Seric 				map->map_file, map->map_keycolnm);
153468350Seric 		errno = EBADR;
153568350Seric 		return FALSE;
153668350Seric 	}
153768350Seric 
153868350Seric 	/* default value column is the last column */
153968350Seric 	if (map->map_valcolnm == NULL)
154068350Seric 	{
154168350Seric 		map->map_valcolno = max_col - 1;
154268350Seric 		return TRUE;
154368350Seric 	}
154468350Seric 
154568350Seric 	for (i=0; i< max_col; i++)
154668350Seric 	{
154768350Seric 		if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
154868350Seric 		{
154968350Seric 			map->map_valcolno = i;
155068350Seric 			return TRUE;
155168350Seric 		}
155268350Seric 	}
155368350Seric 
155468350Seric 	if (tTd(38, 2))
155568350Seric 		printf("nisplus_map_open(%s): can not find column %s\n",
155668350Seric 			 map->map_file, map->map_keycolnm);
155768350Seric 	errno = EBADR;
155868350Seric 	return FALSE;
155967848Seric }
156067848Seric 
156167848Seric 
156267848Seric /*
156368350Seric **  NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
156467848Seric */
156567848Seric 
156668350Seric char *
156768350Seric nisplus_map_lookup(map, name, av, statp)
156867848Seric 	MAP *map;
156968350Seric 	char *name;
157068350Seric 	char **av;
157168350Seric 	int *statp;
157267848Seric {
157368350Seric 	char *vp;
157468350Seric 	auto int vsize;
157568350Seric 	int buflen;
157668350Seric 	char search_key[MAXNAME + 1];
157768350Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
157868350Seric 	nis_result *result;
157968350Seric 
158068350Seric 	if (tTd(38, 20))
158168350Seric 		printf("nisplus_map_lookup(%s, %s)\n",
158268350Seric 			map->map_mname, name);
158368350Seric 
158468350Seric 	if (!bitset(MF_OPEN, map->map_mflags))
158568350Seric 	{
158668350Seric 		if (nisplus_map_open(map, O_RDONLY))
158768350Seric 			map->map_mflags |= MF_OPEN;
158868350Seric 		else
158968350Seric 		{
159068350Seric 			*statp = EX_UNAVAILABLE;
159168350Seric 			return NULL;
159268350Seric 		}
159368350Seric 	}
159468350Seric 
159568350Seric 	buflen = strlen(name);
159668350Seric 	if (buflen > sizeof search_key - 1)
159768350Seric 		buflen = sizeof search_key - 1;
159868350Seric 	bcopy(name, search_key, buflen + 1);
159968350Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
160068350Seric 		makelower(search_key);
160168350Seric 
160268350Seric 	/* construct the query */
160368350Seric 	if (PARTIAL_NAME(map->map_file))
160468350Seric 		sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm,
160568350Seric 			search_key, map->map_file, map->map_domain);
160668350Seric 	else
160768350Seric 		sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm,
160868350Seric 			search_key, map->map_file);
160968350Seric 
161068350Seric 	if (tTd(38, 20))
161168350Seric 		printf("qbuf=%s\n", qbuf);
161268350Seric 	result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
161368350Seric 	if (result->status == NIS_SUCCESS)
161468350Seric 	{
161568350Seric 		int count;
161668350Seric 		char *str;
161768350Seric 
161868350Seric 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
161968350Seric 		{
162068350Seric 			if (LogLevel > 10)
162168350Seric 				syslog(LOG_WARNING,
162268350Seric 				  "%s:Lookup error, expected 1 entry, got (%d)",
162368350Seric 				    map->map_file, count);
162468350Seric 
162568350Seric 			/* ignore second entry */
162668350Seric 			if (tTd(38, 20))
162768350Seric 				printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
162868350Seric 					name, count);
162968350Seric 		}
163068350Seric 
163168350Seric 		vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
163268350Seric 		/* set the length of the result */
163368350Seric 		if (vp == NULL)
163468350Seric 			vp = "";
163568350Seric 		vsize = strlen(vp);
163668350Seric 		if (tTd(38, 20))
163768350Seric 			printf("nisplus_map_lookup(%s), found %s\n",
163868350Seric 				name, vp);
163968350Seric 		if (bitset(MF_MATCHONLY, map->map_mflags))
164068350Seric 			str = map_rewrite(map, name, strlen(name), NULL);
164168350Seric 		else
164268350Seric 			str = map_rewrite(map, vp, vsize, av);
164368350Seric 		nis_freeresult(result);
164468350Seric #ifdef MAP_EXIT_STAT
164568350Seric 		*statp = EX_OK;
164668350Seric #endif
164768350Seric 		return str;
164868350Seric 	}
164968350Seric 	else
165068350Seric 	{
165168350Seric #ifdef MAP_EXIT_STAT
165268350Seric 		if (result->status == NIS_NOTFOUND)
165368350Seric 			*statp = EX_NOTFOUND;
165468350Seric 		else if (result->status == NIS_TRYAGAIN)
165568350Seric 			*statp = EX_TEMPFAIL;
165668350Seric 		else
165768350Seric 		{
165868350Seric 			*statp = EX_UNAVAILABLE;
165968350Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
166068350Seric 		}
166168350Seric #else
166268350Seric 		if ((result->status != NIS_NOTFOUND) &&
166368350Seric 		    (result->status != NIS_TRYAGAIN))
166468350Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
166568350Seric #endif
166668350Seric 	}
166768350Seric 	if (tTd(38, 20))
166868350Seric 		printf("nisplus_map_lookup(%s), failed\n", name);
166968350Seric 	nis_freeresult(result);
167068350Seric 	return NULL;
167167848Seric }
167267848Seric 
167368350Seric 
167469401Seric 
167569401Seric /*
167669401Seric **  NISPLUS_GETCANONNAME -- look up canonical name in NIS+
167769401Seric */
167869401Seric 
167969401Seric bool
168069401Seric nisplus_getcanonname(name, hbsize, statp)
168169401Seric 	char *name;
168269401Seric 	int hbsize;
168369401Seric 	int *statp;
168469401Seric {
168569401Seric 	char *vp;
168669401Seric 	auto int vsize;
168769401Seric 	int buflen;
168869401Seric 	nis_result *result;
168969401Seric 	char *p;
169069401Seric 	int len;
169169780Seric 	char nbuf[MAXNAME + 1];
169269780Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
169369401Seric 
169469780Seric 	if (strlen(name) >= sizeof nbuf)
169569780Seric 	{
169669780Seric 		*statp = EX_UNAVAILABLE;
169769780Seric 		return FALSE;
169869780Seric 	}
169969780Seric 	(void) strcpy(nbuf, name);
170069780Seric 	shorten_hostname(nbuf);
170169401Seric 
170269780Seric 	p = strchr(nbuf, '.');
170369401Seric 	if (p == NULL)
170469401Seric 	{
170569401Seric 		/* single token */
170669780Seric 		sprintf(qbuf, "[name=%s],hosts.org_dir", nbuf);
170769401Seric 	}
170869401Seric 	else if (p[1] != '\0')
170969401Seric 	{
171069780Seric 		/* multi token -- take only first token in nbuf */
171169401Seric 		*p = '\0';
171269780Seric 		sprintf(qbuf, "[name=%s],hosts.org_dir.%s", nbuf, &p[1]);
171369401Seric 	}
171469401Seric 	else
171569401Seric 	{
171669401Seric 		*statp = EX_NOHOST;
171769401Seric 		return FALSE;
171869401Seric 	}
171969401Seric 
172069401Seric 	if (tTd(38, 20))
172169478Seric 		printf("\nnisplus_getcanoname(%s), qbuf=%s\n",
172269780Seric 			 name, qbuf);
172369401Seric 
172469780Seric 	result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH,
172569401Seric 		NULL, NULL);
172669401Seric 
172769401Seric 	if (result->status == NIS_SUCCESS)
172869401Seric 	{
172969401Seric 		int count;
173069401Seric 		char *str;
173169401Seric 		char *domain;
173269401Seric 
173369401Seric 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
173469401Seric 		{
173569401Seric #ifdef LOG
173669401Seric 			if (LogLevel > 10)
173769401Seric 				syslog(LOG_WARNING,
173869401Seric 				       "nisplus_getcanonname: Lookup error, expected 1 entry, got (%d)",
173969401Seric 				       count);
174069401Seric #endif
174169401Seric 
174269401Seric 			/* ignore second entry */
174369401Seric 			if (tTd(38, 20))
174469401Seric 				printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name);
174569401Seric 		}
174669401Seric 
174769401Seric 		if (tTd(38, 20))
174869401Seric 			printf("nisplus_getcanoname(%s), found in directory \"%s\"\n",
174969401Seric 			       name, (NIS_RES_OBJECT(result))->zo_domain);
175069401Seric 
175169401Seric 
175269401Seric 		vp = ((NIS_RES_OBJECT(result))->EN_col(0));
175369401Seric 		vsize = strlen(vp);
175469401Seric 		if (tTd(38, 20))
175569401Seric 			printf("nisplus_getcanonname(%s), found %s\n",
175669401Seric 				name, vp);
175769703Seric 		if (strchr(vp, '.') != NULL)
175869703Seric 		{
175969636Seric 			domain = "";
176069703Seric 		}
176169703Seric 		else
176269703Seric 		{
176369703Seric 			domain = macvalue('m', CurEnv);
176469703Seric 			if (domain == NULL)
176569703Seric 				domain = "";
176669703Seric 		}
176769636Seric 		if (hbsize > vsize + (int) strlen(domain) + 1)
176869401Seric 		{
176969636Seric 			if (domain[0] == '\0')
177069636Seric 				strcpy(name, vp);
177169636Seric 			else
177269636Seric 				sprintf(name, "%s.%s", vp, domain);
177369401Seric 			*statp = EX_OK;
177469401Seric 		}
177569401Seric 		else
177669401Seric 			*statp = EX_NOHOST;
177769401Seric 		nis_freeresult(result);
177869401Seric 		return TRUE;
177969401Seric 	}
178069401Seric 	else
178169401Seric 	{
178269401Seric 		if (result->status == NIS_NOTFOUND)
178369401Seric 			*statp = EX_NOHOST;
178469401Seric 		else if (result->status == NIS_TRYAGAIN)
178569401Seric 			*statp = EX_TEMPFAIL;
178669401Seric 		else
178769401Seric 			*statp = EX_UNAVAILABLE;
178869401Seric 	}
178969401Seric 	if (tTd(38, 20))
179069401Seric 		printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
179169401Seric 			name, result->status, *statp);
179269401Seric 	nis_freeresult(result);
179369401Seric 	return FALSE;
179469401Seric }
179569401Seric 
179669401Seric 
179768350Seric char *
179868350Seric nisplus_default_domain()
179968350Seric {
180068528Seric 	static char default_domain[MAXNAME + 1] = "";
180168350Seric 	char *p;
180268350Seric 
180368350Seric 	if (default_domain[0] != '\0')
180468350Seric 		return(default_domain);
180568350Seric 
180668458Seric 	p = nis_local_directory();
180768350Seric 	strcpy(default_domain, p);
180868458Seric 	return default_domain;
180968350Seric }
181068350Seric 
181168350Seric #endif /* NISPLUS */
181267848Seric /*
181368350Seric **  HESIOD Modules
181468350Seric */
181568350Seric 
181668350Seric #ifdef HESIOD
181768350Seric 
181868350Seric #include <hesiod.h>
181968350Seric 
182068350Seric char *
182168350Seric hes_map_lookup(map, name, av, statp)
182268350Seric         MAP *map;
182368350Seric         char *name;
182468350Seric         char **av;
182568350Seric         int *statp;
182668350Seric {
182768350Seric 	char **hp;
182868350Seric 
182968350Seric 	if (tTd(38, 20))
183068350Seric 		printf("hes_map_lookup(%s, %s)\n", map->map_file, name);
183168350Seric 
183269688Seric 	if (name[0] == '\\')
183369688Seric 	{
183469688Seric 		char *np;
183569688Seric 		int nl;
183669688Seric 		char nbuf[MAXNAME];
183769688Seric 
183869688Seric 		nl = strlen(name);
183969688Seric 		if (nl < sizeof nbuf - 1)
184069688Seric 			np = nbuf;
184169688Seric 		else
184269688Seric 			np = xalloc(strlen(name) + 2);
184369688Seric 		np[0] = '\\';
184469688Seric 		strcpy(&np[1], name);
184569688Seric 		hp = hes_resolve(np, map->map_file);
184669688Seric 		if (np != nbuf)
184769688Seric 			free(np);
184869688Seric 	}
184969688Seric 	else
185069688Seric 	{
185169688Seric 		hp = hes_resolve(name, map->map_file);
185269688Seric 	}
185369623Seric 	if (hp == NULL || hp[0] == NULL)
185468350Seric 		return NULL;
185568350Seric 
185669623Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
185769623Seric 		return map_rewrite(map, name, strlen(name), NULL);
185869623Seric 	else
185969623Seric 		return map_rewrite(map, hp[0], strlen(hp[0]), av);
186068350Seric }
186168350Seric 
186268350Seric #endif
186368350Seric /*
186468350Seric **  NeXT NETINFO Modules
186568350Seric */
186668350Seric 
186768350Seric #ifdef NETINFO
186868350Seric 
186968350Seric #define NETINFO_DEFAULT_DIR		"/aliases"
187068350Seric #define NETINFO_DEFAULT_PROPERTY	"members"
187168350Seric 
187268350Seric 
187368350Seric /*
187468350Seric **  NI_MAP_OPEN -- open NetInfo Aliases
187568350Seric */
187668350Seric 
187768350Seric bool
187868350Seric ni_map_open(map, mode)
187968350Seric 	MAP *map;
188068350Seric 	int mode;
188168350Seric {
188268350Seric 	char *p;
188368350Seric 
188468350Seric 	if (tTd(38, 20))
188568350Seric 		printf("ni_map_open: %s\n", map->map_file);
188668350Seric 
188768350Seric 	if (*map->map_file == '\0')
188868350Seric 		map->map_file = NETINFO_DEFAULT_DIR;
188968350Seric 
189068350Seric 	if (map->map_valcolnm == NULL)
189168350Seric 		map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
189268350Seric 
189368350Seric 	if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags))
189468350Seric 		map->map_coldelim = ',';
189568350Seric 
189668350Seric 	return TRUE;
189768350Seric }
189868350Seric 
189968350Seric 
190068350Seric /*
190168350Seric **  NI_MAP_LOOKUP -- look up a datum in NetInfo
190268350Seric */
190368350Seric 
190468350Seric char *
190568350Seric ni_map_lookup(map, name, av, statp)
190668350Seric 	MAP *map;
190768350Seric 	char *name;
190868350Seric 	char **av;
190968350Seric 	int *statp;
191068350Seric {
191168350Seric 	char *res;
191268350Seric 	char *propval;
191368350Seric 	extern char *ni_propval();
191468350Seric 
191568350Seric 	if (tTd(38, 20))
191668350Seric 		printf("ni_map_lookup(%s, %s)\n",
191768350Seric 			map->map_mname, name);
191868350Seric 
191968350Seric 	propval = ni_propval(map->map_file, map->map_keycolnm, name,
192068350Seric 			     map->map_valcolnm, map->map_coldelim);
192168350Seric 
192268350Seric 	if (propval == NULL)
192368350Seric 		return NULL;
192468350Seric 
192568350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
192668350Seric 		res = map_rewrite(map, name, strlen(name), NULL);
192768350Seric 	else
192868350Seric 		res = map_rewrite(map, propval, strlen(propval), av);
192968350Seric 	free(propval);
193068350Seric 	return res;
193168350Seric }
193268350Seric 
193368350Seric #endif
193468350Seric /*
193568350Seric **  TEXT (unindexed text file) Modules
193668350Seric **
193768350Seric **	This code donated by Sun Microsystems.
193868350Seric */
193968350Seric 
194068350Seric 
194168350Seric /*
194268350Seric **  TEXT_MAP_OPEN -- open text table
194368350Seric */
194468350Seric 
194568350Seric bool
194668350Seric text_map_open(map, mode)
194768350Seric 	MAP *map;
194868350Seric 	int mode;
194968350Seric {
195068350Seric 	struct stat sbuf;
195168350Seric 
195268350Seric 	if (tTd(38, 2))
195368350Seric 		printf("text_map_open(%s, %s, %d)\n",
195468350Seric 			map->map_mname, map->map_file, mode);
195568350Seric 
195668350Seric 	if (mode != O_RDONLY)
195768350Seric 	{
195868350Seric 		errno = ENODEV;
195968350Seric 		return FALSE;
196068350Seric 	}
196168350Seric 
196268350Seric 	if (*map->map_file == '\0')
196368350Seric 	{
196468350Seric 		if (tTd(38, 2))
196568350Seric 			printf("text_map_open: file name required\n");
196668350Seric 		return FALSE;
196768350Seric 	}
196868350Seric 
196968350Seric 	if (map->map_file[0] != '/')
197068350Seric 	{
197168350Seric 		if (tTd(38, 2))
197268350Seric 			printf("text_map_open(%s): file name must be fully qualified\n",
197368350Seric 				map->map_file);
197468350Seric 		return FALSE;
197568350Seric 	}
197668350Seric 	/* check to see if this map actually accessable */
197768350Seric 	if (access(map->map_file, R_OK) <0)
197868350Seric 		return FALSE;
197968350Seric 
198068350Seric 	/* check to see if this map actually exist */
198168350Seric 	if (stat(map->map_file, &sbuf) <0)
198268350Seric 	{
198368350Seric 		if (tTd(38, 2))
198468350Seric 			printf("text_map_open(%s): can not stat %s\n",
198568350Seric 				map->map_file, map->map_file);
198668350Seric 		return FALSE;
198768350Seric 	}
198868350Seric 
198968350Seric 	if (!S_ISREG(sbuf.st_mode))
199068350Seric 	{
199168350Seric 		if (tTd(38, 2))
199268350Seric 			printf("text_map_open(%s): %s is not a file\n",
199368350Seric 				map->map_file, map->map_file);
199468350Seric 		return FALSE;
199568350Seric 	}
199668350Seric 
199768350Seric 	if (map->map_keycolnm == NULL)
199868350Seric 		map->map_keycolno = 0;
199968350Seric 	else
200068350Seric 	{
200168350Seric 		if (!isdigit(*map->map_keycolnm))
200268350Seric 		{
200368350Seric 			if (tTd(38, 2))
200468350Seric 				printf("text_map_open(%s): -k should specify a number, not %s\n",
200568350Seric 					map->map_file, map->map_keycolnm);
200668350Seric 			return FALSE;
200768350Seric 		}
200868350Seric 		map->map_keycolno = atoi(map->map_keycolnm);
200968350Seric 	}
201068350Seric 
201168350Seric 	if (map->map_valcolnm == NULL)
201268350Seric 		map->map_valcolno = 0;
201368350Seric 	else
201468350Seric 	{
201568350Seric 		if (!isdigit(*map->map_valcolnm))
201668350Seric 		{
201768350Seric 			if (tTd(38, 2))
201868350Seric 				printf("text_map_open(%s): -v should specify a number, not %s\n",
201968350Seric 					map->map_file, map->map_valcolnm);
202068350Seric 			return FALSE;
202168350Seric 		}
202268350Seric 		map->map_valcolno = atoi(map->map_valcolnm);
202368350Seric 	}
202468350Seric 
202568350Seric 	if (tTd(38, 2))
202668350Seric 	{
202768520Seric 		printf("text_map_open(%s): delimiter = ",
202868520Seric 			map->map_file);
202968520Seric 		if (map->map_coldelim == '\0')
203068520Seric 			printf("(white space)\n");
203168520Seric 		else
203268520Seric 			printf("%c\n", map->map_coldelim);
203368350Seric 	}
203468350Seric 
203568350Seric 	return TRUE;
203668350Seric }
203768350Seric 
203868350Seric 
203968350Seric /*
204068350Seric **  TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
204168350Seric */
204268350Seric 
204368350Seric char *
204468350Seric text_map_lookup(map, name, av, statp)
204568350Seric 	MAP *map;
204668350Seric 	char *name;
204768350Seric 	char **av;
204868350Seric 	int *statp;
204968350Seric {
205068350Seric 	char *vp;
205168350Seric 	auto int vsize;
205268350Seric 	int buflen;
205368350Seric 	char search_key[MAXNAME + 1];
205468350Seric 	char linebuf[MAXLINE];
205568350Seric 	FILE *f;
205668528Seric 	char buf[MAXNAME + 1];
205768350Seric 	char delim;
205868350Seric 	int key_idx;
205968350Seric 	bool found_it;
206068350Seric 	extern char *get_column();
206168350Seric 
206268350Seric 
206368350Seric 	found_it = FALSE;
206468350Seric 	if (tTd(38, 20))
206568350Seric 		printf("text_map_lookup(%s)\n", name);
206668350Seric 
206768350Seric 	buflen = strlen(name);
206868350Seric 	if (buflen > sizeof search_key - 1)
206968350Seric 		buflen = sizeof search_key - 1;
207068350Seric 	bcopy(name, search_key, buflen + 1);
207168350Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
207268350Seric 		makelower(search_key);
207368350Seric 
207468350Seric 	f = fopen(map->map_file, "r");
207568350Seric 	if (f == NULL)
207668350Seric 	{
207768350Seric 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
207868350Seric 		*statp = EX_UNAVAILABLE;
207968350Seric 		return NULL;
208068350Seric 	}
208168350Seric 	key_idx = map->map_keycolno;
208268350Seric 	delim = map->map_coldelim;
208368350Seric 	while (fgets(linebuf, MAXLINE, f))
208468350Seric 	{
208568350Seric 		char *lf;
208668350Seric 		if (linebuf[0] == '#')
208768350Seric 			continue; /* skip comment line */
208868350Seric 		if (lf = strchr(linebuf, '\n'))
208968350Seric 			*lf = '\0';
209068350Seric 		if (!strcasecmp(search_key,
209168350Seric 				get_column(linebuf, key_idx, delim, buf)))
209268350Seric 		{
209368350Seric 			found_it = TRUE;
209468350Seric 			break;
209568350Seric 		}
209668350Seric 	}
209768350Seric 	fclose(f);
209868350Seric 	if (!found_it)
209968350Seric 	{
210068350Seric #ifdef MAP_EXIT_STAT
210168350Seric 		*statp = EX_NOTFOUND;
210268350Seric #endif
210368350Seric 		return(NULL);
210468350Seric 	}
210568350Seric 	vp = get_column(linebuf, map->map_valcolno, delim, buf);
210668350Seric 	vsize = strlen(vp);
210768350Seric #ifdef MAP_EXIT_STAT
210868350Seric 	*statp = EX_OK;
210968350Seric #endif
211068350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
211168350Seric 		return map_rewrite(map, name, strlen(name), NULL);
211268350Seric 	else
211368350Seric 		return map_rewrite(map, vp, vsize, av);
211468350Seric }
211569401Seric 
211669401Seric 
211769401Seric /*
211869401Seric **  TEXT_GETCANONNAME -- look up canonical name in hosts file
211969401Seric */
212069401Seric 
212169401Seric bool
212269401Seric text_getcanonname(name, hbsize, statp)
212369401Seric 	char *name;
212469401Seric 	int hbsize;
212569401Seric 	int *statp;
212669401Seric {
212769401Seric 	int key_idx;
212869401Seric 	char *cname;
212969401Seric 	bool found;
213069401Seric 	FILE *f;
213169401Seric 	char linebuf[MAXLINE];
213269401Seric 	char cbuf[MAXNAME + 1];
213369780Seric 	char fbuf[MAXNAME + 1];
213469780Seric 	char nbuf[MAXNAME + 1];
213569401Seric 	extern char *get_column();
213669401Seric 
213769780Seric 	if (strlen(name) >= sizeof nbuf)
213869780Seric 	{
213969780Seric 		*statp = EX_UNAVAILABLE;
214069780Seric 		return FALSE;
214169780Seric 	}
214269780Seric 	(void) strcpy(nbuf, name);
214369780Seric 	shorten_hostname(nbuf);
214469401Seric 
214569401Seric 	/* we only accept single token search key */
214669780Seric 	if (strchr(nbuf, '.') != NULL)
214769401Seric 	{
214869401Seric 		*statp = EX_NOHOST;
214969401Seric 		return FALSE;
215069401Seric 	}
215169401Seric 
215269401Seric 	found = FALSE;
215369401Seric 
215469401Seric 	f = fopen(HostsFile, "r");
215569401Seric 	if (f == NULL)
215669401Seric 	{
215769401Seric #ifdef MAP_EXIT_STAT
215869401Seric 		*statp = EX_UNAVAILABLE;
215969401Seric #endif
216069401Seric 		return FALSE;
216169401Seric 	}
216269401Seric 	while (!found && fgets(linebuf, MAXLINE, f) != NULL)
216369401Seric 	{
216469401Seric 		char *p;
216569401Seric 
216669401Seric 		if (linebuf[0] == '#')
216769401Seric 			continue;
216869401Seric 		if ((p = strchr(linebuf, '\n')) != NULL)
216969401Seric 			*p = '\0';
217069663Seric 		cname = get_column(linebuf, 1, '\0', cbuf);
217169780Seric 		if (cname != NULL && strcasecmp(nbuf,  cname) == 0)
217269401Seric 		{
217369401Seric 			found = TRUE;
217469401Seric 			break;
217569401Seric 		}
217669401Seric 
217769401Seric 		key_idx = 2;
217869780Seric 		while ((p = get_column(linebuf, key_idx, '\0', fbuf)) != NULL)
217969401Seric 		{
218069780Seric 			if (strcasecmp(nbuf, p) == 0)
218169401Seric 			{
218269401Seric 				found = TRUE;
218369401Seric 				break;
218469401Seric 			}
218569401Seric 			key_idx++;
218669401Seric 		}
218769401Seric 	}
218869401Seric 	fclose(f);
218969401Seric 	if (!found)
219069401Seric 	{
219169401Seric 		*statp = EX_NOHOST;
219269401Seric 		return FALSE;
219369401Seric 	}
219469401Seric 
219569401Seric 	if (hbsize >= strlen(cname))
219669401Seric 	{
219769401Seric 		strcpy(name, cname);
219869401Seric 		*statp = EX_OK;
219969401Seric 		return TRUE;
220069401Seric 	}
220169401Seric 	*statp = EX_UNAVAILABLE;
220269401Seric 	return FALSE;
220369401Seric }
220468350Seric /*
220560089Seric **  STAB (Symbol Table) Modules
220660089Seric */
220760089Seric 
220860089Seric 
220960089Seric /*
221060207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
221160089Seric */
221260089Seric 
221360089Seric char *
221461707Seric stab_map_lookup(map, name, av, pstat)
221560089Seric 	register MAP *map;
221660089Seric 	char *name;
221761707Seric 	char **av;
221861707Seric 	int *pstat;
221960089Seric {
222060089Seric 	register STAB *s;
222160089Seric 
222260537Seric 	if (tTd(38, 20))
222368350Seric 		printf("stab_lookup(%s, %s)\n",
222468350Seric 			map->map_mname, name);
222560089Seric 
222660089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
222760089Seric 	if (s != NULL)
222860089Seric 		return (s->s_alias);
222960089Seric 	return (NULL);
223060089Seric }
223160089Seric 
223260089Seric 
223360089Seric /*
223460207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
223560089Seric */
223660089Seric 
223760089Seric void
223860089Seric stab_map_store(map, lhs, rhs)
223960089Seric 	register MAP *map;
224060089Seric 	char *lhs;
224160089Seric 	char *rhs;
224260089Seric {
224360089Seric 	register STAB *s;
224460089Seric 
224560089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
224660089Seric 	s->s_alias = newstr(rhs);
224760089Seric }
224860089Seric 
224960089Seric 
225060089Seric /*
225160207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
225260207Seric **
225360207Seric **	This is a wierd case -- it is only intended as a fallback for
225460207Seric **	aliases.  For this reason, opens for write (only during a
225560207Seric **	"newaliases") always fails, and opens for read open the
225660207Seric **	actual underlying text file instead of the database.
225760089Seric */
225860089Seric 
225960089Seric bool
226060089Seric stab_map_open(map, mode)
226160089Seric 	register MAP *map;
226260089Seric 	int mode;
226360089Seric {
226463835Seric 	FILE *af;
226564284Seric 	struct stat st;
226663835Seric 
226760537Seric 	if (tTd(38, 2))
226868350Seric 		printf("stab_map_open(%s, %s)\n",
226968350Seric 			map->map_mname, map->map_file);
227060089Seric 
227160089Seric 	if (mode != O_RDONLY)
227260207Seric 	{
227360207Seric 		errno = ENODEV;
227460089Seric 		return FALSE;
227560207Seric 	}
227660089Seric 
227763835Seric 	af = fopen(map->map_file, "r");
227863835Seric 	if (af == NULL)
227963835Seric 		return FALSE;
228068350Seric 	readaliases(map, af, FALSE, FALSE);
228164284Seric 
228264284Seric 	if (fstat(fileno(af), &st) >= 0)
228364284Seric 		map->map_mtime = st.st_mtime;
228463835Seric 	fclose(af);
228563835Seric 
228660089Seric 	return TRUE;
228760089Seric }
228860089Seric /*
228960089Seric **  Implicit Modules
229056822Seric **
229160089Seric **	Tries several types.  For back compatibility of aliases.
229256822Seric */
229356822Seric 
229460089Seric 
229560089Seric /*
229660207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
229760089Seric */
229860089Seric 
229960089Seric char *
230060089Seric impl_map_lookup(map, name, av, pstat)
230160089Seric 	MAP *map;
230260089Seric 	char *name;
230356822Seric 	char **av;
230460089Seric 	int *pstat;
230556822Seric {
230660537Seric 	if (tTd(38, 20))
230768350Seric 		printf("impl_map_lookup(%s, %s)\n",
230868350Seric 			map->map_mname, name);
230956822Seric 
231060089Seric #ifdef NEWDB
231160207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
231260089Seric 		return db_map_lookup(map, name, av, pstat);
231360089Seric #endif
231460089Seric #ifdef NDBM
231560207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
231660089Seric 		return ndbm_map_lookup(map, name, av, pstat);
231760089Seric #endif
231860089Seric 	return stab_map_lookup(map, name, av, pstat);
231960089Seric }
232060089Seric 
232160089Seric /*
232260207Seric **  IMPL_MAP_STORE -- store in open databases
232360089Seric */
232460089Seric 
232560089Seric void
232660089Seric impl_map_store(map, lhs, rhs)
232760089Seric 	MAP *map;
232860089Seric 	char *lhs;
232960089Seric 	char *rhs;
233060089Seric {
233160089Seric #ifdef NEWDB
233260207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
233360089Seric 		db_map_store(map, lhs, rhs);
233460089Seric #endif
233560089Seric #ifdef NDBM
233660207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
233760089Seric 		ndbm_map_store(map, lhs, rhs);
233860089Seric #endif
233960089Seric 	stab_map_store(map, lhs, rhs);
234060089Seric }
234160089Seric 
234260089Seric /*
234360089Seric **  IMPL_MAP_OPEN -- implicit database open
234460089Seric */
234560089Seric 
234660089Seric bool
234760089Seric impl_map_open(map, mode)
234860089Seric 	MAP *map;
234960089Seric 	int mode;
235060089Seric {
235160089Seric 	struct stat stb;
235260089Seric 
235360537Seric 	if (tTd(38, 2))
235468350Seric 		printf("impl_map_open(%s, %s, %d)\n",
235568350Seric 			map->map_mname, map->map_file, mode);
235660089Seric 
235760089Seric 	if (stat(map->map_file, &stb) < 0)
235856822Seric 	{
235960089Seric 		/* no alias file at all */
236064718Seric 		if (tTd(38, 3))
236164718Seric 			printf("no map file\n");
236260089Seric 		return FALSE;
236356822Seric 	}
236456822Seric 
236560089Seric #ifdef NEWDB
236660207Seric 	map->map_mflags |= MF_IMPL_HASH;
236760089Seric 	if (hash_map_open(map, mode))
236856822Seric 	{
236964250Seric #if defined(NDBM) && defined(NIS)
237069651Seric 		if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
237160207Seric #endif
237260207Seric 			return TRUE;
237360089Seric 	}
237460207Seric 	else
237560207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
237660089Seric #endif
237760089Seric #ifdef NDBM
237860207Seric 	map->map_mflags |= MF_IMPL_NDBM;
237960089Seric 	if (ndbm_map_open(map, mode))
238060089Seric 	{
238160089Seric 		return TRUE;
238260089Seric 	}
238360207Seric 	else
238460207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
238560089Seric #endif
238656822Seric 
238764650Seric #if defined(NEWDB) || defined(NDBM)
238860089Seric 	if (Verbose)
238960089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
239064964Seric #else
239164964Seric 	if (mode != O_RDONLY)
239264964Seric 		usrerr("Cannot rebuild aliases: no database format defined");
239360207Seric #endif
239460089Seric 
239560207Seric 	return stab_map_open(map, mode);
239656822Seric }
239760089Seric 
239860207Seric 
239960089Seric /*
240060207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
240160089Seric */
240260089Seric 
240360089Seric void
240460207Seric impl_map_close(map)
240560089Seric 	MAP *map;
240660089Seric {
240768350Seric 	if (tTd(38, 20))
240868350Seric 		printf("impl_map_close(%s, %s, %x)\n",
240968350Seric 			map->map_mname, map->map_file, map->map_mflags);
241060089Seric #ifdef NEWDB
241160207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
241260089Seric 	{
241360207Seric 		db_map_close(map);
241460207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
241560089Seric 	}
241660089Seric #endif
241760089Seric 
241860089Seric #ifdef NDBM
241960207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
242060089Seric 	{
242160207Seric 		ndbm_map_close(map);
242260207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
242360089Seric 	}
242460089Seric #endif
242560089Seric }
242660207Seric /*
242768350Seric **  User map class.
242868350Seric **
242968350Seric **	Provides access to the system password file.
243068350Seric */
243168350Seric 
243268350Seric /*
243368350Seric **  USER_MAP_OPEN -- open user map
243468350Seric **
243568350Seric **	Really just binds field names to field numbers.
243668350Seric */
243768350Seric 
243868350Seric bool
243968350Seric user_map_open(map, mode)
244068350Seric 	MAP *map;
244168350Seric 	int mode;
244268350Seric {
244368350Seric 	if (tTd(38, 2))
244468350Seric 		printf("user_map_open(%s)\n", map->map_mname);
244568350Seric 
244668350Seric 	if (mode != O_RDONLY)
244768350Seric 	{
244868350Seric 		/* issue a pseudo-error message */
244968350Seric #ifdef ENOSYS
245068350Seric 		errno = ENOSYS;
245168350Seric #else
245268350Seric # ifdef EFTYPE
245368350Seric 		errno = EFTYPE;
245468350Seric # else
245568350Seric 		errno = ENXIO;
245668350Seric # endif
245768350Seric #endif
245868350Seric 		return FALSE;
245968350Seric 	}
246068350Seric 	if (map->map_valcolnm == NULL)
246168350Seric 		/* nothing */ ;
246268350Seric 	else if (strcasecmp(map->map_valcolnm, "name") == 0)
246368350Seric 		map->map_valcolno = 1;
246468350Seric 	else if (strcasecmp(map->map_valcolnm, "passwd") == 0)
246568350Seric 		map->map_valcolno = 2;
246668350Seric 	else if (strcasecmp(map->map_valcolnm, "uid") == 0)
246768350Seric 		map->map_valcolno = 3;
246868350Seric 	else if (strcasecmp(map->map_valcolnm, "gid") == 0)
246968350Seric 		map->map_valcolno = 4;
247068350Seric 	else if (strcasecmp(map->map_valcolnm, "gecos") == 0)
247168350Seric 		map->map_valcolno = 5;
247268350Seric 	else if (strcasecmp(map->map_valcolnm, "dir") == 0)
247368350Seric 		map->map_valcolno = 6;
247468350Seric 	else if (strcasecmp(map->map_valcolnm, "shell") == 0)
247568350Seric 		map->map_valcolno = 7;
247668350Seric 	else
247768350Seric 	{
247868350Seric 		syserr("User map %s: unknown column name %s",
247968350Seric 			map->map_mname, map->map_valcolnm);
248068350Seric 		return FALSE;
248168350Seric 	}
248268350Seric 	return TRUE;
248368350Seric }
248468350Seric 
248568350Seric 
248668350Seric /*
248768350Seric **  USER_MAP_LOOKUP -- look up a user in the passwd file.
248868350Seric */
248968350Seric 
249068350Seric char *
249168350Seric user_map_lookup(map, key, av, statp)
249268350Seric 	MAP *map;
249368350Seric 	char *key;
249468350Seric 	char **av;
249568350Seric 	int *statp;
249668350Seric {
249768350Seric 	struct passwd *pw;
249868350Seric 
249968350Seric 	if (tTd(38, 20))
250068350Seric 		printf("user_map_lookup(%s, %s)\n",
250168350Seric 			map->map_mname, key);
250268350Seric 
250368693Seric 	pw = sm_getpwnam(key);
250468350Seric 	if (pw == NULL)
250568350Seric 		return NULL;
250668350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
250768350Seric 		return map_rewrite(map, key, strlen(key), NULL);
250868350Seric 	else
250968350Seric 	{
251068433Seric 		char *rwval = NULL;
251168350Seric 		char buf[30];
251268350Seric 
251368350Seric 		switch (map->map_valcolno)
251468350Seric 		{
251568350Seric 		  case 0:
251668350Seric 		  case 1:
251768350Seric 			rwval = pw->pw_name;
251868350Seric 			break;
251968350Seric 
252068350Seric 		  case 2:
252168350Seric 			rwval = pw->pw_passwd;
252268350Seric 			break;
252368350Seric 
252468350Seric 		  case 3:
252568350Seric 			sprintf(buf, "%d", pw->pw_uid);
252668350Seric 			rwval = buf;
252768350Seric 			break;
252868350Seric 
252968350Seric 		  case 4:
253068350Seric 			sprintf(buf, "%d", pw->pw_gid);
253168350Seric 			rwval = buf;
253268350Seric 			break;
253368350Seric 
253468350Seric 		  case 5:
253568350Seric 			rwval = pw->pw_gecos;
253668350Seric 			break;
253768350Seric 
253868350Seric 		  case 6:
253968350Seric 			rwval = pw->pw_dir;
254068350Seric 			break;
254168350Seric 
254268350Seric 		  case 7:
254368350Seric 			rwval = pw->pw_shell;
254468350Seric 			break;
254568350Seric 		}
254668350Seric 		return map_rewrite(map, rwval, strlen(rwval), av);
254768350Seric 	}
254868350Seric }
254968350Seric /*
255068350Seric **  BESTMX -- find the best MX for a name
255168350Seric **
255268350Seric **	This is really a hack, but I don't see any obvious way
255368350Seric **	to generalize it at the moment.
255468350Seric */
255568350Seric 
255668350Seric #if NAMED_BIND
255768350Seric 
255868350Seric char *
255968350Seric bestmx_map_lookup(map, name, av, statp)
256068350Seric 	MAP *map;
256168350Seric 	char *name;
256268350Seric 	char **av;
256368350Seric 	int *statp;
256468350Seric {
256568350Seric         int nmx;
256668350Seric         auto int rcode;
256768350Seric         char *mxhosts[MAXMXHOSTS + 1];
256868350Seric 
256968350Seric 	nmx = getmxrr(name, mxhosts, FALSE, &rcode);
257068350Seric 	if (nmx <= 0)
257168350Seric 		return NULL;
257268350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
257368350Seric 		return map_rewrite(map, name, strlen(name), NULL);
257468350Seric 	else
257568350Seric 		return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av);
257668350Seric }
257768350Seric 
257868350Seric #endif
257968350Seric /*
258069453Seric **  Program map type.
258169453Seric **
258269453Seric **	This provides access to arbitrary programs.  It should be used
258369453Seric **	only very sparingly, since there is no way to bound the cost
258469453Seric **	of invoking an arbitrary program.
258569453Seric */
258669453Seric 
258769453Seric char *
258869453Seric prog_map_lookup(map, name, av, statp)
258969453Seric 	MAP *map;
259069453Seric 	char *name;
259169453Seric 	char **av;
259269453Seric 	int *statp;
259369453Seric {
259469453Seric 	int i;
259569453Seric 	register char *p;
259669453Seric 	int fd;
259769453Seric 	auto pid_t pid;
259869453Seric 	char *argv[MAXPV + 1];
259969453Seric 	char buf[MAXLINE];
260069453Seric 
260169453Seric 	if (tTd(38, 20))
260269453Seric 		printf("prog_map_lookup(%s, %s) %s\n",
260369453Seric 			map->map_mname, name, map->map_file);
260469453Seric 
260569453Seric 	i = 0;
260669453Seric 	argv[i++] = map->map_file;
260769453Seric 	strcpy(buf, map->map_rebuild);
260869453Seric 	for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t"))
260969453Seric 	{
261069453Seric 		if (i >= MAXPV - 1)
261169453Seric 			break;
261269453Seric 		argv[i++] = p;
261369453Seric 	}
261469453Seric 	argv[i++] = name;
261569453Seric 	argv[i] = NULL;
261669453Seric 	pid = prog_open(argv, &fd, CurEnv);
261769453Seric 	if (pid < 0)
261869453Seric 	{
261969453Seric 		if (tTd(38, 9))
262069453Seric 			printf("prog_map_lookup(%s) failed (%s) -- closing",
262169453Seric 				map->map_mname, errstring(errno));
262269453Seric 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
262369453Seric 		return NULL;
262469453Seric 	}
262569453Seric 	i = read(fd, buf, sizeof buf - 1);
262669453Seric 	if (i <= 0 && tTd(38, 2))
262769453Seric 		printf("prog_map_lookup(%s): read error %s\n",
262869562Seric 			map->map_mname, errstring(errno));
262969453Seric 	if (i > 0)
263069453Seric 	{
263169453Seric 		char *rval;
263269453Seric 
263369453Seric 		buf[i] = '\0';
263469453Seric 		p = strchr(buf, '\n');
263569453Seric 		if (p != NULL)
263669453Seric 			*p = '\0';
263769453Seric 
263869453Seric 		/* collect the return value */
263969453Seric 		if (bitset(MF_MATCHONLY, map->map_mflags))
264069453Seric 			rval = map_rewrite(map, name, strlen(name), NULL);
264169453Seric 		else
264269453Seric 			rval = map_rewrite(map, buf, strlen(buf), NULL);
264369453Seric 
264469453Seric 		/* now flush any additional output */
264569453Seric 		while ((i = read(fd, buf, sizeof buf)) > 0)
264669453Seric 			continue;
264769453Seric 		close(fd);
264869453Seric 
264969453Seric 		/* and wait for the process to terminate */
265069453Seric 		*statp = waitfor(pid);
265169453Seric 
265269453Seric 		return rval;
265369453Seric 	}
265469453Seric 
265569453Seric 	close(fd);
265669453Seric 	*statp = waitfor(pid);
265769453Seric 	return NULL;
265869453Seric }
265969453Seric /*
266068350Seric **  Sequenced map type.
266168350Seric **
266268350Seric **	Tries each map in order until something matches, much like
266368350Seric **	implicit.  Stores go to the first map in the list that can
266468350Seric **	support storing.
266568350Seric **
266668350Seric **	This is slightly unusual in that there are two interfaces.
266768350Seric **	The "sequence" interface lets you stack maps arbitrarily.
266868350Seric **	The "switch" interface builds a sequence map by looking
266968350Seric **	at a system-dependent configuration file such as
267068350Seric **	/etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
267168350Seric **
267268350Seric **	We don't need an explicit open, since all maps are
267368350Seric **	opened during startup, including underlying maps.
267468350Seric */
267568350Seric 
267668350Seric /*
267768350Seric **  SEQ_MAP_PARSE -- Sequenced map parsing
267868350Seric */
267968350Seric 
268068350Seric bool
268168350Seric seq_map_parse(map, ap)
268268350Seric 	MAP *map;
268368350Seric 	char *ap;
268468350Seric {
268568350Seric 	int maxmap;
268668350Seric 
268768350Seric 	if (tTd(38, 2))
268868350Seric 		printf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
268968350Seric 	maxmap = 0;
269068350Seric 	while (*ap != '\0')
269168350Seric 	{
269268350Seric 		register char *p;
269368350Seric 		STAB *s;
269468350Seric 
269568350Seric 		/* find beginning of map name */
269668350Seric 		while (isascii(*ap) && isspace(*ap))
269768350Seric 			ap++;
269868350Seric 		for (p = ap; isascii(*p) && isalnum(*p); p++)
269968350Seric 			continue;
270068350Seric 		if (*p != '\0')
270168350Seric 			*p++ = '\0';
270268350Seric 		while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
270368350Seric 			p++;
270468350Seric 		if (*ap == '\0')
270568350Seric 		{
270668350Seric 			ap = p;
270768350Seric 			continue;
270868350Seric 		}
270968350Seric 		s = stab(ap, ST_MAP, ST_FIND);
271068350Seric 		if (s == NULL)
271168350Seric 		{
271268350Seric 			syserr("Sequence map %s: unknown member map %s",
271368350Seric 				map->map_mname, ap);
271468350Seric 		}
271568350Seric 		else if (maxmap == MAXMAPSTACK)
271668350Seric 		{
271768350Seric 			syserr("Sequence map %s: too many member maps (%d max)",
271868350Seric 				map->map_mname, MAXMAPSTACK);
271968350Seric 			maxmap++;
272068350Seric 		}
272168350Seric 		else if (maxmap < MAXMAPSTACK)
272268350Seric 		{
272368350Seric 			map->map_stack[maxmap++] = &s->s_map;
272468350Seric 		}
272568350Seric 		ap = p;
272668350Seric 	}
272768350Seric 	return TRUE;
272868350Seric }
272968350Seric 
273068350Seric 
273168350Seric /*
273268350Seric **  SWITCH_MAP_OPEN -- open a switched map
273368350Seric **
273468350Seric **	This looks at the system-dependent configuration and builds
273568350Seric **	a sequence map that does the same thing.
273668350Seric **
273768350Seric **	Every system must define a switch_map_find routine in conf.c
273868350Seric **	that will return the list of service types associated with a
273968350Seric **	given service class.
274068350Seric */
274168350Seric 
274268350Seric bool
274368350Seric switch_map_open(map, mode)
274468350Seric 	MAP *map;
274568350Seric 	int mode;
274668350Seric {
274768350Seric 	int mapno;
274868350Seric 	int nmaps;
274968350Seric 	char *maptype[MAXMAPSTACK];
275068350Seric 
275168350Seric 	if (tTd(38, 2))
275268350Seric 		printf("switch_map_open(%s, %s, %d)\n",
275368350Seric 			map->map_mname, map->map_file, mode);
275468350Seric 
275568350Seric 	nmaps = switch_map_find(map->map_file, maptype, map->map_return);
275668350Seric 	if (tTd(38, 19))
275768350Seric 	{
275868350Seric 		printf("\tswitch_map_find => %d\n", nmaps);
275968350Seric 		for (mapno = 0; mapno < nmaps; mapno++)
276068350Seric 			printf("\t\t%s\n", maptype[mapno]);
276168350Seric 	}
276268350Seric 	if (nmaps <= 0 || nmaps > MAXMAPSTACK)
276368350Seric 		return FALSE;
276468350Seric 
276568350Seric 	for (mapno = 0; mapno < nmaps; mapno++)
276668350Seric 	{
276768350Seric 		register STAB *s;
276868350Seric 		char nbuf[MAXNAME + 1];
276968350Seric 
277068350Seric 		if (maptype[mapno] == NULL)
277168350Seric 			continue;
277268350Seric 		(void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]);
277368350Seric 		s = stab(nbuf, ST_MAP, ST_FIND);
277468350Seric 		if (s == NULL)
277568350Seric 		{
277668350Seric 			syserr("Switch map %s: unknown member map %s",
277768350Seric 				map->map_mname, nbuf);
277868350Seric 		}
277968350Seric 		else
278068350Seric 		{
278168350Seric 			map->map_stack[mapno] = &s->s_map;
278268350Seric 			if (tTd(38, 4))
278368350Seric 				printf("\tmap_stack[%d] = %s:%s\n",
278468350Seric 					mapno, s->s_map.map_class->map_cname,
278568350Seric 					nbuf);
278668350Seric 		}
278768350Seric 	}
278868350Seric 	return TRUE;
278968350Seric }
279068350Seric 
279168350Seric 
279268350Seric /*
279368350Seric **  SEQ_MAP_CLOSE -- close all underlying maps
279468350Seric */
279568350Seric 
279669748Seric void
279768350Seric seq_map_close(map)
279868350Seric 	MAP *map;
279968350Seric {
280068350Seric 	int mapno;
280168350Seric 
280268350Seric 	if (tTd(38, 20))
280368350Seric 		printf("seq_map_close(%s)\n", map->map_mname);
280468350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
280568350Seric 	{
280668350Seric 		MAP *mm = map->map_stack[mapno];
280768350Seric 
280868350Seric 		if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
280968350Seric 			continue;
281068350Seric 		mm->map_class->map_close(mm);
281168798Seric 		mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
281268350Seric 	}
281368350Seric }
281468350Seric 
281568350Seric 
281668350Seric /*
281768350Seric **  SEQ_MAP_LOOKUP -- sequenced map lookup
281868350Seric */
281968350Seric 
282068350Seric char *
282168350Seric seq_map_lookup(map, key, args, pstat)
282268350Seric 	MAP *map;
282368350Seric 	char *key;
282468350Seric 	char **args;
282568350Seric 	int *pstat;
282668350Seric {
282768350Seric 	int mapno;
282868350Seric 	int mapbit = 0x01;
282968350Seric 
283068350Seric 	if (tTd(38, 20))
283168350Seric 		printf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
283268350Seric 
283368350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
283468350Seric 	{
283568350Seric 		MAP *mm = map->map_stack[mapno];
283668350Seric 		int stat = 0;
283768350Seric 		char *rv;
283868350Seric 
283968350Seric 		if (mm == NULL)
284068350Seric 			continue;
284168350Seric 		if (!bitset(MF_OPEN, mm->map_mflags))
284268350Seric 		{
284368350Seric 			if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
284468350Seric 			{
284568350Seric 				*pstat = EX_UNAVAILABLE;
284668350Seric 				return NULL;
284768350Seric 			}
284868350Seric 			continue;
284968350Seric 		}
285068350Seric 		rv = mm->map_class->map_lookup(mm, key, args, &stat);
285168350Seric 		if (rv != NULL)
285268350Seric 			return rv;
285368350Seric 		if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND]))
285468350Seric 			return NULL;
285568350Seric 		if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN]))
285668350Seric 		{
285768350Seric 			*pstat = stat;
285868350Seric 			return NULL;
285968350Seric 		}
286068350Seric 	}
286168350Seric 	return NULL;
286268350Seric }
286368350Seric 
286468350Seric 
286568350Seric /*
286668350Seric **  SEQ_MAP_STORE -- sequenced map store
286768350Seric */
286868350Seric 
286968350Seric void
287068350Seric seq_map_store(map, key, val)
287168350Seric 	MAP *map;
287268350Seric 	char *key;
287368350Seric 	char *val;
287468350Seric {
287568350Seric 	int mapno;
287668350Seric 
287768350Seric 	if (tTd(38, 12))
287868350Seric 		printf("seq_map_store(%s, %s, %s)\n",
287968350Seric 			map->map_mname, key, val);
288068350Seric 
288168350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
288268350Seric 	{
288368350Seric 		MAP *mm = map->map_stack[mapno];
288468350Seric 
288568350Seric 		if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
288668350Seric 			continue;
288768350Seric 
288868350Seric 		mm->map_class->map_store(mm, key, val);
288968350Seric 		return;
289068350Seric 	}
289168350Seric 	syserr("seq_map_store(%s, %s, %s): no writable map",
289268350Seric 		map->map_mname, key, val);
289368350Seric }
289468350Seric /*
289560207Seric **  NULL stubs
289660089Seric */
289760089Seric 
289860207Seric bool
289960207Seric null_map_open(map, mode)
290060089Seric 	MAP *map;
290160207Seric 	int mode;
290260089Seric {
290360207Seric 	return TRUE;
290460089Seric }
290560089Seric 
290660207Seric void
290760207Seric null_map_close(map)
290860207Seric 	MAP *map;
290960089Seric {
291060207Seric 	return;
291160207Seric }
291260089Seric 
291360207Seric void
291460207Seric null_map_store(map, key, val)
291560207Seric 	MAP *map;
291660207Seric 	char *key;
291760207Seric 	char *val;
291860089Seric {
291960207Seric 	return;
292060089Seric }
292168350Seric 
292268350Seric 
292368350Seric /*
292468350Seric **  BOGUS stubs
292568350Seric */
292668350Seric 
292768350Seric char *
292868350Seric bogus_map_lookup(map, key, args, pstat)
292968350Seric 	MAP *map;
293068350Seric 	char *key;
293168350Seric 	char **args;
293268350Seric 	int *pstat;
293368350Seric {
293468350Seric 	*pstat = EX_TEMPFAIL;
293568350Seric 	return NULL;
293668350Seric }
293768350Seric 
293868350Seric MAPCLASS	BogusMapClass =
293968350Seric {
294068350Seric 	"bogus-map",		NULL,		0,
294168350Seric 	NULL,		bogus_map_lookup,	null_map_store,
294268350Seric 	null_map_open,	null_map_close,
294368350Seric };
2944