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