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