xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 67895)
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*67895Seric static char sccsid[] = "@(#)map.c	8.35 (Berkeley) 11/08/94";
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;
12167726Seric 
12267726Seric 		  case 'k':
12367726Seric 			while (isascii(*++p) && isspace(*p))
12467726Seric 				continue;
12567726Seric 			map->map_keycolnm = p;
12667726Seric 			break;
12767726Seric 
12867726Seric 		  case 'v':
12967726Seric 			while (isascii(*++p) && isspace(*p))
13067726Seric 				continue;
13167726Seric 			map->map_valcolnm = p;
13267726Seric 			break;
13367726Seric 
13467726Seric 		  case 'z':
13567726Seric 			if (*++p != '\\')
13667726Seric 				map->map_coldelim = *p;
13767726Seric 			else
13867726Seric 			{
13967726Seric 				switch (*++p)
14067726Seric 				{
14167726Seric 				  case 'n':
14267726Seric 					map->map_coldelim = '\n';
14367726Seric 					break;
14467726Seric 
14567726Seric 				  case 't':
14667726Seric 					map->map_coldelim = '\t';
14767726Seric 					break;
14867726Seric 
14967726Seric 				  default:
15067726Seric 					map->map_coldelim = '\\';
15167726Seric 				}
15267726Seric 			}
15367726Seric 			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);
16267726Seric 	if (map->map_keycolnm != NULL)
16367726Seric 		map->map_keycolnm = newstr(map->map_keycolnm);
16467726Seric 	if (map->map_valcolnm != NULL)
16567726Seric 		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 
18256822Seric 	if (map->map_file == NULL)
18357208Seric 	{
18460089Seric 		syserr("No file name for %s map %s",
18560089Seric 			map->map_class->map_cname, map->map_mname);
18656822Seric 		return FALSE;
18757208Seric 	}
18860089Seric 	return TRUE;
18960089Seric }
19060089Seric /*
19160089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
19260089Seric **
19360089Seric **	It also adds the map_app string.  It can be used as a utility
19460089Seric **	in the map_lookup method.
19560089Seric **
19660089Seric **	Parameters:
19760089Seric **		map -- the map that causes this.
19860089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
19960089Seric **		slen -- the length of s.
20060089Seric **		av -- arguments to interpolate into buf.
20160089Seric **
20260089Seric **	Returns:
203*67895Seric **		Pointer to rewritten result.  This is static data that
204*67895Seric **		should be copied if it is to be saved!
20560089Seric **
20660089Seric **	Side Effects:
20760089Seric **		none.
20860089Seric */
20960089Seric 
21060089Seric char *
21160089Seric map_rewrite(map, s, slen, av)
21260089Seric 	register MAP *map;
21360089Seric 	register char *s;
21460089Seric 	int slen;
21560089Seric 	char **av;
21660089Seric {
21760089Seric 	register char *bp;
21860089Seric 	register char c;
21960089Seric 	char **avp;
22060089Seric 	register char *ap;
22160089Seric 	int i;
22260089Seric 	int len;
223*67895Seric 	static int buflen = -1;
224*67895Seric 	static char *buf = NULL;
22560089Seric 
22660537Seric 	if (tTd(39, 1))
22760089Seric 	{
22860256Seric 		printf("map_rewrite(%.*s), av =", slen, s);
22960256Seric 		if (av == NULL)
23060256Seric 			printf(" (nullv)");
23160256Seric 		else
23260256Seric 		{
23360256Seric 			for (avp = av; *avp != NULL; avp++)
23460256Seric 				printf("\n\t%s", *avp);
23560256Seric 		}
23660256Seric 		printf("\n");
23760089Seric 	}
23860089Seric 
23960089Seric 	/* count expected size of output (can safely overestimate) */
24060089Seric 	i = len = slen;
24160089Seric 	if (av != NULL)
24260089Seric 	{
24360089Seric 		bp = s;
24460089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
24560089Seric 		{
24660089Seric 			if (c != '%')
24760089Seric 				continue;
24860089Seric 			if (--i < 0)
24960089Seric 				break;
25060089Seric 			c = *bp++;
25160089Seric 			if (!(isascii(c) && isdigit(c)))
25260089Seric 				continue;
25363937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
25460089Seric 				continue;
25560089Seric 			if (*avp == NULL)
25660089Seric 				continue;
25760089Seric 			len += strlen(*avp);
25860089Seric 		}
25960089Seric 	}
26060089Seric 	if (map->map_app != NULL)
26160089Seric 		len += strlen(map->map_app);
262*67895Seric 	if (buflen < ++len)
26360089Seric 	{
26460089Seric 		/* need to malloc additional space */
265*67895Seric 		buflen = len;
266*67895Seric 		if (buf != NULL)
267*67895Seric 			free(buf);
268*67895Seric 		buf = xalloc(buflen);
26960089Seric 	}
27060089Seric 
271*67895Seric 	bp = buf;
27260089Seric 	if (av == NULL)
27360089Seric 	{
27460089Seric 		bcopy(s, bp, slen);
27560089Seric 		bp += slen;
27660089Seric 	}
27760089Seric 	else
27860089Seric 	{
27960089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
28060089Seric 		{
28160089Seric 			if (c != '%')
28260089Seric 			{
28360089Seric   pushc:
28460089Seric 				*bp++ = c;
28560089Seric 				continue;
28660089Seric 			}
28760089Seric 			if (--slen < 0 || (c = *s++) == '\0')
28860089Seric 				c = '%';
28960089Seric 			if (c == '%')
29060089Seric 				goto pushc;
29160089Seric 			if (!(isascii(c) && isdigit(c)))
29260089Seric 			{
29360089Seric 				*bp++ = '%';
29460089Seric 				goto pushc;
29560089Seric 			}
29663937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
29760089Seric 				continue;
29860089Seric 			if (*avp == NULL)
29960089Seric 				continue;
30060089Seric 
30160089Seric 			/* transliterate argument into output string */
30260089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
30360089Seric 				*bp++ = c;
30460089Seric 		}
30560089Seric 	}
30660089Seric 	if (map->map_app != NULL)
30760089Seric 		strcpy(bp, map->map_app);
30860089Seric 	else
30960089Seric 		*bp = '\0';
31060537Seric 	if (tTd(39, 1))
311*67895Seric 		printf("map_rewrite => %s\n", buf);
312*67895Seric 	return buf;
31360089Seric }
31460089Seric /*
31560537Seric **  INITMAPS -- initialize for aliasing
31660537Seric **
31760537Seric **	Parameters:
31860537Seric **		rebuild -- if TRUE, this rebuilds the cached versions.
31960537Seric **		e -- current envelope.
32060537Seric **
32160537Seric **	Returns:
32260537Seric **		none.
32360537Seric **
32460537Seric **	Side Effects:
32560537Seric **		initializes aliases:
32660537Seric **		if NDBM:  opens the database.
32760537Seric **		if ~NDBM: reads the aliases into the symbol table.
32860537Seric */
32960537Seric 
33060537Seric initmaps(rebuild, e)
33160537Seric 	bool rebuild;
33260537Seric 	register ENVELOPE *e;
33360537Seric {
33460537Seric 	extern void map_init();
33560537Seric 
33664671Seric #ifdef XDEBUG
33764671Seric 	checkfd012("entering initmaps");
33864671Seric #endif
33960537Seric 	CurEnv = e;
34065085Seric 	if (rebuild)
34165085Seric 	{
34265085Seric 		stabapply(map_init, 1);
34365085Seric 		stabapply(map_init, 2);
34465085Seric 	}
34565085Seric 	else
34665085Seric 	{
34765085Seric 		stabapply(map_init, 0);
34865085Seric 	}
34964671Seric #ifdef XDEBUG
35064671Seric 	checkfd012("exiting initmaps");
35164671Seric #endif
35260537Seric }
35360537Seric 
35460537Seric void
35560537Seric map_init(s, rebuild)
35660537Seric 	register STAB *s;
35760537Seric 	int rebuild;
35860537Seric {
35960537Seric 	register MAP *map;
36060537Seric 
36160537Seric 	/* has to be a map */
36260537Seric 	if (s->s_type != ST_MAP)
36360537Seric 		return;
36460537Seric 
36560537Seric 	map = &s->s_map;
36660537Seric 	if (!bitset(MF_VALID, map->map_mflags))
36760537Seric 		return;
36860537Seric 
36960537Seric 	if (tTd(38, 2))
37067726Seric 		printf("map_init(%s:%s, %s, %d)\n",
37164690Seric 			map->map_class->map_cname == NULL ? "NULL" :
37264690Seric 				map->map_class->map_cname,
37367726Seric 			map->map_mname == NULL ? "NULL" : map->map_mname,
37465085Seric 			map->map_file == NULL ? "NULL" : map->map_file,
37565085Seric 			rebuild);
37660537Seric 
37765085Seric 	if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&
37865085Seric 		    bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))
37965085Seric 	{
38065085Seric 		if (tTd(38, 3))
38165085Seric 			printf("\twrong pass\n");
38265085Seric 		return;
38365085Seric 	}
38465085Seric 
38560537Seric 	/* if already open, close it (for nested open) */
38660537Seric 	if (bitset(MF_OPEN, map->map_mflags))
38760537Seric 	{
38860537Seric 		map->map_class->map_close(map);
38960537Seric 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
39060537Seric 	}
39160537Seric 
39265085Seric 	if (rebuild == 2)
39360537Seric 	{
39465085Seric 		rebuildaliases(map, FALSE);
39560537Seric 	}
39660537Seric 	else
39760537Seric 	{
39860537Seric 		if (map->map_class->map_open(map, O_RDONLY))
39960537Seric 		{
40060537Seric 			if (tTd(38, 4))
40167726Seric 				printf("\t%s:%s %s: valid\n",
40264690Seric 					map->map_class->map_cname == NULL ? "NULL" :
40364690Seric 						map->map_class->map_cname,
40467726Seric 					map->map_mname == NULL ? "NULL" :
40567726Seric 						map->map_mname,
40664690Seric 					map->map_file == NULL ? "NULL" :
40764690Seric 						map->map_file);
40860537Seric 			map->map_mflags |= MF_OPEN;
40960537Seric 		}
41060537Seric 		else if (tTd(38, 4))
41167726Seric 			printf("\t%s:%s %s: invalid: %s\n",
41264690Seric 				map->map_class->map_cname == NULL ? "NULL" :
41364690Seric 					map->map_class->map_cname,
41467726Seric 				map->map_mname == NULL ? "NULL" :
41567726Seric 					map->map_mname,
41664690Seric 				map->map_file == NULL ? "NULL" :
41764690Seric 					map->map_file,
41860537Seric 				errstring(errno));
41960537Seric 	}
42060537Seric }
42160537Seric /*
42260089Seric **  NDBM modules
42360089Seric */
42460089Seric 
42560089Seric #ifdef NDBM
42660089Seric 
42760089Seric /*
42860089Seric **  DBM_MAP_OPEN -- DBM-style map open
42960089Seric */
43060089Seric 
43160089Seric bool
43260089Seric ndbm_map_open(map, mode)
43360089Seric 	MAP *map;
43460089Seric 	int mode;
43560089Seric {
43664284Seric 	register DBM *dbm;
43764284Seric 	struct stat st;
43860089Seric 
43960537Seric 	if (tTd(38, 2))
44067726Seric 		printf("ndbm_map_open(%s, %s, %d)\n",
44167726Seric 			map->map_mname, map->map_file, mode);
44260089Seric 
44360207Seric 	if (mode == O_RDWR)
44460207Seric 		mode |= O_CREAT|O_TRUNC;
44560207Seric 
44660089Seric 	/* open the database */
44760089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
44856822Seric 	if (dbm == NULL)
44956822Seric 	{
45064718Seric #ifdef MAYBENEXTRELEASE
45164718Seric 		if (aliaswait(map, ".pag", FALSE))
45264718Seric 			return TRUE;
45364718Seric #endif
45460207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
45556836Seric 			syserr("Cannot open DBM database %s", map->map_file);
45656822Seric 		return FALSE;
45756822Seric 	}
45860089Seric 	map->map_db1 = (void *) dbm;
45964964Seric 	if (mode == O_RDONLY)
46064964Seric 	{
46164964Seric 		if (bitset(MF_ALIAS, map->map_mflags) &&
46264964Seric 		    !aliaswait(map, ".pag", TRUE))
46364718Seric 			return FALSE;
46464964Seric 	}
46564964Seric 	else
46664964Seric 	{
46764964Seric 		int fd;
46864964Seric 
46964964Seric 		/* exclusive lock for duration of rebuild */
47064964Seric 		fd = dbm_dirfno((DBM *) map->map_db1);
47164964Seric 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
47264964Seric 		    lockfile(fd, map->map_file, ".dir", LOCK_EX))
47364964Seric 			map->map_mflags |= MF_LOCKED;
47464964Seric 	}
47564718Seric 	if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
47664284Seric 		map->map_mtime = st.st_mtime;
47756822Seric 	return TRUE;
47856822Seric }
47960089Seric 
48060089Seric 
48160089Seric /*
48256822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
48356822Seric */
48456822Seric 
48556822Seric char *
48660089Seric ndbm_map_lookup(map, name, av, statp)
48756822Seric 	MAP *map;
48860089Seric 	char *name;
48956822Seric 	char **av;
49059084Seric 	int *statp;
49156822Seric {
49256822Seric 	datum key, val;
49364373Seric 	int fd;
49460089Seric 	char keybuf[MAXNAME + 1];
49556822Seric 
49660537Seric 	if (tTd(38, 20))
49767726Seric 		printf("ndbm_map_lookup(%s, %s)\n",
49867726Seric 			map->map_mname, name);
49960089Seric 
50060089Seric 	key.dptr = name;
50160089Seric 	key.dsize = strlen(name);
50260207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
50357014Seric 	{
50460089Seric 		if (key.dsize > sizeof keybuf - 1)
50560089Seric 			key.dsize = sizeof keybuf - 1;
50660089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
50760089Seric 		makelower(keybuf);
50860089Seric 		key.dptr = keybuf;
50957014Seric 	}
51064373Seric 	fd = dbm_dirfno((DBM *) map->map_db1);
51164388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
51264373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
51363753Seric 	val.dptr = NULL;
51463753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
51563753Seric 	{
51663753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
51763753Seric 		if (val.dptr != NULL)
51863753Seric 			map->map_mflags &= ~MF_TRY1NULL;
51963753Seric 	}
52063753Seric 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
52163753Seric 	{
52256822Seric 		key.dsize++;
52363753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
52463753Seric 		if (val.dptr != NULL)
52563753Seric 			map->map_mflags &= ~MF_TRY0NULL;
52663753Seric 	}
52764388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
52864373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
52956822Seric 	if (val.dptr == NULL)
53056822Seric 		return NULL;
53160207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
53263753Seric 		return map_rewrite(map, name, strlen(name), NULL);
53363753Seric 	else
53463753Seric 		return map_rewrite(map, val.dptr, val.dsize, av);
53556822Seric }
53656822Seric 
53756822Seric 
53856822Seric /*
53960089Seric **  DBM_MAP_STORE -- store a datum in the database
54056822Seric */
54156822Seric 
54260089Seric void
54360089Seric ndbm_map_store(map, lhs, rhs)
54460089Seric 	register MAP *map;
54560089Seric 	char *lhs;
54660089Seric 	char *rhs;
54760089Seric {
54860089Seric 	datum key;
54960089Seric 	datum data;
55060089Seric 	int stat;
55160089Seric 
55260537Seric 	if (tTd(38, 12))
55367726Seric 		printf("ndbm_map_store(%s, %s, %s)\n",
55467726Seric 			map->map_mname, lhs, rhs);
55560089Seric 
55660089Seric 	key.dsize = strlen(lhs);
55760089Seric 	key.dptr = lhs;
55860089Seric 
55960089Seric 	data.dsize = strlen(rhs);
56060089Seric 	data.dptr = rhs;
56160089Seric 
56260207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
56360089Seric 	{
56460089Seric 		key.dsize++;
56560089Seric 		data.dsize++;
56660089Seric 	}
56760089Seric 
56860089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
56960089Seric 	if (stat > 0)
57060089Seric 	{
57160089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
57260089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
57360089Seric 	}
57460089Seric 	if (stat != 0)
57560089Seric 		syserr("readaliases: dbm put (%s)", lhs);
57660089Seric }
57760089Seric 
57860089Seric 
57960089Seric /*
58060207Seric **  NDBM_MAP_CLOSE -- close the database
58160089Seric */
58260089Seric 
58360089Seric void
58460089Seric ndbm_map_close(map)
58560089Seric 	register MAP  *map;
58660089Seric {
58766773Seric 	if (tTd(38, 9))
58867726Seric 		printf("ndbm_map_close(%s, %s, %x)\n",
58967726Seric 			map->map_mname, map->map_file, map->map_mflags);
59066773Seric 
59160207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
59260089Seric 	{
59364250Seric #ifdef NIS
59464075Seric 		bool inclnull;
59560089Seric 		char buf[200];
59660089Seric 
59764075Seric 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
59864075Seric 		map->map_mflags &= ~MF_INCLNULL;
59964075Seric 
60060089Seric 		(void) sprintf(buf, "%010ld", curtime());
60160089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
60260089Seric 
60364941Seric 		(void) gethostname(buf, sizeof buf);
60460089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
60564075Seric 
60664075Seric 		if (inclnull)
60764075Seric 			map->map_mflags |= MF_INCLNULL;
60860089Seric #endif
60960089Seric 
61060089Seric 		/* write out the distinguished alias */
61160089Seric 		ndbm_map_store(map, "@", "@");
61260089Seric 	}
61360089Seric 	dbm_close((DBM *) map->map_db1);
61460089Seric }
61560089Seric 
61660089Seric #endif
61760089Seric /*
61860582Seric **  NEWDB (Hash and BTree) Modules
61960089Seric */
62060089Seric 
62160089Seric #ifdef NEWDB
62260089Seric 
62360089Seric /*
62460582Seric **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
62560582Seric **
62660582Seric **	These do rather bizarre locking.  If you can lock on open,
62760582Seric **	do that to avoid the condition of opening a database that
62860582Seric **	is being rebuilt.  If you don't, we'll try to fake it, but
62960582Seric **	there will be a race condition.  If opening for read-only,
63060582Seric **	we immediately release the lock to avoid freezing things up.
63160582Seric **	We really ought to hold the lock, but guarantee that we won't
63260582Seric **	be pokey about it.  That's hard to do.
63360089Seric */
63460089Seric 
63556822Seric bool
63660089Seric bt_map_open(map, mode)
63756822Seric 	MAP *map;
63860089Seric 	int mode;
63956822Seric {
64056822Seric 	DB *db;
64160228Seric 	int i;
64260582Seric 	int omode;
64364373Seric 	int fd;
64464284Seric 	struct stat st;
64560089Seric 	char buf[MAXNAME];
64656822Seric 
64760537Seric 	if (tTd(38, 2))
64867726Seric 		printf("bt_map_open(%s, %s, %d)\n",
64967726Seric 			map->map_mname, map->map_file, mode);
65060089Seric 
65160582Seric 	omode = mode;
65260582Seric 	if (omode == O_RDWR)
65360582Seric 	{
65460582Seric 		omode |= O_CREAT|O_TRUNC;
65565830Seric #if defined(O_EXLOCK) && HASFLOCK
65660582Seric 		omode |= O_EXLOCK;
65766843Seric # if !OLD_NEWDB
65860582Seric 	}
65960582Seric 	else
66060582Seric 	{
66160582Seric 		omode |= O_SHLOCK;
66260582Seric # endif
66360582Seric #endif
66460582Seric 	}
66560207Seric 
66660228Seric 	(void) strcpy(buf, map->map_file);
66760228Seric 	i = strlen(buf);
66860228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
66960228Seric 		(void) strcat(buf, ".db");
67060582Seric 	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
67156822Seric 	if (db == NULL)
67256822Seric 	{
67364718Seric #ifdef MAYBENEXTRELEASE
67464718Seric 		if (aliaswait(map, ".db", FALSE))
67564718Seric 			return TRUE;
67664718Seric #endif
67760207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
67856836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
67956822Seric 		return FALSE;
68056822Seric 	}
68167173Seric #if !OLD_NEWDB
68264373Seric 	fd = db->fd(db);
68367187Seric # if HASFLOCK
68467187Seric #  if !defined(O_EXLOCK)
68564373Seric 	if (mode == O_RDWR && fd >= 0)
68664388Seric 	{
68764388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
68864388Seric 			map->map_mflags |= MF_LOCKED;
68964388Seric 	}
69067187Seric #  else
69164373Seric 	if (mode == O_RDONLY && fd >= 0)
69264373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
69364388Seric 	else
69464388Seric 		map->map_mflags |= MF_LOCKED;
69567187Seric #  endif
69660582Seric # endif
69760582Seric #endif
69860585Seric 
69960585Seric 	/* try to make sure that at least the database header is on disk */
70060585Seric 	if (mode == O_RDWR)
70166843Seric #if OLD_NEWDB
70264373Seric 		(void) db->sync(db);
70364373Seric #else
70460585Seric 		(void) db->sync(db, 0);
70560585Seric 
70664373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
70764284Seric 		map->map_mtime = st.st_mtime;
70864284Seric #endif
70964284Seric 
71060089Seric 	map->map_db2 = (void *) db;
71160207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
71264718Seric 		if (!aliaswait(map, ".db", TRUE))
71364718Seric 			return FALSE;
71456822Seric 	return TRUE;
71556822Seric }
71656822Seric 
71756822Seric 
71856822Seric /*
71956822Seric **  HASH_MAP_INIT -- HASH-style map initialization
72056822Seric */
72156822Seric 
72256822Seric bool
72360089Seric hash_map_open(map, mode)
72456822Seric 	MAP *map;
72560089Seric 	int mode;
72656822Seric {
72756822Seric 	DB *db;
72860228Seric 	int i;
72960582Seric 	int omode;
73064373Seric 	int fd;
73164284Seric 	struct stat st;
73260089Seric 	char buf[MAXNAME];
73356822Seric 
73460537Seric 	if (tTd(38, 2))
73567726Seric 		printf("hash_map_open(%s, %s, %d)\n",
73667726Seric 			map->map_mname, map->map_file, mode);
73760089Seric 
73860582Seric 	omode = mode;
73960582Seric 	if (omode == O_RDWR)
74060582Seric 	{
74160582Seric 		omode |= O_CREAT|O_TRUNC;
74265830Seric #if defined(O_EXLOCK) && HASFLOCK
74360582Seric 		omode |= O_EXLOCK;
74466843Seric # if !OLD_NEWDB
74560582Seric 	}
74660582Seric 	else
74760582Seric 	{
74860582Seric 		omode |= O_SHLOCK;
74960582Seric # endif
75060582Seric #endif
75160582Seric 	}
75260207Seric 
75360228Seric 	(void) strcpy(buf, map->map_file);
75460228Seric 	i = strlen(buf);
75560228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
75660228Seric 		(void) strcat(buf, ".db");
75760582Seric 	db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
75856822Seric 	if (db == NULL)
75956822Seric 	{
76064718Seric #ifdef MAYBENEXTRELEASE
76164718Seric 		if (aliaswait(map, ".db", FALSE))
76264718Seric 			return TRUE;
76364718Seric #endif
76460207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
76556836Seric 			syserr("Cannot open HASH database %s", map->map_file);
76656822Seric 		return FALSE;
76756822Seric 	}
76867173Seric #if !OLD_NEWDB
76964373Seric 	fd = db->fd(db);
77067187Seric # if HASFLOCK
77167187Seric #  if !defined(O_EXLOCK)
77264373Seric 	if (mode == O_RDWR && fd >= 0)
77364388Seric 	{
77464388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
77564388Seric 			map->map_mflags |= MF_LOCKED;
77664388Seric 	}
77767187Seric #  else
77864373Seric 	if (mode == O_RDONLY && fd >= 0)
77964373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
78064388Seric 	else
78164388Seric 		map->map_mflags |= MF_LOCKED;
78267187Seric #  endif
78360582Seric # endif
78460582Seric #endif
78560585Seric 
78660585Seric 	/* try to make sure that at least the database header is on disk */
78760585Seric 	if (mode == O_RDWR)
78866843Seric #if OLD_NEWDB
78964373Seric 		(void) db->sync(db);
79064373Seric #else
79160585Seric 		(void) db->sync(db, 0);
79260585Seric 
79364373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
79464284Seric 		map->map_mtime = st.st_mtime;
79564284Seric #endif
79664284Seric 
79760089Seric 	map->map_db2 = (void *) db;
79860207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
79964718Seric 		if (!aliaswait(map, ".db", TRUE))
80064718Seric 			return FALSE;
80156822Seric 	return TRUE;
80256822Seric }
80356822Seric 
80456822Seric 
80556822Seric /*
80656822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
80756822Seric */
80856822Seric 
80956822Seric char *
81060089Seric db_map_lookup(map, name, av, statp)
81156822Seric 	MAP *map;
81260089Seric 	char *name;
81356822Seric 	char **av;
81459084Seric 	int *statp;
81556822Seric {
81656822Seric 	DBT key, val;
81760422Seric 	register DB *db = (DB *) map->map_db2;
81860422Seric 	int st;
81960422Seric 	int saveerrno;
82064373Seric 	int fd;
82160089Seric 	char keybuf[MAXNAME + 1];
82256822Seric 
82360537Seric 	if (tTd(38, 20))
82467726Seric 		printf("db_map_lookup(%s, %s)\n",
82567726Seric 			map->map_mname, name);
82660089Seric 
82760089Seric 	key.size = strlen(name);
82860089Seric 	if (key.size > sizeof keybuf - 1)
82960089Seric 		key.size = sizeof keybuf - 1;
83060089Seric 	key.data = keybuf;
83160089Seric 	bcopy(name, keybuf, key.size + 1);
83260207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
83360089Seric 		makelower(keybuf);
83466843Seric #if !OLD_NEWDB
83564388Seric 	fd = db->fd(db);
83664388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
83764388Seric 		(void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
83860422Seric #endif
83963753Seric 	st = 1;
84063753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
84163753Seric 	{
84263753Seric 		st = db->get(db, &key, &val, 0);
84363753Seric 		if (st == 0)
84463753Seric 			map->map_mflags &= ~MF_TRY1NULL;
84563753Seric 	}
84663753Seric 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
84763753Seric 	{
84863753Seric 		key.size++;
84963753Seric 		st = db->get(db, &key, &val, 0);
85063753Seric 		if (st == 0)
85163753Seric 			map->map_mflags &= ~MF_TRY0NULL;
85263753Seric 	}
85360422Seric 	saveerrno = errno;
85466843Seric #if !OLD_NEWDB
85564388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
85664373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
85760422Seric #endif
85860422Seric 	if (st != 0)
85960422Seric 	{
86060422Seric 		errno = saveerrno;
86160422Seric 		if (st < 0)
86260422Seric 			syserr("db_map_lookup: get (%s)", name);
86356822Seric 		return NULL;
86460422Seric 	}
86560207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
86663753Seric 		return map_rewrite(map, name, strlen(name), NULL);
86763753Seric 	else
86863753Seric 		return map_rewrite(map, val.data, val.size, av);
86956822Seric }
87056822Seric 
87160089Seric 
87260089Seric /*
87360089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
87456822Seric */
87556822Seric 
87660089Seric void
87760089Seric db_map_store(map, lhs, rhs)
87860089Seric 	register MAP *map;
87960089Seric 	char *lhs;
88060089Seric 	char *rhs;
88156822Seric {
88260089Seric 	int stat;
88360089Seric 	DBT key;
88460089Seric 	DBT data;
88560089Seric 	register DB *db = map->map_db2;
88656822Seric 
88760537Seric 	if (tTd(38, 20))
88867726Seric 		printf("db_map_store(%s, %s, %s)\n",
88967726Seric 			map->map_mname, lhs, rhs);
89060089Seric 
89160089Seric 	key.size = strlen(lhs);
89260089Seric 	key.data = lhs;
89360089Seric 
89460089Seric 	data.size = strlen(rhs);
89560089Seric 	data.data = rhs;
89660089Seric 
89760207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
89856822Seric 	{
89960089Seric 		key.size++;
90060089Seric 		data.size++;
90160089Seric 	}
90256836Seric 
90360089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
90460089Seric 	if (stat > 0)
90560089Seric 	{
90660089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
90760089Seric 		stat = db->put(db, &key, &data, 0);
90860089Seric 	}
90960089Seric 	if (stat != 0)
91060089Seric 		syserr("readaliases: db put (%s)", lhs);
91160089Seric }
91256836Seric 
91356847Seric 
91460089Seric /*
91560089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
91660089Seric */
91760089Seric 
91860089Seric void
91960089Seric db_map_close(map)
92060089Seric 	MAP *map;
92160089Seric {
92260089Seric 	register DB *db = map->map_db2;
92360089Seric 
92460537Seric 	if (tTd(38, 9))
92567726Seric 		printf("db_map_close(%s, %s, %x)\n",
92667726Seric 			map->map_mname, map->map_file, map->map_mflags);
92760089Seric 
92860207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
92958804Seric 	{
93060089Seric 		/* write out the distinguished alias */
93160089Seric 		db_map_store(map, "@", "@");
93258804Seric 	}
93358963Seric 
93460089Seric 	if (db->close(db) != 0)
93560089Seric 		syserr("readaliases: db close failure");
93656822Seric }
93757208Seric 
93860089Seric #endif
93960089Seric /*
94060089Seric **  NIS Modules
94160089Seric */
94260089Seric 
94360089Seric # ifdef NIS
94460089Seric 
94564369Seric # ifndef YPERR_BUSY
94664369Seric #  define YPERR_BUSY	16
94764369Seric # endif
94864369Seric 
94957208Seric /*
95060089Seric **  NIS_MAP_OPEN -- open DBM map
95157208Seric */
95257208Seric 
95357208Seric bool
95460089Seric nis_map_open(map, mode)
95557208Seric 	MAP *map;
95660089Seric 	int mode;
95757208Seric {
95857216Seric 	int yperr;
95960215Seric 	register char *p;
96060215Seric 	auto char *vp;
96160215Seric 	auto int vsize;
96257216Seric 	char *master;
96357216Seric 
96460537Seric 	if (tTd(38, 2))
96567726Seric 		printf("nis_map_open(%s, %s)\n",
96667726Seric 			map->map_mname, map->map_file);
96760089Seric 
96860207Seric 	if (mode != O_RDONLY)
96960207Seric 	{
97064650Seric 		/* issue a pseudo-error message */
97164650Seric #ifdef ENOSYS
97264650Seric 		errno = ENOSYS;
97364650Seric #else
97464650Seric # ifdef EFTYPE
97564650Seric 		errno = EFTYPE;
97664650Seric # else
97764650Seric 		errno = ENXIO;
97864650Seric # endif
97964650Seric #endif
98060207Seric 		return FALSE;
98160207Seric 	}
98260207Seric 
98360089Seric 	p = strchr(map->map_file, '@');
98460089Seric 	if (p != NULL)
98560089Seric 	{
98660089Seric 		*p++ = '\0';
98760089Seric 		if (*p != '\0')
98860089Seric 			map->map_domain = p;
98960089Seric 	}
99060215Seric 
99160089Seric 	if (*map->map_file == '\0')
99260089Seric 		map->map_file = "mail.aliases";
99360089Seric 
99466157Seric 	if (map->map_domain == NULL)
99566157Seric 	{
99666157Seric 		yperr = yp_get_default_domain(&map->map_domain);
99766157Seric 		if (yperr != 0)
99866157Seric 		{
99966744Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
100066744Seric 				syserr("NIS map %s specified, but NIS not running\n",
100166744Seric 					map->map_file);
100266157Seric 			return FALSE;
100366157Seric 		}
100466157Seric 	}
100566157Seric 
100660215Seric 	/* check to see if this map actually exists */
100760089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
100860089Seric 			&vp, &vsize);
100960537Seric 	if (tTd(38, 10))
101060089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
101160089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
101260089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
101360089Seric 		return TRUE;
101460215Seric 
101560215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
101660215Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
101760215Seric 			yperr_string(yperr));
101860215Seric 
101960089Seric 	return FALSE;
102060089Seric }
102160089Seric 
102260089Seric 
102360089Seric /*
102457208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
102557208Seric */
102657208Seric 
102757208Seric char *
102860089Seric nis_map_lookup(map, name, av, statp)
102957208Seric 	MAP *map;
103060089Seric 	char *name;
103157208Seric 	char **av;
103259084Seric 	int *statp;
103357208Seric {
103457208Seric 	char *vp;
103557642Seric 	auto int vsize;
103659274Seric 	int buflen;
103760215Seric 	int yperr;
103860089Seric 	char keybuf[MAXNAME + 1];
103957208Seric 
104060537Seric 	if (tTd(38, 20))
104167726Seric 		printf("nis_map_lookup(%s, %s)\n",
104267726Seric 			map->map_mname, name);
104360089Seric 
104460089Seric 	buflen = strlen(name);
104560089Seric 	if (buflen > sizeof keybuf - 1)
104660089Seric 		buflen = sizeof keybuf - 1;
104760089Seric 	bcopy(name, keybuf, buflen + 1);
104860207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
104960089Seric 		makelower(keybuf);
105063753Seric 	yperr = YPERR_KEY;
105163753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
105263753Seric 	{
105363753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
105463753Seric 			     &vp, &vsize);
105563753Seric 		if (yperr == 0)
105663753Seric 			map->map_mflags &= ~MF_TRY1NULL;
105763753Seric 	}
105863753Seric 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
105963753Seric 	{
106059274Seric 		buflen++;
106163753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
106263753Seric 			     &vp, &vsize);
106363753Seric 		if (yperr == 0)
106463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
106563753Seric 	}
106660089Seric 	if (yperr != 0)
106760089Seric 	{
106860089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
106960215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
107057208Seric 		return NULL;
107160089Seric 	}
107260207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
107363753Seric 		return map_rewrite(map, name, strlen(name), NULL);
107463753Seric 	else
107563753Seric 		return map_rewrite(map, vp, vsize, av);
107657208Seric }
107757208Seric 
107867726Seric #endif
107957208Seric /*
108067848Seric **  NISPLUS Modules
108167848Seric **
108267848Seric **	This code donated by Sun Microsystems.
108367848Seric */
108467848Seric 
108567848Seric #ifdef NISPLUS
108667848Seric 
108767848Seric #undef NIS /* symbol conflict in nis.h */
108867848Seric #include <rpcsvc/nis.h>
108967848Seric #include <rpcsvc/nislib.h>
109067848Seric 
109167848Seric #define EN_col(col)	zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
109267848Seric #define COL_NAME(res,i)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
109367848Seric #define COL_MAX(res)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
109467848Seric #define PARTIAL_NAME(x)	((x)[strlen(x) - 1] != '.')
109567848Seric 
109667848Seric /*
109767848Seric **  NISPLUS_MAP_OPEN -- open nisplus table
109867848Seric */
109967848Seric 
110067848Seric bool
110167848Seric nisplus_map_open(map, mode)
110267848Seric 	MAP *map;
110367848Seric 	int mode;
110467848Seric {
110567848Seric 	register char *p;
110667848Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
110767848Seric 	nis_result *res = NULL;
110867848Seric 	u_int objs_len;
110967848Seric 	nis_object *obj_ptr;
111067848Seric 	int retry_cnt, max_col, i;
111167848Seric 
111267848Seric 	if (tTd(38, 2))
111367848Seric 		printf("nisplus_map_open(%s, %s, %d)\n",
111467848Seric 			map->map_mname, map->map_file, mode);
111567848Seric 
111667848Seric 	if (mode != O_RDONLY)
111767848Seric 	{
111867848Seric 		errno = ENODEV;
111967848Seric 		return FALSE;
112067848Seric 	}
112167848Seric 
112267848Seric 	if (*map->map_file == '\0')
112367848Seric 		map->map_file = "mail_aliases.org_dir";
112467848Seric 
112567848Seric 	if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
112667848Seric 	{
112767848Seric 		/* set default NISPLUS Domain to $m */
112867848Seric 		extern char *nisplus_default_domain();
112967848Seric 
113067848Seric 		map->map_domain = newstr(nisplus_default_domain());
113167848Seric 		if (tTd(38, 2))
113267848Seric 			printf("nisplus_map_open(%s): using domain %s\n",
113367848Seric 				 map->map_file, map->map_domain);
113467848Seric 	}
113567848Seric 	if (!PARTIAL_NAME(map->map_file))
113667848Seric 		map->map_domain = newstr("");
113767848Seric 
113867848Seric 	/* check to see if this map actually exists */
113967848Seric 	if (PARTIAL_NAME(map->map_file))
114067848Seric 		sprintf(qbuf, "%s.%s", map->map_file, map->map_domain);
114167848Seric 	else
114267848Seric 		strcpy(qbuf, map->map_file);
114367848Seric 
114467848Seric 	retry_cnt = 0;
114567848Seric 	while (res == NULL || res->status != NIS_SUCCESS)
114667848Seric 	{
114767848Seric 		res = nis_lookup(qbuf, FOLLOW_LINKS);
114867848Seric 		switch (res->status)
114967848Seric 		{
115067848Seric 		  case NIS_SUCCESS:
115167848Seric 		  case NIS_TRYAGAIN:
115267848Seric 		  case NIS_RPCERROR:
115367848Seric 		  case NIS_NAMEUNREACHABLE:
115467848Seric 			break;
115567848Seric 
115667848Seric 		  default:		/* all other nisplus errors */
115767848Seric #if 0
115867848Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
115967848Seric 				syserr("Cannot find table %s.%s: %s",
116067848Seric 					map->map_file, map->map_domain,
116167848Seric 					nis_sperrno(res->status));
116267848Seric #endif
116367848Seric 			errno = EBADR;
116467848Seric 			return FALSE;
116567848Seric 		}
116667848Seric 		sleep(2);		/* try not to overwhelm hosed server */
116767848Seric 		if (retry_cnt++ > 4)
116867848Seric 		{
116967848Seric 			errno = EBADR;
117067848Seric 			return FALSE;
117167848Seric 		}
117267848Seric 	}
117367848Seric 
117467848Seric 	if (NIS_RES_NUMOBJ(res) != 1 ||
117567848Seric 	    (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
117667848Seric 	{
117767848Seric 		if (tTd(38, 10))
117867848Seric 			printf("nisplus_map_open: %s is not a table\n", qbuf);
117967848Seric #if 0
118067848Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
118167848Seric 			syserr("%s.%s: %s is not a table",
118267848Seric 				map->map_file, map->map_domain,
118367848Seric 				nis_sperrno(res->status));
118467848Seric #endif
118567848Seric 		errno = EBADR;
118667848Seric 		return FALSE;
118767848Seric 	}
118867848Seric 	/* default key column is column 0 */
118967848Seric 	if (map->map_keycolnm == NULL)
119067848Seric 		map->map_keycolnm = newstr(COL_NAME(res,0));
119167848Seric 
119267848Seric 	max_col = COL_MAX(res);
119367848Seric 
119467848Seric 	/* verify the key column exist */
119567848Seric 	for (i=0; i< max_col; i++)
119667848Seric 	{
119767848Seric 		if (!strcmp(map->map_keycolnm, COL_NAME(res,i)))
119867848Seric 			break;
119967848Seric 	}
120067848Seric 	if (i == max_col)
120167848Seric 	{
120267848Seric 		if (tTd(38, 2))
120367848Seric 			printf("nisplus_map_open(%s): can not find key column %s\n",
120467848Seric 				map->map_file, map->map_keycolnm);
120567848Seric 		errno = EBADR;
120667848Seric 		return FALSE;
120767848Seric 	}
120867848Seric 
120967848Seric 	/* default value column is the last column */
121067848Seric 	if (map->map_valcolnm == NULL)
121167848Seric 	{
121267848Seric 		map->map_valcolno = max_col - 1;
121367848Seric 		return TRUE;
121467848Seric 	}
121567848Seric 
121667848Seric 	for (i=0; i< max_col; i++)
121767848Seric 	{
121867848Seric 		if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
121967848Seric 		{
122067848Seric 			map->map_valcolno = i;
122167848Seric 			return TRUE;
122267848Seric 		}
122367848Seric 	}
122467848Seric 
122567848Seric 	if (tTd(38, 2))
122667848Seric 		printf("nisplus_map_open(%s): can not find column %s\n",
122767848Seric 			 map->map_file, map->map_keycolnm);
122867848Seric 	errno = EBADR;
122967848Seric 	return FALSE;
123067848Seric }
123167848Seric 
123267848Seric 
123367848Seric /*
123467848Seric **  NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
123567848Seric */
123667848Seric 
123767848Seric char *
123867848Seric nisplus_map_lookup(map, name, av, statp)
123967848Seric 	MAP *map;
124067848Seric 	char *name;
124167848Seric 	char **av;
124267848Seric 	int *statp;
124367848Seric {
124467848Seric 	char *vp;
124567848Seric 	auto int vsize;
124667848Seric 	int buflen;
124767848Seric 	char search_key[MAXNAME + 1];
124867848Seric 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
124967848Seric 	nis_result *result;
125067848Seric 
125167848Seric 	if (tTd(38, 20))
125267848Seric 		printf("nisplus_map_lookup(%s, %s)\n",
125367848Seric 			map->map_mname, name);
125467848Seric 
125567848Seric 	if (!bitset(MF_OPEN, map->map_mflags))
125667848Seric 	{
125767848Seric 		if (nisplus_map_open(map, O_RDONLY))
125867848Seric 			map->map_mflags |= MF_OPEN;
125967848Seric 		else
126067848Seric 		{
126167848Seric 			*statp = EX_UNAVAILABLE;
126267848Seric 			return NULL;
126367848Seric 		}
126467848Seric 	}
126567848Seric 
126667848Seric 	buflen = strlen(name);
126767848Seric 	if (buflen > sizeof search_key - 1)
126867848Seric 		buflen = sizeof search_key - 1;
126967848Seric 	bcopy(name, search_key, buflen + 1);
127067848Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
127167848Seric 		makelower(search_key);
127267848Seric 
127367848Seric 	/* construct the query */
127467848Seric 	if (PARTIAL_NAME(map->map_file))
127567848Seric 		sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm,
127667848Seric 			search_key, map->map_file, map->map_domain);
127767848Seric 	else
127867848Seric 		sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm,
127967848Seric 			search_key, map->map_file);
128067848Seric 
128167848Seric 	if (tTd(38, 20))
128267848Seric 		printf("qbuf=%s\n", qbuf);
128367848Seric 	result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
128467848Seric 	if (result->status == NIS_SUCCESS)
128567848Seric 	{
128667848Seric 		int count;
128767848Seric 		char *str;
128867848Seric 
128967848Seric 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
129067848Seric 		{
129167848Seric 			if (LogLevel > 10)
129267848Seric 				syslog(LOG_WARNING,
129367848Seric 				  "%s:Lookup error, expected 1 entry, got (%d)",
129467848Seric 				    map->map_file, count);
129567848Seric 
129667848Seric 			/* ignore second entry */
129767848Seric 			if (tTd(38, 20))
129867848Seric 				printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
129967848Seric 					name, count);
130067848Seric 		}
130167848Seric 
130267848Seric 		vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
130367848Seric 		/* set the length of the result */
130467848Seric 		if (vp == NULL)
130567848Seric 			vp = "";
130667848Seric 		vsize = strlen(vp);
130767848Seric 		if (tTd(38, 20))
130867848Seric 			printf("nisplus_map_lookup(%s), found %s\n",
130967848Seric 				name, vp);
131067848Seric 		if (bitset(MF_MATCHONLY, map->map_mflags))
131167848Seric 			str = map_rewrite(map, name, strlen(name), NULL);
131267848Seric 		else
131367848Seric 			str = map_rewrite(map, vp, vsize, av);
131467848Seric 		nis_freeresult(result);
131567848Seric #ifdef MAP_EXIT_STAT
131667848Seric 		*statp = EX_OK;
131767848Seric #endif
131867848Seric 		return str;
131967848Seric 	}
132067848Seric 	else
132167848Seric 	{
132267848Seric #ifdef MAP_EXIT_STAT
132367848Seric 		if (result->status == NIS_NOTFOUND)
132467848Seric 			*statp = EX_NOTFOUND;
132567848Seric 		else if (result->status == NIS_TRYAGAIN)
132667848Seric 			*statp = EX_TEMPFAIL;
132767848Seric 		else
132867848Seric 		{
132967848Seric 			*statp = EX_UNAVAILABLE;
133067848Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
133167848Seric 		}
133267848Seric #else
133367848Seric 		if ((result->status != NIS_NOTFOUND) &&
133467848Seric 		    (result->status != NIS_TRYAGAIN))
133567848Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
133667848Seric #endif
133767848Seric 	}
133867848Seric 	if (tTd(38, 20))
133967848Seric 		printf("nisplus_map_lookup(%s), failed\n", name);
134067848Seric 	nis_freeresult(result);
134167848Seric 	return NULL;
134267848Seric }
134367848Seric 
134467848Seric 
134567848Seric char *
134667848Seric nisplus_default_domain()
134767848Seric {
134867848Seric 	static char default_domain[MAXNAME] = "";
134967848Seric 	nis_result *res = NULL;
135067848Seric 	char *p;
135167848Seric 
135267848Seric 	if (default_domain[0] != '\0')
135367848Seric 		return(default_domain);
135467848Seric 
135567848Seric 	if (VendorCode == VENDOR_SUN && ConfigLevel < 2)
135667848Seric 	{
135767848Seric 		/* for old config, user nis+ local directory        */
135867848Seric 		/* have to be backward compatible with bugs too :-( */
135967848Seric 		p = nis_local_directory();
136067848Seric 		strcpy(default_domain, p);
136167848Seric 		return default_domain;
136267848Seric 	}
136367848Seric 
136467848Seric 	if ((p = macvalue('m', CurEnv)) == NULL)
136567848Seric 	{
136667848Seric 		p = nis_local_directory();
136767848Seric 		strcpy(default_domain, p);
136867848Seric 		return default_domain;
136967848Seric 	}
137067848Seric 
137167848Seric 	strcpy(default_domain, p);
137267848Seric 	if (PARTIAL_NAME(default_domain))
137367848Seric 		strcat(default_domain, ".");
137467848Seric 
137567848Seric 	res = nis_lookup(default_domain, FOLLOW_LINKS);
137667848Seric 	if (res->status == NIS_NOTFOUND)
137767848Seric 	{
137867848Seric 		p = nis_local_directory();
137967848Seric 		strcpy(default_domain, p);
138067848Seric 	}
138167848Seric 	return(default_domain);
138267848Seric }
138367848Seric 
138467848Seric #endif /* NISPLUS */
138567848Seric /*
138667832Seric **  HESIOD Modules
138767832Seric **
138867832Seric **	Only works for aliases (for now).
138967832Seric */
139067832Seric 
139167832Seric #ifdef HESIOD
139267832Seric 
139367832Seric char *
139467832Seric hes_map_lookup(map, name, av, statp)
139567832Seric         MAP *map;
139667832Seric         char *name;
139767832Seric         char **av;
139867832Seric         int *statp;
139967832Seric {
140067832Seric 	struct hes_postoffice *pobox;
140167832Seric 	char keybuf[MAXNAME + 1];
140267832Seric 
140367832Seric 	if (tTd(38, 20))
140467832Seric 		printf("hes_map_lookup(%s)\n", name);
140567832Seric 
140667832Seric 	pobox = hes_getmailhost(name);
140767832Seric 	if (pobox == NULL)
140867832Seric 		return NULL;
140967832Seric 
141067832Seric 	/* We only know how to deal with the SMTP types right now */
141167832Seric 	if (strcmp(pobox->po_type, "SMTP") != 0 &&
141267832Seric 	    strcmp(pobox->po_type, "ESMTP") != 0)
141367832Seric 		return NULL;
141467832Seric 
141567832Seric 	/* if just checking for a match, we are done */
141667832Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
141767832Seric 		return map_rewrite(map, name, strlen(name), NULL);
141867832Seric 
141967832Seric 	/* Do the rewriting with new values */
142067832Seric 	if (strlen(pobox->po_name) + strlen(pobox->po_host) + 1 > sizeof keybuf)
142167848Seric 	{
142267848Seric 		*statp = EX_DATAERR;
142367832Seric 		return NULL;
142467848Seric 	}
142567832Seric 	(void) sprintf(keybuf, "%s@%s", pobox->po_name, pobox->po_host);
142667832Seric 	return map_rewrite(map, keybuf, strlen(keybuf), av);
142767832Seric }
142867832Seric 
142967832Seric #endif
143067832Seric /*
143167842Seric **  NeXT NETINFO Modules
143267842Seric */
143367842Seric 
143467842Seric #ifdef NETINFO
143567842Seric 
143667842Seric #define NETINFO_DEFAULT_DIR		"/aliases"
143767842Seric #define NETINFO_DEFAULT_PROPERTY	"members"
143867842Seric 
143967842Seric 
144067842Seric /*
144167842Seric **  NI_MAP_OPEN -- open NetInfo Aliases
144267842Seric */
144367842Seric 
144467848Seric bool
144567842Seric ni_map_open(map, mode)
144667842Seric 	MAP *map;
144767842Seric 	int mode;
144867842Seric {
144967842Seric 	char *p;
145067842Seric 
145167842Seric 	if (tTd(38, 20))
145267842Seric 		printf("ni_map_open: %s\n", map->map_file);
145367842Seric 
145467842Seric 	p = strchr(map->map_file, '@');
145567842Seric 	if (p != NULL)
145667842Seric 	{
145767842Seric 		*p++ = '\0';
145867842Seric 		if (*p != '\0')
145967842Seric 			map->map_domain = p;
146067842Seric 	}
146167842Seric 	if (*map->map_file == '\0')
146267842Seric 		map->map_file = NETINFO_DEFAULT_DIR;
146367842Seric 
146467842Seric 	if (map->map_domain == NULL)
146567842Seric 		map->map_domain = NETINFO_DEFAULT_PROPERTY;
146667842Seric 
146767857Seric 	if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags))
146867857Seric 		map->map_coldelim = ',';
146967842Seric 
147067842Seric 	return TRUE;
147167842Seric }
147267842Seric 
147367842Seric 
147467842Seric /*
147567842Seric **  NI_MAP_LOOKUP -- look up a datum in NetInfo
147667842Seric */
147767842Seric 
147867842Seric char *
147967842Seric ni_map_lookup(map, name, av, statp)
148067842Seric 	MAP *map;
148167842Seric 	char *name;
148267842Seric 	char **av;
148367842Seric 	int *statp;
148467842Seric {
148567842Seric 	char *res;
148667842Seric 	char *propval;
148767842Seric 	extern char *ni_propval();
148867842Seric 
148967842Seric 	if (tTd(38, 20))
149067848Seric 		printf("ni_map_lookup(%s, %s)\n",
149167842Seric 			map->map_mname, name);
149267842Seric 
149367842Seric 	propval = ni_propval(map->map_file, map->map_keycolnm, name,
149467842Seric 			     map->map_valcolnm, map->map_coldelim);
149567842Seric 
149667848Seric 	if (propval == NULL)
149767842Seric 		return NULL;
149867842Seric 
149967842Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
150067842Seric 		res = map_rewrite(map, name, strlen(name), NULL);
150167842Seric 	else
150267842Seric 		res = map_rewrite(map, propval, strlen(propval), av);
150367842Seric 	free(propval);
150467842Seric 	return res;
150567842Seric }
150667842Seric 
150767842Seric #endif
150867842Seric /*
150967848Seric **  TEXT (unindexed text file) Modules
151067848Seric **
151167848Seric **	This code donated by Sun Microsystems.
151267848Seric */
151367848Seric 
151467848Seric 
151567848Seric /*
151667848Seric **  TEXT_MAP_OPEN -- open text table
151767848Seric */
151867848Seric 
151967848Seric bool
152067848Seric text_map_open(map, mode)
152167848Seric 	MAP *map;
152267848Seric 	int mode;
152367848Seric {
152467848Seric 	struct stat sbuf;
152567848Seric 
152667848Seric 	if (tTd(38, 2))
152767848Seric 		printf("text_map_open(%s, %s, %d)\n",
152867848Seric 			map->map_mname, map->map_file, mode);
152967848Seric 
153067848Seric 	if (mode != O_RDONLY)
153167848Seric 	{
153267848Seric 		errno = ENODEV;
153367848Seric 		return FALSE;
153467848Seric 	}
153567848Seric 
153667848Seric 	if (*map->map_file == '\0')
153767848Seric 	{
153867848Seric 		if (tTd(38, 2))
153967848Seric 			printf("text_map_open: file name required\n");
154067848Seric 		return FALSE;
154167848Seric 	}
154267848Seric 
154367848Seric 	if (map->map_file[0] != '/')
154467848Seric 	{
154567848Seric 		if (tTd(38, 2))
154667848Seric 			printf("text_map_open(%s): file name must be fully qualified\n",
154767848Seric 				map->map_file);
154867848Seric 		return FALSE;
154967848Seric 	}
155067848Seric 	/* check to see if this map actually accessable */
155167848Seric 	if (access(map->map_file, R_OK) <0)
155267848Seric 		return FALSE;
155367848Seric 
155467848Seric 	/* check to see if this map actually exist */
155567848Seric 	if (stat(map->map_file, &sbuf) <0)
155667848Seric 	{
155767848Seric 		if (tTd(38, 2))
155867848Seric 			printf("text_map_open(%s): can not stat %s\n",
155967848Seric 				map->map_file, map->map_file);
156067848Seric 		return FALSE;
156167848Seric 	}
156267848Seric 
156367848Seric 	if (!S_ISREG(sbuf.st_mode))
156467848Seric 	{
156567848Seric 		if (tTd(38, 2))
156667848Seric 			printf("text_map_open(%s): %s is not a file\n",
156767848Seric 				map->map_file, map->map_file);
156867848Seric 		return FALSE;
156967848Seric 	}
157067848Seric 
157167848Seric 	if (map->map_keycolnm == NULL)
157267848Seric 		map->map_keycolno = 0;
157367848Seric 	else
157467848Seric 	{
157567848Seric 		if (!isdigit(*map->map_keycolnm))
157667848Seric 		{
157767848Seric 			if (tTd(38, 2))
157867848Seric 				printf("text_map_open(%s): -k should specify a number, not %s\n",
157967848Seric 					map->map_file, map->map_keycolnm);
158067848Seric 			return FALSE;
158167848Seric 		}
158267848Seric 		map->map_keycolno = atoi(map->map_keycolnm);
158367848Seric 	}
158467848Seric 
158567848Seric 	if (map->map_valcolnm == NULL)
158667848Seric 		map->map_valcolno = 0;
158767848Seric 	else
158867848Seric 	{
158967848Seric 		if (!isdigit(*map->map_valcolnm))
159067848Seric 		{
159167848Seric 			if (tTd(38, 2))
159267848Seric 				printf("text_map_open(%s): -v should specify a number, not %s\n",
159367848Seric 					map->map_file, map->map_valcolnm);
159467848Seric 			return FALSE;
159567848Seric 		}
159667848Seric 		map->map_valcolno = atoi(map->map_valcolnm);
159767848Seric 	}
159867848Seric 
159967848Seric 	if (map->map_coldelim == '\0')
160067848Seric 		map->map_coldelim = ':';
160167848Seric 
160267848Seric 	if (tTd(38, 2))
160367848Seric 	{
160467848Seric 		printf("text_map_open(%s): delimiter = %c\n",
160567848Seric 			map->map_file, map->map_coldelim);
160667848Seric 	}
160767848Seric 
160867848Seric 	return TRUE;
160967848Seric }
161067848Seric 
161167848Seric 
161267848Seric /*
161367848Seric **  TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
161467848Seric */
161567848Seric 
161667848Seric char *
161767848Seric text_map_lookup(map, name, av, statp)
161867848Seric 	MAP *map;
161967848Seric 	char *name;
162067848Seric 	char **av;
162167848Seric 	int *statp;
162267848Seric {
162367848Seric 	char *vp;
162467848Seric 	auto int vsize;
162567848Seric 	int buflen;
162667848Seric 	char search_key[MAXNAME + 1];
162767848Seric 	char linebuf[MAXLINE];
162867848Seric 	FILE *f;
162967848Seric 	char buf[MAXNAME+1];
163067848Seric 	char delim;
163167848Seric 	int key_idx;
163267848Seric 	bool found_it;
163367848Seric 	extern char *get_column();
163467848Seric 
163567848Seric 
163667848Seric 	found_it = FALSE;
163767848Seric 	if (tTd(38, 20))
163867848Seric 		printf("text_map_lookup(%s)\n", name);
163967848Seric 
164067848Seric 	buflen = strlen(name);
164167848Seric 	if (buflen > sizeof search_key - 1)
164267848Seric 		buflen = sizeof search_key - 1;
164367848Seric 	bcopy(name, search_key, buflen + 1);
164467848Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
164567848Seric 		makelower(search_key);
164667848Seric 
164767848Seric 	f = fopen(map->map_file, "r");
164867848Seric 	if (f == NULL)
164967848Seric 	{
165067848Seric 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
165167848Seric 		*statp = EX_UNAVAILABLE;
165267848Seric 		return NULL;
165367848Seric 	}
165467848Seric 	key_idx = map->map_keycolno;
165567848Seric 	delim = map->map_coldelim;
165667848Seric 	while (fgets(linebuf, MAXLINE, f))
165767848Seric 	{
165867848Seric 		char *lf;
165967848Seric 		if (linebuf[0] == '#')
166067848Seric 			continue; /* skip comment line */
166167848Seric 		if (lf = strchr(linebuf, '\n'))
166267848Seric 			*lf = '\0';
166367848Seric 		if (!strcasecmp(search_key,
166467848Seric 				get_column(linebuf, key_idx, delim, buf)))
166567848Seric 		{
166667848Seric 			found_it = TRUE;
166767848Seric 			break;
166867848Seric 		}
166967848Seric 	}
167067848Seric 	fclose(f);
167167848Seric 	if (!found_it)
167267848Seric 	{
167367848Seric #ifdef MAP_EXIT_STAT
167467848Seric 		*statp = EX_NOTFOUND;
167567848Seric #endif
167667848Seric 		return(NULL);
167767848Seric 	}
167867848Seric 	vp = get_column(linebuf, map->map_valcolno, delim, buf);
167967848Seric 	vsize = strlen(vp);
168067848Seric #ifdef MAP_EXIT_STAT
168167848Seric 	*statp = EX_OK;
168267848Seric #endif
168367848Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
168467848Seric 		return map_rewrite(map, name, strlen(name), NULL);
168567848Seric 	else
168667848Seric 		return map_rewrite(map, vp, vsize, av);
168767848Seric }
168867848Seric /*
168960089Seric **  STAB (Symbol Table) Modules
169060089Seric */
169160089Seric 
169260089Seric 
169360089Seric /*
169460207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
169560089Seric */
169660089Seric 
169760089Seric char *
169861707Seric stab_map_lookup(map, name, av, pstat)
169960089Seric 	register MAP *map;
170060089Seric 	char *name;
170161707Seric 	char **av;
170261707Seric 	int *pstat;
170360089Seric {
170460089Seric 	register STAB *s;
170560089Seric 
170660537Seric 	if (tTd(38, 20))
170767726Seric 		printf("stab_lookup(%s, %s)\n",
170867726Seric 			map->map_mname, name);
170960089Seric 
171060089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
171160089Seric 	if (s != NULL)
171260089Seric 		return (s->s_alias);
171360089Seric 	return (NULL);
171460089Seric }
171560089Seric 
171660089Seric 
171760089Seric /*
171860207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
171960089Seric */
172060089Seric 
172160089Seric void
172260089Seric stab_map_store(map, lhs, rhs)
172360089Seric 	register MAP *map;
172460089Seric 	char *lhs;
172560089Seric 	char *rhs;
172660089Seric {
172760089Seric 	register STAB *s;
172860089Seric 
172960089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
173060089Seric 	s->s_alias = newstr(rhs);
173160089Seric }
173260089Seric 
173360089Seric 
173460089Seric /*
173560207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
173660207Seric **
173760207Seric **	This is a wierd case -- it is only intended as a fallback for
173860207Seric **	aliases.  For this reason, opens for write (only during a
173960207Seric **	"newaliases") always fails, and opens for read open the
174060207Seric **	actual underlying text file instead of the database.
174160089Seric */
174260089Seric 
174360089Seric bool
174460089Seric stab_map_open(map, mode)
174560089Seric 	register MAP *map;
174660089Seric 	int mode;
174760089Seric {
174863835Seric 	FILE *af;
174964284Seric 	struct stat st;
175063835Seric 
175160537Seric 	if (tTd(38, 2))
175267726Seric 		printf("stab_map_open(%s, %s)\n",
175367726Seric 			map->map_mname, map->map_file);
175460089Seric 
175560089Seric 	if (mode != O_RDONLY)
175660207Seric 	{
175760207Seric 		errno = ENODEV;
175860089Seric 		return FALSE;
175960207Seric 	}
176060089Seric 
176163835Seric 	af = fopen(map->map_file, "r");
176263835Seric 	if (af == NULL)
176363835Seric 		return FALSE;
176467263Seric 	readaliases(map, af, FALSE, FALSE);
176564284Seric 
176664284Seric 	if (fstat(fileno(af), &st) >= 0)
176764284Seric 		map->map_mtime = st.st_mtime;
176863835Seric 	fclose(af);
176963835Seric 
177060089Seric 	return TRUE;
177160089Seric }
177260089Seric /*
177360089Seric **  Implicit Modules
177456822Seric **
177560089Seric **	Tries several types.  For back compatibility of aliases.
177656822Seric */
177756822Seric 
177860089Seric 
177960089Seric /*
178060207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
178160089Seric */
178260089Seric 
178360089Seric char *
178460089Seric impl_map_lookup(map, name, av, pstat)
178560089Seric 	MAP *map;
178660089Seric 	char *name;
178756822Seric 	char **av;
178860089Seric 	int *pstat;
178956822Seric {
179060537Seric 	if (tTd(38, 20))
179167726Seric 		printf("impl_map_lookup(%s, %s)\n",
179267726Seric 			map->map_mname, name);
179356822Seric 
179460089Seric #ifdef NEWDB
179560207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
179660089Seric 		return db_map_lookup(map, name, av, pstat);
179760089Seric #endif
179860089Seric #ifdef NDBM
179960207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
180060089Seric 		return ndbm_map_lookup(map, name, av, pstat);
180160089Seric #endif
180260089Seric 	return stab_map_lookup(map, name, av, pstat);
180360089Seric }
180460089Seric 
180560089Seric /*
180660207Seric **  IMPL_MAP_STORE -- store in open databases
180760089Seric */
180860089Seric 
180960089Seric void
181060089Seric impl_map_store(map, lhs, rhs)
181160089Seric 	MAP *map;
181260089Seric 	char *lhs;
181360089Seric 	char *rhs;
181460089Seric {
181560089Seric #ifdef NEWDB
181660207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
181760089Seric 		db_map_store(map, lhs, rhs);
181860089Seric #endif
181960089Seric #ifdef NDBM
182060207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
182160089Seric 		ndbm_map_store(map, lhs, rhs);
182260089Seric #endif
182360089Seric 	stab_map_store(map, lhs, rhs);
182460089Seric }
182560089Seric 
182660089Seric /*
182760089Seric **  IMPL_MAP_OPEN -- implicit database open
182860089Seric */
182960089Seric 
183060089Seric bool
183160089Seric impl_map_open(map, mode)
183260089Seric 	MAP *map;
183360089Seric 	int mode;
183460089Seric {
183560089Seric 	struct stat stb;
183660089Seric 
183760537Seric 	if (tTd(38, 2))
183867726Seric 		printf("impl_map_open(%s, %s, %d)\n",
183967726Seric 			map->map_mname, map->map_file, mode);
184060089Seric 
184160089Seric 	if (stat(map->map_file, &stb) < 0)
184256822Seric 	{
184360089Seric 		/* no alias file at all */
184464718Seric 		if (tTd(38, 3))
184564718Seric 			printf("no map file\n");
184660089Seric 		return FALSE;
184756822Seric 	}
184856822Seric 
184960089Seric #ifdef NEWDB
185060207Seric 	map->map_mflags |= MF_IMPL_HASH;
185160089Seric 	if (hash_map_open(map, mode))
185256822Seric 	{
185364250Seric #if defined(NDBM) && defined(NIS)
185460561Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
185560207Seric #endif
185660207Seric 			return TRUE;
185760089Seric 	}
185860207Seric 	else
185960207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
186060089Seric #endif
186160089Seric #ifdef NDBM
186260207Seric 	map->map_mflags |= MF_IMPL_NDBM;
186360089Seric 	if (ndbm_map_open(map, mode))
186460089Seric 	{
186560089Seric 		return TRUE;
186660089Seric 	}
186760207Seric 	else
186860207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
186960089Seric #endif
187056822Seric 
187164650Seric #if defined(NEWDB) || defined(NDBM)
187260089Seric 	if (Verbose)
187360089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
187464964Seric #else
187564964Seric 	if (mode != O_RDONLY)
187664964Seric 		usrerr("Cannot rebuild aliases: no database format defined");
187760207Seric #endif
187860089Seric 
187960207Seric 	return stab_map_open(map, mode);
188056822Seric }
188160089Seric 
188260207Seric 
188360089Seric /*
188460207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
188560089Seric */
188660089Seric 
188760089Seric void
188860207Seric impl_map_close(map)
188960089Seric 	MAP *map;
189060089Seric {
189160089Seric #ifdef NEWDB
189260207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
189360089Seric 	{
189460207Seric 		db_map_close(map);
189560207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
189660089Seric 	}
189760089Seric #endif
189860089Seric 
189960089Seric #ifdef NDBM
190060207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
190160089Seric 	{
190260207Seric 		ndbm_map_close(map);
190360207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
190460089Seric 	}
190560089Seric #endif
190660089Seric }
190760207Seric /*
190867726Seric **  User map class.
190967726Seric **
191067726Seric **	Provides access to the system password file.
191167726Seric */
191267726Seric 
191367726Seric /*
191467726Seric **  USER_MAP_OPEN -- open user map
191567726Seric **
191667726Seric **	Really just binds field names to field numbers.
191767726Seric */
191867726Seric 
191967726Seric bool
192067726Seric user_map_open(map, mode)
192167726Seric 	MAP *map;
192267726Seric 	int mode;
192367726Seric {
192467726Seric 	if (tTd(38, 2))
192567726Seric 		printf("user_map_open(%s)\n", map->map_mname);
192667726Seric 
192767726Seric 	if (mode != O_RDONLY)
192867726Seric 	{
192967726Seric 		/* issue a pseudo-error message */
193067726Seric #ifdef ENOSYS
193167726Seric 		errno = ENOSYS;
193267726Seric #else
193367726Seric # ifdef EFTYPE
193467726Seric 		errno = EFTYPE;
193567726Seric # else
193667726Seric 		errno = ENXIO;
193767726Seric # endif
193867726Seric #endif
193967726Seric 		return FALSE;
194067726Seric 	}
194167726Seric 	if (map->map_valcolnm == NULL)
194267726Seric 		/* nothing */ ;
194367726Seric 	else if (strcasecmp(map->map_valcolnm, "name") == 0)
194467726Seric 		map->map_valcolno = 1;
194567726Seric 	else if (strcasecmp(map->map_valcolnm, "passwd") == 0)
194667726Seric 		map->map_valcolno = 2;
194767726Seric 	else if (strcasecmp(map->map_valcolnm, "uid") == 0)
194867726Seric 		map->map_valcolno = 3;
194967726Seric 	else if (strcasecmp(map->map_valcolnm, "gid") == 0)
195067726Seric 		map->map_valcolno = 4;
195167726Seric 	else if (strcasecmp(map->map_valcolnm, "gecos") == 0)
195267726Seric 		map->map_valcolno = 5;
195367726Seric 	else if (strcasecmp(map->map_valcolnm, "dir") == 0)
195467726Seric 		map->map_valcolno = 6;
195567726Seric 	else if (strcasecmp(map->map_valcolnm, "shell") == 0)
195667726Seric 		map->map_valcolno = 7;
195767726Seric 	else
195867726Seric 	{
195967726Seric 		syserr("User map %s: unknown column name %s",
196067726Seric 			map->map_mname, map->map_valcolnm);
196167726Seric 		return FALSE;
196267726Seric 	}
196367726Seric 	return TRUE;
196467726Seric }
196567726Seric 
196667726Seric 
196767726Seric /*
196867726Seric **  USER_MAP_LOOKUP -- look up a user in the passwd file.
196967726Seric */
197067726Seric 
197167726Seric #include <pwd.h>
197267726Seric 
197367726Seric char *
197467726Seric user_map_lookup(map, key, av, statp)
197567726Seric 	MAP *map;
197667726Seric 	char *key;
197767726Seric 	char **av;
197867726Seric 	int *statp;
197967726Seric {
198067726Seric 	struct passwd *pw;
198167726Seric 
198267726Seric 	if (tTd(38, 20))
198367726Seric 		printf("user_map_lookup(%s, %s)\n",
198467726Seric 			map->map_mname, key);
198567726Seric 
198667726Seric 	pw = getpwnam(key);
198767726Seric 	if (pw == NULL)
198867726Seric 		return NULL;
198967726Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
199067726Seric 		return map_rewrite(map, key, strlen(key), NULL);
199167726Seric 	else
199267726Seric 	{
199367726Seric 		char *rwval;
199467726Seric 		char buf[30];
199567726Seric 
199667726Seric 		switch (map->map_valcolno)
199767726Seric 		{
199867726Seric 		  case 0:
199967726Seric 		  case 1:
200067848Seric 			rwval = pw->pw_name;
200167726Seric 			break;
200267726Seric 
200367726Seric 		  case 2:
200467726Seric 			rwval = pw->pw_passwd;
200567726Seric 			break;
200667726Seric 
200767726Seric 		  case 3:
200867726Seric 			sprintf(buf, "%d", pw->pw_uid);
200967726Seric 			rwval = buf;
201067726Seric 			break;
201167726Seric 
201267726Seric 		  case 4:
201367726Seric 			sprintf(buf, "%d", pw->pw_gid);
201467726Seric 			rwval = buf;
201567726Seric 			break;
201667726Seric 
201767726Seric 		  case 5:
201867726Seric 			rwval = pw->pw_gecos;
201967726Seric 			break;
202067726Seric 
202167726Seric 		  case 6:
202267726Seric 			rwval = pw->pw_dir;
202367726Seric 			break;
202467726Seric 
202567726Seric 		  case 7:
202667726Seric 			rwval = pw->pw_shell;
202767726Seric 			break;
202867726Seric 		}
202967726Seric 		return map_rewrite(map, rwval, strlen(rwval), av);
203067726Seric 	}
203167726Seric }
203267726Seric /*
203367726Seric **  Sequenced map type.
203467726Seric **
203567726Seric **	Tries each map in order until something matches, much like
203667726Seric **	implicit.  Stores go to the first map in the list that can
203767726Seric **	support storing.
203867848Seric **
203967848Seric **	This is slightly unusual in that there are two interfaces.
204067848Seric **	The "sequence" interface lets you stack maps arbitrarily.
204167848Seric **	The "switch" interface builds a sequence map by looking
204267848Seric **	at a system-dependent configuration file such as
204367848Seric **	/etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
204467848Seric **
204567848Seric **	We don't need an explicit open, since all maps are
204667848Seric **	opened during startup, including underlying maps.
204767726Seric */
204867726Seric 
204967726Seric /*
205067726Seric **  SEQ_MAP_PARSE -- Sequenced map parsing
205167726Seric */
205267726Seric 
205367726Seric bool
205467726Seric seq_map_parse(map, ap)
205567726Seric 	MAP *map;
205667726Seric 	char *ap;
205767726Seric {
205867726Seric 	int maxmap;
205967726Seric 
206067726Seric 	if (tTd(38, 2))
206167726Seric 		printf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
206267726Seric 	maxmap = 0;
206367726Seric 	while (*ap != '\0')
206467726Seric 	{
206567726Seric 		register char *p;
206667726Seric 		STAB *s;
206767726Seric 
206867726Seric 		/* find beginning of map name */
206967726Seric 		while (isascii(*ap) && isspace(*ap))
207067726Seric 			ap++;
207167726Seric 		for (p = ap; isascii(*p) && isalnum(*p); p++)
207267726Seric 			continue;
207367726Seric 		if (*p != '\0')
207467726Seric 			*p++ = '\0';
207567726Seric 		while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
207667726Seric 			p++;
207767726Seric 		if (*ap == '\0')
207867726Seric 		{
207967726Seric 			ap = p;
208067726Seric 			continue;
208167726Seric 		}
208267726Seric 		s = stab(ap, ST_MAP, ST_FIND);
208367726Seric 		if (s == NULL)
208467726Seric 		{
208567726Seric 			syserr("Sequence map %s: unknown member map %s",
208667726Seric 				map->map_mname, ap);
208767726Seric 		}
208867726Seric 		else if (maxmap == MAXMAPSTACK)
208967726Seric 		{
209067726Seric 			syserr("Sequence map %s: too many member maps (%d max)",
209167726Seric 				map->map_mname, MAXMAPSTACK);
209267726Seric 			maxmap++;
209367726Seric 		}
209467726Seric 		else if (maxmap < MAXMAPSTACK)
209567726Seric 		{
209667726Seric 			map->map_stack[maxmap++] = &s->s_map;
209767726Seric 		}
209867726Seric 		ap = p;
209967726Seric 	}
210067726Seric 	return TRUE;
210167726Seric }
210267726Seric 
210367726Seric 
210467726Seric /*
210567848Seric **  SWITCH_MAP_OPEN -- open a switched map
210667848Seric **
210767848Seric **	This looks at the system-dependent configuration and builds
210867848Seric **	a sequence map that does the same thing.
210967848Seric **
211067848Seric **	Every system must define a switch_map_find routine in conf.c
211167848Seric **	that will return the list of service types associated with a
211267848Seric **	given service class.
211367848Seric */
211467848Seric 
211567848Seric bool
211667848Seric switch_map_open(map, mode)
211767848Seric 	MAP *map;
211867848Seric 	int mode;
211967848Seric {
212067848Seric 	int mapno;
212167848Seric 	int nmaps;
212267848Seric 	char *maptype[MAXMAPSTACK];
212367848Seric 
212467848Seric 	if (tTd(38, 2))
212567848Seric 		printf("switch_map_open(%s, %s, %d)\n",
212667848Seric 			map->map_mname, map->map_file, mode);
212767848Seric 
212867850Seric 	nmaps = switch_map_find(map->map_file, maptype, map->map_return);
212967848Seric 	if (tTd(38, 19))
213067848Seric 	{
213167848Seric 		printf("\tswitch_map_find => %d\n", nmaps);
213267848Seric 		for (mapno = 0; mapno < nmaps; mapno++)
213367848Seric 			printf("\t\t%s\n", maptype[mapno]);
213467848Seric 	}
213567848Seric 	if (nmaps <= 0 || nmaps > MAXMAPSTACK)
213667848Seric 		return FALSE;
213767848Seric 
213867848Seric 	for (mapno = 0; mapno < nmaps; mapno++)
213967848Seric 	{
214067848Seric 		register STAB *s;
214167848Seric 		char nbuf[MAXNAME + 1];
214267848Seric 
214367848Seric 		if (maptype[mapno] == NULL)
214467848Seric 			continue;
214567848Seric 		(void) sprintf(nbuf, "%s.%s", map->map_file, maptype[mapno]);
214667848Seric 		s = stab(nbuf, ST_MAP, ST_FIND);
214767848Seric 		if (s == NULL)
214867848Seric 		{
214967848Seric 			syserr("Switch map %s: unknown member map %s",
215067848Seric 				map->map_mname, nbuf);
215167848Seric 		}
215267848Seric 		else
215367848Seric 		{
215467848Seric 			map->map_stack[mapno] = &s->s_map;
215567848Seric 			if (tTd(38, 4))
215667848Seric 				printf("\tmap_stack[%d] = %s:%s\n",
215767848Seric 					mapno, s->s_map.map_class->map_cname,
215867848Seric 					nbuf);
215967848Seric 		}
216067848Seric 	}
216167848Seric 	return TRUE;
216267848Seric }
216367848Seric 
216467848Seric 
216567848Seric /*
216667848Seric **  SEQ_MAP_CLOSE -- close all underlying maps
216767848Seric */
216867848Seric 
216967848Seric seq_map_close(map)
217067848Seric 	MAP *map;
217167848Seric {
217267848Seric 	int mapno;
217367848Seric 
217467848Seric 	if (tTd(38, 20))
217567848Seric 		printf("seq_map_close(%s)\n", map->map_mname);
217667848Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
217767848Seric 	{
217867848Seric 		MAP *mm = map->map_stack[mapno];
217967848Seric 
218067848Seric 		if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
218167848Seric 			continue;
218267848Seric 		mm->map_class->map_close(mm);
218367848Seric 	}
218467848Seric }
218567848Seric 
218667848Seric 
218767848Seric /*
218867726Seric **  SEQ_MAP_LOOKUP -- sequenced map lookup
218967726Seric */
219067726Seric 
219167726Seric char *
219267726Seric seq_map_lookup(map, key, args, pstat)
219367726Seric 	MAP *map;
219467726Seric 	char *key;
219567726Seric 	char **args;
219667726Seric 	int *pstat;
219767726Seric {
219867726Seric 	int mapno;
219967726Seric 	int mapbit = 0x01;
220067726Seric 
220167726Seric 	if (tTd(38, 20))
220267726Seric 		printf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
220367726Seric 
220467726Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
220567726Seric 	{
220667726Seric 		MAP *mm = map->map_stack[mapno];
220767726Seric 		int stat = 0;
220867726Seric 		char *rv;
220967726Seric 
221067726Seric 		if (mm == NULL)
221167726Seric 			continue;
221267726Seric 		if (!bitset(MF_OPEN, mm->map_mflags))
221367726Seric 		{
221467726Seric 			if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
221567848Seric 			{
221667848Seric 				*pstat = EX_UNAVAILABLE;
221767726Seric 				return NULL;
221867848Seric 			}
221967726Seric 			continue;
222067726Seric 		}
222167726Seric 		rv = mm->map_class->map_lookup(mm, key, args, &stat);
222267726Seric 		if (rv != NULL)
222367726Seric 			return rv;
222467726Seric 		if (stat == 0 && bitset(mapbit, map->map_return[MA_NOTFOUND]))
222567726Seric 			return NULL;
222667726Seric 		if (stat != 0 && bitset(mapbit, map->map_return[MA_TRYAGAIN]))
222767726Seric 		{
222867726Seric 			*pstat = stat;
222967726Seric 			return NULL;
223067726Seric 		}
223167726Seric 	}
223267726Seric 	return NULL;
223367726Seric }
223467726Seric 
223567726Seric 
223667726Seric /*
223767726Seric **  SEQ_MAP_STORE -- sequenced map store
223867726Seric */
223967726Seric 
224067726Seric void
224167726Seric seq_map_store(map, key, val)
224267726Seric 	MAP *map;
224367726Seric 	char *key;
224467726Seric 	char *val;
224567726Seric {
224667726Seric 	int mapno;
224767726Seric 
224867726Seric 	if (tTd(38, 12))
224967726Seric 		printf("seq_map_store(%s, %s, %s)\n",
225067726Seric 			map->map_mname, key, val);
225167726Seric 
225267726Seric 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
225367726Seric 	{
225467726Seric 		MAP *mm = map->map_stack[mapno];
225567726Seric 
225667726Seric 		if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
225767726Seric 			continue;
225867726Seric 
225967726Seric 		mm->map_class->map_store(mm, key, val);
226067726Seric 		return;
226167726Seric 	}
226267726Seric 	syserr("seq_map_store(%s, %s, %s): no writable map",
226367726Seric 		map->map_mname, key, val);
226467726Seric }
226567726Seric /*
226660207Seric **  NULL stubs
226760089Seric */
226860089Seric 
226960207Seric bool
227060207Seric null_map_open(map, mode)
227160089Seric 	MAP *map;
227260207Seric 	int mode;
227360089Seric {
227460207Seric 	return TRUE;
227560089Seric }
227660089Seric 
227760207Seric void
227860207Seric null_map_close(map)
227960207Seric 	MAP *map;
228060089Seric {
228160207Seric 	return;
228260207Seric }
228360089Seric 
228460207Seric void
228560207Seric null_map_store(map, key, val)
228660207Seric 	MAP *map;
228760207Seric 	char *key;
228860207Seric 	char *val;
228960089Seric {
229060207Seric 	return;
229160089Seric }
2292