xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 60089)
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*60089Seric static char sccsid[] = "@(#)map.c	6.14 (Berkeley) 05/17/93";
1156822Seric #endif /* not lint */
1256822Seric 
1356822Seric #include "sendmail.h"
1456822Seric 
15*60089Seric #ifdef NDBM
1656822Seric #include <ndbm.h>
1756822Seric #endif
18*60089Seric #ifdef NEWDB
1956822Seric #include <db.h>
2056822Seric #endif
21*60089Seric #ifdef NIS
2257208Seric #include <rpcsvc/ypclnt.h>
2357208Seric #endif
2456822Seric 
2556822Seric /*
26*60089Seric **  MAP.C -- implementations for various map classes.
2756822Seric **
28*60089Seric **	Each map class implements a series of functions:
29*60089Seric **
30*60089Seric **	bool map_parse(MAP *map, char *args)
31*60089Seric **		Parse the arguments from the config file.  Return TRUE
32*60089Seric **		if they were ok, FALSE otherwise.  Fill in map with the
33*60089Seric **		values.
34*60089Seric **
35*60089Seric **	char *map_lookup(MAP *map, char buf[], int bufsize,
36*60089Seric **			 char **args, int *pstat)
37*60089Seric **		Look up the key given in buf in the given map.  If found,
38*60089Seric **		do any rewriting the map wants (including "args" if desired)
39*60089Seric **		and return the value.  Set *pstat to the appropriate status
40*60089Seric **		on error and return NULL.
41*60089Seric **
42*60089Seric **	void map_store(MAP *map, char *key, char *value)
43*60089Seric **		Store the key:value pair in the map.
44*60089Seric **
45*60089Seric **	void map_rebuild(MAP *map, FILE *fp, int automatic)
46*60089Seric **		Rebuild the map.  If automatic is set, this is an
47*60089Seric **		auto-rebuild.
48*60089Seric **
49*60089Seric **	bool map_open(MAP *map, int mode)
50*60089Seric **		Open the map for the indicated mode.  Return TRUE if it
51*60089Seric **		was opened successfully, FALSE otherwise.
52*60089Seric **
53*60089Seric **	void map_close(MAP *map)
54*60089Seric **		Close the map.
55*60089Seric */
56*60089Seric 
57*60089Seric #define DBMMODE		0644
58*60089Seric /*
59*60089Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
60*60089Seric **
61*60089Seric **	This is a generic version of the map_parse method.
62*60089Seric **
6356822Seric **	Parameters:
64*60089Seric **		map -- the map being initialized.
65*60089Seric **		ap -- a pointer to the args on the config line.
6656822Seric **
6756822Seric **	Returns:
68*60089Seric **		TRUE -- if everything parsed OK.
6956822Seric **		FALSE -- otherwise.
7056822Seric **
7156822Seric **	Side Effects:
72*60089Seric **		null terminates the filename; stores it in map
7356822Seric */
7456822Seric 
7556822Seric bool
76*60089Seric map_parseargs(map, ap)
7756822Seric 	MAP *map;
78*60089Seric 	char *ap;
7956822Seric {
80*60089Seric 	register char *p = ap;
8156822Seric 
82*60089Seric 	for (;;)
83*60089Seric 	{
84*60089Seric 		while (isascii(*p) && isspace(*p))
85*60089Seric 			p++;
86*60089Seric 		if (*p != '-')
87*60089Seric 			break;
88*60089Seric 		switch (*++p)
89*60089Seric 		{
90*60089Seric 		  case 'N':
91*60089Seric 			map->map_flags |= MF_INCLNULL;
92*60089Seric 			break;
93*60089Seric 
94*60089Seric 		  case 'o':
95*60089Seric 			map->map_flags |= MF_OPTIONAL;
96*60089Seric 			break;
97*60089Seric 
98*60089Seric 		  case 'f':
99*60089Seric 			map->map_flags |= MF_NOFOLDCASE;
100*60089Seric 			break;
101*60089Seric 
102*60089Seric 		  case 'm':
103*60089Seric 			map->map_flags |= MF_MATCHONLY;
104*60089Seric 			break;
105*60089Seric 
106*60089Seric 		  case 'a':
107*60089Seric 			map->map_app = ++p;
108*60089Seric 			break;
109*60089Seric 
110*60089Seric 		  case 'd':
111*60089Seric 			map->map_domain = ++p;
112*60089Seric 			break;
113*60089Seric 		}
114*60089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
115*60089Seric 			p++;
116*60089Seric 		if (*p != '\0')
117*60089Seric 			*p++ = '\0';
118*60089Seric 	}
119*60089Seric 	if (map->map_app != NULL)
120*60089Seric 		map->map_app = newstr(map->map_app);
121*60089Seric 	if (map->map_domain != NULL)
122*60089Seric 		map->map_domain = newstr(map->map_domain);
123*60089Seric 
124*60089Seric 	if (*p != '\0')
125*60089Seric 	{
126*60089Seric 		map->map_file = p;
127*60089Seric 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
128*60089Seric 			p++;
129*60089Seric 		if (*p != '\0')
130*60089Seric 			*p++ = '\0';
131*60089Seric 		map->map_file = newstr(map->map_file);
132*60089Seric 	}
133*60089Seric 
134*60089Seric 	while (*p != '\0' && isascii(*p) && isspace(*p))
135*60089Seric 		p++;
136*60089Seric 	if (*p != '\0')
137*60089Seric 		map->map_rebuild = newstr(p);
138*60089Seric 
13956822Seric 	if (map->map_file == NULL)
14057208Seric 	{
141*60089Seric 		syserr("No file name for %s map %s",
142*60089Seric 			map->map_class->map_cname, map->map_mname);
14356822Seric 		return FALSE;
14457208Seric 	}
145*60089Seric 	return TRUE;
146*60089Seric }
147*60089Seric /*
148*60089Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
149*60089Seric **
150*60089Seric **	It also adds the map_app string.  It can be used as a utility
151*60089Seric **	in the map_lookup method.
152*60089Seric **
153*60089Seric **	Parameters:
154*60089Seric **		map -- the map that causes this.
155*60089Seric **		s -- the string to rewrite, NOT necessarily null terminated.
156*60089Seric **		slen -- the length of s.
157*60089Seric **		av -- arguments to interpolate into buf.
158*60089Seric **
159*60089Seric **	Returns:
160*60089Seric **		Pointer to rewritten result.
161*60089Seric **
162*60089Seric **	Side Effects:
163*60089Seric **		none.
164*60089Seric */
165*60089Seric 
166*60089Seric char *
167*60089Seric map_rewrite(map, s, slen, av)
168*60089Seric 	register MAP *map;
169*60089Seric 	register char *s;
170*60089Seric 	int slen;
171*60089Seric 	char **av;
172*60089Seric {
173*60089Seric 	register char *bp;
174*60089Seric 	register char c;
175*60089Seric 	char **avp;
176*60089Seric 	register char *ap;
177*60089Seric 	int i;
178*60089Seric 	int len;
179*60089Seric 	static int buflen = -1;
180*60089Seric 	static char *buf = NULL;
181*60089Seric 
182*60089Seric 	if (tTd(23, 1))
183*60089Seric 	{
184*60089Seric 		printf("map_rewrite(%.*s), av =\n", slen, s);
185*60089Seric 		for (avp = av; *avp != NULL; avp++)
186*60089Seric 			printf("\t%s\n", *avp);
187*60089Seric 	}
188*60089Seric 
189*60089Seric 	/* count expected size of output (can safely overestimate) */
190*60089Seric 	i = len = slen;
191*60089Seric 	if (av != NULL)
192*60089Seric 	{
193*60089Seric 		bp = s;
194*60089Seric 		for (i = slen; --i >= 0 && (c = *bp++) != 0; )
195*60089Seric 		{
196*60089Seric 			if (c != '%')
197*60089Seric 				continue;
198*60089Seric 			if (--i < 0)
199*60089Seric 				break;
200*60089Seric 			c = *bp++;
201*60089Seric 			if (!(isascii(c) && isdigit(c)))
202*60089Seric 				continue;
203*60089Seric 			c -= 0;
204*60089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
205*60089Seric 				continue;
206*60089Seric 			if (*avp == NULL)
207*60089Seric 				continue;
208*60089Seric 			len += strlen(*avp);
209*60089Seric 		}
210*60089Seric 	}
211*60089Seric 	if (map->map_app != NULL)
212*60089Seric 		len += strlen(map->map_app);
213*60089Seric 	if (buflen < ++len)
214*60089Seric 	{
215*60089Seric 		/* need to malloc additional space */
216*60089Seric 		buflen = len;
217*60089Seric 		if (buf != NULL)
218*60089Seric 			free(buf);
219*60089Seric 		buf = xalloc(buflen);
220*60089Seric 	}
221*60089Seric 
222*60089Seric 	bp = buf;
223*60089Seric 	if (av == NULL)
224*60089Seric 	{
225*60089Seric 		bcopy(s, bp, slen);
226*60089Seric 		bp += slen;
227*60089Seric 	}
228*60089Seric 	else
229*60089Seric 	{
230*60089Seric 		while (--slen >= 0 && (c = *s++) != '\0')
231*60089Seric 		{
232*60089Seric 			if (c != '%')
233*60089Seric 			{
234*60089Seric   pushc:
235*60089Seric 				*bp++ = c;
236*60089Seric 				continue;
237*60089Seric 			}
238*60089Seric 			if (--slen < 0 || (c = *s++) == '\0')
239*60089Seric 				c = '%';
240*60089Seric 			if (c == '%')
241*60089Seric 				goto pushc;
242*60089Seric 			if (!(isascii(c) && isdigit(c)))
243*60089Seric 			{
244*60089Seric 				*bp++ = '%';
245*60089Seric 				goto pushc;
246*60089Seric 			}
247*60089Seric 			c -= '0';
248*60089Seric 			for (avp = av; --c >= 0 && *avp != NULL; avp++)
249*60089Seric 				continue;
250*60089Seric 			if (*avp == NULL)
251*60089Seric 				continue;
252*60089Seric 
253*60089Seric 			/* transliterate argument into output string */
254*60089Seric 			for (ap = *avp; (c = *ap++) != '\0'; )
255*60089Seric 				*bp++ = c;
256*60089Seric 		}
257*60089Seric 	}
258*60089Seric 	if (map->map_app != NULL)
259*60089Seric 		strcpy(bp, map->map_app);
260*60089Seric 	else
261*60089Seric 		*bp = '\0';
262*60089Seric 	if (tTd(23, 1))
263*60089Seric 		printf("map_rewrite => %s\n", buf);
264*60089Seric 	return buf;
265*60089Seric }
266*60089Seric /*
267*60089Seric **  NDBM modules
268*60089Seric */
269*60089Seric 
270*60089Seric #ifdef NDBM
271*60089Seric 
272*60089Seric /*
273*60089Seric **  DBM_MAP_OPEN -- DBM-style map open
274*60089Seric */
275*60089Seric 
276*60089Seric bool
277*60089Seric ndbm_map_open(map, mode)
278*60089Seric 	MAP *map;
279*60089Seric 	int mode;
280*60089Seric {
281*60089Seric 	DBM *dbm;
282*60089Seric 
283*60089Seric 	if (tTd(27, 2))
284*60089Seric 		printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
285*60089Seric 
286*60089Seric 	/* open the database */
287*60089Seric 	dbm = dbm_open(map->map_file, mode, DBMMODE);
28856822Seric 	if (dbm == NULL)
28956822Seric 	{
29056836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
29156836Seric 			syserr("Cannot open DBM database %s", map->map_file);
29256822Seric 		return FALSE;
29356822Seric 	}
294*60089Seric 	map->map_db1 = (void *) dbm;
29556822Seric 	return TRUE;
29656822Seric }
297*60089Seric 
298*60089Seric 
299*60089Seric /*
30056822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
30156822Seric */
30256822Seric 
30356822Seric char *
304*60089Seric ndbm_map_lookup(map, name, av, statp)
30556822Seric 	MAP *map;
306*60089Seric 	char *name;
30756822Seric 	char **av;
30859084Seric 	int *statp;
30956822Seric {
31056822Seric 	datum key, val;
311*60089Seric 	char keybuf[MAXNAME + 1];
31256822Seric 
313*60089Seric 	if (tTd(27, 20))
314*60089Seric 		printf("ndbm_map_lookup(%s)\n", name);
315*60089Seric 
316*60089Seric 	key.dptr = name;
317*60089Seric 	key.dsize = strlen(name);
31857033Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
31957014Seric 	{
320*60089Seric 		if (key.dsize > sizeof keybuf - 1)
321*60089Seric 			key.dsize = sizeof keybuf - 1;
322*60089Seric 		bcopy(key.dptr, keybuf, key.dsize + 1);
323*60089Seric 		makelower(keybuf);
324*60089Seric 		key.dptr = keybuf;
32557014Seric 	}
32656822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
32756822Seric 		key.dsize++;
328*60089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
329*60089Seric 	val = dbm_fetch((DBM *) map->map_db1, key);
330*60089Seric 	(void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
33156822Seric 	if (val.dptr == NULL)
33256822Seric 		return NULL;
333*60089Seric 	if (bitset(MF_MATCHONLY, map->map_flags))
334*60089Seric 		av = NULL;
335*60089Seric 	return map_rewrite(map, val.dptr, val.dsize, av);
33656822Seric }
33756822Seric 
33856822Seric 
33956822Seric /*
340*60089Seric **  DBM_MAP_STORE -- store a datum in the database
34156822Seric */
34256822Seric 
343*60089Seric void
344*60089Seric ndbm_map_store(map, lhs, rhs)
345*60089Seric 	register MAP *map;
346*60089Seric 	char *lhs;
347*60089Seric 	char *rhs;
348*60089Seric {
349*60089Seric 	datum key;
350*60089Seric 	datum data;
351*60089Seric 	int stat;
352*60089Seric 
353*60089Seric 	if (tTd(27, 12))
354*60089Seric 		printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
355*60089Seric 
356*60089Seric 	key.dsize = strlen(lhs);
357*60089Seric 	key.dptr = lhs;
358*60089Seric 
359*60089Seric 	data.dsize = strlen(rhs);
360*60089Seric 	data.dptr = rhs;
361*60089Seric 
362*60089Seric 	if (bitset(MF_INCLNULL, map->map_flags))
363*60089Seric 	{
364*60089Seric 		key.dsize++;
365*60089Seric 		data.dsize++;
366*60089Seric 	}
367*60089Seric 
368*60089Seric 	stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
369*60089Seric 	if (stat > 0)
370*60089Seric 	{
371*60089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
372*60089Seric 		stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
373*60089Seric 	}
374*60089Seric 	if (stat != 0)
375*60089Seric 		syserr("readaliases: dbm put (%s)", lhs);
376*60089Seric }
377*60089Seric 
378*60089Seric 
379*60089Seric /*
380*60089Seric **  DBM_MAP_REBUILD -- rebuild DBM database
381*60089Seric */
382*60089Seric 
383*60089Seric void
384*60089Seric ndbm_map_rebuild(map, fp, automatic)
385*60089Seric 	register MAP *map;
386*60089Seric 	FILE *fp;
387*60089Seric 	int automatic;
388*60089Seric {
389*60089Seric 	register DBM *db;
390*60089Seric 	int i;
391*60089Seric 	char buf[MAXNAME];
392*60089Seric 
393*60089Seric 	if (tTd(27, 2))
394*60089Seric 		printf("ndbm_map_rebuild(%s)\n", map->map_file);
395*60089Seric 
396*60089Seric 	db = dbm_open(map->map_file, O_RDWR|O_CREAT|O_TRUNC, DBMMODE);
397*60089Seric 	if (db == NULL)
398*60089Seric 	{
399*60089Seric 		syserr("ndbm_map_rebuild: cannot create %s", buf);
400*60089Seric 		return;
401*60089Seric 	}
402*60089Seric 	map->map_db1 = (void *) db;
403*60089Seric 	map->map_flags |= MF_WRITABLE|MF_VALID;
404*60089Seric }
405*60089Seric 
406*60089Seric /*
407*60089Seric **  NDBM_ACLOSE -- close the database
408*60089Seric */
409*60089Seric 
410*60089Seric void
411*60089Seric ndbm_map_close(map)
412*60089Seric 	register MAP  *map;
413*60089Seric {
414*60089Seric 	if (bitset(MF_WRITABLE, map->map_flags))
415*60089Seric 	{
416*60089Seric #ifdef YPCOMPAT
417*60089Seric 		char buf[200];
418*60089Seric 
419*60089Seric 		(void) sprintf(buf, "%010ld", curtime());
420*60089Seric 		ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
421*60089Seric 
422*60089Seric 		(void) myhostname(buf, sizeof buf);
423*60089Seric 		ndbm_map_store(map, "YP_MASTER_NAME", buf);
424*60089Seric #endif
425*60089Seric 
426*60089Seric 		/* write out the distinguished alias */
427*60089Seric 		ndbm_map_store(map, "@", "@");
428*60089Seric 	}
429*60089Seric 	dbm_close((DBM *) map->map_db1);
430*60089Seric }
431*60089Seric 
432*60089Seric #endif
433*60089Seric /*
434*60089Seric **  HASH (NEWDB) Modules
435*60089Seric */
436*60089Seric 
437*60089Seric #ifdef NEWDB
438*60089Seric 
439*60089Seric /*
440*60089Seric **  BTREE_MAP_PARSE -- BTREE-style map initialization
441*60089Seric */
442*60089Seric 
44356822Seric bool
444*60089Seric bt_map_open(map, mode)
44556822Seric 	MAP *map;
446*60089Seric 	int mode;
44756822Seric {
44856822Seric 	DB *db;
449*60089Seric 	char buf[MAXNAME];
45056822Seric 
451*60089Seric 	if (tTd(27, 2))
452*60089Seric 		printf("bt_map_open(%s, %d)\n", map->map_file, mode);
453*60089Seric 
454*60089Seric 	(void) sprintf(buf, "%s.db", map->map_file);
455*60089Seric 	db = dbopen(buf, mode, 0644, DB_BTREE, NULL);
45656822Seric 	if (db == NULL)
45756822Seric 	{
45856836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
45956836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
46056822Seric 		return FALSE;
46156822Seric 	}
462*60089Seric 	map->map_db2 = (void *) db;
46356822Seric 	return TRUE;
46456822Seric }
46556822Seric 
46656822Seric 
46756822Seric /*
46856822Seric **  HASH_MAP_INIT -- HASH-style map initialization
46956822Seric */
47056822Seric 
47156822Seric bool
472*60089Seric hash_map_open(map, mode)
47356822Seric 	MAP *map;
474*60089Seric 	int mode;
47556822Seric {
47656822Seric 	DB *db;
477*60089Seric 	char buf[MAXNAME];
47856822Seric 
479*60089Seric 	if (tTd(27, 2))
480*60089Seric 		printf("hash_map_open(%s, %d)\n", map->map_file, mode);
481*60089Seric 
482*60089Seric 	(void) sprintf(buf, "%s.db", map->map_file);
483*60089Seric 	db = dbopen(buf, mode, 0644, DB_HASH, NULL);
48456822Seric 	if (db == NULL)
48556822Seric 	{
48656836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
48756836Seric 			syserr("Cannot open HASH database %s", map->map_file);
48856822Seric 		return FALSE;
48956822Seric 	}
490*60089Seric 	map->map_db2 = (void *) db;
49156822Seric 	return TRUE;
49256822Seric }
49356822Seric 
49456822Seric 
49556822Seric /*
49656822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
49756822Seric */
49856822Seric 
49956822Seric char *
500*60089Seric db_map_lookup(map, name, av, statp)
50156822Seric 	MAP *map;
502*60089Seric 	char *name;
50356822Seric 	char **av;
50459084Seric 	int *statp;
50556822Seric {
50656822Seric 	DBT key, val;
507*60089Seric 	char keybuf[MAXNAME + 1];
50856822Seric 
509*60089Seric 	if (tTd(27, 20))
510*60089Seric 		printf("db_map_lookup(%s)\n", name);
511*60089Seric 
512*60089Seric 	key.size = strlen(name);
513*60089Seric 	if (key.size > sizeof keybuf - 1)
514*60089Seric 		key.size = sizeof keybuf - 1;
515*60089Seric 	key.data = keybuf;
516*60089Seric 	bcopy(name, keybuf, key.size + 1);
51757033Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
518*60089Seric 		makelower(keybuf);
51956822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
52056822Seric 		key.size++;
521*60089Seric 	if (((DB *) map->map_db2)->get((DB *) map->map_db2, &key, &val, 0) != 0)
52256822Seric 		return NULL;
523*60089Seric 	if (bitset(MF_MATCHONLY, map->map_flags))
524*60089Seric 		av = NULL;
525*60089Seric 	return map_rewrite(map, val.data, val.size, av);
52656822Seric }
52756822Seric 
528*60089Seric 
529*60089Seric /*
530*60089Seric **  DB_MAP_STORE -- store a datum in the NEWDB database
53156822Seric */
53256822Seric 
533*60089Seric void
534*60089Seric db_map_store(map, lhs, rhs)
535*60089Seric 	register MAP *map;
536*60089Seric 	char *lhs;
537*60089Seric 	char *rhs;
53856822Seric {
539*60089Seric 	int stat;
540*60089Seric 	DBT key;
541*60089Seric 	DBT data;
542*60089Seric 	register DB *db = map->map_db2;
54356822Seric 
544*60089Seric 	if (tTd(27, 20))
545*60089Seric 		printf("db_map_store(%s, %s)\n", lhs, rhs);
546*60089Seric 
547*60089Seric 	key.size = strlen(lhs);
548*60089Seric 	key.data = lhs;
549*60089Seric 
550*60089Seric 	data.size = strlen(rhs);
551*60089Seric 	data.data = rhs;
552*60089Seric 
553*60089Seric 	if (bitset(MF_INCLNULL, map->map_flags))
55456822Seric 	{
555*60089Seric 		key.size++;
556*60089Seric 		data.size++;
557*60089Seric 	}
55856836Seric 
559*60089Seric 	stat = db->put(db, &key, &data, R_NOOVERWRITE);
560*60089Seric 	if (stat > 0)
561*60089Seric 	{
562*60089Seric 		usrerr("050 Warning: duplicate alias name %s", lhs);
563*60089Seric 		stat = db->put(db, &key, &data, 0);
564*60089Seric 	}
565*60089Seric 	if (stat != 0)
566*60089Seric 		syserr("readaliases: db put (%s)", lhs);
567*60089Seric }
56856836Seric 
56956847Seric 
570*60089Seric /*
571*60089Seric **  HASH_MAP_REBUILD -- rebuild hash database
572*60089Seric */
57357208Seric 
574*60089Seric void
575*60089Seric db_map_rebuild(map, fp, automatic, e)
576*60089Seric 	register MAP *map;
577*60089Seric 	FILE *fp;
578*60089Seric 	int automatic;
579*60089Seric 	ENVELOPE *e;
580*60089Seric {
581*60089Seric 	register DB *db;
582*60089Seric 	char buf[MAXNAME];
58357208Seric 
584*60089Seric 	if (tTd(27, 2))
585*60089Seric 		printf("hash_map_rebuild(%s)\n", map->map_file);
586*60089Seric 
587*60089Seric 	(void) strcpy(buf, map->map_file);
588*60089Seric 	(void) strcat(buf, ".db");
589*60089Seric 	db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL);
590*60089Seric 	if (db == NULL)
591*60089Seric 	{
592*60089Seric 		syserr("hash_map_rebuild: cannot create %s", buf);
593*60089Seric 		return;
59456822Seric 	}
595*60089Seric 	map->map_db2 = db;
596*60089Seric 	map->map_flags |= MF_WRITABLE|MF_VALID;
597*60089Seric }
59856822Seric 
599*60089Seric 
600*60089Seric /*
601*60089Seric **  DB_MAP_CLOSE -- add distinguished entries and close the database
602*60089Seric */
603*60089Seric 
604*60089Seric void
605*60089Seric db_map_close(map)
606*60089Seric 	MAP *map;
607*60089Seric {
608*60089Seric 	register DB *db = map->map_db2;
609*60089Seric 
610*60089Seric 	if (tTd(27, 9))
611*60089Seric 		printf("db_map_close(%s, %x)\n", map->map_file, map->map_flags);
612*60089Seric 
613*60089Seric 	if (bitset(MF_WRITABLE, map->map_flags))
61458804Seric 	{
615*60089Seric 		/* write out the distinguished alias */
616*60089Seric 		db_map_store(map, "@", "@");
61758804Seric 	}
61858963Seric 
619*60089Seric 	if (db->close(db) != 0)
620*60089Seric 		syserr("readaliases: db close failure");
62156822Seric }
62257208Seric 
623*60089Seric #endif
624*60089Seric /*
625*60089Seric **  NIS Modules
626*60089Seric */
627*60089Seric 
628*60089Seric # ifdef NIS
629*60089Seric 
63057208Seric /*
631*60089Seric **  NIS_MAP_OPEN -- open DBM map
63257208Seric */
63357208Seric 
63457208Seric bool
635*60089Seric nis_map_open(map, mode)
63657208Seric 	MAP *map;
637*60089Seric 	int mode;
63857208Seric {
63957216Seric 	int yperr;
64057216Seric 	char *master;
64157216Seric 
642*60089Seric 	if (tTd(27, 2))
643*60089Seric 		printf("nis_map_open(%s)\n", map->map_file);
644*60089Seric 
64557208Seric 	if (map->map_domain == NULL)
64657208Seric 		yp_get_default_domain(&map->map_domain);
64757216Seric 
64857216Seric 	/* check to see if this map actually exists */
64957216Seric 	yperr = yp_master(map->map_domain, map->map_file, &master);
65057216Seric 	if (yperr == 0)
65157216Seric 		return TRUE;
65257216Seric 	if (!bitset(MF_OPTIONAL, map->map_flags))
65357216Seric 		syserr("Cannot bind to domain %s: %s", map->map_domain,
65457216Seric 			yperr_string(yperr));
65557216Seric 	return FALSE;
65657208Seric }
657*60089Seric 
658*60089Seric bool
659*60089Seric nis_map_open(map, mode)
660*60089Seric 	MAP *map;
661*60089Seric 	int mode;
662*60089Seric {
663*60089Seric 	register char *p;
664*60089Seric 	int yperr;
665*60089Seric 	auto char *vp;
666*60089Seric 	auto int vsize;
667*60089Seric 
668*60089Seric 	p = strchr(map->map_file, '@');
669*60089Seric 	if (p != NULL)
670*60089Seric 	{
671*60089Seric 		*p++ = '\0';
672*60089Seric 		if (*p != '\0')
673*60089Seric 			map->map_domain = p;
674*60089Seric 	}
675*60089Seric 	if (map->map_domain == NULL)
676*60089Seric 		yp_get_default_domain(&map->map_domain);
677*60089Seric 
678*60089Seric 	if (*map->map_file == '\0')
679*60089Seric 		map->map_file = "mail.aliases";
680*60089Seric 
681*60089Seric 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
682*60089Seric 			&vp, &vsize);
683*60089Seric 	if (tTd(27, 10))
684*60089Seric 		printf("nis_map_open: yp_match(%s, %s) => %s\n",
685*60089Seric 			map->map_domain, map->map_file, yperr_string(yperr));
686*60089Seric 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
687*60089Seric 		return TRUE;
688*60089Seric 	return FALSE;
689*60089Seric }
690*60089Seric 
691*60089Seric 
692*60089Seric /*
69357208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
69457208Seric */
69557208Seric 
69657208Seric char *
697*60089Seric nis_map_lookup(map, name, av, statp)
69857208Seric 	MAP *map;
699*60089Seric 	char *name;
70057208Seric 	char **av;
70159084Seric 	int *statp;
70257208Seric {
70357208Seric 	char *vp;
70457642Seric 	auto int vsize;
70559274Seric 	int buflen;
706*60089Seric 	char keybuf[MAXNAME + 1];
70757208Seric 
708*60089Seric 	if (tTd(27, 20))
709*60089Seric 		printf("nis_map_lookup(%s)\n", name);
710*60089Seric 
711*60089Seric 	buflen = strlen(name);
712*60089Seric 	if (buflen > sizeof keybuf - 1)
713*60089Seric 		buflen = sizeof keybuf - 1;
714*60089Seric 	bcopy(name, keybuf, buflen + 1);
71557208Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
716*60089Seric 		makelower(keybuf);
71759274Seric 	if (bitset(MF_INCLNULL, map->map_flags))
71859274Seric 		buflen++;
719*60089Seric 	yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
720*60089Seric 		     &vp, &vsize);
721*60089Seric 	if (yperr != 0)
722*60089Seric 	{
723*60089Seric 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
724*60089Seric 			map->map_flags &= ~MF_VALID;
72557208Seric 		return NULL;
726*60089Seric 	}
727*60089Seric 	if (bitset(MF_MATCHONLY, map->map_flags))
728*60089Seric 		av = NULL;
729*60089Seric 	return map_rewrite(map, val.dptr, val.dsize, av);
73057208Seric }
73157208Seric 
732*60089Seric 
733*60089Seric /*
734*60089Seric **  NIS_ASTORE
735*60089Seric */
736*60089Seric 
737*60089Seric void
738*60089Seric nis_map_store(map, lhs, rhs)
739*60089Seric 	MAP *map;
740*60089Seric 	char *lhs;
741*60089Seric 	char *rhs;
742*60089Seric {
743*60089Seric 	/* nothing */
744*60089Seric }
745*60089Seric 
746*60089Seric /*
747*60089Seric **  NIS_AREBUILD
748*60089Seric */
749*60089Seric 
750*60089Seric void
751*60089Seric nis_map_rebuild(map, fp, automatic, e)
752*60089Seric 	MAP *map;
753*60089Seric 	FILE *fp;
754*60089Seric 	int automatic;
755*60089Seric 	ENVELOPE *e;
756*60089Seric {
757*60089Seric 	if (tTd(27, 2))
758*60089Seric 		printf("nis_map_rebuild(%s)\n", map->map_file);
759*60089Seric }
760*60089Seric 
761*60089Seric 
762*60089Seric /*
763*60089Seric **  NIS_ACLOSE
764*60089Seric */
765*60089Seric 
766*60089Seric void
767*60089Seric nis_map_close(map)
768*60089Seric 	MAP *map;
769*60089Seric {
770*60089Seric 	/* nothing */
771*60089Seric }
772*60089Seric 
773*60089Seric #endif /* NIS */
77457208Seric /*
775*60089Seric **  STAB (Symbol Table) Modules
776*60089Seric */
777*60089Seric 
778*60089Seric 
779*60089Seric /*
780*60089Seric **  STAB_ALOOKUP -- look up alias in symbol table
781*60089Seric */
782*60089Seric 
783*60089Seric char *
784*60089Seric stab_map_lookup(map, name)
785*60089Seric 	register MAP *map;
786*60089Seric 	char *name;
787*60089Seric {
788*60089Seric 	register STAB *s;
789*60089Seric 
790*60089Seric 	if (tTd(27, 20))
791*60089Seric 		printf("stab_lookup(%s)\n", name);
792*60089Seric 
793*60089Seric 	s = stab(name, ST_ALIAS, ST_FIND);
794*60089Seric 	if (s != NULL)
795*60089Seric 		return (s->s_alias);
796*60089Seric 	return (NULL);
797*60089Seric }
798*60089Seric 
799*60089Seric 
800*60089Seric /*
801*60089Seric **  STAB_ASTORE -- store in symtab (actually using during init, not rebuild)
802*60089Seric */
803*60089Seric 
804*60089Seric void
805*60089Seric stab_map_store(map, lhs, rhs)
806*60089Seric 	register MAP *map;
807*60089Seric 	char *lhs;
808*60089Seric 	char *rhs;
809*60089Seric {
810*60089Seric 	register STAB *s;
811*60089Seric 
812*60089Seric 	s = stab(lhs, ST_ALIAS, ST_ENTER);
813*60089Seric 	s->s_alias = newstr(rhs);
814*60089Seric }
815*60089Seric 
816*60089Seric 
817*60089Seric /*
818*60089Seric **  STAB_AINIT -- initialize (reads data file)
819*60089Seric */
820*60089Seric 
821*60089Seric bool
822*60089Seric stab_map_open(map, mode)
823*60089Seric 	register MAP *map;
824*60089Seric 	int mode;
825*60089Seric {
826*60089Seric 	FILE *af;
827*60089Seric 
828*60089Seric 	if (tTd(27, 2))
829*60089Seric 		printf("stab_map_open(%s)\n", map->map_file);
830*60089Seric 
831*60089Seric 	if (mode != O_RDONLY)
832*60089Seric 		return FALSE;
833*60089Seric 
834*60089Seric 	af = fopen(map->map_file, "r");
835*60089Seric 	if (af == NULL)
836*60089Seric 		return FALSE;
837*60089Seric 	return TRUE;
838*60089Seric }
839*60089Seric 
840*60089Seric 
841*60089Seric /*
842*60089Seric **  STAB_AREBUILD -- rebuild alias file
843*60089Seric */
844*60089Seric 
845*60089Seric void
846*60089Seric stab_map_rebuild(map, fp, automatic, e)
847*60089Seric 	MAP *map;
848*60089Seric 	FILE *fp;
849*60089Seric 	int automatic;
850*60089Seric 	ENVELOPE *e;
851*60089Seric {
852*60089Seric 	if (tTd(27, 2))
853*60089Seric 		printf("stab_map_rebuild(%s)\n", map->map_file);
854*60089Seric 
855*60089Seric 	map->map_flags |= MF_WRITABLE|MF_VALID;
856*60089Seric }
857*60089Seric 
858*60089Seric 
859*60089Seric /*
860*60089Seric **  STAB_ACLOSE -- close symbol table (???)
861*60089Seric */
862*60089Seric 
863*60089Seric void
864*60089Seric stab_map_close(map)
865*60089Seric 	MAP *map;
866*60089Seric {
867*60089Seric 	/* ignore it */
868*60089Seric }
869*60089Seric /*
870*60089Seric **  Implicit Modules
87156822Seric **
872*60089Seric **	Tries several types.  For back compatibility of aliases.
87356822Seric */
87456822Seric 
875*60089Seric 
876*60089Seric /*
877*60089Seric **  IMPL_ALOOKUP -- lookup in best open database
878*60089Seric */
879*60089Seric 
880*60089Seric char *
881*60089Seric impl_map_lookup(map, name, av, pstat)
882*60089Seric 	MAP *map;
883*60089Seric 	char *name;
88456822Seric 	char **av;
885*60089Seric 	int *pstat;
88656822Seric {
887*60089Seric 	if (tTd(27, 20))
888*60089Seric 		printf("impl_map_lookup(%s)\n", name);
88956822Seric 
890*60089Seric #ifdef NEWDB
891*60089Seric 	if (bitset(MF_IMPL_HASH, map->map_flags))
892*60089Seric 		return db_map_lookup(map, name, av, pstat);
893*60089Seric #endif
894*60089Seric #ifdef NDBM
895*60089Seric 	if (bitset(MF_IMPL_NDBM, map->map_flags))
896*60089Seric 		return ndbm_map_lookup(map, name, av, pstat);
897*60089Seric #endif
898*60089Seric 	return stab_map_lookup(map, name, av, pstat);
899*60089Seric }
900*60089Seric 
901*60089Seric /*
902*60089Seric **  IMPL_ASTORE -- store in open databases
903*60089Seric */
904*60089Seric 
905*60089Seric void
906*60089Seric impl_map_store(map, lhs, rhs)
907*60089Seric 	MAP *map;
908*60089Seric 	char *lhs;
909*60089Seric 	char *rhs;
910*60089Seric {
911*60089Seric #ifdef NEWDB
912*60089Seric 	if (bitset(MF_IMPL_HASH, map->map_flags))
913*60089Seric 		db_map_store(map, lhs, rhs);
914*60089Seric #endif
915*60089Seric #ifdef NDBM
916*60089Seric 	if (bitset(MF_IMPL_NDBM, map->map_flags))
917*60089Seric 		ndbm_map_store(map, lhs, rhs);
918*60089Seric #endif
919*60089Seric 	stab_map_store(map, lhs, rhs);
920*60089Seric }
921*60089Seric 
922*60089Seric /*
923*60089Seric **  IMPL_MAP_OPEN -- implicit database open
924*60089Seric */
925*60089Seric 
926*60089Seric bool
927*60089Seric impl_map_open(map, mode)
928*60089Seric 	MAP *map;
929*60089Seric 	int mode;
930*60089Seric {
931*60089Seric 	struct stat stb;
932*60089Seric 
933*60089Seric 	if (tTd(27, 2))
934*60089Seric 		printf("impl_map_open(%s)\n", map->map_file);
935*60089Seric 
936*60089Seric 	if (stat(map->map_file, &stb) < 0)
93756822Seric 	{
938*60089Seric 		/* no alias file at all */
939*60089Seric 		return FALSE;
94056822Seric 	}
94156822Seric 
942*60089Seric #ifdef NEWDB
943*60089Seric 	if (hash_map_open(map, mode))
94456822Seric 	{
945*60089Seric 		map->map_flags |= MF_IMPL_HASH;
946*60089Seric 		return TRUE;
947*60089Seric 	}
948*60089Seric #endif
949*60089Seric #ifdef NDBM
950*60089Seric 	if (ndbm_map_open(map, mode))
951*60089Seric 	{
952*60089Seric 		map->map_flags |= MF_IMPL_NDBM;
953*60089Seric 		return TRUE;
954*60089Seric 	}
955*60089Seric #endif
95656822Seric 
957*60089Seric 	if (Verbose)
958*60089Seric 		message("WARNING: cannot open alias database %s", map->map_file);
959*60089Seric 
960*60089Seric 	if (stab_map_open(map, mode))
961*60089Seric 	{
962*60089Seric 		return TRUE;
96356822Seric 	}
964*60089Seric 
965*60089Seric 	return FALSE;
96656822Seric }
967*60089Seric 
968*60089Seric /*
969*60089Seric **  IMPL_AREBUILD -- rebuild alias database
970*60089Seric */
971*60089Seric 
972*60089Seric void
973*60089Seric impl_map_rebuild(map, fp, automatic, e)
974*60089Seric 	MAP *map;
975*60089Seric 	FILE *fp;
976*60089Seric 	int automatic;
977*60089Seric 	ENVELOPE *e;
978*60089Seric {
979*60089Seric #ifdef NEWDB
980*60089Seric 	DB *ndb;
981*60089Seric 	char buf[MAXNAME];
982*60089Seric #endif
983*60089Seric 
984*60089Seric 	if (tTd(27, 2))
985*60089Seric 		printf("impl_map_rebuild(%s)\n", map->map_file);
986*60089Seric 
987*60089Seric #ifdef NEWDB
988*60089Seric 	(void) strcpy(buf, map->map_file);
989*60089Seric 	(void) strcat(buf, ".db");
990*60089Seric 	ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL);
991*60089Seric 	if (ndb == NULL)
992*60089Seric 	{
993*60089Seric 		syserr("rebuildaliases: cannot create %s", buf);
994*60089Seric 	}
995*60089Seric 	else
996*60089Seric 	{
997*60089Seric 		map->map_db2 = ndb;
998*60089Seric 		map->map_flags |= MF_IMPL_HASH;
999*60089Seric #if defined(NDBM) && defined(YPCOMPAT)
1000*60089Seric 		if (access("/var/yp/Makefile", R_OK) != 0)
1001*60089Seric #endif
1002*60089Seric 			goto readem;
1003*60089Seric 	}
1004*60089Seric #endif
1005*60089Seric 
1006*60089Seric #ifdef NDBM
1007*60089Seric 	map->map_db1 = (void *) dbm_open(map->map_file, O_RDWR|O_CREAT|O_TRUNC, DBMMODE);
1008*60089Seric 	if (map->map_db1 == NULL)
1009*60089Seric 	{
1010*60089Seric 		syserr("rebuildaliases: cannot create %s.{pag,dir}",
1011*60089Seric 			map->map_file);
1012*60089Seric 	}
1013*60089Seric 	else
1014*60089Seric 	{
1015*60089Seric 		map->map_flags |= MF_IMPL_NDBM;
1016*60089Seric 	}
1017*60089Seric #endif
1018*60089Seric 
1019*60089Seric 	if (!bitset(MF_IMPL_HASH|MF_IMPL_NDBM, map->map_flags))
1020*60089Seric 		return;
1021*60089Seric 
1022*60089Seric   readem:
1023*60089Seric 	map->map_flags |= MF_WRITABLE|MF_VALID;
1024*60089Seric }
1025*60089Seric 
1026*60089Seric 
1027*60089Seric /*
1028*60089Seric **  IMPL_ACLOSE -- close any open database(s)
1029*60089Seric */
1030*60089Seric 
1031*60089Seric void
1032*60089Seric impl_map_close(map, e)
1033*60089Seric 	MAP *map;
1034*60089Seric 	ENVELOPE *e;
1035*60089Seric {
1036*60089Seric #ifdef NEWDB
1037*60089Seric 	if (bitset(MF_IMPL_HASH, map->map_flags))
1038*60089Seric 		db_map_close(map, e);
1039*60089Seric #endif
1040*60089Seric 
1041*60089Seric #ifdef NDBM
1042*60089Seric 	if (bitset(MF_IMPL_NDBM, map->map_flags))
1043*60089Seric 		ndbm_map_close(map, e);
1044*60089Seric #endif
1045*60089Seric }
1046*60089Seric /*
1047*60089Seric **  SETUPALIASES -- set up aliases classes
1048*60089Seric */
1049*60089Seric 
1050*60089Seric extern bool	host_map_init __P((MAP *, char *));
1051*60089Seric extern char	*host_map_lookup __P((MAP *, char *, char **, int *));
1052*60089Seric 
1053*60089Seric extern bool	dequote_init __P((MAP *, char *));
1054*60089Seric extern char	*dequote_map __P((MAP *, char *, char **, int *));
1055*60089Seric 
1056*60089Seric #if 0
1057*60089Seric extern bool	udb_map_parse __P((MAP *, char *));
1058*60089Seric extern char	*udb_map_lookup __P((MAP *, char *, char **, int *));
1059*60089Seric #endif
1060*60089Seric 
1061*60089Seric static MAPCLASS	MapClasses[] =
1062*60089Seric {
1063*60089Seric #ifdef NEWDB
1064*60089Seric 	{
1065*60089Seric 		"hash",		".db",	map_parseargs,
1066*60089Seric 		db_map_lookup,		db_map_store,
1067*60089Seric 		db_map_rebuild,		hash_map_open,	db_map_close,
1068*60089Seric 	},
1069*60089Seric 
1070*60089Seric 	{
1071*60089Seric 		"btree",	".db",	map_parseargs,
1072*60089Seric 		db_map_lookup,		db_map_store,
1073*60089Seric 		db_map_rebuild,		bt_map_open,	db_map_close,
1074*60089Seric 	},
1075*60089Seric #endif
1076*60089Seric 
1077*60089Seric #ifdef NDBM
1078*60089Seric 	{
1079*60089Seric 		"dbm",		".dir",	map_parseargs,
1080*60089Seric 		ndbm_map_lookup,	ndbm_map_store,
1081*60089Seric 		ndbm_map_rebuild,	ndbm_map_open,	ndbm_map_close,
1082*60089Seric 	},
1083*60089Seric #endif
1084*60089Seric 
1085*60089Seric #ifdef NIS
1086*60089Seric 	{
1087*60089Seric 		"nis",		NULL,	map_parseargs,
1088*60089Seric 		nis_map_lookup,		NULL,
1089*60089Seric 		NULL,			nis_map_open,	nis_map_close,
1090*60089Seric 	},
1091*60089Seric #endif
1092*60089Seric 
1093*60089Seric 	{
1094*60089Seric 		"stab",		NULL,	map_parseargs,
1095*60089Seric 		stab_map_lookup,	stab_map_store,
1096*60089Seric 		NULL,			stab_map_open,	stab_map_close,
1097*60089Seric 	},
1098*60089Seric 
1099*60089Seric 	{
1100*60089Seric 		"implicit",	NULL,	map_parseargs,
1101*60089Seric 		impl_map_lookup,	impl_map_store,
1102*60089Seric 		impl_map_rebuild,	impl_map_open,	impl_map_close,
1103*60089Seric 	},
1104*60089Seric 
1105*60089Seric 	/* host DNS lookup */
1106*60089Seric 	{
1107*60089Seric 		"host",		NULL,	host_map_init,
1108*60089Seric 		host_map_lookup,	NULL,
1109*60089Seric 		NULL,			NULL,		NULL,
1110*60089Seric 	},
1111*60089Seric 
1112*60089Seric 	/* dequote map */
1113*60089Seric 	{
1114*60089Seric 		"dequote",	NULL,	dequote_init,
1115*60089Seric 		dequote_map,		NULL,
1116*60089Seric 		NULL,			NULL,		NULL,
1117*60089Seric 	},
1118*60089Seric 
1119*60089Seric #if 0
1120*60089Seric # ifdef USERDB
1121*60089Seric 	/* user database */
1122*60089Seric 	{
1123*60089Seric 		"udb",		".db",	udb_map_parse,
1124*60089Seric 		udb_map_lookup,		NULL,
1125*60089Seric 		NULL,			NULL,		NULL,
1126*60089Seric 	},
1127*60089Seric # endif
1128*60089Seric #endif
1129*60089Seric 
1130*60089Seric 	{
1131*60089Seric 		NULL
1132*60089Seric 	}
1133*60089Seric };
1134*60089Seric 
1135*60089Seric setupmaps()
1136*60089Seric {
1137*60089Seric 	register MAPCLASS *mc;
1138*60089Seric 	register STAB *s;
1139*60089Seric 
1140*60089Seric 	for (mc = MapClasses; mc->map_cname != NULL; mc++)
1141*60089Seric 	{
1142*60089Seric 		s = stab(mc->map_cname, ST_MAPCLASS, ST_ENTER);
1143*60089Seric 		s->s_mapclass = mc;
1144*60089Seric 	}
1145*60089Seric }
1146