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