1 /* 2 * Copyright (c) 1983, 1995 Eric P. Allman 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #include "sendmail.h" 10 11 #ifndef lint 12 #ifdef USERDB 13 static char sccsid [] = "@(#)udb.c 8.21 (Berkeley) 05/23/95 (with USERDB)"; 14 #else 15 static char sccsid [] = "@(#)udb.c 8.21 (Berkeley) 05/23/95 (without USERDB)"; 16 #endif 17 #endif 18 19 #ifdef USERDB 20 21 #include <errno.h> 22 #include <db.h> 23 24 #ifdef HESIOD 25 #include <hesiod.h> 26 #endif /* HESIOD */ 27 28 /* 29 ** UDB.C -- interface between sendmail and Berkeley User Data Base. 30 ** 31 ** This depends on the 4.4BSD db package. 32 */ 33 34 35 struct udbent 36 { 37 char *udb_spec; /* string version of spec */ 38 int udb_type; /* type of entry */ 39 char *udb_default; /* default host for outgoing mail */ 40 union 41 { 42 /* type UE_REMOTE -- do remote call for lookup */ 43 struct 44 { 45 struct sockaddr_in _udb_addr; /* address */ 46 int _udb_timeout; /* timeout */ 47 } udb_remote; 48 #define udb_addr udb_u.udb_remote._udb_addr 49 #define udb_timeout udb_u.udb_remote._udb_timeout 50 51 /* type UE_FORWARD -- forward message to remote */ 52 struct 53 { 54 char *_udb_fwdhost; /* name of forward host */ 55 } udb_forward; 56 #define udb_fwdhost udb_u.udb_forward._udb_fwdhost 57 58 /* type UE_FETCH -- lookup in local database */ 59 struct 60 { 61 char *_udb_dbname; /* pathname of database */ 62 DB *_udb_dbp; /* open database ptr */ 63 } udb_lookup; 64 #define udb_dbname udb_u.udb_lookup._udb_dbname 65 #define udb_dbp udb_u.udb_lookup._udb_dbp 66 } udb_u; 67 }; 68 69 #define UDB_EOLIST 0 /* end of list */ 70 #define UDB_SKIP 1 /* skip this entry */ 71 #define UDB_REMOTE 2 /* look up in remote database */ 72 #define UDB_DBFETCH 3 /* look up in local database */ 73 #define UDB_FORWARD 4 /* forward to remote host */ 74 #define UDB_HESIOD 5 /* look up via hesiod */ 75 76 #define MAXUDBENT 10 /* maximum number of UDB entries */ 77 78 79 struct option 80 { 81 char *name; 82 char *val; 83 }; 84 /* 85 ** UDBEXPAND -- look up user in database and expand 86 ** 87 ** Parameters: 88 ** a -- address to expand. 89 ** sendq -- pointer to head of sendq to put the expansions in. 90 ** aliaslevel -- the current alias nesting depth. 91 ** e -- the current envelope. 92 ** 93 ** Returns: 94 ** EX_TEMPFAIL -- if something "odd" happened -- probably due 95 ** to accessing a file on an NFS server that is down. 96 ** EX_OK -- otherwise. 97 ** 98 ** Side Effects: 99 ** Modifies sendq. 100 */ 101 102 int UdbPort = 1616; 103 int UdbTimeout = 10; 104 105 struct udbent UdbEnts[MAXUDBENT + 1]; 106 int UdbSock = -1; 107 bool UdbInitialized = FALSE; 108 109 int 110 udbexpand(a, sendq, aliaslevel, e) 111 register ADDRESS *a; 112 ADDRESS **sendq; 113 int aliaslevel; 114 register ENVELOPE *e; 115 { 116 int i; 117 register char *p; 118 DBT key; 119 DBT info; 120 bool breakout; 121 register struct udbent *up; 122 int keylen; 123 int naddrs; 124 char keybuf[MAXKEY]; 125 char buf[BUFSIZ]; 126 127 if (tTd(28, 1)) 128 printf("udbexpand(%s)\n", a->q_paddr); 129 130 /* make certain we are supposed to send to this address */ 131 if (bitset(QDONTSEND|QVERIFIED, a->q_flags)) 132 return EX_OK; 133 e->e_to = a->q_paddr; 134 135 /* on first call, locate the database */ 136 if (!UdbInitialized) 137 { 138 extern int _udbx_init(); 139 140 if (_udbx_init() == EX_TEMPFAIL) 141 return EX_TEMPFAIL; 142 } 143 144 /* short circuit the process if no chance of a match */ 145 if (UdbSpec == NULL || UdbSpec[0] == '\0') 146 return EX_OK; 147 148 /* short circuit name begins with '\\' since it can't possibly match */ 149 if (a->q_user[0] == '\\') 150 return EX_OK; 151 152 /* if name is too long, assume it won't match */ 153 if (strlen(a->q_user) > sizeof keybuf - 12) 154 return EX_OK; 155 156 /* if name begins with a colon, it indicates our metadata */ 157 if (a->q_user[0] == ':') 158 return EX_OK; 159 160 /* build actual database key */ 161 (void) strcpy(keybuf, a->q_user); 162 (void) strcat(keybuf, ":maildrop"); 163 keylen = strlen(keybuf); 164 165 breakout = FALSE; 166 for (up = UdbEnts; !breakout; up++) 167 { 168 char *user; 169 170 /* 171 ** Select action based on entry type. 172 ** 173 ** On dropping out of this switch, "class" should 174 ** explain the type of the data, and "user" should 175 ** contain the user information. 176 */ 177 178 switch (up->udb_type) 179 { 180 #ifdef NEWDB 181 case UDB_DBFETCH: 182 key.data = keybuf; 183 key.size = keylen; 184 if (tTd(28, 80)) 185 printf("udbexpand: trying %s (%d) via db\n", 186 keybuf, keylen); 187 i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR); 188 if (i > 0 || info.size <= 0) 189 { 190 if (tTd(28, 2)) 191 printf("udbexpand: no match on %s (%d)\n", 192 keybuf, keylen); 193 continue; 194 } 195 if (tTd(28, 80)) 196 printf("udbexpand: match %.*s: %.*s\n", 197 key.size, key.data, info.size, info.data); 198 199 naddrs = 0; 200 a->q_flags &= ~QSELFREF; 201 while (i == 0 && key.size == keylen && 202 bcmp(key.data, keybuf, keylen) == 0) 203 { 204 if (bitset(EF_VRFYONLY, e->e_flags)) 205 { 206 a->q_flags |= QVERIFIED; 207 e->e_nrcpts++; 208 return EX_OK; 209 } 210 211 breakout = TRUE; 212 if (info.size < sizeof buf) 213 user = buf; 214 else 215 user = xalloc(info.size + 1); 216 bcopy(info.data, user, info.size); 217 user[info.size] = '\0'; 218 219 message("expanded to %s", user); 220 #ifdef LOG 221 if (LogLevel >= 10) 222 syslog(LOG_INFO, "%s: expand %s => %s", 223 e->e_id, e->e_to, user); 224 #endif 225 naddrs += sendtolist(user, a, sendq, aliaslevel + 1, e); 226 227 if (user != buf) 228 free(user); 229 230 /* get the next record */ 231 i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT); 232 } 233 234 /* if nothing ever matched, try next database */ 235 if (!breakout) 236 continue; 237 238 if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) 239 { 240 if (tTd(28, 5)) 241 { 242 printf("udbexpand: QDONTSEND "); 243 printaddr(a, FALSE); 244 } 245 a->q_flags |= QDONTSEND; 246 } 247 if (i < 0) 248 { 249 syserr("udbexpand: db-get %.*s stat %d", 250 key.size, key.data, i); 251 return EX_TEMPFAIL; 252 } 253 254 /* 255 ** If this address has a -request address, reflect 256 ** it into the envelope. 257 */ 258 259 (void) strcpy(keybuf, a->q_user); 260 (void) strcat(keybuf, ":mailsender"); 261 keylen = strlen(keybuf); 262 key.data = keybuf; 263 key.size = keylen; 264 i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); 265 if (i != 0 || info.size <= 0) 266 break; 267 a->q_owner = xalloc(info.size + 1); 268 bcopy(info.data, a->q_owner, info.size); 269 a->q_owner[info.size] = '\0'; 270 271 /* announce delivery; NORECEIPT bit set later */ 272 if (e->e_xfp != NULL) 273 { 274 fprintf(e->e_xfp, 275 "Message delivered to mailing list %s\n", 276 a->q_paddr); 277 } 278 e->e_flags |= EF_SENDRECEIPT; 279 a->q_flags |= QDELIVERED|QEXPANDED; 280 break; 281 #endif 282 283 #ifdef HESIOD 284 case UDB_HESIOD: 285 key.data = keybuf; 286 key.size = keylen; 287 if (tTd(28, 80)) 288 printf("udbexpand: trying %s (%d) via hesiod\n", 289 keybuf, keylen); 290 /* look up the key via hesiod */ 291 i = hes_udb_get(&key, &info); 292 if (i < 0) 293 { 294 syserr("udbexpand: hesiod-get %.*s stat %d", 295 key.size, key.data, i); 296 return EX_TEMPFAIL; 297 } 298 else if (i > 0 || info.size <= 0) 299 { 300 if (tTd(28, 2)) 301 printf("udbexpand: no match on %s (%d)\n", 302 keybuf, keylen); 303 continue; 304 } 305 if (tTd(28, 80)) 306 printf("udbexpand: match %.*s: %.*s\n", 307 key.size, key.data, info.size, info.data); 308 a->q_flags &= ~QSELFREF; 309 310 if (bitset(EF_VRFYONLY, e->e_flags)) 311 { 312 a->q_flags |= QVERIFIED; 313 e->e_nrcpts++; 314 return EX_OK; 315 } 316 317 breakout = TRUE; 318 if (info.size < sizeof buf) 319 user = buf; 320 else 321 user = xalloc(info.size + 1); 322 bcopy(info.data, user, info.size); 323 user[info.size] = '\0'; 324 325 message("hesioded to %s", user); 326 #ifdef LOG 327 if (LogLevel >= 10) 328 syslog(LOG_INFO, "%s: hesiod %s => %s", 329 e->e_id, e->e_to, user); 330 #endif 331 naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e); 332 333 if (user != buf) 334 free(user); 335 336 if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) 337 { 338 if (tTd(28, 5)) 339 { 340 printf("udbexpand: QDONTSEND "); 341 printaddr(a, FALSE); 342 } 343 a->q_flags |= QDONTSEND; 344 } 345 346 /* 347 ** If this address has a -request address, reflect 348 ** it into the envelope. 349 */ 350 351 (void) strcpy(keybuf, a->q_user); 352 (void) strcat(keybuf, ":mailsender"); 353 keylen = strlen(keybuf); 354 key.data = keybuf; 355 key.size = keylen; 356 i = hes_udb_get(&key, &info); 357 if (i != 0 || info.size <= 0) 358 break; 359 a->q_owner = xalloc(info.size + 1); 360 bcopy(info.data, a->q_owner, info.size); 361 a->q_owner[info.size] = '\0'; 362 break; 363 #endif /* HESIOD */ 364 365 case UDB_REMOTE: 366 /* not yet implemented */ 367 continue; 368 369 case UDB_FORWARD: 370 if (bitset(EF_VRFYONLY, e->e_flags)) 371 return EX_OK; 372 i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1; 373 if (i < sizeof buf) 374 user = buf; 375 else 376 user = xalloc(i + 1); 377 (void) sprintf(user, "%s@%s", a->q_user, up->udb_fwdhost); 378 message("expanded to %s", user); 379 a->q_flags &= ~QSELFREF; 380 naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e); 381 if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) 382 { 383 if (tTd(28, 5)) 384 { 385 printf("udbexpand: QDONTSEND "); 386 printaddr(a, FALSE); 387 } 388 a->q_flags |= QDONTSEND; 389 } 390 if (user != buf) 391 free(user); 392 breakout = TRUE; 393 break; 394 395 case UDB_EOLIST: 396 breakout = TRUE; 397 continue; 398 399 default: 400 /* unknown entry type */ 401 continue; 402 } 403 } 404 return EX_OK; 405 } 406 /* 407 ** UDBSENDER -- return canonical external name of sender, given local name 408 ** 409 ** Parameters: 410 ** sender -- the name of the sender on the local machine. 411 ** 412 ** Returns: 413 ** The external name for this sender, if derivable from the 414 ** database. 415 ** NULL -- if nothing is changed from the database. 416 ** 417 ** Side Effects: 418 ** none. 419 */ 420 421 char * 422 udbsender(sender) 423 char *sender; 424 { 425 extern char *udbmatch(); 426 427 return udbmatch(sender, "mailname"); 428 } 429 430 431 char * 432 udbmatch(user, field) 433 char *user; 434 char *field; 435 { 436 register char *p; 437 register struct udbent *up; 438 int i; 439 int keylen; 440 DBT key, info; 441 char keybuf[MAXKEY]; 442 443 if (tTd(28, 1)) 444 printf("udbmatch(%s, %s)\n", user, field); 445 446 if (!UdbInitialized) 447 { 448 if (_udbx_init() == EX_TEMPFAIL) 449 return NULL; 450 } 451 452 /* short circuit if no spec */ 453 if (UdbSpec == NULL || UdbSpec[0] == '\0') 454 return NULL; 455 456 /* short circuit name begins with '\\' since it can't possibly match */ 457 if (user[0] == '\\') 458 return NULL; 459 460 /* long names can never match and are a pain to deal with */ 461 if ((strlen(user) + strlen(field)) > sizeof keybuf - 4) 462 return NULL; 463 464 /* names beginning with colons indicate metadata */ 465 if (user[0] == ':') 466 return NULL; 467 468 /* build database key */ 469 (void) strcpy(keybuf, user); 470 (void) strcat(keybuf, ":"); 471 (void) strcat(keybuf, field); 472 keylen = strlen(keybuf); 473 474 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++) 475 { 476 /* 477 ** Select action based on entry type. 478 */ 479 480 switch (up->udb_type) 481 { 482 #ifdef NEWDB 483 case UDB_DBFETCH: 484 key.data = keybuf; 485 key.size = keylen; 486 i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); 487 if (i != 0 || info.size <= 0) 488 { 489 if (tTd(28, 2)) 490 printf("udbmatch: no match on %s (%d) via db\n", 491 keybuf, keylen); 492 continue; 493 } 494 495 p = xalloc(info.size + 1); 496 bcopy(info.data, p, info.size); 497 p[info.size] = '\0'; 498 if (tTd(28, 1)) 499 printf("udbmatch ==> %s\n", p); 500 return p; 501 break; 502 #endif 503 504 #ifdef HESIOD 505 case UDB_HESIOD: 506 key.data = keybuf; 507 key.size = keylen; 508 i = hes_udb_get(&key, &info); 509 if (i != 0 || info.size <= 0) 510 { 511 if (tTd(28, 2)) 512 printf("udbmatch: no match on %s (%d) via hesiod\n", 513 keybuf, keylen); 514 continue; 515 } 516 517 p = xalloc(info.size + 1); 518 bcopy(info.data, p, info.size); 519 p[info.size] = '\0'; 520 if (tTd(28, 1)) 521 printf("udbmatch ==> %s\n", p); 522 return p; 523 #endif /* HESIOD */ 524 } 525 } 526 527 if (strcmp(field, "mailname") != 0) 528 return NULL; 529 530 /* 531 ** Nothing yet. Search again for a default case. But only 532 ** use it if we also have a forward (:maildrop) pointer already 533 ** in the database. 534 */ 535 536 /* build database key */ 537 (void) strcpy(keybuf, user); 538 (void) strcat(keybuf, ":maildrop"); 539 keylen = strlen(keybuf); 540 541 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++) 542 { 543 switch (up->udb_type) 544 { 545 #ifdef NEWDB 546 case UDB_DBFETCH: 547 /* get the default case for this database */ 548 if (up->udb_default == NULL) 549 { 550 key.data = ":default:mailname"; 551 key.size = strlen(key.data); 552 i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); 553 if (i != 0 || info.size <= 0) 554 { 555 /* no default case */ 556 up->udb_default = ""; 557 continue; 558 } 559 560 /* save the default case */ 561 up->udb_default = xalloc(info.size + 1); 562 bcopy(info.data, up->udb_default, info.size); 563 up->udb_default[info.size] = '\0'; 564 } 565 else if (up->udb_default[0] == '\0') 566 continue; 567 568 /* we have a default case -- verify user:maildrop */ 569 key.data = keybuf; 570 key.size = keylen; 571 i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); 572 if (i != 0 || info.size <= 0) 573 { 574 /* nope -- no aliasing for this user */ 575 continue; 576 } 577 578 /* they exist -- build the actual address */ 579 p = xalloc(strlen(user) + strlen(up->udb_default) + 2); 580 (void) strcpy(p, user); 581 (void) strcat(p, "@"); 582 (void) strcat(p, up->udb_default); 583 if (tTd(28, 1)) 584 printf("udbmatch ==> %s\n", p); 585 return p; 586 break; 587 #endif 588 589 #ifdef HESIOD 590 case UDB_HESIOD: 591 /* get the default case for this database */ 592 if (up->udb_default == NULL) 593 { 594 key.data = ":default:mailname"; 595 key.size = strlen(key.data); 596 i = hes_udb_get(&key, &info); 597 598 if (i != 0 || info.size <= 0) 599 { 600 /* no default case */ 601 up->udb_default = ""; 602 continue; 603 } 604 605 /* save the default case */ 606 up->udb_default = xalloc(info.size + 1); 607 bcopy(info.data, up->udb_default, info.size); 608 up->udb_default[info.size] = '\0'; 609 } 610 else if (up->udb_default[0] == '\0') 611 continue; 612 613 /* we have a default case -- verify user:maildrop */ 614 key.data = keybuf; 615 key.size = keylen; 616 i = hes_udb_get(&key, &info); 617 if (i != 0 || info.size <= 0) 618 { 619 /* nope -- no aliasing for this user */ 620 continue; 621 } 622 623 /* they exist -- build the actual address */ 624 p = xalloc(strlen(user) + strlen(up->udb_default) + 2); 625 (void) strcpy(p, user); 626 (void) strcat(p, "@"); 627 (void) strcat(p, up->udb_default); 628 if (tTd(28, 1)) 629 printf("udbmatch ==> %s\n", p); 630 return p; 631 break; 632 #endif /* HESIOD */ 633 } 634 } 635 636 /* still nothing.... too bad */ 637 return NULL; 638 } 639 /* 640 ** UDB_MAP_LOOKUP -- look up arbitrary entry in user database map 641 ** 642 ** Parameters: 643 ** map -- the map being queried. 644 ** name -- the name to look up. 645 ** av -- arguments to the map lookup. 646 ** statp -- to get any error status. 647 ** 648 ** Returns: 649 ** NULL if name not found in map. 650 ** The rewritten name otherwise. 651 */ 652 653 char * 654 udb_map_lookup(map, name, av, statp) 655 MAP *map; 656 char *name; 657 char **av; 658 int *statp; 659 { 660 char *val; 661 662 if (tTd(38, 20)) 663 printf("udb_map_lookup(%s, %s)\n", map->map_mname, name); 664 val = udbmatch(name, map->map_file); 665 if (val == NULL) 666 return NULL; 667 if (bitset(MF_MATCHONLY, map->map_mflags)) 668 return map_rewrite(map, name, strlen(name), NULL); 669 else 670 return map_rewrite(map, val, strlen(val), av); 671 } 672 /* 673 ** _UDBX_INIT -- parse the UDB specification, opening any valid entries. 674 ** 675 ** Parameters: 676 ** none. 677 ** 678 ** Returns: 679 ** EX_TEMPFAIL -- if it appeared it couldn't get hold of a 680 ** database due to a host being down or some similar 681 ** (recoverable) situation. 682 ** EX_OK -- otherwise. 683 ** 684 ** Side Effects: 685 ** Fills in the UdbEnts structure from UdbSpec. 686 */ 687 688 #define MAXUDBOPTS 27 689 690 int 691 _udbx_init() 692 { 693 register char *p; 694 int i; 695 register struct udbent *up; 696 char buf[BUFSIZ]; 697 698 if (UdbInitialized) 699 return EX_OK; 700 701 # ifdef UDB_DEFAULT_SPEC 702 if (UdbSpec == NULL) 703 UdbSpec = UDB_DEFAULT_SPEC; 704 # endif 705 706 p = UdbSpec; 707 up = UdbEnts; 708 while (p != NULL) 709 { 710 char *spec; 711 auto int rcode; 712 int nopts; 713 int nmx; 714 register struct hostent *h; 715 char *mxhosts[MAXMXHOSTS + 1]; 716 struct option opts[MAXUDBOPTS + 1]; 717 718 while (*p == ' ' || *p == '\t' || *p == ',') 719 p++; 720 if (*p == '\0') 721 break; 722 spec = p; 723 p = strchr(p, ','); 724 if (p != NULL) 725 *p++ = '\0'; 726 727 /* extract options */ 728 nopts = _udb_parsespec(spec, opts, MAXUDBOPTS); 729 730 /* 731 ** Decode database specification. 732 ** 733 ** In the sendmail tradition, the leading character 734 ** defines the semantics of the rest of the entry. 735 ** 736 ** +hostname -- send a datagram to the udb server 737 ** on host "hostname" asking for the 738 ** home mail server for this user. 739 ** *hostname -- similar to +hostname, except that the 740 ** hostname is searched as an MX record; 741 ** resulting hosts are searched as for 742 ** +mxhostname. If no MX host is found, 743 ** this is the same as +hostname. 744 ** @hostname -- forward email to the indicated host. 745 ** This should be the last in the list, 746 ** since it always matches the input. 747 ** /dbname -- search the named database on the local 748 ** host using the Berkeley db package. 749 */ 750 751 switch (*spec) 752 { 753 #if 0 754 case '+': /* search remote database */ 755 case '*': /* search remote database (expand MX) */ 756 if (*spec == '*') 757 { 758 #if NAMED_BIND 759 nmx = getmxrr(spec + 1, mxhosts, FALSE, &rcode); 760 #else 761 mxhosts[0] = spec + 1; 762 nmx = 1; 763 rcode = 0; 764 #endif 765 if (tTd(28, 16)) 766 { 767 int i; 768 769 printf("getmxrr(%s): %d", spec + 1, nmx); 770 for (i = 0; i <= nmx; i++) 771 printf(" %s", mxhosts[i]); 772 printf("\n"); 773 } 774 } 775 else 776 { 777 nmx = 1; 778 mxhosts[0] = spec + 1; 779 } 780 781 for (i = 0; i < nmx; i++) 782 { 783 h = sm_gethostbyname(mxhosts[i]); 784 if (h == NULL) 785 continue; 786 up->udb_type = UDB_REMOTE; 787 up->udb_addr.sin_family = h->h_addrtype; 788 bcopy(h->h_addr_list[0], 789 (char *) &up->udb_addr.sin_addr, 790 INADDRSZ); 791 up->udb_addr.sin_port = UdbPort; 792 up->udb_timeout = UdbTimeout; 793 up++; 794 } 795 796 /* set up a datagram socket */ 797 if (UdbSock < 0) 798 { 799 UdbSock = socket(AF_INET, SOCK_DGRAM, 0); 800 (void) fcntl(UdbSock, F_SETFD, 1); 801 } 802 break; 803 #endif 804 805 case '@': /* forward to remote host */ 806 up->udb_type = UDB_FORWARD; 807 up->udb_fwdhost = spec + 1; 808 up++; 809 break; 810 811 #ifdef HESIOD 812 case 'h': /* use hesiod */ 813 case 'H': 814 if (strcasecmp(spec, "hesiod") != 0) 815 goto badspec; 816 up->udb_type = UDB_HESIOD; 817 up++; 818 break; 819 #endif /* HESIOD */ 820 821 #ifdef NEWDB 822 case '/': /* look up remote name */ 823 up->udb_dbname = spec; 824 errno = 0; 825 up->udb_dbp = dbopen(spec, O_RDONLY, 0644, DB_BTREE, NULL); 826 if (up->udb_dbp == NULL) 827 { 828 if (tTd(28, 1)) 829 { 830 int saveerrno = errno; 831 832 printf("dbopen(%s): %s", 833 spec, errstring(errno)); 834 errno = saveerrno; 835 } 836 if (errno != ENOENT && errno != EACCES) 837 { 838 #ifdef LOG 839 if (LogLevel > 2) 840 syslog(LOG_ERR, "dbopen(%s): %s", 841 spec, errstring(errno)); 842 #endif 843 up->udb_type = UDB_EOLIST; 844 goto tempfail; 845 } 846 break; 847 } 848 up->udb_type = UDB_DBFETCH; 849 up++; 850 break; 851 #endif 852 853 default: 854 badspec: 855 syserr("Unknown UDB spec %s", spec); 856 break; 857 } 858 } 859 up->udb_type = UDB_EOLIST; 860 861 if (tTd(28, 4)) 862 { 863 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++) 864 { 865 switch (up->udb_type) 866 { 867 case UDB_REMOTE: 868 printf("REMOTE: addr %s, timeo %d\n", 869 anynet_ntoa((SOCKADDR *) &up->udb_addr), 870 up->udb_timeout); 871 break; 872 873 case UDB_DBFETCH: 874 printf("FETCH: file %s\n", 875 up->udb_dbname); 876 break; 877 878 case UDB_FORWARD: 879 printf("FORWARD: host %s\n", 880 up->udb_fwdhost); 881 break; 882 883 case UDB_HESIOD: 884 printf("HESIOD\n"); 885 break; 886 887 default: 888 printf("UNKNOWN\n"); 889 break; 890 } 891 } 892 } 893 894 UdbInitialized = TRUE; 895 errno = 0; 896 return EX_OK; 897 898 /* 899 ** On temporary failure, back out anything we've already done 900 */ 901 902 tempfail: 903 #ifdef NEWDB 904 for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++) 905 { 906 if (up->udb_type == UDB_DBFETCH) 907 { 908 (*up->udb_dbp->close)(up->udb_dbp); 909 } 910 } 911 #endif 912 return EX_TEMPFAIL; 913 } 914 915 int 916 _udb_parsespec(udbspec, opt, maxopts) 917 char *udbspec; 918 struct option opt[]; 919 int maxopts; 920 { 921 register char *spec; 922 register char *spec_end; 923 register int optnum; 924 925 spec_end = strchr(udbspec, ':'); 926 for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++) 927 { 928 register char *p; 929 930 while (isascii(*spec) && isspace(*spec)) 931 spec++; 932 spec_end = strchr(spec, ':'); 933 if (spec_end != NULL) 934 *spec_end++ = '\0'; 935 936 opt[optnum].name = spec; 937 opt[optnum].val = NULL; 938 p = strchr(spec, '='); 939 if (p != NULL) 940 opt[optnum].val = ++p; 941 } 942 return optnum; 943 } 944 945 #ifdef HESIOD 946 947 int 948 hes_udb_get(key, info) 949 DBT *key; 950 DBT *info; 951 { 952 char *name, *type; 953 char *p, **hp; 954 char kbuf[MAXKEY + 1]; 955 956 strcpy(kbuf, key->data); 957 name = kbuf; 958 type = strchr(name, ':'); 959 if (type == NULL) 960 return 1; 961 *type++ = '\0'; 962 963 if (tTd(28, 1)) 964 printf("hes_udb_get(%s, %s)\n", name, type); 965 966 /* make the hesiod query */ 967 hp = hes_resolve(name, type); 968 if (hp == NULL) 969 { 970 /* network problem or timeout */ 971 if (hes_error() == HES_ER_NET) 972 return -1; 973 974 return 1; 975 } 976 else 977 { 978 /* 979 ** If there are multiple matches, just return the 980 ** first one. 981 ** 982 ** XXX These should really be returned; for example, 983 ** XXX it is legal for :maildrop to be multi-valued. 984 */ 985 986 info->data = hp[0]; 987 info->size = (size_t) strlen(info->data); 988 } 989 990 return 0; 991 } 992 #endif /* HESIOD */ 993 994 #else /* not USERDB */ 995 996 int 997 udbexpand(a, sendq, aliaslevel, e) 998 ADDRESS *a; 999 ADDRESS **sendq; 1000 int aliaslevel; 1001 ENVELOPE *e; 1002 { 1003 return EX_OK; 1004 } 1005 1006 #endif /* USERDB */ 1007