1 /* 2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 * Copyright (c) 1988, 1993 10 * The Regents of the University of California. All rights reserved. 11 */ 12 13 # include "sendmail.h" 14 15 #ifndef lint 16 static char sccsid[] = "@(#)alias.c 8.92 (Berkeley) 6/5/98"; 17 #endif /* not lint */ 18 19 20 MAP *AliasFileMap = NULL; /* the actual aliases.files map */ 21 int NAliasFileMaps; /* the number of entries in AliasFileMap */ 22 /* 23 ** ALIAS -- Compute aliases. 24 ** 25 ** Scans the alias file for an alias for the given address. 26 ** If found, it arranges to deliver to the alias list instead. 27 ** Uses libdbm database if -DDBM. 28 ** 29 ** Parameters: 30 ** a -- address to alias. 31 ** sendq -- a pointer to the head of the send queue 32 ** to put the aliases in. 33 ** aliaslevel -- the current alias nesting depth. 34 ** e -- the current envelope. 35 ** 36 ** Returns: 37 ** none 38 ** 39 ** Side Effects: 40 ** Aliases found are expanded. 41 ** 42 ** Deficiencies: 43 ** It should complain about names that are aliased to 44 ** nothing. 45 */ 46 47 void 48 alias(a, sendq, aliaslevel, e) 49 register ADDRESS *a; 50 ADDRESS **sendq; 51 int aliaslevel; 52 register ENVELOPE *e; 53 { 54 register char *p; 55 char *owner; 56 auto int stat = EX_OK; 57 char obuf[MAXNAME + 7]; 58 extern char *aliaslookup __P((char *, int *, ENVELOPE *)); 59 60 if (tTd(27, 1)) 61 printf("alias(%s)\n", a->q_user); 62 63 /* don't realias already aliased names */ 64 if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags)) 65 return; 66 67 if (NoAlias) 68 return; 69 70 e->e_to = a->q_paddr; 71 72 /* 73 ** Look up this name. 74 ** 75 ** If the map was unavailable, we will queue this message 76 ** until the map becomes available; otherwise, we could 77 ** bounce messages inappropriately. 78 */ 79 80 p = aliaslookup(a->q_user, &stat, e); 81 if (stat == EX_TEMPFAIL || stat == EX_UNAVAILABLE) 82 { 83 a->q_flags |= QQUEUEUP; 84 if (e->e_message == NULL) 85 e->e_message = newstr("alias database unavailable"); 86 return; 87 } 88 if (p == NULL) 89 return; 90 91 /* 92 ** Match on Alias. 93 ** Deliver to the target list. 94 */ 95 96 if (tTd(27, 1)) 97 printf("%s (%s, %s) aliased to %s\n", 98 a->q_paddr, a->q_host, a->q_user, p); 99 if (bitset(EF_VRFYONLY, e->e_flags)) 100 { 101 a->q_flags |= QVERIFIED; 102 return; 103 } 104 message("aliased to %s", shortenstring(p, MAXSHORTSTR)); 105 if (LogLevel > 9) 106 sm_syslog(LOG_INFO, e->e_id, 107 "alias %.100s => %s", 108 a->q_paddr, shortenstring(p, MAXSHORTSTR)); 109 a->q_flags &= ~QSELFREF; 110 if (tTd(27, 5)) 111 { 112 printf("alias: QDONTSEND "); 113 printaddr(a, FALSE); 114 } 115 a->q_flags |= QDONTSEND; 116 (void) sendtolist(p, a, sendq, aliaslevel + 1, e); 117 if (bitset(QSELFREF, a->q_flags)) 118 a->q_flags &= ~QDONTSEND; 119 120 /* 121 ** Look for owner of alias 122 */ 123 124 (void) strcpy(obuf, "owner-"); 125 if (strncmp(a->q_user, "owner-", 6) == 0 || 126 strlen(a->q_user) > (SIZE_T) sizeof obuf - 7) 127 (void) strcat(obuf, "owner"); 128 else 129 (void) strcat(obuf, a->q_user); 130 owner = aliaslookup(obuf, &stat, e); 131 if (owner == NULL) 132 return; 133 134 /* reflect owner into envelope sender */ 135 if (strpbrk(owner, ",:/|\"") != NULL) 136 owner = obuf; 137 a->q_owner = newstr(owner); 138 139 /* announce delivery to this alias; NORECEIPT bit set later */ 140 if (e->e_xfp != NULL) 141 fprintf(e->e_xfp, "Message delivered to mailing list %s\n", 142 a->q_paddr); 143 e->e_flags |= EF_SENDRECEIPT; 144 a->q_flags |= QDELIVERED|QEXPANDED; 145 } 146 /* 147 ** ALIASLOOKUP -- look up a name in the alias file. 148 ** 149 ** Parameters: 150 ** name -- the name to look up. 151 ** pstat -- a pointer to a place to put the status. 152 ** e -- the current envelope. 153 ** 154 ** Returns: 155 ** the value of name. 156 ** NULL if unknown. 157 ** 158 ** Side Effects: 159 ** none. 160 ** 161 ** Warnings: 162 ** The return value will be trashed across calls. 163 */ 164 165 char * 166 aliaslookup(name, pstat, e) 167 char *name; 168 int *pstat; 169 ENVELOPE *e; 170 { 171 static MAP *map = NULL; 172 173 if (map == NULL) 174 { 175 STAB *s = stab("aliases", ST_MAP, ST_FIND); 176 177 if (s == NULL) 178 return NULL; 179 map = &s->s_map; 180 } 181 if (!bitset(MF_OPEN, map->map_mflags)) 182 return NULL; 183 184 /* special case POstMastER -- always use lower case */ 185 if (strcasecmp(name, "postmaster") == 0) 186 name = "postmaster"; 187 188 return (*map->map_class->map_lookup)(map, name, NULL, pstat); 189 } 190 /* 191 ** SETALIAS -- set up an alias map 192 ** 193 ** Called when reading configuration file. 194 ** 195 ** Parameters: 196 ** spec -- the alias specification 197 ** 198 ** Returns: 199 ** none. 200 */ 201 202 void 203 setalias(spec) 204 char *spec; 205 { 206 register char *p; 207 register MAP *map; 208 char *class; 209 STAB *s; 210 211 if (tTd(27, 8)) 212 printf("setalias(%s)\n", spec); 213 214 for (p = spec; p != NULL; ) 215 { 216 char buf[50]; 217 218 while (isascii(*p) && isspace(*p)) 219 p++; 220 if (*p == '\0') 221 break; 222 spec = p; 223 224 if (NAliasFileMaps >= MAXMAPSTACK) 225 { 226 syserr("Too many alias databases defined, %d max", 227 MAXMAPSTACK); 228 return; 229 } 230 if (AliasFileMap == NULL) 231 { 232 strcpy(buf, "aliases.files sequence"); 233 AliasFileMap = makemapentry(buf); 234 if (AliasFileMap == NULL) 235 { 236 syserr("setalias: cannot create aliases.files map"); 237 return; 238 } 239 } 240 (void) snprintf(buf, sizeof buf, "Alias%d", NAliasFileMaps); 241 s = stab(buf, ST_MAP, ST_ENTER); 242 map = &s->s_map; 243 bzero(map, sizeof *map); 244 map->map_mname = s->s_name; 245 246 p = strpbrk(p, " ,/:"); 247 if (p != NULL && *p == ':') 248 { 249 /* map name */ 250 *p++ = '\0'; 251 class = spec; 252 spec = p; 253 } 254 else 255 { 256 class = "implicit"; 257 map->map_mflags = MF_INCLNULL; 258 } 259 260 /* find end of spec */ 261 if (p != NULL) 262 p = strchr(p, ','); 263 if (p != NULL) 264 *p++ = '\0'; 265 266 if (tTd(27, 20)) 267 printf(" map %s:%s %s\n", class, s->s_name, spec); 268 269 /* look up class */ 270 s = stab(class, ST_MAPCLASS, ST_FIND); 271 if (s == NULL) 272 { 273 syserr("setalias: unknown alias class %s", class); 274 } 275 else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags)) 276 { 277 syserr("setalias: map class %s can't handle aliases", 278 class); 279 } 280 else 281 { 282 map->map_class = &s->s_mapclass; 283 if (map->map_class->map_parse(map, spec)) 284 { 285 map->map_mflags |= MF_VALID|MF_ALIAS; 286 AliasFileMap->map_stack[NAliasFileMaps++] = map; 287 } 288 } 289 } 290 } 291 /* 292 ** ALIASWAIT -- wait for distinguished @:@ token to appear. 293 ** 294 ** This can decide to reopen or rebuild the alias file 295 ** 296 ** Parameters: 297 ** map -- a pointer to the map descriptor for this alias file. 298 ** ext -- the filename extension (e.g., ".db") for the 299 ** database file. 300 ** isopen -- if set, the database is already open, and we 301 ** should check for validity; otherwise, we are 302 ** just checking to see if it should be created. 303 ** 304 ** Returns: 305 ** TRUE -- if the database is open when we return. 306 ** FALSE -- if the database is closed when we return. 307 */ 308 309 bool 310 aliaswait(map, ext, isopen) 311 MAP *map; 312 char *ext; 313 int isopen; 314 { 315 bool attimeout = FALSE; 316 time_t mtime; 317 struct stat stb; 318 char buf[MAXNAME + 1]; 319 320 if (tTd(27, 3)) 321 printf("aliaswait(%s:%s)\n", 322 map->map_class->map_cname, map->map_file); 323 if (bitset(MF_ALIASWAIT, map->map_mflags)) 324 return isopen; 325 map->map_mflags |= MF_ALIASWAIT; 326 327 if (SafeAlias > 0) 328 { 329 auto int st; 330 time_t toolong = curtime() + SafeAlias; 331 unsigned int sleeptime = 2; 332 333 while (isopen && 334 map->map_class->map_lookup(map, "@", NULL, &st) == NULL) 335 { 336 if (curtime() > toolong) 337 { 338 /* we timed out */ 339 attimeout = TRUE; 340 break; 341 } 342 343 /* 344 ** Close and re-open the alias database in case 345 ** the one is mv'ed instead of cp'ed in. 346 */ 347 348 if (tTd(27, 2)) 349 printf("aliaswait: sleeping for %d seconds\n", 350 sleeptime); 351 352 map->map_class->map_close(map); 353 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 354 sleep(sleeptime); 355 sleeptime *= 2; 356 if (sleeptime > 60) 357 sleeptime = 60; 358 isopen = map->map_class->map_open(map, O_RDONLY); 359 } 360 } 361 362 /* see if we need to go into auto-rebuild mode */ 363 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 364 { 365 if (tTd(27, 3)) 366 printf("aliaswait: not rebuildable\n"); 367 map->map_mflags &= ~MF_ALIASWAIT; 368 return isopen; 369 } 370 if (stat(map->map_file, &stb) < 0) 371 { 372 if (tTd(27, 3)) 373 printf("aliaswait: no source file\n"); 374 map->map_mflags &= ~MF_ALIASWAIT; 375 return isopen; 376 } 377 mtime = stb.st_mtime; 378 snprintf(buf, sizeof buf, "%s%s", 379 map->map_file, ext == NULL ? "" : ext); 380 if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout) 381 { 382 /* database is out of date */ 383 if (AutoRebuild && stb.st_ino != 0 && 384 (stb.st_uid == geteuid() || 385 (geteuid() == 0 && stb.st_uid == TrustedFileUid))) 386 { 387 bool oldSuprErrs; 388 389 message("auto-rebuilding alias database %s", buf); 390 oldSuprErrs = SuprErrs; 391 SuprErrs = TRUE; 392 if (isopen) 393 { 394 map->map_class->map_close(map); 395 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 396 } 397 (void) rebuildaliases(map, TRUE); 398 isopen = map->map_class->map_open(map, O_RDONLY); 399 SuprErrs = oldSuprErrs; 400 } 401 else 402 { 403 if (LogLevel > 3) 404 sm_syslog(LOG_INFO, NOQID, 405 "alias database %s out of date", 406 buf); 407 message("Warning: alias database %s out of date", buf); 408 } 409 } 410 map->map_mflags &= ~MF_ALIASWAIT; 411 return isopen; 412 } 413 /* 414 ** REBUILDALIASES -- rebuild the alias database. 415 ** 416 ** Parameters: 417 ** map -- the database to rebuild. 418 ** automatic -- set if this was automatically generated. 419 ** 420 ** Returns: 421 ** TRUE if successful; FALSE otherwise. 422 ** 423 ** Side Effects: 424 ** Reads the text version of the database, builds the 425 ** DBM or DB version. 426 */ 427 428 bool 429 rebuildaliases(map, automatic) 430 register MAP *map; 431 bool automatic; 432 { 433 FILE *af; 434 bool nolock = FALSE; 435 bool success = FALSE; 436 int sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK; 437 sigfunc_t oldsigint, oldsigquit; 438 #ifdef SIGTSTP 439 sigfunc_t oldsigtstp; 440 #endif 441 442 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) 443 return FALSE; 444 445 if (!bitset(DBS_LINKEDALIASFILEINWRITABLEDIR, DontBlameSendmail)) 446 sff |= SFF_NOWLINK; 447 if (!bitset(DBS_GROUPWRITABLEALIASFILE, DontBlameSendmail)) 448 sff |= SFF_NOGWFILES; 449 if (!bitset(DBS_WORLDWRITABLEALIASFILE, DontBlameSendmail)) 450 sff |= SFF_NOWWFILES; 451 452 /* try to lock the source file */ 453 if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL) 454 { 455 struct stat stb; 456 457 if ((errno != EACCES && errno != EROFS) || automatic || 458 (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL) 459 { 460 int saveerr = errno; 461 462 if (tTd(27, 1)) 463 printf("Can't open %s: %s\n", 464 map->map_file, errstring(saveerr)); 465 if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags)) 466 message("newaliases: cannot open %s: %s", 467 map->map_file, errstring(saveerr)); 468 errno = 0; 469 return FALSE; 470 } 471 nolock = TRUE; 472 if (tTd(27, 1) || 473 fstat(fileno(af), &stb) < 0 || 474 bitset(S_IWUSR|S_IWGRP|S_IWOTH, stb.st_mode)) 475 message("warning: cannot lock %s: %s", 476 map->map_file, errstring(errno)); 477 } 478 479 /* see if someone else is rebuilding the alias file */ 480 if (!nolock && 481 !lockfile(fileno(af), map->map_file, NULL, LOCK_EX|LOCK_NB)) 482 { 483 /* yes, they are -- wait until done */ 484 message("Alias file %s is locked (maybe being rebuilt)", 485 map->map_file); 486 if (OpMode != MD_INITALIAS) 487 { 488 /* wait for other rebuild to complete */ 489 (void) lockfile(fileno(af), map->map_file, NULL, 490 LOCK_EX); 491 } 492 (void) xfclose(af, "rebuildaliases1", map->map_file); 493 errno = 0; 494 return FALSE; 495 } 496 497 oldsigint = setsignal(SIGINT, SIG_IGN); 498 oldsigquit = setsignal(SIGQUIT, SIG_IGN); 499 #ifdef SIGTSTP 500 oldsigtstp = setsignal(SIGTSTP, SIG_IGN); 501 #endif 502 503 if (map->map_class->map_open(map, O_RDWR)) 504 { 505 if (LogLevel > 7) 506 { 507 sm_syslog(LOG_NOTICE, NOQID, 508 "alias database %s %srebuilt by %s", 509 map->map_file, automatic ? "auto" : "", 510 username()); 511 } 512 map->map_mflags |= MF_OPEN|MF_WRITABLE; 513 readaliases(map, af, !automatic, TRUE); 514 success = TRUE; 515 } 516 else 517 { 518 if (tTd(27, 1)) 519 printf("Can't create database for %s: %s\n", 520 map->map_file, errstring(errno)); 521 if (!automatic) 522 syserr("Cannot create database for alias file %s", 523 map->map_file); 524 } 525 526 /* close the file, thus releasing locks */ 527 xfclose(af, "rebuildaliases2", map->map_file); 528 529 /* add distinguished entries and close the database */ 530 if (bitset(MF_OPEN, map->map_mflags)) 531 { 532 map->map_class->map_close(map); 533 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); 534 } 535 536 /* restore the old signals */ 537 (void) setsignal(SIGINT, oldsigint); 538 (void) setsignal(SIGQUIT, oldsigquit); 539 #ifdef SIGTSTP 540 (void) setsignal(SIGTSTP, oldsigtstp); 541 #endif 542 return success; 543 } 544 /* 545 ** READALIASES -- read and process the alias file. 546 ** 547 ** This routine implements the part of initaliases that occurs 548 ** when we are not going to use the DBM stuff. 549 ** 550 ** Parameters: 551 ** map -- the alias database descriptor. 552 ** af -- file to read the aliases from. 553 ** announcestats -- anounce statistics regarding number of 554 ** aliases, longest alias, etc. 555 ** logstats -- lot the same info. 556 ** 557 ** Returns: 558 ** none. 559 ** 560 ** Side Effects: 561 ** Reads aliasfile into the symbol table. 562 ** Optionally, builds the .dir & .pag files. 563 */ 564 565 void 566 readaliases(map, af, announcestats, logstats) 567 register MAP *map; 568 FILE *af; 569 bool announcestats; 570 bool logstats; 571 { 572 register char *p; 573 char *rhs; 574 bool skipping; 575 long naliases, bytes, longest; 576 ADDRESS al, bl; 577 char line[BUFSIZ]; 578 579 /* 580 ** Read and interpret lines 581 */ 582 583 FileName = map->map_file; 584 LineNumber = 0; 585 naliases = bytes = longest = 0; 586 skipping = FALSE; 587 while (fgets(line, sizeof (line), af) != NULL) 588 { 589 int lhssize, rhssize; 590 int c; 591 592 LineNumber++; 593 p = strchr(line, '\n'); 594 #if _FFR_BACKSLASH_IN_ALIASES 595 while (p != NULL && p > line && p[-1] == '\\') 596 { 597 p--; 598 if (fgets(p, SPACELEFT(line, p), af) == NULL) 599 break; 600 LineNumber++; 601 p = strchr(p, '\n'); 602 } 603 #endif 604 if (p != NULL) 605 *p = '\0'; 606 else if (!feof(af)) 607 { 608 syserr("554 alias line too long"); 609 610 /* flush to end of line */ 611 while ((c = getc(af)) != EOF && c != '\n') 612 continue; 613 614 /* skip any continuation lines */ 615 skipping = TRUE; 616 continue; 617 } 618 switch (line[0]) 619 { 620 case '#': 621 case '\0': 622 skipping = FALSE; 623 continue; 624 625 case ' ': 626 case '\t': 627 if (!skipping) 628 syserr("554 Non-continuation line starts with space"); 629 skipping = TRUE; 630 continue; 631 } 632 skipping = FALSE; 633 634 /* 635 ** Process the LHS 636 ** Find the colon separator, and parse the address. 637 ** It should resolve to a local name -- this will 638 ** be checked later (we want to optionally do 639 ** parsing of the RHS first to maximize error 640 ** detection). 641 */ 642 643 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 644 continue; 645 if (*p++ != ':') 646 { 647 syserr("554 missing colon"); 648 continue; 649 } 650 if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv) == NULL) 651 { 652 syserr("554 %.40s... illegal alias name", line); 653 continue; 654 } 655 656 /* 657 ** Process the RHS. 658 ** 'al' is the internal form of the LHS address. 659 ** 'p' points to the text of the RHS. 660 */ 661 662 while (isascii(*p) && isspace(*p)) 663 p++; 664 rhs = p; 665 for (;;) 666 { 667 register char *nlp; 668 669 nlp = &p[strlen(p)]; 670 if (nlp[-1] == '\n') 671 *--nlp = '\0'; 672 673 if (CheckAliases) 674 { 675 /* do parsing & compression of addresses */ 676 while (*p != '\0') 677 { 678 auto char *delimptr; 679 680 while ((isascii(*p) && isspace(*p)) || 681 *p == ',') 682 p++; 683 if (*p == '\0') 684 break; 685 if (parseaddr(p, &bl, RF_COPYNONE, ',', 686 &delimptr, CurEnv) == NULL) 687 usrerr("553 %s... bad address", p); 688 p = delimptr; 689 } 690 } 691 else 692 { 693 p = nlp; 694 } 695 696 /* see if there should be a continuation line */ 697 c = getc(af); 698 if (!feof(af)) 699 (void) ungetc(c, af); 700 if (c != ' ' && c != '\t') 701 break; 702 703 /* read continuation line */ 704 if (fgets(p, sizeof line - (p - line), af) == NULL) 705 break; 706 LineNumber++; 707 708 /* check for line overflow */ 709 if (strchr(p, '\n') == NULL && !feof(af)) 710 { 711 usrerr("554 alias too long"); 712 while ((c = fgetc(af)) != EOF && c != '\n') 713 continue; 714 skipping = TRUE; 715 break; 716 } 717 } 718 719 if (skipping) 720 continue; 721 722 if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags)) 723 { 724 syserr("554 %s... cannot alias non-local names", 725 al.q_paddr); 726 continue; 727 } 728 729 /* 730 ** Insert alias into symbol table or database file. 731 ** 732 ** Special case pOStmaStER -- always make it lower case. 733 */ 734 735 if (strcasecmp(al.q_user, "postmaster") == 0) 736 makelower(al.q_user); 737 738 lhssize = strlen(al.q_user); 739 rhssize = strlen(rhs); 740 map->map_class->map_store(map, al.q_user, rhs); 741 742 if (al.q_paddr != NULL) 743 free(al.q_paddr); 744 if (al.q_host != NULL) 745 free(al.q_host); 746 if (al.q_user != NULL) 747 free(al.q_user); 748 749 /* statistics */ 750 naliases++; 751 bytes += lhssize + rhssize; 752 if (rhssize > longest) 753 longest = rhssize; 754 } 755 756 CurEnv->e_to = NULL; 757 FileName = NULL; 758 if (Verbose || announcestats) 759 message("%s: %d aliases, longest %d bytes, %d bytes total", 760 map->map_file, naliases, longest, bytes); 761 if (LogLevel > 7 && logstats) 762 sm_syslog(LOG_INFO, NOQID, 763 "%s: %d aliases, longest %d bytes, %d bytes total", 764 map->map_file, naliases, longest, bytes); 765 } 766 /* 767 ** FORWARD -- Try to forward mail 768 ** 769 ** This is similar but not identical to aliasing. 770 ** 771 ** Parameters: 772 ** user -- the name of the user who's mail we would like 773 ** to forward to. It must have been verified -- 774 ** i.e., the q_home field must have been filled 775 ** in. 776 ** sendq -- a pointer to the head of the send queue to 777 ** put this user's aliases in. 778 ** aliaslevel -- the current alias nesting depth. 779 ** e -- the current envelope. 780 ** 781 ** Returns: 782 ** none. 783 ** 784 ** Side Effects: 785 ** New names are added to send queues. 786 */ 787 788 void 789 forward(user, sendq, aliaslevel, e) 790 ADDRESS *user; 791 ADDRESS **sendq; 792 int aliaslevel; 793 register ENVELOPE *e; 794 { 795 char *pp; 796 char *ep; 797 bool got_transient; 798 799 if (tTd(27, 1)) 800 printf("forward(%s)\n", user->q_paddr); 801 802 if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) || 803 bitset(QBADADDR, user->q_flags)) 804 return; 805 if (user->q_home == NULL) 806 { 807 syserr("554 forward: no home"); 808 user->q_home = "/no/such/directory"; 809 } 810 811 /* good address -- look for .forward file in home */ 812 define('z', user->q_home, e); 813 define('u', user->q_user, e); 814 define('h', user->q_host, e); 815 if (ForwardPath == NULL) 816 ForwardPath = newstr("\201z/.forward"); 817 818 got_transient = FALSE; 819 for (pp = ForwardPath; pp != NULL; pp = ep) 820 { 821 int err; 822 char buf[MAXPATHLEN+1]; 823 824 ep = strchr(pp, ':'); 825 if (ep != NULL) 826 *ep = '\0'; 827 expand(pp, buf, sizeof buf, e); 828 if (ep != NULL) 829 *ep++ = ':'; 830 if (buf[0] == '\0') 831 continue; 832 if (tTd(27, 3)) 833 printf("forward: trying %s\n", buf); 834 835 err = include(buf, TRUE, user, sendq, aliaslevel, e); 836 if (err == 0) 837 break; 838 else if (transienterror(err)) 839 { 840 /* we may have to suspend this message */ 841 got_transient = TRUE; 842 if (tTd(27, 2)) 843 printf("forward: transient error on %s\n", buf); 844 if (LogLevel > 2) 845 sm_syslog(LOG_ERR, e->e_id, 846 "forward %s: transient error: %s", 847 buf, errstring(err)); 848 } 849 else 850 { 851 switch (err) 852 { 853 case ENOENT: 854 break; 855 856 #if _FFR_FORWARD_SYSERR 857 case E_SM_NOSLINK: 858 case E_SM_NOHLINK: 859 case E_SM_REGONLY: 860 case E_SM_ISEXEC: 861 case E_SM_WWDIR: 862 case E_SM_GWDIR: 863 case E_SM_WWFILE: 864 case E_SM_GWFILE: 865 syserr("forward: %s: %s", buf, errstring(err)); 866 break; 867 #endif 868 869 default: 870 if (LogLevel > (RunAsUid == 0 ? 2 : 10)) 871 sm_syslog(LOG_WARNING, e->e_id, 872 "forward %s: %s", buf, 873 errstring(err)); 874 if (Verbose) 875 message("forward: %s: %s", 876 buf, 877 errstring(err)); 878 break; 879 } 880 } 881 } 882 if (pp == NULL && got_transient) 883 { 884 /* 885 ** There was no successful .forward open and at least one 886 ** transient open. We have to defer this address for 887 ** further delivery. 888 */ 889 890 message("transient .forward open error: message queued"); 891 user->q_flags |= QQUEUEUP; 892 return; 893 } 894 } 895