xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 64718)
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*64718Seric static char sccsid[] = "@(#)map.c	8.17 (Berkeley) 10/15/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
62*64718Seric 
63*64718Seric 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;
31360537Seric 	stabapply(map_init, rebuild);
31464671Seric #ifdef XDEBUG
31564671Seric 	checkfd012("exiting initmaps");
31664671Seric #endif
31760537Seric }
31860537Seric 
31960537Seric void
32060537Seric map_init(s, rebuild)
32160537Seric 	register STAB *s;
32260537Seric 	int rebuild;
32360537Seric {
32460537Seric 	register MAP *map;
32560537Seric 
32660537Seric 	/* has to be a map */
32760537Seric 	if (s->s_type != ST_MAP)
32860537Seric 		return;
32960537Seric 
33060537Seric 	map = &s->s_map;
33160537Seric 	if (!bitset(MF_VALID, map->map_mflags))
33260537Seric 		return;
33360537Seric 
33460537Seric 	if (tTd(38, 2))
33560537Seric 		printf("map_init(%s:%s)\n",
33664690Seric 			map->map_class->map_cname == NULL ? "NULL" :
33764690Seric 				map->map_class->map_cname,
33864690Seric 			map->map_file == NULL ? "NULL" : map->map_file);
33960537Seric 
34060537Seric 	/* if already open, close it (for nested open) */
34160537Seric 	if (bitset(MF_OPEN, map->map_mflags))
34260537Seric 	{
34360537Seric 		map->map_class->map_close(map);
34460537Seric 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
34560537Seric 	}
34660537Seric 
34760537Seric 	if (rebuild)
34860537Seric 	{
34960926Seric 		if (bitset(MF_ALIAS, map->map_mflags) &&
35060926Seric 		    bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
35160537Seric 			rebuildaliases(map, FALSE);
35260537Seric 	}
35360537Seric 	else
35460537Seric 	{
35560537Seric 		if (map->map_class->map_open(map, O_RDONLY))
35660537Seric 		{
35760537Seric 			if (tTd(38, 4))
35860537Seric 				printf("%s:%s: valid\n",
35964690Seric 					map->map_class->map_cname == NULL ? "NULL" :
36064690Seric 						map->map_class->map_cname,
36164690Seric 					map->map_file == NULL ? "NULL" :
36264690Seric 						map->map_file);
36360537Seric 			map->map_mflags |= MF_OPEN;
36460537Seric 		}
36560537Seric 		else if (tTd(38, 4))
36660537Seric 			printf("%s:%s: invalid: %s\n",
36764690Seric 				map->map_class->map_cname == NULL ? "NULL" :
36864690Seric 					map->map_class->map_cname,
36964690Seric 				map->map_file == NULL ? "NULL" :
37064690Seric 					map->map_file,
37160537Seric 				errstring(errno));
37260537Seric 	}
37360537Seric }
37460537Seric /*
37560089Seric **  NDBM modules
37660089Seric */
37760089Seric 
37860089Seric #ifdef NDBM
37960089Seric 
38060089Seric /*
38160089Seric **  DBM_MAP_OPEN -- DBM-style map open
38260089Seric */
38360089Seric 
38460089Seric bool
38560089Seric ndbm_map_open(map, mode)
38660089Seric 	MAP *map;
38760089Seric 	int mode;
38860089Seric {
38964284Seric 	register DBM *dbm;
39064284Seric 	struct stat st;
39160089Seric 
39260537Seric 	if (tTd(38, 2))
39360089Seric 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
39460089Seric 
39560207Seric 	if (mode == O_RDWR)
39660207Seric 		mode |= O_CREAT|O_TRUNC;
39760207Seric 
39860089Seric 	/* open the database */
39960089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
40056822Seric 	if (dbm == NULL)
40156822Seric 	{
402*64718Seric #ifdef MAYBENEXTRELEASE
403*64718Seric 		if (aliaswait(map, ".pag", FALSE))
404*64718Seric 			return TRUE;
405*64718Seric #endif
40660207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
40756836Seric 			syserr("Cannot open DBM database %s", map->map_file);
40856822Seric 		return FALSE;
40956822Seric 	}
41060089Seric 	map->map_db1 = (void *) dbm;
41160207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
412*64718Seric 		if (!aliaswait(map, ".pag", TRUE))
413*64718Seric 			return FALSE;
414*64718Seric 	if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
41564284Seric 		map->map_mtime = st.st_mtime;
41656822Seric 	return TRUE;
41756822Seric }
41860089Seric 
41960089Seric 
42060089Seric /*
42156822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
42256822Seric */
42356822Seric 
42456822Seric char *
42560089Seric ndbm_map_lookup(map, name, av, statp)
42656822Seric 	MAP *map;
42760089Seric 	char *name;
42856822Seric 	char **av;
42959084Seric 	int *statp;
43056822Seric {
43156822Seric 	datum key, val;
43264373Seric 	int fd;
43360089Seric 	char keybuf[MAXNAME + 1];
43456822Seric 
43560537Seric 	if (tTd(38, 20))
43660089Seric 		printf("ndbm_map_lookup(%s)\n", name);
43760089Seric 
43860089Seric 	key.dptr = name;
43960089Seric 	key.dsize = strlen(name);
44060207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
44157014Seric 	{
44260089Seric 		if (key.dsize > sizeof keybuf - 1)
44360089Seric 			key.dsize = sizeof keybuf - 1;
44460089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
44560089Seric 		makelower(keybuf);
44660089Seric 		key.dptr = keybuf;
44757014Seric 	}
44864373Seric 	fd = dbm_dirfno((DBM *) map->map_db1);
44964388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
45064373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
45163753Seric 	val.dptr = NULL;
45263753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
45363753Seric 	{
45463753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
45563753Seric 		if (val.dptr != NULL)
45663753Seric 			map->map_mflags &= ~MF_TRY1NULL;
45763753Seric 	}
45863753Seric 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
45963753Seric 	{
46056822Seric 		key.dsize++;
46163753Seric 		val = dbm_fetch((DBM *) map->map_db1, key);
46263753Seric 		if (val.dptr != NULL)
46363753Seric 			map->map_mflags &= ~MF_TRY0NULL;
46463753Seric 	}
46564388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
46664373Seric 		(void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
46756822Seric 	if (val.dptr == NULL)
46856822Seric 		return NULL;
46960207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
47063753Seric 		return map_rewrite(map, name, strlen(name), NULL);
47163753Seric 	else
47263753Seric 		return map_rewrite(map, val.dptr, val.dsize, av);
47356822Seric }
47456822Seric 
47556822Seric 
47656822Seric /*
47760089Seric **  DBM_MAP_STORE -- store a datum in the database
47856822Seric */
47956822Seric 
48060089Seric void
48160089Seric ndbm_map_store(map, lhs, rhs)
48260089Seric 	register MAP *map;
48360089Seric 	char *lhs;
48460089Seric 	char *rhs;
48560089Seric {
48660089Seric 	datum key;
48760089Seric 	datum data;
48860089Seric 	int stat;
48960089Seric 
49060537Seric 	if (tTd(38, 12))
49160089Seric 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
49260089Seric 
49360089Seric 	key.dsize = strlen(lhs);
49460089Seric 	key.dptr = lhs;
49560089Seric 
49660089Seric 	data.dsize = strlen(rhs);
49760089Seric 	data.dptr = rhs;
49860089Seric 
49960207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
50060089Seric 	{
50160089Seric 		key.dsize++;
50260089Seric 		data.dsize++;
50360089Seric 	}
50460089Seric 
50560089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
50660089Seric 	if (stat > 0)
50760089Seric 	{
50860089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
50960089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
51060089Seric 	}
51160089Seric 	if (stat != 0)
51260089Seric 		syserr("readaliases: dbm put (%s)", lhs);
51360089Seric }
51460089Seric 
51560089Seric 
51660089Seric /*
51760207Seric **  NDBM_MAP_CLOSE -- close the database
51860089Seric */
51960089Seric 
52060089Seric void
52160089Seric ndbm_map_close(map)
52260089Seric 	register MAP  *map;
52360089Seric {
52460207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
52560089Seric 	{
52664250Seric #ifdef NIS
52764075Seric 		bool inclnull;
52860089Seric 		char buf[200];
52960089Seric 
53064075Seric 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
53164075Seric 		map->map_mflags &= ~MF_INCLNULL;
53264075Seric 
53360089Seric 		(void) sprintf(buf, "%010ld", curtime());
53460089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
53560089Seric 
53660089Seric 		(void) myhostname(buf, sizeof buf);
53760089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
53864075Seric 
53964075Seric 		if (inclnull)
54064075Seric 			map->map_mflags |= MF_INCLNULL;
54160089Seric #endif
54260089Seric 
54360089Seric 		/* write out the distinguished alias */
54460089Seric 		ndbm_map_store(map, "@", "@");
54560089Seric 	}
54660089Seric 	dbm_close((DBM *) map->map_db1);
54760089Seric }
54860089Seric 
54960089Seric #endif
55060089Seric /*
55160582Seric **  NEWDB (Hash and BTree) Modules
55260089Seric */
55360089Seric 
55460089Seric #ifdef NEWDB
55560089Seric 
55660089Seric /*
55760582Seric **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
55860582Seric **
55960582Seric **	These do rather bizarre locking.  If you can lock on open,
56060582Seric **	do that to avoid the condition of opening a database that
56160582Seric **	is being rebuilt.  If you don't, we'll try to fake it, but
56260582Seric **	there will be a race condition.  If opening for read-only,
56360582Seric **	we immediately release the lock to avoid freezing things up.
56460582Seric **	We really ought to hold the lock, but guarantee that we won't
56560582Seric **	be pokey about it.  That's hard to do.
56660089Seric */
56760089Seric 
56856822Seric bool
56960089Seric bt_map_open(map, mode)
57056822Seric 	MAP *map;
57160089Seric 	int mode;
57256822Seric {
57356822Seric 	DB *db;
57460228Seric 	int i;
57560582Seric 	int omode;
57664373Seric 	int fd;
57764284Seric 	struct stat st;
57860089Seric 	char buf[MAXNAME];
57956822Seric 
58060537Seric 	if (tTd(38, 2))
58160089Seric 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
58260089Seric 
58360582Seric 	omode = mode;
58460582Seric 	if (omode == O_RDWR)
58560582Seric 	{
58660582Seric 		omode |= O_CREAT|O_TRUNC;
58764035Seric #if defined(O_EXLOCK) && defined(HASFLOCK)
58860582Seric 		omode |= O_EXLOCK;
58960582Seric # if !defined(OLD_NEWDB)
59060582Seric 	}
59160582Seric 	else
59260582Seric 	{
59360582Seric 		omode |= O_SHLOCK;
59460582Seric # endif
59560582Seric #endif
59660582Seric 	}
59760207Seric 
59860228Seric 	(void) strcpy(buf, map->map_file);
59960228Seric 	i = strlen(buf);
60060228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
60160228Seric 		(void) strcat(buf, ".db");
60260582Seric 	db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
60356822Seric 	if (db == NULL)
60456822Seric 	{
605*64718Seric #ifdef MAYBENEXTRELEASE
606*64718Seric 		if (aliaswait(map, ".db", FALSE))
607*64718Seric 			return TRUE;
608*64718Seric #endif
60960207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
61056836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
61156822Seric 		return FALSE;
61256822Seric 	}
61364035Seric #if !defined(OLD_NEWDB) && defined(HASFLOCK)
61464373Seric 	fd = db->fd(db);
61560582Seric # if !defined(O_EXLOCK)
61664373Seric 	if (mode == O_RDWR && fd >= 0)
61764388Seric 	{
61864388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
61964388Seric 			map->map_mflags |= MF_LOCKED;
62064388Seric 	}
62160582Seric # else
62264373Seric 	if (mode == O_RDONLY && fd >= 0)
62364373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
62464388Seric 	else
62564388Seric 		map->map_mflags |= MF_LOCKED;
62660582Seric # endif
62760582Seric #endif
62860585Seric 
62960585Seric 	/* try to make sure that at least the database header is on disk */
63060585Seric 	if (mode == O_RDWR)
63164373Seric #ifdef OLD_NEWDB
63264373Seric 		(void) db->sync(db);
63364373Seric #else
63460585Seric 		(void) db->sync(db, 0);
63560585Seric 
63664373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
63764284Seric 		map->map_mtime = st.st_mtime;
63864284Seric #endif
63964284Seric 
64060089Seric 	map->map_db2 = (void *) db;
64160207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
642*64718Seric 		if (!aliaswait(map, ".db", TRUE))
643*64718Seric 			return FALSE;
64456822Seric 	return TRUE;
64556822Seric }
64656822Seric 
64756822Seric 
64856822Seric /*
64956822Seric **  HASH_MAP_INIT -- HASH-style map initialization
65056822Seric */
65156822Seric 
65256822Seric bool
65360089Seric hash_map_open(map, mode)
65456822Seric 	MAP *map;
65560089Seric 	int mode;
65656822Seric {
65756822Seric 	DB *db;
65860228Seric 	int i;
65960582Seric 	int omode;
66064373Seric 	int fd;
66164284Seric 	struct stat st;
66260089Seric 	char buf[MAXNAME];
66356822Seric 
66460537Seric 	if (tTd(38, 2))
66560089Seric 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
66660089Seric 
66760582Seric 	omode = mode;
66860582Seric 	if (omode == O_RDWR)
66960582Seric 	{
67060582Seric 		omode |= O_CREAT|O_TRUNC;
67164035Seric #if defined(O_EXLOCK) && defined(HASFLOCK)
67260582Seric 		omode |= O_EXLOCK;
67360582Seric # if !defined(OLD_NEWDB)
67460582Seric 	}
67560582Seric 	else
67660582Seric 	{
67760582Seric 		omode |= O_SHLOCK;
67860582Seric # endif
67960582Seric #endif
68060582Seric 	}
68160207Seric 
68260228Seric 	(void) strcpy(buf, map->map_file);
68360228Seric 	i = strlen(buf);
68460228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
68560228Seric 		(void) strcat(buf, ".db");
68660582Seric 	db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
68756822Seric 	if (db == NULL)
68856822Seric 	{
689*64718Seric #ifdef MAYBENEXTRELEASE
690*64718Seric 		if (aliaswait(map, ".db", FALSE))
691*64718Seric 			return TRUE;
692*64718Seric #endif
69360207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
69456836Seric 			syserr("Cannot open HASH database %s", map->map_file);
69556822Seric 		return FALSE;
69656822Seric 	}
69764035Seric #if !defined(OLD_NEWDB) && defined(HASFLOCK)
69864373Seric 	fd = db->fd(db);
69960582Seric # if !defined(O_EXLOCK)
70064373Seric 	if (mode == O_RDWR && fd >= 0)
70164388Seric 	{
70264388Seric 		if (lockfile(fd, map->map_file, ".db", LOCK_EX))
70364388Seric 			map->map_mflags |= MF_LOCKED;
70464388Seric 	}
70560582Seric # else
70664373Seric 	if (mode == O_RDONLY && fd >= 0)
70764373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
70864388Seric 	else
70964388Seric 		map->map_mflags |= MF_LOCKED;
71060582Seric # endif
71160582Seric #endif
71260585Seric 
71360585Seric 	/* try to make sure that at least the database header is on disk */
71460585Seric 	if (mode == O_RDWR)
71564373Seric #ifdef OLD_NEWDB
71664373Seric 		(void) db->sync(db);
71764373Seric #else
71860585Seric 		(void) db->sync(db, 0);
71960585Seric 
72064373Seric 	if (fd >= 0 && fstat(fd, &st) >= 0)
72164284Seric 		map->map_mtime = st.st_mtime;
72264284Seric #endif
72364284Seric 
72460089Seric 	map->map_db2 = (void *) db;
72560207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
726*64718Seric 		if (!aliaswait(map, ".db", TRUE))
727*64718Seric 			return FALSE;
72856822Seric 	return TRUE;
72956822Seric }
73056822Seric 
73156822Seric 
73256822Seric /*
73356822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
73456822Seric */
73556822Seric 
73656822Seric char *
73760089Seric db_map_lookup(map, name, av, statp)
73856822Seric 	MAP *map;
73960089Seric 	char *name;
74056822Seric 	char **av;
74159084Seric 	int *statp;
74256822Seric {
74356822Seric 	DBT key, val;
74460422Seric 	register DB *db = (DB *) map->map_db2;
74560422Seric 	int st;
74660422Seric 	int saveerrno;
74764373Seric 	int fd;
74860089Seric 	char keybuf[MAXNAME + 1];
74956822Seric 
75060537Seric 	if (tTd(38, 20))
75160089Seric 		printf("db_map_lookup(%s)\n", name);
75260089Seric 
75360089Seric 	key.size = strlen(name);
75460089Seric 	if (key.size > sizeof keybuf - 1)
75560089Seric 		key.size = sizeof keybuf - 1;
75660089Seric 	key.data = keybuf;
75760089Seric 	bcopy(name, keybuf, key.size + 1);
75860207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
75960089Seric 		makelower(keybuf);
76060422Seric #ifndef OLD_NEWDB
76164388Seric 	fd = db->fd(db);
76264388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
76364388Seric 		(void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
76460422Seric #endif
76563753Seric 	st = 1;
76663753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
76763753Seric 	{
76863753Seric 		st = db->get(db, &key, &val, 0);
76963753Seric 		if (st == 0)
77063753Seric 			map->map_mflags &= ~MF_TRY1NULL;
77163753Seric 	}
77263753Seric 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
77363753Seric 	{
77463753Seric 		key.size++;
77563753Seric 		st = db->get(db, &key, &val, 0);
77663753Seric 		if (st == 0)
77763753Seric 			map->map_mflags &= ~MF_TRY0NULL;
77863753Seric 	}
77960422Seric 	saveerrno = errno;
78060422Seric #ifndef OLD_NEWDB
78164388Seric 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
78264373Seric 		(void) lockfile(fd, map->map_file, ".db", LOCK_UN);
78360422Seric #endif
78460422Seric 	if (st != 0)
78560422Seric 	{
78660422Seric 		errno = saveerrno;
78760422Seric 		if (st < 0)
78860422Seric 			syserr("db_map_lookup: get (%s)", name);
78956822Seric 		return NULL;
79060422Seric 	}
79160207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
79263753Seric 		return map_rewrite(map, name, strlen(name), NULL);
79363753Seric 	else
79463753Seric 		return map_rewrite(map, val.data, val.size, av);
79556822Seric }
79656822Seric 
79760089Seric 
79860089Seric /*
79960089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
80056822Seric */
80156822Seric 
80260089Seric void
80360089Seric db_map_store(map, lhs, rhs)
80460089Seric 	register MAP *map;
80560089Seric 	char *lhs;
80660089Seric 	char *rhs;
80756822Seric {
80860089Seric 	int stat;
80960089Seric 	DBT key;
81060089Seric 	DBT data;
81160089Seric 	register DB *db = map->map_db2;
81256822Seric 
81360537Seric 	if (tTd(38, 20))
81460089Seric 		printf("db_map_store(%s, %s)\n", lhs, rhs);
81560089Seric 
81660089Seric 	key.size = strlen(lhs);
81760089Seric 	key.data = lhs;
81860089Seric 
81960089Seric 	data.size = strlen(rhs);
82060089Seric 	data.data = rhs;
82160089Seric 
82260207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
82356822Seric 	{
82460089Seric 		key.size++;
82560089Seric 		data.size++;
82660089Seric 	}
82756836Seric 
82860089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
82960089Seric 	if (stat > 0)
83060089Seric 	{
83160089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
83260089Seric 		stat = db->put(db, &key, &data, 0);
83360089Seric 	}
83460089Seric 	if (stat != 0)
83560089Seric 		syserr("readaliases: db put (%s)", lhs);
83660089Seric }
83756836Seric 
83856847Seric 
83960089Seric /*
84060089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
84160089Seric */
84260089Seric 
84360089Seric void
84460089Seric db_map_close(map)
84560089Seric 	MAP *map;
84660089Seric {
84760089Seric 	register DB *db = map->map_db2;
84860089Seric 
84960537Seric 	if (tTd(38, 9))
85060207Seric 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
85160089Seric 
85260207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
85358804Seric 	{
85460089Seric 		/* write out the distinguished alias */
85560089Seric 		db_map_store(map, "@", "@");
85658804Seric 	}
85758963Seric 
85860089Seric 	if (db->close(db) != 0)
85960089Seric 		syserr("readaliases: db close failure");
86056822Seric }
86157208Seric 
86260089Seric #endif
86360089Seric /*
86460089Seric **  NIS Modules
86560089Seric */
86660089Seric 
86760089Seric # ifdef NIS
86860089Seric 
86964369Seric # ifndef YPERR_BUSY
87064369Seric #  define YPERR_BUSY	16
87164369Seric # endif
87264369Seric 
87357208Seric /*
87460089Seric **  NIS_MAP_OPEN -- open DBM map
87557208Seric */
87657208Seric 
87757208Seric bool
87860089Seric nis_map_open(map, mode)
87957208Seric 	MAP *map;
88060089Seric 	int mode;
88157208Seric {
88257216Seric 	int yperr;
88360215Seric 	register char *p;
88460215Seric 	auto char *vp;
88560215Seric 	auto int vsize;
88657216Seric 	char *master;
88757216Seric 
88860537Seric 	if (tTd(38, 2))
88960089Seric 		printf("nis_map_open(%s)\n", map->map_file);
89060089Seric 
89160207Seric 	if (mode != O_RDONLY)
89260207Seric 	{
89364650Seric 		/* issue a pseudo-error message */
89464650Seric #ifdef ENOSYS
89564650Seric 		errno = ENOSYS;
89664650Seric #else
89764650Seric # ifdef EFTYPE
89864650Seric 		errno = EFTYPE;
89964650Seric # else
90064650Seric 		errno = ENXIO;
90164650Seric # endif
90264650Seric #endif
90360207Seric 		return FALSE;
90460207Seric 	}
90560207Seric 
90660089Seric 	p = strchr(map->map_file, '@');
90760089Seric 	if (p != NULL)
90860089Seric 	{
90960089Seric 		*p++ = '\0';
91060089Seric 		if (*p != '\0')
91160089Seric 			map->map_domain = p;
91260089Seric 	}
91360215Seric 
91460089Seric 	if (map->map_domain == NULL)
91560089Seric 		yp_get_default_domain(&map->map_domain);
91660089Seric 
91760089Seric 	if (*map->map_file == '\0')
91860089Seric 		map->map_file = "mail.aliases";
91960089Seric 
92060215Seric 	/* check to see if this map actually exists */
92160089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
92260089Seric 			&vp, &vsize);
92360537Seric 	if (tTd(38, 10))
92460089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
92560089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
92660089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
92760089Seric 		return TRUE;
92860215Seric 
92960215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
93060215Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
93160215Seric 			yperr_string(yperr));
93260215Seric 
93360089Seric 	return FALSE;
93460089Seric }
93560089Seric 
93660089Seric 
93760089Seric /*
93857208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
93957208Seric */
94057208Seric 
94157208Seric char *
94260089Seric nis_map_lookup(map, name, av, statp)
94357208Seric 	MAP *map;
94460089Seric 	char *name;
94557208Seric 	char **av;
94659084Seric 	int *statp;
94757208Seric {
94857208Seric 	char *vp;
94957642Seric 	auto int vsize;
95059274Seric 	int buflen;
95160215Seric 	int yperr;
95260089Seric 	char keybuf[MAXNAME + 1];
95357208Seric 
95460537Seric 	if (tTd(38, 20))
95560089Seric 		printf("nis_map_lookup(%s)\n", name);
95660089Seric 
95760089Seric 	buflen = strlen(name);
95860089Seric 	if (buflen > sizeof keybuf - 1)
95960089Seric 		buflen = sizeof keybuf - 1;
96060089Seric 	bcopy(name, keybuf, buflen + 1);
96160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
96260089Seric 		makelower(keybuf);
96363753Seric 	yperr = YPERR_KEY;
96463753Seric 	if (bitset(MF_TRY0NULL, map->map_mflags))
96563753Seric 	{
96663753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
96763753Seric 			     &vp, &vsize);
96863753Seric 		if (yperr == 0)
96963753Seric 			map->map_mflags &= ~MF_TRY1NULL;
97063753Seric 	}
97163753Seric 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
97263753Seric 	{
97359274Seric 		buflen++;
97463753Seric 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
97563753Seric 			     &vp, &vsize);
97663753Seric 		if (yperr == 0)
97763753Seric 			map->map_mflags &= ~MF_TRY0NULL;
97863753Seric 	}
97960089Seric 	if (yperr != 0)
98060089Seric 	{
98160089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
98260215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
98357208Seric 		return NULL;
98460089Seric 	}
98560207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
98663753Seric 		return map_rewrite(map, name, strlen(name), NULL);
98763753Seric 	else
98863753Seric 		return map_rewrite(map, vp, vsize, av);
98957208Seric }
99057208Seric 
99160089Seric 
99260089Seric /*
99360207Seric **  NIS_MAP_STORE
99460089Seric */
99560089Seric 
99660089Seric void
99760089Seric nis_map_store(map, lhs, rhs)
99860089Seric 	MAP *map;
99960089Seric 	char *lhs;
100060089Seric 	char *rhs;
100160089Seric {
100260089Seric 	/* nothing */
100360089Seric }
100460089Seric 
100560089Seric 
100660089Seric /*
100760207Seric **  NIS_MAP_CLOSE
100860089Seric */
100960089Seric 
101060089Seric void
101160089Seric nis_map_close(map)
101260089Seric 	MAP *map;
101360089Seric {
101460089Seric 	/* nothing */
101560089Seric }
101660089Seric 
101760089Seric #endif /* NIS */
101857208Seric /*
101960089Seric **  STAB (Symbol Table) Modules
102060089Seric */
102160089Seric 
102260089Seric 
102360089Seric /*
102460207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
102560089Seric */
102660089Seric 
102760089Seric char *
102861707Seric stab_map_lookup(map, name, av, pstat)
102960089Seric 	register MAP *map;
103060089Seric 	char *name;
103161707Seric 	char **av;
103261707Seric 	int *pstat;
103360089Seric {
103460089Seric 	register STAB *s;
103560089Seric 
103660537Seric 	if (tTd(38, 20))
103760089Seric 		printf("stab_lookup(%s)\n", name);
103860089Seric 
103960089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
104060089Seric 	if (s != NULL)
104160089Seric 		return (s->s_alias);
104260089Seric 	return (NULL);
104360089Seric }
104460089Seric 
104560089Seric 
104660089Seric /*
104760207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
104860089Seric */
104960089Seric 
105060089Seric void
105160089Seric stab_map_store(map, lhs, rhs)
105260089Seric 	register MAP *map;
105360089Seric 	char *lhs;
105460089Seric 	char *rhs;
105560089Seric {
105660089Seric 	register STAB *s;
105760089Seric 
105860089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
105960089Seric 	s->s_alias = newstr(rhs);
106060089Seric }
106160089Seric 
106260089Seric 
106360089Seric /*
106460207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
106560207Seric **
106660207Seric **	This is a wierd case -- it is only intended as a fallback for
106760207Seric **	aliases.  For this reason, opens for write (only during a
106860207Seric **	"newaliases") always fails, and opens for read open the
106960207Seric **	actual underlying text file instead of the database.
107060089Seric */
107160089Seric 
107260089Seric bool
107360089Seric stab_map_open(map, mode)
107460089Seric 	register MAP *map;
107560089Seric 	int mode;
107660089Seric {
107763835Seric 	FILE *af;
107864284Seric 	struct stat st;
107963835Seric 
108060537Seric 	if (tTd(38, 2))
108160089Seric 		printf("stab_map_open(%s)\n", map->map_file);
108260089Seric 
108360089Seric 	if (mode != O_RDONLY)
108460207Seric 	{
108560207Seric 		errno = ENODEV;
108660089Seric 		return FALSE;
108760207Seric 	}
108860089Seric 
108963835Seric 	af = fopen(map->map_file, "r");
109063835Seric 	if (af == NULL)
109163835Seric 		return FALSE;
109263835Seric 	readaliases(map, af, TRUE);
109364284Seric 
109464284Seric 	if (fstat(fileno(af), &st) >= 0)
109564284Seric 		map->map_mtime = st.st_mtime;
109663835Seric 	fclose(af);
109763835Seric 
109860089Seric 	return TRUE;
109960089Seric }
110060089Seric 
110160089Seric 
110260089Seric /*
110364642Seric **  STAB_MAP_CLOSE -- close symbol table.
110464642Seric **
110564642Seric **	Since this is in memory, there is nothing to do.
110660089Seric */
110760089Seric 
110860089Seric void
110960089Seric stab_map_close(map)
111060089Seric 	MAP *map;
111160089Seric {
111260089Seric 	/* ignore it */
111360089Seric }
111460089Seric /*
111560089Seric **  Implicit Modules
111656822Seric **
111760089Seric **	Tries several types.  For back compatibility of aliases.
111856822Seric */
111956822Seric 
112060089Seric 
112160089Seric /*
112260207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
112360089Seric */
112460089Seric 
112560089Seric char *
112660089Seric impl_map_lookup(map, name, av, pstat)
112760089Seric 	MAP *map;
112860089Seric 	char *name;
112956822Seric 	char **av;
113060089Seric 	int *pstat;
113156822Seric {
113260537Seric 	if (tTd(38, 20))
113360089Seric 		printf("impl_map_lookup(%s)\n", name);
113456822Seric 
113560089Seric #ifdef NEWDB
113660207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
113760089Seric 		return db_map_lookup(map, name, av, pstat);
113860089Seric #endif
113960089Seric #ifdef NDBM
114060207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
114160089Seric 		return ndbm_map_lookup(map, name, av, pstat);
114260089Seric #endif
114360089Seric 	return stab_map_lookup(map, name, av, pstat);
114460089Seric }
114560089Seric 
114660089Seric /*
114760207Seric **  IMPL_MAP_STORE -- store in open databases
114860089Seric */
114960089Seric 
115060089Seric void
115160089Seric impl_map_store(map, lhs, rhs)
115260089Seric 	MAP *map;
115360089Seric 	char *lhs;
115460089Seric 	char *rhs;
115560089Seric {
115660089Seric #ifdef NEWDB
115760207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
115860089Seric 		db_map_store(map, lhs, rhs);
115960089Seric #endif
116060089Seric #ifdef NDBM
116160207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
116260089Seric 		ndbm_map_store(map, lhs, rhs);
116360089Seric #endif
116460089Seric 	stab_map_store(map, lhs, rhs);
116560089Seric }
116660089Seric 
116760089Seric /*
116860089Seric **  IMPL_MAP_OPEN -- implicit database open
116960089Seric */
117060089Seric 
117160089Seric bool
117260089Seric impl_map_open(map, mode)
117360089Seric 	MAP *map;
117460089Seric 	int mode;
117560089Seric {
117660089Seric 	struct stat stb;
117760089Seric 
117860537Seric 	if (tTd(38, 2))
1179*64718Seric 		printf("impl_map_open(%s, %d)\n", map->map_file, mode);
118060089Seric 
118160089Seric 	if (stat(map->map_file, &stb) < 0)
118256822Seric 	{
118360089Seric 		/* no alias file at all */
1184*64718Seric 		if (tTd(38, 3))
1185*64718Seric 			printf("no map file\n");
118660089Seric 		return FALSE;
118756822Seric 	}
118856822Seric 
118960089Seric #ifdef NEWDB
119060207Seric 	map->map_mflags |= MF_IMPL_HASH;
119160089Seric 	if (hash_map_open(map, mode))
119256822Seric 	{
119364250Seric #if defined(NDBM) && defined(NIS)
119460561Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
119560207Seric #endif
119660207Seric 			return TRUE;
119760089Seric 	}
119860207Seric 	else
119960207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
120060089Seric #endif
120160089Seric #ifdef NDBM
120260207Seric 	map->map_mflags |= MF_IMPL_NDBM;
120360089Seric 	if (ndbm_map_open(map, mode))
120460089Seric 	{
120560089Seric 		return TRUE;
120660089Seric 	}
120760207Seric 	else
120860207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
120960089Seric #endif
121056822Seric 
121164650Seric #if defined(NEWDB) || defined(NDBM)
121260089Seric 	if (Verbose)
121360089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
121460207Seric #endif
121560089Seric 
121660207Seric 	return stab_map_open(map, mode);
121756822Seric }
121860089Seric 
121960207Seric 
122060089Seric /*
122160207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
122260089Seric */
122360089Seric 
122460089Seric void
122560207Seric impl_map_close(map)
122660089Seric 	MAP *map;
122760089Seric {
122860089Seric #ifdef NEWDB
122960207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
123060089Seric 	{
123160207Seric 		db_map_close(map);
123260207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
123360089Seric 	}
123460089Seric #endif
123560089Seric 
123660089Seric #ifdef NDBM
123760207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
123860089Seric 	{
123960207Seric 		ndbm_map_close(map);
124060207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
124160089Seric 	}
124260089Seric #endif
124360089Seric }
124460207Seric /*
124560207Seric **  NULL stubs
124660089Seric */
124760089Seric 
124860207Seric bool
124960207Seric null_map_open(map, mode)
125060089Seric 	MAP *map;
125160207Seric 	int mode;
125260089Seric {
125360207Seric 	return TRUE;
125460089Seric }
125560089Seric 
125660207Seric void
125760207Seric null_map_close(map)
125860207Seric 	MAP *map;
125960089Seric {
126060207Seric 	return;
126160207Seric }
126260089Seric 
126360207Seric void
126460207Seric null_map_store(map, key, val)
126560207Seric 	MAP *map;
126660207Seric 	char *key;
126760207Seric 	char *val;
126860089Seric {
126960207Seric 	return;
127060089Seric }
1271