xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 57033)
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*57033Seric static char sccsid[] = "@(#)map.c	5.5 (Berkeley) 12/09/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
2256822Seric 
2356822Seric 
2456822Seric #ifdef DBM_MAP
2556822Seric 
2656822Seric /*
2756822Seric **  DBM_MAP_INIT -- DBM-style map initialization
2856822Seric **
2956822Seric **	Parameters:
3056822Seric **		map -- the pointer to the actual map
3156822Seric **		mapname -- the name of the map (for error messages)
3256822Seric **		args -- a pointer to the config file line arguments
3356822Seric **
3456822Seric **	Returns:
3556822Seric **		TRUE -- if it could successfully open the map.
3656822Seric **		FALSE -- otherwise.
3756822Seric **
3856822Seric **	Side Effects:
3956822Seric **		Gives an error if it can't open the map.
4056822Seric */
4156822Seric 
4256822Seric bool
4356822Seric dbm_map_init(map, mapname, args)
4456822Seric 	MAP *map;
4556822Seric 	char *mapname;
4656822Seric 	char *args;
4756822Seric {
4856822Seric 	DBM *dbm;
4956822Seric 
5056822Seric 	map_parseargs(map, &args, mapname);
5156822Seric 	if (map->map_file == NULL)
5256822Seric 		return FALSE;
5356822Seric 	dbm = dbm_open(map->map_file, O_RDONLY, 0644);
5456822Seric 	if (dbm == NULL)
5556822Seric 	{
5656836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
5756836Seric 			syserr("Cannot open DBM database %s", map->map_file);
5856822Seric 		return FALSE;
5956822Seric 	}
6056822Seric 	map->map_db = (void *) dbm;
6156822Seric 	return TRUE;
6256822Seric }
6356822Seric /*
6456822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
6556822Seric **
6656822Seric **	Parameters:
6756822Seric **		map -- the map to look up in.
6856822Seric **		buf -- a pointer to to the buffer containing the key.
6956822Seric **			This is a null terminated string.
7056822Seric **		bufsiz -- the size of buf -- note that this is in general
7156822Seric **			larger that strlen(buf), and buf can be changed
7256822Seric **			in place if desired.
7356822Seric **		av -- arguments from the config file (can be interpolated
7456822Seric **			into the final result).
7556822Seric **
7656822Seric **	Returns:
7756822Seric **		A pointer to the rewritten result.
7856822Seric **		NULL if not found in the map.
7956822Seric */
8056822Seric 
8156822Seric char *
8256822Seric dbm_map_lookup(map, buf, bufsiz, av)
8356822Seric 	MAP *map;
8456822Seric 	char buf[];
8556822Seric 	int bufsiz;
8656822Seric 	char **av;
8756822Seric {
8856822Seric 	datum key, val;
8956822Seric 
9056822Seric 	key.dptr = buf;
9156822Seric 	key.dsize = strlen(buf);
92*57033Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
9357014Seric 	{
9457014Seric 		register char *p;
9557014Seric 
9657014Seric 		for (p = buf; *p != '\0'; p++)
9757014Seric 			if (isupper(*p))
9857014Seric 				*p = tolower(*p);
9957014Seric 	}
10056822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
10156822Seric 		key.dsize++;
10256822Seric 	val = dbm_fetch(map->map_db, key);
10356822Seric 	if (val.dptr == NULL)
10456822Seric 		return NULL;
10556822Seric 	map_rewrite(val.dptr, val.dsize, buf, bufsiz, av);
10656822Seric 	return buf;
10756822Seric }
10856822Seric 
10956822Seric #endif /* DBM_MAP */
11056822Seric 
11156822Seric #ifdef BTREE_MAP
11256822Seric 
11356822Seric /*
11456822Seric **  BTREE_MAP_INIT -- BTREE-style map initialization
11556822Seric **
11656822Seric **	Parameters:
11756822Seric **		map -- the pointer to the actual map
11856822Seric **		mapname -- the name of the map (for error messages)
11956822Seric **		args -- a pointer to the config file line arguments
12056822Seric **
12156822Seric **	Returns:
12256822Seric **		TRUE -- if it could successfully open the map.
12356822Seric **		FALSE -- otherwise.
12456822Seric **
12556822Seric **	Side Effects:
12656822Seric **		Gives an error if it can't open the map.
12756822Seric */
12856822Seric 
12956822Seric bool
13056822Seric bt_map_init(map, mapname, args)
13156822Seric 	MAP *map;
13256822Seric 	char *mapname;
13356822Seric 	char *args;
13456822Seric {
13556822Seric 	DB *db;
13656822Seric 
13756822Seric 	map_parseargs(map, &args, mapname);
13856822Seric 	if (map->map_file == NULL)
13956822Seric 		return FALSE;
14056822Seric 	db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL);
14156822Seric 	if (db == NULL)
14256822Seric 	{
14356836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
14456836Seric 			syserr("Cannot open BTREE database %s", map->map_file);
14556822Seric 		return FALSE;
14656822Seric 	}
14756822Seric 	map->map_db = (void *) db;
14856822Seric 	return TRUE;
14956822Seric }
15056822Seric 
15156822Seric #endif /* BTREE_MAP */
15256822Seric 
15356822Seric #ifdef HASH_MAP
15456822Seric 
15556822Seric /*
15656822Seric **  HASH_MAP_INIT -- HASH-style map initialization
15756822Seric **
15856822Seric **	Parameters:
15956822Seric **		map -- the pointer to the actual map
16056822Seric **		mapname -- the name of the map (for error messages)
16156822Seric **		args -- a pointer to the config file line arguments
16256822Seric **
16356822Seric **	Returns:
16456822Seric **		TRUE -- if it could successfully open the map.
16556822Seric **		FALSE -- otherwise.
16656822Seric **
16756822Seric **	Side Effects:
16856822Seric **		Gives an error if it can't open the map.
16956822Seric */
17056822Seric 
17156822Seric bool
17256822Seric hash_map_init(map, mapname, args)
17356822Seric 	MAP *map;
17456822Seric 	char *mapname;
17556822Seric 	char *args;
17656822Seric {
17756822Seric 	DB *db;
17856822Seric 
17956822Seric 	map_parseargs(map, &args, mapname);
18056822Seric 	if (map->map_file == NULL)
18156822Seric 		return FALSE;
18256822Seric 	db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL);
18356822Seric 	if (db == NULL)
18456822Seric 	{
18556836Seric 		if (!bitset(MF_OPTIONAL, map->map_flags))
18656836Seric 			syserr("Cannot open HASH database %s", map->map_file);
18756822Seric 		return FALSE;
18856822Seric 	}
18956822Seric 	map->map_db = (void *) db;
19056822Seric 	return TRUE;
19156822Seric }
19256822Seric 
19356822Seric #endif /* HASH_MAP */
19456822Seric 
19556822Seric #if defined(BTREE_MAP) || defined(HASH_MAP)
19656822Seric 
19756822Seric /*
19856822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
19956822Seric **
20056822Seric **	Parameters:
20156822Seric **		map -- the map to look up in.
20256822Seric **		buf -- a pointer to to the buffer containing the key.
20356822Seric **			This is a null terminated string.
20456822Seric **		bufsiz -- the size of buf -- note that this is in general
20556822Seric **			larger that strlen(buf), and buf can be changed
20656822Seric **			in place if desired.
20756822Seric **		av -- arguments from the config file (can be interpolated
20856822Seric **			into the final result).
20956822Seric **
21056822Seric **	Returns:
21156822Seric **		A pointer to the rewritten result.
21256822Seric **		NULL if not found in the map.
21356822Seric */
21456822Seric 
21556822Seric char *
21656822Seric db_map_lookup(map, buf, bufsiz, av)
21756822Seric 	MAP *map;
21856822Seric 	char buf[];
21956822Seric 	int bufsiz;
22056822Seric 	char **av;
22156822Seric {
22256822Seric 	DBT key, val;
22356822Seric 
22456822Seric 	key.data = buf;
22556822Seric 	key.size = strlen(buf);
226*57033Seric 	if (!bitset(MF_NOFOLDCASE, map->map_flags))
22756847Seric 	{
22856847Seric 		register char *p;
22956847Seric 
23056847Seric 		for (p = buf; *p != '\0'; p++)
23156847Seric 			if (isupper(*p))
23256847Seric 				*p = tolower(*p);
23356847Seric 	}
23456822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
23556822Seric 		key.size++;
23656836Seric 	if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0)
23756822Seric 		return NULL;
23856822Seric 	map_rewrite(val.data, val.size, buf, bufsiz, av);
23956822Seric 	return buf;
24056822Seric }
24156822Seric 
24256822Seric #endif /* BTREE_MAP || HASH_MAP */
24356822Seric /*
24456822Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
24556822Seric **
24656822Seric **	Parameters:
24756822Seric **		map -- the map being initialized.
24856822Seric **		pp -- an indirect pointer to the config line.  It will
24956822Seric **			be replaced with a pointer to the next field
25056822Seric **			on the line.
25156822Seric **		mapname -- the name of the map (for errors).
25256822Seric **
25356822Seric **	Returns:
25456822Seric **		none
25556822Seric **
25656822Seric **	Side Effects:
25756822Seric **		null terminates the filename; stores it in map
25856822Seric */
25956822Seric 
26056822Seric map_parseargs(map, pp, mapname)
26156822Seric 	MAP *map;
26256822Seric 	char **pp;
26356822Seric 	char *mapname;
26456822Seric {
26556822Seric 	register char *p = *pp;
26656822Seric 
26756822Seric 	for (;;)
26856822Seric 	{
26956822Seric 		while (isspace(*p))
27056822Seric 			p++;
27156822Seric 		if (*p != '-')
27256822Seric 			break;
27356822Seric 		switch (*++p)
27456822Seric 		{
27556822Seric 		  case 'N':
27656822Seric 			map->map_flags |= MF_INCLNULL;
27756822Seric 			break;
27856836Seric 
27956836Seric 		  case 'o':
28056836Seric 			map->map_flags |= MF_OPTIONAL;
28156836Seric 			break;
28256836Seric 
28356847Seric 		  case 'f':
284*57033Seric 			map->map_flags |= MF_NOFOLDCASE;
28556847Seric 			break;
28656847Seric 
28756836Seric 		  case 'a':
28856836Seric 			map->map_app = ++p;
28956836Seric 			break;
29056822Seric 		}
29156822Seric 		while (*p != '\0' && !isspace(*p))
29256822Seric 			p++;
29356836Seric 		if (*p != '\0')
29456836Seric 			*p++ = 0;
29556822Seric 	}
29656836Seric 	if (map->map_app != NULL)
29756836Seric 		map->map_app = newstr(map->map_app);
29856822Seric 
29956822Seric 	if (*p == '\0')
30056822Seric 	{
30156822Seric 		syserr("No file name for map %s", mapname);
30256822Seric 		return NULL;
30356822Seric 	}
30456822Seric 	map->map_file = p;
30556822Seric 	while (*p != '\0' && !isspace(*p))
30656822Seric 		p++;
30756822Seric 	if (*p != '\0')
30856822Seric 		*p++ = '\0';
30956836Seric 	map->map_file = newstr(map->map_file);
31056822Seric 	*pp = p;
31156822Seric }
31256822Seric /*
31356822Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
31456822Seric **
31556822Seric **	Parameters:
31656822Seric **		s -- the string to rewrite, NOT necessarily null terminated.
31756822Seric **		slen -- the length of s.
31856822Seric **		buf -- the place to write it.
31956822Seric **		buflen -- the length of buf.
32056822Seric **		av -- arguments to interpolate into buf.
32156822Seric **
32256822Seric **	Returns:
32356822Seric **		none.
32456822Seric **
32556822Seric **	Side Effects:
32656822Seric **		none.
32756822Seric */
32856822Seric 
32956822Seric map_rewrite(s, slen, buf, buflen, av)
33056822Seric 	register char *s;
33156822Seric 	int slen;
33256822Seric 	char buf[];
33356822Seric 	int buflen;
33456822Seric 	char **av;
33556822Seric {
33656822Seric 	register char *bp;
33756822Seric 	char *buflim;
33856822Seric 	register char c;
33956822Seric 	char **avp;
34056822Seric 	register char *ap;
34156822Seric 
34256822Seric 	if (tTd(23, 1))
34356822Seric 	{
34456822Seric 		printf("map_rewrite(%.*s), av =\n", slen, s);
34556822Seric 		for (avp = av; *avp != NULL; avp++)
34656822Seric 			printf("\t%s\n", *avp);
34756822Seric 	}
34856822Seric 
34956822Seric 	bp = buf;
35056822Seric 	buflim = &buf[buflen - 2];
35156822Seric 	while (--slen >= 0 && (c = *s++) != '\0')
35256822Seric 	{
35356822Seric 		if (c != '%')
35456822Seric 		{
35556822Seric   pushc:
35656822Seric 			if (bp < buflim)
35756822Seric 				*bp++ = c;
35856822Seric 			continue;
35956822Seric 		}
36056822Seric 		if (--slen < 0 || (c = *s++) == '\0')
36156822Seric 			c = '%';
36256822Seric 		if (c == '%')
36356822Seric 			goto pushc;
36456822Seric 		if (!isdigit(c))
36556822Seric 		{
36656822Seric 			*bp++ = '%';
36756822Seric 			goto pushc;
36856822Seric 		}
36956822Seric 		c -= '0';
37056822Seric 		for (avp = av; --c >= 0 && *avp != NULL; avp++)
37156822Seric 			continue;
37256822Seric 		if (*avp == NULL)
37356822Seric 			continue;
37456822Seric 
37556822Seric 		/* transliterate argument into output string */
37656822Seric 		for (ap = *avp; (c = *ap++) != '\0'; )
37756822Seric 		{
37856822Seric 			if (bp < buflim)
37956822Seric 				*bp++ = c;
38056822Seric 		}
38156822Seric 	}
38256822Seric 	*bp++ = '\0';
38356822Seric 	if (tTd(23, 1))
38456822Seric 		printf("map_rewrite => %s\n", buf);
38556822Seric }
386