xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 64671)
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*64671Seric static char sccsid[] = "@(#)map.c	8.15 (Berkeley) 09/27/93";
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
6260089Seric /*
6360089Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
6460089Seric **
6560089Seric **	This is a generic version of the map_parse method.
6660089Seric **
6756822Seric **	Parameters:
6860089Seric **		map -- the map being initialized.
6960089Seric **		ap -- a pointer to the args on the config line.
7056822Seric **
7156822Seric **	Returns:
7260089Seric **		TRUE -- if everything parsed OK.
7356822Seric **		FALSE -- otherwise.
7456822Seric **
7556822Seric **	Side Effects:
7660089Seric **		null terminates the filename; stores it in map
7756822Seric */
7856822Seric 
7956822Seric bool
8060089Seric map_parseargs(map, ap)
8156822Seric 	MAP *map;
8260089Seric 	char *ap;
8356822Seric {
8460089Seric 	register char *p = ap;
8556822Seric 
8663753Seric 	map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
8760089Seric 	for (;;)
8860089Seric 	{
8960089Seric 		while (isascii(*p) && isspace(*p))
9060089Seric 			p++;
9160089Seric 		if (*p != '-')
9260089Seric 			break;
9360089Seric 		switch (*++p)
9460089Seric 		{
9560089Seric 		  case 'N':
9660207Seric 			map->map_mflags |= MF_INCLNULL;
9763753Seric 			map->map_mflags &= ~MF_TRY0NULL;
9860089Seric 			break;
9960089Seric 
10063753Seric 		  case 'O':
10163753Seric 			map->map_mflags &= ~MF_TRY1NULL;
10263753Seric 			break;
10363753Seric 
10460089Seric 		  case 'o':
10560207Seric 			map->map_mflags |= MF_OPTIONAL;
10660089Seric 			break;
10760089Seric 
10860089Seric 		  case 'f':
10960207Seric 			map->map_mflags |= MF_NOFOLDCASE;
11060089Seric 			break;
11160089Seric 
11260089Seric 		  case 'm':
11360207Seric 			map->map_mflags |= MF_MATCHONLY;
11460089Seric 			break;
11560089Seric 
11660089Seric 		  case 'a':
11760089Seric 			map->map_app = ++p;
11860089Seric 			break;
11960089Seric 		}
12060089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
12160089Seric 			p++;
12260089Seric 		if (*p != '\0')
12360089Seric 			*p++ = '\0';
12460089Seric 	}
12560089Seric 	if (map->map_app != NULL)
12660089Seric 		map->map_app = newstr(map->map_app);
12760089Seric 
12860089Seric 	if (*p != '\0')
12960089Seric 	{
13060089Seric 		map->map_file = p;
13160089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
13260089Seric 			p++;
13360089Seric 		if (*p != '\0')
13460089Seric 			*p++ = '\0';
13560089Seric 		map->map_file = newstr(map->map_file);
13660089Seric 	}
13760089Seric 
13860089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
13960089Seric 		p++;
14060089Seric 	if (*p != '\0')
14160089Seric 		map->map_rebuild = newstr(p);
14260089Seric 
14356822Seric 	if (map->map_file == NULL)
14457208Seric 	{
14560089Seric 		syserr("No file name for %s map %s",
14660089Seric 			map->map_class->map_cname, map->map_mname);
14756822Seric 		return FALSE;
14857208Seric 	}
14960089Seric 	return TRUE;
15060089Seric }
15160089Seric /*
15260089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
15360089Seric **
15460089Seric **	It also adds the map_app string.  It can be used as a utility
15560089Seric **	in the map_lookup method.
15660089Seric **
15760089Seric **	Parameters:
15860089Seric **		map -- the map that causes this.
15960089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
16060089Seric **		slen -- the length of s.
16160089Seric **		av -- arguments to interpolate into buf.
16260089Seric **
16360089Seric **	Returns:
16460089Seric **		Pointer to rewritten result.
16560089Seric **
16660089Seric **	Side Effects:
16760089Seric **		none.
16860089Seric */
16960089Seric 
17060492Seric struct rwbuf
17160492Seric {
17260492Seric 	int	rwb_len;	/* size of buffer */
17360492Seric 	char	*rwb_buf;	/* ptr to buffer */
17460492Seric };
17560492Seric 
17660492Seric struct rwbuf	RwBufs[2];	/* buffers for rewriting output */
17760492Seric 
17860089Seric char *
17960089Seric map_rewrite(map, s, slen, av)
18060089Seric 	register MAP *map;
18160089Seric 	register char *s;
18260089Seric 	int slen;
18360089Seric 	char **av;
18460089Seric {
18560089Seric 	register char *bp;
18660089Seric 	register char c;
18760089Seric 	char **avp;
18860089Seric 	register char *ap;
18960492Seric 	register struct rwbuf *rwb;
19060089Seric 	int i;
19160089Seric 	int len;
19260089Seric 
19360537Seric 	if (tTd(39, 1))
19460089Seric 	{
19560256Seric 		printf("map_rewrite(%.*s), av =", slen, s);
19660256Seric 		if (av == NULL)
19760256Seric 			printf(" (nullv)");
19860256Seric 		else
19960256Seric 		{
20060256Seric 			for (avp = av; *avp != NULL; avp++)
20160256Seric 				printf("\n\t%s", *avp);
20260256Seric 		}
20360256Seric 		printf("\n");
20460089Seric 	}
20560089Seric 
20660492Seric 	rwb = RwBufs;
20760492Seric 	if (av == NULL)
20860492Seric 		rwb++;
20960492Seric 
21060089Seric 	/* count expected size of output (can safely overestimate) */
21160089Seric 	i = len = slen;
21260089Seric 	if (av != NULL)
21360089Seric 	{
21460089Seric 		bp = s;
21560089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
21660089Seric 		{
21760089Seric 			if (c != '%')
21860089Seric 				continue;
21960089Seric 			if (--i < 0)
22060089Seric 				break;
22160089Seric 			c = *bp++;
22260089Seric 			if (!(isascii(c) && isdigit(c)))
22360089Seric 				continue;
22463937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
22560089Seric 				continue;
22660089Seric 			if (*avp == NULL)
22760089Seric 				continue;
22860089Seric 			len += strlen(*avp);
22960089Seric 		}
23060089Seric 	}
23160089Seric 	if (map->map_app != NULL)
23260089Seric 		len += strlen(map->map_app);
23360492Seric 	if (rwb->rwb_len < ++len)
23460089Seric 	{
23560089Seric 		/* need to malloc additional space */
23660492Seric 		rwb->rwb_len = len;
23760492Seric 		if (rwb->rwb_buf != NULL)
23860492Seric 			free(rwb->rwb_buf);
23960492Seric 		rwb->rwb_buf = xalloc(rwb->rwb_len);
24060089Seric 	}
24160089Seric 
24260492Seric 	bp = rwb->rwb_buf;
24360089Seric 	if (av == NULL)
24460089Seric 	{
24560089Seric 		bcopy(s, bp, slen);
24660089Seric 		bp += slen;
24760089Seric 	}
24860089Seric 	else
24960089Seric 	{
25060089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
25160089Seric 		{
25260089Seric 			if (c != '%')
25360089Seric 			{
25460089Seric   pushc:
25560089Seric 				*bp++ = c;
25660089Seric 				continue;
25760089Seric 			}
25860089Seric 			if (--slen < 0 || (c = *s++) == '\0')
25960089Seric 				c = '%';
26060089Seric 			if (c == '%')
26160089Seric 				goto pushc;
26260089Seric 			if (!(isascii(c) && isdigit(c)))
26360089Seric 			{
26460089Seric 				*bp++ = '%';
26560089Seric 				goto pushc;
26660089Seric 			}
26763937Seric 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
26860089Seric 				continue;
26960089Seric 			if (*avp == NULL)
27060089Seric 				continue;
27160089Seric 
27260089Seric 			/* transliterate argument into output string */
27360089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
27460089Seric 				*bp++ = c;
27560089Seric 		}
27660089Seric 	}
27760089Seric 	if (map->map_app != NULL)
27860089Seric 		strcpy(bp, map->map_app);
27960089Seric 	else
28060089Seric 		*bp = '\0';
28160537Seric 	if (tTd(39, 1))
28260492Seric 		printf("map_rewrite => %s\n", rwb->rwb_buf);
28360492Seric 	return rwb->rwb_buf;
28460089Seric }
28560089Seric /*
28660537Seric **  INITMAPS -- initialize for aliasing
28760537Seric **
28860537Seric **	Parameters:
28960537Seric **		rebuild -- if TRUE, this rebuilds the cached versions.
29060537Seric **		e -- current envelope.
29160537Seric **
29260537Seric **	Returns:
29360537Seric **		none.
29460537Seric **
29560537Seric **	Side Effects:
29660537Seric **		initializes aliases:
29760537Seric **		if NDBM:  opens the database.
29860537Seric **		if ~NDBM: reads the aliases into the symbol table.
29960537Seric */
30060537Seric 
30160537Seric initmaps(rebuild, e)
30260537Seric 	bool rebuild;
30360537Seric 	register ENVELOPE *e;
30460537Seric {
30560537Seric 	extern void map_init();
30660537Seric 
307*64671Seric #ifdef XDEBUG
308*64671Seric 	checkfd012("entering initmaps");
309*64671Seric #endif
31060537Seric 	CurEnv = e;
31160537Seric 	stabapply(map_init, rebuild);
312*64671Seric #ifdef XDEBUG
313*64671Seric 	checkfd012("exiting initmaps");
314*64671Seric #endif
31560537Seric }
31660537Seric 
31760537Seric void
31860537Seric map_init(s, rebuild)
31960537Seric 	register STAB *s;
32060537Seric 	int rebuild;
32160537Seric {
32260537Seric 	register MAP *map;
32360537Seric 
32460537Seric 	/* has to be a map */
32560537Seric 	if (s->s_type != ST_MAP)
32660537Seric 		return;
32760537Seric 
32860537Seric 	map = &s->s_map;
32960537Seric 	if (!bitset(MF_VALID, map->map_mflags))
33060537Seric 		return;
33160537Seric 
33260537Seric 	if (tTd(38, 2))
33360537Seric 		printf("map_init(%s:%s)\n",
33460537Seric 			map->map_class->map_cname, map->map_file);
33560537Seric 
33660537Seric 	/* if already open, close it (for nested open) */
33760537Seric 	if (bitset(MF_OPEN, map->map_mflags))
33860537Seric 	{
33960537Seric 		map->map_class->map_close(map);
34060537Seric 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
34160537Seric 	}
34260537Seric 
34360537Seric 	if (rebuild)
34460537Seric 	{
34560926Seric 		if (bitset(MF_ALIAS, map->map_mflags) &&
34660926Seric 		    bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
34760537Seric 			rebuildaliases(map, FALSE);
34860537Seric 	}
34960537Seric 	else
35060537Seric 	{
35160537Seric 		if (map->map_class->map_open(map, O_RDONLY))
35260537Seric 		{
35360537Seric 			if (tTd(38, 4))
35460537Seric 				printf("%s:%s: valid\n",
35560537Seric 					map->map_class->map_cname,
35660537Seric 					map->map_file);
35760537Seric 			map->map_mflags |= MF_OPEN;
35860537Seric 		}
35960537Seric 		else if (tTd(38, 4))
36060537Seric 			printf("%s:%s: invalid: %s\n",
36160537Seric 				map->map_class->map_cname,
36260537Seric 				map->map_file,
36360537Seric 				errstring(errno));
36460537Seric 	}
36560537Seric }
36660537Seric /*
36760089Seric **  NDBM modules
36860089Seric */
36960089Seric 
37060089Seric #ifdef NDBM
37160089Seric 
37260089Seric /*
37360089Seric **  DBM_MAP_OPEN -- DBM-style map open
37460089Seric */
37560089Seric 
37660089Seric bool
37760089Seric ndbm_map_open(map, mode)
37860089Seric 	MAP *map;
37960089Seric 	int mode;
38060089Seric {
38164284Seric 	register DBM *dbm;
38264284Seric 	struct stat st;
38360089Seric 
38460537Seric 	if (tTd(38, 2))
38560089Seric 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
38660089Seric 
38760207Seric 	if (mode == O_RDWR)
38860207Seric 		mode |= O_CREAT|O_TRUNC;
38960207Seric 
39060089Seric 	/* open the database */
39160089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
39256822Seric 	if (dbm == NULL)
39356822Seric 	{
39460207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
39556836Seric 			syserr("Cannot open DBM database %s", map->map_file);
39656822Seric 		return FALSE;
39756822Seric 	}
39860089Seric 	map->map_db1 = (void *) dbm;
39960207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
40060604Seric 		aliaswait(map, ".pag");
40164284Seric 	if (fstat(dbm_dirfno(dbm), &st) >= 0)
40264284Seric 		map->map_mtime = st.st_mtime;
40356822Seric 	return TRUE;
40456822Seric }
40560089Seric 
40660089Seric 
40760089Seric /*
40856822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
40956822Seric */
41056822Seric 
41156822Seric char *
41260089Seric ndbm_map_lookup(map, name, av, statp)
41356822Seric 	MAP *map;
41460089Seric 	char *name;
41556822Seric 	char **av;
41659084Seric 	int *statp;
41756822Seric {
41856822Seric 	datum key, val;
41964373Seric 	int fd;
42060089Seric 	char keybuf[MAXNAME + 1];
42156822Seric 
42260537Seric 	if (tTd(38, 20))
42360089Seric 		printf("ndbm_map_lookup(%s)\n", name);
42460089Seric 
42560089Seric 	key.dptr = name;
42660089Seric 	key.dsize = strlen(name);
42760207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
42857014Seric 	{
42960089Seric 		if (key.dsize > sizeof keybuf - 1)
43060089Seric 			key.dsize = sizeof keybuf - 1;
43160089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
43260089Seric 		makelower(keybuf);
43360089Seric 		key.dptr = keybuf;
43457014Seric 	}
43564373Seric 	fd = dbm_dirfno((DBM *) map->map_db1);
43664388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
43764373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
43863753Seric 	val.dptr = NULL;
43963753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
44063753Seric 	{
44163753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
44263753Seric 		if (val.dptr != NULL)
44363753Seric 			map->map_mflags &= ~MF_TRY1NULL;
44463753Seric 	}
44563753Seric 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
44663753Seric 	{
44756822Seric 		key.dsize++;
44863753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
44963753Seric 		if (val.dptr != NULL)
45063753Seric 			map->map_mflags &= ~MF_TRY0NULL;
45163753Seric 	}
45264388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
45364373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
45456822Seric 	if (val.dptr == NULL)
45556822Seric 		return NULL;
45660207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
45763753Seric 		return map_rewrite(map, name, strlen(name), NULL);
45863753Seric 	else
45963753Seric 		return map_rewrite(map, val.dptr, val.dsize, av);
46056822Seric }
46156822Seric 
46256822Seric 
46356822Seric /*
46460089Seric **  DBM_MAP_STORE -- store a datum in the database
46556822Seric */
46656822Seric 
46760089Seric void
46860089Seric ndbm_map_store(map, lhs, rhs)
46960089Seric 	register MAP *map;
47060089Seric 	char *lhs;
47160089Seric 	char *rhs;
47260089Seric {
47360089Seric 	datum key;
47460089Seric 	datum data;
47560089Seric 	int stat;
47660089Seric 
47760537Seric 	if (tTd(38, 12))
47860089Seric 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
47960089Seric 
48060089Seric 	key.dsize = strlen(lhs);
48160089Seric 	key.dptr = lhs;
48260089Seric 
48360089Seric 	data.dsize = strlen(rhs);
48460089Seric 	data.dptr = rhs;
48560089Seric 
48660207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
48760089Seric 	{
48860089Seric 		key.dsize++;
48960089Seric 		data.dsize++;
49060089Seric 	}
49160089Seric 
49260089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
49360089Seric 	if (stat > 0)
49460089Seric 	{
49560089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
49660089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
49760089Seric 	}
49860089Seric 	if (stat != 0)
49960089Seric 		syserr("readaliases: dbm put (%s)", lhs);
50060089Seric }
50160089Seric 
50260089Seric 
50360089Seric /*
50460207Seric **  NDBM_MAP_CLOSE -- close the database
50560089Seric */
50660089Seric 
50760089Seric void
50860089Seric ndbm_map_close(map)
50960089Seric 	register MAP  *map;
51060089Seric {
51160207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
51260089Seric 	{
51364250Seric #ifdef NIS
51464075Seric 		bool inclnull;
51560089Seric 		char buf[200];
51660089Seric 
51764075Seric 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
51864075Seric 		map->map_mflags &= ~MF_INCLNULL;
51964075Seric 
52060089Seric 		(void) sprintf(buf, "%010ld", curtime());
52160089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
52260089Seric 
52360089Seric 		(void) myhostname(buf, sizeof buf);
52460089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
52564075Seric 
52664075Seric 		if (inclnull)
52764075Seric 			map->map_mflags |= MF_INCLNULL;
52860089Seric #endif
52960089Seric 
53060089Seric 		/* write out the distinguished alias */
53160089Seric 		ndbm_map_store(map, "@", "@");
53260089Seric 	}
53360089Seric 	dbm_close((DBM *) map->map_db1);
53460089Seric }
53560089Seric 
53660089Seric #endif
53760089Seric /*
53860582Seric **  NEWDB (Hash and BTree) Modules
53960089Seric */
54060089Seric 
54160089Seric #ifdef NEWDB
54260089Seric 
54360089Seric /*
54460582Seric **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
54560582Seric **
54660582Seric **	These do rather bizarre locking.  If you can lock on open,
54760582Seric **	do that to avoid the condition of opening a database that
54860582Seric **	is being rebuilt.  If you don't, we'll try to fake it, but
54960582Seric **	there will be a race condition.  If opening for read-only,
55060582Seric **	we immediately release the lock to avoid freezing things up.
55160582Seric **	We really ought to hold the lock, but guarantee that we won't
55260582Seric **	be pokey about it.  That's hard to do.
55360089Seric */
55460089Seric 
55556822Seric bool
55660089Seric bt_map_open(map, mode)
55756822Seric 	MAP *map;
55860089Seric 	int mode;
55956822Seric {
56056822Seric 	DB *db;
56160228Seric 	int i;
56260582Seric 	int omode;
56364373Seric 	int fd;
56464284Seric 	struct stat st;
56560089Seric 	char buf[MAXNAME];
56656822Seric 
56760537Seric 	if (tTd(38, 2))
56860089Seric 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
56960089Seric 
57060582Seric 	omode = mode;
57160582Seric 	if (omode == O_RDWR)
57260582Seric 	{
57360582Seric 		omode |= O_CREAT|O_TRUNC;
57464035Seric #if defined(O_EXLOCK) && defined(HASFLOCK)
57560582Seric 		omode |= O_EXLOCK;
57660582Seric # if !defined(OLD_NEWDB)
57760582Seric 	}
57860582Seric 	else
57960582Seric 	{
58060582Seric 		omode |= O_SHLOCK;
58160582Seric # endif
58260582Seric #endif
58360582Seric 	}
58460207Seric 
58560228Seric 	(void) strcpy(buf, map->map_file);
58660228Seric 	i = strlen(buf);
58760228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
58860228Seric 		(void) strcat(buf, ".db");
58960582Seric 	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
59056822Seric 	if (db == NULL)
59156822Seric 	{
59260207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
59356836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
59456822Seric 		return FALSE;
59556822Seric 	}
59664035Seric #if !defined(OLD_NEWDB) && defined(HASFLOCK)
59764373Seric 	fd = db->fd(db);
59860582Seric # if !defined(O_EXLOCK)
59964373Seric 	if (mode == O_RDWR && fd >= 0)
60064388Seric 	{
60164388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
60264388Seric 			map->map_mflags |= MF_LOCKED;
60364388Seric 	}
60460582Seric # else
60564373Seric 	if (mode == O_RDONLY && fd >= 0)
60664373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
60764388Seric 	else
60864388Seric 		map->map_mflags |= MF_LOCKED;
60960582Seric # endif
61060582Seric #endif
61160585Seric 
61260585Seric 	/* try to make sure that at least the database header is on disk */
61360585Seric 	if (mode == O_RDWR)
61464373Seric #ifdef OLD_NEWDB
61564373Seric 		(void) db->sync(db);
61664373Seric #else
61760585Seric 		(void) db->sync(db, 0);
61860585Seric 
61964373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
62064284Seric 		map->map_mtime = st.st_mtime;
62164284Seric #endif
62264284Seric 
62360089Seric 	map->map_db2 = (void *) db;
62460207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
62560207Seric 		aliaswait(map, ".db");
62656822Seric 	return TRUE;
62756822Seric }
62856822Seric 
62956822Seric 
63056822Seric /*
63156822Seric **  HASH_MAP_INIT -- HASH-style map initialization
63256822Seric */
63356822Seric 
63456822Seric bool
63560089Seric hash_map_open(map, mode)
63656822Seric 	MAP *map;
63760089Seric 	int mode;
63856822Seric {
63956822Seric 	DB *db;
64060228Seric 	int i;
64160582Seric 	int omode;
64264373Seric 	int fd;
64364284Seric 	struct stat st;
64460089Seric 	char buf[MAXNAME];
64556822Seric 
64660537Seric 	if (tTd(38, 2))
64760089Seric 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
64860089Seric 
64960582Seric 	omode = mode;
65060582Seric 	if (omode == O_RDWR)
65160582Seric 	{
65260582Seric 		omode |= O_CREAT|O_TRUNC;
65364035Seric #if defined(O_EXLOCK) && defined(HASFLOCK)
65460582Seric 		omode |= O_EXLOCK;
65560582Seric # if !defined(OLD_NEWDB)
65660582Seric 	}
65760582Seric 	else
65860582Seric 	{
65960582Seric 		omode |= O_SHLOCK;
66060582Seric # endif
66160582Seric #endif
66260582Seric 	}
66360207Seric 
66460228Seric 	(void) strcpy(buf, map->map_file);
66560228Seric 	i = strlen(buf);
66660228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
66760228Seric 		(void) strcat(buf, ".db");
66860582Seric 	db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
66956822Seric 	if (db == NULL)
67056822Seric 	{
67160207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
67256836Seric 			syserr("Cannot open HASH database %s", map->map_file);
67356822Seric 		return FALSE;
67456822Seric 	}
67564035Seric #if !defined(OLD_NEWDB) && defined(HASFLOCK)
67664373Seric 	fd = db->fd(db);
67760582Seric # if !defined(O_EXLOCK)
67864373Seric 	if (mode == O_RDWR && fd >= 0)
67964388Seric 	{
68064388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
68164388Seric 			map->map_mflags |= MF_LOCKED;
68264388Seric 	}
68360582Seric # else
68464373Seric 	if (mode == O_RDONLY && fd >= 0)
68564373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
68664388Seric 	else
68764388Seric 		map->map_mflags |= MF_LOCKED;
68860582Seric # endif
68960582Seric #endif
69060585Seric 
69160585Seric 	/* try to make sure that at least the database header is on disk */
69260585Seric 	if (mode == O_RDWR)
69364373Seric #ifdef OLD_NEWDB
69464373Seric 		(void) db->sync(db);
69564373Seric #else
69660585Seric 		(void) db->sync(db, 0);
69760585Seric 
69864373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
69964284Seric 		map->map_mtime = st.st_mtime;
70064284Seric #endif
70164284Seric 
70260089Seric 	map->map_db2 = (void *) db;
70360207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
70460207Seric 		aliaswait(map, ".db");
70556822Seric 	return TRUE;
70656822Seric }
70756822Seric 
70856822Seric 
70956822Seric /*
71056822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
71156822Seric */
71256822Seric 
71356822Seric char *
71460089Seric db_map_lookup(map, name, av, statp)
71556822Seric 	MAP *map;
71660089Seric 	char *name;
71756822Seric 	char **av;
71859084Seric 	int *statp;
71956822Seric {
72056822Seric 	DBT key, val;
72160422Seric 	register DB *db = (DB *) map->map_db2;
72260422Seric 	int st;
72360422Seric 	int saveerrno;
72464373Seric 	int fd;
72560089Seric 	char keybuf[MAXNAME + 1];
72656822Seric 
72760537Seric 	if (tTd(38, 20))
72860089Seric 		printf("db_map_lookup(%s)\n", name);
72960089Seric 
73060089Seric 	key.size = strlen(name);
73160089Seric 	if (key.size > sizeof keybuf - 1)
73260089Seric 		key.size = sizeof keybuf - 1;
73360089Seric 	key.data = keybuf;
73460089Seric 	bcopy(name, keybuf, key.size + 1);
73560207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
73660089Seric 		makelower(keybuf);
73760422Seric #ifndef OLD_NEWDB
73864388Seric 	fd = db->fd(db);
73964388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
74064388Seric 		(void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
74160422Seric #endif
74263753Seric 	st = 1;
74363753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
74463753Seric 	{
74563753Seric 		st = db->get(db, &key, &val, 0);
74663753Seric 		if (st == 0)
74763753Seric 			map->map_mflags &= ~MF_TRY1NULL;
74863753Seric 	}
74963753Seric 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
75063753Seric 	{
75163753Seric 		key.size++;
75263753Seric 		st = db->get(db, &key, &val, 0);
75363753Seric 		if (st == 0)
75463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
75563753Seric 	}
75660422Seric 	saveerrno = errno;
75760422Seric #ifndef OLD_NEWDB
75864388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
75964373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
76060422Seric #endif
76160422Seric 	if (st != 0)
76260422Seric 	{
76360422Seric 		errno = saveerrno;
76460422Seric 		if (st < 0)
76560422Seric 			syserr("db_map_lookup: get (%s)", name);
76656822Seric 		return NULL;
76760422Seric 	}
76860207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
76963753Seric 		return map_rewrite(map, name, strlen(name), NULL);
77063753Seric 	else
77163753Seric 		return map_rewrite(map, val.data, val.size, av);
77256822Seric }
77356822Seric 
77460089Seric 
77560089Seric /*
77660089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
77756822Seric */
77856822Seric 
77960089Seric void
78060089Seric db_map_store(map, lhs, rhs)
78160089Seric 	register MAP *map;
78260089Seric 	char *lhs;
78360089Seric 	char *rhs;
78456822Seric {
78560089Seric 	int stat;
78660089Seric 	DBT key;
78760089Seric 	DBT data;
78860089Seric 	register DB *db = map->map_db2;
78956822Seric 
79060537Seric 	if (tTd(38, 20))
79160089Seric 		printf("db_map_store(%s, %s)\n", lhs, rhs);
79260089Seric 
79360089Seric 	key.size = strlen(lhs);
79460089Seric 	key.data = lhs;
79560089Seric 
79660089Seric 	data.size = strlen(rhs);
79760089Seric 	data.data = rhs;
79860089Seric 
79960207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
80056822Seric 	{
80160089Seric 		key.size++;
80260089Seric 		data.size++;
80360089Seric 	}
80456836Seric 
80560089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
80660089Seric 	if (stat > 0)
80760089Seric 	{
80860089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
80960089Seric 		stat = db->put(db, &key, &data, 0);
81060089Seric 	}
81160089Seric 	if (stat != 0)
81260089Seric 		syserr("readaliases: db put (%s)", lhs);
81360089Seric }
81456836Seric 
81556847Seric 
81660089Seric /*
81760089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
81860089Seric */
81960089Seric 
82060089Seric void
82160089Seric db_map_close(map)
82260089Seric 	MAP *map;
82360089Seric {
82460089Seric 	register DB *db = map->map_db2;
82560089Seric 
82660537Seric 	if (tTd(38, 9))
82760207Seric 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
82860089Seric 
82960207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
83058804Seric 	{
83160089Seric 		/* write out the distinguished alias */
83260089Seric 		db_map_store(map, "@", "@");
83358804Seric 	}
83458963Seric 
83560089Seric 	if (db->close(db) != 0)
83660089Seric 		syserr("readaliases: db close failure");
83756822Seric }
83857208Seric 
83960089Seric #endif
84060089Seric /*
84160089Seric **  NIS Modules
84260089Seric */
84360089Seric 
84460089Seric # ifdef NIS
84560089Seric 
84664369Seric # ifndef YPERR_BUSY
84764369Seric #  define YPERR_BUSY	16
84864369Seric # endif
84964369Seric 
85057208Seric /*
85160089Seric **  NIS_MAP_OPEN -- open DBM map
85257208Seric */
85357208Seric 
85457208Seric bool
85560089Seric nis_map_open(map, mode)
85657208Seric 	MAP *map;
85760089Seric 	int mode;
85857208Seric {
85957216Seric 	int yperr;
86060215Seric 	register char *p;
86160215Seric 	auto char *vp;
86260215Seric 	auto int vsize;
86357216Seric 	char *master;
86457216Seric 
86560537Seric 	if (tTd(38, 2))
86660089Seric 		printf("nis_map_open(%s)\n", map->map_file);
86760089Seric 
86860207Seric 	if (mode != O_RDONLY)
86960207Seric 	{
87064650Seric 		/* issue a pseudo-error message */
87164650Seric #ifdef ENOSYS
87264650Seric 		errno = ENOSYS;
87364650Seric #else
87464650Seric # ifdef EFTYPE
87564650Seric 		errno = EFTYPE;
87664650Seric # else
87764650Seric 		errno = ENXIO;
87864650Seric # endif
87964650Seric #endif
88060207Seric 		return FALSE;
88160207Seric 	}
88260207Seric 
88360089Seric 	p = strchr(map->map_file, '@');
88460089Seric 	if (p != NULL)
88560089Seric 	{
88660089Seric 		*p++ = '\0';
88760089Seric 		if (*p != '\0')
88860089Seric 			map->map_domain = p;
88960089Seric 	}
89060215Seric 
89160089Seric 	if (map->map_domain == NULL)
89260089Seric 		yp_get_default_domain(&map->map_domain);
89360089Seric 
89460089Seric 	if (*map->map_file == '\0')
89560089Seric 		map->map_file = "mail.aliases";
89660089Seric 
89760215Seric 	/* check to see if this map actually exists */
89860089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
89960089Seric 			&vp, &vsize);
90060537Seric 	if (tTd(38, 10))
90160089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
90260089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
90360089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
90460089Seric 		return TRUE;
90560215Seric 
90660215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
90760215Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
90860215Seric 			yperr_string(yperr));
90960215Seric 
91060089Seric 	return FALSE;
91160089Seric }
91260089Seric 
91360089Seric 
91460089Seric /*
91557208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
91657208Seric */
91757208Seric 
91857208Seric char *
91960089Seric nis_map_lookup(map, name, av, statp)
92057208Seric 	MAP *map;
92160089Seric 	char *name;
92257208Seric 	char **av;
92359084Seric 	int *statp;
92457208Seric {
92557208Seric 	char *vp;
92657642Seric 	auto int vsize;
92759274Seric 	int buflen;
92860215Seric 	int yperr;
92960089Seric 	char keybuf[MAXNAME + 1];
93057208Seric 
93160537Seric 	if (tTd(38, 20))
93260089Seric 		printf("nis_map_lookup(%s)\n", name);
93360089Seric 
93460089Seric 	buflen = strlen(name);
93560089Seric 	if (buflen > sizeof keybuf - 1)
93660089Seric 		buflen = sizeof keybuf - 1;
93760089Seric 	bcopy(name, keybuf, buflen + 1);
93860207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
93960089Seric 		makelower(keybuf);
94063753Seric 	yperr = YPERR_KEY;
94163753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
94263753Seric 	{
94363753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
94463753Seric 			     &vp, &vsize);
94563753Seric 		if (yperr == 0)
94663753Seric 			map->map_mflags &= ~MF_TRY1NULL;
94763753Seric 	}
94863753Seric 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
94963753Seric 	{
95059274Seric 		buflen++;
95163753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
95263753Seric 			     &vp, &vsize);
95363753Seric 		if (yperr == 0)
95463753Seric 			map->map_mflags &= ~MF_TRY0NULL;
95563753Seric 	}
95660089Seric 	if (yperr != 0)
95760089Seric 	{
95860089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
95960215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
96057208Seric 		return NULL;
96160089Seric 	}
96260207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
96363753Seric 		return map_rewrite(map, name, strlen(name), NULL);
96463753Seric 	else
96563753Seric 		return map_rewrite(map, vp, vsize, av);
96657208Seric }
96757208Seric 
96860089Seric 
96960089Seric /*
97060207Seric **  NIS_MAP_STORE
97160089Seric */
97260089Seric 
97360089Seric void
97460089Seric nis_map_store(map, lhs, rhs)
97560089Seric 	MAP *map;
97660089Seric 	char *lhs;
97760089Seric 	char *rhs;
97860089Seric {
97960089Seric 	/* nothing */
98060089Seric }
98160089Seric 
98260089Seric 
98360089Seric /*
98460207Seric **  NIS_MAP_CLOSE
98560089Seric */
98660089Seric 
98760089Seric void
98860089Seric nis_map_close(map)
98960089Seric 	MAP *map;
99060089Seric {
99160089Seric 	/* nothing */
99260089Seric }
99360089Seric 
99460089Seric #endif /* NIS */
99557208Seric /*
99660089Seric **  STAB (Symbol Table) Modules
99760089Seric */
99860089Seric 
99960089Seric 
100060089Seric /*
100160207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
100260089Seric */
100360089Seric 
100460089Seric char *
100561707Seric stab_map_lookup(map, name, av, pstat)
100660089Seric 	register MAP *map;
100760089Seric 	char *name;
100861707Seric 	char **av;
100961707Seric 	int *pstat;
101060089Seric {
101160089Seric 	register STAB *s;
101260089Seric 
101360537Seric 	if (tTd(38, 20))
101460089Seric 		printf("stab_lookup(%s)\n", name);
101560089Seric 
101660089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
101760089Seric 	if (s != NULL)
101860089Seric 		return (s->s_alias);
101960089Seric 	return (NULL);
102060089Seric }
102160089Seric 
102260089Seric 
102360089Seric /*
102460207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
102560089Seric */
102660089Seric 
102760089Seric void
102860089Seric stab_map_store(map, lhs, rhs)
102960089Seric 	register MAP *map;
103060089Seric 	char *lhs;
103160089Seric 	char *rhs;
103260089Seric {
103360089Seric 	register STAB *s;
103460089Seric 
103560089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
103660089Seric 	s->s_alias = newstr(rhs);
103760089Seric }
103860089Seric 
103960089Seric 
104060089Seric /*
104160207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
104260207Seric **
104360207Seric **	This is a wierd case -- it is only intended as a fallback for
104460207Seric **	aliases.  For this reason, opens for write (only during a
104560207Seric **	"newaliases") always fails, and opens for read open the
104660207Seric **	actual underlying text file instead of the database.
104760089Seric */
104860089Seric 
104960089Seric bool
105060089Seric stab_map_open(map, mode)
105160089Seric 	register MAP *map;
105260089Seric 	int mode;
105360089Seric {
105463835Seric 	FILE *af;
105564284Seric 	struct stat st;
105663835Seric 
105760537Seric 	if (tTd(38, 2))
105860089Seric 		printf("stab_map_open(%s)\n", map->map_file);
105960089Seric 
106060089Seric 	if (mode != O_RDONLY)
106160207Seric 	{
106260207Seric 		errno = ENODEV;
106360089Seric 		return FALSE;
106460207Seric 	}
106560089Seric 
106663835Seric 	af = fopen(map->map_file, "r");
106763835Seric 	if (af == NULL)
106863835Seric 		return FALSE;
106963835Seric 	readaliases(map, af, TRUE);
107064284Seric 
107164284Seric 	if (fstat(fileno(af), &st) >= 0)
107264284Seric 		map->map_mtime = st.st_mtime;
107363835Seric 	fclose(af);
107463835Seric 
107560089Seric 	return TRUE;
107660089Seric }
107760089Seric 
107860089Seric 
107960089Seric /*
108064642Seric **  STAB_MAP_CLOSE -- close symbol table.
108164642Seric **
108264642Seric **	Since this is in memory, there is nothing to do.
108360089Seric */
108460089Seric 
108560089Seric void
108660089Seric stab_map_close(map)
108760089Seric 	MAP *map;
108860089Seric {
108960089Seric 	/* ignore it */
109060089Seric }
109160089Seric /*
109260089Seric **  Implicit Modules
109356822Seric **
109460089Seric **	Tries several types.  For back compatibility of aliases.
109556822Seric */
109656822Seric 
109760089Seric 
109860089Seric /*
109960207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
110060089Seric */
110160089Seric 
110260089Seric char *
110360089Seric impl_map_lookup(map, name, av, pstat)
110460089Seric 	MAP *map;
110560089Seric 	char *name;
110656822Seric 	char **av;
110760089Seric 	int *pstat;
110856822Seric {
110960537Seric 	if (tTd(38, 20))
111060089Seric 		printf("impl_map_lookup(%s)\n", name);
111156822Seric 
111260089Seric #ifdef NEWDB
111360207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
111460089Seric 		return db_map_lookup(map, name, av, pstat);
111560089Seric #endif
111660089Seric #ifdef NDBM
111760207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
111860089Seric 		return ndbm_map_lookup(map, name, av, pstat);
111960089Seric #endif
112060089Seric 	return stab_map_lookup(map, name, av, pstat);
112160089Seric }
112260089Seric 
112360089Seric /*
112460207Seric **  IMPL_MAP_STORE -- store in open databases
112560089Seric */
112660089Seric 
112760089Seric void
112860089Seric impl_map_store(map, lhs, rhs)
112960089Seric 	MAP *map;
113060089Seric 	char *lhs;
113160089Seric 	char *rhs;
113260089Seric {
113360089Seric #ifdef NEWDB
113460207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
113560089Seric 		db_map_store(map, lhs, rhs);
113660089Seric #endif
113760089Seric #ifdef NDBM
113860207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
113960089Seric 		ndbm_map_store(map, lhs, rhs);
114060089Seric #endif
114160089Seric 	stab_map_store(map, lhs, rhs);
114260089Seric }
114360089Seric 
114460089Seric /*
114560089Seric **  IMPL_MAP_OPEN -- implicit database open
114660089Seric */
114760089Seric 
114860089Seric bool
114960089Seric impl_map_open(map, mode)
115060089Seric 	MAP *map;
115160089Seric 	int mode;
115260089Seric {
115360089Seric 	struct stat stb;
115460089Seric 
115560537Seric 	if (tTd(38, 2))
115660089Seric 		printf("impl_map_open(%s)\n", map->map_file);
115760089Seric 
115860089Seric 	if (stat(map->map_file, &stb) < 0)
115956822Seric 	{
116060089Seric 		/* no alias file at all */
116160089Seric 		return FALSE;
116256822Seric 	}
116356822Seric 
116460089Seric #ifdef NEWDB
116560207Seric 	map->map_mflags |= MF_IMPL_HASH;
116660089Seric 	if (hash_map_open(map, mode))
116756822Seric 	{
116864250Seric #if defined(NDBM) && defined(NIS)
116960561Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
117060207Seric #endif
117160207Seric 			return TRUE;
117260089Seric 	}
117360207Seric 	else
117460207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
117560089Seric #endif
117660089Seric #ifdef NDBM
117760207Seric 	map->map_mflags |= MF_IMPL_NDBM;
117860089Seric 	if (ndbm_map_open(map, mode))
117960089Seric 	{
118060089Seric 		return TRUE;
118160089Seric 	}
118260207Seric 	else
118360207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
118460089Seric #endif
118556822Seric 
118664650Seric #if defined(NEWDB) || defined(NDBM)
118760089Seric 	if (Verbose)
118860089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
118960207Seric #endif
119060089Seric 
119160207Seric 	return stab_map_open(map, mode);
119256822Seric }
119360089Seric 
119460207Seric 
119560089Seric /*
119660207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
119760089Seric */
119860089Seric 
119960089Seric void
120060207Seric impl_map_close(map)
120160089Seric 	MAP *map;
120260089Seric {
120360089Seric #ifdef NEWDB
120460207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
120560089Seric 	{
120660207Seric 		db_map_close(map);
120760207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
120860089Seric 	}
120960089Seric #endif
121060089Seric 
121160089Seric #ifdef NDBM
121260207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
121360089Seric 	{
121460207Seric 		ndbm_map_close(map);
121560207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
121660089Seric 	}
121760089Seric #endif
121860089Seric }
121960207Seric /*
122060207Seric **  NULL stubs
122160089Seric */
122260089Seric 
122360207Seric bool
122460207Seric null_map_open(map, mode)
122560089Seric 	MAP *map;
122660207Seric 	int mode;
122760089Seric {
122860207Seric 	return TRUE;
122960089Seric }
123060089Seric 
123160207Seric void
123260207Seric null_map_close(map)
123360207Seric 	MAP *map;
123460089Seric {
123560207Seric 	return;
123660207Seric }
123760089Seric 
123860207Seric void
123960207Seric null_map_store(map, key, val)
124060207Seric 	MAP *map;
124160207Seric 	char *key;
124260207Seric 	char *val;
124360089Seric {
124460207Seric 	return;
124560089Seric }
1246