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