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