add debugging to putoutmsg
[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
476a894f 10static char sccsid[] = "@(#)map.c 8.6 (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;
e6cb9fc4 224 for (avp = av; --c >= '0' && *avp != NULL; avp++)
713c523f
EA
225 continue;
226 if (*avp == NULL)
227 continue;
228 len += strlen(*avp);
229 }
230 }
231 if (map->map_app != NULL)
232 len += strlen(map->map_app);
67d3f5c1 233 if (rwb->rwb_len < ++len)
713c523f
EA
234 {
235 /* need to malloc additional space */
67d3f5c1
EA
236 rwb->rwb_len = len;
237 if (rwb->rwb_buf != NULL)
238 free(rwb->rwb_buf);
239 rwb->rwb_buf = xalloc(rwb->rwb_len);
713c523f
EA
240 }
241
67d3f5c1 242 bp = rwb->rwb_buf;
713c523f
EA
243 if (av == NULL)
244 {
245 bcopy(s, bp, slen);
246 bp += slen;
247 }
248 else
4cb3af58 249 {
713c523f 250 while (--slen >= 0 && (c = *s++) != '\0')
4cb3af58 251 {
713c523f
EA
252 if (c != '%')
253 {
4cb3af58 254 pushc:
4cb3af58 255 *bp++ = c;
713c523f
EA
256 continue;
257 }
258 if (--slen < 0 || (c = *s++) == '\0')
259 c = '%';
260 if (c == '%')
261 goto pushc;
262 if (!(isascii(c) && isdigit(c)))
263 {
264 *bp++ = '%';
265 goto pushc;
266 }
e6cb9fc4 267 for (avp = av; --c >= '0' && *avp != NULL; avp++)
713c523f
EA
268 continue;
269 if (*avp == NULL)
270 continue;
271
272 /* transliterate argument into output string */
273 for (ap = *avp; (c = *ap++) != '\0'; )
4cb3af58
EA
274 *bp++ = c;
275 }
276 }
713c523f
EA
277 if (map->map_app != NULL)
278 strcpy(bp, map->map_app);
279 else
280 *bp = '\0';
36b09297 281 if (tTd(39, 1))
67d3f5c1
EA
282 printf("map_rewrite => %s\n", rwb->rwb_buf);
283 return rwb->rwb_buf;
713c523f
EA
284}
285\f/*
36b09297
EA
286** INITMAPS -- initialize for aliasing
287**
288** Parameters:
289** rebuild -- if TRUE, this rebuilds the cached versions.
290** e -- current envelope.
291**
292** Returns:
293** none.
294**
295** Side Effects:
296** initializes aliases:
297** if NDBM: opens the database.
298** if ~NDBM: reads the aliases into the symbol table.
299*/
300
301initmaps(rebuild, e)
302 bool rebuild;
303 register ENVELOPE *e;
304{
305 extern void map_init();
306
307 CurEnv = e;
308 stabapply(map_init, rebuild);
309}
310
311void
312map_init(s, rebuild)
313 register STAB *s;
314 int rebuild;
315{
316 register MAP *map;
317
318 /* has to be a map */
319 if (s->s_type != ST_MAP)
320 return;
321
322 map = &s->s_map;
323 if (!bitset(MF_VALID, map->map_mflags))
324 return;
325
326 if (tTd(38, 2))
327 printf("map_init(%s:%s)\n",
328 map->map_class->map_cname, map->map_file);
329
330 /* if already open, close it (for nested open) */
331 if (bitset(MF_OPEN, map->map_mflags))
332 {
333 map->map_class->map_close(map);
334 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
335 }
336
337 if (rebuild)
338 {
d71eb2f5
EA
339 if (bitset(MF_ALIAS, map->map_mflags) &&
340 bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
36b09297
EA
341 rebuildaliases(map, FALSE);
342 }
343 else
344 {
345 if (map->map_class->map_open(map, O_RDONLY))
346 {
347 if (tTd(38, 4))
348 printf("%s:%s: valid\n",
349 map->map_class->map_cname,
350 map->map_file);
351 map->map_mflags |= MF_OPEN;
352 }
353 else if (tTd(38, 4))
354 printf("%s:%s: invalid: %s\n",
355 map->map_class->map_cname,
356 map->map_file,
357 errstring(errno));
358 }
359}
360\f/*
713c523f
EA
361** NDBM modules
362*/
363
364#ifdef NDBM
365
366/*
367** DBM_MAP_OPEN -- DBM-style map open
368*/
369
370bool
371ndbm_map_open(map, mode)
372 MAP *map;
373 int mode;
374{
375 DBM *dbm;
376
36b09297 377 if (tTd(38, 2))
713c523f
EA
378 printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
379
31f1ab13
EA
380 if (mode == O_RDWR)
381 mode |= O_CREAT|O_TRUNC;
382
713c523f
EA
383 /* open the database */
384 dbm = dbm_open(map->map_file, mode, DBMMODE);
385 if (dbm == NULL)
386 {
31f1ab13 387 if (!bitset(MF_OPTIONAL, map->map_mflags))
713c523f
EA
388 syserr("Cannot open DBM database %s", map->map_file);
389 return FALSE;
390 }
391 map->map_db1 = (void *) dbm;
31f1ab13 392 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
7b1e23ea 393 aliaswait(map, ".pag");
713c523f
EA
394 return TRUE;
395}
396
397
398/*
399** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
400*/
401
402char *
403ndbm_map_lookup(map, name, av, statp)
404 MAP *map;
405 char *name;
406 char **av;
407 int *statp;
408{
409 datum key, val;
410 char keybuf[MAXNAME + 1];
411
36b09297 412 if (tTd(38, 20))
713c523f
EA
413 printf("ndbm_map_lookup(%s)\n", name);
414
415 key.dptr = name;
416 key.dsize = strlen(name);
31f1ab13 417 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
713c523f
EA
418 {
419 if (key.dsize > sizeof keybuf - 1)
420 key.dsize = sizeof keybuf - 1;
421 bcopy(key.dptr, keybuf, key.dsize + 1);
422 makelower(keybuf);
423 key.dptr = keybuf;
424 }
713c523f 425 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
8e5c6745
EA
426 val.dptr = NULL;
427 if (bitset(MF_TRY0NULL, map->map_mflags))
428 {
429 val = dbm_fetch((DBM *) map->map_db1, key);
430 if (val.dptr != NULL)
431 map->map_mflags &= ~MF_TRY1NULL;
432 }
433 if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
434 {
435 key.dsize++;
436 val = dbm_fetch((DBM *) map->map_db1, key);
437 if (val.dptr != NULL)
438 map->map_mflags &= ~MF_TRY0NULL;
439 }
713c523f
EA
440 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
441 if (val.dptr == NULL)
442 return NULL;
31f1ab13 443 if (bitset(MF_MATCHONLY, map->map_mflags))
8e5c6745
EA
444 return map_rewrite(map, name, strlen(name), NULL);
445 else
446 return map_rewrite(map, val.dptr, val.dsize, av);
713c523f
EA
447}
448
449
450/*
451** DBM_MAP_STORE -- store a datum in the database
452*/
453
454void
455ndbm_map_store(map, lhs, rhs)
456 register MAP *map;
457 char *lhs;
458 char *rhs;
459{
460 datum key;
461 datum data;
462 int stat;
463
36b09297 464 if (tTd(38, 12))
713c523f
EA
465 printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
466
467 key.dsize = strlen(lhs);
468 key.dptr = lhs;
469
470 data.dsize = strlen(rhs);
471 data.dptr = rhs;
472
31f1ab13 473 if (bitset(MF_INCLNULL, map->map_mflags))
713c523f
EA
474 {
475 key.dsize++;
476 data.dsize++;
477 }
478
479 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
480 if (stat > 0)
481 {
482 usrerr("050 Warning: duplicate alias name %s", lhs);
483 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
484 }
485 if (stat != 0)
486 syserr("readaliases: dbm put (%s)", lhs);
487}
488
489
490/*
31f1ab13 491** NDBM_MAP_CLOSE -- close the database
713c523f
EA
492*/
493
494void
495ndbm_map_close(map)
496 register MAP *map;
497{
31f1ab13 498 if (bitset(MF_WRITABLE, map->map_mflags))
713c523f
EA
499 {
500#ifdef YPCOMPAT
476a894f 501 bool inclnull;
713c523f
EA
502 char buf[200];
503
476a894f
EA
504 inclnull = bitset(MF_INCLNULL, map->map_mflags);
505 map->map_mflags &= ~MF_INCLNULL;
506
713c523f
EA
507 (void) sprintf(buf, "%010ld", curtime());
508 ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
509
510 (void) myhostname(buf, sizeof buf);
511 ndbm_map_store(map, "YP_MASTER_NAME", buf);
476a894f
EA
512
513 if (inclnull)
514 map->map_mflags |= MF_INCLNULL;
713c523f
EA
515#endif
516
517 /* write out the distinguished alias */
518 ndbm_map_store(map, "@", "@");
519 }
520 dbm_close((DBM *) map->map_db1);
521}
522
523#endif
524\f/*
8f43ee9e 525** NEWDB (Hash and BTree) Modules
713c523f
EA
526*/
527
528#ifdef NEWDB
529
530/*
8f43ee9e
EA
531** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
532**
533** These do rather bizarre locking. If you can lock on open,
534** do that to avoid the condition of opening a database that
535** is being rebuilt. If you don't, we'll try to fake it, but
536** there will be a race condition. If opening for read-only,
537** we immediately release the lock to avoid freezing things up.
538** We really ought to hold the lock, but guarantee that we won't
539** be pokey about it. That's hard to do.
713c523f
EA
540*/
541
542bool
543bt_map_open(map, mode)
544 MAP *map;
545 int mode;
546{
547 DB *db;
df88f2ef 548 int i;
8f43ee9e 549 int omode;
713c523f
EA
550 char buf[MAXNAME];
551
36b09297 552 if (tTd(38, 2))
713c523f
EA
553 printf("bt_map_open(%s, %d)\n", map->map_file, mode);
554
8f43ee9e
EA
555 omode = mode;
556 if (omode == O_RDWR)
557 {
558 omode |= O_CREAT|O_TRUNC;
39270cfd 559#if defined(O_EXLOCK) && defined(HASFLOCK)
8f43ee9e
EA
560 omode |= O_EXLOCK;
561# if !defined(OLD_NEWDB)
562 }
563 else
564 {
565 omode |= O_SHLOCK;
566# endif
567#endif
568 }
31f1ab13 569
df88f2ef
EA
570 (void) strcpy(buf, map->map_file);
571 i = strlen(buf);
572 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
573 (void) strcat(buf, ".db");
8f43ee9e 574 db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
713c523f
EA
575 if (db == NULL)
576 {
31f1ab13 577 if (!bitset(MF_OPTIONAL, map->map_mflags))
713c523f
EA
578 syserr("Cannot open BTREE database %s", map->map_file);
579 return FALSE;
580 }
39270cfd 581#if !defined(OLD_NEWDB) && defined(HASFLOCK)
8f43ee9e
EA
582# if !defined(O_EXLOCK)
583 if (mode == O_RDWR)
584 (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
585# else
586 if (mode == O_RDONLY)
587 (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
588# endif
589#endif
b215b035
EA
590
591 /* try to make sure that at least the database header is on disk */
592 if (mode == O_RDWR)
593 (void) db->sync(db, 0);
594
713c523f 595 map->map_db2 = (void *) db;
31f1ab13
EA
596 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
597 aliaswait(map, ".db");
713c523f
EA
598 return TRUE;
599}
600
601
602/*
603** HASH_MAP_INIT -- HASH-style map initialization
604*/
605
606bool
607hash_map_open(map, mode)
608 MAP *map;
609 int mode;
610{
611 DB *db;
df88f2ef 612 int i;
8f43ee9e 613 int omode;
713c523f
EA
614 char buf[MAXNAME];
615
36b09297 616 if (tTd(38, 2))
713c523f
EA
617 printf("hash_map_open(%s, %d)\n", map->map_file, mode);
618
8f43ee9e
EA
619 omode = mode;
620 if (omode == O_RDWR)
621 {
622 omode |= O_CREAT|O_TRUNC;
39270cfd 623#if defined(O_EXLOCK) && defined(HASFLOCK)
8f43ee9e
EA
624 omode |= O_EXLOCK;
625# if !defined(OLD_NEWDB)
626 }
627 else
628 {
629 omode |= O_SHLOCK;
630# endif
631#endif
632 }
31f1ab13 633
df88f2ef
EA
634 (void) strcpy(buf, map->map_file);
635 i = strlen(buf);
636 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
637 (void) strcat(buf, ".db");
8f43ee9e 638 db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
713c523f
EA
639 if (db == NULL)
640 {
31f1ab13 641 if (!bitset(MF_OPTIONAL, map->map_mflags))
713c523f
EA
642 syserr("Cannot open HASH database %s", map->map_file);
643 return FALSE;
644 }
39270cfd 645#if !defined(OLD_NEWDB) && defined(HASFLOCK)
8f43ee9e
EA
646# if !defined(O_EXLOCK)
647 if (mode == O_RDWR)
648 (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
649# else
650 if (mode == O_RDONLY)
651 (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
652# endif
653#endif
b215b035
EA
654
655 /* try to make sure that at least the database header is on disk */
656 if (mode == O_RDWR)
657 (void) db->sync(db, 0);
658
713c523f 659 map->map_db2 = (void *) db;
31f1ab13
EA
660 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
661 aliaswait(map, ".db");
713c523f
EA
662 return TRUE;
663}
664
665
666/*
667** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
668*/
669
670char *
671db_map_lookup(map, name, av, statp)
672 MAP *map;
673 char *name;
674 char **av;
675 int *statp;
676{
677 DBT key, val;
31ffabe6
EA
678 register DB *db = (DB *) map->map_db2;
679 int st;
680 int saveerrno;
713c523f
EA
681 char keybuf[MAXNAME + 1];
682
36b09297 683 if (tTd(38, 20))
713c523f
EA
684 printf("db_map_lookup(%s)\n", name);
685
686 key.size = strlen(name);
687 if (key.size > sizeof keybuf - 1)
688 key.size = sizeof keybuf - 1;
689 key.data = keybuf;
690 bcopy(name, keybuf, key.size + 1);
31f1ab13 691 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
713c523f 692 makelower(keybuf);
31ffabe6
EA
693#ifndef OLD_NEWDB
694 (void) lockfile(db->fd(db), map->map_file, LOCK_SH);
695#endif
8e5c6745
EA
696 st = 1;
697 if (bitset(MF_TRY0NULL, map->map_mflags))
698 {
699 st = db->get(db, &key, &val, 0);
700 if (st == 0)
701 map->map_mflags &= ~MF_TRY1NULL;
702 }
703 if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
704 {
705 key.size++;
706 st = db->get(db, &key, &val, 0);
707 if (st == 0)
708 map->map_mflags &= ~MF_TRY0NULL;
709 }
31ffabe6
EA
710 saveerrno = errno;
711#ifndef OLD_NEWDB
712 (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
713#endif
714 if (st != 0)
715 {
716 errno = saveerrno;
717 if (st < 0)
718 syserr("db_map_lookup: get (%s)", name);
713c523f 719 return NULL;
31ffabe6 720 }
31f1ab13 721 if (bitset(MF_MATCHONLY, map->map_mflags))
8e5c6745
EA
722 return map_rewrite(map, name, strlen(name), NULL);
723 else
724 return map_rewrite(map, val.data, val.size, av);
713c523f
EA
725}
726
727
728/*
729** DB_MAP_STORE -- store a datum in the NEWDB database
730*/
731
732void
733db_map_store(map, lhs, rhs)
734 register MAP *map;
735 char *lhs;
736 char *rhs;
737{
738 int stat;
739 DBT key;
740 DBT data;
741 register DB *db = map->map_db2;
742
36b09297 743 if (tTd(38, 20))
713c523f
EA
744 printf("db_map_store(%s, %s)\n", lhs, rhs);
745
746 key.size = strlen(lhs);
747 key.data = lhs;
748
749 data.size = strlen(rhs);
750 data.data = rhs;
751
31f1ab13 752 if (bitset(MF_INCLNULL, map->map_mflags))
713c523f
EA
753 {
754 key.size++;
755 data.size++;
756 }
757
758 stat = db->put(db, &key, &data, R_NOOVERWRITE);
759 if (stat > 0)
760 {
761 usrerr("050 Warning: duplicate alias name %s", lhs);
762 stat = db->put(db, &key, &data, 0);
763 }
764 if (stat != 0)
765 syserr("readaliases: db put (%s)", lhs);
766}
767
768
713c523f
EA
769/*
770** DB_MAP_CLOSE -- add distinguished entries and close the database
771*/
772
773void
774db_map_close(map)
775 MAP *map;
776{
777 register DB *db = map->map_db2;
778
36b09297 779 if (tTd(38, 9))
31f1ab13 780 printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
713c523f 781
31f1ab13 782 if (bitset(MF_WRITABLE, map->map_mflags))
713c523f
EA
783 {
784 /* write out the distinguished alias */
785 db_map_store(map, "@", "@");
786 }
787
788 if (db->close(db) != 0)
789 syserr("readaliases: db close failure");
790}
791
792#endif
793\f/*
794** NIS Modules
795*/
796
797# ifdef NIS
798
799/*
800** NIS_MAP_OPEN -- open DBM map
801*/
802
803bool
804nis_map_open(map, mode)
805 MAP *map;
806 int mode;
807{
808 int yperr;
94b8a28b
EA
809 register char *p;
810 auto char *vp;
811 auto int vsize;
713c523f
EA
812 char *master;
813
36b09297 814 if (tTd(38, 2))
713c523f
EA
815 printf("nis_map_open(%s)\n", map->map_file);
816
31f1ab13
EA
817 if (mode != O_RDONLY)
818 {
819 errno = ENODEV;
820 return FALSE;
821 }
822
713c523f
EA
823 p = strchr(map->map_file, '@');
824 if (p != NULL)
825 {
826 *p++ = '\0';
827 if (*p != '\0')
828 map->map_domain = p;
829 }
94b8a28b 830
713c523f
EA
831 if (map->map_domain == NULL)
832 yp_get_default_domain(&map->map_domain);
833
834 if (*map->map_file == '\0')
835 map->map_file = "mail.aliases";
836
94b8a28b 837 /* check to see if this map actually exists */
713c523f
EA
838 yperr = yp_match(map->map_domain, map->map_file, "@", 1,
839 &vp, &vsize);
36b09297 840 if (tTd(38, 10))
713c523f
EA
841 printf("nis_map_open: yp_match(%s, %s) => %s\n",
842 map->map_domain, map->map_file, yperr_string(yperr));
843 if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
844 return TRUE;
94b8a28b
EA
845
846 if (!bitset(MF_OPTIONAL, map->map_mflags))
847 syserr("Cannot bind to domain %s: %s", map->map_domain,
848 yperr_string(yperr));
849
713c523f
EA
850 return FALSE;
851}
852
853
854/*
855** NIS_MAP_LOOKUP -- look up a datum in a NIS map
856*/
857
858char *
859nis_map_lookup(map, name, av, statp)
860 MAP *map;
861 char *name;
862 char **av;
863 int *statp;
864{
865 char *vp;
866 auto int vsize;
867 int buflen;
94b8a28b 868 int yperr;
713c523f
EA
869 char keybuf[MAXNAME + 1];
870
36b09297 871 if (tTd(38, 20))
713c523f
EA
872 printf("nis_map_lookup(%s)\n", name);
873
874 buflen = strlen(name);
875 if (buflen > sizeof keybuf - 1)
876 buflen = sizeof keybuf - 1;
877 bcopy(name, keybuf, buflen + 1);
31f1ab13 878 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
713c523f 879 makelower(keybuf);
8e5c6745
EA
880 yperr = YPERR_KEY;
881 if (bitset(MF_TRY0NULL, map->map_mflags))
882 {
883 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
884 &vp, &vsize);
885 if (yperr == 0)
886 map->map_mflags &= ~MF_TRY1NULL;
887 }
888 if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
889 {
713c523f 890 buflen++;
8e5c6745
EA
891 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
892 &vp, &vsize);
893 if (yperr == 0)
894 map->map_mflags &= ~MF_TRY0NULL;
895 }
713c523f
EA
896 if (yperr != 0)
897 {
898 if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
94b8a28b 899 map->map_mflags &= ~(MF_VALID|MF_OPEN);
713c523f
EA
900 return NULL;
901 }
31f1ab13 902 if (bitset(MF_MATCHONLY, map->map_mflags))
8e5c6745
EA
903 return map_rewrite(map, name, strlen(name), NULL);
904 else
905 return map_rewrite(map, vp, vsize, av);
713c523f
EA
906}
907
908
909/*
31f1ab13 910** NIS_MAP_STORE
713c523f
EA
911*/
912
913void
914nis_map_store(map, lhs, rhs)
915 MAP *map;
916 char *lhs;
917 char *rhs;
918{
919 /* nothing */
920}
921
713c523f
EA
922
923/*
31f1ab13 924** NIS_MAP_CLOSE
713c523f
EA
925*/
926
927void
928nis_map_close(map)
929 MAP *map;
930{
931 /* nothing */
932}
933
934#endif /* NIS */
935\f/*
936** STAB (Symbol Table) Modules
937*/
938
939
940/*
31f1ab13 941** STAB_MAP_LOOKUP -- look up alias in symbol table
713c523f
EA
942*/
943
944char *
a3934270 945stab_map_lookup(map, name, av, pstat)
713c523f
EA
946 register MAP *map;
947 char *name;
a3934270
EA
948 char **av;
949 int *pstat;
713c523f
EA
950{
951 register STAB *s;
952
36b09297 953 if (tTd(38, 20))
713c523f
EA
954 printf("stab_lookup(%s)\n", name);
955
956 s = stab(name, ST_ALIAS, ST_FIND);
957 if (s != NULL)
958 return (s->s_alias);
959 return (NULL);
960}
961
962
963/*
31f1ab13 964** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
713c523f
EA
965*/
966
967void
968stab_map_store(map, lhs, rhs)
969 register MAP *map;
970 char *lhs;
971 char *rhs;
972{
973 register STAB *s;
974
975 s = stab(lhs, ST_ALIAS, ST_ENTER);
976 s->s_alias = newstr(rhs);
977}
978
979
980/*
31f1ab13
EA
981** STAB_MAP_OPEN -- initialize (reads data file)
982**
983** This is a wierd case -- it is only intended as a fallback for
984** aliases. For this reason, opens for write (only during a
985** "newaliases") always fails, and opens for read open the
986** actual underlying text file instead of the database.
713c523f
EA
987*/
988
989bool
990stab_map_open(map, mode)
991 register MAP *map;
992 int mode;
993{
1fe2880b
EA
994 FILE *af;
995
36b09297 996 if (tTd(38, 2))
713c523f
EA
997 printf("stab_map_open(%s)\n", map->map_file);
998
999 if (mode != O_RDONLY)
31f1ab13
EA
1000 {
1001 errno = ENODEV;
713c523f 1002 return FALSE;
31f1ab13 1003 }
713c523f 1004
1fe2880b
EA
1005 af = fopen(map->map_file, "r");
1006 if (af == NULL)
1007 return FALSE;
1008 readaliases(map, af, TRUE);
1009 fclose(af);
1010
713c523f
EA
1011 return TRUE;
1012}
1013
1014
1015/*
31f1ab13 1016** STAB_MAP_CLOSE -- close symbol table (???)
713c523f
EA
1017*/
1018
1019void
1020stab_map_close(map)
1021 MAP *map;
1022{
1023 /* ignore it */
1024}
1025\f/*
1026** Implicit Modules
1027**
1028** Tries several types. For back compatibility of aliases.
1029*/
1030
1031
1032/*
31f1ab13 1033** IMPL_MAP_LOOKUP -- lookup in best open database
713c523f
EA
1034*/
1035
1036char *
1037impl_map_lookup(map, name, av, pstat)
1038 MAP *map;
1039 char *name;
1040 char **av;
1041 int *pstat;
1042{
36b09297 1043 if (tTd(38, 20))
713c523f
EA
1044 printf("impl_map_lookup(%s)\n", name);
1045
1046#ifdef NEWDB
31f1ab13 1047 if (bitset(MF_IMPL_HASH, map->map_mflags))
713c523f
EA
1048 return db_map_lookup(map, name, av, pstat);
1049#endif
1050#ifdef NDBM
31f1ab13 1051 if (bitset(MF_IMPL_NDBM, map->map_mflags))
713c523f
EA
1052 return ndbm_map_lookup(map, name, av, pstat);
1053#endif
1054 return stab_map_lookup(map, name, av, pstat);
1055}
1056
1057/*
31f1ab13 1058** IMPL_MAP_STORE -- store in open databases
713c523f
EA
1059*/
1060
1061void
1062impl_map_store(map, lhs, rhs)
1063 MAP *map;
1064 char *lhs;
1065 char *rhs;
1066{
1067#ifdef NEWDB
31f1ab13 1068 if (bitset(MF_IMPL_HASH, map->map_mflags))
713c523f
EA
1069 db_map_store(map, lhs, rhs);
1070#endif
1071#ifdef NDBM
31f1ab13 1072 if (bitset(MF_IMPL_NDBM, map->map_mflags))
713c523f
EA
1073 ndbm_map_store(map, lhs, rhs);
1074#endif
1075 stab_map_store(map, lhs, rhs);
1076}
1077
1078/*
1079** IMPL_MAP_OPEN -- implicit database open
1080*/
1081
1082bool
1083impl_map_open(map, mode)
1084 MAP *map;
1085 int mode;
1086{
1087 struct stat stb;
1088
36b09297 1089 if (tTd(38, 2))
713c523f
EA
1090 printf("impl_map_open(%s)\n", map->map_file);
1091
1092 if (stat(map->map_file, &stb) < 0)
1093 {
1094 /* no alias file at all */
1095 return FALSE;
1096 }
1097
1098#ifdef NEWDB
31f1ab13 1099 map->map_mflags |= MF_IMPL_HASH;
713c523f
EA
1100 if (hash_map_open(map, mode))
1101 {
31f1ab13 1102#if defined(NDBM) && defined(YPCOMPAT)
08979aed 1103 if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
31f1ab13
EA
1104#endif
1105 return TRUE;
713c523f 1106 }
31f1ab13
EA
1107 else
1108 map->map_mflags &= ~MF_IMPL_HASH;
713c523f
EA
1109#endif
1110#ifdef NDBM
31f1ab13 1111 map->map_mflags |= MF_IMPL_NDBM;
713c523f
EA
1112 if (ndbm_map_open(map, mode))
1113 {
713c523f
EA
1114 return TRUE;
1115 }
31f1ab13
EA
1116 else
1117 map->map_mflags &= ~MF_IMPL_NDBM;
713c523f
EA
1118#endif
1119
31f1ab13 1120#if !defined(NEWDB) && !defined(NDBM)
713c523f
EA
1121 if (Verbose)
1122 message("WARNING: cannot open alias database %s", map->map_file);
31f1ab13 1123#endif
713c523f 1124
31f1ab13 1125 return stab_map_open(map, mode);
713c523f
EA
1126}
1127
31f1ab13 1128
713c523f 1129/*
31f1ab13 1130** IMPL_MAP_CLOSE -- close any open database(s)
713c523f
EA
1131*/
1132
1133void
31f1ab13 1134impl_map_close(map)
713c523f 1135 MAP *map;
713c523f
EA
1136{
1137#ifdef NEWDB
31f1ab13 1138 if (bitset(MF_IMPL_HASH, map->map_mflags))
713c523f 1139 {
31f1ab13
EA
1140 db_map_close(map);
1141 map->map_mflags &= ~MF_IMPL_HASH;
713c523f
EA
1142 }
1143#endif
1144
1145#ifdef NDBM
31f1ab13 1146 if (bitset(MF_IMPL_NDBM, map->map_mflags))
713c523f 1147 {
31f1ab13
EA
1148 ndbm_map_close(map);
1149 map->map_mflags &= ~MF_IMPL_NDBM;
713c523f
EA
1150 }
1151#endif
713c523f 1152}
31f1ab13
EA
1153\f/*
1154** NULL stubs
713c523f
EA
1155*/
1156
31f1ab13
EA
1157bool
1158null_map_open(map, mode)
713c523f 1159 MAP *map;
31f1ab13 1160 int mode;
713c523f 1161{
31f1ab13 1162 return TRUE;
713c523f 1163}
713c523f 1164
31f1ab13
EA
1165void
1166null_map_close(map)
1167 MAP *map;
713c523f 1168{
31f1ab13
EA
1169 return;
1170}
713c523f 1171
31f1ab13
EA
1172void
1173null_map_store(map, key, val)
1174 MAP *map;
1175 char *key;
1176 char *val;
713c523f 1177{
31f1ab13 1178 return;
4cb3af58 1179}