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