xref: /csrg-svn/usr.sbin/sendmail/src/map.c (revision 56822)
1*56822Seric /*
2*56822Seric  * Copyright (c) 1992 Eric P. Allman.
3*56822Seric  * Copyright (c) 1992 Regents of the University of California.
4*56822Seric  * All rights reserved.
5*56822Seric  *
6*56822Seric  * %sccs.include.redist.c%
7*56822Seric  */
8*56822Seric 
9*56822Seric #ifndef lint
10*56822Seric static char sccsid[] = "@(#)map.c	5.1 (Berkeley) 11/15/92";
11*56822Seric #endif /* not lint */
12*56822Seric 
13*56822Seric #include "sendmail.h"
14*56822Seric #include <sys/file.h>
15*56822Seric 
16*56822Seric #ifdef DBM_MAP
17*56822Seric #include <ndbm.h>
18*56822Seric #endif
19*56822Seric #if defined(HASH_MAP) || defined(BTREE_MAP)
20*56822Seric #include <db.h>
21*56822Seric #endif
22*56822Seric 
23*56822Seric 
24*56822Seric #ifdef DBM_MAP
25*56822Seric 
26*56822Seric /*
27*56822Seric **  DBM_MAP_INIT -- DBM-style map initialization
28*56822Seric **
29*56822Seric **	Parameters:
30*56822Seric **		map -- the pointer to the actual map
31*56822Seric **		mapname -- the name of the map (for error messages)
32*56822Seric **		args -- a pointer to the config file line arguments
33*56822Seric **
34*56822Seric **	Returns:
35*56822Seric **		TRUE -- if it could successfully open the map.
36*56822Seric **		FALSE -- otherwise.
37*56822Seric **
38*56822Seric **	Side Effects:
39*56822Seric **		Gives an error if it can't open the map.
40*56822Seric */
41*56822Seric 
42*56822Seric bool
43*56822Seric dbm_map_init(map, mapname, args)
44*56822Seric 	MAP *map;
45*56822Seric 	char *mapname;
46*56822Seric 	char *args;
47*56822Seric {
48*56822Seric 	DBM *dbm;
49*56822Seric 
50*56822Seric 	map_parseargs(map, &args, mapname);
51*56822Seric 	if (map->map_file == NULL)
52*56822Seric 		return FALSE;
53*56822Seric 	dbm = dbm_open(map->map_file, O_RDONLY, 0644);
54*56822Seric 	if (dbm == NULL)
55*56822Seric 	{
56*56822Seric 		syserr("Cannot open DBM database %s", map->map_file);
57*56822Seric 		return FALSE;
58*56822Seric 	}
59*56822Seric 	map->map_db = (void *) dbm;
60*56822Seric 	return TRUE;
61*56822Seric }
62*56822Seric /*
63*56822Seric **  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
64*56822Seric **
65*56822Seric **	Parameters:
66*56822Seric **		map -- the map to look up in.
67*56822Seric **		buf -- a pointer to to the buffer containing the key.
68*56822Seric **			This is a null terminated string.
69*56822Seric **		bufsiz -- the size of buf -- note that this is in general
70*56822Seric **			larger that strlen(buf), and buf can be changed
71*56822Seric **			in place if desired.
72*56822Seric **		av -- arguments from the config file (can be interpolated
73*56822Seric **			into the final result).
74*56822Seric **
75*56822Seric **	Returns:
76*56822Seric **		A pointer to the rewritten result.
77*56822Seric **		NULL if not found in the map.
78*56822Seric */
79*56822Seric 
80*56822Seric char *
81*56822Seric dbm_map_lookup(map, buf, bufsiz, av)
82*56822Seric 	MAP *map;
83*56822Seric 	char buf[];
84*56822Seric 	int bufsiz;
85*56822Seric 	char **av;
86*56822Seric {
87*56822Seric 	datum key, val;
88*56822Seric 
89*56822Seric 	key.dptr = buf;
90*56822Seric 	key.dsize = strlen(buf);
91*56822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
92*56822Seric 		key.dsize++;
93*56822Seric 	val = dbm_fetch(map->map_db, key);
94*56822Seric 	if (val.dptr == NULL)
95*56822Seric 		return NULL;
96*56822Seric 	map_rewrite(val.dptr, val.dsize, buf, bufsiz, av);
97*56822Seric 	return buf;
98*56822Seric }
99*56822Seric 
100*56822Seric #endif /* DBM_MAP */
101*56822Seric 
102*56822Seric #ifdef BTREE_MAP
103*56822Seric 
104*56822Seric /*
105*56822Seric **  BTREE_MAP_INIT -- BTREE-style map initialization
106*56822Seric **
107*56822Seric **	Parameters:
108*56822Seric **		map -- the pointer to the actual map
109*56822Seric **		mapname -- the name of the map (for error messages)
110*56822Seric **		args -- a pointer to the config file line arguments
111*56822Seric **
112*56822Seric **	Returns:
113*56822Seric **		TRUE -- if it could successfully open the map.
114*56822Seric **		FALSE -- otherwise.
115*56822Seric **
116*56822Seric **	Side Effects:
117*56822Seric **		Gives an error if it can't open the map.
118*56822Seric */
119*56822Seric 
120*56822Seric bool
121*56822Seric bt_map_init(map, mapname, args)
122*56822Seric 	MAP *map;
123*56822Seric 	char *mapname;
124*56822Seric 	char *args;
125*56822Seric {
126*56822Seric 	DB *db;
127*56822Seric 
128*56822Seric 	map_parseargs(map, &args, mapname);
129*56822Seric 	if (map->map_file == NULL)
130*56822Seric 		return FALSE;
131*56822Seric 	db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL);
132*56822Seric 	if (db == NULL)
133*56822Seric 	{
134*56822Seric 		syserr("Cannot open BTREE database %s", map->map_file);
135*56822Seric 		return FALSE;
136*56822Seric 	}
137*56822Seric 	map->map_db = (void *) db;
138*56822Seric 	return TRUE;
139*56822Seric }
140*56822Seric 
141*56822Seric #endif /* BTREE_MAP */
142*56822Seric 
143*56822Seric #ifdef HASH_MAP
144*56822Seric 
145*56822Seric /*
146*56822Seric **  HASH_MAP_INIT -- HASH-style map initialization
147*56822Seric **
148*56822Seric **	Parameters:
149*56822Seric **		map -- the pointer to the actual map
150*56822Seric **		mapname -- the name of the map (for error messages)
151*56822Seric **		args -- a pointer to the config file line arguments
152*56822Seric **
153*56822Seric **	Returns:
154*56822Seric **		TRUE -- if it could successfully open the map.
155*56822Seric **		FALSE -- otherwise.
156*56822Seric **
157*56822Seric **	Side Effects:
158*56822Seric **		Gives an error if it can't open the map.
159*56822Seric */
160*56822Seric 
161*56822Seric bool
162*56822Seric hash_map_init(map, mapname, args)
163*56822Seric 	MAP *map;
164*56822Seric 	char *mapname;
165*56822Seric 	char *args;
166*56822Seric {
167*56822Seric 	DB *db;
168*56822Seric 
169*56822Seric 	map_parseargs(map, &args, mapname);
170*56822Seric 	if (map->map_file == NULL)
171*56822Seric 		return FALSE;
172*56822Seric 	db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL);
173*56822Seric 	if (db == NULL)
174*56822Seric 	{
175*56822Seric 		syserr("Cannot open HASH database %s", map->map_file);
176*56822Seric 		return FALSE;
177*56822Seric 	}
178*56822Seric 	map->map_db = (void *) db;
179*56822Seric 	return TRUE;
180*56822Seric }
181*56822Seric 
182*56822Seric #endif /* HASH_MAP */
183*56822Seric 
184*56822Seric #if defined(BTREE_MAP) || defined(HASH_MAP)
185*56822Seric 
186*56822Seric /*
187*56822Seric **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
188*56822Seric **
189*56822Seric **	Parameters:
190*56822Seric **		map -- the map to look up in.
191*56822Seric **		buf -- a pointer to to the buffer containing the key.
192*56822Seric **			This is a null terminated string.
193*56822Seric **		bufsiz -- the size of buf -- note that this is in general
194*56822Seric **			larger that strlen(buf), and buf can be changed
195*56822Seric **			in place if desired.
196*56822Seric **		av -- arguments from the config file (can be interpolated
197*56822Seric **			into the final result).
198*56822Seric **
199*56822Seric **	Returns:
200*56822Seric **		A pointer to the rewritten result.
201*56822Seric **		NULL if not found in the map.
202*56822Seric */
203*56822Seric 
204*56822Seric char *
205*56822Seric db_map_lookup(map, buf, bufsiz, av)
206*56822Seric 	MAP *map;
207*56822Seric 	char buf[];
208*56822Seric 	int bufsiz;
209*56822Seric 	char **av;
210*56822Seric {
211*56822Seric 	DBT key, val;
212*56822Seric 
213*56822Seric 	key.data = buf;
214*56822Seric 	key.size = strlen(buf);
215*56822Seric 	if (bitset(MF_INCLNULL, map->map_flags))
216*56822Seric 		key.size++;
217*56822Seric 	if ((*((DB *) map->map_db)->get)((DB *) map->map_db, &key, &val, 0) != 0)
218*56822Seric 		return NULL;
219*56822Seric 	map_rewrite(val.data, val.size, buf, bufsiz, av);
220*56822Seric 	return buf;
221*56822Seric }
222*56822Seric 
223*56822Seric #endif /* BTREE_MAP || HASH_MAP */
224*56822Seric /*
225*56822Seric **  MAP_PARSEARGS -- parse config line arguments for database lookup
226*56822Seric **
227*56822Seric **	Parameters:
228*56822Seric **		map -- the map being initialized.
229*56822Seric **		pp -- an indirect pointer to the config line.  It will
230*56822Seric **			be replaced with a pointer to the next field
231*56822Seric **			on the line.
232*56822Seric **		mapname -- the name of the map (for errors).
233*56822Seric **
234*56822Seric **	Returns:
235*56822Seric **		none
236*56822Seric **
237*56822Seric **	Side Effects:
238*56822Seric **		null terminates the filename; stores it in map
239*56822Seric */
240*56822Seric 
241*56822Seric map_parseargs(map, pp, mapname)
242*56822Seric 	MAP *map;
243*56822Seric 	char **pp;
244*56822Seric 	char *mapname;
245*56822Seric {
246*56822Seric 	register char *p = *pp;
247*56822Seric 
248*56822Seric 	for (;;)
249*56822Seric 	{
250*56822Seric 		while (isspace(*p))
251*56822Seric 			p++;
252*56822Seric 		if (*p != '-')
253*56822Seric 			break;
254*56822Seric 		switch (*++p)
255*56822Seric 		{
256*56822Seric 		  case 'N':
257*56822Seric 			map->map_flags |= MF_INCLNULL;
258*56822Seric 			break;
259*56822Seric 		}
260*56822Seric 		while (*p != '\0' && !isspace(*p))
261*56822Seric 			p++;
262*56822Seric 	}
263*56822Seric 
264*56822Seric 	if (*p == '\0')
265*56822Seric 	{
266*56822Seric 		syserr("No file name for map %s", mapname);
267*56822Seric 		return NULL;
268*56822Seric 	}
269*56822Seric 	map->map_file = p;
270*56822Seric 	while (*p != '\0' && !isspace(*p))
271*56822Seric 		p++;
272*56822Seric 	if (*p != '\0')
273*56822Seric 		*p++ = '\0';
274*56822Seric 	*pp = p;
275*56822Seric }
276*56822Seric /*
277*56822Seric **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
278*56822Seric **
279*56822Seric **	Parameters:
280*56822Seric **		s -- the string to rewrite, NOT necessarily null terminated.
281*56822Seric **		slen -- the length of s.
282*56822Seric **		buf -- the place to write it.
283*56822Seric **		buflen -- the length of buf.
284*56822Seric **		av -- arguments to interpolate into buf.
285*56822Seric **
286*56822Seric **	Returns:
287*56822Seric **		none.
288*56822Seric **
289*56822Seric **	Side Effects:
290*56822Seric **		none.
291*56822Seric */
292*56822Seric 
293*56822Seric map_rewrite(s, slen, buf, buflen, av)
294*56822Seric 	register char *s;
295*56822Seric 	int slen;
296*56822Seric 	char buf[];
297*56822Seric 	int buflen;
298*56822Seric 	char **av;
299*56822Seric {
300*56822Seric 	register char *bp;
301*56822Seric 	char *buflim;
302*56822Seric 	register char c;
303*56822Seric 	char **avp;
304*56822Seric 	register char *ap;
305*56822Seric 
306*56822Seric 	if (tTd(23, 1))
307*56822Seric 	{
308*56822Seric 		printf("map_rewrite(%.*s), av =\n", slen, s);
309*56822Seric 		for (avp = av; *avp != NULL; avp++)
310*56822Seric 			printf("\t%s\n", *avp);
311*56822Seric 	}
312*56822Seric 
313*56822Seric 	bp = buf;
314*56822Seric 	buflim = &buf[buflen - 2];
315*56822Seric 	while (--slen >= 0 && (c = *s++) != '\0')
316*56822Seric 	{
317*56822Seric 		if (c != '%')
318*56822Seric 		{
319*56822Seric   pushc:
320*56822Seric 			if (bp < buflim)
321*56822Seric 				*bp++ = c;
322*56822Seric 			continue;
323*56822Seric 		}
324*56822Seric 		if (--slen < 0 || (c = *s++) == '\0')
325*56822Seric 			c = '%';
326*56822Seric 		if (c == '%')
327*56822Seric 			goto pushc;
328*56822Seric 		if (!isdigit(c))
329*56822Seric 		{
330*56822Seric 			*bp++ = '%';
331*56822Seric 			goto pushc;
332*56822Seric 		}
333*56822Seric 		c -= '0';
334*56822Seric 		for (avp = av; --c >= 0 && *avp != NULL; avp++)
335*56822Seric 			continue;
336*56822Seric 		if (*avp == NULL)
337*56822Seric 			continue;
338*56822Seric 
339*56822Seric 		/* transliterate argument into output string */
340*56822Seric 		for (ap = *avp; (c = *ap++) != '\0'; )
341*56822Seric 		{
342*56822Seric 			if (bp < buflim)
343*56822Seric 				*bp++ = c;
344*56822Seric 		}
345*56822Seric 	}
346*56822Seric 	*bp++ = '\0';
347*56822Seric 	if (tTd(23, 1))
348*56822Seric 		printf("map_rewrite => %s\n", buf);
349*56822Seric }
350