minor tweaking of syslog levels & compile fixes for SunOS & Ultrix
[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
73f6752a 10static char sccsid[] = "@(#)map.c 6.12 (Berkeley) %G%";
4cb3af58
EA
11#endif /* not lint */
12
13#include "sendmail.h"
4cb3af58
EA
14
15#ifdef DBM_MAP
16#include <ndbm.h>
17#endif
18#if defined(HASH_MAP) || defined(BTREE_MAP)
73f6752a 19#undef __P
4cb3af58
EA
20#include <db.h>
21#endif
33844dcf
EA
22#ifdef NIS_MAP
23#include <rpcsvc/ypclnt.h>
24#endif
4cb3af58
EA
25
26
27#ifdef DBM_MAP
28
29/*
30** DBM_MAP_INIT -- DBM-style map initialization
31**
32** Parameters:
33** map -- the pointer to the actual map
34** mapname -- the name of the map (for error messages)
35** args -- a pointer to the config file line arguments
36**
37** Returns:
38** TRUE -- if it could successfully open the map.
39** FALSE -- otherwise.
40**
41** Side Effects:
42** Gives an error if it can't open the map.
43*/
44
45bool
46dbm_map_init(map, mapname, args)
47 MAP *map;
48 char *mapname;
49 char *args;
50{
51 DBM *dbm;
52
33844dcf 53 map_parseargs(map, &args);
4cb3af58 54 if (map->map_file == NULL)
33844dcf
EA
55 {
56 syserr("No file name for DBM map %s", mapname);
4cb3af58 57 return FALSE;
33844dcf 58 }
4cb3af58
EA
59 dbm = dbm_open(map->map_file, O_RDONLY, 0644);
60 if (dbm == NULL)
61 {
32fd13db
EA
62 if (!bitset(MF_OPTIONAL, map->map_flags))
63 syserr("Cannot open DBM database %s", map->map_file);
4cb3af58
EA
64 return FALSE;
65 }
66 map->map_db = (void *) dbm;
67 return TRUE;
68}
69\f/*
70** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
71**
72** Parameters:
73** map -- the map to look up in.
74** buf -- a pointer to to the buffer containing the key.
75** This is a null terminated string.
76** bufsiz -- the size of buf -- note that this is in general
77** larger that strlen(buf), and buf can be changed
78** in place if desired.
79** av -- arguments from the config file (can be interpolated
80** into the final result).
d1db7a89 81** statp -- pointer to status word (out-parameter).
4cb3af58
EA
82**
83** Returns:
84** A pointer to the rewritten result.
85** NULL if not found in the map.
86*/
87
88char *
d1db7a89 89dbm_map_lookup(map, buf, bufsiz, av, statp)
4cb3af58
EA
90 MAP *map;
91 char buf[];
92 int bufsiz;
93 char **av;
d1db7a89 94 int *statp;
4cb3af58
EA
95{
96 datum key, val;
97
98 key.dptr = buf;
99 key.dsize = strlen(buf);
5dac3bbf 100 if (!bitset(MF_NOFOLDCASE, map->map_flags))
f22e3888
EA
101 {
102 register char *p;
103
104 for (p = buf; *p != '\0'; p++)
2bee003d 105 if (isascii(*p) && isupper(*p))
f22e3888
EA
106 *p = tolower(*p);
107 }
4cb3af58
EA
108 if (bitset(MF_INCLNULL, map->map_flags))
109 key.dsize++;
73f6752a
EA
110 (void) lockfile(dbm_dirfno((DBM *) map->map_db), map->map_file, LOCK_SH);
111 val = dbm_fetch((DBM *) map->map_db, key);
112 (void) lockfile(dbm_dirfno((DBM *) map->map_db), map->map_file, LOCK_UN);
4cb3af58
EA
113 if (val.dptr == NULL)
114 return NULL;
33844dcf
EA
115 if (!bitset(MF_MATCHONLY, map->map_flags))
116 map_rewrite(val.dptr, val.dsize, buf, bufsiz, av);
4cb3af58
EA
117 return buf;
118}
119
120#endif /* DBM_MAP */
121\f
122#ifdef BTREE_MAP
123
124/*
125** BTREE_MAP_INIT -- BTREE-style map initialization
126**
127** Parameters:
128** map -- the pointer to the actual map
129** mapname -- the name of the map (for error messages)
130** args -- a pointer to the config file line arguments
131**
132** Returns:
133** TRUE -- if it could successfully open the map.
134** FALSE -- otherwise.
135**
136** Side Effects:
137** Gives an error if it can't open the map.
138*/
139
140bool
141bt_map_init(map, mapname, args)
142 MAP *map;
143 char *mapname;
144 char *args;
145{
146 DB *db;
147
33844dcf 148 map_parseargs(map, &args);
4cb3af58 149 if (map->map_file == NULL)
33844dcf
EA
150 {
151 syserr("No file name for BTREE map %s", mapname);
4cb3af58 152 return FALSE;
33844dcf 153 }
4cb3af58
EA
154 db = dbopen(map->map_file, O_RDONLY, 0644, DB_BTREE, NULL);
155 if (db == NULL)
156 {
32fd13db
EA
157 if (!bitset(MF_OPTIONAL, map->map_flags))
158 syserr("Cannot open BTREE database %s", map->map_file);
4cb3af58
EA
159 return FALSE;
160 }
161 map->map_db = (void *) db;
162 return TRUE;
163}
164
165#endif /* BTREE_MAP */
166\f
167#ifdef HASH_MAP
168
169/*
170** HASH_MAP_INIT -- HASH-style map initialization
171**
172** Parameters:
173** map -- the pointer to the actual map
174** mapname -- the name of the map (for error messages)
175** args -- a pointer to the config file line arguments
176**
177** Returns:
178** TRUE -- if it could successfully open the map.
179** FALSE -- otherwise.
180**
181** Side Effects:
182** Gives an error if it can't open the map.
183*/
184
185bool
186hash_map_init(map, mapname, args)
187 MAP *map;
188 char *mapname;
189 char *args;
190{
191 DB *db;
192
33844dcf 193 map_parseargs(map, &args);
4cb3af58 194 if (map->map_file == NULL)
33844dcf
EA
195 {
196 syserr("No file name for HASH map %s", mapname);
4cb3af58 197 return FALSE;
33844dcf 198 }
4cb3af58
EA
199 db = dbopen(map->map_file, O_RDONLY, 0644, DB_HASH, NULL);
200 if (db == NULL)
201 {
32fd13db
EA
202 if (!bitset(MF_OPTIONAL, map->map_flags))
203 syserr("Cannot open HASH database %s", map->map_file);
4cb3af58
EA
204 return FALSE;
205 }
206 map->map_db = (void *) db;
207 return TRUE;
208}
209
210#endif /* HASH_MAP */
211\f
212#if defined(BTREE_MAP) || defined(HASH_MAP)
213
214/*
215** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
216**
217** Parameters:
218** map -- the map to look up in.
219** buf -- a pointer to to the buffer containing the key.
220** This is a null terminated string.
221** bufsiz -- the size of buf -- note that this is in general
222** larger that strlen(buf), and buf can be changed
223** in place if desired.
224** av -- arguments from the config file (can be interpolated
225** into the final result).
d1db7a89 226** statp -- pointer to status word (out-parameter).
4cb3af58
EA
227**
228** Returns:
229** A pointer to the rewritten result.
230** NULL if not found in the map.
231*/
232
233char *
d1db7a89 234db_map_lookup(map, buf, bufsiz, av, statp)
4cb3af58
EA
235 MAP *map;
236 char buf[];
237 int bufsiz;
238 char **av;
d1db7a89 239 int *statp;
4cb3af58
EA
240{
241 DBT key, val;
242
243 key.data = buf;
244 key.size = strlen(buf);
5dac3bbf 245 if (!bitset(MF_NOFOLDCASE, map->map_flags))
c58eb4cc
EA
246 {
247 register char *p;
248
249 for (p = buf; *p != '\0'; p++)
2bee003d 250 if (isascii(*p) && isupper(*p))
c58eb4cc
EA
251 *p = tolower(*p);
252 }
4cb3af58
EA
253 if (bitset(MF_INCLNULL, map->map_flags))
254 key.size++;
32fd13db 255 if (((DB *) map->map_db)->get((DB *) map->map_db, &key, &val, 0) != 0)
4cb3af58 256 return NULL;
33844dcf
EA
257 if (!bitset(MF_MATCHONLY, map->map_flags))
258 map_rewrite(val.data, val.size, buf, bufsiz, av);
4cb3af58
EA
259 return buf;
260}
261
262#endif /* BTREE_MAP || HASH_MAP */
263\f/*
264** MAP_PARSEARGS -- parse config line arguments for database lookup
265**
266** Parameters:
267** map -- the map being initialized.
268** pp -- an indirect pointer to the config line. It will
269** be replaced with a pointer to the next field
270** on the line.
4cb3af58
EA
271**
272** Returns:
273** none
274**
275** Side Effects:
276** null terminates the filename; stores it in map
277*/
278
33844dcf 279map_parseargs(map, pp)
4cb3af58
EA
280 MAP *map;
281 char **pp;
4cb3af58
EA
282{
283 register char *p = *pp;
284
285 for (;;)
286 {
2bee003d 287 while (isascii(*p) && isspace(*p))
4cb3af58
EA
288 p++;
289 if (*p != '-')
290 break;
291 switch (*++p)
292 {
293 case 'N':
294 map->map_flags |= MF_INCLNULL;
295 break;
32fd13db
EA
296
297 case 'o':
298 map->map_flags |= MF_OPTIONAL;
299 break;
300
c58eb4cc 301 case 'f':
5dac3bbf 302 map->map_flags |= MF_NOFOLDCASE;
c58eb4cc
EA
303 break;
304
33844dcf
EA
305 case 'm':
306 map->map_flags |= MF_MATCHONLY;
307 break;
308
32fd13db
EA
309 case 'a':
310 map->map_app = ++p;
311 break;
33844dcf
EA
312
313 case 'd':
314 map->map_domain = ++p;
315 break;
4cb3af58 316 }
2bee003d 317 while (*p != '\0' && !(isascii(*p) && isspace(*p)))
4cb3af58 318 p++;
32fd13db 319 if (*p != '\0')
4aaafa33 320 *p++ = '\0';
4cb3af58 321 }
32fd13db
EA
322 if (map->map_app != NULL)
323 map->map_app = newstr(map->map_app);
33844dcf
EA
324 if (map->map_domain != NULL)
325 map->map_domain = newstr(map->map_domain);
4cb3af58 326
4cb3af58 327 if (*p != '\0')
4aaafa33
EA
328 {
329 map->map_file = p;
330 while (*p != '\0' && !(isascii(*p) && isspace(*p)))
331 p++;
332 if (*p != '\0')
333 *p++ = '\0';
334 map->map_file = newstr(map->map_file);
335 }
cc047d90
EA
336
337 while (*p != '\0' && isascii(*p) && isspace(*p))
338 p++;
4cb3af58 339 *pp = p;
cc047d90
EA
340 if (*p != '\0')
341 map->map_rebuild = newstr(p);
4cb3af58 342}
33844dcf
EA
343\f
344# ifdef NIS_MAP
345
346/*
347** NIS_MAP_INIT -- initialize DBM map
348**
349** Parameters:
350** map -- the pointer to the actual map.
351** mapname -- the name of the map (for error messages).
352** args -- a pointer to the config file line arguments.
353**
354** Returns:
355** TRUE -- if it could successfully open the map.
356** FALSE -- otherwise.
357**
358** Side Effects:
359** Prints an error if it can't open the map.
360*/
361
362bool
363nis_map_init(map, mapname, args)
364 MAP *map;
365 char *mapname;
366 char *args;
367{
0044540e
EA
368 int yperr;
369 char *master;
370
33844dcf
EA
371 /* parse arguments */
372 map_parseargs(map, &args);
373 if (map->map_file == NULL)
374 {
375 syserr("No NIS map name for map %s", mapname);
376 return FALSE;
377 }
378 if (map->map_domain == NULL)
379 yp_get_default_domain(&map->map_domain);
0044540e
EA
380
381 /* check to see if this map actually exists */
382 yperr = yp_master(map->map_domain, map->map_file, &master);
383 if (yperr == 0)
384 return TRUE;
385 if (!bitset(MF_OPTIONAL, map->map_flags))
386 syserr("Cannot bind to domain %s: %s", map->map_domain,
387 yperr_string(yperr));
388 return FALSE;
33844dcf
EA
389}
390\f/*
391** NIS_MAP_LOOKUP -- look up a datum in a NIS map
392**
393** Parameters:
394** map -- the map to look up in.
395** buf -- a pointer to to the buffer containing the key.
396** This is a null terminated string.
397** bufsiz -- the size of buf -- note that this is in general
398** larger that strlen(buf), and buf can be changed
399** in place if desired.
400** av -- arguments from the config file (can be interpolated
401** into the final result).
d1db7a89 402** statp -- pointer to status word (out-parameter).
33844dcf
EA
403**
404** Returns:
405** A pointer to the rewritten result.
406** NULL if not found in the map.
407*/
408
409char *
d1db7a89 410nis_map_lookup(map, buf, bufsiz, av, statp)
33844dcf
EA
411 MAP *map;
412 char buf[];
413 int bufsiz;
414 char **av;
d1db7a89 415 int *statp;
33844dcf
EA
416{
417 char *vp;
6e99f903 418 auto int vsize;
0753ae18 419 int buflen;
33844dcf
EA
420
421 if (!bitset(MF_NOFOLDCASE, map->map_flags))
422 {
423 register char *p;
424
425 for (p = buf; *p != '\0'; p++)
2bee003d 426 if (isascii(*p) && isupper(*p))
33844dcf
EA
427 *p = tolower(*p);
428 }
0753ae18
EA
429 buflen = strlen(buf);
430 if (bitset(MF_INCLNULL, map->map_flags))
431 buflen++;
432 if (yp_match(map->map_domain, map->map_file, buf, buflen,
6e99f903 433 &vp, &vsize) != 0)
33844dcf
EA
434 return NULL;
435 if (!bitset(MF_MATCHONLY, map->map_flags))
436 map_rewrite(vp, vsize, buf, bufsiz, av);
437 return buf;
438}
439
440#endif /* NIS_MAP */
4cb3af58
EA
441\f/*
442** MAP_REWRITE -- rewrite a database key, interpolating %n indications.
443**
444** Parameters:
445** s -- the string to rewrite, NOT necessarily null terminated.
446** slen -- the length of s.
447** buf -- the place to write it.
448** buflen -- the length of buf.
449** av -- arguments to interpolate into buf.
450**
451** Returns:
452** none.
453**
454** Side Effects:
455** none.
456*/
457
458map_rewrite(s, slen, buf, buflen, av)
459 register char *s;
460 int slen;
461 char buf[];
462 int buflen;
463 char **av;
464{
465 register char *bp;
466 char *buflim;
467 register char c;
468 char **avp;
469 register char *ap;
470
471 if (tTd(23, 1))
472 {
473 printf("map_rewrite(%.*s), av =\n", slen, s);
474 for (avp = av; *avp != NULL; avp++)
475 printf("\t%s\n", *avp);
476 }
477
478 bp = buf;
479 buflim = &buf[buflen - 2];
480 while (--slen >= 0 && (c = *s++) != '\0')
481 {
482 if (c != '%')
483 {
484 pushc:
485 if (bp < buflim)
486 *bp++ = c;
487 continue;
488 }
489 if (--slen < 0 || (c = *s++) == '\0')
490 c = '%';
491 if (c == '%')
492 goto pushc;
2bee003d 493 if (!(isascii(c) && isdigit(c)))
4cb3af58
EA
494 {
495 *bp++ = '%';
496 goto pushc;
497 }
498 c -= '0';
499 for (avp = av; --c >= 0 && *avp != NULL; avp++)
500 continue;
501 if (*avp == NULL)
502 continue;
503
504 /* transliterate argument into output string */
505 for (ap = *avp; (c = *ap++) != '\0'; )
506 {
507 if (bp < buflim)
508 *bp++ = c;
509 }
510 }
511 *bp++ = '\0';
512 if (tTd(23, 1))
513 printf("map_rewrite => %s\n", buf);
514}