xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 66744)
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*66744Seric static char sccsid[] = "@(#)map.c	8.23 (Berkeley) 04/12/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;
12160089Seric 		}
12260089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
12360089Seric 			p++;
12460089Seric 		if (*p != '\0')
12560089Seric 			*p++ = '\0';
12660089Seric 	}
12760089Seric 	if (map->map_app != NULL)
12860089Seric 		map->map_app = newstr(map->map_app);
12960089Seric 
13060089Seric 	if (*p != '\0')
13160089Seric 	{
13260089Seric 		map->map_file = p;
13360089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
13460089Seric 			p++;
13560089Seric 		if (*p != '\0')
13660089Seric 			*p++ = '\0';
13760089Seric 		map->map_file = newstr(map->map_file);
13860089Seric 	}
13960089Seric 
14060089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
14160089Seric 		p++;
14260089Seric 	if (*p != '\0')
14360089Seric 		map->map_rebuild = newstr(p);
14460089Seric 
14556822Seric 	if (map->map_file == NULL)
14657208Seric 	{
14760089Seric 		syserr("No file name for %s map %s",
14860089Seric 			map->map_class->map_cname, map->map_mname);
14956822Seric 		return FALSE;
15057208Seric 	}
15160089Seric 	return TRUE;
15260089Seric }
15360089Seric /*
15460089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
15560089Seric **
15660089Seric **	It also adds the map_app string.  It can be used as a utility
15760089Seric **	in the map_lookup method.
15860089Seric **
15960089Seric **	Parameters:
16060089Seric **		map -- the map that causes this.
16160089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
16260089Seric **		slen -- the length of s.
16360089Seric **		av -- arguments to interpolate into buf.
16460089Seric **
16560089Seric **	Returns:
16660089Seric **		Pointer to rewritten result.
16760089Seric **
16860089Seric **	Side Effects:
16960089Seric **		none.
17060089Seric */
17160089Seric 
17260492Seric struct rwbuf
17360492Seric {
17460492Seric 	int	rwb_len;	/* size of buffer */
17560492Seric 	char	*rwb_buf;	/* ptr to buffer */
17660492Seric };
17760492Seric 
17860492Seric struct rwbuf	RwBufs[2];	/* buffers for rewriting output */
17960492Seric 
18060089Seric char *
18160089Seric map_rewrite(map, s, slen, av)
18260089Seric 	register MAP *map;
18360089Seric 	register char *s;
18460089Seric 	int slen;
18560089Seric 	char **av;
18660089Seric {
18760089Seric 	register char *bp;
18860089Seric 	register char c;
18960089Seric 	char **avp;
19060089Seric 	register char *ap;
19160492Seric 	register struct rwbuf *rwb;
19260089Seric 	int i;
19360089Seric 	int len;
19460089Seric 
19560537Seric 	if (tTd(39, 1))
19660089Seric 	{
19760256Seric 		printf("map_rewrite(%.*s), av =", slen, s);
19860256Seric 		if (av == NULL)
19960256Seric 			printf(" (nullv)");
20060256Seric 		else
20160256Seric 		{
20260256Seric 			for (avp = av; *avp != NULL; avp++)
20360256Seric 				printf("\n\t%s", *avp);
20460256Seric 		}
20560256Seric 		printf("\n");
20660089Seric 	}
20760089Seric 
20860492Seric 	rwb = RwBufs;
20960492Seric 	if (av == NULL)
21060492Seric 		rwb++;
21160492Seric 
21260089Seric 	/* count expected size of output (can safely overestimate) */
21360089Seric 	i = len = slen;
21460089Seric 	if (av != NULL)
21560089Seric 	{
21660089Seric 		bp = s;
21760089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
21860089Seric 		{
21960089Seric 			if (c != '%')
22060089Seric 				continue;
22160089Seric 			if (--i < 0)
22260089Seric 				break;
22360089Seric 			c = *bp++;
22460089Seric 			if (!(isascii(c) && isdigit(c)))
22560089Seric 				continue;
22663937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
22760089Seric 				continue;
22860089Seric 			if (*avp == NULL)
22960089Seric 				continue;
23060089Seric 			len += strlen(*avp);
23160089Seric 		}
23260089Seric 	}
23360089Seric 	if (map->map_app != NULL)
23460089Seric 		len += strlen(map->map_app);
23560492Seric 	if (rwb->rwb_len < ++len)
23660089Seric 	{
23760089Seric 		/* need to malloc additional space */
23860492Seric 		rwb->rwb_len = len;
23960492Seric 		if (rwb->rwb_buf != NULL)
24060492Seric 			free(rwb->rwb_buf);
24160492Seric 		rwb->rwb_buf = xalloc(rwb->rwb_len);
24260089Seric 	}
24360089Seric 
24460492Seric 	bp = rwb->rwb_buf;
24560089Seric 	if (av == NULL)
24660089Seric 	{
24760089Seric 		bcopy(s, bp, slen);
24860089Seric 		bp += slen;
24960089Seric 	}
25060089Seric 	else
25160089Seric 	{
25260089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
25360089Seric 		{
25460089Seric 			if (c != '%')
25560089Seric 			{
25660089Seric   pushc:
25760089Seric 				*bp++ = c;
25860089Seric 				continue;
25960089Seric 			}
26060089Seric 			if (--slen < 0 || (c = *s++) == '\0')
26160089Seric 				c = '%';
26260089Seric 			if (c == '%')
26360089Seric 				goto pushc;
26460089Seric 			if (!(isascii(c) && isdigit(c)))
26560089Seric 			{
26660089Seric 				*bp++ = '%';
26760089Seric 				goto pushc;
26860089Seric 			}
26963937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
27060089Seric 				continue;
27160089Seric 			if (*avp == NULL)
27260089Seric 				continue;
27360089Seric 
27460089Seric 			/* transliterate argument into output string */
27560089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
27660089Seric 				*bp++ = c;
27760089Seric 		}
27860089Seric 	}
27960089Seric 	if (map->map_app != NULL)
28060089Seric 		strcpy(bp, map->map_app);
28160089Seric 	else
28260089Seric 		*bp = '\0';
28360537Seric 	if (tTd(39, 1))
28460492Seric 		printf("map_rewrite => %s\n", rwb->rwb_buf);
28560492Seric 	return rwb->rwb_buf;
28660089Seric }
28760089Seric /*
28860537Seric **  INITMAPS -- initialize for aliasing
28960537Seric **
29060537Seric **	Parameters:
29160537Seric **		rebuild -- if TRUE, this rebuilds the cached versions.
29260537Seric **		e -- current envelope.
29360537Seric **
29460537Seric **	Returns:
29560537Seric **		none.
29660537Seric **
29760537Seric **	Side Effects:
29860537Seric **		initializes aliases:
29960537Seric **		if NDBM:  opens the database.
30060537Seric **		if ~NDBM: reads the aliases into the symbol table.
30160537Seric */
30260537Seric 
30360537Seric initmaps(rebuild, e)
30460537Seric 	bool rebuild;
30560537Seric 	register ENVELOPE *e;
30660537Seric {
30760537Seric 	extern void map_init();
30860537Seric 
30964671Seric #ifdef XDEBUG
31064671Seric 	checkfd012("entering initmaps");
31164671Seric #endif
31260537Seric 	CurEnv = e;
31365085Seric 	if (rebuild)
31465085Seric 	{
31565085Seric 		stabapply(map_init, 1);
31665085Seric 		stabapply(map_init, 2);
31765085Seric 	}
31865085Seric 	else
31965085Seric 	{
32065085Seric 		stabapply(map_init, 0);
32165085Seric 	}
32264671Seric #ifdef XDEBUG
32364671Seric 	checkfd012("exiting initmaps");
32464671Seric #endif
32560537Seric }
32660537Seric 
32760537Seric void
32860537Seric map_init(s, rebuild)
32960537Seric 	register STAB *s;
33060537Seric 	int rebuild;
33160537Seric {
33260537Seric 	register MAP *map;
33360537Seric 
33460537Seric 	/* has to be a map */
33560537Seric 	if (s->s_type != ST_MAP)
33660537Seric 		return;
33760537Seric 
33860537Seric 	map = &s->s_map;
33960537Seric 	if (!bitset(MF_VALID, map->map_mflags))
34060537Seric 		return;
34160537Seric 
34260537Seric 	if (tTd(38, 2))
34365085Seric 		printf("map_init(%s:%s, %d)\n",
34464690Seric 			map->map_class->map_cname == NULL ? "NULL" :
34564690Seric 				map->map_class->map_cname,
34665085Seric 			map->map_file == NULL ? "NULL" : map->map_file,
34765085Seric 			rebuild);
34860537Seric 
34965085Seric 	if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&
35065085Seric 		    bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))
35165085Seric 	{
35265085Seric 		if (tTd(38, 3))
35365085Seric 			printf("\twrong pass\n");
35465085Seric 		return;
35565085Seric 	}
35665085Seric 
35760537Seric 	/* if already open, close it (for nested open) */
35860537Seric 	if (bitset(MF_OPEN, map->map_mflags))
35960537Seric 	{
36060537Seric 		map->map_class->map_close(map);
36160537Seric 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
36260537Seric 	}
36360537Seric 
36465085Seric 	if (rebuild == 2)
36560537Seric 	{
36665085Seric 		rebuildaliases(map, FALSE);
36760537Seric 	}
36860537Seric 	else
36960537Seric 	{
37060537Seric 		if (map->map_class->map_open(map, O_RDONLY))
37160537Seric 		{
37260537Seric 			if (tTd(38, 4))
37365085Seric 				printf("\t%s:%s: valid\n",
37464690Seric 					map->map_class->map_cname == NULL ? "NULL" :
37564690Seric 						map->map_class->map_cname,
37664690Seric 					map->map_file == NULL ? "NULL" :
37764690Seric 						map->map_file);
37860537Seric 			map->map_mflags |= MF_OPEN;
37960537Seric 		}
38060537Seric 		else if (tTd(38, 4))
38165085Seric 			printf("\t%s:%s: invalid: %s\n",
38264690Seric 				map->map_class->map_cname == NULL ? "NULL" :
38364690Seric 					map->map_class->map_cname,
38464690Seric 				map->map_file == NULL ? "NULL" :
38564690Seric 					map->map_file,
38660537Seric 				errstring(errno));
38760537Seric 	}
38860537Seric }
38960537Seric /*
39060089Seric **  NDBM modules
39160089Seric */
39260089Seric 
39360089Seric #ifdef NDBM
39460089Seric 
39560089Seric /*
39660089Seric **  DBM_MAP_OPEN -- DBM-style map open
39760089Seric */
39860089Seric 
39960089Seric bool
40060089Seric ndbm_map_open(map, mode)
40160089Seric 	MAP *map;
40260089Seric 	int mode;
40360089Seric {
40464284Seric 	register DBM *dbm;
40564284Seric 	struct stat st;
40660089Seric 
40760537Seric 	if (tTd(38, 2))
40860089Seric 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
40960089Seric 
41060207Seric 	if (mode == O_RDWR)
41160207Seric 		mode |= O_CREAT|O_TRUNC;
41260207Seric 
41360089Seric 	/* open the database */
41460089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
41556822Seric 	if (dbm == NULL)
41656822Seric 	{
41764718Seric #ifdef MAYBENEXTRELEASE
41864718Seric 		if (aliaswait(map, ".pag", FALSE))
41964718Seric 			return TRUE;
42064718Seric #endif
42160207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
42256836Seric 			syserr("Cannot open DBM database %s", map->map_file);
42356822Seric 		return FALSE;
42456822Seric 	}
42560089Seric 	map->map_db1 = (void *) dbm;
42664964Seric 	if (mode == O_RDONLY)
42764964Seric 	{
42864964Seric 		if (bitset(MF_ALIAS, map->map_mflags) &&
42964964Seric 		    !aliaswait(map, ".pag", TRUE))
43064718Seric 			return FALSE;
43164964Seric 	}
43264964Seric 	else
43364964Seric 	{
43464964Seric 		int fd;
43564964Seric 
43664964Seric 		/* exclusive lock for duration of rebuild */
43764964Seric 		fd = dbm_dirfno((DBM *) map->map_db1);
43864964Seric 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
43964964Seric 		    lockfile(fd, map->map_file, ".dir", LOCK_EX))
44064964Seric 			map->map_mflags |= MF_LOCKED;
44164964Seric 	}
44264718Seric 	if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
44364284Seric 		map->map_mtime = st.st_mtime;
44456822Seric 	return TRUE;
44556822Seric }
44660089Seric 
44760089Seric 
44860089Seric /*
44956822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
45056822Seric */
45156822Seric 
45256822Seric char *
45360089Seric ndbm_map_lookup(map, name, av, statp)
45456822Seric 	MAP *map;
45560089Seric 	char *name;
45656822Seric 	char **av;
45759084Seric 	int *statp;
45856822Seric {
45956822Seric 	datum key, val;
46064373Seric 	int fd;
46160089Seric 	char keybuf[MAXNAME + 1];
46256822Seric 
46360537Seric 	if (tTd(38, 20))
46460089Seric 		printf("ndbm_map_lookup(%s)\n", name);
46560089Seric 
46660089Seric 	key.dptr = name;
46760089Seric 	key.dsize = strlen(name);
46860207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
46957014Seric 	{
47060089Seric 		if (key.dsize > sizeof keybuf - 1)
47160089Seric 			key.dsize = sizeof keybuf - 1;
47260089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
47360089Seric 		makelower(keybuf);
47460089Seric 		key.dptr = keybuf;
47557014Seric 	}
47664373Seric 	fd = dbm_dirfno((DBM *) map->map_db1);
47764388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
47864373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
47963753Seric 	val.dptr = NULL;
48063753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
48163753Seric 	{
48263753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
48363753Seric 		if (val.dptr != NULL)
48463753Seric 			map->map_mflags &= ~MF_TRY1NULL;
48563753Seric 	}
48663753Seric 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
48763753Seric 	{
48856822Seric 		key.dsize++;
48963753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
49063753Seric 		if (val.dptr != NULL)
49163753Seric 			map->map_mflags &= ~MF_TRY0NULL;
49263753Seric 	}
49364388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
49464373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
49556822Seric 	if (val.dptr == NULL)
49656822Seric 		return NULL;
49760207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
49863753Seric 		return map_rewrite(map, name, strlen(name), NULL);
49963753Seric 	else
50063753Seric 		return map_rewrite(map, val.dptr, val.dsize, av);
50156822Seric }
50256822Seric 
50356822Seric 
50456822Seric /*
50560089Seric **  DBM_MAP_STORE -- store a datum in the database
50656822Seric */
50756822Seric 
50860089Seric void
50960089Seric ndbm_map_store(map, lhs, rhs)
51060089Seric 	register MAP *map;
51160089Seric 	char *lhs;
51260089Seric 	char *rhs;
51360089Seric {
51460089Seric 	datum key;
51560089Seric 	datum data;
51660089Seric 	int stat;
51760089Seric 
51860537Seric 	if (tTd(38, 12))
51960089Seric 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
52060089Seric 
52160089Seric 	key.dsize = strlen(lhs);
52260089Seric 	key.dptr = lhs;
52360089Seric 
52460089Seric 	data.dsize = strlen(rhs);
52560089Seric 	data.dptr = rhs;
52660089Seric 
52760207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
52860089Seric 	{
52960089Seric 		key.dsize++;
53060089Seric 		data.dsize++;
53160089Seric 	}
53260089Seric 
53360089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
53460089Seric 	if (stat > 0)
53560089Seric 	{
53660089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
53760089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
53860089Seric 	}
53960089Seric 	if (stat != 0)
54060089Seric 		syserr("readaliases: dbm put (%s)", lhs);
54160089Seric }
54260089Seric 
54360089Seric 
54460089Seric /*
54560207Seric **  NDBM_MAP_CLOSE -- close the database
54660089Seric */
54760089Seric 
54860089Seric void
54960089Seric ndbm_map_close(map)
55060089Seric 	register MAP  *map;
55160089Seric {
55260207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
55360089Seric 	{
55464250Seric #ifdef NIS
55564075Seric 		bool inclnull;
55660089Seric 		char buf[200];
55760089Seric 
55864075Seric 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
55964075Seric 		map->map_mflags &= ~MF_INCLNULL;
56064075Seric 
56160089Seric 		(void) sprintf(buf, "%010ld", curtime());
56260089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
56360089Seric 
56464941Seric 		(void) gethostname(buf, sizeof buf);
56560089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
56664075Seric 
56764075Seric 		if (inclnull)
56864075Seric 			map->map_mflags |= MF_INCLNULL;
56960089Seric #endif
57060089Seric 
57160089Seric 		/* write out the distinguished alias */
57260089Seric 		ndbm_map_store(map, "@", "@");
57360089Seric 	}
57460089Seric 	dbm_close((DBM *) map->map_db1);
57560089Seric }
57660089Seric 
57760089Seric #endif
57860089Seric /*
57960582Seric **  NEWDB (Hash and BTree) Modules
58060089Seric */
58160089Seric 
58260089Seric #ifdef NEWDB
58360089Seric 
58460089Seric /*
58560582Seric **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
58660582Seric **
58760582Seric **	These do rather bizarre locking.  If you can lock on open,
58860582Seric **	do that to avoid the condition of opening a database that
58960582Seric **	is being rebuilt.  If you don't, we'll try to fake it, but
59060582Seric **	there will be a race condition.  If opening for read-only,
59160582Seric **	we immediately release the lock to avoid freezing things up.
59260582Seric **	We really ought to hold the lock, but guarantee that we won't
59360582Seric **	be pokey about it.  That's hard to do.
59460089Seric */
59560089Seric 
59656822Seric bool
59760089Seric bt_map_open(map, mode)
59856822Seric 	MAP *map;
59960089Seric 	int mode;
60056822Seric {
60156822Seric 	DB *db;
60260228Seric 	int i;
60360582Seric 	int omode;
60464373Seric 	int fd;
60564284Seric 	struct stat st;
60660089Seric 	char buf[MAXNAME];
60756822Seric 
60860537Seric 	if (tTd(38, 2))
60960089Seric 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
61060089Seric 
61160582Seric 	omode = mode;
61260582Seric 	if (omode == O_RDWR)
61360582Seric 	{
61460582Seric 		omode |= O_CREAT|O_TRUNC;
61565830Seric #if defined(O_EXLOCK) && HASFLOCK
61660582Seric 		omode |= O_EXLOCK;
61760582Seric # if !defined(OLD_NEWDB)
61860582Seric 	}
61960582Seric 	else
62060582Seric 	{
62160582Seric 		omode |= O_SHLOCK;
62260582Seric # endif
62360582Seric #endif
62460582Seric 	}
62560207Seric 
62660228Seric 	(void) strcpy(buf, map->map_file);
62760228Seric 	i = strlen(buf);
62860228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
62960228Seric 		(void) strcat(buf, ".db");
63060582Seric 	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
63156822Seric 	if (db == NULL)
63256822Seric 	{
63364718Seric #ifdef MAYBENEXTRELEASE
63464718Seric 		if (aliaswait(map, ".db", FALSE))
63564718Seric 			return TRUE;
63664718Seric #endif
63760207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
63856836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
63956822Seric 		return FALSE;
64056822Seric 	}
64165830Seric #if !defined(OLD_NEWDB) && HASFLOCK
64264373Seric 	fd = db->fd(db);
64360582Seric # if !defined(O_EXLOCK)
64464373Seric 	if (mode == O_RDWR && fd >= 0)
64564388Seric 	{
64664388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
64764388Seric 			map->map_mflags |= MF_LOCKED;
64864388Seric 	}
64960582Seric # else
65064373Seric 	if (mode == O_RDONLY && fd >= 0)
65164373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
65264388Seric 	else
65364388Seric 		map->map_mflags |= MF_LOCKED;
65460582Seric # endif
65560582Seric #endif
65660585Seric 
65760585Seric 	/* try to make sure that at least the database header is on disk */
65860585Seric 	if (mode == O_RDWR)
65964373Seric #ifdef OLD_NEWDB
66064373Seric 		(void) db->sync(db);
66164373Seric #else
66260585Seric 		(void) db->sync(db, 0);
66360585Seric 
66464373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
66564284Seric 		map->map_mtime = st.st_mtime;
66664284Seric #endif
66764284Seric 
66860089Seric 	map->map_db2 = (void *) db;
66960207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
67064718Seric 		if (!aliaswait(map, ".db", TRUE))
67164718Seric 			return FALSE;
67256822Seric 	return TRUE;
67356822Seric }
67456822Seric 
67556822Seric 
67656822Seric /*
67756822Seric **  HASH_MAP_INIT -- HASH-style map initialization
67856822Seric */
67956822Seric 
68056822Seric bool
68160089Seric hash_map_open(map, mode)
68256822Seric 	MAP *map;
68360089Seric 	int mode;
68456822Seric {
68556822Seric 	DB *db;
68660228Seric 	int i;
68760582Seric 	int omode;
68864373Seric 	int fd;
68964284Seric 	struct stat st;
69060089Seric 	char buf[MAXNAME];
69156822Seric 
69260537Seric 	if (tTd(38, 2))
69360089Seric 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
69460089Seric 
69560582Seric 	omode = mode;
69660582Seric 	if (omode == O_RDWR)
69760582Seric 	{
69860582Seric 		omode |= O_CREAT|O_TRUNC;
69965830Seric #if defined(O_EXLOCK) && HASFLOCK
70060582Seric 		omode |= O_EXLOCK;
70160582Seric # if !defined(OLD_NEWDB)
70260582Seric 	}
70360582Seric 	else
70460582Seric 	{
70560582Seric 		omode |= O_SHLOCK;
70660582Seric # endif
70760582Seric #endif
70860582Seric 	}
70960207Seric 
71060228Seric 	(void) strcpy(buf, map->map_file);
71160228Seric 	i = strlen(buf);
71260228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
71360228Seric 		(void) strcat(buf, ".db");
71460582Seric 	db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
71556822Seric 	if (db == NULL)
71656822Seric 	{
71764718Seric #ifdef MAYBENEXTRELEASE
71864718Seric 		if (aliaswait(map, ".db", FALSE))
71964718Seric 			return TRUE;
72064718Seric #endif
72160207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
72256836Seric 			syserr("Cannot open HASH database %s", map->map_file);
72356822Seric 		return FALSE;
72456822Seric 	}
72565830Seric #if !defined(OLD_NEWDB) && HASFLOCK
72664373Seric 	fd = db->fd(db);
72760582Seric # if !defined(O_EXLOCK)
72864373Seric 	if (mode == O_RDWR && fd >= 0)
72964388Seric 	{
73064388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
73164388Seric 			map->map_mflags |= MF_LOCKED;
73264388Seric 	}
73360582Seric # else
73464373Seric 	if (mode == O_RDONLY && fd >= 0)
73564373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
73664388Seric 	else
73764388Seric 		map->map_mflags |= MF_LOCKED;
73860582Seric # endif
73960582Seric #endif
74060585Seric 
74160585Seric 	/* try to make sure that at least the database header is on disk */
74260585Seric 	if (mode == O_RDWR)
74364373Seric #ifdef OLD_NEWDB
74464373Seric 		(void) db->sync(db);
74564373Seric #else
74660585Seric 		(void) db->sync(db, 0);
74760585Seric 
74864373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
74964284Seric 		map->map_mtime = st.st_mtime;
75064284Seric #endif
75164284Seric 
75260089Seric 	map->map_db2 = (void *) db;
75360207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
75464718Seric 		if (!aliaswait(map, ".db", TRUE))
75564718Seric 			return FALSE;
75656822Seric 	return TRUE;
75756822Seric }
75856822Seric 
75956822Seric 
76056822Seric /*
76156822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
76256822Seric */
76356822Seric 
76456822Seric char *
76560089Seric db_map_lookup(map, name, av, statp)
76656822Seric 	MAP *map;
76760089Seric 	char *name;
76856822Seric 	char **av;
76959084Seric 	int *statp;
77056822Seric {
77156822Seric 	DBT key, val;
77260422Seric 	register DB *db = (DB *) map->map_db2;
77360422Seric 	int st;
77460422Seric 	int saveerrno;
77564373Seric 	int fd;
77660089Seric 	char keybuf[MAXNAME + 1];
77756822Seric 
77860537Seric 	if (tTd(38, 20))
77960089Seric 		printf("db_map_lookup(%s)\n", name);
78060089Seric 
78160089Seric 	key.size = strlen(name);
78260089Seric 	if (key.size > sizeof keybuf - 1)
78360089Seric 		key.size = sizeof keybuf - 1;
78460089Seric 	key.data = keybuf;
78560089Seric 	bcopy(name, keybuf, key.size + 1);
78660207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
78760089Seric 		makelower(keybuf);
78860422Seric #ifndef OLD_NEWDB
78964388Seric 	fd = db->fd(db);
79064388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
79164388Seric 		(void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
79260422Seric #endif
79363753Seric 	st = 1;
79463753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
79563753Seric 	{
79663753Seric 		st = db->get(db, &key, &val, 0);
79763753Seric 		if (st == 0)
79863753Seric 			map->map_mflags &= ~MF_TRY1NULL;
79963753Seric 	}
80063753Seric 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
80163753Seric 	{
80263753Seric 		key.size++;
80363753Seric 		st = db->get(db, &key, &val, 0);
80463753Seric 		if (st == 0)
80563753Seric 			map->map_mflags &= ~MF_TRY0NULL;
80663753Seric 	}
80760422Seric 	saveerrno = errno;
80860422Seric #ifndef OLD_NEWDB
80964388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
81064373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
81160422Seric #endif
81260422Seric 	if (st != 0)
81360422Seric 	{
81460422Seric 		errno = saveerrno;
81560422Seric 		if (st < 0)
81660422Seric 			syserr("db_map_lookup: get (%s)", name);
81756822Seric 		return NULL;
81860422Seric 	}
81960207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
82063753Seric 		return map_rewrite(map, name, strlen(name), NULL);
82163753Seric 	else
82263753Seric 		return map_rewrite(map, val.data, val.size, av);
82356822Seric }
82456822Seric 
82560089Seric 
82660089Seric /*
82760089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
82856822Seric */
82956822Seric 
83060089Seric void
83160089Seric db_map_store(map, lhs, rhs)
83260089Seric 	register MAP *map;
83360089Seric 	char *lhs;
83460089Seric 	char *rhs;
83556822Seric {
83660089Seric 	int stat;
83760089Seric 	DBT key;
83860089Seric 	DBT data;
83960089Seric 	register DB *db = map->map_db2;
84056822Seric 
84160537Seric 	if (tTd(38, 20))
84260089Seric 		printf("db_map_store(%s, %s)\n", lhs, rhs);
84360089Seric 
84460089Seric 	key.size = strlen(lhs);
84560089Seric 	key.data = lhs;
84660089Seric 
84760089Seric 	data.size = strlen(rhs);
84860089Seric 	data.data = rhs;
84960089Seric 
85060207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
85156822Seric 	{
85260089Seric 		key.size++;
85360089Seric 		data.size++;
85460089Seric 	}
85556836Seric 
85660089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
85760089Seric 	if (stat > 0)
85860089Seric 	{
85960089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
86060089Seric 		stat = db->put(db, &key, &data, 0);
86160089Seric 	}
86260089Seric 	if (stat != 0)
86360089Seric 		syserr("readaliases: db put (%s)", lhs);
86460089Seric }
86556836Seric 
86656847Seric 
86760089Seric /*
86860089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
86960089Seric */
87060089Seric 
87160089Seric void
87260089Seric db_map_close(map)
87360089Seric 	MAP *map;
87460089Seric {
87560089Seric 	register DB *db = map->map_db2;
87660089Seric 
87760537Seric 	if (tTd(38, 9))
87860207Seric 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
87960089Seric 
88060207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
88158804Seric 	{
88260089Seric 		/* write out the distinguished alias */
88360089Seric 		db_map_store(map, "@", "@");
88458804Seric 	}
88558963Seric 
88660089Seric 	if (db->close(db) != 0)
88760089Seric 		syserr("readaliases: db close failure");
88856822Seric }
88957208Seric 
89060089Seric #endif
89160089Seric /*
89260089Seric **  NIS Modules
89360089Seric */
89460089Seric 
89560089Seric # ifdef NIS
89660089Seric 
89764369Seric # ifndef YPERR_BUSY
89864369Seric #  define YPERR_BUSY	16
89964369Seric # endif
90064369Seric 
90157208Seric /*
90260089Seric **  NIS_MAP_OPEN -- open DBM map
90357208Seric */
90457208Seric 
90557208Seric bool
90660089Seric nis_map_open(map, mode)
90757208Seric 	MAP *map;
90860089Seric 	int mode;
90957208Seric {
91057216Seric 	int yperr;
91160215Seric 	register char *p;
91260215Seric 	auto char *vp;
91360215Seric 	auto int vsize;
91457216Seric 	char *master;
91557216Seric 
91660537Seric 	if (tTd(38, 2))
91760089Seric 		printf("nis_map_open(%s)\n", map->map_file);
91860089Seric 
91960207Seric 	if (mode != O_RDONLY)
92060207Seric 	{
92164650Seric 		/* issue a pseudo-error message */
92264650Seric #ifdef ENOSYS
92364650Seric 		errno = ENOSYS;
92464650Seric #else
92564650Seric # ifdef EFTYPE
92664650Seric 		errno = EFTYPE;
92764650Seric # else
92864650Seric 		errno = ENXIO;
92964650Seric # endif
93064650Seric #endif
93160207Seric 		return FALSE;
93260207Seric 	}
93360207Seric 
93460089Seric 	p = strchr(map->map_file, '@');
93560089Seric 	if (p != NULL)
93660089Seric 	{
93760089Seric 		*p++ = '\0';
93860089Seric 		if (*p != '\0')
93960089Seric 			map->map_domain = p;
94060089Seric 	}
94160215Seric 
94260089Seric 	if (*map->map_file == '\0')
94360089Seric 		map->map_file = "mail.aliases";
94460089Seric 
94566157Seric 	if (map->map_domain == NULL)
94666157Seric 	{
94766157Seric 		yperr = yp_get_default_domain(&map->map_domain);
94866157Seric 		if (yperr != 0)
94966157Seric 		{
950*66744Seric 			if (!bitset(MF_OPTIONAL, map->map_mflags))
951*66744Seric 				syserr("NIS map %s specified, but NIS not running\n",
952*66744Seric 					map->map_file);
95366157Seric 			return FALSE;
95466157Seric 		}
95566157Seric 	}
95666157Seric 
95760215Seric 	/* check to see if this map actually exists */
95860089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
95960089Seric 			&vp, &vsize);
96060537Seric 	if (tTd(38, 10))
96160089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
96260089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
96360089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
96460089Seric 		return TRUE;
96560215Seric 
96660215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
96760215Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
96860215Seric 			yperr_string(yperr));
96960215Seric 
97060089Seric 	return FALSE;
97160089Seric }
97260089Seric 
97360089Seric 
97460089Seric /*
97557208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
97657208Seric */
97757208Seric 
97857208Seric char *
97960089Seric nis_map_lookup(map, name, av, statp)
98057208Seric 	MAP *map;
98160089Seric 	char *name;
98257208Seric 	char **av;
98359084Seric 	int *statp;
98457208Seric {
98557208Seric 	char *vp;
98657642Seric 	auto int vsize;
98759274Seric 	int buflen;
98860215Seric 	int yperr;
98960089Seric 	char keybuf[MAXNAME + 1];
99057208Seric 
99160537Seric 	if (tTd(38, 20))
99260089Seric 		printf("nis_map_lookup(%s)\n", name);
99360089Seric 
99460089Seric 	buflen = strlen(name);
99560089Seric 	if (buflen > sizeof keybuf - 1)
99660089Seric 		buflen = sizeof keybuf - 1;
99760089Seric 	bcopy(name, keybuf, buflen + 1);
99860207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
99960089Seric 		makelower(keybuf);
100063753Seric 	yperr = YPERR_KEY;
100163753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
100263753Seric 	{
100363753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
100463753Seric 			     &vp, &vsize);
100563753Seric 		if (yperr == 0)
100663753Seric 			map->map_mflags &= ~MF_TRY1NULL;
100763753Seric 	}
100863753Seric 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
100963753Seric 	{
101059274Seric 		buflen++;
101163753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
101263753Seric 			     &vp, &vsize);
101363753Seric 		if (yperr == 0)
101463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
101563753Seric 	}
101660089Seric 	if (yperr != 0)
101760089Seric 	{
101860089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
101960215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
102057208Seric 		return NULL;
102160089Seric 	}
102260207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
102363753Seric 		return map_rewrite(map, name, strlen(name), NULL);
102463753Seric 	else
102563753Seric 		return map_rewrite(map, vp, vsize, av);
102657208Seric }
102757208Seric 
102860089Seric 
102960089Seric /*
103060207Seric **  NIS_MAP_STORE
103160089Seric */
103260089Seric 
103360089Seric void
103460089Seric nis_map_store(map, lhs, rhs)
103560089Seric 	MAP *map;
103660089Seric 	char *lhs;
103760089Seric 	char *rhs;
103860089Seric {
103960089Seric 	/* nothing */
104060089Seric }
104160089Seric 
104260089Seric 
104360089Seric /*
104460207Seric **  NIS_MAP_CLOSE
104560089Seric */
104660089Seric 
104760089Seric void
104860089Seric nis_map_close(map)
104960089Seric 	MAP *map;
105060089Seric {
105160089Seric 	/* nothing */
105260089Seric }
105360089Seric 
105460089Seric #endif /* NIS */
105557208Seric /*
105660089Seric **  STAB (Symbol Table) Modules
105760089Seric */
105860089Seric 
105960089Seric 
106060089Seric /*
106160207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
106260089Seric */
106360089Seric 
106460089Seric char *
106561707Seric stab_map_lookup(map, name, av, pstat)
106660089Seric 	register MAP *map;
106760089Seric 	char *name;
106861707Seric 	char **av;
106961707Seric 	int *pstat;
107060089Seric {
107160089Seric 	register STAB *s;
107260089Seric 
107360537Seric 	if (tTd(38, 20))
107460089Seric 		printf("stab_lookup(%s)\n", name);
107560089Seric 
107660089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
107760089Seric 	if (s != NULL)
107860089Seric 		return (s->s_alias);
107960089Seric 	return (NULL);
108060089Seric }
108160089Seric 
108260089Seric 
108360089Seric /*
108460207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
108560089Seric */
108660089Seric 
108760089Seric void
108860089Seric stab_map_store(map, lhs, rhs)
108960089Seric 	register MAP *map;
109060089Seric 	char *lhs;
109160089Seric 	char *rhs;
109260089Seric {
109360089Seric 	register STAB *s;
109460089Seric 
109560089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
109660089Seric 	s->s_alias = newstr(rhs);
109760089Seric }
109860089Seric 
109960089Seric 
110060089Seric /*
110160207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
110260207Seric **
110360207Seric **	This is a wierd case -- it is only intended as a fallback for
110460207Seric **	aliases.  For this reason, opens for write (only during a
110560207Seric **	"newaliases") always fails, and opens for read open the
110660207Seric **	actual underlying text file instead of the database.
110760089Seric */
110860089Seric 
110960089Seric bool
111060089Seric stab_map_open(map, mode)
111160089Seric 	register MAP *map;
111260089Seric 	int mode;
111360089Seric {
111463835Seric 	FILE *af;
111564284Seric 	struct stat st;
111663835Seric 
111760537Seric 	if (tTd(38, 2))
111860089Seric 		printf("stab_map_open(%s)\n", map->map_file);
111960089Seric 
112060089Seric 	if (mode != O_RDONLY)
112160207Seric 	{
112260207Seric 		errno = ENODEV;
112360089Seric 		return FALSE;
112460207Seric 	}
112560089Seric 
112663835Seric 	af = fopen(map->map_file, "r");
112763835Seric 	if (af == NULL)
112863835Seric 		return FALSE;
112963835Seric 	readaliases(map, af, TRUE);
113064284Seric 
113164284Seric 	if (fstat(fileno(af), &st) >= 0)
113264284Seric 		map->map_mtime = st.st_mtime;
113363835Seric 	fclose(af);
113463835Seric 
113560089Seric 	return TRUE;
113660089Seric }
113760089Seric 
113860089Seric 
113960089Seric /*
114064642Seric **  STAB_MAP_CLOSE -- close symbol table.
114164642Seric **
114264642Seric **	Since this is in memory, there is nothing to do.
114360089Seric */
114460089Seric 
114560089Seric void
114660089Seric stab_map_close(map)
114760089Seric 	MAP *map;
114860089Seric {
114960089Seric 	/* ignore it */
115060089Seric }
115160089Seric /*
115260089Seric **  Implicit Modules
115356822Seric **
115460089Seric **	Tries several types.  For back compatibility of aliases.
115556822Seric */
115656822Seric 
115760089Seric 
115860089Seric /*
115960207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
116060089Seric */
116160089Seric 
116260089Seric char *
116360089Seric impl_map_lookup(map, name, av, pstat)
116460089Seric 	MAP *map;
116560089Seric 	char *name;
116656822Seric 	char **av;
116760089Seric 	int *pstat;
116856822Seric {
116960537Seric 	if (tTd(38, 20))
117060089Seric 		printf("impl_map_lookup(%s)\n", name);
117156822Seric 
117260089Seric #ifdef NEWDB
117360207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
117460089Seric 		return db_map_lookup(map, name, av, pstat);
117560089Seric #endif
117660089Seric #ifdef NDBM
117760207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
117860089Seric 		return ndbm_map_lookup(map, name, av, pstat);
117960089Seric #endif
118060089Seric 	return stab_map_lookup(map, name, av, pstat);
118160089Seric }
118260089Seric 
118360089Seric /*
118460207Seric **  IMPL_MAP_STORE -- store in open databases
118560089Seric */
118660089Seric 
118760089Seric void
118860089Seric impl_map_store(map, lhs, rhs)
118960089Seric 	MAP *map;
119060089Seric 	char *lhs;
119160089Seric 	char *rhs;
119260089Seric {
119360089Seric #ifdef NEWDB
119460207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
119560089Seric 		db_map_store(map, lhs, rhs);
119660089Seric #endif
119760089Seric #ifdef NDBM
119860207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
119960089Seric 		ndbm_map_store(map, lhs, rhs);
120060089Seric #endif
120160089Seric 	stab_map_store(map, lhs, rhs);
120260089Seric }
120360089Seric 
120460089Seric /*
120560089Seric **  IMPL_MAP_OPEN -- implicit database open
120660089Seric */
120760089Seric 
120860089Seric bool
120960089Seric impl_map_open(map, mode)
121060089Seric 	MAP *map;
121160089Seric 	int mode;
121260089Seric {
121360089Seric 	struct stat stb;
121460089Seric 
121560537Seric 	if (tTd(38, 2))
121664718Seric 		printf("impl_map_open(%s, %d)\n", map->map_file, mode);
121760089Seric 
121860089Seric 	if (stat(map->map_file, &stb) < 0)
121956822Seric 	{
122060089Seric 		/* no alias file at all */
122164718Seric 		if (tTd(38, 3))
122264718Seric 			printf("no map file\n");
122360089Seric 		return FALSE;
122456822Seric 	}
122556822Seric 
122660089Seric #ifdef NEWDB
122760207Seric 	map->map_mflags |= MF_IMPL_HASH;
122860089Seric 	if (hash_map_open(map, mode))
122956822Seric 	{
123064250Seric #if defined(NDBM) && defined(NIS)
123160561Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
123260207Seric #endif
123360207Seric 			return TRUE;
123460089Seric 	}
123560207Seric 	else
123660207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
123760089Seric #endif
123860089Seric #ifdef NDBM
123960207Seric 	map->map_mflags |= MF_IMPL_NDBM;
124060089Seric 	if (ndbm_map_open(map, mode))
124160089Seric 	{
124260089Seric 		return TRUE;
124360089Seric 	}
124460207Seric 	else
124560207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
124660089Seric #endif
124756822Seric 
124864650Seric #if defined(NEWDB) || defined(NDBM)
124960089Seric 	if (Verbose)
125060089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
125164964Seric #else
125264964Seric 	if (mode != O_RDONLY)
125364964Seric 		usrerr("Cannot rebuild aliases: no database format defined");
125460207Seric #endif
125560089Seric 
125660207Seric 	return stab_map_open(map, mode);
125756822Seric }
125860089Seric 
125960207Seric 
126060089Seric /*
126160207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
126260089Seric */
126360089Seric 
126460089Seric void
126560207Seric impl_map_close(map)
126660089Seric 	MAP *map;
126760089Seric {
126860089Seric #ifdef NEWDB
126960207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
127060089Seric 	{
127160207Seric 		db_map_close(map);
127260207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
127360089Seric 	}
127460089Seric #endif
127560089Seric 
127660089Seric #ifdef NDBM
127760207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
127860089Seric 	{
127960207Seric 		ndbm_map_close(map);
128060207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
128160089Seric 	}
128260089Seric #endif
128360089Seric }
128460207Seric /*
128560207Seric **  NULL stubs
128660089Seric */
128760089Seric 
128860207Seric bool
128960207Seric null_map_open(map, mode)
129060089Seric 	MAP *map;
129160207Seric 	int mode;
129260089Seric {
129360207Seric 	return TRUE;
129460089Seric }
129560089Seric 
129660207Seric void
129760207Seric null_map_close(map)
129860207Seric 	MAP *map;
129960089Seric {
130060207Seric 	return;
130160207Seric }
130260089Seric 
130360207Seric void
130460207Seric null_map_store(map, key, val)
130560207Seric 	MAP *map;
130660207Seric 	char *key;
130760207Seric 	char *val;
130860089Seric {
130960207Seric 	return;
131060089Seric }
1311