SCO compatibility
[unix-history] / usr / src / usr.sbin / sendmail / src / map.c
CommitLineData
4cb3af58
EA
1/*
2 * Copyright (c) 1992 Eric P. Allman.
eb0bafab
KB
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
4cb3af58
EA
5 *
6 * %sccs.include.redist.c%
7 */
8
9#ifndef lint
8e5c6745 10static char sccsid[] = "@(#)map.c 8.2 (Berkeley) %G%";
4cb3af58
EA
11#endif /* not lint */
12
13#include "sendmail.h"
4cb3af58 14
713c523f 15#ifdef NDBM
4cb3af58
EA
16#include <ndbm.h>
17#endif
713c523f 18#ifdef NEWDB
4cb3af58
EA
19#include <db.h>
20#endif
713c523f 21#ifdef NIS
33844dcf
EA
22#include <rpcsvc/ypclnt.h>
23#endif
4cb3af58 24
4cb3af58 25/*
713c523f 26** MAP.C -- implementations for various map classes.
4cb3af58 27**
713c523f 28** Each map class implements a series of functions:
4cb3af58 29**
713c523f
EA
30** bool map_parse(MAP *map, char *args)
31** Parse the arguments from the config file. Return TRUE
32** if they were ok, FALSE otherwise. Fill in map with the
33** values.
4cb3af58 34**
f500979e
EA
35** char *map_lookup(MAP *map, char *key, char **args, int *pstat)
36** Look up the key in the given map. If found, do any
37** rewriting the map wants (including "args" if desired)
713c523f 38** and return the value. Set *pstat to the appropriate status
f500979e
EA
39** on error and return NULL. Args will be NULL if called
40** from the alias routines, although this should probably
41** not be relied upon. It is suggested you call map_rewrite
42** to return the results -- it takes care of null termination
43** and uses a dynamically expanded buffer as needed.
4cb3af58 44**
713c523f
EA
45** void map_store(MAP *map, char *key, char *value)
46** Store the key:value pair in the map.
4cb3af58 47**
713c523f 48** bool map_open(MAP *map, int mode)
f500979e
EA
49** Open the map for the indicated mode. Mode should
50** be either O_RDONLY or O_RDWR. Return TRUE if it
51** was opened successfully, FALSE otherwise. If the open
52** failed an the MF_OPTIONAL flag is not set, it should
53** also print an error. If the MF_ALIAS bit is set
54** and this map class understands the @:@ convention, it
55** should call aliaswait() before returning.
4cb3af58 56**
713c523f
EA
57** void map_close(MAP *map)
58** Close the map.
4cb3af58
EA
59*/
60
713c523f 61#define DBMMODE 0644
4cb3af58
EA
62\f/*
63** MAP_PARSEARGS -- parse config line arguments for database lookup
64**
713c523f
EA
65** This is a generic version of the map_parse method.
66**
4cb3af58
EA
67** Parameters:
68** map -- the map being initialized.
713c523f 69** ap -- a pointer to the args on the config line.
4cb3af58
EA
70**
71** Returns:
713c523f
EA
72** TRUE -- if everything parsed OK.
73** FALSE -- otherwise.
4cb3af58
EA
74**
75** Side Effects:
76** null terminates the filename; stores it in map
77*/
78
713c523f
EA
79bool
80map_parseargs(map, ap)
4cb3af58 81 MAP *map;
713c523f 82 char *ap;
4cb3af58 83{
713c523f 84 register char *p = ap;
4cb3af58 85
8e5c6745 86 map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
4cb3af58
EA
87 for (;;)
88 {
2bee003d 89 while (isascii(*p) && isspace(*p))
4cb3af58
EA
90 p++;
91 if (*p != '-')
92 break;
93 switch (*++p)
94 {
95 case 'N':
31f1ab13 96 map->map_mflags |= MF_INCLNULL;
8e5c6745
EA
97 map->map_mflags &= ~MF_TRY0NULL;
98 break;
99
100 case 'O':
101 map->map_mflags &= ~MF_TRY1NULL;
4cb3af58 102 break;
32fd13db
EA
103
104 case 'o':
31f1ab13 105 map->map_mflags |= MF_OPTIONAL;
32fd13db
EA
106 break;
107
c58eb4cc 108 case 'f':
31f1ab13 109 map->map_mflags |= MF_NOFOLDCASE;
c58eb4cc
EA
110 break;
111
33844dcf 112 case 'm':
31f1ab13 113 map->map_mflags |= MF_MATCHONLY;
33844dcf
EA
114 break;
115
32fd13db
EA
116 case 'a':
117 map->map_app = ++p;
118 break;
4cb3af58 119 }
2bee003d 120 while (*p != '\0' && !(isascii(*p) && isspace(*p)))
4cb3af58 121 p++;
32fd13db 122 if (*p != '\0')
4aaafa33 123 *p++ = '\0';
4cb3af58 124 }
32fd13db
EA
125 if (map->map_app != NULL)
126 map->map_app = newstr(map->map_app);
4cb3af58 127
4cb3af58 128 if (*p != '\0')
4aaafa33
EA
129 {
130 map->map_file = p;
131 while (*p != '\0' && !(isascii(*p) && isspace(*p)))
132 p++;
133 if (*p != '\0')
134 *p++ = '\0';
135 map->map_file = newstr(map->map_file);
136 }
cc047d90
EA
137
138 while (*p != '\0' && isascii(*p) && isspace(*p))
139 p++;
cc047d90
EA
140 if (*p != '\0')
141 map->map_rebuild = newstr(p);
33844dcf 142
33844dcf
EA
143 if (map->map_file == NULL)
144 {
713c523f
EA
145 syserr("No file name for %s map %s",
146 map->map_class->map_cname, map->map_mname);
33844dcf
EA
147 return FALSE;
148 }
713c523f 149 return TRUE;
33844dcf 150}
4cb3af58
EA
151\f/*
152** MAP_REWRITE -- rewrite a database key, interpolating %n indications.
153**
713c523f
EA
154** It also adds the map_app string. It can be used as a utility
155** in the map_lookup method.
156**
4cb3af58 157** Parameters:
713c523f 158** map -- the map that causes this.
4cb3af58
EA
159** s -- the string to rewrite, NOT necessarily null terminated.
160** slen -- the length of s.
4cb3af58
EA
161** av -- arguments to interpolate into buf.
162**
163** Returns:
713c523f 164** Pointer to rewritten result.
4cb3af58
EA
165**
166** Side Effects:
167** none.
168*/
169
67d3f5c1
EA
170struct rwbuf
171{
172 int rwb_len; /* size of buffer */
173 char *rwb_buf; /* ptr to buffer */
174};
175
176struct rwbuf RwBufs[2]; /* buffers for rewriting output */
177
713c523f
EA
178char *
179map_rewrite(map, s, slen, av)
180 register MAP *map;
4cb3af58
EA
181 register char *s;
182 int slen;
4cb3af58
EA
183 char **av;
184{
185 register char *bp;
4cb3af58
EA
186 register char c;
187 char **avp;
188 register char *ap;
67d3f5c1 189 register struct rwbuf *rwb;
713c523f
EA
190 int i;
191 int len;
4cb3af58 192
36b09297 193 if (tTd(39, 1))
4cb3af58 194 {
eb76c0ac
EA
195 printf("map_rewrite(%.*s), av =", slen, s);
196 if (av == NULL)
197 printf(" (nullv)");
198 else
199 {
200 for (avp = av; *avp != NULL; avp++)
201 printf("\n\t%s", *avp);
202 }
203 printf("\n");
4cb3af58
EA
204 }
205
67d3f5c1
EA
206 rwb = RwBufs;
207 if (av == NULL)
208 rwb++;
209
713c523f
EA
210 /* count expected size of output (can safely overestimate) */
211 i = len = slen;
212 if (av != NULL)
213 {
214 bp = s;
215 for (i = slen; --i >= 0 && (c = *bp++) != 0; )
216 {
217 if (c != '%')
218 continue;
219 if (--i < 0)
220 break;
221 c = *bp++;
222 if (!(isascii(c) && isdigit(c)))
223 continue;
224 c -= 0;
225 for (avp = av; --c >= 0 && *avp != NULL; avp++)
226 continue;
227 if (*avp == NULL)
228 continue;
229 len += strlen(*avp);
230 }
231 }
232 if (map->map_app != NULL)
233 len += strlen(map->map_app);
67d3f5c1 234 if (rwb->rwb_len < ++len)
713c523f
EA
235 {
236 /* need to malloc additional space */
67d3f5c1
EA
237 rwb->rwb_len = len;
238 if (rwb->rwb_buf != NULL)
239 free(rwb->rwb_buf);
240 rwb->rwb_buf = xalloc(rwb->rwb_len);
713c523f
EA
241 }
242
67d3f5c1 243 bp = rwb->rwb_buf;
713c523f
EA
244 if (av == NULL)
245 {
246 bcopy(s, bp, slen);
247 bp += slen;
248 }
249 else
4cb3af58 250 {
713c523f 251 while (--slen >= 0 && (c = *s++) != '\0')
4cb3af58 252 {
713c523f
EA
253 if (c != '%')
254 {
4cb3af58 255 pushc:
4cb3af58 256 *bp++ = c;
713c523f
EA
257 continue;
258 }
259 if (--slen < 0 || (c = *s++) == '\0')
260 c = '%';
261 if (c == '%')
262 goto pushc;
263 if (!(isascii(c) && isdigit(c)))
264 {
265 *bp++ = '%';
266 goto pushc;
267 }
268 c -= '0';
269 for (avp = av; --c >= 0 && *avp != NULL; avp++)
270 continue;
271 if (*avp == NULL)
272 continue;
273
274 /* transliterate argument into output string */
275 for (ap = *avp; (c = *ap++) != '\0'; )
4cb3af58
EA
276 *bp++ = c;
277 }
278 }
713c523f
EA
279 if (map->map_app != NULL)
280 strcpy(bp, map->map_app);
281 else
282 *bp = '\0';
36b09297 283 if (tTd(39, 1))
67d3f5c1
EA
284 printf("map_rewrite => %s\n", rwb->rwb_buf);
285 return rwb->rwb_buf;
713c523f
EA
286}
287\f/*
36b09297
EA
288** INITMAPS -- initialize for aliasing
289**
290** Parameters:
291** rebuild -- if TRUE, this rebuilds the cached versions.
292** e -- current envelope.
293**
294** Returns:
295** none.
296**
297** Side Effects:
298** initializes aliases:
299** if NDBM: opens the database.
300** if ~NDBM: reads the aliases into the symbol table.
301*/
302
303initmaps(rebuild, e)
304 bool rebuild;
305 register ENVELOPE *e;
306{
307 extern void map_init();
308
309 CurEnv = e;
310 stabapply(map_init, rebuild);
311}
312
313void
314map_init(s, rebuild)
315 register STAB *s;
316 int rebuild;
317{
318 register MAP *map;
319
320 /* has to be a map */
321 if (s->s_type != ST_MAP)
322 return;
323
324 map = &s->s_map;
325 if (!bitset(MF_VALID, map->map_mflags))
326 return;
327
328 if (tTd(38, 2))
329 printf("map_init(%s:%s)\n",
330 map->map_class->map_cname, map->map_file);
331
332 /* if already open, close it (for nested open) */
333 if (bitset(MF_OPEN, map->map_mflags))
334 {
335 map->map_class->map_close(map);
336 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
337 }
338
339 if (rebuild)
340 {
d71eb2f5
EA
341 if (bitset(MF_ALIAS, map->map_mflags) &&
342 bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
36b09297
EA
343 rebuildaliases(map, FALSE);
344 }
345 else
346 {
347 if (map->map_class->map_open(map, O_RDONLY))
348 {
349 if (tTd(38, 4))
350 printf("%s:%s: valid\n",
351 map->map_class->map_cname,
352 map->map_file);
353 map->map_mflags |= MF_OPEN;
354 }
355 else if (tTd(38, 4))
356 printf("%s:%s: invalid: %s\n",
357 map->map_class->map_cname,
358 map->map_file,
359 errstring(errno));
360 }
361}
362\f/*
713c523f
EA
363** NDBM modules
364*/
365
366#ifdef NDBM
367
368/*
369** DBM_MAP_OPEN -- DBM-style map open
370*/
371
372bool
373ndbm_map_open(map, mode)
374 MAP *map;
375 int mode;
376{
377 DBM *dbm;
378
36b09297 379 if (tTd(38, 2))
713c523f
EA
380 printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
381
31f1ab13
EA
382 if (mode == O_RDWR)
383 mode |= O_CREAT|O_TRUNC;
384
713c523f
EA
385 /* open the database */
386 dbm = dbm_open(map->map_file, mode, DBMMODE);
387 if (dbm == NULL)
388 {
31f1ab13 389 if (!bitset(MF_OPTIONAL, map->map_mflags))
713c523f
EA
390 syserr("Cannot open DBM database %s", map->map_file);
391 return FALSE;
392 }
393 map->map_db1 = (void *) dbm;
31f1ab13 394 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
7b1e23ea 395 aliaswait(map, ".pag");
713c523f
EA
396 return TRUE;
397}
398
399
400/*
401** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
402*/
403
404char *
405ndbm_map_lookup(map, name, av, statp)
406 MAP *map;
407 char *name;
408 char **av;
409 int *statp;
410{
411 datum key, val;
412 char keybuf[MAXNAME + 1];
413
36b09297 414 if (tTd(38, 20))
713c523f
EA
415 printf("ndbm_map_lookup(%s)\n", name);
416
417 key.dptr = name;
418 key.dsize = strlen(name);
31f1ab13 419 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
713c523f
EA
420 {
421 if (key.dsize > sizeof keybuf - 1)
422 key.dsize = sizeof keybuf - 1;
423 bcopy(key.dptr, keybuf, key.dsize + 1);
424 makelower(keybuf);
425 key.dptr = keybuf;
426 }
713c523f 427 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
8e5c6745
EA
428 val.dptr = NULL;
429 if (bitset(MF_TRY0NULL, map->map_mflags))
430 {
431 val = dbm_fetch((DBM *) map->map_db1, key);
432 if (val.dptr != NULL)
433 map->map_mflags &= ~MF_TRY1NULL;
434 }
435 if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
436 {
437 key.dsize++;
438 val = dbm_fetch((DBM *) map->map_db1, key);
439 if (val.dptr != NULL)
440 map->map_mflags &= ~MF_TRY0NULL;
441 }
713c523f
EA
442 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
443 if (val.dptr == NULL)
444 return NULL;
31f1ab13 445 if (bitset(MF_MATCHONLY, map->map_mflags))
8e5c6745
EA
446 return map_rewrite(map, name, strlen(name), NULL);
447 else
448 return map_rewrite(map, val.dptr, val.dsize, av);
713c523f
EA
449}
450
451
452/*
453** DBM_MAP_STORE -- store a datum in the database
454*/
455
456void
457ndbm_map_store(map, lhs, rhs)
458 register MAP *map;
459 char *lhs;
460 char *rhs;
461{
462 datum key;
463 datum data;
464 int stat;
465
36b09297 466 if (tTd(38, 12))
713c523f
EA
467 printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
468
469 key.dsize = strlen(lhs);
470 key.dptr = lhs;
471
472 data.dsize = strlen(rhs);
473 data.dptr = rhs;
474
31f1ab13 475 if (bitset(MF_INCLNULL, map->map_mflags))
713c523f
EA
476 {
477 key.dsize++;
478 data.dsize++;
479 }
480
481 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
482 if (stat > 0)
483 {
484 usrerr("050 Warning: duplicate alias name %s", lhs);
485 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
486 }
487 if (stat != 0)
488 syserr("readaliases: dbm put (%s)", lhs);
489}
490
491
492/*
31f1ab13 493** NDBM_MAP_CLOSE -- close the database
713c523f
EA
494*/
495
496void
497ndbm_map_close(map)
498 register MAP *map;
499{
31f1ab13 500 if (bitset(MF_WRITABLE, map->map_mflags))
713c523f
EA
501 {
502#ifdef YPCOMPAT
503 char buf[200];
504
505 (void) sprintf(buf, "%010ld", curtime());
506 ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
507
508 (void) myhostname(buf, sizeof buf);
509 ndbm_map_store(map, "YP_MASTER_NAME", buf);
510#endif
511
512 /* write out the distinguished alias */
513 ndbm_map_store(map, "@", "@");
514 }
515 dbm_close((DBM *) map->map_db1);
516}
517
518#endif
519\f/*
8f43ee9e 520** NEWDB (Hash and BTree) Modules
713c523f
EA
521*/
522
523#ifdef NEWDB
524
525/*
8f43ee9e
EA
526** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
527**
528** These do rather bizarre locking. If you can lock on open,
529** do that to avoid the condition of opening a database that
530** is being rebuilt. If you don't, we'll try to fake it, but
531** there will be a race condition. If opening for read-only,
532** we immediately release the lock to avoid freezing things up.
533** We really ought to hold the lock, but guarantee that we won't
534** be pokey about it. That's hard to do.
713c523f
EA
535*/
536
537bool
538bt_map_open(map, mode)
539 MAP *map;
540 int mode;
541{
542 DB *db;
df88f2ef 543 int i;
8f43ee9e 544 int omode;
713c523f
EA
545 char buf[MAXNAME];
546
36b09297 547 if (tTd(38, 2))
713c523f
EA
548 printf("bt_map_open(%s, %d)\n", map->map_file, mode);
549
8f43ee9e
EA
550 omode = mode;
551 if (omode == O_RDWR)
552 {
553 omode |= O_CREAT|O_TRUNC;
554#if defined(O_EXLOCK) && !defined(LOCKF)
555 omode |= O_EXLOCK;
556# if !defined(OLD_NEWDB)
557 }
558 else
559 {
560 omode |= O_SHLOCK;
561# endif
562#endif
563 }
31f1ab13 564
df88f2ef
EA
565 (void) strcpy(buf, map->map_file);
566 i = strlen(buf);
567 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
568 (void) strcat(buf, ".db");
8f43ee9e 569 db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
713c523f
EA
570 if (db == NULL)
571 {
31f1ab13 572 if (!bitset(MF_OPTIONAL, map->map_mflags))
713c523f
EA
573 syserr("Cannot open BTREE database %s", map->map_file);
574 return FALSE;
575 }
8f43ee9e
EA
576#if !defined(OLD_NEWDB) && !defined(LOCKF)
577# if !defined(O_EXLOCK)
578 if (mode == O_RDWR)
579 (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
580# else
581 if (mode == O_RDONLY)
582 (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
583# endif
584#endif
b215b035
EA
585
586 /* try to make sure that at least the database header is on disk */
587 if (mode == O_RDWR)
588 (void) db->sync(db, 0);
589
713c523f 590 map->map_db2 = (void *) db;
31f1ab13
EA
591 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
592 aliaswait(map, ".db");
713c523f
EA
593 return TRUE;
594}
595
596
597/*
598** HASH_MAP_INIT -- HASH-style map initialization
599*/
600
601bool
602hash_map_open(map, mode)
603 MAP *map;
604 int mode;
605{
606 DB *db;
df88f2ef 607 int i;
8f43ee9e 608 int omode;
713c523f
EA
609 char buf[MAXNAME];
610
36b09297 611 if (tTd(38, 2))
713c523f
EA
612 printf("hash_map_open(%s, %d)\n", map->map_file, mode);
613
8f43ee9e
EA
614 omode = mode;
615 if (omode == O_RDWR)
616 {
617 omode |= O_CREAT|O_TRUNC;
618#if defined(O_EXLOCK) && !defined(LOCKF)
619 omode |= O_EXLOCK;
620# if !defined(OLD_NEWDB)
621 }
622 else
623 {
624 omode |= O_SHLOCK;
625# endif
626#endif
627 }
31f1ab13 628
df88f2ef
EA
629 (void) strcpy(buf, map->map_file);
630 i = strlen(buf);
631 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
632 (void) strcat(buf, ".db");
8f43ee9e 633 db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
713c523f
EA
634 if (db == NULL)
635 {
31f1ab13 636 if (!bitset(MF_OPTIONAL, map->map_mflags))
713c523f
EA
637 syserr("Cannot open HASH database %s", map->map_file);
638 return FALSE;
639 }
8f43ee9e
EA
640#if !defined(OLD_NEWDB) && !defined(LOCKF)
641# if !defined(O_EXLOCK)
642 if (mode == O_RDWR)
643 (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
644# else
645 if (mode == O_RDONLY)
646 (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
647# endif
648#endif
b215b035
EA
649
650 /* try to make sure that at least the database header is on disk */
651 if (mode == O_RDWR)
652 (void) db->sync(db, 0);
653
713c523f 654 map->map_db2 = (void *) db;
31f1ab13
EA
655 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
656 aliaswait(map, ".db");
713c523f
EA
657 return TRUE;
658}
659
660
661/*
662** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
663*/
664
665char *
666db_map_lookup(map, name, av, statp)
667 MAP *map;
668 char *name;
669 char **av;
670 int *statp;
671{
672 DBT key, val;
31ffabe6
EA
673 register DB *db = (DB *) map->map_db2;
674 int st;
675 int saveerrno;
713c523f
EA
676 char keybuf[MAXNAME + 1];
677
36b09297 678 if (tTd(38, 20))
713c523f
EA
679 printf("db_map_lookup(%s)\n", name);
680
681 key.size = strlen(name);
682 if (key.size > sizeof keybuf - 1)
683 key.size = sizeof keybuf - 1;
684 key.data = keybuf;
685 bcopy(name, keybuf, key.size + 1);
31f1ab13 686 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
713c523f 687 makelower(keybuf);
31ffabe6
EA
688#ifndef OLD_NEWDB
689 (void) lockfile(db->fd(db), map->map_file, LOCK_SH);
690#endif
8e5c6745
EA
691 st = 1;
692 if (bitset(MF_TRY0NULL, map->map_mflags))
693 {
694 st = db->get(db, &key, &val, 0);
695 if (st == 0)
696 map->map_mflags &= ~MF_TRY1NULL;
697 }
698 if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
699 {
700 key.size++;
701 st = db->get(db, &key, &val, 0);
702 if (st == 0)
703 map->map_mflags &= ~MF_TRY0NULL;
704 }
31ffabe6
EA
705 saveerrno = errno;
706#ifndef OLD_NEWDB
707 (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
708#endif
709 if (st != 0)
710 {
711 errno = saveerrno;
712 if (st < 0)
713 syserr("db_map_lookup: get (%s)", name);
713c523f 714 return NULL;
31ffabe6 715 }
31f1ab13 716 if (bitset(MF_MATCHONLY, map->map_mflags))
8e5c6745
EA
717 return map_rewrite(map, name, strlen(name), NULL);
718 else
719 return map_rewrite(map, val.data, val.size, av);
713c523f
EA
720}
721
722
723/*
724** DB_MAP_STORE -- store a datum in the NEWDB database
725*/
726
727void
728db_map_store(map, lhs, rhs)
729 register MAP *map;
730 char *lhs;
731 char *rhs;
732{
733 int stat;
734 DBT key;
735 DBT data;
736 register DB *db = map->map_db2;
737
36b09297 738 if (tTd(38, 20))
713c523f
EA
739 printf("db_map_store(%s, %s)\n", lhs, rhs);
740
741 key.size = strlen(lhs);
742 key.data = lhs;
743
744 data.size = strlen(rhs);
745 data.data = rhs;
746
31f1ab13 747 if (bitset(MF_INCLNULL, map->map_mflags))
713c523f
EA
748 {
749 key.size++;
750 data.size++;
751 }
752
753 stat = db->put(db, &key, &data, R_NOOVERWRITE);
754 if (stat > 0)
755 {
756 usrerr("050 Warning: duplicate alias name %s", lhs);
757 stat = db->put(db, &key, &data, 0);
758 }
759 if (stat != 0)
760 syserr("readaliases: db put (%s)", lhs);
761}
762
763
713c523f
EA
764/*
765** DB_MAP_CLOSE -- add distinguished entries and close the database
766*/
767
768void
769db_map_close(map)
770 MAP *map;
771{
772 register DB *db = map->map_db2;
773
36b09297 774 if (tTd(38, 9))
31f1ab13 775 printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
713c523f 776
31f1ab13 777 if (bitset(MF_WRITABLE, map->map_mflags))
713c523f
EA
778 {
779 /* write out the distinguished alias */
780 db_map_store(map, "@", "@");
781 }
782
783 if (db->close(db) != 0)
784 syserr("readaliases: db close failure");
785}
786
787#endif
788\f/*
789** NIS Modules
790*/
791
792# ifdef NIS
793
794/*
795** NIS_MAP_OPEN -- open DBM map
796*/
797
798bool
799nis_map_open(map, mode)
800 MAP *map;
801 int mode;
802{
803 int yperr;
94b8a28b
EA
804 register char *p;
805 auto char *vp;
806 auto int vsize;
713c523f
EA
807 char *master;
808
36b09297 809 if (tTd(38, 2))
713c523f
EA
810 printf("nis_map_open(%s)\n", map->map_file);
811
31f1ab13
EA
812 if (mode != O_RDONLY)
813 {
814 errno = ENODEV;
815 return FALSE;
816 }
817
713c523f
EA
818 p = strchr(map->map_file, '@');
819 if (p != NULL)
820 {
821 *p++ = '\0';
822 if (*p != '\0')
823 map->map_domain = p;
824 }
94b8a28b 825
713c523f
EA
826 if (map->map_domain == NULL)
827 yp_get_default_domain(&map->map_domain);
828
829 if (*map->map_file == '\0')
830 map->map_file = "mail.aliases";
831
94b8a28b 832 /* check to see if this map actually exists */
713c523f
EA
833 yperr = yp_match(map->map_domain, map->map_file, "@", 1,
834 &vp, &vsize);
36b09297 835 if (tTd(38, 10))
713c523f
EA
836 printf("nis_map_open: yp_match(%s, %s) => %s\n",
837 map->map_domain, map->map_file, yperr_string(yperr));
838 if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
839 return TRUE;
94b8a28b
EA
840
841 if (!bitset(MF_OPTIONAL, map->map_mflags))
842 syserr("Cannot bind to domain %s: %s", map->map_domain,
843 yperr_string(yperr));
844
713c523f
EA
845 return FALSE;
846}
847
848
849/*
850** NIS_MAP_LOOKUP -- look up a datum in a NIS map
851*/
852
853char *
854nis_map_lookup(map, name, av, statp)
855 MAP *map;
856 char *name;
857 char **av;
858 int *statp;
859{
860 char *vp;
861 auto int vsize;
862 int buflen;
94b8a28b 863 int yperr;
713c523f
EA
864 char keybuf[MAXNAME + 1];
865
36b09297 866 if (tTd(38, 20))
713c523f
EA
867 printf("nis_map_lookup(%s)\n", name);
868
869 buflen = strlen(name);
870 if (buflen > sizeof keybuf - 1)
871 buflen = sizeof keybuf - 1;
872 bcopy(name, keybuf, buflen + 1);
31f1ab13 873 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
713c523f 874 makelower(keybuf);
8e5c6745
EA
875 yperr = YPERR_KEY;
876 if (bitset(MF_TRY0NULL, map->map_mflags))
877 {
878 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
879 &vp, &vsize);
880 if (yperr == 0)
881 map->map_mflags &= ~MF_TRY1NULL;
882 }
883 if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
884 {
713c523f 885 buflen++;
8e5c6745
EA
886 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
887 &vp, &vsize);
888 if (yperr == 0)
889 map->map_mflags &= ~MF_TRY0NULL;
890 }
713c523f
EA
891 if (yperr != 0)
892 {
893 if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
94b8a28b 894 map->map_mflags &= ~(MF_VALID|MF_OPEN);
713c523f
EA
895 return NULL;
896 }
31f1ab13 897 if (bitset(MF_MATCHONLY, map->map_mflags))
8e5c6745
EA
898 return map_rewrite(map, name, strlen(name), NULL);
899 else
900 return map_rewrite(map, vp, vsize, av);
713c523f
EA
901}
902
903
904/*
31f1ab13 905** NIS_MAP_STORE
713c523f
EA
906*/
907
908void
909nis_map_store(map, lhs, rhs)
910 MAP *map;
911 char *lhs;
912 char *rhs;
913{
914 /* nothing */
915}
916
713c523f
EA
917
918/*
31f1ab13 919** NIS_MAP_CLOSE
713c523f
EA
920*/
921
922void
923nis_map_close(map)
924 MAP *map;
925{
926 /* nothing */
927}
928
929#endif /* NIS */
930\f/*
931** STAB (Symbol Table) Modules
932*/
933
934
935/*
31f1ab13 936** STAB_MAP_LOOKUP -- look up alias in symbol table
713c523f
EA
937*/
938
939char *
a3934270 940stab_map_lookup(map, name, av, pstat)
713c523f
EA
941 register MAP *map;
942 char *name;
a3934270
EA
943 char **av;
944 int *pstat;
713c523f
EA
945{
946 register STAB *s;
947
36b09297 948 if (tTd(38, 20))
713c523f
EA
949 printf("stab_lookup(%s)\n", name);
950
951 s = stab(name, ST_ALIAS, ST_FIND);
952 if (s != NULL)
953 return (s->s_alias);
954 return (NULL);
955}
956
957
958/*
31f1ab13 959** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
713c523f
EA
960*/
961
962void
963stab_map_store(map, lhs, rhs)
964 register MAP *map;
965 char *lhs;
966 char *rhs;
967{
968 register STAB *s;
969
970 s = stab(lhs, ST_ALIAS, ST_ENTER);
971 s->s_alias = newstr(rhs);
972}
973
974
975/*
31f1ab13
EA
976** STAB_MAP_OPEN -- initialize (reads data file)
977**
978** This is a wierd case -- it is only intended as a fallback for
979** aliases. For this reason, opens for write (only during a
980** "newaliases") always fails, and opens for read open the
981** actual underlying text file instead of the database.
713c523f
EA
982*/
983
984bool
985stab_map_open(map, mode)
986 register MAP *map;
987 int mode;
988{
36b09297 989 if (tTd(38, 2))
713c523f
EA
990 printf("stab_map_open(%s)\n", map->map_file);
991
992 if (mode != O_RDONLY)
31f1ab13
EA
993 {
994 errno = ENODEV;
713c523f 995 return FALSE;
31f1ab13 996 }
713c523f 997
713c523f
EA
998 return TRUE;
999}
1000
1001
1002/*
31f1ab13 1003** STAB_MAP_CLOSE -- close symbol table (???)
713c523f
EA
1004*/
1005
1006void
1007stab_map_close(map)
1008 MAP *map;
1009{
1010 /* ignore it */
1011}
1012\f/*
1013** Implicit Modules
1014**
1015** Tries several types. For back compatibility of aliases.
1016*/
1017
1018
1019/*
31f1ab13 1020** IMPL_MAP_LOOKUP -- lookup in best open database
713c523f
EA
1021*/
1022
1023char *
1024impl_map_lookup(map, name, av, pstat)
1025 MAP *map;
1026 char *name;
1027 char **av;
1028 int *pstat;
1029{
36b09297 1030 if (tTd(38, 20))
713c523f
EA
1031 printf("impl_map_lookup(%s)\n", name);
1032
1033#ifdef NEWDB
31f1ab13 1034 if (bitset(MF_IMPL_HASH, map->map_mflags))
713c523f
EA
1035 return db_map_lookup(map, name, av, pstat);
1036#endif
1037#ifdef NDBM
31f1ab13 1038 if (bitset(MF_IMPL_NDBM, map->map_mflags))
713c523f
EA
1039 return ndbm_map_lookup(map, name, av, pstat);
1040#endif
1041 return stab_map_lookup(map, name, av, pstat);
1042}
1043
1044/*
31f1ab13 1045** IMPL_MAP_STORE -- store in open databases
713c523f
EA
1046*/
1047
1048void
1049impl_map_store(map, lhs, rhs)
1050 MAP *map;
1051 char *lhs;
1052 char *rhs;
1053{
1054#ifdef NEWDB
31f1ab13 1055 if (bitset(MF_IMPL_HASH, map->map_mflags))
713c523f
EA
1056 db_map_store(map, lhs, rhs);
1057#endif
1058#ifdef NDBM
31f1ab13 1059 if (bitset(MF_IMPL_NDBM, map->map_mflags))
713c523f
EA
1060 ndbm_map_store(map, lhs, rhs);
1061#endif
1062 stab_map_store(map, lhs, rhs);
1063}
1064
1065/*
1066** IMPL_MAP_OPEN -- implicit database open
1067*/
1068
1069bool
1070impl_map_open(map, mode)
1071 MAP *map;
1072 int mode;
1073{
1074 struct stat stb;
1075
36b09297 1076 if (tTd(38, 2))
713c523f
EA
1077 printf("impl_map_open(%s)\n", map->map_file);
1078
1079 if (stat(map->map_file, &stb) < 0)
1080 {
1081 /* no alias file at all */
1082 return FALSE;
1083 }
1084
1085#ifdef NEWDB
31f1ab13 1086 map->map_mflags |= MF_IMPL_HASH;
713c523f
EA
1087 if (hash_map_open(map, mode))
1088 {
31f1ab13 1089#if defined(NDBM) && defined(YPCOMPAT)
08979aed 1090 if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
31f1ab13
EA
1091#endif
1092 return TRUE;
713c523f 1093 }
31f1ab13
EA
1094 else
1095 map->map_mflags &= ~MF_IMPL_HASH;
713c523f
EA
1096#endif
1097#ifdef NDBM
31f1ab13 1098 map->map_mflags |= MF_IMPL_NDBM;
713c523f
EA
1099 if (ndbm_map_open(map, mode))
1100 {
713c523f
EA
1101 return TRUE;
1102 }
31f1ab13
EA
1103 else
1104 map->map_mflags &= ~MF_IMPL_NDBM;
713c523f
EA
1105#endif
1106
31f1ab13 1107#if !defined(NEWDB) && !defined(NDBM)
713c523f
EA
1108 if (Verbose)
1109 message("WARNING: cannot open alias database %s", map->map_file);
31f1ab13 1110#endif
713c523f 1111
31f1ab13 1112 return stab_map_open(map, mode);
713c523f
EA
1113}
1114
31f1ab13 1115
713c523f 1116/*
31f1ab13 1117** IMPL_MAP_CLOSE -- close any open database(s)
713c523f
EA
1118*/
1119
1120void
31f1ab13 1121impl_map_close(map)
713c523f 1122 MAP *map;
713c523f
EA
1123{
1124#ifdef NEWDB
31f1ab13 1125 if (bitset(MF_IMPL_HASH, map->map_mflags))
713c523f 1126 {
31f1ab13
EA
1127 db_map_close(map);
1128 map->map_mflags &= ~MF_IMPL_HASH;
713c523f
EA
1129 }
1130#endif
1131
1132#ifdef NDBM
31f1ab13 1133 if (bitset(MF_IMPL_NDBM, map->map_mflags))
713c523f 1134 {
31f1ab13
EA
1135 ndbm_map_close(map);
1136 map->map_mflags &= ~MF_IMPL_NDBM;
713c523f
EA
1137 }
1138#endif
713c523f 1139}
31f1ab13
EA
1140\f/*
1141** NULL stubs
713c523f
EA
1142*/
1143
31f1ab13
EA
1144bool
1145null_map_open(map, mode)
713c523f 1146 MAP *map;
31f1ab13 1147 int mode;
713c523f 1148{
31f1ab13 1149 return TRUE;
713c523f 1150}
713c523f 1151
31f1ab13
EA
1152void
1153null_map_close(map)
1154 MAP *map;
713c523f 1155{
31f1ab13
EA
1156 return;
1157}
713c523f 1158
31f1ab13
EA
1159void
1160null_map_store(map, key, val)
1161 MAP *map;
1162 char *key;
1163 char *val;
713c523f 1164{
31f1ab13 1165 return;
4cb3af58 1166}