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.5 (Berkeley) 07/26/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 DBM *dbm; 376 377 if (tTd(38, 2)) 378 printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 379 380 if (mode == O_RDWR) 381 mode |= O_CREAT|O_TRUNC; 382 383 /* open the database */ 384 dbm = dbm_open(map->map_file, mode, DBMMODE); 385 if (dbm == NULL) 386 { 387 if (!bitset(MF_OPTIONAL, map->map_mflags)) 388 syserr("Cannot open DBM database %s", map->map_file); 389 return FALSE; 390 } 391 map->map_db1 = (void *) dbm; 392 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 393 aliaswait(map, ".pag"); 394 return TRUE; 395 } 396 397 398 /* 399 ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 400 */ 401 402 char * 403 ndbm_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 412 if (tTd(38, 20)) 413 printf("ndbm_map_lookup(%s)\n", name); 414 415 key.dptr = name; 416 key.dsize = strlen(name); 417 if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 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 } 425 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH); 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 } 440 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN); 441 if (val.dptr == NULL) 442 return NULL; 443 if (bitset(MF_MATCHONLY, map->map_mflags)) 444 return map_rewrite(map, name, strlen(name), NULL); 445 else 446 return map_rewrite(map, val.dptr, val.dsize, av); 447 } 448 449 450 /* 451 ** DBM_MAP_STORE -- store a datum in the database 452 */ 453 454 void 455 ndbm_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 464 if (tTd(38, 12)) 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 473 if (bitset(MF_INCLNULL, map->map_mflags)) 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 /* 491 ** NDBM_MAP_CLOSE -- close the database 492 */ 493 494 void 495 ndbm_map_close(map) 496 register MAP *map; 497 { 498 if (bitset(MF_WRITABLE, map->map_mflags)) 499 { 500 #ifdef YPCOMPAT 501 char buf[200]; 502 503 (void) sprintf(buf, "%010ld", curtime()); 504 ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 505 506 (void) myhostname(buf, sizeof buf); 507 ndbm_map_store(map, "YP_MASTER_NAME", buf); 508 #endif 509 510 /* write out the distinguished alias */ 511 ndbm_map_store(map, "@", "@"); 512 } 513 dbm_close((DBM *) map->map_db1); 514 } 515 516 #endif 517 /* 518 ** NEWDB (Hash and BTree) Modules 519 */ 520 521 #ifdef NEWDB 522 523 /* 524 ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives. 525 ** 526 ** These do rather bizarre locking. If you can lock on open, 527 ** do that to avoid the condition of opening a database that 528 ** is being rebuilt. If you don't, we'll try to fake it, but 529 ** there will be a race condition. If opening for read-only, 530 ** we immediately release the lock to avoid freezing things up. 531 ** We really ought to hold the lock, but guarantee that we won't 532 ** be pokey about it. That's hard to do. 533 */ 534 535 bool 536 bt_map_open(map, mode) 537 MAP *map; 538 int mode; 539 { 540 DB *db; 541 int i; 542 int omode; 543 char buf[MAXNAME]; 544 545 if (tTd(38, 2)) 546 printf("bt_map_open(%s, %d)\n", map->map_file, mode); 547 548 omode = mode; 549 if (omode == O_RDWR) 550 { 551 omode |= O_CREAT|O_TRUNC; 552 #if defined(O_EXLOCK) && defined(HASFLOCK) 553 omode |= O_EXLOCK; 554 # if !defined(OLD_NEWDB) 555 } 556 else 557 { 558 omode |= O_SHLOCK; 559 # endif 560 #endif 561 } 562 563 (void) strcpy(buf, map->map_file); 564 i = strlen(buf); 565 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 566 (void) strcat(buf, ".db"); 567 db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL); 568 if (db == NULL) 569 { 570 if (!bitset(MF_OPTIONAL, map->map_mflags)) 571 syserr("Cannot open BTREE database %s", map->map_file); 572 return FALSE; 573 } 574 #if !defined(OLD_NEWDB) && defined(HASFLOCK) 575 # if !defined(O_EXLOCK) 576 if (mode == O_RDWR) 577 (void) lockfile(db->fd(db), map->map_file, LOCK_EX); 578 # else 579 if (mode == O_RDONLY) 580 (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 581 # endif 582 #endif 583 584 /* try to make sure that at least the database header is on disk */ 585 if (mode == O_RDWR) 586 (void) db->sync(db, 0); 587 588 map->map_db2 = (void *) db; 589 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 590 aliaswait(map, ".db"); 591 return TRUE; 592 } 593 594 595 /* 596 ** HASH_MAP_INIT -- HASH-style map initialization 597 */ 598 599 bool 600 hash_map_open(map, mode) 601 MAP *map; 602 int mode; 603 { 604 DB *db; 605 int i; 606 int omode; 607 char buf[MAXNAME]; 608 609 if (tTd(38, 2)) 610 printf("hash_map_open(%s, %d)\n", map->map_file, mode); 611 612 omode = mode; 613 if (omode == O_RDWR) 614 { 615 omode |= O_CREAT|O_TRUNC; 616 #if defined(O_EXLOCK) && defined(HASFLOCK) 617 omode |= O_EXLOCK; 618 # if !defined(OLD_NEWDB) 619 } 620 else 621 { 622 omode |= O_SHLOCK; 623 # endif 624 #endif 625 } 626 627 (void) strcpy(buf, map->map_file); 628 i = strlen(buf); 629 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 630 (void) strcat(buf, ".db"); 631 db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL); 632 if (db == NULL) 633 { 634 if (!bitset(MF_OPTIONAL, map->map_mflags)) 635 syserr("Cannot open HASH database %s", map->map_file); 636 return FALSE; 637 } 638 #if !defined(OLD_NEWDB) && defined(HASFLOCK) 639 # if !defined(O_EXLOCK) 640 if (mode == O_RDWR) 641 (void) lockfile(db->fd(db), map->map_file, LOCK_EX); 642 # else 643 if (mode == O_RDONLY) 644 (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 645 # endif 646 #endif 647 648 /* try to make sure that at least the database header is on disk */ 649 if (mode == O_RDWR) 650 (void) db->sync(db, 0); 651 652 map->map_db2 = (void *) db; 653 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 654 aliaswait(map, ".db"); 655 return TRUE; 656 } 657 658 659 /* 660 ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 661 */ 662 663 char * 664 db_map_lookup(map, name, av, statp) 665 MAP *map; 666 char *name; 667 char **av; 668 int *statp; 669 { 670 DBT key, val; 671 register DB *db = (DB *) map->map_db2; 672 int st; 673 int saveerrno; 674 char keybuf[MAXNAME + 1]; 675 676 if (tTd(38, 20)) 677 printf("db_map_lookup(%s)\n", name); 678 679 key.size = strlen(name); 680 if (key.size > sizeof keybuf - 1) 681 key.size = sizeof keybuf - 1; 682 key.data = keybuf; 683 bcopy(name, keybuf, key.size + 1); 684 if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 685 makelower(keybuf); 686 #ifndef OLD_NEWDB 687 (void) lockfile(db->fd(db), map->map_file, LOCK_SH); 688 #endif 689 st = 1; 690 if (bitset(MF_TRY0NULL, map->map_mflags)) 691 { 692 st = db->get(db, &key, &val, 0); 693 if (st == 0) 694 map->map_mflags &= ~MF_TRY1NULL; 695 } 696 if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) 697 { 698 key.size++; 699 st = db->get(db, &key, &val, 0); 700 if (st == 0) 701 map->map_mflags &= ~MF_TRY0NULL; 702 } 703 saveerrno = errno; 704 #ifndef OLD_NEWDB 705 (void) lockfile(db->fd(db), map->map_file, LOCK_UN); 706 #endif 707 if (st != 0) 708 { 709 errno = saveerrno; 710 if (st < 0) 711 syserr("db_map_lookup: get (%s)", name); 712 return NULL; 713 } 714 if (bitset(MF_MATCHONLY, map->map_mflags)) 715 return map_rewrite(map, name, strlen(name), NULL); 716 else 717 return map_rewrite(map, val.data, val.size, av); 718 } 719 720 721 /* 722 ** DB_MAP_STORE -- store a datum in the NEWDB database 723 */ 724 725 void 726 db_map_store(map, lhs, rhs) 727 register MAP *map; 728 char *lhs; 729 char *rhs; 730 { 731 int stat; 732 DBT key; 733 DBT data; 734 register DB *db = map->map_db2; 735 736 if (tTd(38, 20)) 737 printf("db_map_store(%s, %s)\n", lhs, rhs); 738 739 key.size = strlen(lhs); 740 key.data = lhs; 741 742 data.size = strlen(rhs); 743 data.data = rhs; 744 745 if (bitset(MF_INCLNULL, map->map_mflags)) 746 { 747 key.size++; 748 data.size++; 749 } 750 751 stat = db->put(db, &key, &data, R_NOOVERWRITE); 752 if (stat > 0) 753 { 754 usrerr("050 Warning: duplicate alias name %s", lhs); 755 stat = db->put(db, &key, &data, 0); 756 } 757 if (stat != 0) 758 syserr("readaliases: db put (%s)", lhs); 759 } 760 761 762 /* 763 ** DB_MAP_CLOSE -- add distinguished entries and close the database 764 */ 765 766 void 767 db_map_close(map) 768 MAP *map; 769 { 770 register DB *db = map->map_db2; 771 772 if (tTd(38, 9)) 773 printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 774 775 if (bitset(MF_WRITABLE, map->map_mflags)) 776 { 777 /* write out the distinguished alias */ 778 db_map_store(map, "@", "@"); 779 } 780 781 if (db->close(db) != 0) 782 syserr("readaliases: db close failure"); 783 } 784 785 #endif 786 /* 787 ** NIS Modules 788 */ 789 790 # ifdef NIS 791 792 /* 793 ** NIS_MAP_OPEN -- open DBM map 794 */ 795 796 bool 797 nis_map_open(map, mode) 798 MAP *map; 799 int mode; 800 { 801 int yperr; 802 register char *p; 803 auto char *vp; 804 auto int vsize; 805 char *master; 806 807 if (tTd(38, 2)) 808 printf("nis_map_open(%s)\n", map->map_file); 809 810 if (mode != O_RDONLY) 811 { 812 errno = ENODEV; 813 return FALSE; 814 } 815 816 p = strchr(map->map_file, '@'); 817 if (p != NULL) 818 { 819 *p++ = '\0'; 820 if (*p != '\0') 821 map->map_domain = p; 822 } 823 824 if (map->map_domain == NULL) 825 yp_get_default_domain(&map->map_domain); 826 827 if (*map->map_file == '\0') 828 map->map_file = "mail.aliases"; 829 830 /* check to see if this map actually exists */ 831 yperr = yp_match(map->map_domain, map->map_file, "@", 1, 832 &vp, &vsize); 833 if (tTd(38, 10)) 834 printf("nis_map_open: yp_match(%s, %s) => %s\n", 835 map->map_domain, map->map_file, yperr_string(yperr)); 836 if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 837 return TRUE; 838 839 if (!bitset(MF_OPTIONAL, map->map_mflags)) 840 syserr("Cannot bind to domain %s: %s", map->map_domain, 841 yperr_string(yperr)); 842 843 return FALSE; 844 } 845 846 847 /* 848 ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 849 */ 850 851 char * 852 nis_map_lookup(map, name, av, statp) 853 MAP *map; 854 char *name; 855 char **av; 856 int *statp; 857 { 858 char *vp; 859 auto int vsize; 860 int buflen; 861 int yperr; 862 char keybuf[MAXNAME + 1]; 863 864 if (tTd(38, 20)) 865 printf("nis_map_lookup(%s)\n", name); 866 867 buflen = strlen(name); 868 if (buflen > sizeof keybuf - 1) 869 buflen = sizeof keybuf - 1; 870 bcopy(name, keybuf, buflen + 1); 871 if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 872 makelower(keybuf); 873 yperr = YPERR_KEY; 874 if (bitset(MF_TRY0NULL, map->map_mflags)) 875 { 876 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 877 &vp, &vsize); 878 if (yperr == 0) 879 map->map_mflags &= ~MF_TRY1NULL; 880 } 881 if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags)) 882 { 883 buflen++; 884 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 885 &vp, &vsize); 886 if (yperr == 0) 887 map->map_mflags &= ~MF_TRY0NULL; 888 } 889 if (yperr != 0) 890 { 891 if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 892 map->map_mflags &= ~(MF_VALID|MF_OPEN); 893 return NULL; 894 } 895 if (bitset(MF_MATCHONLY, map->map_mflags)) 896 return map_rewrite(map, name, strlen(name), NULL); 897 else 898 return map_rewrite(map, vp, vsize, av); 899 } 900 901 902 /* 903 ** NIS_MAP_STORE 904 */ 905 906 void 907 nis_map_store(map, lhs, rhs) 908 MAP *map; 909 char *lhs; 910 char *rhs; 911 { 912 /* nothing */ 913 } 914 915 916 /* 917 ** NIS_MAP_CLOSE 918 */ 919 920 void 921 nis_map_close(map) 922 MAP *map; 923 { 924 /* nothing */ 925 } 926 927 #endif /* NIS */ 928 /* 929 ** STAB (Symbol Table) Modules 930 */ 931 932 933 /* 934 ** STAB_MAP_LOOKUP -- look up alias in symbol table 935 */ 936 937 char * 938 stab_map_lookup(map, name, av, pstat) 939 register MAP *map; 940 char *name; 941 char **av; 942 int *pstat; 943 { 944 register STAB *s; 945 946 if (tTd(38, 20)) 947 printf("stab_lookup(%s)\n", name); 948 949 s = stab(name, ST_ALIAS, ST_FIND); 950 if (s != NULL) 951 return (s->s_alias); 952 return (NULL); 953 } 954 955 956 /* 957 ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 958 */ 959 960 void 961 stab_map_store(map, lhs, rhs) 962 register MAP *map; 963 char *lhs; 964 char *rhs; 965 { 966 register STAB *s; 967 968 s = stab(lhs, ST_ALIAS, ST_ENTER); 969 s->s_alias = newstr(rhs); 970 } 971 972 973 /* 974 ** STAB_MAP_OPEN -- initialize (reads data file) 975 ** 976 ** This is a wierd case -- it is only intended as a fallback for 977 ** aliases. For this reason, opens for write (only during a 978 ** "newaliases") always fails, and opens for read open the 979 ** actual underlying text file instead of the database. 980 */ 981 982 bool 983 stab_map_open(map, mode) 984 register MAP *map; 985 int mode; 986 { 987 FILE *af; 988 989 if (tTd(38, 2)) 990 printf("stab_map_open(%s)\n", map->map_file); 991 992 if (mode != O_RDONLY) 993 { 994 errno = ENODEV; 995 return FALSE; 996 } 997 998 af = fopen(map->map_file, "r"); 999 if (af == NULL) 1000 return FALSE; 1001 readaliases(map, af, TRUE); 1002 fclose(af); 1003 1004 return TRUE; 1005 } 1006 1007 1008 /* 1009 ** STAB_MAP_CLOSE -- close symbol table (???) 1010 */ 1011 1012 void 1013 stab_map_close(map) 1014 MAP *map; 1015 { 1016 /* ignore it */ 1017 } 1018 /* 1019 ** Implicit Modules 1020 ** 1021 ** Tries several types. For back compatibility of aliases. 1022 */ 1023 1024 1025 /* 1026 ** IMPL_MAP_LOOKUP -- lookup in best open database 1027 */ 1028 1029 char * 1030 impl_map_lookup(map, name, av, pstat) 1031 MAP *map; 1032 char *name; 1033 char **av; 1034 int *pstat; 1035 { 1036 if (tTd(38, 20)) 1037 printf("impl_map_lookup(%s)\n", name); 1038 1039 #ifdef NEWDB 1040 if (bitset(MF_IMPL_HASH, map->map_mflags)) 1041 return db_map_lookup(map, name, av, pstat); 1042 #endif 1043 #ifdef NDBM 1044 if (bitset(MF_IMPL_NDBM, map->map_mflags)) 1045 return ndbm_map_lookup(map, name, av, pstat); 1046 #endif 1047 return stab_map_lookup(map, name, av, pstat); 1048 } 1049 1050 /* 1051 ** IMPL_MAP_STORE -- store in open databases 1052 */ 1053 1054 void 1055 impl_map_store(map, lhs, rhs) 1056 MAP *map; 1057 char *lhs; 1058 char *rhs; 1059 { 1060 #ifdef NEWDB 1061 if (bitset(MF_IMPL_HASH, map->map_mflags)) 1062 db_map_store(map, lhs, rhs); 1063 #endif 1064 #ifdef NDBM 1065 if (bitset(MF_IMPL_NDBM, map->map_mflags)) 1066 ndbm_map_store(map, lhs, rhs); 1067 #endif 1068 stab_map_store(map, lhs, rhs); 1069 } 1070 1071 /* 1072 ** IMPL_MAP_OPEN -- implicit database open 1073 */ 1074 1075 bool 1076 impl_map_open(map, mode) 1077 MAP *map; 1078 int mode; 1079 { 1080 struct stat stb; 1081 1082 if (tTd(38, 2)) 1083 printf("impl_map_open(%s)\n", map->map_file); 1084 1085 if (stat(map->map_file, &stb) < 0) 1086 { 1087 /* no alias file at all */ 1088 return FALSE; 1089 } 1090 1091 #ifdef NEWDB 1092 map->map_mflags |= MF_IMPL_HASH; 1093 if (hash_map_open(map, mode)) 1094 { 1095 #if defined(NDBM) && defined(YPCOMPAT) 1096 if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0) 1097 #endif 1098 return TRUE; 1099 } 1100 else 1101 map->map_mflags &= ~MF_IMPL_HASH; 1102 #endif 1103 #ifdef NDBM 1104 map->map_mflags |= MF_IMPL_NDBM; 1105 if (ndbm_map_open(map, mode)) 1106 { 1107 return TRUE; 1108 } 1109 else 1110 map->map_mflags &= ~MF_IMPL_NDBM; 1111 #endif 1112 1113 #if !defined(NEWDB) && !defined(NDBM) 1114 if (Verbose) 1115 message("WARNING: cannot open alias database %s", map->map_file); 1116 #endif 1117 1118 return stab_map_open(map, mode); 1119 } 1120 1121 1122 /* 1123 ** IMPL_MAP_CLOSE -- close any open database(s) 1124 */ 1125 1126 void 1127 impl_map_close(map) 1128 MAP *map; 1129 { 1130 #ifdef NEWDB 1131 if (bitset(MF_IMPL_HASH, map->map_mflags)) 1132 { 1133 db_map_close(map); 1134 map->map_mflags &= ~MF_IMPL_HASH; 1135 } 1136 #endif 1137 1138 #ifdef NDBM 1139 if (bitset(MF_IMPL_NDBM, map->map_mflags)) 1140 { 1141 ndbm_map_close(map); 1142 map->map_mflags &= ~MF_IMPL_NDBM; 1143 } 1144 #endif 1145 } 1146 /* 1147 ** NULL stubs 1148 */ 1149 1150 bool 1151 null_map_open(map, mode) 1152 MAP *map; 1153 int mode; 1154 { 1155 return TRUE; 1156 } 1157 1158 void 1159 null_map_close(map) 1160 MAP *map; 1161 { 1162 return; 1163 } 1164 1165 void 1166 null_map_store(map, key, val) 1167 MAP *map; 1168 char *key; 1169 char *val; 1170 { 1171 return; 1172 } 1173