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