1 /* 2 * Copyright (c) 1992 Eric P. Allman. 3 * Copyright (c) 1992 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)map.c 6.19 (Berkeley) 05/24/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 char * 165 map_rewrite(map, s, slen, av) 166 register MAP *map; 167 register char *s; 168 int slen; 169 char **av; 170 { 171 register char *bp; 172 register char c; 173 char **avp; 174 register char *ap; 175 int i; 176 int len; 177 static int buflen = -1; 178 static char *buf = NULL; 179 180 if (tTd(23, 1)) 181 { 182 printf("map_rewrite(%.*s), av =", slen, s); 183 if (av == NULL) 184 printf(" (nullv)"); 185 else 186 { 187 for (avp = av; *avp != NULL; avp++) 188 printf("\n\t%s", *avp); 189 } 190 printf("\n"); 191 } 192 193 /* count expected size of output (can safely overestimate) */ 194 i = len = slen; 195 if (av != NULL) 196 { 197 bp = s; 198 for (i = slen; --i >= 0 && (c = *bp++) != 0; ) 199 { 200 if (c != '%') 201 continue; 202 if (--i < 0) 203 break; 204 c = *bp++; 205 if (!(isascii(c) && isdigit(c))) 206 continue; 207 c -= 0; 208 for (avp = av; --c >= 0 && *avp != NULL; avp++) 209 continue; 210 if (*avp == NULL) 211 continue; 212 len += strlen(*avp); 213 } 214 } 215 if (map->map_app != NULL) 216 len += strlen(map->map_app); 217 if (buflen < ++len) 218 { 219 /* need to malloc additional space */ 220 buflen = len; 221 if (buf != NULL) 222 free(buf); 223 buf = xalloc(buflen); 224 } 225 226 bp = buf; 227 if (av == NULL) 228 { 229 bcopy(s, bp, slen); 230 bp += slen; 231 } 232 else 233 { 234 while (--slen >= 0 && (c = *s++) != '\0') 235 { 236 if (c != '%') 237 { 238 pushc: 239 *bp++ = c; 240 continue; 241 } 242 if (--slen < 0 || (c = *s++) == '\0') 243 c = '%'; 244 if (c == '%') 245 goto pushc; 246 if (!(isascii(c) && isdigit(c))) 247 { 248 *bp++ = '%'; 249 goto pushc; 250 } 251 c -= '0'; 252 for (avp = av; --c >= 0 && *avp != NULL; avp++) 253 continue; 254 if (*avp == NULL) 255 continue; 256 257 /* transliterate argument into output string */ 258 for (ap = *avp; (c = *ap++) != '\0'; ) 259 *bp++ = c; 260 } 261 } 262 if (map->map_app != NULL) 263 strcpy(bp, map->map_app); 264 else 265 *bp = '\0'; 266 if (tTd(23, 1)) 267 printf("map_rewrite => %s\n", buf); 268 return buf; 269 } 270 /* 271 ** NDBM modules 272 */ 273 274 #ifdef NDBM 275 276 /* 277 ** DBM_MAP_OPEN -- DBM-style map open 278 */ 279 280 bool 281 ndbm_map_open(map, mode) 282 MAP *map; 283 int mode; 284 { 285 DBM *dbm; 286 287 if (tTd(27, 2)) 288 printf("ndbm_map_open(%s, %d)\n", map->map_file, mode); 289 290 if (mode == O_RDWR) 291 mode |= O_CREAT|O_TRUNC; 292 293 /* open the database */ 294 dbm = dbm_open(map->map_file, mode, DBMMODE); 295 if (dbm == NULL) 296 { 297 if (!bitset(MF_OPTIONAL, map->map_mflags)) 298 syserr("Cannot open DBM database %s", map->map_file); 299 return FALSE; 300 } 301 map->map_db1 = (void *) dbm; 302 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 303 aliaswait(map, ".dir"); 304 return TRUE; 305 } 306 307 308 /* 309 ** DBM_MAP_LOOKUP -- look up a datum in a DBM-type map 310 */ 311 312 char * 313 ndbm_map_lookup(map, name, av, statp) 314 MAP *map; 315 char *name; 316 char **av; 317 int *statp; 318 { 319 datum key, val; 320 char keybuf[MAXNAME + 1]; 321 322 if (tTd(27, 20)) 323 printf("ndbm_map_lookup(%s)\n", name); 324 325 key.dptr = name; 326 key.dsize = strlen(name); 327 if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 328 { 329 if (key.dsize > sizeof keybuf - 1) 330 key.dsize = sizeof keybuf - 1; 331 bcopy(key.dptr, keybuf, key.dsize + 1); 332 makelower(keybuf); 333 key.dptr = keybuf; 334 } 335 if (bitset(MF_INCLNULL, map->map_mflags)) 336 key.dsize++; 337 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH); 338 val = dbm_fetch((DBM *) map->map_db1, key); 339 (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN); 340 if (val.dptr == NULL) 341 return NULL; 342 if (bitset(MF_MATCHONLY, map->map_mflags)) 343 av = NULL; 344 return map_rewrite(map, val.dptr, val.dsize, av); 345 } 346 347 348 /* 349 ** DBM_MAP_STORE -- store a datum in the database 350 */ 351 352 void 353 ndbm_map_store(map, lhs, rhs) 354 register MAP *map; 355 char *lhs; 356 char *rhs; 357 { 358 datum key; 359 datum data; 360 int stat; 361 362 if (tTd(27, 12)) 363 printf("ndbm_map_store(%s, %s)\n", lhs, rhs); 364 365 key.dsize = strlen(lhs); 366 key.dptr = lhs; 367 368 data.dsize = strlen(rhs); 369 data.dptr = rhs; 370 371 if (bitset(MF_INCLNULL, map->map_mflags)) 372 { 373 key.dsize++; 374 data.dsize++; 375 } 376 377 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); 378 if (stat > 0) 379 { 380 usrerr("050 Warning: duplicate alias name %s", lhs); 381 stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE); 382 } 383 if (stat != 0) 384 syserr("readaliases: dbm put (%s)", lhs); 385 } 386 387 388 /* 389 ** NDBM_MAP_CLOSE -- close the database 390 */ 391 392 void 393 ndbm_map_close(map) 394 register MAP *map; 395 { 396 if (bitset(MF_WRITABLE, map->map_mflags)) 397 { 398 #ifdef YPCOMPAT 399 char buf[200]; 400 401 (void) sprintf(buf, "%010ld", curtime()); 402 ndbm_map_store(map, "YP_LAST_MODIFIED", buf); 403 404 (void) myhostname(buf, sizeof buf); 405 ndbm_map_store(map, "YP_MASTER_NAME", buf); 406 #endif 407 408 /* write out the distinguished alias */ 409 ndbm_map_store(map, "@", "@"); 410 } 411 dbm_close((DBM *) map->map_db1); 412 } 413 414 #endif 415 /* 416 ** HASH (NEWDB) Modules 417 */ 418 419 #ifdef NEWDB 420 421 /* 422 ** BTREE_MAP_PARSE -- BTREE-style map initialization 423 */ 424 425 bool 426 bt_map_open(map, mode) 427 MAP *map; 428 int mode; 429 { 430 DB *db; 431 int i; 432 char buf[MAXNAME]; 433 434 if (tTd(27, 2)) 435 printf("bt_map_open(%s, %d)\n", map->map_file, mode); 436 437 if (mode == O_RDWR) 438 mode |= O_CREAT|O_TRUNC; 439 440 (void) strcpy(buf, map->map_file); 441 i = strlen(buf); 442 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 443 (void) strcat(buf, ".db"); 444 db = dbopen(buf, mode, DBMMODE, DB_BTREE, NULL); 445 if (db == NULL) 446 { 447 if (!bitset(MF_OPTIONAL, map->map_mflags)) 448 syserr("Cannot open BTREE database %s", map->map_file); 449 return FALSE; 450 } 451 map->map_db2 = (void *) db; 452 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 453 aliaswait(map, ".db"); 454 return TRUE; 455 } 456 457 458 /* 459 ** HASH_MAP_INIT -- HASH-style map initialization 460 */ 461 462 bool 463 hash_map_open(map, mode) 464 MAP *map; 465 int mode; 466 { 467 DB *db; 468 int i; 469 char buf[MAXNAME]; 470 471 if (tTd(27, 2)) 472 printf("hash_map_open(%s, %d)\n", map->map_file, mode); 473 474 if (mode == O_RDWR) 475 mode |= O_CREAT|O_TRUNC; 476 477 (void) strcpy(buf, map->map_file); 478 i = strlen(buf); 479 if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) 480 (void) strcat(buf, ".db"); 481 db = dbopen(buf, mode, DBMMODE, DB_HASH, NULL); 482 if (db == NULL) 483 { 484 if (!bitset(MF_OPTIONAL, map->map_mflags)) 485 syserr("Cannot open HASH database %s", map->map_file); 486 return FALSE; 487 } 488 map->map_db2 = (void *) db; 489 if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags)) 490 aliaswait(map, ".db"); 491 return TRUE; 492 } 493 494 495 /* 496 ** DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map 497 */ 498 499 char * 500 db_map_lookup(map, name, av, statp) 501 MAP *map; 502 char *name; 503 char **av; 504 int *statp; 505 { 506 DBT key, val; 507 char keybuf[MAXNAME + 1]; 508 509 if (tTd(27, 20)) 510 printf("db_map_lookup(%s)\n", name); 511 512 key.size = strlen(name); 513 if (key.size > sizeof keybuf - 1) 514 key.size = sizeof keybuf - 1; 515 key.data = keybuf; 516 bcopy(name, keybuf, key.size + 1); 517 if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 518 makelower(keybuf); 519 if (bitset(MF_INCLNULL, map->map_mflags)) 520 key.size++; 521 if (((DB *) map->map_db2)->get((DB *) map->map_db2, &key, &val, 0) != 0) 522 return NULL; 523 if (bitset(MF_MATCHONLY, map->map_mflags)) 524 av = NULL; 525 return map_rewrite(map, val.data, val.size, av); 526 } 527 528 529 /* 530 ** DB_MAP_STORE -- store a datum in the NEWDB database 531 */ 532 533 void 534 db_map_store(map, lhs, rhs) 535 register MAP *map; 536 char *lhs; 537 char *rhs; 538 { 539 int stat; 540 DBT key; 541 DBT data; 542 register DB *db = map->map_db2; 543 544 if (tTd(27, 20)) 545 printf("db_map_store(%s, %s)\n", lhs, rhs); 546 547 key.size = strlen(lhs); 548 key.data = lhs; 549 550 data.size = strlen(rhs); 551 data.data = rhs; 552 553 if (bitset(MF_INCLNULL, map->map_mflags)) 554 { 555 key.size++; 556 data.size++; 557 } 558 559 stat = db->put(db, &key, &data, R_NOOVERWRITE); 560 if (stat > 0) 561 { 562 usrerr("050 Warning: duplicate alias name %s", lhs); 563 stat = db->put(db, &key, &data, 0); 564 } 565 if (stat != 0) 566 syserr("readaliases: db put (%s)", lhs); 567 } 568 569 570 /* 571 ** DB_MAP_CLOSE -- add distinguished entries and close the database 572 */ 573 574 void 575 db_map_close(map) 576 MAP *map; 577 { 578 register DB *db = map->map_db2; 579 580 if (tTd(27, 9)) 581 printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags); 582 583 if (bitset(MF_WRITABLE, map->map_mflags)) 584 { 585 /* write out the distinguished alias */ 586 db_map_store(map, "@", "@"); 587 } 588 589 if (db->close(db) != 0) 590 syserr("readaliases: db close failure"); 591 } 592 593 #endif 594 /* 595 ** NIS Modules 596 */ 597 598 # ifdef NIS 599 600 /* 601 ** NIS_MAP_OPEN -- open DBM map 602 */ 603 604 bool 605 nis_map_open(map, mode) 606 MAP *map; 607 int mode; 608 { 609 int yperr; 610 register char *p; 611 auto char *vp; 612 auto int vsize; 613 char *master; 614 615 if (tTd(27, 2)) 616 printf("nis_map_open(%s)\n", map->map_file); 617 618 if (mode != O_RDONLY) 619 { 620 errno = ENODEV; 621 return FALSE; 622 } 623 624 p = strchr(map->map_file, '@'); 625 if (p != NULL) 626 { 627 *p++ = '\0'; 628 if (*p != '\0') 629 map->map_domain = p; 630 } 631 632 if (map->map_domain == NULL) 633 yp_get_default_domain(&map->map_domain); 634 635 if (*map->map_file == '\0') 636 map->map_file = "mail.aliases"; 637 638 /* check to see if this map actually exists */ 639 yperr = yp_match(map->map_domain, map->map_file, "@", 1, 640 &vp, &vsize); 641 if (tTd(27, 10)) 642 printf("nis_map_open: yp_match(%s, %s) => %s\n", 643 map->map_domain, map->map_file, yperr_string(yperr)); 644 if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 645 return TRUE; 646 647 if (!bitset(MF_OPTIONAL, map->map_mflags)) 648 syserr("Cannot bind to domain %s: %s", map->map_domain, 649 yperr_string(yperr)); 650 651 return FALSE; 652 } 653 654 655 /* 656 ** NIS_MAP_LOOKUP -- look up a datum in a NIS map 657 */ 658 659 char * 660 nis_map_lookup(map, name, av, statp) 661 MAP *map; 662 char *name; 663 char **av; 664 int *statp; 665 { 666 char *vp; 667 auto int vsize; 668 int buflen; 669 int yperr; 670 char keybuf[MAXNAME + 1]; 671 672 if (tTd(27, 20)) 673 printf("nis_map_lookup(%s)\n", name); 674 675 buflen = strlen(name); 676 if (buflen > sizeof keybuf - 1) 677 buflen = sizeof keybuf - 1; 678 bcopy(name, keybuf, buflen + 1); 679 if (!bitset(MF_NOFOLDCASE, map->map_mflags)) 680 makelower(keybuf); 681 if (bitset(MF_INCLNULL, map->map_mflags)) 682 buflen++; 683 yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen, 684 &vp, &vsize); 685 if (yperr != 0) 686 { 687 if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 688 map->map_mflags &= ~(MF_VALID|MF_OPEN); 689 return NULL; 690 } 691 if (bitset(MF_MATCHONLY, map->map_mflags)) 692 av = NULL; 693 return map_rewrite(map, vp, vsize, av); 694 } 695 696 697 /* 698 ** NIS_MAP_STORE 699 */ 700 701 void 702 nis_map_store(map, lhs, rhs) 703 MAP *map; 704 char *lhs; 705 char *rhs; 706 { 707 /* nothing */ 708 } 709 710 711 /* 712 ** NIS_MAP_CLOSE 713 */ 714 715 void 716 nis_map_close(map) 717 MAP *map; 718 { 719 /* nothing */ 720 } 721 722 #endif /* NIS */ 723 /* 724 ** STAB (Symbol Table) Modules 725 */ 726 727 728 /* 729 ** STAB_MAP_LOOKUP -- look up alias in symbol table 730 */ 731 732 char * 733 stab_map_lookup(map, name) 734 register MAP *map; 735 char *name; 736 { 737 register STAB *s; 738 739 if (tTd(27, 20)) 740 printf("stab_lookup(%s)\n", name); 741 742 s = stab(name, ST_ALIAS, ST_FIND); 743 if (s != NULL) 744 return (s->s_alias); 745 return (NULL); 746 } 747 748 749 /* 750 ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild) 751 */ 752 753 void 754 stab_map_store(map, lhs, rhs) 755 register MAP *map; 756 char *lhs; 757 char *rhs; 758 { 759 register STAB *s; 760 761 s = stab(lhs, ST_ALIAS, ST_ENTER); 762 s->s_alias = newstr(rhs); 763 } 764 765 766 /* 767 ** STAB_MAP_OPEN -- initialize (reads data file) 768 ** 769 ** This is a wierd case -- it is only intended as a fallback for 770 ** aliases. For this reason, opens for write (only during a 771 ** "newaliases") always fails, and opens for read open the 772 ** actual underlying text file instead of the database. 773 */ 774 775 bool 776 stab_map_open(map, mode) 777 register MAP *map; 778 int mode; 779 { 780 FILE *af; 781 782 if (tTd(27, 2)) 783 printf("stab_map_open(%s)\n", map->map_file); 784 785 if (mode != O_RDONLY) 786 { 787 errno = ENODEV; 788 return FALSE; 789 } 790 791 return TRUE; 792 } 793 794 795 /* 796 ** STAB_MAP_CLOSE -- close symbol table (???) 797 */ 798 799 void 800 stab_map_close(map) 801 MAP *map; 802 { 803 /* ignore it */ 804 } 805 /* 806 ** Implicit Modules 807 ** 808 ** Tries several types. For back compatibility of aliases. 809 */ 810 811 812 /* 813 ** IMPL_MAP_LOOKUP -- lookup in best open database 814 */ 815 816 char * 817 impl_map_lookup(map, name, av, pstat) 818 MAP *map; 819 char *name; 820 char **av; 821 int *pstat; 822 { 823 if (tTd(27, 20)) 824 printf("impl_map_lookup(%s)\n", name); 825 826 #ifdef NEWDB 827 if (bitset(MF_IMPL_HASH, map->map_mflags)) 828 return db_map_lookup(map, name, av, pstat); 829 #endif 830 #ifdef NDBM 831 if (bitset(MF_IMPL_NDBM, map->map_mflags)) 832 return ndbm_map_lookup(map, name, av, pstat); 833 #endif 834 return stab_map_lookup(map, name, av, pstat); 835 } 836 837 /* 838 ** IMPL_MAP_STORE -- store in open databases 839 */ 840 841 void 842 impl_map_store(map, lhs, rhs) 843 MAP *map; 844 char *lhs; 845 char *rhs; 846 { 847 #ifdef NEWDB 848 if (bitset(MF_IMPL_HASH, map->map_mflags)) 849 db_map_store(map, lhs, rhs); 850 #endif 851 #ifdef NDBM 852 if (bitset(MF_IMPL_NDBM, map->map_mflags)) 853 ndbm_map_store(map, lhs, rhs); 854 #endif 855 stab_map_store(map, lhs, rhs); 856 } 857 858 /* 859 ** IMPL_MAP_OPEN -- implicit database open 860 */ 861 862 bool 863 impl_map_open(map, mode) 864 MAP *map; 865 int mode; 866 { 867 struct stat stb; 868 869 if (tTd(27, 2)) 870 printf("impl_map_open(%s)\n", map->map_file); 871 872 if (stat(map->map_file, &stb) < 0) 873 { 874 /* no alias file at all */ 875 return FALSE; 876 } 877 878 #ifdef NEWDB 879 map->map_mflags |= MF_IMPL_HASH; 880 if (hash_map_open(map, mode)) 881 { 882 #if defined(NDBM) && defined(YPCOMPAT) 883 if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) == 0) 884 #endif 885 return TRUE; 886 } 887 else 888 map->map_mflags &= ~MF_IMPL_HASH; 889 #endif 890 #ifdef NDBM 891 map->map_mflags |= MF_IMPL_NDBM; 892 if (ndbm_map_open(map, mode)) 893 { 894 return TRUE; 895 } 896 else 897 map->map_mflags &= ~MF_IMPL_NDBM; 898 #endif 899 900 #if !defined(NEWDB) && !defined(NDBM) 901 if (Verbose) 902 message("WARNING: cannot open alias database %s", map->map_file); 903 #endif 904 905 return stab_map_open(map, mode); 906 } 907 908 909 /* 910 ** IMPL_MAP_CLOSE -- close any open database(s) 911 */ 912 913 void 914 impl_map_close(map) 915 MAP *map; 916 { 917 #ifdef NEWDB 918 if (bitset(MF_IMPL_HASH, map->map_mflags)) 919 { 920 db_map_close(map); 921 map->map_mflags &= ~MF_IMPL_HASH; 922 } 923 #endif 924 925 #ifdef NDBM 926 if (bitset(MF_IMPL_NDBM, map->map_mflags)) 927 { 928 ndbm_map_close(map); 929 map->map_mflags &= ~MF_IMPL_NDBM; 930 } 931 #endif 932 } 933 /* 934 ** NULL stubs 935 */ 936 937 bool 938 null_map_open(map, mode) 939 MAP *map; 940 int mode; 941 { 942 return TRUE; 943 } 944 945 void 946 null_map_close(map) 947 MAP *map; 948 { 949 return; 950 } 951 952 void 953 null_map_store(map, key, val) 954 MAP *map; 955 char *key; 956 char *val; 957 { 958 return; 959 } 960