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