xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 60228)
156822Seric /*
256822Seric  * Copyright (c) 1992 Eric P. Allman.
356822Seric  * Copyright (c) 1992 Regents of the University of California.
456822Seric  * All rights reserved.
556822Seric  *
656822Seric  * %sccs.include.redist.c%
756822Seric  */
856822Seric 
956822Seric #ifndef lint
10*60228Seric static char sccsid[] = "@(#)map.c	6.18 (Berkeley) 05/22/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 
8660089Seric 	for (;;)
8760089Seric 	{
8860089Seric 		while (isascii(*p) && isspace(*p))
8960089Seric 			p++;
9060089Seric 		if (*p != '-')
9160089Seric 			break;
9260089Seric 		switch (*++p)
9360089Seric 		{
9460089Seric 		  case 'N':
9560207Seric 			map->map_mflags |= MF_INCLNULL;
9660089Seric 			break;
9760089Seric 
9860089Seric 		  case 'o':
9960207Seric 			map->map_mflags |= MF_OPTIONAL;
10060089Seric 			break;
10160089Seric 
10260089Seric 		  case 'f':
10360207Seric 			map->map_mflags |= MF_NOFOLDCASE;
10460089Seric 			break;
10560089Seric 
10660089Seric 		  case 'm':
10760207Seric 			map->map_mflags |= MF_MATCHONLY;
10860089Seric 			break;
10960089Seric 
11060089Seric 		  case 'a':
11160089Seric 			map->map_app = ++p;
11260089Seric 			break;
11360089Seric 		}
11460089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
11560089Seric 			p++;
11660089Seric 		if (*p != '\0')
11760089Seric 			*p++ = '\0';
11860089Seric 	}
11960089Seric 	if (map->map_app != NULL)
12060089Seric 		map->map_app = newstr(map->map_app);
12160089Seric 
12260089Seric 	if (*p != '\0')
12360089Seric 	{
12460089Seric 		map->map_file = p;
12560089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
12660089Seric 			p++;
12760089Seric 		if (*p != '\0')
12860089Seric 			*p++ = '\0';
12960089Seric 		map->map_file = newstr(map->map_file);
13060089Seric 	}
13160089Seric 
13260089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
13360089Seric 		p++;
13460089Seric 	if (*p != '\0')
13560089Seric 		map->map_rebuild = newstr(p);
13660089Seric 
13756822Seric 	if (map->map_file == NULL)
13857208Seric 	{
13960089Seric 		syserr("No file name for %s map %s",
14060089Seric 			map->map_class->map_cname, map->map_mname);
14156822Seric 		return FALSE;
14257208Seric 	}
14360089Seric 	return TRUE;
14460089Seric }
14560089Seric /*
14660089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
14760089Seric **
14860089Seric **	It also adds the map_app string.  It can be used as a utility
14960089Seric **	in the map_lookup method.
15060089Seric **
15160089Seric **	Parameters:
15260089Seric **		map -- the map that causes this.
15360089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
15460089Seric **		slen -- the length of s.
15560089Seric **		av -- arguments to interpolate into buf.
15660089Seric **
15760089Seric **	Returns:
15860089Seric **		Pointer to rewritten result.
15960089Seric **
16060089Seric **	Side Effects:
16160089Seric **		none.
16260089Seric */
16360089Seric 
16460089Seric char *
16560089Seric map_rewrite(map, s, slen, av)
16660089Seric 	register MAP *map;
16760089Seric 	register char *s;
16860089Seric 	int slen;
16960089Seric 	char **av;
17060089Seric {
17160089Seric 	register char *bp;
17260089Seric 	register char c;
17360089Seric 	char **avp;
17460089Seric 	register char *ap;
17560089Seric 	int i;
17660089Seric 	int len;
17760089Seric 	static int buflen = -1;
17860089Seric 	static char *buf = NULL;
17960089Seric 
18060089Seric 	if (tTd(23, 1))
18160089Seric 	{
18260089Seric 		printf("map_rewrite(%.*s), av =\n", slen, s);
18360089Seric 		for (avp = av; *avp != NULL; avp++)
18460089Seric 			printf("\t%s\n", *avp);
18560089Seric 	}
18660089Seric 
18760089Seric 	/* count expected size of output (can safely overestimate) */
18860089Seric 	i = len = slen;
18960089Seric 	if (av != NULL)
19060089Seric 	{
19160089Seric 		bp = s;
19260089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
19360089Seric 		{
19460089Seric 			if (c != '%')
19560089Seric 				continue;
19660089Seric 			if (--i < 0)
19760089Seric 				break;
19860089Seric 			c = *bp++;
19960089Seric 			if (!(isascii(c) && isdigit(c)))
20060089Seric 				continue;
20160089Seric 			c -= 0;
20260089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
20360089Seric 				continue;
20460089Seric 			if (*avp == NULL)
20560089Seric 				continue;
20660089Seric 			len += strlen(*avp);
20760089Seric 		}
20860089Seric 	}
20960089Seric 	if (map->map_app != NULL)
21060089Seric 		len += strlen(map->map_app);
21160089Seric 	if (buflen < ++len)
21260089Seric 	{
21360089Seric 		/* need to malloc additional space */
21460089Seric 		buflen = len;
21560089Seric 		if (buf != NULL)
21660089Seric 			free(buf);
21760089Seric 		buf = xalloc(buflen);
21860089Seric 	}
21960089Seric 
22060089Seric 	bp = buf;
22160089Seric 	if (av == NULL)
22260089Seric 	{
22360089Seric 		bcopy(s, bp, slen);
22460089Seric 		bp += slen;
22560089Seric 	}
22660089Seric 	else
22760089Seric 	{
22860089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
22960089Seric 		{
23060089Seric 			if (c != '%')
23160089Seric 			{
23260089Seric   pushc:
23360089Seric 				*bp++ = c;
23460089Seric 				continue;
23560089Seric 			}
23660089Seric 			if (--slen < 0 || (c = *s++) == '\0')
23760089Seric 				c = '%';
23860089Seric 			if (c == '%')
23960089Seric 				goto pushc;
24060089Seric 			if (!(isascii(c) && isdigit(c)))
24160089Seric 			{
24260089Seric 				*bp++ = '%';
24360089Seric 				goto pushc;
24460089Seric 			}
24560089Seric 			c -= '0';
24660089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
24760089Seric 				continue;
24860089Seric 			if (*avp == NULL)
24960089Seric 				continue;
25060089Seric 
25160089Seric 			/* transliterate argument into output string */
25260089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
25360089Seric 				*bp++ = c;
25460089Seric 		}
25560089Seric 	}
25660089Seric 	if (map->map_app != NULL)
25760089Seric 		strcpy(bp, map->map_app);
25860089Seric 	else
25960089Seric 		*bp = '\0';
26060089Seric 	if (tTd(23, 1))
26160089Seric 		printf("map_rewrite => %s\n", buf);
26260089Seric 	return buf;
26360089Seric }
26460089Seric /*
26560089Seric **  NDBM modules
26660089Seric */
26760089Seric 
26860089Seric #ifdef NDBM
26960089Seric 
27060089Seric /*
27160089Seric **  DBM_MAP_OPEN -- DBM-style map open
27260089Seric */
27360089Seric 
27460089Seric bool
27560089Seric ndbm_map_open(map, mode)
27660089Seric 	MAP *map;
27760089Seric 	int mode;
27860089Seric {
27960089Seric 	DBM *dbm;
28060089Seric 
28160089Seric 	if (tTd(27, 2))
28260089Seric 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
28360089Seric 
28460207Seric 	if (mode == O_RDWR)
28560207Seric 		mode |= O_CREAT|O_TRUNC;
28660207Seric 
28760089Seric 	/* open the database */
28860089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
28956822Seric 	if (dbm == NULL)
29056822Seric 	{
29160207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
29256836Seric 			syserr("Cannot open DBM database %s", map->map_file);
29356822Seric 		return FALSE;
29456822Seric 	}
29560089Seric 	map->map_db1 = (void *) dbm;
29660207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
29760207Seric 		aliaswait(map, ".dir");
29856822Seric 	return TRUE;
29956822Seric }
30060089Seric 
30160089Seric 
30260089Seric /*
30356822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
30456822Seric */
30556822Seric 
30656822Seric char *
30760089Seric ndbm_map_lookup(map, name, av, statp)
30856822Seric 	MAP *map;
30960089Seric 	char *name;
31056822Seric 	char **av;
31159084Seric 	int *statp;
31256822Seric {
31356822Seric 	datum key, val;
31460089Seric 	char keybuf[MAXNAME + 1];
31556822Seric 
31660089Seric 	if (tTd(27, 20))
31760089Seric 		printf("ndbm_map_lookup(%s)\n", name);
31860089Seric 
31960089Seric 	key.dptr = name;
32060089Seric 	key.dsize = strlen(name);
32160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
32257014Seric 	{
32360089Seric 		if (key.dsize > sizeof keybuf - 1)
32460089Seric 			key.dsize = sizeof keybuf - 1;
32560089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
32660089Seric 		makelower(keybuf);
32760089Seric 		key.dptr = keybuf;
32857014Seric 	}
32960207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
33056822Seric 		key.dsize++;
33160089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
33260089Seric 	val = dbm_fetch((DBM *) map->map_db1, key);
33360089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
33456822Seric 	if (val.dptr == NULL)
33556822Seric 		return NULL;
33660207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
33760089Seric 		av = NULL;
33860089Seric 	return map_rewrite(map, val.dptr, val.dsize, av);
33956822Seric }
34056822Seric 
34156822Seric 
34256822Seric /*
34360089Seric **  DBM_MAP_STORE -- store a datum in the database
34456822Seric */
34556822Seric 
34660089Seric void
34760089Seric ndbm_map_store(map, lhs, rhs)
34860089Seric 	register MAP *map;
34960089Seric 	char *lhs;
35060089Seric 	char *rhs;
35160089Seric {
35260089Seric 	datum key;
35360089Seric 	datum data;
35460089Seric 	int stat;
35560089Seric 
35660089Seric 	if (tTd(27, 12))
35760089Seric 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
35860089Seric 
35960089Seric 	key.dsize = strlen(lhs);
36060089Seric 	key.dptr = lhs;
36160089Seric 
36260089Seric 	data.dsize = strlen(rhs);
36360089Seric 	data.dptr = rhs;
36460089Seric 
36560207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
36660089Seric 	{
36760089Seric 		key.dsize++;
36860089Seric 		data.dsize++;
36960089Seric 	}
37060089Seric 
37160089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
37260089Seric 	if (stat > 0)
37360089Seric 	{
37460089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
37560089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
37660089Seric 	}
37760089Seric 	if (stat != 0)
37860089Seric 		syserr("readaliases: dbm put (%s)", lhs);
37960089Seric }
38060089Seric 
38160089Seric 
38260089Seric /*
38360207Seric **  NDBM_MAP_CLOSE -- close the database
38460089Seric */
38560089Seric 
38660089Seric void
38760089Seric ndbm_map_close(map)
38860089Seric 	register MAP  *map;
38960089Seric {
39060207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
39160089Seric 	{
39260089Seric #ifdef YPCOMPAT
39360089Seric 		char buf[200];
39460089Seric 
39560089Seric 		(void) sprintf(buf, "%010ld", curtime());
39660089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
39760089Seric 
39860089Seric 		(void) myhostname(buf, sizeof buf);
39960089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
40060089Seric #endif
40160089Seric 
40260089Seric 		/* write out the distinguished alias */
40360089Seric 		ndbm_map_store(map, "@", "@");
40460089Seric 	}
40560089Seric 	dbm_close((DBM *) map->map_db1);
40660089Seric }
40760089Seric 
40860089Seric #endif
40960089Seric /*
41060089Seric **  HASH (NEWDB) Modules
41160089Seric */
41260089Seric 
41360089Seric #ifdef NEWDB
41460089Seric 
41560089Seric /*
41660089Seric **  BTREE_MAP_PARSE -- BTREE-style map initialization
41760089Seric */
41860089Seric 
41956822Seric bool
42060089Seric bt_map_open(map, mode)
42156822Seric 	MAP *map;
42260089Seric 	int mode;
42356822Seric {
42456822Seric 	DB *db;
425*60228Seric 	int i;
42660089Seric 	char buf[MAXNAME];
42756822Seric 
42860089Seric 	if (tTd(27, 2))
42960089Seric 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
43060089Seric 
43160207Seric 	if (mode == O_RDWR)
43260207Seric 		mode |= O_CREAT|O_TRUNC;
43360207Seric 
434*60228Seric 	(void) strcpy(buf, map->map_file);
435*60228Seric 	i = strlen(buf);
436*60228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
437*60228Seric 		(void) strcat(buf, ".db");
43860222Seric 	db = dbopen(buf, mode, DBMMODE, DB_BTREE, NULL);
43956822Seric 	if (db == NULL)
44056822Seric 	{
44160207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
44256836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
44356822Seric 		return FALSE;
44456822Seric 	}
44560089Seric 	map->map_db2 = (void *) db;
44660207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
44760207Seric 		aliaswait(map, ".db");
44856822Seric 	return TRUE;
44956822Seric }
45056822Seric 
45156822Seric 
45256822Seric /*
45356822Seric **  HASH_MAP_INIT -- HASH-style map initialization
45456822Seric */
45556822Seric 
45656822Seric bool
45760089Seric hash_map_open(map, mode)
45856822Seric 	MAP *map;
45960089Seric 	int mode;
46056822Seric {
46156822Seric 	DB *db;
462*60228Seric 	int i;
46360089Seric 	char buf[MAXNAME];
46456822Seric 
46560089Seric 	if (tTd(27, 2))
46660089Seric 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
46760089Seric 
46860207Seric 	if (mode == O_RDWR)
46960207Seric 		mode |= O_CREAT|O_TRUNC;
47060207Seric 
471*60228Seric 	(void) strcpy(buf, map->map_file);
472*60228Seric 	i = strlen(buf);
473*60228Seric 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
474*60228Seric 		(void) strcat(buf, ".db");
47560222Seric 	db = dbopen(buf, mode, DBMMODE, DB_HASH, NULL);
47656822Seric 	if (db == NULL)
47756822Seric 	{
47860207Seric 		if (!bitset(MF_OPTIONAL, map->map_mflags))
47956836Seric 			syserr("Cannot open HASH database %s", map->map_file);
48056822Seric 		return FALSE;
48156822Seric 	}
48260089Seric 	map->map_db2 = (void *) db;
48360207Seric 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
48460207Seric 		aliaswait(map, ".db");
48556822Seric 	return TRUE;
48656822Seric }
48756822Seric 
48856822Seric 
48956822Seric /*
49056822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
49156822Seric */
49256822Seric 
49356822Seric char *
49460089Seric db_map_lookup(map, name, av, statp)
49556822Seric 	MAP *map;
49660089Seric 	char *name;
49756822Seric 	char **av;
49859084Seric 	int *statp;
49956822Seric {
50056822Seric 	DBT key, val;
50160089Seric 	char keybuf[MAXNAME + 1];
50256822Seric 
50360089Seric 	if (tTd(27, 20))
50460089Seric 		printf("db_map_lookup(%s)\n", name);
50560089Seric 
50660089Seric 	key.size = strlen(name);
50760089Seric 	if (key.size > sizeof keybuf - 1)
50860089Seric 		key.size = sizeof keybuf - 1;
50960089Seric 	key.data = keybuf;
51060089Seric 	bcopy(name, keybuf, key.size + 1);
51160207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
51260089Seric 		makelower(keybuf);
51360207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
51456822Seric 		key.size++;
51560089Seric 	if (((DB *) map->map_db2)->get((DB *) map->map_db2, &key, &val, 0) != 0)
51656822Seric 		return NULL;
51760207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
51860089Seric 		av = NULL;
51960089Seric 	return map_rewrite(map, val.data, val.size, av);
52056822Seric }
52156822Seric 
52260089Seric 
52360089Seric /*
52460089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
52556822Seric */
52656822Seric 
52760089Seric void
52860089Seric db_map_store(map, lhs, rhs)
52960089Seric 	register MAP *map;
53060089Seric 	char *lhs;
53160089Seric 	char *rhs;
53256822Seric {
53360089Seric 	int stat;
53460089Seric 	DBT key;
53560089Seric 	DBT data;
53660089Seric 	register DB *db = map->map_db2;
53756822Seric 
53860089Seric 	if (tTd(27, 20))
53960089Seric 		printf("db_map_store(%s, %s)\n", lhs, rhs);
54060089Seric 
54160089Seric 	key.size = strlen(lhs);
54260089Seric 	key.data = lhs;
54360089Seric 
54460089Seric 	data.size = strlen(rhs);
54560089Seric 	data.data = rhs;
54660089Seric 
54760207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
54856822Seric 	{
54960089Seric 		key.size++;
55060089Seric 		data.size++;
55160089Seric 	}
55256836Seric 
55360089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
55460089Seric 	if (stat > 0)
55560089Seric 	{
55660089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
55760089Seric 		stat = db->put(db, &key, &data, 0);
55860089Seric 	}
55960089Seric 	if (stat != 0)
56060089Seric 		syserr("readaliases: db put (%s)", lhs);
56160089Seric }
56256836Seric 
56356847Seric 
56460089Seric /*
56560089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
56660089Seric */
56760089Seric 
56860089Seric void
56960089Seric db_map_close(map)
57060089Seric 	MAP *map;
57160089Seric {
57260089Seric 	register DB *db = map->map_db2;
57360089Seric 
57460089Seric 	if (tTd(27, 9))
57560207Seric 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
57660089Seric 
57760207Seric 	if (bitset(MF_WRITABLE, map->map_mflags))
57858804Seric 	{
57960089Seric 		/* write out the distinguished alias */
58060089Seric 		db_map_store(map, "@", "@");
58158804Seric 	}
58258963Seric 
58360089Seric 	if (db->close(db) != 0)
58460089Seric 		syserr("readaliases: db close failure");
58556822Seric }
58657208Seric 
58760089Seric #endif
58860089Seric /*
58960089Seric **  NIS Modules
59060089Seric */
59160089Seric 
59260089Seric # ifdef NIS
59360089Seric 
59457208Seric /*
59560089Seric **  NIS_MAP_OPEN -- open DBM map
59657208Seric */
59757208Seric 
59857208Seric bool
59960089Seric nis_map_open(map, mode)
60057208Seric 	MAP *map;
60160089Seric 	int mode;
60257208Seric {
60357216Seric 	int yperr;
60460215Seric 	register char *p;
60560215Seric 	auto char *vp;
60660215Seric 	auto int vsize;
60757216Seric 	char *master;
60857216Seric 
60960089Seric 	if (tTd(27, 2))
61060089Seric 		printf("nis_map_open(%s)\n", map->map_file);
61160089Seric 
61260207Seric 	if (mode != O_RDONLY)
61360207Seric 	{
61460207Seric 		errno = ENODEV;
61560207Seric 		return FALSE;
61660207Seric 	}
61760207Seric 
61860089Seric 	p = strchr(map->map_file, '@');
61960089Seric 	if (p != NULL)
62060089Seric 	{
62160089Seric 		*p++ = '\0';
62260089Seric 		if (*p != '\0')
62360089Seric 			map->map_domain = p;
62460089Seric 	}
62560215Seric 
62660089Seric 	if (map->map_domain == NULL)
62760089Seric 		yp_get_default_domain(&map->map_domain);
62860089Seric 
62960089Seric 	if (*map->map_file == '\0')
63060089Seric 		map->map_file = "mail.aliases";
63160089Seric 
63260215Seric 	/* check to see if this map actually exists */
63360089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
63460089Seric 			&vp, &vsize);
63560089Seric 	if (tTd(27, 10))
63660089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
63760089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
63860089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
63960089Seric 		return TRUE;
64060215Seric 
64160215Seric 	if (!bitset(MF_OPTIONAL, map->map_mflags))
64260215Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
64360215Seric 			yperr_string(yperr));
64460215Seric 
64560089Seric 	return FALSE;
64660089Seric }
64760089Seric 
64860089Seric 
64960089Seric /*
65057208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
65157208Seric */
65257208Seric 
65357208Seric char *
65460089Seric nis_map_lookup(map, name, av, statp)
65557208Seric 	MAP *map;
65660089Seric 	char *name;
65757208Seric 	char **av;
65859084Seric 	int *statp;
65957208Seric {
66057208Seric 	char *vp;
66157642Seric 	auto int vsize;
66259274Seric 	int buflen;
66360215Seric 	int yperr;
66460089Seric 	char keybuf[MAXNAME + 1];
66557208Seric 
66660089Seric 	if (tTd(27, 20))
66760089Seric 		printf("nis_map_lookup(%s)\n", name);
66860089Seric 
66960089Seric 	buflen = strlen(name);
67060089Seric 	if (buflen > sizeof keybuf - 1)
67160089Seric 		buflen = sizeof keybuf - 1;
67260089Seric 	bcopy(name, keybuf, buflen + 1);
67360207Seric 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
67460089Seric 		makelower(keybuf);
67560207Seric 	if (bitset(MF_INCLNULL, map->map_mflags))
67659274Seric 		buflen++;
67760089Seric 	yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
67860089Seric 		     &vp, &vsize);
67960089Seric 	if (yperr != 0)
68060089Seric 	{
68160089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
68260215Seric 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
68357208Seric 		return NULL;
68460089Seric 	}
68560207Seric 	if (bitset(MF_MATCHONLY, map->map_mflags))
68660089Seric 		av = NULL;
68760215Seric 	return map_rewrite(map, vp, vsize, av);
68857208Seric }
68957208Seric 
69060089Seric 
69160089Seric /*
69260207Seric **  NIS_MAP_STORE
69360089Seric */
69460089Seric 
69560089Seric void
69660089Seric nis_map_store(map, lhs, rhs)
69760089Seric 	MAP *map;
69860089Seric 	char *lhs;
69960089Seric 	char *rhs;
70060089Seric {
70160089Seric 	/* nothing */
70260089Seric }
70360089Seric 
70460089Seric 
70560089Seric /*
70660207Seric **  NIS_MAP_CLOSE
70760089Seric */
70860089Seric 
70960089Seric void
71060089Seric nis_map_close(map)
71160089Seric 	MAP *map;
71260089Seric {
71360089Seric 	/* nothing */
71460089Seric }
71560089Seric 
71660089Seric #endif /* NIS */
71757208Seric /*
71860089Seric **  STAB (Symbol Table) Modules
71960089Seric */
72060089Seric 
72160089Seric 
72260089Seric /*
72360207Seric **  STAB_MAP_LOOKUP -- look up alias in symbol table
72460089Seric */
72560089Seric 
72660089Seric char *
72760089Seric stab_map_lookup(map, name)
72860089Seric 	register MAP *map;
72960089Seric 	char *name;
73060089Seric {
73160089Seric 	register STAB *s;
73260089Seric 
73360089Seric 	if (tTd(27, 20))
73460089Seric 		printf("stab_lookup(%s)\n", name);
73560089Seric 
73660089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
73760089Seric 	if (s != NULL)
73860089Seric 		return (s->s_alias);
73960089Seric 	return (NULL);
74060089Seric }
74160089Seric 
74260089Seric 
74360089Seric /*
74460207Seric **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
74560089Seric */
74660089Seric 
74760089Seric void
74860089Seric stab_map_store(map, lhs, rhs)
74960089Seric 	register MAP *map;
75060089Seric 	char *lhs;
75160089Seric 	char *rhs;
75260089Seric {
75360089Seric 	register STAB *s;
75460089Seric 
75560089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
75660089Seric 	s->s_alias = newstr(rhs);
75760089Seric }
75860089Seric 
75960089Seric 
76060089Seric /*
76160207Seric **  STAB_MAP_OPEN -- initialize (reads data file)
76260207Seric **
76360207Seric **	This is a wierd case -- it is only intended as a fallback for
76460207Seric **	aliases.  For this reason, opens for write (only during a
76560207Seric **	"newaliases") always fails, and opens for read open the
76660207Seric **	actual underlying text file instead of the database.
76760089Seric */
76860089Seric 
76960089Seric bool
77060089Seric stab_map_open(map, mode)
77160089Seric 	register MAP *map;
77260089Seric 	int mode;
77360089Seric {
77460089Seric 	FILE *af;
77560089Seric 
77660089Seric 	if (tTd(27, 2))
77760089Seric 		printf("stab_map_open(%s)\n", map->map_file);
77860089Seric 
77960089Seric 	if (mode != O_RDONLY)
78060207Seric 	{
78160207Seric 		errno = ENODEV;
78260089Seric 		return FALSE;
78360207Seric 	}
78460089Seric 
78560089Seric 	return TRUE;
78660089Seric }
78760089Seric 
78860089Seric 
78960089Seric /*
79060207Seric **  STAB_MAP_CLOSE -- close symbol table (???)
79160089Seric */
79260089Seric 
79360089Seric void
79460089Seric stab_map_close(map)
79560089Seric 	MAP *map;
79660089Seric {
79760089Seric 	/* ignore it */
79860089Seric }
79960089Seric /*
80060089Seric **  Implicit Modules
80156822Seric **
80260089Seric **	Tries several types.  For back compatibility of aliases.
80356822Seric */
80456822Seric 
80560089Seric 
80660089Seric /*
80760207Seric **  IMPL_MAP_LOOKUP -- lookup in best open database
80860089Seric */
80960089Seric 
81060089Seric char *
81160089Seric impl_map_lookup(map, name, av, pstat)
81260089Seric 	MAP *map;
81360089Seric 	char *name;
81456822Seric 	char **av;
81560089Seric 	int *pstat;
81656822Seric {
81760089Seric 	if (tTd(27, 20))
81860089Seric 		printf("impl_map_lookup(%s)\n", name);
81956822Seric 
82060089Seric #ifdef NEWDB
82160207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
82260089Seric 		return db_map_lookup(map, name, av, pstat);
82360089Seric #endif
82460089Seric #ifdef NDBM
82560207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
82660089Seric 		return ndbm_map_lookup(map, name, av, pstat);
82760089Seric #endif
82860089Seric 	return stab_map_lookup(map, name, av, pstat);
82960089Seric }
83060089Seric 
83160089Seric /*
83260207Seric **  IMPL_MAP_STORE -- store in open databases
83360089Seric */
83460089Seric 
83560089Seric void
83660089Seric impl_map_store(map, lhs, rhs)
83760089Seric 	MAP *map;
83860089Seric 	char *lhs;
83960089Seric 	char *rhs;
84060089Seric {
84160089Seric #ifdef NEWDB
84260207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
84360089Seric 		db_map_store(map, lhs, rhs);
84460089Seric #endif
84560089Seric #ifdef NDBM
84660207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
84760089Seric 		ndbm_map_store(map, lhs, rhs);
84860089Seric #endif
84960089Seric 	stab_map_store(map, lhs, rhs);
85060089Seric }
85160089Seric 
85260089Seric /*
85360089Seric **  IMPL_MAP_OPEN -- implicit database open
85460089Seric */
85560089Seric 
85660089Seric bool
85760089Seric impl_map_open(map, mode)
85860089Seric 	MAP *map;
85960089Seric 	int mode;
86060089Seric {
86160089Seric 	struct stat stb;
86260089Seric 
86360089Seric 	if (tTd(27, 2))
86460089Seric 		printf("impl_map_open(%s)\n", map->map_file);
86560089Seric 
86660089Seric 	if (stat(map->map_file, &stb) < 0)
86756822Seric 	{
86860089Seric 		/* no alias file at all */
86960089Seric 		return FALSE;
87056822Seric 	}
87156822Seric 
87260089Seric #ifdef NEWDB
87360207Seric 	map->map_mflags |= MF_IMPL_HASH;
87460089Seric 	if (hash_map_open(map, mode))
87556822Seric 	{
87660207Seric #if defined(NDBM) && defined(YPCOMPAT)
87760207Seric 		if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) == 0)
87860207Seric #endif
87960207Seric 			return TRUE;
88060089Seric 	}
88160207Seric 	else
88260207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
88360089Seric #endif
88460089Seric #ifdef NDBM
88560207Seric 	map->map_mflags |= MF_IMPL_NDBM;
88660089Seric 	if (ndbm_map_open(map, mode))
88760089Seric 	{
88860089Seric 		return TRUE;
88960089Seric 	}
89060207Seric 	else
89160207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
89260089Seric #endif
89356822Seric 
89460207Seric #if !defined(NEWDB) && !defined(NDBM)
89560089Seric 	if (Verbose)
89660089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
89760207Seric #endif
89860089Seric 
89960207Seric 	return stab_map_open(map, mode);
90056822Seric }
90160089Seric 
90260207Seric 
90360089Seric /*
90460207Seric **  IMPL_MAP_CLOSE -- close any open database(s)
90560089Seric */
90660089Seric 
90760089Seric void
90860207Seric impl_map_close(map)
90960089Seric 	MAP *map;
91060089Seric {
91160089Seric #ifdef NEWDB
91260207Seric 	if (bitset(MF_IMPL_HASH, map->map_mflags))
91360089Seric 	{
91460207Seric 		db_map_close(map);
91560207Seric 		map->map_mflags &= ~MF_IMPL_HASH;
91660089Seric 	}
91760089Seric #endif
91860089Seric 
91960089Seric #ifdef NDBM
92060207Seric 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
92160089Seric 	{
92260207Seric 		ndbm_map_close(map);
92360207Seric 		map->map_mflags &= ~MF_IMPL_NDBM;
92460089Seric 	}
92560089Seric #endif
92660089Seric }
92760207Seric /*
92860207Seric **  NULL stubs
92960089Seric */
93060089Seric 
93160207Seric bool
93260207Seric null_map_open(map, mode)
93360089Seric 	MAP *map;
93460207Seric 	int mode;
93560089Seric {
93660207Seric 	return TRUE;
93760089Seric }
93860089Seric 
93960207Seric void
94060207Seric null_map_close(map)
94160207Seric 	MAP *map;
94260089Seric {
94360207Seric 	return;
94460207Seric }
94560089Seric 
94660207Seric void
94760207Seric null_map_store(map, key, val)
94860207Seric 	MAP *map;
94960207Seric 	char *key;
95060207Seric 	char *val;
95160089Seric {
95260207Seric 	return;
95360089Seric }
954