xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 57208)
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*57208Seric static char sccsid[] = "@(#)map.c	5.6 (Berkeley) 12/18/92";
1156822Seric #endif /* not lint */
1256822Seric 
1356822Seric #include "sendmail.h"
1456822Seric #include <sys/file.h>
1556822Seric 
1656822Seric #ifdef DBM_MAP
1756822Seric #include <ndbm.h>
1856822Seric #endif
1956822Seric #if defined(HASH_MAP) || defined(BTREE_MAP)
2056822Seric #include <db.h>
2156822Seric #endif
22*57208Seric #ifdef NIS_MAP
23*57208Seric #include <rpcsvc/ypclnt.h>
24*57208Seric #endif
2556822Seric 
2656822Seric 
2756822Seric #ifdef DBM_MAP
2856822Seric 
2956822Seric /*
3056822Seric **  DBM_MAP_INIT -- DBM-style map initialization
3156822Seric **
3256822Seric **	Parameters:
3356822Seric **		map -- the pointer to the actual map
3456822Seric **		mapname -- the name of the map (for error messages)
3556822Seric **		args -- a pointer to the config file line arguments
3656822Seric **
3756822Seric **	Returns:
3856822Seric **		TRUE -- if it could successfully open the map.
3956822Seric **		FALSE -- otherwise.
4056822Seric **
4156822Seric **	Side Effects:
4256822Seric **		Gives an error if it can't open the map.
4356822Seric */
4456822Seric 
4556822Seric bool
4656822Seric dbm_map_init(map, mapname, args)
4756822Seric 	MAP *map;
4856822Seric 	char *mapname;
4956822Seric 	char *args;
5056822Seric {
5156822Seric 	DBM *dbm;
5256822Seric 
53*57208Seric 	map_parseargs(map, &args);
5456822Seric 	if (map->map_file == NULL)
55*57208Seric 	{
56*57208Seric 		syserr("No file name for DBM map %s", mapname);
5756822Seric 		return FALSE;
58*57208Seric 	}
5956822Seric 	dbm = dbm_open(map->map_file, O_RDONLY, 0644);
6056822Seric 	if (dbm == NULL)
6156822Seric 	{
6256836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
6356836Seric 			syserr("Cannot open DBM database %s", map->map_file);
6456822Seric 		return FALSE;
6556822Seric 	}
6656822Seric 	map->map_db = (void *) dbm;
6756822Seric 	return TRUE;
6856822Seric }
6956822Seric /*
7056822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
7156822Seric **
7256822Seric **	Parameters:
7356822Seric **		map -- the map to look up in.
7456822Seric **		buf -- a pointer to to the buffer containing the key.
7556822Seric **			This is a null terminated string.
7656822Seric **		bufsiz -- the size of buf -- note that this is in general
7756822Seric **			larger that strlen(buf), and buf can be changed
7856822Seric **			in place if desired.
7956822Seric **		av -- arguments from the config file (can be interpolated
8056822Seric **			into the final result).
8156822Seric **
8256822Seric **	Returns:
8356822Seric **		A pointer to the rewritten result.
8456822Seric **		NULL if not found in the map.
8556822Seric */
8656822Seric 
8756822Seric char *
8856822Seric dbm_map_lookup(map, buf, bufsiz, av)
8956822Seric 	MAP *map;
9056822Seric 	char buf[];
9156822Seric 	int bufsiz;
9256822Seric 	char **av;
9356822Seric {
9456822Seric 	datum key, val;
9556822Seric 
9656822Seric 	key.dptr = buf;
9756822Seric 	key.dsize = strlen(buf);
9857033Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
9957014Seric 	{
10057014Seric 		register char *p;
10157014Seric 
10257014Seric 		for (p = buf; *p != '\0'; p++)
10357014Seric 			if (isupper(*p))
10457014Seric 				*p = tolower(*p);
10557014Seric 	}
10656822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
10756822Seric 		key.dsize++;
10856822Seric 	val = dbm_fetch(map->map_db, key);
10956822Seric 	if (val.dptr == NULL)
11056822Seric 		return NULL;
111*57208Seric 	if (!bitset(MF_MATCHONLY, map->map_flags))
112*57208Seric 		map_rewrite(val.dptr, val.dsize, buf, bufsiz, av);
11356822Seric 	return buf;
11456822Seric }
11556822Seric 
11656822Seric #endif /* DBM_MAP */
11756822Seric 
11856822Seric #ifdef BTREE_MAP
11956822Seric 
12056822Seric /*
12156822Seric **  BTREE_MAP_INIT -- BTREE-style map initialization
12256822Seric **
12356822Seric **	Parameters:
12456822Seric **		map -- the pointer to the actual map
12556822Seric **		mapname -- the name of the map (for error messages)
12656822Seric **		args -- a pointer to the config file line arguments
12756822Seric **
12856822Seric **	Returns:
12956822Seric **		TRUE -- if it could successfully open the map.
13056822Seric **		FALSE -- otherwise.
13156822Seric **
13256822Seric **	Side Effects:
13356822Seric **		Gives an error if it can't open the map.
13456822Seric */
13556822Seric 
13656822Seric bool
13756822Seric bt_map_init(map, mapname, args)
13856822Seric 	MAP *map;
13956822Seric 	char *mapname;
14056822Seric 	char *args;
14156822Seric {
14256822Seric 	DB *db;
14356822Seric 
144*57208Seric 	map_parseargs(map, &args);
14556822Seric 	if (map->map_file == NULL)
146*57208Seric 	{
147*57208Seric 		syserr("No file name for BTREE map %s", mapname);
14856822Seric 		return FALSE;
149*57208Seric 	}
15056822Seric 	db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL);
15156822Seric 	if (db == NULL)
15256822Seric 	{
15356836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
15456836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
15556822Seric 		return FALSE;
15656822Seric 	}
15756822Seric 	map->map_db = (void *) db;
15856822Seric 	return TRUE;
15956822Seric }
16056822Seric 
16156822Seric #endif /* BTREE_MAP */
16256822Seric 
16356822Seric #ifdef HASH_MAP
16456822Seric 
16556822Seric /*
16656822Seric **  HASH_MAP_INIT -- HASH-style map initialization
16756822Seric **
16856822Seric **	Parameters:
16956822Seric **		map -- the pointer to the actual map
17056822Seric **		mapname -- the name of the map (for error messages)
17156822Seric **		args -- a pointer to the config file line arguments
17256822Seric **
17356822Seric **	Returns:
17456822Seric **		TRUE -- if it could successfully open the map.
17556822Seric **		FALSE -- otherwise.
17656822Seric **
17756822Seric **	Side Effects:
17856822Seric **		Gives an error if it can't open the map.
17956822Seric */
18056822Seric 
18156822Seric bool
18256822Seric hash_map_init(map, mapname, args)
18356822Seric 	MAP *map;
18456822Seric 	char *mapname;
18556822Seric 	char *args;
18656822Seric {
18756822Seric 	DB *db;
18856822Seric 
189*57208Seric 	map_parseargs(map, &args);
19056822Seric 	if (map->map_file == NULL)
191*57208Seric 	{
192*57208Seric 		syserr("No file name for HASH map %s", mapname);
19356822Seric 		return FALSE;
194*57208Seric 	}
19556822Seric 	db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL);
19656822Seric 	if (db == NULL)
19756822Seric 	{
19856836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
19956836Seric 			syserr("Cannot open HASH database %s", map->map_file);
20056822Seric 		return FALSE;
20156822Seric 	}
20256822Seric 	map->map_db = (void *) db;
20356822Seric 	return TRUE;
20456822Seric }
20556822Seric 
20656822Seric #endif /* HASH_MAP */
20756822Seric 
20856822Seric #if defined(BTREE_MAP) || defined(HASH_MAP)
20956822Seric 
21056822Seric /*
21156822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
21256822Seric **
21356822Seric **	Parameters:
21456822Seric **		map -- the map to look up in.
21556822Seric **		buf -- a pointer to to the buffer containing the key.
21656822Seric **			This is a null terminated string.
21756822Seric **		bufsiz -- the size of buf -- note that this is in general
21856822Seric **			larger that strlen(buf), and buf can be changed
21956822Seric **			in place if desired.
22056822Seric **		av -- arguments from the config file (can be interpolated
22156822Seric **			into the final result).
22256822Seric **
22356822Seric **	Returns:
22456822Seric **		A pointer to the rewritten result.
22556822Seric **		NULL if not found in the map.
22656822Seric */
22756822Seric 
22856822Seric char *
22956822Seric db_map_lookup(map, buf, bufsiz, av)
23056822Seric 	MAP *map;
23156822Seric 	char buf[];
23256822Seric 	int bufsiz;
23356822Seric 	char **av;
23456822Seric {
23556822Seric 	DBT key, val;
23656822Seric 
23756822Seric 	key.data = buf;
23856822Seric 	key.size = strlen(buf);
23957033Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
24056847Seric 	{
24156847Seric 		register char *p;
24256847Seric 
24356847Seric 		for (p = buf; *p != '\0'; p++)
24456847Seric 			if (isupper(*p))
24556847Seric 				*p = tolower(*p);
24656847Seric 	}
24756822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
24856822Seric 		key.size++;
24956836Seric 	if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0)
25056822Seric 		return NULL;
251*57208Seric 	if (!bitset(MF_MATCHONLY, map->map_flags))
252*57208Seric 		map_rewrite(val.data, val.size, buf, bufsiz, av);
25356822Seric 	return buf;
25456822Seric }
25556822Seric 
25656822Seric #endif /* BTREE_MAP || HASH_MAP */
25756822Seric /*
25856822Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
25956822Seric **
26056822Seric **	Parameters:
26156822Seric **		map -- the map being initialized.
26256822Seric **		pp -- an indirect pointer to the config line.  It will
26356822Seric **			be replaced with a pointer to the next field
26456822Seric **			on the line.
26556822Seric **
26656822Seric **	Returns:
26756822Seric **		none
26856822Seric **
26956822Seric **	Side Effects:
27056822Seric **		null terminates the filename; stores it in map
27156822Seric */
27256822Seric 
273*57208Seric map_parseargs(map, pp)
27456822Seric 	MAP *map;
27556822Seric 	char **pp;
27656822Seric {
27756822Seric 	register char *p = *pp;
27856822Seric 
27956822Seric 	for (;;)
28056822Seric 	{
28156822Seric 		while (isspace(*p))
28256822Seric 			p++;
28356822Seric 		if (*p != '-')
28456822Seric 			break;
28556822Seric 		switch (*++p)
28656822Seric 		{
28756822Seric 		  case 'N':
28856822Seric 			map->map_flags |= MF_INCLNULL;
28956822Seric 			break;
29056836Seric 
29156836Seric 		  case 'o':
29256836Seric 			map->map_flags |= MF_OPTIONAL;
29356836Seric 			break;
29456836Seric 
29556847Seric 		  case 'f':
29657033Seric 			map->map_flags |= MF_NOFOLDCASE;
29756847Seric 			break;
29856847Seric 
299*57208Seric 		  case 'm':
300*57208Seric 			map->map_flags |= MF_MATCHONLY;
301*57208Seric 			break;
302*57208Seric 
30356836Seric 		  case 'a':
30456836Seric 			map->map_app = ++p;
30556836Seric 			break;
306*57208Seric 
307*57208Seric 		  case 'd':
308*57208Seric 			map->map_domain = ++p;
309*57208Seric 			break;
31056822Seric 		}
31156822Seric 		while (*p != '\0' && !isspace(*p))
31256822Seric 			p++;
31356836Seric 		if (*p != '\0')
31456836Seric 			*p++ = 0;
31556822Seric 	}
31656836Seric 	if (map->map_app != NULL)
31756836Seric 		map->map_app = newstr(map->map_app);
318*57208Seric 	if (map->map_domain != NULL)
319*57208Seric 		map->map_domain = newstr(map->map_domain);
32056822Seric 
32156822Seric 	if (*p == '\0')
32256822Seric 		return NULL;
32356822Seric 	map->map_file = p;
32456822Seric 	while (*p != '\0' && !isspace(*p))
32556822Seric 		p++;
32656822Seric 	if (*p != '\0')
32756822Seric 		*p++ = '\0';
32856836Seric 	map->map_file = newstr(map->map_file);
32956822Seric 	*pp = p;
33056822Seric }
331*57208Seric 
332*57208Seric # ifdef NIS_MAP
333*57208Seric 
334*57208Seric /*
335*57208Seric **  NIS_MAP_INIT -- initialize DBM map
336*57208Seric **
337*57208Seric **	Parameters:
338*57208Seric **		map -- the pointer to the actual map.
339*57208Seric **		mapname -- the name of the map (for error messages).
340*57208Seric **		args -- a pointer to the config file line arguments.
341*57208Seric **
342*57208Seric **	Returns:
343*57208Seric **		TRUE -- if it could successfully open the map.
344*57208Seric **		FALSE -- otherwise.
345*57208Seric **
346*57208Seric **	Side Effects:
347*57208Seric **		Prints an error if it can't open the map.
348*57208Seric */
349*57208Seric 
350*57208Seric bool
351*57208Seric nis_map_init(map, mapname, args)
352*57208Seric 	MAP *map;
353*57208Seric 	char *mapname;
354*57208Seric 	char *args;
355*57208Seric {
356*57208Seric 	/* parse arguments */
357*57208Seric 	map_parseargs(map, &args);
358*57208Seric 	if (map->map_file == NULL)
359*57208Seric 	{
360*57208Seric 		syserr("No NIS map name for map %s", mapname);
361*57208Seric 		return FALSE;
362*57208Seric 	}
363*57208Seric 	if (map->map_domain == NULL)
364*57208Seric 		yp_get_default_domain(&map->map_domain);
365*57208Seric 	return TRUE;
366*57208Seric }
36756822Seric /*
368*57208Seric **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
369*57208Seric **
370*57208Seric **	Parameters:
371*57208Seric **		map -- the map to look up in.
372*57208Seric **		buf -- a pointer to to the buffer containing the key.
373*57208Seric **			This is a null terminated string.
374*57208Seric **		bufsiz -- the size of buf -- note that this is in general
375*57208Seric **			larger that strlen(buf), and buf can be changed
376*57208Seric **			in place if desired.
377*57208Seric **		av -- arguments from the config file (can be interpolated
378*57208Seric **			into the final result).
379*57208Seric **
380*57208Seric **	Returns:
381*57208Seric **		A pointer to the rewritten result.
382*57208Seric **		NULL if not found in the map.
383*57208Seric */
384*57208Seric 
385*57208Seric char *
386*57208Seric nis_map_lookup(map, buf, bufsiz, av)
387*57208Seric 	MAP *map;
388*57208Seric 	char buf[];
389*57208Seric 	int bufsiz;
390*57208Seric 	char **av;
391*57208Seric {
392*57208Seric 	char *vp;
393*57208Seric 	int *vsize;
394*57208Seric 
395*57208Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
396*57208Seric 	{
397*57208Seric 		register char *p;
398*57208Seric 
399*57208Seric 		for (p = buf; *p != '\0'; p++)
400*57208Seric 			if (isupper(*p))
401*57208Seric 				*p = tolower(*p);
402*57208Seric 	}
403*57208Seric 	if (yp_match(map->map_domain, map->map_file, buf, bufsiz, &vp, &vsize) != 0)
404*57208Seric 		return NULL;
405*57208Seric 	if (!bitset(MF_MATCHONLY, map->map_flags))
406*57208Seric 		map_rewrite(vp, vsize, buf, bufsiz, av);
407*57208Seric 	return buf;
408*57208Seric }
409*57208Seric 
410*57208Seric #endif /* NIS_MAP */
411*57208Seric /*
41256822Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
41356822Seric **
41456822Seric **	Parameters:
41556822Seric **		s -- the string to rewrite, NOT necessarily null terminated.
41656822Seric **		slen -- the length of s.
41756822Seric **		buf -- the place to write it.
41856822Seric **		buflen -- the length of buf.
41956822Seric **		av -- arguments to interpolate into buf.
42056822Seric **
42156822Seric **	Returns:
42256822Seric **		none.
42356822Seric **
42456822Seric **	Side Effects:
42556822Seric **		none.
42656822Seric */
42756822Seric 
42856822Seric map_rewrite(s, slen, buf, buflen, av)
42956822Seric 	register char *s;
43056822Seric 	int slen;
43156822Seric 	char buf[];
43256822Seric 	int buflen;
43356822Seric 	char **av;
43456822Seric {
43556822Seric 	register char *bp;
43656822Seric 	char *buflim;
43756822Seric 	register char c;
43856822Seric 	char **avp;
43956822Seric 	register char *ap;
44056822Seric 
44156822Seric 	if (tTd(23, 1))
44256822Seric 	{
44356822Seric 		printf("map_rewrite(%.*s), av =\n", slen, s);
44456822Seric 		for (avp = av; *avp != NULL; avp++)
44556822Seric 			printf("\t%s\n", *avp);
44656822Seric 	}
44756822Seric 
44856822Seric 	bp = buf;
44956822Seric 	buflim = &buf[buflen - 2];
45056822Seric 	while (--slen >= 0 && (c = *s++) != '\0')
45156822Seric 	{
45256822Seric 		if (c != '%')
45356822Seric 		{
45456822Seric   pushc:
45556822Seric 			if (bp < buflim)
45656822Seric 				*bp++ = c;
45756822Seric 			continue;
45856822Seric 		}
45956822Seric 		if (--slen < 0 || (c = *s++) == '\0')
46056822Seric 			c = '%';
46156822Seric 		if (c == '%')
46256822Seric 			goto pushc;
46356822Seric 		if (!isdigit(c))
46456822Seric 		{
46556822Seric 			*bp++ = '%';
46656822Seric 			goto pushc;
46756822Seric 		}
46856822Seric 		c -= '0';
46956822Seric 		for (avp = av; --c >= 0 && *avp != NULL; avp++)
47056822Seric 			continue;
47156822Seric 		if (*avp == NULL)
47256822Seric 			continue;
47356822Seric 
47456822Seric 		/* transliterate argument into output string */
47556822Seric 		for (ap = *avp; (c = *ap++) != '\0'; )
47656822Seric 		{
47756822Seric 			if (bp < buflim)
47856822Seric 				*bp++ = c;
47956822Seric 		}
48056822Seric 	}
48156822Seric 	*bp++ = '\0';
48256822Seric 	if (tTd(23, 1))
48356822Seric 		printf("map_rewrite => %s\n", buf);
48456822Seric }
485