This commit was generated by cvs2svn to track changes on a CVS vendor
[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
d747e748 36static char sccsid[] = "@(#)map.c 8.17 (Berkeley) 10/15/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
d747e748
JH
88
89extern bool aliaswait __P((MAP *, char *, int));
6f14531a
RG
90\f/*
91** MAP_PARSEARGS -- parse config line arguments for database lookup
92**
93** This is a generic version of the map_parse method.
94**
95** Parameters:
96** map -- the map being initialized.
97** ap -- a pointer to the args on the config line.
98**
99** Returns:
100** TRUE -- if everything parsed OK.
101** FALSE -- otherwise.
102**
103** Side Effects:
104** null terminates the filename; stores it in map
105*/
106
107bool
108map_parseargs(map, ap)
109 MAP *map;
110 char *ap;
111{
112 register char *p = ap;
113
3a363396 114 map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
6f14531a
RG
115 for (;;)
116 {
117 while (isascii(*p) && isspace(*p))
118 p++;
119 if (*p != '-')
120 break;
121 switch (*++p)
122 {
123 case 'N':
124 map->map_mflags |= MF_INCLNULL;
3a363396
NW
125 map->map_mflags &= ~MF_TRY0NULL;
126 break;
127
128 case 'O':
129 map->map_mflags &= ~MF_TRY1NULL;
6f14531a
RG
130 break;
131
132 case 'o':
133 map->map_mflags |= MF_OPTIONAL;
134 break;
135
136 case 'f':
137 map->map_mflags |= MF_NOFOLDCASE;
138 break;
139
140 case 'm':
141 map->map_mflags |= MF_MATCHONLY;
142 break;
143
144 case 'a':
145 map->map_app = ++p;
146 break;
147 }
148 while (*p != '\0' && !(isascii(*p) && isspace(*p)))
149 p++;
150 if (*p != '\0')
151 *p++ = '\0';
152 }
153 if (map->map_app != NULL)
154 map->map_app = newstr(map->map_app);
155
156 if (*p != '\0')
157 {
158 map->map_file = p;
159 while (*p != '\0' && !(isascii(*p) && isspace(*p)))
160 p++;
161 if (*p != '\0')
162 *p++ = '\0';
163 map->map_file = newstr(map->map_file);
164 }
165
166 while (*p != '\0' && isascii(*p) && isspace(*p))
167 p++;
168 if (*p != '\0')
169 map->map_rebuild = newstr(p);
170
171 if (map->map_file == NULL)
172 {
173 syserr("No file name for %s map %s",
174 map->map_class->map_cname, map->map_mname);
175 return FALSE;
176 }
177 return TRUE;
178}
179\f/*
180** MAP_REWRITE -- rewrite a database key, interpolating %n indications.
181**
182** It also adds the map_app string. It can be used as a utility
183** in the map_lookup method.
184**
185** Parameters:
186** map -- the map that causes this.
187** s -- the string to rewrite, NOT necessarily null terminated.
188** slen -- the length of s.
189** av -- arguments to interpolate into buf.
190**
191** Returns:
192** Pointer to rewritten result.
193**
194** Side Effects:
195** none.
196*/
197
198struct rwbuf
199{
200 int rwb_len; /* size of buffer */
201 char *rwb_buf; /* ptr to buffer */
202};
203
204struct rwbuf RwBufs[2]; /* buffers for rewriting output */
205
206char *
207map_rewrite(map, s, slen, av)
208 register MAP *map;
209 register char *s;
210 int slen;
211 char **av;
212{
213 register char *bp;
214 register char c;
215 char **avp;
216 register char *ap;
217 register struct rwbuf *rwb;
218 int i;
219 int len;
220
221 if (tTd(39, 1))
222 {
223 printf("map_rewrite(%.*s), av =", slen, s);
224 if (av == NULL)
225 printf(" (nullv)");
226 else
227 {
228 for (avp = av; *avp != NULL; avp++)
229 printf("\n\t%s", *avp);
230 }
231 printf("\n");
232 }
233
234 rwb = RwBufs;
235 if (av == NULL)
236 rwb++;
237
238 /* count expected size of output (can safely overestimate) */
239 i = len = slen;
240 if (av != NULL)
241 {
242 bp = s;
243 for (i = slen; --i >= 0 && (c = *bp++) != 0; )
244 {
245 if (c != '%')
246 continue;
247 if (--i < 0)
248 break;
249 c = *bp++;
250 if (!(isascii(c) && isdigit(c)))
251 continue;
d747e748 252 for (avp = av; --c >= '0' && *avp != NULL; avp++)
6f14531a
RG
253 continue;
254 if (*avp == NULL)
255 continue;
256 len += strlen(*avp);
257 }
258 }
259 if (map->map_app != NULL)
260 len += strlen(map->map_app);
261 if (rwb->rwb_len < ++len)
262 {
263 /* need to malloc additional space */
264 rwb->rwb_len = len;
265 if (rwb->rwb_buf != NULL)
266 free(rwb->rwb_buf);
267 rwb->rwb_buf = xalloc(rwb->rwb_len);
268 }
269
270 bp = rwb->rwb_buf;
271 if (av == NULL)
272 {
273 bcopy(s, bp, slen);
274 bp += slen;
275 }
276 else
277 {
278 while (--slen >= 0 && (c = *s++) != '\0')
279 {
280 if (c != '%')
281 {
282 pushc:
283 *bp++ = c;
284 continue;
285 }
286 if (--slen < 0 || (c = *s++) == '\0')
287 c = '%';
288 if (c == '%')
289 goto pushc;
290 if (!(isascii(c) && isdigit(c)))
291 {
292 *bp++ = '%';
293 goto pushc;
294 }
d747e748 295 for (avp = av; --c >= '0' && *avp != NULL; avp++)
6f14531a
RG
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
d747e748
JH
335#ifdef XDEBUG
336 checkfd012("entering initmaps");
337#endif
6f14531a
RG
338 CurEnv = e;
339 stabapply(map_init, rebuild);
d747e748
JH
340#ifdef XDEBUG
341 checkfd012("exiting initmaps");
342#endif
6f14531a
RG
343}
344
345void
346map_init(s, rebuild)
347 register STAB *s;
348 int rebuild;
349{
350 register MAP *map;
351
352 /* has to be a map */
353 if (s->s_type != ST_MAP)
354 return;
355
356 map = &s->s_map;
357 if (!bitset(MF_VALID, map->map_mflags))
358 return;
359
360 if (tTd(38, 2))
361 printf("map_init(%s:%s)\n",
d747e748
JH
362 map->map_class->map_cname == NULL ? "NULL" :
363 map->map_class->map_cname,
364 map->map_file == NULL ? "NULL" : map->map_file);
6f14531a
RG
365
366 /* if already open, close it (for nested open) */
367 if (bitset(MF_OPEN, map->map_mflags))
368 {
369 map->map_class->map_close(map);
370 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
371 }
372
373 if (rebuild)
374 {
375 if (bitset(MF_ALIAS, map->map_mflags) &&
376 bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
377 rebuildaliases(map, FALSE);
378 }
379 else
380 {
381 if (map->map_class->map_open(map, O_RDONLY))
382 {
383 if (tTd(38, 4))
384 printf("%s:%s: valid\n",
d747e748
JH
385 map->map_class->map_cname == NULL ? "NULL" :
386 map->map_class->map_cname,
387 map->map_file == NULL ? "NULL" :
388 map->map_file);
6f14531a
RG
389 map->map_mflags |= MF_OPEN;
390 }
391 else if (tTd(38, 4))
392 printf("%s:%s: invalid: %s\n",
d747e748
JH
393 map->map_class->map_cname == NULL ? "NULL" :
394 map->map_class->map_cname,
395 map->map_file == NULL ? "NULL" :
396 map->map_file,
6f14531a
RG
397 errstring(errno));
398 }
399}
400\f/*
401** NDBM modules
402*/
403
404#ifdef NDBM
405
406/*
407** DBM_MAP_OPEN -- DBM-style map open
408*/
409
410bool
411ndbm_map_open(map, mode)
412 MAP *map;
413 int mode;
414{
d747e748
JH
415 register DBM *dbm;
416 struct stat st;
6f14531a
RG
417
418 if (tTd(38, 2))
419 printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
420
421 if (mode == O_RDWR)
422 mode |= O_CREAT|O_TRUNC;
423
424 /* open the database */
425 dbm = dbm_open(map->map_file, mode, DBMMODE);
426 if (dbm == NULL)
427 {
d747e748
JH
428#ifdef MAYBENEXTRELEASE
429 if (aliaswait(map, ".pag", FALSE))
430 return TRUE;
431#endif
6f14531a
RG
432 if (!bitset(MF_OPTIONAL, map->map_mflags))
433 syserr("Cannot open DBM database %s", map->map_file);
434 return FALSE;
435 }
436 map->map_db1 = (void *) dbm;
437 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
d747e748
JH
438 if (!aliaswait(map, ".pag", TRUE))
439 return FALSE;
440 if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
441 map->map_mtime = st.st_mtime;
6f14531a
RG
442 return TRUE;
443}
444
445
446/*
447** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
448*/
449
450char *
451ndbm_map_lookup(map, name, av, statp)
452 MAP *map;
453 char *name;
454 char **av;
455 int *statp;
456{
457 datum key, val;
d747e748 458 int fd;
6f14531a
RG
459 char keybuf[MAXNAME + 1];
460
461 if (tTd(38, 20))
462 printf("ndbm_map_lookup(%s)\n", name);
463
464 key.dptr = name;
465 key.dsize = strlen(name);
466 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
467 {
468 if (key.dsize > sizeof keybuf - 1)
469 key.dsize = sizeof keybuf - 1;
470 bcopy(key.dptr, keybuf, key.dsize + 1);
471 makelower(keybuf);
472 key.dptr = keybuf;
473 }
d747e748
JH
474 fd = dbm_dirfno((DBM *) map->map_db1);
475 if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
476 (void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
3a363396
NW
477 val.dptr = NULL;
478 if (bitset(MF_TRY0NULL, map->map_mflags))
479 {
480 val = dbm_fetch((DBM *) map->map_db1, key);
481 if (val.dptr != NULL)
482 map->map_mflags &= ~MF_TRY1NULL;
483 }
484 if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
485 {
486 key.dsize++;
487 val = dbm_fetch((DBM *) map->map_db1, key);
488 if (val.dptr != NULL)
489 map->map_mflags &= ~MF_TRY0NULL;
490 }
d747e748
JH
491 if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
492 (void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
6f14531a
RG
493 if (val.dptr == NULL)
494 return NULL;
495 if (bitset(MF_MATCHONLY, map->map_mflags))
3a363396
NW
496 return map_rewrite(map, name, strlen(name), NULL);
497 else
498 return map_rewrite(map, val.dptr, val.dsize, av);
6f14531a
RG
499}
500
501
502/*
503** DBM_MAP_STORE -- store a datum in the database
504*/
505
506void
507ndbm_map_store(map, lhs, rhs)
508 register MAP *map;
509 char *lhs;
510 char *rhs;
511{
512 datum key;
513 datum data;
514 int stat;
515
516 if (tTd(38, 12))
517 printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
518
519 key.dsize = strlen(lhs);
520 key.dptr = lhs;
521
522 data.dsize = strlen(rhs);
523 data.dptr = rhs;
524
525 if (bitset(MF_INCLNULL, map->map_mflags))
526 {
527 key.dsize++;
528 data.dsize++;
529 }
530
531 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
532 if (stat > 0)
533 {
534 usrerr("050 Warning: duplicate alias name %s", lhs);
535 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
536 }
537 if (stat != 0)
538 syserr("readaliases: dbm put (%s)", lhs);
539}
540
541
542/*
543** NDBM_MAP_CLOSE -- close the database
544*/
545
546void
547ndbm_map_close(map)
548 register MAP *map;
549{
550 if (bitset(MF_WRITABLE, map->map_mflags))
551 {
d747e748
JH
552#ifdef NIS
553 bool inclnull;
6f14531a
RG
554 char buf[200];
555
d747e748
JH
556 inclnull = bitset(MF_INCLNULL, map->map_mflags);
557 map->map_mflags &= ~MF_INCLNULL;
558
6f14531a
RG
559 (void) sprintf(buf, "%010ld", curtime());
560 ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
561
562 (void) myhostname(buf, sizeof buf);
563 ndbm_map_store(map, "YP_MASTER_NAME", buf);
d747e748
JH
564
565 if (inclnull)
566 map->map_mflags |= MF_INCLNULL;
6f14531a
RG
567#endif
568
569 /* write out the distinguished alias */
570 ndbm_map_store(map, "@", "@");
571 }
572 dbm_close((DBM *) map->map_db1);
573}
574
575#endif
576\f/*
577** NEWDB (Hash and BTree) Modules
578*/
579
580#ifdef NEWDB
581
582/*
583** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
584**
585** These do rather bizarre locking. If you can lock on open,
586** do that to avoid the condition of opening a database that
587** is being rebuilt. If you don't, we'll try to fake it, but
588** there will be a race condition. If opening for read-only,
589** we immediately release the lock to avoid freezing things up.
590** We really ought to hold the lock, but guarantee that we won't
591** be pokey about it. That's hard to do.
592*/
593
594bool
595bt_map_open(map, mode)
596 MAP *map;
597 int mode;
598{
599 DB *db;
600 int i;
601 int omode;
d747e748
JH
602 int fd;
603 struct stat st;
6f14531a
RG
604 char buf[MAXNAME];
605
606 if (tTd(38, 2))
607 printf("bt_map_open(%s, %d)\n", map->map_file, mode);
608
609 omode = mode;
610 if (omode == O_RDWR)
611 {
612 omode |= O_CREAT|O_TRUNC;
d747e748 613#if defined(O_EXLOCK) && defined(HASFLOCK)
6f14531a
RG
614 omode |= O_EXLOCK;
615# if !defined(OLD_NEWDB)
616 }
617 else
618 {
619 omode |= O_SHLOCK;
620# endif
621#endif
622 }
623
624 (void) strcpy(buf, map->map_file);
625 i = strlen(buf);
626 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
627 (void) strcat(buf, ".db");
628 db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
629 if (db == NULL)
630 {
d747e748
JH
631#ifdef MAYBENEXTRELEASE
632 if (aliaswait(map, ".db", FALSE))
633 return TRUE;
634#endif
6f14531a
RG
635 if (!bitset(MF_OPTIONAL, map->map_mflags))
636 syserr("Cannot open BTREE database %s", map->map_file);
637 return FALSE;
638 }
d747e748
JH
639#if !defined(OLD_NEWDB) && defined(HASFLOCK)
640 fd = db->fd(db);
6f14531a 641# if !defined(O_EXLOCK)
d747e748
JH
642 if (mode == O_RDWR && fd >= 0)
643 {
644 if (lockfile(fd, map->map_file, ".db", LOCK_EX))
645 map->map_mflags |= MF_LOCKED;
646 }
6f14531a 647# else
d747e748
JH
648 if (mode == O_RDONLY && fd >= 0)
649 (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
650 else
651 map->map_mflags |= MF_LOCKED;
6f14531a
RG
652# endif
653#endif
654
655 /* try to make sure that at least the database header is on disk */
656 if (mode == O_RDWR)
d747e748
JH
657#ifdef OLD_NEWDB
658 (void) db->sync(db);
659#else
6f14531a
RG
660 (void) db->sync(db, 0);
661
d747e748
JH
662 if (fd >= 0 && fstat(fd, &st) >= 0)
663 map->map_mtime = st.st_mtime;
664#endif
665
6f14531a
RG
666 map->map_db2 = (void *) db;
667 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
d747e748
JH
668 if (!aliaswait(map, ".db", TRUE))
669 return FALSE;
6f14531a
RG
670 return TRUE;
671}
672
673
674/*
675** HASH_MAP_INIT -- HASH-style map initialization
676*/
677
678bool
679hash_map_open(map, mode)
680 MAP *map;
681 int mode;
682{
683 DB *db;
684 int i;
685 int omode;
d747e748
JH
686 int fd;
687 struct stat st;
6f14531a
RG
688 char buf[MAXNAME];
689
690 if (tTd(38, 2))
691 printf("hash_map_open(%s, %d)\n", map->map_file, mode);
692
693 omode = mode;
694 if (omode == O_RDWR)
695 {
696 omode |= O_CREAT|O_TRUNC;
d747e748 697#if defined(O_EXLOCK) && defined(HASFLOCK)
6f14531a
RG
698 omode |= O_EXLOCK;
699# if !defined(OLD_NEWDB)
700 }
701 else
702 {
703 omode |= O_SHLOCK;
704# endif
705#endif
706 }
707
708 (void) strcpy(buf, map->map_file);
709 i = strlen(buf);
710 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
711 (void) strcat(buf, ".db");
712 db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
713 if (db == NULL)
714 {
d747e748
JH
715#ifdef MAYBENEXTRELEASE
716 if (aliaswait(map, ".db", FALSE))
717 return TRUE;
718#endif
6f14531a
RG
719 if (!bitset(MF_OPTIONAL, map->map_mflags))
720 syserr("Cannot open HASH database %s", map->map_file);
721 return FALSE;
722 }
d747e748
JH
723#if !defined(OLD_NEWDB) && defined(HASFLOCK)
724 fd = db->fd(db);
6f14531a 725# if !defined(O_EXLOCK)
d747e748
JH
726 if (mode == O_RDWR && fd >= 0)
727 {
728 if (lockfile(fd, map->map_file, ".db", LOCK_EX))
729 map->map_mflags |= MF_LOCKED;
730 }
6f14531a 731# else
d747e748
JH
732 if (mode == O_RDONLY && fd >= 0)
733 (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
734 else
735 map->map_mflags |= MF_LOCKED;
6f14531a
RG
736# endif
737#endif
738
739 /* try to make sure that at least the database header is on disk */
740 if (mode == O_RDWR)
d747e748
JH
741#ifdef OLD_NEWDB
742 (void) db->sync(db);
743#else
6f14531a
RG
744 (void) db->sync(db, 0);
745
d747e748
JH
746 if (fd >= 0 && fstat(fd, &st) >= 0)
747 map->map_mtime = st.st_mtime;
748#endif
749
6f14531a
RG
750 map->map_db2 = (void *) db;
751 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
d747e748
JH
752 if (!aliaswait(map, ".db", TRUE))
753 return FALSE;
6f14531a
RG
754 return TRUE;
755}
756
757
758/*
759** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
760*/
761
762char *
763db_map_lookup(map, name, av, statp)
764 MAP *map;
765 char *name;
766 char **av;
767 int *statp;
768{
769 DBT key, val;
770 register DB *db = (DB *) map->map_db2;
771 int st;
772 int saveerrno;
d747e748 773 int fd;
6f14531a
RG
774 char keybuf[MAXNAME + 1];
775
776 if (tTd(38, 20))
777 printf("db_map_lookup(%s)\n", name);
778
779 key.size = strlen(name);
780 if (key.size > sizeof keybuf - 1)
781 key.size = sizeof keybuf - 1;
782 key.data = keybuf;
783 bcopy(name, keybuf, key.size + 1);
784 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
785 makelower(keybuf);
6f14531a 786#ifndef OLD_NEWDB
d747e748
JH
787 fd = db->fd(db);
788 if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
789 (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
6f14531a 790#endif
3a363396
NW
791 st = 1;
792 if (bitset(MF_TRY0NULL, map->map_mflags))
793 {
794 st = db->get(db, &key, &val, 0);
795 if (st == 0)
796 map->map_mflags &= ~MF_TRY1NULL;
797 }
798 if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
799 {
800 key.size++;
801 st = db->get(db, &key, &val, 0);
802 if (st == 0)
803 map->map_mflags &= ~MF_TRY0NULL;
804 }
6f14531a
RG
805 saveerrno = errno;
806#ifndef OLD_NEWDB
d747e748
JH
807 if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
808 (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
6f14531a
RG
809#endif
810 if (st != 0)
811 {
812 errno = saveerrno;
813 if (st < 0)
814 syserr("db_map_lookup: get (%s)", name);
815 return NULL;
816 }
817 if (bitset(MF_MATCHONLY, map->map_mflags))
3a363396
NW
818 return map_rewrite(map, name, strlen(name), NULL);
819 else
820 return map_rewrite(map, val.data, val.size, av);
6f14531a
RG
821}
822
823
824/*
825** DB_MAP_STORE -- store a datum in the NEWDB database
826*/
827
828void
829db_map_store(map, lhs, rhs)
830 register MAP *map;
831 char *lhs;
832 char *rhs;
833{
834 int stat;
835 DBT key;
836 DBT data;
837 register DB *db = map->map_db2;
838
839 if (tTd(38, 20))
840 printf("db_map_store(%s, %s)\n", lhs, rhs);
841
842 key.size = strlen(lhs);
843 key.data = lhs;
844
845 data.size = strlen(rhs);
846 data.data = rhs;
847
848 if (bitset(MF_INCLNULL, map->map_mflags))
849 {
850 key.size++;
851 data.size++;
852 }
853
854 stat = db->put(db, &key, &data, R_NOOVERWRITE);
855 if (stat > 0)
856 {
857 usrerr("050 Warning: duplicate alias name %s", lhs);
858 stat = db->put(db, &key, &data, 0);
859 }
860 if (stat != 0)
861 syserr("readaliases: db put (%s)", lhs);
862}
863
864
865/*
866** DB_MAP_CLOSE -- add distinguished entries and close the database
867*/
868
869void
870db_map_close(map)
871 MAP *map;
872{
873 register DB *db = map->map_db2;
874
875 if (tTd(38, 9))
876 printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
877
878 if (bitset(MF_WRITABLE, map->map_mflags))
879 {
880 /* write out the distinguished alias */
881 db_map_store(map, "@", "@");
882 }
883
884 if (db->close(db) != 0)
885 syserr("readaliases: db close failure");
886}
887
888#endif
889\f/*
890** NIS Modules
891*/
892
893# ifdef NIS
894
d747e748
JH
895# ifndef YPERR_BUSY
896# define YPERR_BUSY 16
897# endif
898
6f14531a
RG
899/*
900** NIS_MAP_OPEN -- open DBM map
901*/
902
903bool
904nis_map_open(map, mode)
905 MAP *map;
906 int mode;
907{
908 int yperr;
909 register char *p;
910 auto char *vp;
911 auto int vsize;
912 char *master;
913
914 if (tTd(38, 2))
915 printf("nis_map_open(%s)\n", map->map_file);
916
917 if (mode != O_RDONLY)
918 {
d747e748
JH
919 /* issue a pseudo-error message */
920#ifdef ENOSYS
921 errno = ENOSYS;
922#else
923# ifdef EFTYPE
924 errno = EFTYPE;
925# else
926 errno = ENXIO;
927# endif
928#endif
6f14531a
RG
929 return FALSE;
930 }
931
932 p = strchr(map->map_file, '@');
933 if (p != NULL)
934 {
935 *p++ = '\0';
936 if (*p != '\0')
937 map->map_domain = p;
938 }
939
940 if (map->map_domain == NULL)
941 yp_get_default_domain(&map->map_domain);
942
943 if (*map->map_file == '\0')
944 map->map_file = "mail.aliases";
945
946 /* check to see if this map actually exists */
947 yperr = yp_match(map->map_domain, map->map_file, "@", 1,
948 &vp, &vsize);
949 if (tTd(38, 10))
950 printf("nis_map_open: yp_match(%s, %s) => %s\n",
951 map->map_domain, map->map_file, yperr_string(yperr));
952 if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
953 return TRUE;
954
955 if (!bitset(MF_OPTIONAL, map->map_mflags))
956 syserr("Cannot bind to domain %s: %s", map->map_domain,
957 yperr_string(yperr));
958
959 return FALSE;
960}
961
962
963/*
964** NIS_MAP_LOOKUP -- look up a datum in a NIS map
965*/
966
967char *
968nis_map_lookup(map, name, av, statp)
969 MAP *map;
970 char *name;
971 char **av;
972 int *statp;
973{
974 char *vp;
975 auto int vsize;
976 int buflen;
977 int yperr;
978 char keybuf[MAXNAME + 1];
979
980 if (tTd(38, 20))
981 printf("nis_map_lookup(%s)\n", name);
982
983 buflen = strlen(name);
984 if (buflen > sizeof keybuf - 1)
985 buflen = sizeof keybuf - 1;
986 bcopy(name, keybuf, buflen + 1);
987 if (!bitset(MF_NOFOLDCASE, map->map_mflags))
988 makelower(keybuf);
3a363396
NW
989 yperr = YPERR_KEY;
990 if (bitset(MF_TRY0NULL, map->map_mflags))
991 {
992 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
993 &vp, &vsize);
994 if (yperr == 0)
995 map->map_mflags &= ~MF_TRY1NULL;
996 }
997 if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
998 {
6f14531a 999 buflen++;
3a363396
NW
1000 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
1001 &vp, &vsize);
1002 if (yperr == 0)
1003 map->map_mflags &= ~MF_TRY0NULL;
1004 }
6f14531a
RG
1005 if (yperr != 0)
1006 {
1007 if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
1008 map->map_mflags &= ~(MF_VALID|MF_OPEN);
1009 return NULL;
1010 }
1011 if (bitset(MF_MATCHONLY, map->map_mflags))
3a363396
NW
1012 return map_rewrite(map, name, strlen(name), NULL);
1013 else
1014 return map_rewrite(map, vp, vsize, av);
6f14531a
RG
1015}
1016
1017
1018/*
1019** NIS_MAP_STORE
1020*/
1021
1022void
1023nis_map_store(map, lhs, rhs)
1024 MAP *map;
1025 char *lhs;
1026 char *rhs;
1027{
1028 /* nothing */
1029}
1030
1031
1032/*
1033** NIS_MAP_CLOSE
1034*/
1035
1036void
1037nis_map_close(map)
1038 MAP *map;
1039{
1040 /* nothing */
1041}
1042
1043#endif /* NIS */
1044\f/*
1045** STAB (Symbol Table) Modules
1046*/
1047
1048
1049/*
1050** STAB_MAP_LOOKUP -- look up alias in symbol table
1051*/
1052
1053char *
1054stab_map_lookup(map, name, av, pstat)
1055 register MAP *map;
1056 char *name;
1057 char **av;
1058 int *pstat;
1059{
1060 register STAB *s;
1061
1062 if (tTd(38, 20))
1063 printf("stab_lookup(%s)\n", name);
1064
1065 s = stab(name, ST_ALIAS, ST_FIND);
1066 if (s != NULL)
1067 return (s->s_alias);
1068 return (NULL);
1069}
1070
1071
1072/*
1073** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
1074*/
1075
1076void
1077stab_map_store(map, lhs, rhs)
1078 register MAP *map;
1079 char *lhs;
1080 char *rhs;
1081{
1082 register STAB *s;
1083
1084 s = stab(lhs, ST_ALIAS, ST_ENTER);
1085 s->s_alias = newstr(rhs);
1086}
1087
1088
1089/*
1090** STAB_MAP_OPEN -- initialize (reads data file)
1091**
1092** This is a wierd case -- it is only intended as a fallback for
1093** aliases. For this reason, opens for write (only during a
1094** "newaliases") always fails, and opens for read open the
1095** actual underlying text file instead of the database.
1096*/
1097
1098bool
1099stab_map_open(map, mode)
1100 register MAP *map;
1101 int mode;
1102{
d747e748
JH
1103 FILE *af;
1104 struct stat st;
1105
6f14531a
RG
1106 if (tTd(38, 2))
1107 printf("stab_map_open(%s)\n", map->map_file);
1108
1109 if (mode != O_RDONLY)
1110 {
1111 errno = ENODEV;
1112 return FALSE;
1113 }
1114
d747e748
JH
1115 af = fopen(map->map_file, "r");
1116 if (af == NULL)
1117 return FALSE;
1118 readaliases(map, af, TRUE);
1119
1120 if (fstat(fileno(af), &st) >= 0)
1121 map->map_mtime = st.st_mtime;
1122 fclose(af);
1123
6f14531a
RG
1124 return TRUE;
1125}
1126
1127
1128/*
d747e748
JH
1129** STAB_MAP_CLOSE -- close symbol table.
1130**
1131** Since this is in memory, there is nothing to do.
6f14531a
RG
1132*/
1133
1134void
1135stab_map_close(map)
1136 MAP *map;
1137{
1138 /* ignore it */
1139}
1140\f/*
1141** Implicit Modules
1142**
1143** Tries several types. For back compatibility of aliases.
1144*/
1145
1146
1147/*
1148** IMPL_MAP_LOOKUP -- lookup in best open database
1149*/
1150
1151char *
1152impl_map_lookup(map, name, av, pstat)
1153 MAP *map;
1154 char *name;
1155 char **av;
1156 int *pstat;
1157{
1158 if (tTd(38, 20))
1159 printf("impl_map_lookup(%s)\n", name);
1160
1161#ifdef NEWDB
1162 if (bitset(MF_IMPL_HASH, map->map_mflags))
1163 return db_map_lookup(map, name, av, pstat);
1164#endif
1165#ifdef NDBM
1166 if (bitset(MF_IMPL_NDBM, map->map_mflags))
1167 return ndbm_map_lookup(map, name, av, pstat);
1168#endif
1169 return stab_map_lookup(map, name, av, pstat);
1170}
1171
1172/*
1173** IMPL_MAP_STORE -- store in open databases
1174*/
1175
1176void
1177impl_map_store(map, lhs, rhs)
1178 MAP *map;
1179 char *lhs;
1180 char *rhs;
1181{
1182#ifdef NEWDB
1183 if (bitset(MF_IMPL_HASH, map->map_mflags))
1184 db_map_store(map, lhs, rhs);
1185#endif
1186#ifdef NDBM
1187 if (bitset(MF_IMPL_NDBM, map->map_mflags))
1188 ndbm_map_store(map, lhs, rhs);
1189#endif
1190 stab_map_store(map, lhs, rhs);
1191}
1192
1193/*
1194** IMPL_MAP_OPEN -- implicit database open
1195*/
1196
1197bool
1198impl_map_open(map, mode)
1199 MAP *map;
1200 int mode;
1201{
1202 struct stat stb;
1203
1204 if (tTd(38, 2))
d747e748 1205 printf("impl_map_open(%s, %d)\n", map->map_file, mode);
6f14531a
RG
1206
1207 if (stat(map->map_file, &stb) < 0)
1208 {
1209 /* no alias file at all */
d747e748
JH
1210 if (tTd(38, 3))
1211 printf("no map file\n");
6f14531a
RG
1212 return FALSE;
1213 }
1214
1215#ifdef NEWDB
1216 map->map_mflags |= MF_IMPL_HASH;
1217 if (hash_map_open(map, mode))
1218 {
d747e748 1219#if defined(NDBM) && defined(NIS)
6f14531a
RG
1220 if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
1221#endif
1222 return TRUE;
1223 }
1224 else
1225 map->map_mflags &= ~MF_IMPL_HASH;
1226#endif
1227#ifdef NDBM
1228 map->map_mflags |= MF_IMPL_NDBM;
1229 if (ndbm_map_open(map, mode))
1230 {
1231 return TRUE;
1232 }
1233 else
1234 map->map_mflags &= ~MF_IMPL_NDBM;
1235#endif
1236
d747e748 1237#if defined(NEWDB) || defined(NDBM)
6f14531a
RG
1238 if (Verbose)
1239 message("WARNING: cannot open alias database %s", map->map_file);
1240#endif
1241
1242 return stab_map_open(map, mode);
1243}
1244
1245
1246/*
1247** IMPL_MAP_CLOSE -- close any open database(s)
1248*/
1249
1250void
1251impl_map_close(map)
1252 MAP *map;
1253{
1254#ifdef NEWDB
1255 if (bitset(MF_IMPL_HASH, map->map_mflags))
1256 {
1257 db_map_close(map);
1258 map->map_mflags &= ~MF_IMPL_HASH;
1259 }
1260#endif
1261
1262#ifdef NDBM
1263 if (bitset(MF_IMPL_NDBM, map->map_mflags))
1264 {
1265 ndbm_map_close(map);
1266 map->map_mflags &= ~MF_IMPL_NDBM;
1267 }
1268#endif
1269}
1270\f/*
1271** NULL stubs
1272*/
1273
1274bool
1275null_map_open(map, mode)
1276 MAP *map;
1277 int mode;
1278{
1279 return TRUE;
1280}
1281
1282void
1283null_map_close(map)
1284 MAP *map;
1285{
1286 return;
1287}
1288
1289void
1290null_map_store(map, key, val)
1291 MAP *map;
1292 char *key;
1293 char *val;
1294{
1295 return;
1296}