xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 68350)
156822Seric /*
256822Seric  * Copyright (c) 1992 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*68350Seric static char sccsid[] = "@(#)map.c	8.42 (Berkeley) 02/17/95";
1156822Seric #endif /* not lint */
1256822Seric 
1356822Seric #include "sendmail.h"
1456822Seric 
1560089Seric #ifdef NDBM
1656822Seric #include <ndbm.h>
1756822Seric #endif
1860089Seric #ifdef NEWDB
1956822Seric #include <db.h>
2056822Seric #endif
2160089Seric #ifdef NIS
2257208Seric #include <rpcsvc/ypclnt.h>
2357208Seric #endif
2456822Seric 
2556822Seric /*
2660089Seric **  MAP.C -- implementations for various map classes.
2756822Seric **
2860089Seric **	Each map class implements a series of functions:
2960089Seric **
3060089Seric **	bool map_parse(MAP *map, char *args)
3160089Seric **		Parse the arguments from the config file.  Return TRUE
3260089Seric **		if they were ok, FALSE otherwise.  Fill in map with the
3360089Seric **		values.
3460089Seric **
3560222Seric **	char *map_lookup(MAP *map, char *key, char **args, int *pstat)
3660222Seric **		Look up the key in the given map.  If found, do any
3760222Seric **		rewriting the map wants (including "args" if desired)
3860089Seric **		and return the value.  Set *pstat to the appropriate status
3960222Seric **		on error and return NULL.  Args will be NULL if called
4060222Seric **		from the alias routines, although this should probably
4160222Seric **		not be relied upon.  It is suggested you call map_rewrite
4260222Seric **		to return the results -- it takes care of null termination
4360222Seric **		and uses a dynamically expanded buffer as needed.
4460089Seric **
4560089Seric **	void map_store(MAP *map, char *key, char *value)
4660089Seric **		Store the key:value pair in the map.
4760089Seric **
4860089Seric **	bool map_open(MAP *map, int mode)
4960222Seric **		Open the map for the indicated mode.  Mode should
5060222Seric **		be either O_RDONLY or O_RDWR.  Return TRUE if it
5160222Seric **		was opened successfully, FALSE otherwise.  If the open
5260222Seric **		failed an the MF_OPTIONAL flag is not set, it should
5360222Seric **		also print an error.  If the MF_ALIAS bit is set
5460222Seric **		and this map class understands the @:@ convention, it
5560222Seric **		should call aliaswait() before returning.
5660089Seric **
5760089Seric **	void map_close(MAP *map)
5860089Seric **		Close the map.
5960089Seric */
6060089Seric 
6160089Seric #define DBMMODE		0644
6264718Seric 
6364718Seric extern bool	aliaswait __P((MAP *, char *, int));
6460089Seric /*
6560089Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
6660089Seric **
6760089Seric **	This is a generic version of the map_parse method.
6860089Seric **
6956822Seric **	Parameters:
7060089Seric **		map -- the map being initialized.
7160089Seric **		ap -- a pointer to the args on the config line.
7256822Seric **
7356822Seric **	Returns:
7460089Seric **		TRUE -- if everything parsed OK.
7556822Seric **		FALSE -- otherwise.
7656822Seric **
7756822Seric **	Side Effects:
7860089Seric **		null terminates the filename; stores it in map
7956822Seric */
8056822Seric 
8156822Seric bool
8260089Seric map_parseargs(map, ap)
8356822Seric 	MAP *map;
8460089Seric 	char *ap;
8556822Seric {
8660089Seric 	register char *p = ap;
8756822Seric 
8863753Seric 	map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
8960089Seric 	for (;;)
9060089Seric 	{
9160089Seric 		while (isascii(*p) && isspace(*p))
9260089Seric 			p++;
9360089Seric 		if (*p != '-')
9460089Seric 			break;
9560089Seric 		switch (*++p)
9660089Seric 		{
9760089Seric 		  case 'N':
9860207Seric 			map->map_mflags |= MF_INCLNULL;
9963753Seric 			map->map_mflags &= ~MF_TRY0NULL;
10060089Seric 			break;
10160089Seric 
10263753Seric 		  case 'O':
10363753Seric 			map->map_mflags &= ~MF_TRY1NULL;
10463753Seric 			break;
10563753Seric 
10660089Seric 		  case 'o':
10760207Seric 			map->map_mflags |= MF_OPTIONAL;
10860089Seric 			break;
10960089Seric 
11060089Seric 		  case 'f':
11160207Seric 			map->map_mflags |= MF_NOFOLDCASE;
11260089Seric 			break;
11360089Seric 
11460089Seric 		  case 'm':
11560207Seric 			map->map_mflags |= MF_MATCHONLY;
11660089Seric 			break;
11760089Seric 
11860089Seric 		  case 'a':
11960089Seric 			map->map_app = ++p;
12060089Seric 			break;
121*68350Seric 
122*68350Seric 		  case 'k':
123*68350Seric 			while (isascii(*++p) && isspace(*p))
124*68350Seric 				continue;
125*68350Seric 			map->map_keycolnm = p;
126*68350Seric 			break;
127*68350Seric 
128*68350Seric 		  case 'v':
129*68350Seric 			while (isascii(*++p) && isspace(*p))
130*68350Seric 				continue;
131*68350Seric 			map->map_valcolnm = p;
132*68350Seric 			break;
133*68350Seric 
134*68350Seric 		  case 'z':
135*68350Seric 			if (*++p != '\\')
136*68350Seric 				map->map_coldelim = *p;
137*68350Seric 			else
138*68350Seric 			{
139*68350Seric 				switch (*++p)
140*68350Seric 				{
141*68350Seric 				  case 'n':
142*68350Seric 					map->map_coldelim = '\n';
143*68350Seric 					break;
144*68350Seric 
145*68350Seric 				  case 't':
146*68350Seric 					map->map_coldelim = '\t';
147*68350Seric 					break;
148*68350Seric 
149*68350Seric 				  default:
150*68350Seric 					map->map_coldelim = '\\';
151*68350Seric 				}
152*68350Seric 			}
153*68350Seric 			break;
15460089Seric 		}
15560089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
15660089Seric 			p++;
15760089Seric 		if (*p != '\0')
15860089Seric 			*p++ = '\0';
15960089Seric 	}
16060089Seric 	if (map->map_app != NULL)
16160089Seric 		map->map_app = newstr(map->map_app);
162*68350Seric 	if (map->map_keycolnm != NULL)
163*68350Seric 		map->map_keycolnm = newstr(map->map_keycolnm);
164*68350Seric 	if (map->map_valcolnm != NULL)
165*68350Seric 		map->map_valcolnm = newstr(map->map_valcolnm);
16660089Seric 
16760089Seric 	if (*p != '\0')
16860089Seric 	{
16960089Seric 		map->map_file = p;
17060089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
17160089Seric 			p++;
17260089Seric 		if (*p != '\0')
17360089Seric 			*p++ = '\0';
17460089Seric 		map->map_file = newstr(map->map_file);
17560089Seric 	}
17660089Seric 
17760089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
17860089Seric 		p++;
17960089Seric 	if (*p != '\0')
18060089Seric 		map->map_rebuild = newstr(p);
18160089Seric 
182*68350Seric 	if (map->map_file == NULL &&
183*68350Seric 	    !bitset(MCF_OPTFILE, map->map_class->map_cflags))
18457208Seric 	{
18560089Seric 		syserr("No file name for %s map %s",
18660089Seric 			map->map_class->map_cname, map->map_mname);
18756822Seric 		return FALSE;
18857208Seric 	}
18960089Seric 	return TRUE;
19060089Seric }
19160089Seric /*
19260089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
19360089Seric **
19460089Seric **	It also adds the map_app string.  It can be used as a utility
19560089Seric **	in the map_lookup method.
19660089Seric **
19760089Seric **	Parameters:
19860089Seric **		map -- the map that causes this.
19960089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
20060089Seric **		slen -- the length of s.
20160089Seric **		av -- arguments to interpolate into buf.
20260089Seric **
20360089Seric **	Returns:
20467895Seric **		Pointer to rewritten result.  This is static data that
20567895Seric **		should be copied if it is to be saved!
20660089Seric **
20760089Seric **	Side Effects:
20860089Seric **		none.
20960089Seric */
21060089Seric 
21160089Seric char *
21260089Seric map_rewrite(map, s, slen, av)
21360089Seric 	register MAP *map;
21460089Seric 	register char *s;
21560089Seric 	int slen;
21660089Seric 	char **av;
21760089Seric {
21860089Seric 	register char *bp;
21960089Seric 	register char c;
22060089Seric 	char **avp;
22160089Seric 	register char *ap;
22260089Seric 	int i;
22360089Seric 	int len;
22467895Seric 	static int buflen = -1;
22567895Seric 	static char *buf = NULL;
22660089Seric 
22760537Seric 	if (tTd(39, 1))
22860089Seric 	{
22960256Seric 		printf("map_rewrite(%.*s), av =", slen, s);
23060256Seric 		if (av == NULL)
23160256Seric 			printf(" (nullv)");
23260256Seric 		else
23360256Seric 		{
23460256Seric 			for (avp = av; *avp != NULL; avp++)
23560256Seric 				printf("\n\t%s", *avp);
23660256Seric 		}
23760256Seric 		printf("\n");
23860089Seric 	}
23960089Seric 
24060089Seric 	/* count expected size of output (can safely overestimate) */
24160089Seric 	i = len = slen;
24260089Seric 	if (av != NULL)
24360089Seric 	{
24460089Seric 		bp = s;
24560089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
24660089Seric 		{
24760089Seric 			if (c != '%')
24860089Seric 				continue;
24960089Seric 			if (--i < 0)
25060089Seric 				break;
25160089Seric 			c = *bp++;
25260089Seric 			if (!(isascii(c) && isdigit(c)))
25360089Seric 				continue;
25463937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
25560089Seric 				continue;
25660089Seric 			if (*avp == NULL)
25760089Seric 				continue;
25860089Seric 			len += strlen(*avp);
25960089Seric 		}
26060089Seric 	}
26160089Seric 	if (map->map_app != NULL)
26260089Seric 		len += strlen(map->map_app);
26367895Seric 	if (buflen < ++len)
26460089Seric 	{
26560089Seric 		/* need to malloc additional space */
26667895Seric 		buflen = len;
26767895Seric 		if (buf != NULL)
26867895Seric 			free(buf);
26967895Seric 		buf = xalloc(buflen);
27060089Seric 	}
27160089Seric 
27267895Seric 	bp = buf;
27360089Seric 	if (av == NULL)
27460089Seric 	{
27560089Seric 		bcopy(s, bp, slen);
27660089Seric 		bp += slen;
27760089Seric 	}
27860089Seric 	else
27960089Seric 	{
28060089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
28160089Seric 		{
28260089Seric 			if (c != '%')
28360089Seric 			{
28460089Seric   pushc:
28560089Seric 				*bp++ = c;
28660089Seric 				continue;
28760089Seric 			}
28860089Seric 			if (--slen < 0 || (c = *s++) == '\0')
28960089Seric 				c = '%';
29060089Seric 			if (c == '%')
29160089Seric 				goto pushc;
29260089Seric 			if (!(isascii(c) && isdigit(c)))
29360089Seric 			{
29460089Seric 				*bp++ = '%';
29560089Seric 				goto pushc;
29660089Seric 			}
29763937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
29860089Seric 				continue;
29960089Seric 			if (*avp == NULL)
30060089Seric 				continue;
30160089Seric 
30260089Seric 			/* transliterate argument into output string */
30360089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
30460089Seric 				*bp++ = c;
30560089Seric 		}
30660089Seric 	}
30760089Seric 	if (map->map_app != NULL)
30860089Seric 		strcpy(bp, map->map_app);
30960089Seric 	else
31060089Seric 		*bp = '\0';
31160537Seric 	if (tTd(39, 1))
31267895Seric 		printf("map_rewrite => %s\n", buf);
31367895Seric 	return buf;
31460089Seric }
31560089Seric /*
31660537Seric **  INITMAPS -- initialize for aliasing
31760537Seric **
31860537Seric **	Parameters:
31960537Seric **		rebuild -- if TRUE, this rebuilds the cached versions.
32060537Seric **		e -- current envelope.
32160537Seric **
32260537Seric **	Returns:
32360537Seric **		none.
32460537Seric **
32560537Seric **	Side Effects:
32660537Seric **		initializes aliases:
32760537Seric **		if NDBM:  opens the database.
32860537Seric **		if ~NDBM: reads the aliases into the symbol table.
32960537Seric */
33060537Seric 
33160537Seric initmaps(rebuild, e)
33260537Seric 	bool rebuild;
33360537Seric 	register ENVELOPE *e;
33460537Seric {
33560537Seric 	extern void map_init();
33660537Seric 
33764671Seric #ifdef XDEBUG
33864671Seric 	checkfd012("entering initmaps");
33964671Seric #endif
34060537Seric 	CurEnv = e;
34165085Seric 	if (rebuild)
34265085Seric 	{
34365085Seric 		stabapply(map_init, 1);
34465085Seric 		stabapply(map_init, 2);
34565085Seric 	}
34665085Seric 	else
34765085Seric 	{
34865085Seric 		stabapply(map_init, 0);
34965085Seric 	}
35064671Seric #ifdef XDEBUG
35164671Seric 	checkfd012("exiting initmaps");
35264671Seric #endif
35360537Seric }
35460537Seric 
35560537Seric void
35660537Seric map_init(s, rebuild)
35760537Seric 	register STAB *s;
35860537Seric 	int rebuild;
35960537Seric {
36060537Seric 	register MAP *map;
36160537Seric 
36260537Seric 	/* has to be a map */
36360537Seric 	if (s->s_type != ST_MAP)
36460537Seric 		return;
36560537Seric 
36660537Seric 	map = &s->s_map;
36760537Seric 	if (!bitset(MF_VALID, map->map_mflags))
36860537Seric 		return;
36960537Seric 
37060537Seric 	if (tTd(38, 2))
371*68350Seric 		printf("map_init(%s:%s, %s, %d)\n",
37264690Seric 			map->map_class->map_cname == NULL ? "NULL" :
37364690Seric 				map->map_class->map_cname,
374*68350Seric 			map->map_mname == NULL ? "NULL" : map->map_mname,
37565085Seric 			map->map_file == NULL ? "NULL" : map->map_file,
37665085Seric 			rebuild);
37760537Seric 
37865085Seric 	if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&
37965085Seric 		    bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))
38065085Seric 	{
38165085Seric 		if (tTd(38, 3))
38265085Seric 			printf("\twrong pass\n");
38365085Seric 		return;
38465085Seric 	}
38565085Seric 
38660537Seric 	/* if already open, close it (for nested open) */
38760537Seric 	if (bitset(MF_OPEN, map->map_mflags))
38860537Seric 	{
38960537Seric 		map->map_class->map_close(map);
39060537Seric 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
39160537Seric 	}
39260537Seric 
39365085Seric 	if (rebuild == 2)
39460537Seric 	{
39565085Seric 		rebuildaliases(map, FALSE);
39660537Seric 	}
39760537Seric 	else
39860537Seric 	{
39960537Seric 		if (map->map_class->map_open(map, O_RDONLY))
40060537Seric 		{
40160537Seric 			if (tTd(38, 4))
402*68350Seric 				printf("\t%s:%s %s: valid\n",
40364690Seric 					map->map_class->map_cname == NULL ? "NULL" :
40464690Seric 						map->map_class->map_cname,
405*68350Seric 					map->map_mname == NULL ? "NULL" :
406*68350Seric 						map->map_mname,
40764690Seric 					map->map_file == NULL ? "NULL" :
40864690Seric 						map->map_file);
40960537Seric 			map->map_mflags |= MF_OPEN;
41060537Seric 		}
411*68350Seric 		else
412*68350Seric 		{
413*68350Seric 			if (tTd(38, 4))
414*68350Seric 				printf("\t%s:%s %s: invalid: %s\n",
415*68350Seric 					map->map_class->map_cname == NULL ? "NULL" :
416*68350Seric 						map->map_class->map_cname,
417*68350Seric 					map->map_mname == NULL ? "NULL" :
418*68350Seric 						map->map_mname,
419*68350Seric 					map->map_file == NULL ? "NULL" :
420*68350Seric 						map->map_file,
421*68350Seric 					errstring(errno));
422*68350Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
423*68350Seric 			{
424*68350Seric 				extern MAPCLASS BogusMapClass;
425*68350Seric 
426*68350Seric 				map->map_class = &BogusMapClass;
427*68350Seric 				map->map_mflags |= MF_OPEN;
428*68350Seric 			}
429*68350Seric 		}
43060537Seric 	}
43160537Seric }
43260537Seric /*
43360089Seric **  NDBM modules
43460089Seric */
43560089Seric 
43660089Seric #ifdef NDBM
43760089Seric 
43860089Seric /*
43960089Seric **  DBM_MAP_OPEN -- DBM-style map open
44060089Seric */
44160089Seric 
44260089Seric bool
44360089Seric ndbm_map_open(map, mode)
44460089Seric 	MAP *map;
44560089Seric 	int mode;
44660089Seric {
44764284Seric 	register DBM *dbm;
44864284Seric 	struct stat st;
44960089Seric 
45060537Seric 	if (tTd(38, 2))
451*68350Seric 		printf("ndbm_map_open(%s, %s, %d)\n",
452*68350Seric 			map->map_mname, map->map_file, mode);
45360089Seric 
45460207Seric 	if (mode == O_RDWR)
45560207Seric 		mode |= O_CREAT|O_TRUNC;
45660207Seric 
45760089Seric 	/* open the database */
45860089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
45956822Seric 	if (dbm == NULL)
46056822Seric 	{
46164718Seric 		if (aliaswait(map, ".pag", FALSE))
46264718Seric 			return TRUE;
46360207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
46456836Seric 			syserr("Cannot open DBM database %s", map->map_file);
46556822Seric 		return FALSE;
46656822Seric 	}
46760089Seric 	map->map_db1 = (void *) dbm;
46864964Seric 	if (mode == O_RDONLY)
46964964Seric 	{
47064964Seric 		if (bitset(MF_ALIAS, map->map_mflags) &&
47164964Seric 		    !aliaswait(map, ".pag", TRUE))
47264718Seric 			return FALSE;
47364964Seric 	}
47464964Seric 	else
47564964Seric 	{
47664964Seric 		int fd;
47764964Seric 
47864964Seric 		/* exclusive lock for duration of rebuild */
47964964Seric 		fd = dbm_dirfno((DBM *) map->map_db1);
48064964Seric 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
48164964Seric 		    lockfile(fd, map->map_file, ".dir", LOCK_EX))
48264964Seric 			map->map_mflags |= MF_LOCKED;
48364964Seric 	}
48464718Seric 	if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
48564284Seric 		map->map_mtime = st.st_mtime;
48656822Seric 	return TRUE;
48756822Seric }
48860089Seric 
48960089Seric 
49060089Seric /*
49156822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
49256822Seric */
49356822Seric 
49456822Seric char *
49560089Seric ndbm_map_lookup(map, name, av, statp)
49656822Seric 	MAP *map;
49760089Seric 	char *name;
49856822Seric 	char **av;
49959084Seric 	int *statp;
50056822Seric {
50156822Seric 	datum key, val;
50264373Seric 	int fd;
50360089Seric 	char keybuf[MAXNAME + 1];
50456822Seric 
50560537Seric 	if (tTd(38, 20))
506*68350Seric 		printf("ndbm_map_lookup(%s, %s)\n",
507*68350Seric 			map->map_mname, name);
50860089Seric 
50960089Seric 	key.dptr = name;
51060089Seric 	key.dsize = strlen(name);
51160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
51257014Seric 	{
51360089Seric 		if (key.dsize > sizeof keybuf - 1)
51460089Seric 			key.dsize = sizeof keybuf - 1;
51560089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
51660089Seric 		makelower(keybuf);
51760089Seric 		key.dptr = keybuf;
51857014Seric 	}
51964373Seric 	fd = dbm_dirfno((DBM *) map->map_db1);
52064388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
52164373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
52263753Seric 	val.dptr = NULL;
52363753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
52463753Seric 	{
52563753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
52663753Seric 		if (val.dptr != NULL)
52763753Seric 			map->map_mflags &= ~MF_TRY1NULL;
52863753Seric 	}
52963753Seric 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
53063753Seric 	{
53156822Seric 		key.dsize++;
53263753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
53363753Seric 		if (val.dptr != NULL)
53463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
53563753Seric 	}
53664388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
53764373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
53856822Seric 	if (val.dptr == NULL)
53956822Seric 		return NULL;
54060207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
54163753Seric 		return map_rewrite(map, name, strlen(name), NULL);
54263753Seric 	else
54363753Seric 		return map_rewrite(map, val.dptr, val.dsize, av);
54456822Seric }
54556822Seric 
54656822Seric 
54756822Seric /*
54860089Seric **  DBM_MAP_STORE -- store a datum in the database
54956822Seric */
55056822Seric 
55160089Seric void
55260089Seric ndbm_map_store(map, lhs, rhs)
55360089Seric 	register MAP *map;
55460089Seric 	char *lhs;
55560089Seric 	char *rhs;
55660089Seric {
55760089Seric 	datum key;
55860089Seric 	datum data;
55960089Seric 	int stat;
56060089Seric 
56160537Seric 	if (tTd(38, 12))
562*68350Seric 		printf("ndbm_map_store(%s, %s, %s)\n",
563*68350Seric 			map->map_mname, lhs, rhs);
56460089Seric 
56560089Seric 	key.dsize = strlen(lhs);
56660089Seric 	key.dptr = lhs;
56760089Seric 
56860089Seric 	data.dsize = strlen(rhs);
56960089Seric 	data.dptr = rhs;
57060089Seric 
57160207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
57260089Seric 	{
57360089Seric 		key.dsize++;
57460089Seric 		data.dsize++;
57560089Seric 	}
57660089Seric 
57760089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
57860089Seric 	if (stat > 0)
57960089Seric 	{
58060089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
58160089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
58260089Seric 	}
58360089Seric 	if (stat != 0)
58460089Seric 		syserr("readaliases: dbm put (%s)", lhs);
58560089Seric }
58660089Seric 
58760089Seric 
58860089Seric /*
58960207Seric **  NDBM_MAP_CLOSE -- close the database
59060089Seric */
59160089Seric 
59260089Seric void
59360089Seric ndbm_map_close(map)
59460089Seric 	register MAP  *map;
59560089Seric {
59666773Seric 	if (tTd(38, 9))
597*68350Seric 		printf("ndbm_map_close(%s, %s, %x)\n",
598*68350Seric 			map->map_mname, map->map_file, map->map_mflags);
59966773Seric 
60060207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
60160089Seric 	{
60264250Seric #ifdef NIS
60364075Seric 		bool inclnull;
60460089Seric 		char buf[200];
60560089Seric 
60664075Seric 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
60764075Seric 		map->map_mflags &= ~MF_INCLNULL;
60864075Seric 
60960089Seric 		(void) sprintf(buf, "%010ld", curtime());
61060089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
61160089Seric 
61264941Seric 		(void) gethostname(buf, sizeof buf);
61360089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
61464075Seric 
61564075Seric 		if (inclnull)
61664075Seric 			map->map_mflags |= MF_INCLNULL;
61760089Seric #endif
61860089Seric 
61960089Seric 		/* write out the distinguished alias */
62060089Seric 		ndbm_map_store(map, "@", "@");
62160089Seric 	}
62260089Seric 	dbm_close((DBM *) map->map_db1);
62360089Seric }
62460089Seric 
62560089Seric #endif
62660089Seric /*
62760582Seric **  NEWDB (Hash and BTree) Modules
62860089Seric */
62960089Seric 
63060089Seric #ifdef NEWDB
63160089Seric 
63260089Seric /*
63360582Seric **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
63460582Seric **
63560582Seric **	These do rather bizarre locking.  If you can lock on open,
63660582Seric **	do that to avoid the condition of opening a database that
63760582Seric **	is being rebuilt.  If you don't, we'll try to fake it, but
63860582Seric **	there will be a race condition.  If opening for read-only,
63960582Seric **	we immediately release the lock to avoid freezing things up.
64060582Seric **	We really ought to hold the lock, but guarantee that we won't
64160582Seric **	be pokey about it.  That's hard to do.
64260089Seric */
64360089Seric 
64456822Seric bool
64560089Seric bt_map_open(map, mode)
64656822Seric 	MAP *map;
64760089Seric 	int mode;
64856822Seric {
64956822Seric 	DB *db;
65060228Seric 	int i;
65160582Seric 	int omode;
65264373Seric 	int fd;
65364284Seric 	struct stat st;
65460089Seric 	char buf[MAXNAME];
65556822Seric 
65660537Seric 	if (tTd(38, 2))
657*68350Seric 		printf("bt_map_open(%s, %s, %d)\n",
658*68350Seric 			map->map_mname, map->map_file, mode);
65960089Seric 
66060582Seric 	omode = mode;
66160582Seric 	if (omode == O_RDWR)
66260582Seric 	{
66360582Seric 		omode |= O_CREAT|O_TRUNC;
66465830Seric #if defined(O_EXLOCK) && HASFLOCK
66560582Seric 		omode |= O_EXLOCK;
66666843Seric # if !OLD_NEWDB
66760582Seric 	}
66860582Seric 	else
66960582Seric 	{
67060582Seric 		omode |= O_SHLOCK;
67160582Seric # endif
67260582Seric #endif
67360582Seric 	}
67460207Seric 
67560228Seric 	(void) strcpy(buf, map->map_file);
67660228Seric 	i = strlen(buf);
67760228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
67860228Seric 		(void) strcat(buf, ".db");
67960582Seric 	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
68056822Seric 	if (db == NULL)
68156822Seric 	{
68264718Seric #ifdef MAYBENEXTRELEASE
68364718Seric 		if (aliaswait(map, ".db", FALSE))
68464718Seric 			return TRUE;
68564718Seric #endif
68660207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
68756836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
68856822Seric 		return FALSE;
68956822Seric 	}
690*68350Seric #if !OLD_NEWDB
69164373Seric 	fd = db->fd(db);
692*68350Seric # if HASFLOCK
693*68350Seric #  if !defined(O_EXLOCK)
69464373Seric 	if (mode == O_RDWR && fd >= 0)
69564388Seric 	{
69664388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
69764388Seric 			map->map_mflags |= MF_LOCKED;
69864388Seric 	}
699*68350Seric #  else
70064373Seric 	if (mode == O_RDONLY && fd >= 0)
70164373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
70264388Seric 	else
70364388Seric 		map->map_mflags |= MF_LOCKED;
704*68350Seric #  endif
70560582Seric # endif
70660582Seric #endif
70760585Seric 
70860585Seric 	/* try to make sure that at least the database header is on disk */
70960585Seric 	if (mode == O_RDWR)
71066843Seric #if OLD_NEWDB
71164373Seric 		(void) db->sync(db);
71264373Seric #else
71360585Seric 		(void) db->sync(db, 0);
71460585Seric 
71564373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
71664284Seric 		map->map_mtime = st.st_mtime;
71764284Seric #endif
71864284Seric 
71960089Seric 	map->map_db2 = (void *) db;
72060207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
72164718Seric 		if (!aliaswait(map, ".db", TRUE))
72264718Seric 			return FALSE;
72356822Seric 	return TRUE;
72456822Seric }
72556822Seric 
72656822Seric 
72756822Seric /*
72856822Seric **  HASH_MAP_INIT -- HASH-style map initialization
72956822Seric */
73056822Seric 
73156822Seric bool
73260089Seric hash_map_open(map, mode)
73356822Seric 	MAP *map;
73460089Seric 	int mode;
73556822Seric {
73656822Seric 	DB *db;
73760228Seric 	int i;
73860582Seric 	int omode;
73964373Seric 	int fd;
74064284Seric 	struct stat st;
74160089Seric 	char buf[MAXNAME];
74256822Seric 
74360537Seric 	if (tTd(38, 2))
744*68350Seric 		printf("hash_map_open(%s, %s, %d)\n",
745*68350Seric 			map->map_mname, map->map_file, mode);
74660089Seric 
74760582Seric 	omode = mode;
74860582Seric 	if (omode == O_RDWR)
74960582Seric 	{
75060582Seric 		omode |= O_CREAT|O_TRUNC;
75165830Seric #if defined(O_EXLOCK) && HASFLOCK
75260582Seric 		omode |= O_EXLOCK;
75366843Seric # if !OLD_NEWDB
75460582Seric 	}
75560582Seric 	else
75660582Seric 	{
75760582Seric 		omode |= O_SHLOCK;
75860582Seric # endif
75960582Seric #endif
76060582Seric 	}
76160207Seric 
76260228Seric 	(void) strcpy(buf, map->map_file);
76360228Seric 	i = strlen(buf);
76460228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
76560228Seric 		(void) strcat(buf, ".db");
76660582Seric 	db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
76756822Seric 	if (db == NULL)
76856822Seric 	{
76964718Seric #ifdef MAYBENEXTRELEASE
77064718Seric 		if (aliaswait(map, ".db", FALSE))
77164718Seric 			return TRUE;
77264718Seric #endif
77360207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
77456836Seric 			syserr("Cannot open HASH database %s", map->map_file);
77556822Seric 		return FALSE;
77656822Seric 	}
777*68350Seric #if !OLD_NEWDB
77864373Seric 	fd = db->fd(db);
779*68350Seric # if HASFLOCK
780*68350Seric #  if !defined(O_EXLOCK)
78164373Seric 	if (mode == O_RDWR && fd >= 0)
78264388Seric 	{
78364388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
78464388Seric 			map->map_mflags |= MF_LOCKED;
78564388Seric 	}
786*68350Seric #  else
78764373Seric 	if (mode == O_RDONLY && fd >= 0)
78864373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
78964388Seric 	else
79064388Seric 		map->map_mflags |= MF_LOCKED;
791*68350Seric #  endif
79260582Seric # endif
79360582Seric #endif
79460585Seric 
79560585Seric 	/* try to make sure that at least the database header is on disk */
79660585Seric 	if (mode == O_RDWR)
79766843Seric #if OLD_NEWDB
79864373Seric 		(void) db->sync(db);
79964373Seric #else
80060585Seric 		(void) db->sync(db, 0);
80160585Seric 
80264373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
80364284Seric 		map->map_mtime = st.st_mtime;
80464284Seric #endif
80564284Seric 
80660089Seric 	map->map_db2 = (void *) db;
80760207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
80864718Seric 		if (!aliaswait(map, ".db", TRUE))
80964718Seric 			return FALSE;
81056822Seric 	return TRUE;
81156822Seric }
81256822Seric 
81356822Seric 
81456822Seric /*
81556822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
81656822Seric */
81756822Seric 
81856822Seric char *
81960089Seric db_map_lookup(map, name, av, statp)
82056822Seric 	MAP *map;
82160089Seric 	char *name;
82256822Seric 	char **av;
82359084Seric 	int *statp;
82456822Seric {
82556822Seric 	DBT key, val;
82660422Seric 	register DB *db = (DB *) map->map_db2;
82760422Seric 	int st;
82860422Seric 	int saveerrno;
82964373Seric 	int fd;
83060089Seric 	char keybuf[MAXNAME + 1];
83156822Seric 
83260537Seric 	if (tTd(38, 20))
833*68350Seric 		printf("db_map_lookup(%s, %s)\n",
834*68350Seric 			map->map_mname, name);
83560089Seric 
83660089Seric 	key.size = strlen(name);
83760089Seric 	if (key.size > sizeof keybuf - 1)
83860089Seric 		key.size = sizeof keybuf - 1;
83960089Seric 	key.data = keybuf;
84060089Seric 	bcopy(name, keybuf, key.size + 1);
84160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
84260089Seric 		makelower(keybuf);
84366843Seric #if !OLD_NEWDB
84464388Seric 	fd = db->fd(db);
84564388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
84664388Seric 		(void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
84760422Seric #endif
84863753Seric 	st = 1;
84963753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
85063753Seric 	{
85163753Seric 		st = db->get(db, &key, &val, 0);
85263753Seric 		if (st == 0)
85363753Seric 			map->map_mflags &= ~MF_TRY1NULL;
85463753Seric 	}
85563753Seric 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
85663753Seric 	{
85763753Seric 		key.size++;
85863753Seric 		st = db->get(db, &key, &val, 0);
85963753Seric 		if (st == 0)
86063753Seric 			map->map_mflags &= ~MF_TRY0NULL;
86163753Seric 	}
86260422Seric 	saveerrno = errno;
86366843Seric #if !OLD_NEWDB
86464388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
86564373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
86660422Seric #endif
86760422Seric 	if (st != 0)
86860422Seric 	{
86960422Seric 		errno = saveerrno;
87060422Seric 		if (st < 0)
87160422Seric 			syserr("db_map_lookup: get (%s)", name);
87256822Seric 		return NULL;
87360422Seric 	}
87460207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
87563753Seric 		return map_rewrite(map, name, strlen(name), NULL);
87663753Seric 	else
87763753Seric 		return map_rewrite(map, val.data, val.size, av);
87856822Seric }
87956822Seric 
88060089Seric 
88160089Seric /*
88260089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
88356822Seric */
88456822Seric 
88560089Seric void
88660089Seric db_map_store(map, lhs, rhs)
88760089Seric 	register MAP *map;
88860089Seric 	char *lhs;
88960089Seric 	char *rhs;
89056822Seric {
89160089Seric 	int stat;
89260089Seric 	DBT key;
89360089Seric 	DBT data;
89460089Seric 	register DB *db = map->map_db2;
89556822Seric 
89660537Seric 	if (tTd(38, 20))
897*68350Seric 		printf("db_map_store(%s, %s, %s)\n",
898*68350Seric 			map->map_mname, lhs, rhs);
89960089Seric 
90060089Seric 	key.size = strlen(lhs);
90160089Seric 	key.data = lhs;
90260089Seric 
90360089Seric 	data.size = strlen(rhs);
90460089Seric 	data.data = rhs;
90560089Seric 
90660207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
90756822Seric 	{
90860089Seric 		key.size++;
90960089Seric 		data.size++;
91060089Seric 	}
91156836Seric 
91260089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
91360089Seric 	if (stat > 0)
91460089Seric 	{
91560089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
91660089Seric 		stat = db->put(db, &key, &data, 0);
91760089Seric 	}
91860089Seric 	if (stat != 0)
91960089Seric 		syserr("readaliases: db put (%s)", lhs);
92060089Seric }
92156836Seric 
92256847Seric 
92360089Seric /*
92460089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
92560089Seric */
92660089Seric 
92760089Seric void
92860089Seric db_map_close(map)
92960089Seric 	MAP *map;
93060089Seric {
93160089Seric 	register DB *db = map->map_db2;
93260089Seric 
93360537Seric 	if (tTd(38, 9))
934*68350Seric 		printf("db_map_close(%s, %s, %x)\n",
935*68350Seric 			map->map_mname, map->map_file, map->map_mflags);
93660089Seric 
93760207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
93858804Seric 	{
93960089Seric 		/* write out the distinguished alias */
94060089Seric 		db_map_store(map, "@", "@");
94158804Seric 	}
94258963Seric 
94360089Seric 	if (db->close(db) != 0)
94460089Seric 		syserr("readaliases: db close failure");
94556822Seric }
94657208Seric 
94760089Seric #endif
94860089Seric /*
94960089Seric **  NIS Modules
95060089Seric */
95160089Seric 
95260089Seric # ifdef NIS
95360089Seric 
95464369Seric # ifndef YPERR_BUSY
95564369Seric #  define YPERR_BUSY	16
95664369Seric # endif
95764369Seric 
95857208Seric /*
95960089Seric **  NIS_MAP_OPEN -- open DBM map
96057208Seric */
96157208Seric 
96257208Seric bool
96360089Seric nis_map_open(map, mode)
96457208Seric 	MAP *map;
96560089Seric 	int mode;
96657208Seric {
96757216Seric 	int yperr;
96860215Seric 	register char *p;
96960215Seric 	auto char *vp;
97060215Seric 	auto int vsize;
97157216Seric 	char *master;
97257216Seric 
97360537Seric 	if (tTd(38, 2))
974*68350Seric 		printf("nis_map_open(%s, %s)\n",
975*68350Seric 			map->map_mname, map->map_file);
97660089Seric 
97760207Seric 	if (mode != O_RDONLY)
97860207Seric 	{
97964650Seric 		/* issue a pseudo-error message */
98064650Seric #ifdef ENOSYS
98164650Seric 		errno = ENOSYS;
98264650Seric #else
98364650Seric # ifdef EFTYPE
98464650Seric 		errno = EFTYPE;
98564650Seric # else
98664650Seric 		errno = ENXIO;
98764650Seric # endif
98864650Seric #endif
98960207Seric 		return FALSE;
99060207Seric 	}
99160207Seric 
99260089Seric 	p = strchr(map->map_file, '@');
99360089Seric 	if (p != NULL)
99460089Seric 	{
99560089Seric 		*p++ = '\0';
99660089Seric 		if (*p != '\0')
99760089Seric 			map->map_domain = p;
99860089Seric 	}
99960215Seric 
100060089Seric 	if (*map->map_file == '\0')
100160089Seric 		map->map_file = "mail.aliases";
100260089Seric 
100366157Seric 	if (map->map_domain == NULL)
100466157Seric 	{
100566157Seric 		yperr = yp_get_default_domain(&map->map_domain);
100666157Seric 		if (yperr != 0)
100766157Seric 		{
100866744Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
1009*68350Seric 				syserr("421 NIS map %s specified, but NIS not running\n",
101066744Seric 					map->map_file);
101166157Seric 			return FALSE;
101266157Seric 		}
101366157Seric 	}
101466157Seric 
101560215Seric 	/* check to see if this map actually exists */
101660089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
101760089Seric 			&vp, &vsize);
101860537Seric 	if (tTd(38, 10))
101960089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
102060089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
102160089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
1022*68350Seric 	{
1023*68350Seric 		if (!bitset(MF_ALIAS, map->map_mflags) ||
1024*68350Seric 		    aliaswait(map, NULL, TRUE))
1025*68350Seric 			return TRUE;
1026*68350Seric 	}
102760215Seric 
102860215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
1029*68350Seric 		syserr("421 Cannot bind to domain %s: %s", map->map_domain,
103060215Seric 			yperr_string(yperr));
103160215Seric 
103260089Seric 	return FALSE;
103360089Seric }
103460089Seric 
103560089Seric 
103660089Seric /*
103757208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
103857208Seric */
103957208Seric 
104057208Seric char *
104160089Seric nis_map_lookup(map, name, av, statp)
104257208Seric 	MAP *map;
104360089Seric 	char *name;
104457208Seric 	char **av;
104559084Seric 	int *statp;
104657208Seric {
104757208Seric 	char *vp;
104857642Seric 	auto int vsize;
104959274Seric 	int buflen;
105060215Seric 	int yperr;
105160089Seric 	char keybuf[MAXNAME + 1];
105257208Seric 
105360537Seric 	if (tTd(38, 20))
1054*68350Seric 		printf("nis_map_lookup(%s, %s)\n",
1055*68350Seric 			map->map_mname, name);
105660089Seric 
105760089Seric 	buflen = strlen(name);
105860089Seric 	if (buflen > sizeof keybuf - 1)
105960089Seric 		buflen = sizeof keybuf - 1;
106060089Seric 	bcopy(name, keybuf, buflen + 1);
106160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
106260089Seric 		makelower(keybuf);
106363753Seric 	yperr = YPERR_KEY;
106463753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
106563753Seric 	{
106663753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
106763753Seric 			     &vp, &vsize);
106863753Seric 		if (yperr == 0)
106963753Seric 			map->map_mflags &= ~MF_TRY1NULL;
107063753Seric 	}
107163753Seric 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
107263753Seric 	{
107359274Seric 		buflen++;
107463753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
107563753Seric 			     &vp, &vsize);
107663753Seric 		if (yperr == 0)
107763753Seric 			map->map_mflags &= ~MF_TRY0NULL;
107863753Seric 	}
107960089Seric 	if (yperr != 0)
108060089Seric 	{
108160089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
108260215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
108357208Seric 		return NULL;
108460089Seric 	}
108560207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
108663753Seric 		return map_rewrite(map, name, strlen(name), NULL);
108763753Seric 	else
108863753Seric 		return map_rewrite(map, vp, vsize, av);
108957208Seric }
109057208Seric 
1091*68350Seric #endif
1092*68350Seric /*
1093*68350Seric **  NISPLUS Modules
1094*68350Seric **
1095*68350Seric **	This code donated by Sun Microsystems.
1096*68350Seric */
109767848Seric 
1098*68350Seric #ifdef NISPLUS
1099*68350Seric 
1100*68350Seric #undef NIS /* symbol conflict in nis.h */
1101*68350Seric #include <rpcsvc/nis.h>
1102*68350Seric #include <rpcsvc/nislib.h>
1103*68350Seric 
1104*68350Seric #define EN_col(col)	zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
1105*68350Seric #define COL_NAME(res,i)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
1106*68350Seric #define COL_MAX(res)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
1107*68350Seric #define PARTIAL_NAME(x)	((x)[strlen(x) - 1] != '.')
1108*68350Seric 
110967848Seric /*
1110*68350Seric **  NISPLUS_MAP_OPEN -- open nisplus table
111167848Seric */
111267848Seric 
1113*68350Seric bool
1114*68350Seric nisplus_map_open(map, mode)
111567848Seric 	MAP *map;
1116*68350Seric 	int mode;
111767848Seric {
1118*68350Seric 	register char *p;
1119*68350Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
1120*68350Seric 	nis_result *res = NULL;
1121*68350Seric 	u_int objs_len;
1122*68350Seric 	nis_object *obj_ptr;
1123*68350Seric 	int retry_cnt, max_col, i;
1124*68350Seric 
1125*68350Seric 	if (tTd(38, 2))
1126*68350Seric 		printf("nisplus_map_open(%s, %s, %d)\n",
1127*68350Seric 			map->map_mname, map->map_file, mode);
1128*68350Seric 
1129*68350Seric 	if (mode != O_RDONLY)
1130*68350Seric 	{
1131*68350Seric 		errno = ENODEV;
1132*68350Seric 		return FALSE;
1133*68350Seric 	}
1134*68350Seric 
1135*68350Seric 	if (*map->map_file == '\0')
1136*68350Seric 		map->map_file = "mail_aliases.org_dir";
1137*68350Seric 
1138*68350Seric 	if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
1139*68350Seric 	{
1140*68350Seric 		/* set default NISPLUS Domain to $m */
1141*68350Seric 		extern char *nisplus_default_domain();
1142*68350Seric 
1143*68350Seric 		map->map_domain = newstr(nisplus_default_domain());
1144*68350Seric 		if (tTd(38, 2))
1145*68350Seric 			printf("nisplus_map_open(%s): using domain %s\n",
1146*68350Seric 				 map->map_file, map->map_domain);
1147*68350Seric 	}
1148*68350Seric 	if (!PARTIAL_NAME(map->map_file))
1149*68350Seric 		map->map_domain = newstr("");
1150*68350Seric 
1151*68350Seric 	/* check to see if this map actually exists */
1152*68350Seric 	if (PARTIAL_NAME(map->map_file))
1153*68350Seric 		sprintf(qbuf, "%s.%s", map->map_file, map->map_domain);
1154*68350Seric 	else
1155*68350Seric 		strcpy(qbuf, map->map_file);
1156*68350Seric 
1157*68350Seric 	retry_cnt = 0;
1158*68350Seric 	while (res == NULL || res->status != NIS_SUCCESS)
1159*68350Seric 	{
1160*68350Seric 		res = nis_lookup(qbuf, FOLLOW_LINKS);
1161*68350Seric 		switch (res->status)
1162*68350Seric 		{
1163*68350Seric 		  case NIS_SUCCESS:
1164*68350Seric 		  case NIS_TRYAGAIN:
1165*68350Seric 		  case NIS_RPCERROR:
1166*68350Seric 		  case NIS_NAMEUNREACHABLE:
1167*68350Seric 			break;
1168*68350Seric 
1169*68350Seric 		  default:		/* all other nisplus errors */
1170*68350Seric #if 0
1171*68350Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
1172*68350Seric 				syserr("421 Cannot find table %s.%s: %s",
1173*68350Seric 					map->map_file, map->map_domain,
1174*68350Seric 					nis_sperrno(res->status));
1175*68350Seric #endif
1176*68350Seric 			errno = EBADR;
1177*68350Seric 			return FALSE;
1178*68350Seric 		}
1179*68350Seric 		sleep(2);		/* try not to overwhelm hosed server */
1180*68350Seric 		if (retry_cnt++ > 4)
1181*68350Seric 		{
1182*68350Seric 			errno = EBADR;
1183*68350Seric 			return FALSE;
1184*68350Seric 		}
1185*68350Seric 	}
1186*68350Seric 
1187*68350Seric 	if (NIS_RES_NUMOBJ(res) != 1 ||
1188*68350Seric 	    (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
1189*68350Seric 	{
1190*68350Seric 		if (tTd(38, 10))
1191*68350Seric 			printf("nisplus_map_open: %s is not a table\n", qbuf);
1192*68350Seric #if 0
1193*68350Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
1194*68350Seric 			syserr("421 %s.%s: %s is not a table",
1195*68350Seric 				map->map_file, map->map_domain,
1196*68350Seric 				nis_sperrno(res->status));
1197*68350Seric #endif
1198*68350Seric 		errno = EBADR;
1199*68350Seric 		return FALSE;
1200*68350Seric 	}
1201*68350Seric 	/* default key column is column 0 */
1202*68350Seric 	if (map->map_keycolnm == NULL)
1203*68350Seric 		map->map_keycolnm = newstr(COL_NAME(res,0));
1204*68350Seric 
1205*68350Seric 	max_col = COL_MAX(res);
1206*68350Seric 
1207*68350Seric 	/* verify the key column exist */
1208*68350Seric 	for (i=0; i< max_col; i++)
1209*68350Seric 	{
1210*68350Seric 		if (!strcmp(map->map_keycolnm, COL_NAME(res,i)))
1211*68350Seric 			break;
1212*68350Seric 	}
1213*68350Seric 	if (i == max_col)
1214*68350Seric 	{
1215*68350Seric 		if (tTd(38, 2))
1216*68350Seric 			printf("nisplus_map_open(%s): can not find key column %s\n",
1217*68350Seric 				map->map_file, map->map_keycolnm);
1218*68350Seric 		errno = EBADR;
1219*68350Seric 		return FALSE;
1220*68350Seric 	}
1221*68350Seric 
1222*68350Seric 	/* default value column is the last column */
1223*68350Seric 	if (map->map_valcolnm == NULL)
1224*68350Seric 	{
1225*68350Seric 		map->map_valcolno = max_col - 1;
1226*68350Seric 		return TRUE;
1227*68350Seric 	}
1228*68350Seric 
1229*68350Seric 	for (i=0; i< max_col; i++)
1230*68350Seric 	{
1231*68350Seric 		if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
1232*68350Seric 		{
1233*68350Seric 			map->map_valcolno = i;
1234*68350Seric 			return TRUE;
1235*68350Seric 		}
1236*68350Seric 	}
1237*68350Seric 
1238*68350Seric 	if (tTd(38, 2))
1239*68350Seric 		printf("nisplus_map_open(%s): can not find column %s\n",
1240*68350Seric 			 map->map_file, map->map_keycolnm);
1241*68350Seric 	errno = EBADR;
1242*68350Seric 	return FALSE;
124367848Seric }
124467848Seric 
124567848Seric 
124667848Seric /*
1247*68350Seric **  NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
124867848Seric */
124967848Seric 
1250*68350Seric char *
1251*68350Seric nisplus_map_lookup(map, name, av, statp)
125267848Seric 	MAP *map;
1253*68350Seric 	char *name;
1254*68350Seric 	char **av;
1255*68350Seric 	int *statp;
125667848Seric {
1257*68350Seric 	char *vp;
1258*68350Seric 	auto int vsize;
1259*68350Seric 	int buflen;
1260*68350Seric 	char search_key[MAXNAME + 1];
1261*68350Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
1262*68350Seric 	nis_result *result;
1263*68350Seric 
1264*68350Seric 	if (tTd(38, 20))
1265*68350Seric 		printf("nisplus_map_lookup(%s, %s)\n",
1266*68350Seric 			map->map_mname, name);
1267*68350Seric 
1268*68350Seric 	if (!bitset(MF_OPEN, map->map_mflags))
1269*68350Seric 	{
1270*68350Seric 		if (nisplus_map_open(map, O_RDONLY))
1271*68350Seric 			map->map_mflags |= MF_OPEN;
1272*68350Seric 		else
1273*68350Seric 		{
1274*68350Seric 			*statp = EX_UNAVAILABLE;
1275*68350Seric 			return NULL;
1276*68350Seric 		}
1277*68350Seric 	}
1278*68350Seric 
1279*68350Seric 	buflen = strlen(name);
1280*68350Seric 	if (buflen > sizeof search_key - 1)
1281*68350Seric 		buflen = sizeof search_key - 1;
1282*68350Seric 	bcopy(name, search_key, buflen + 1);
1283*68350Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
1284*68350Seric 		makelower(search_key);
1285*68350Seric 
1286*68350Seric 	/* construct the query */
1287*68350Seric 	if (PARTIAL_NAME(map->map_file))
1288*68350Seric 		sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm,
1289*68350Seric 			search_key, map->map_file, map->map_domain);
1290*68350Seric 	else
1291*68350Seric 		sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm,
1292*68350Seric 			search_key, map->map_file);
1293*68350Seric 
1294*68350Seric 	if (tTd(38, 20))
1295*68350Seric 		printf("qbuf=%s\n", qbuf);
1296*68350Seric 	result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
1297*68350Seric 	if (result->status == NIS_SUCCESS)
1298*68350Seric 	{
1299*68350Seric 		int count;
1300*68350Seric 		char *str;
1301*68350Seric 
1302*68350Seric 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
1303*68350Seric 		{
1304*68350Seric 			if (LogLevel > 10)
1305*68350Seric 				syslog(LOG_WARNING,
1306*68350Seric 				  "%s:Lookup error, expected 1 entry, got (%d)",
1307*68350Seric 				    map->map_file, count);
1308*68350Seric 
1309*68350Seric 			/* ignore second entry */
1310*68350Seric 			if (tTd(38, 20))
1311*68350Seric 				printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
1312*68350Seric 					name, count);
1313*68350Seric 		}
1314*68350Seric 
1315*68350Seric 		vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
1316*68350Seric 		/* set the length of the result */
1317*68350Seric 		if (vp == NULL)
1318*68350Seric 			vp = "";
1319*68350Seric 		vsize = strlen(vp);
1320*68350Seric 		if (tTd(38, 20))
1321*68350Seric 			printf("nisplus_map_lookup(%s), found %s\n",
1322*68350Seric 				name, vp);
1323*68350Seric 		if (bitset(MF_MATCHONLY, map->map_mflags))
1324*68350Seric 			str = map_rewrite(map, name, strlen(name), NULL);
1325*68350Seric 		else
1326*68350Seric 			str = map_rewrite(map, vp, vsize, av);
1327*68350Seric 		nis_freeresult(result);
1328*68350Seric #ifdef MAP_EXIT_STAT
1329*68350Seric 		*statp = EX_OK;
1330*68350Seric #endif
1331*68350Seric 		return str;
1332*68350Seric 	}
1333*68350Seric 	else
1334*68350Seric 	{
1335*68350Seric #ifdef MAP_EXIT_STAT
1336*68350Seric 		if (result->status == NIS_NOTFOUND)
1337*68350Seric 			*statp = EX_NOTFOUND;
1338*68350Seric 		else if (result->status == NIS_TRYAGAIN)
1339*68350Seric 			*statp = EX_TEMPFAIL;
1340*68350Seric 		else
1341*68350Seric 		{
1342*68350Seric 			*statp = EX_UNAVAILABLE;
1343*68350Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
1344*68350Seric 		}
1345*68350Seric #else
1346*68350Seric 		if ((result->status != NIS_NOTFOUND) &&
1347*68350Seric 		    (result->status != NIS_TRYAGAIN))
1348*68350Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
1349*68350Seric #endif
1350*68350Seric 	}
1351*68350Seric 	if (tTd(38, 20))
1352*68350Seric 		printf("nisplus_map_lookup(%s), failed\n", name);
1353*68350Seric 	nis_freeresult(result);
1354*68350Seric 	return NULL;
135567848Seric }
135667848Seric 
1357*68350Seric 
1358*68350Seric char *
1359*68350Seric nisplus_default_domain()
1360*68350Seric {
1361*68350Seric 	static char default_domain[MAXNAME] = "";
1362*68350Seric 	nis_result *res = NULL;
1363*68350Seric 	char *p;
1364*68350Seric 
1365*68350Seric 	if (default_domain[0] != '\0')
1366*68350Seric 		return(default_domain);
1367*68350Seric 
1368*68350Seric 	if (VendorCode == VENDOR_SUN && ConfigLevel < 2)
1369*68350Seric 	{
1370*68350Seric 		/* for old config, user nis+ local directory        */
1371*68350Seric 		/* have to be backward compatible with bugs too :-( */
1372*68350Seric 		p = nis_local_directory();
1373*68350Seric 		strcpy(default_domain, p);
1374*68350Seric 		return default_domain;
1375*68350Seric 	}
1376*68350Seric 
1377*68350Seric 	if ((p = macvalue('m', CurEnv)) == NULL)
1378*68350Seric 	{
1379*68350Seric 		p = nis_local_directory();
1380*68350Seric 		strcpy(default_domain, p);
1381*68350Seric 		return default_domain;
1382*68350Seric 	}
1383*68350Seric 
1384*68350Seric 	strcpy(default_domain, p);
1385*68350Seric 	if (PARTIAL_NAME(default_domain))
1386*68350Seric 		strcat(default_domain, ".");
1387*68350Seric 
1388*68350Seric 	res = nis_lookup(default_domain, FOLLOW_LINKS);
1389*68350Seric 	if (res->status == NIS_NOTFOUND)
1390*68350Seric 	{
1391*68350Seric 		p = nis_local_directory();
1392*68350Seric 		strcpy(default_domain, p);
1393*68350Seric 	}
1394*68350Seric 	return(default_domain);
1395*68350Seric }
1396*68350Seric 
1397*68350Seric #endif /* NISPLUS */
139867848Seric /*
1399*68350Seric **  HESIOD Modules
1400*68350Seric **
1401*68350Seric **	Only works for aliases (for now).
1402*68350Seric */
1403*68350Seric 
1404*68350Seric #ifdef HESIOD
1405*68350Seric 
1406*68350Seric #include <hesiod.h>
1407*68350Seric 
1408*68350Seric char *
1409*68350Seric hes_map_lookup(map, name, av, statp)
1410*68350Seric         MAP *map;
1411*68350Seric         char *name;
1412*68350Seric         char **av;
1413*68350Seric         int *statp;
1414*68350Seric {
1415*68350Seric 	char **hp;
1416*68350Seric 	char *retdata = NULL;
1417*68350Seric 	int i;
1418*68350Seric 
1419*68350Seric 	if (tTd(38, 20))
1420*68350Seric 		printf("hes_map_lookup(%s, %s)\n", map->map_file, name);
1421*68350Seric 
1422*68350Seric 	hp = hes_resolve(name, map->map_file);
1423*68350Seric 	if (hp == NULL)
1424*68350Seric 		return NULL;
1425*68350Seric 
1426*68350Seric 	if (hp[0] != NULL)
1427*68350Seric 	{
1428*68350Seric 		if (tTd(38, 20))
1429*68350Seric 			printf("  %d %s\n", i, p);
1430*68350Seric 		if (bitset(MF_MATCHONLY, map->map_mflags))
1431*68350Seric 			retdata = map_rewrite(map, name, strlen(name), NULL);
1432*68350Seric 		else
1433*68350Seric 			retdata = map_rewrite(map, hp[0], strlen(hp[0]), av);
1434*68350Seric 	}
1435*68350Seric 
1436*68350Seric 	for (i = 0; hp[i] != NULL; i++)
1437*68350Seric 		free(hp[i]);
1438*68350Seric 	free(hp);
1439*68350Seric 	return retdata;
1440*68350Seric }
1441*68350Seric 
1442*68350Seric #endif
1443*68350Seric /*
1444*68350Seric **  NeXT NETINFO Modules
1445*68350Seric */
1446*68350Seric 
1447*68350Seric #ifdef NETINFO
1448*68350Seric 
1449*68350Seric #define NETINFO_DEFAULT_DIR		"/aliases"
1450*68350Seric #define NETINFO_DEFAULT_PROPERTY	"members"
1451*68350Seric 
1452*68350Seric 
1453*68350Seric /*
1454*68350Seric **  NI_MAP_OPEN -- open NetInfo Aliases
1455*68350Seric */
1456*68350Seric 
1457*68350Seric bool
1458*68350Seric ni_map_open(map, mode)
1459*68350Seric 	MAP *map;
1460*68350Seric 	int mode;
1461*68350Seric {
1462*68350Seric 	char *p;
1463*68350Seric 
1464*68350Seric 	if (tTd(38, 20))
1465*68350Seric 		printf("ni_map_open: %s\n", map->map_file);
1466*68350Seric 
1467*68350Seric 	if (*map->map_file == '\0')
1468*68350Seric 		map->map_file = NETINFO_DEFAULT_DIR;
1469*68350Seric 
1470*68350Seric 	if (map->map_valcolnm == NULL)
1471*68350Seric 		map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
1472*68350Seric 
1473*68350Seric 	if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags))
1474*68350Seric 		map->map_coldelim = ',';
1475*68350Seric 
1476*68350Seric 	return TRUE;
1477*68350Seric }
1478*68350Seric 
1479*68350Seric 
1480*68350Seric /*
1481*68350Seric **  NI_MAP_LOOKUP -- look up a datum in NetInfo
1482*68350Seric */
1483*68350Seric 
1484*68350Seric char *
1485*68350Seric ni_map_lookup(map, name, av, statp)
1486*68350Seric 	MAP *map;
1487*68350Seric 	char *name;
1488*68350Seric 	char **av;
1489*68350Seric 	int *statp;
1490*68350Seric {
1491*68350Seric 	char *res;
1492*68350Seric 	char *propval;
1493*68350Seric 	extern char *ni_propval();
1494*68350Seric 
1495*68350Seric 	if (tTd(38, 20))
1496*68350Seric 		printf("ni_map_lookup(%s, %s)\n",
1497*68350Seric 			map->map_mname, name);
1498*68350Seric 
1499*68350Seric 	propval = ni_propval(map->map_file, map->map_keycolnm, name,
1500*68350Seric 			     map->map_valcolnm, map->map_coldelim);
1501*68350Seric 
1502*68350Seric 	if (propval == NULL)
1503*68350Seric 		return NULL;
1504*68350Seric 
1505*68350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
1506*68350Seric 		res = map_rewrite(map, name, strlen(name), NULL);
1507*68350Seric 	else
1508*68350Seric 		res = map_rewrite(map, propval, strlen(propval), av);
1509*68350Seric 	free(propval);
1510*68350Seric 	return res;
1511*68350Seric }
1512*68350Seric 
1513*68350Seric #endif
1514*68350Seric /*
1515*68350Seric **  TEXT (unindexed text file) Modules
1516*68350Seric **
1517*68350Seric **	This code donated by Sun Microsystems.
1518*68350Seric */
1519*68350Seric 
1520*68350Seric 
1521*68350Seric /*
1522*68350Seric **  TEXT_MAP_OPEN -- open text table
1523*68350Seric */
1524*68350Seric 
1525*68350Seric bool
1526*68350Seric text_map_open(map, mode)
1527*68350Seric 	MAP *map;
1528*68350Seric 	int mode;
1529*68350Seric {
1530*68350Seric 	struct stat sbuf;
1531*68350Seric 
1532*68350Seric 	if (tTd(38, 2))
1533*68350Seric 		printf("text_map_open(%s, %s, %d)\n",
1534*68350Seric 			map->map_mname, map->map_file, mode);
1535*68350Seric 
1536*68350Seric 	if (mode != O_RDONLY)
1537*68350Seric 	{
1538*68350Seric 		errno = ENODEV;
1539*68350Seric 		return FALSE;
1540*68350Seric 	}
1541*68350Seric 
1542*68350Seric 	if (*map->map_file == '\0')
1543*68350Seric 	{
1544*68350Seric 		if (tTd(38, 2))
1545*68350Seric 			printf("text_map_open: file name required\n");
1546*68350Seric 		return FALSE;
1547*68350Seric 	}
1548*68350Seric 
1549*68350Seric 	if (map->map_file[0] != '/')
1550*68350Seric 	{
1551*68350Seric 		if (tTd(38, 2))
1552*68350Seric 			printf("text_map_open(%s): file name must be fully qualified\n",
1553*68350Seric 				map->map_file);
1554*68350Seric 		return FALSE;
1555*68350Seric 	}
1556*68350Seric 	/* check to see if this map actually accessable */
1557*68350Seric 	if (access(map->map_file, R_OK) <0)
1558*68350Seric 		return FALSE;
1559*68350Seric 
1560*68350Seric 	/* check to see if this map actually exist */
1561*68350Seric 	if (stat(map->map_file, &sbuf) <0)
1562*68350Seric 	{
1563*68350Seric 		if (tTd(38, 2))
1564*68350Seric 			printf("text_map_open(%s): can not stat %s\n",
1565*68350Seric 				map->map_file, map->map_file);
1566*68350Seric 		return FALSE;
1567*68350Seric 	}
1568*68350Seric 
1569*68350Seric 	if (!S_ISREG(sbuf.st_mode))
1570*68350Seric 	{
1571*68350Seric 		if (tTd(38, 2))
1572*68350Seric 			printf("text_map_open(%s): %s is not a file\n",
1573*68350Seric 				map->map_file, map->map_file);
1574*68350Seric 		return FALSE;
1575*68350Seric 	}
1576*68350Seric 
1577*68350Seric 	if (map->map_keycolnm == NULL)
1578*68350Seric 		map->map_keycolno = 0;
1579*68350Seric 	else
1580*68350Seric 	{
1581*68350Seric 		if (!isdigit(*map->map_keycolnm))
1582*68350Seric 		{
1583*68350Seric 			if (tTd(38, 2))
1584*68350Seric 				printf("text_map_open(%s): -k should specify a number, not %s\n",
1585*68350Seric 					map->map_file, map->map_keycolnm);
1586*68350Seric 			return FALSE;
1587*68350Seric 		}
1588*68350Seric 		map->map_keycolno = atoi(map->map_keycolnm);
1589*68350Seric 	}
1590*68350Seric 
1591*68350Seric 	if (map->map_valcolnm == NULL)
1592*68350Seric 		map->map_valcolno = 0;
1593*68350Seric 	else
1594*68350Seric 	{
1595*68350Seric 		if (!isdigit(*map->map_valcolnm))
1596*68350Seric 		{
1597*68350Seric 			if (tTd(38, 2))
1598*68350Seric 				printf("text_map_open(%s): -v should specify a number, not %s\n",
1599*68350Seric 					map->map_file, map->map_valcolnm);
1600*68350Seric 			return FALSE;
1601*68350Seric 		}
1602*68350Seric 		map->map_valcolno = atoi(map->map_valcolnm);
1603*68350Seric 	}
1604*68350Seric 
1605*68350Seric 	if (map->map_coldelim == '\0')
1606*68350Seric 		map->map_coldelim = ':';
1607*68350Seric 
1608*68350Seric 	if (tTd(38, 2))
1609*68350Seric 	{
1610*68350Seric 		printf("text_map_open(%s): delimiter = %c\n",
1611*68350Seric 			map->map_file, map->map_coldelim);
1612*68350Seric 	}
1613*68350Seric 
1614*68350Seric 	return TRUE;
1615*68350Seric }
1616*68350Seric 
1617*68350Seric 
1618*68350Seric /*
1619*68350Seric **  TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
1620*68350Seric */
1621*68350Seric 
1622*68350Seric char *
1623*68350Seric text_map_lookup(map, name, av, statp)
1624*68350Seric 	MAP *map;
1625*68350Seric 	char *name;
1626*68350Seric 	char **av;
1627*68350Seric 	int *statp;
1628*68350Seric {
1629*68350Seric 	char *vp;
1630*68350Seric 	auto int vsize;
1631*68350Seric 	int buflen;
1632*68350Seric 	char search_key[MAXNAME + 1];
1633*68350Seric 	char linebuf[MAXLINE];
1634*68350Seric 	FILE *f;
1635*68350Seric 	char buf[MAXNAME+1];
1636*68350Seric 	char delim;
1637*68350Seric 	int key_idx;
1638*68350Seric 	bool found_it;
1639*68350Seric 	extern char *get_column();
1640*68350Seric 
1641*68350Seric 
1642*68350Seric 	found_it = FALSE;
1643*68350Seric 	if (tTd(38, 20))
1644*68350Seric 		printf("text_map_lookup(%s)\n", name);
1645*68350Seric 
1646*68350Seric 	buflen = strlen(name);
1647*68350Seric 	if (buflen > sizeof search_key - 1)
1648*68350Seric 		buflen = sizeof search_key - 1;
1649*68350Seric 	bcopy(name, search_key, buflen + 1);
1650*68350Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
1651*68350Seric 		makelower(search_key);
1652*68350Seric 
1653*68350Seric 	f = fopen(map->map_file, "r");
1654*68350Seric 	if (f == NULL)
1655*68350Seric 	{
1656*68350Seric 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
1657*68350Seric 		*statp = EX_UNAVAILABLE;
1658*68350Seric 		return NULL;
1659*68350Seric 	}
1660*68350Seric 	key_idx = map->map_keycolno;
1661*68350Seric 	delim = map->map_coldelim;
1662*68350Seric 	while (fgets(linebuf, MAXLINE, f))
1663*68350Seric 	{
1664*68350Seric 		char *lf;
1665*68350Seric 		if (linebuf[0] == '#')
1666*68350Seric 			continue; /* skip comment line */
1667*68350Seric 		if (lf = strchr(linebuf, '\n'))
1668*68350Seric 			*lf = '\0';
1669*68350Seric 		if (!strcasecmp(search_key,
1670*68350Seric 				get_column(linebuf, key_idx, delim, buf)))
1671*68350Seric 		{
1672*68350Seric 			found_it = TRUE;
1673*68350Seric 			break;
1674*68350Seric 		}
1675*68350Seric 	}
1676*68350Seric 	fclose(f);
1677*68350Seric 	if (!found_it)
1678*68350Seric 	{
1679*68350Seric #ifdef MAP_EXIT_STAT
1680*68350Seric 		*statp = EX_NOTFOUND;
1681*68350Seric #endif
1682*68350Seric 		return(NULL);
1683*68350Seric 	}
1684*68350Seric 	vp = get_column(linebuf, map->map_valcolno, delim, buf);
1685*68350Seric 	vsize = strlen(vp);
1686*68350Seric #ifdef MAP_EXIT_STAT
1687*68350Seric 	*statp = EX_OK;
1688*68350Seric #endif
1689*68350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
1690*68350Seric 		return map_rewrite(map, name, strlen(name), NULL);
1691*68350Seric 	else
1692*68350Seric 		return map_rewrite(map, vp, vsize, av);
1693*68350Seric }
1694*68350Seric /*
169560089Seric **  STAB (Symbol Table) Modules
169660089Seric */
169760089Seric 
169860089Seric 
169960089Seric /*
170060207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
170160089Seric */
170260089Seric 
170360089Seric char *
170461707Seric stab_map_lookup(map, name, av, pstat)
170560089Seric 	register MAP *map;
170660089Seric 	char *name;
170761707Seric 	char **av;
170861707Seric 	int *pstat;
170960089Seric {
171060089Seric 	register STAB *s;
171160089Seric 
171260537Seric 	if (tTd(38, 20))
1713*68350Seric 		printf("stab_lookup(%s, %s)\n",
1714*68350Seric 			map->map_mname, name);
171560089Seric 
171660089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
171760089Seric 	if (s != NULL)
171860089Seric 		return (s->s_alias);
171960089Seric 	return (NULL);
172060089Seric }
172160089Seric 
172260089Seric 
172360089Seric /*
172460207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
172560089Seric */
172660089Seric 
172760089Seric void
172860089Seric stab_map_store(map, lhs, rhs)
172960089Seric 	register MAP *map;
173060089Seric 	char *lhs;
173160089Seric 	char *rhs;
173260089Seric {
173360089Seric 	register STAB *s;
173460089Seric 
173560089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
173660089Seric 	s->s_alias = newstr(rhs);
173760089Seric }
173860089Seric 
173960089Seric 
174060089Seric /*
174160207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
174260207Seric **
174360207Seric **	This is a wierd case -- it is only intended as a fallback for
174460207Seric **	aliases.  For this reason, opens for write (only during a
174560207Seric **	"newaliases") always fails, and opens for read open the
174660207Seric **	actual underlying text file instead of the database.
174760089Seric */
174860089Seric 
174960089Seric bool
175060089Seric stab_map_open(map, mode)
175160089Seric 	register MAP *map;
175260089Seric 	int mode;
175360089Seric {
175463835Seric 	FILE *af;
175564284Seric 	struct stat st;
175663835Seric 
175760537Seric 	if (tTd(38, 2))
1758*68350Seric 		printf("stab_map_open(%s, %s)\n",
1759*68350Seric 			map->map_mname, map->map_file);
176060089Seric 
176160089Seric 	if (mode != O_RDONLY)
176260207Seric 	{
176360207Seric 		errno = ENODEV;
176460089Seric 		return FALSE;
176560207Seric 	}
176660089Seric 
176763835Seric 	af = fopen(map->map_file, "r");
176863835Seric 	if (af == NULL)
176963835Seric 		return FALSE;
1770*68350Seric 	readaliases(map, af, FALSE, FALSE);
177164284Seric 
177264284Seric 	if (fstat(fileno(af), &st) >= 0)
177364284Seric 		map->map_mtime = st.st_mtime;
177463835Seric 	fclose(af);
177563835Seric 
177660089Seric 	return TRUE;
177760089Seric }
177860089Seric /*
177960089Seric **  Implicit Modules
178056822Seric **
178160089Seric **	Tries several types.  For back compatibility of aliases.
178256822Seric */
178356822Seric 
178460089Seric 
178560089Seric /*
178660207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
178760089Seric */
178860089Seric 
178960089Seric char *
179060089Seric impl_map_lookup(map, name, av, pstat)
179160089Seric 	MAP *map;
179260089Seric 	char *name;
179356822Seric 	char **av;
179460089Seric 	int *pstat;
179556822Seric {
179660537Seric 	if (tTd(38, 20))
1797*68350Seric 		printf("impl_map_lookup(%s, %s)\n",
1798*68350Seric 			map->map_mname, name);
179956822Seric 
180060089Seric #ifdef NEWDB
180160207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
180260089Seric 		return db_map_lookup(map, name, av, pstat);
180360089Seric #endif
180460089Seric #ifdef NDBM
180560207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
180660089Seric 		return ndbm_map_lookup(map, name, av, pstat);
180760089Seric #endif
180860089Seric 	return stab_map_lookup(map, name, av, pstat);
180960089Seric }
181060089Seric 
181160089Seric /*
181260207Seric **  IMPL_MAP_STORE -- store in open databases
181360089Seric */
181460089Seric 
181560089Seric void
181660089Seric impl_map_store(map, lhs, rhs)
181760089Seric 	MAP *map;
181860089Seric 	char *lhs;
181960089Seric 	char *rhs;
182060089Seric {
182160089Seric #ifdef NEWDB
182260207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
182360089Seric 		db_map_store(map, lhs, rhs);
182460089Seric #endif
182560089Seric #ifdef NDBM
182660207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
182760089Seric 		ndbm_map_store(map, lhs, rhs);
182860089Seric #endif
182960089Seric 	stab_map_store(map, lhs, rhs);
183060089Seric }
183160089Seric 
183260089Seric /*
183360089Seric **  IMPL_MAP_OPEN -- implicit database open
183460089Seric */
183560089Seric 
183660089Seric bool
183760089Seric impl_map_open(map, mode)
183860089Seric 	MAP *map;
183960089Seric 	int mode;
184060089Seric {
184160089Seric 	struct stat stb;
184260089Seric 
184360537Seric 	if (tTd(38, 2))
1844*68350Seric 		printf("impl_map_open(%s, %s, %d)\n",
1845*68350Seric 			map->map_mname, map->map_file, mode);
184660089Seric 
184760089Seric 	if (stat(map->map_file, &stb) < 0)
184856822Seric 	{
184960089Seric 		/* no alias file at all */
185064718Seric 		if (tTd(38, 3))
185164718Seric 			printf("no map file\n");
185260089Seric 		return FALSE;
185356822Seric 	}
185456822Seric 
185560089Seric #ifdef NEWDB
185660207Seric 	map->map_mflags |= MF_IMPL_HASH;
185760089Seric 	if (hash_map_open(map, mode))
185856822Seric 	{
185964250Seric #if defined(NDBM) && defined(NIS)
186060561Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
186160207Seric #endif
186260207Seric 			return TRUE;
186360089Seric 	}
186460207Seric 	else
186560207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
186660089Seric #endif
186760089Seric #ifdef NDBM
186860207Seric 	map->map_mflags |= MF_IMPL_NDBM;
186960089Seric 	if (ndbm_map_open(map, mode))
187060089Seric 	{
187160089Seric 		return TRUE;
187260089Seric 	}
187360207Seric 	else
187460207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
187560089Seric #endif
187656822Seric 
187764650Seric #if defined(NEWDB) || defined(NDBM)
187860089Seric 	if (Verbose)
187960089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
188064964Seric #else
188164964Seric 	if (mode != O_RDONLY)
188264964Seric 		usrerr("Cannot rebuild aliases: no database format defined");
188360207Seric #endif
188460089Seric 
188560207Seric 	return stab_map_open(map, mode);
188656822Seric }
188760089Seric 
188860207Seric 
188960089Seric /*
189060207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
189160089Seric */
189260089Seric 
189360089Seric void
189460207Seric impl_map_close(map)
189560089Seric 	MAP *map;
189660089Seric {
1897*68350Seric 	if (tTd(38, 20))
1898*68350Seric 		printf("impl_map_close(%s, %s, %x)\n",
1899*68350Seric 			map->map_mname, map->map_file, map->map_mflags);
190060089Seric #ifdef NEWDB
190160207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
190260089Seric 	{
190360207Seric 		db_map_close(map);
190460207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
190560089Seric 	}
190660089Seric #endif
190760089Seric 
190860089Seric #ifdef NDBM
190960207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
191060089Seric 	{
191160207Seric 		ndbm_map_close(map);
191260207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
191360089Seric 	}
191460089Seric #endif
191560089Seric }
191660207Seric /*
1917*68350Seric **  User map class.
1918*68350Seric **
1919*68350Seric **	Provides access to the system password file.
1920*68350Seric */
1921*68350Seric 
1922*68350Seric /*
1923*68350Seric **  USER_MAP_OPEN -- open user map
1924*68350Seric **
1925*68350Seric **	Really just binds field names to field numbers.
1926*68350Seric */
1927*68350Seric 
1928*68350Seric bool
1929*68350Seric user_map_open(map, mode)
1930*68350Seric 	MAP *map;
1931*68350Seric 	int mode;
1932*68350Seric {
1933*68350Seric 	if (tTd(38, 2))
1934*68350Seric 		printf("user_map_open(%s)\n", map->map_mname);
1935*68350Seric 
1936*68350Seric 	if (mode != O_RDONLY)
1937*68350Seric 	{
1938*68350Seric 		/* issue a pseudo-error message */
1939*68350Seric #ifdef ENOSYS
1940*68350Seric 		errno = ENOSYS;
1941*68350Seric #else
1942*68350Seric # ifdef EFTYPE
1943*68350Seric 		errno = EFTYPE;
1944*68350Seric # else
1945*68350Seric 		errno = ENXIO;
1946*68350Seric # endif
1947*68350Seric #endif
1948*68350Seric 		return FALSE;
1949*68350Seric 	}
1950*68350Seric 	if (map->map_valcolnm == NULL)
1951*68350Seric 		/* nothing */ ;
1952*68350Seric 	else if (strcasecmp(map->map_valcolnm, "name") == 0)
1953*68350Seric 		map->map_valcolno = 1;
1954*68350Seric 	else if (strcasecmp(map->map_valcolnm, "passwd") == 0)
1955*68350Seric 		map->map_valcolno = 2;
1956*68350Seric 	else if (strcasecmp(map->map_valcolnm, "uid") == 0)
1957*68350Seric 		map->map_valcolno = 3;
1958*68350Seric 	else if (strcasecmp(map->map_valcolnm, "gid") == 0)
1959*68350Seric 		map->map_valcolno = 4;
1960*68350Seric 	else if (strcasecmp(map->map_valcolnm, "gecos") == 0)
1961*68350Seric 		map->map_valcolno = 5;
1962*68350Seric 	else if (strcasecmp(map->map_valcolnm, "dir") == 0)
1963*68350Seric 		map->map_valcolno = 6;
1964*68350Seric 	else if (strcasecmp(map->map_valcolnm, "shell") == 0)
1965*68350Seric 		map->map_valcolno = 7;
1966*68350Seric 	else
1967*68350Seric 	{
1968*68350Seric 		syserr("User map %s: unknown column name %s",
1969*68350Seric 			map->map_mname, map->map_valcolnm);
1970*68350Seric 		return FALSE;
1971*68350Seric 	}
1972*68350Seric 	return TRUE;
1973*68350Seric }
1974*68350Seric 
1975*68350Seric 
1976*68350Seric /*
1977*68350Seric **  USER_MAP_LOOKUP -- look up a user in the passwd file.
1978*68350Seric */
1979*68350Seric 
1980*68350Seric #include <pwd.h>
1981*68350Seric 
1982*68350Seric char *
1983*68350Seric user_map_lookup(map, key, av, statp)
1984*68350Seric 	MAP *map;
1985*68350Seric 	char *key;
1986*68350Seric 	char **av;
1987*68350Seric 	int *statp;
1988*68350Seric {
1989*68350Seric 	struct passwd *pw;
1990*68350Seric 
1991*68350Seric 	if (tTd(38, 20))
1992*68350Seric 		printf("user_map_lookup(%s, %s)\n",
1993*68350Seric 			map->map_mname, key);
1994*68350Seric 
1995*68350Seric 	pw = getpwnam(key);
1996*68350Seric 	if (pw == NULL)
1997*68350Seric 		return NULL;
1998*68350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
1999*68350Seric 		return map_rewrite(map, key, strlen(key), NULL);
2000*68350Seric 	else
2001*68350Seric 	{
2002*68350Seric 		char *rwval;
2003*68350Seric 		char buf[30];
2004*68350Seric 
2005*68350Seric 		switch (map->map_valcolno)
2006*68350Seric 		{
2007*68350Seric 		  case 0:
2008*68350Seric 		  case 1:
2009*68350Seric 			rwval = pw->pw_name;
2010*68350Seric 			break;
2011*68350Seric 
2012*68350Seric 		  case 2:
2013*68350Seric 			rwval = pw->pw_passwd;
2014*68350Seric 			break;
2015*68350Seric 
2016*68350Seric 		  case 3:
2017*68350Seric 			sprintf(buf, "%d", pw->pw_uid);
2018*68350Seric 			rwval = buf;
2019*68350Seric 			break;
2020*68350Seric 
2021*68350Seric 		  case 4:
2022*68350Seric 			sprintf(buf, "%d", pw->pw_gid);
2023*68350Seric 			rwval = buf;
2024*68350Seric 			break;
2025*68350Seric 
2026*68350Seric 		  case 5:
2027*68350Seric 			rwval = pw->pw_gecos;
2028*68350Seric 			break;
2029*68350Seric 
2030*68350Seric 		  case 6:
2031*68350Seric 			rwval = pw->pw_dir;
2032*68350Seric 			break;
2033*68350Seric 
2034*68350Seric 		  case 7:
2035*68350Seric 			rwval = pw->pw_shell;
2036*68350Seric 			break;
2037*68350Seric 		}
2038*68350Seric 		return map_rewrite(map, rwval, strlen(rwval), av);
2039*68350Seric 	}
2040*68350Seric }
2041*68350Seric /*
2042*68350Seric **  BESTMX -- find the best MX for a name
2043*68350Seric **
2044*68350Seric **	This is really a hack, but I don't see any obvious way
2045*68350Seric **	to generalize it at the moment.
2046*68350Seric */
2047*68350Seric 
2048*68350Seric #if NAMED_BIND
2049*68350Seric 
2050*68350Seric char *
2051*68350Seric bestmx_map_lookup(map, name, av, statp)
2052*68350Seric 	MAP *map;
2053*68350Seric 	char *name;
2054*68350Seric 	char **av;
2055*68350Seric 	int *statp;
2056*68350Seric {
2057*68350Seric         int nmx;
2058*68350Seric         auto int rcode;
2059*68350Seric         char *mxhosts[MAXMXHOSTS + 1];
2060*68350Seric 
2061*68350Seric 	nmx = getmxrr(name, mxhosts, FALSE, &rcode);
2062*68350Seric 	if (nmx <= 0)
2063*68350Seric 		return NULL;
2064*68350Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
2065*68350Seric 		return map_rewrite(map, name, strlen(name), NULL);
2066*68350Seric 	else
2067*68350Seric 		return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av);
2068*68350Seric }
2069*68350Seric 
2070*68350Seric #endif
2071*68350Seric /*
2072*68350Seric **  Sequenced map type.
2073*68350Seric **
2074*68350Seric **	Tries each map in order until something matches, much like
2075*68350Seric **	implicit.  Stores go to the first map in the list that can
2076*68350Seric **	support storing.
2077*68350Seric **
2078*68350Seric **	This is slightly unusual in that there are two interfaces.
2079*68350Seric **	The "sequence" interface lets you stack maps arbitrarily.
2080*68350Seric **	The "switch" interface builds a sequence map by looking
2081*68350Seric **	at a system-dependent configuration file such as
2082*68350Seric **	/etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
2083*68350Seric **
2084*68350Seric **	We don't need an explicit open, since all maps are
2085*68350Seric **	opened during startup, including underlying maps.
2086*68350Seric */
2087*68350Seric 
2088*68350Seric /*
2089*68350Seric **  SEQ_MAP_PARSE -- Sequenced map parsing
2090*68350Seric */
2091*68350Seric 
2092*68350Seric bool
2093*68350Seric seq_map_parse(map, ap)
2094*68350Seric 	MAP *map;
2095*68350Seric 	char *ap;
2096*68350Seric {
2097*68350Seric 	int maxmap;
2098*68350Seric 
2099*68350Seric 	if (tTd(38, 2))
2100*68350Seric 		printf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
2101*68350Seric 	maxmap = 0;
2102*68350Seric 	while (*ap != '\0')
2103*68350Seric 	{
2104*68350Seric 		register char *p;
2105*68350Seric 		STAB *s;
2106*68350Seric 
2107*68350Seric 		/* find beginning of map name */
2108*68350Seric 		while (isascii(*ap) && isspace(*ap))
2109*68350Seric 			ap++;
2110*68350Seric 		for (p = ap; isascii(*p) && isalnum(*p); p++)
2111*68350Seric 			continue;
2112*68350Seric 		if (*p != '\0')
2113*68350Seric 			*p++ = '\0';
2114*68350Seric 		while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
2115*68350Seric 			p++;
2116*68350Seric 		if (*ap == '\0')
2117*68350Seric 		{
2118*68350Seric 			ap = p;
2119*68350Seric 			continue;
2120*68350Seric 		}
2121*68350Seric 		s = stab(ap, ST_MAP, ST_FIND);
2122*68350Seric 		if (s == NULL)
2123*68350Seric 		{
2124*68350Seric 			syserr("Sequence map %s: unknown member map %s",
2125*68350Seric 				map->map_mname, ap);
2126*68350Seric 		}
2127*68350Seric 		else if (maxmap == MAXMAPSTACK)
2128*68350Seric 		{
2129*68350Seric 			syserr("Sequence map %s: too many member maps (%d max)",
2130*68350Seric 				map->map_mname, MAXMAPSTACK);
2131*68350Seric 			maxmap++;
2132*68350Seric 		}
2133*68350Seric 		else if (maxmap < MAXMAPSTACK)
2134*68350Seric 		{
2135*68350Seric 			map->map_stack[maxmap++] = &s->s_map;
2136*68350Seric 		}
2137*68350Seric 		ap = p;
2138*68350Seric 	}
2139*68350Seric 	return TRUE;
2140*68350Seric }
2141*68350Seric 
2142*68350Seric 
2143*68350Seric /*
2144*68350Seric **  SWITCH_MAP_OPEN -- open a switched map
2145*68350Seric **
2146*68350Seric **	This looks at the system-dependent configuration and builds
2147*68350Seric **	a sequence map that does the same thing.
2148*68350Seric **
2149*68350Seric **	Every system must define a switch_map_find routine in conf.c
2150*68350Seric **	that will return the list of service types associated with a
2151*68350Seric **	given service class.
2152*68350Seric */
2153*68350Seric 
2154*68350Seric bool
2155*68350Seric switch_map_open(map, mode)
2156*68350Seric 	MAP *map;
2157*68350Seric 	int mode;
2158*68350Seric {
2159*68350Seric 	int mapno;
2160*68350Seric 	int nmaps;
2161*68350Seric 	char *maptype[MAXMAPSTACK];
2162*68350Seric 
2163*68350Seric 	if (tTd(38, 2))
2164*68350Seric 		printf("switch_map_open(%s, %s, %d)\n",
2165*68350Seric 			map->map_mname, map->map_file, mode);
2166*68350Seric 
2167*68350Seric 	nmaps = switch_map_find(map->map_file, maptype, map->map_return);
2168*68350Seric 	if (tTd(38, 19))
2169*68350Seric 	{
2170*68350Seric 		printf("\tswitch_map_find => %d\n", nmaps);
2171*68350Seric 		for (mapno = 0; mapno < nmaps; mapno++)
2172*68350Seric 			printf("\t\t%s\n", maptype[mapno]);
2173*68350Seric 	}
2174*68350Seric 	if (nmaps <= 0 || nmaps > MAXMAPSTACK)
2175*68350Seric 		return FALSE;
2176*68350Seric 
2177*68350Seric 	for (mapno = 0; mapno < nmaps; mapno++)
2178*68350Seric 	{
2179*68350Seric 		register STAB *s;
2180*68350Seric 		char nbuf[MAXNAME + 1];
2181*68350Seric 
2182*68350Seric 		if (maptype[mapno] == NULL)
2183*68350Seric 			continue;
2184*68350Seric 		(void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]);
2185*68350Seric 		s = stab(nbuf, ST_MAP, ST_FIND);
2186*68350Seric 		if (s == NULL)
2187*68350Seric 		{
2188*68350Seric 			syserr("Switch map %s: unknown member map %s",
2189*68350Seric 				map->map_mname, nbuf);
2190*68350Seric 		}
2191*68350Seric 		else
2192*68350Seric 		{
2193*68350Seric 			map->map_stack[mapno] = &s->s_map;
2194*68350Seric 			if (tTd(38, 4))
2195*68350Seric 				printf("\tmap_stack[%d] = %s:%s\n",
2196*68350Seric 					mapno, s->s_map.map_class->map_cname,
2197*68350Seric 					nbuf);
2198*68350Seric 		}
2199*68350Seric 	}
2200*68350Seric 	return TRUE;
2201*68350Seric }
2202*68350Seric 
2203*68350Seric 
2204*68350Seric /*
2205*68350Seric **  SEQ_MAP_CLOSE -- close all underlying maps
2206*68350Seric */
2207*68350Seric 
2208*68350Seric seq_map_close(map)
2209*68350Seric 	MAP *map;
2210*68350Seric {
2211*68350Seric 	int mapno;
2212*68350Seric 
2213*68350Seric 	if (tTd(38, 20))
2214*68350Seric 		printf("seq_map_close(%s)\n", map->map_mname);
2215*68350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
2216*68350Seric 	{
2217*68350Seric 		MAP *mm = map->map_stack[mapno];
2218*68350Seric 
2219*68350Seric 		if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
2220*68350Seric 			continue;
2221*68350Seric 		mm->map_class->map_close(mm);
2222*68350Seric 	}
2223*68350Seric }
2224*68350Seric 
2225*68350Seric 
2226*68350Seric /*
2227*68350Seric **  SEQ_MAP_LOOKUP -- sequenced map lookup
2228*68350Seric */
2229*68350Seric 
2230*68350Seric char *
2231*68350Seric seq_map_lookup(map, key, args, pstat)
2232*68350Seric 	MAP *map;
2233*68350Seric 	char *key;
2234*68350Seric 	char **args;
2235*68350Seric 	int *pstat;
2236*68350Seric {
2237*68350Seric 	int mapno;
2238*68350Seric 	int mapbit = 0x01;
2239*68350Seric 
2240*68350Seric 	if (tTd(38, 20))
2241*68350Seric 		printf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
2242*68350Seric 
2243*68350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
2244*68350Seric 	{
2245*68350Seric 		MAP *mm = map->map_stack[mapno];
2246*68350Seric 		int stat = 0;
2247*68350Seric 		char *rv;
2248*68350Seric 
2249*68350Seric 		if (mm == NULL)
2250*68350Seric 			continue;
2251*68350Seric 		if (!bitset(MF_OPEN, mm->map_mflags))
2252*68350Seric 		{
2253*68350Seric 			if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
2254*68350Seric 			{
2255*68350Seric 				*pstat = EX_UNAVAILABLE;
2256*68350Seric 				return NULL;
2257*68350Seric 			}
2258*68350Seric 			continue;
2259*68350Seric 		}
2260*68350Seric 		rv = mm->map_class->map_lookup(mm, key, args, &stat);
2261*68350Seric 		if (rv != NULL)
2262*68350Seric 			return rv;
2263*68350Seric 		if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND]))
2264*68350Seric 			return NULL;
2265*68350Seric 		if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN]))
2266*68350Seric 		{
2267*68350Seric 			*pstat = stat;
2268*68350Seric 			return NULL;
2269*68350Seric 		}
2270*68350Seric 	}
2271*68350Seric 	return NULL;
2272*68350Seric }
2273*68350Seric 
2274*68350Seric 
2275*68350Seric /*
2276*68350Seric **  SEQ_MAP_STORE -- sequenced map store
2277*68350Seric */
2278*68350Seric 
2279*68350Seric void
2280*68350Seric seq_map_store(map, key, val)
2281*68350Seric 	MAP *map;
2282*68350Seric 	char *key;
2283*68350Seric 	char *val;
2284*68350Seric {
2285*68350Seric 	int mapno;
2286*68350Seric 
2287*68350Seric 	if (tTd(38, 12))
2288*68350Seric 		printf("seq_map_store(%s, %s, %s)\n",
2289*68350Seric 			map->map_mname, key, val);
2290*68350Seric 
2291*68350Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
2292*68350Seric 	{
2293*68350Seric 		MAP *mm = map->map_stack[mapno];
2294*68350Seric 
2295*68350Seric 		if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
2296*68350Seric 			continue;
2297*68350Seric 
2298*68350Seric 		mm->map_class->map_store(mm, key, val);
2299*68350Seric 		return;
2300*68350Seric 	}
2301*68350Seric 	syserr("seq_map_store(%s, %s, %s): no writable map",
2302*68350Seric 		map->map_mname, key, val);
2303*68350Seric }
2304*68350Seric /*
230560207Seric **  NULL stubs
230660089Seric */
230760089Seric 
230860207Seric bool
230960207Seric null_map_open(map, mode)
231060089Seric 	MAP *map;
231160207Seric 	int mode;
231260089Seric {
231360207Seric 	return TRUE;
231460089Seric }
231560089Seric 
231660207Seric void
231760207Seric null_map_close(map)
231860207Seric 	MAP *map;
231960089Seric {
232060207Seric 	return;
232160207Seric }
232260089Seric 
232360207Seric void
232460207Seric null_map_store(map, key, val)
232560207Seric 	MAP *map;
232660207Seric 	char *key;
232760207Seric 	char *val;
232860089Seric {
232960207Seric 	return;
233060089Seric }
2331*68350Seric 
2332*68350Seric 
2333*68350Seric /*
2334*68350Seric **  BOGUS stubs
2335*68350Seric */
2336*68350Seric 
2337*68350Seric char *
2338*68350Seric bogus_map_lookup(map, key, args, pstat)
2339*68350Seric 	MAP *map;
2340*68350Seric 	char *key;
2341*68350Seric 	char **args;
2342*68350Seric 	int *pstat;
2343*68350Seric {
2344*68350Seric 	*pstat = EX_TEMPFAIL;
2345*68350Seric 	return NULL;
2346*68350Seric }
2347*68350Seric 
2348*68350Seric MAPCLASS	BogusMapClass =
2349*68350Seric {
2350*68350Seric 	"bogus-map",		NULL,		0,
2351*68350Seric 	NULL,		bogus_map_lookup,	null_map_store,
2352*68350Seric 	null_map_open,	null_map_close,
2353*68350Seric };
2354