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