1 /* 2 * Copyright (c) 1983 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 #ifndef lint 10 static char sccsid[] = "@(#)envelope.c 8.45 (Berkeley) 11/22/94"; 11 #endif /* not lint */ 12 13 #include "sendmail.h" 14 #include <pwd.h> 15 16 /* 17 ** NEWENVELOPE -- allocate a new envelope 18 ** 19 ** Supports inheritance. 20 ** 21 ** Parameters: 22 ** e -- the new envelope to fill in. 23 ** parent -- the envelope to be the parent of e. 24 ** 25 ** Returns: 26 ** e. 27 ** 28 ** Side Effects: 29 ** none. 30 */ 31 32 ENVELOPE * 33 newenvelope(e, parent) 34 register ENVELOPE *e; 35 register ENVELOPE *parent; 36 { 37 extern putheader(), putbody(); 38 extern ENVELOPE BlankEnvelope; 39 40 if (e == parent && e->e_parent != NULL) 41 parent = e->e_parent; 42 clearenvelope(e, TRUE); 43 if (e == CurEnv) 44 bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from); 45 else 46 bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from); 47 e->e_parent = parent; 48 e->e_ctime = curtime(); 49 if (parent != NULL) 50 e->e_msgpriority = parent->e_msgsize; 51 e->e_puthdr = putheader; 52 e->e_putbody = putbody; 53 if (CurEnv->e_xfp != NULL) 54 (void) fflush(CurEnv->e_xfp); 55 56 return (e); 57 } 58 /* 59 ** DROPENVELOPE -- deallocate an envelope. 60 ** 61 ** Parameters: 62 ** e -- the envelope to deallocate. 63 ** 64 ** Returns: 65 ** none. 66 ** 67 ** Side Effects: 68 ** housekeeping necessary to dispose of an envelope. 69 ** Unlocks this queue file. 70 */ 71 72 void 73 dropenvelope(e) 74 register ENVELOPE *e; 75 { 76 bool queueit = FALSE; 77 bool failure_return = FALSE; 78 bool success_return = FALSE; 79 register ADDRESS *q; 80 char *id = e->e_id; 81 bool return_no, return_yes; 82 char buf[MAXLINE]; 83 84 if (tTd(50, 1)) 85 { 86 printf("dropenvelope %x: id=", e); 87 xputs(e->e_id); 88 printf(", flags=0x%x\n", e->e_flags); 89 if (tTd(50, 10)) 90 { 91 printf("sendq="); 92 printaddr(e->e_sendqueue, TRUE); 93 } 94 } 95 96 /* we must have an id to remove disk files */ 97 if (id == NULL) 98 return; 99 100 #ifdef LOG 101 if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) 102 logsender(e, NULL); 103 if (LogLevel > 84) 104 syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=0x%x, pid=%d", 105 id, e->e_flags, getpid()); 106 #endif /* LOG */ 107 e->e_flags &= ~EF_LOGSENDER; 108 109 /* post statistics */ 110 poststats(StatFile); 111 112 /* 113 ** Extract state information from dregs of send list. 114 */ 115 116 e->e_flags &= ~EF_QUEUERUN; 117 return_no = return_yes = FALSE; 118 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 119 { 120 if (bitset(QQUEUEUP, q->q_flags)) 121 queueit = TRUE; 122 123 /* see if a notification is needed */ 124 if (e->e_df != NULL && 125 bitset(QBADADDR, q->q_flags) && 126 bitset(QPINGONFAILURE, q->q_flags)) 127 { 128 failure_return = TRUE; 129 if (q->q_owner == NULL && !emptyaddr(&e->e_from)) 130 (void) sendtolist(e->e_from.q_paddr, NULL, 131 &e->e_errorqueue, e); 132 } 133 else if (bitset(QSENT, q->q_flags) && 134 bitnset(M_LOCALMAILER, q->q_mailer->m_flags) && 135 bitset(QPINGONSUCCESS, q->q_flags)) 136 { 137 success_return = TRUE; 138 } 139 else if (bitset(QRELAYED, q->q_flags)) 140 { 141 success_return = TRUE; 142 } 143 else 144 continue; 145 146 /* common code for error returns and return receipts */ 147 148 /* test for returning the body */ 149 if (!bitset(QHAS_RET_PARAM, q->q_flags)) 150 { 151 if (!bitset(EF_NORETURN, e->e_flags)) 152 return_yes = TRUE; 153 } 154 else if (bitset(QRET_HDRS, q->q_flags)) 155 return_no = TRUE; 156 else 157 return_yes = TRUE; 158 } 159 if (return_no && !return_yes) 160 e->e_flags |= EF_NORETURN; 161 162 /* 163 ** See if the message timed out. 164 */ 165 166 if (!queueit) 167 /* nothing to do */ ; 168 else if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) 169 { 170 (void) sprintf(buf, "Cannot send message for %s", 171 pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 172 if (e->e_message != NULL) 173 free(e->e_message); 174 e->e_message = newstr(buf); 175 message(buf); 176 e->e_flags |= EF_CLRQUEUE; 177 failure_return = TRUE; 178 fprintf(e->e_xfp, "Message could not be delivered for %s\n", 179 pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 180 fprintf(e->e_xfp, "Message will be deleted from queue\n"); 181 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 182 { 183 if (bitset(QQUEUEUP, q->q_flags)) 184 q->q_flags |= QBADADDR; 185 } 186 } 187 else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 && 188 curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass]) 189 { 190 bool delay_return = FALSE; 191 192 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 193 { 194 if (bitset(QQUEUEUP, q->q_flags) && 195 bitset(QPINGONDELAY, q->q_flags)) 196 { 197 q->q_flags |= QREPORT; 198 delay_return = TRUE; 199 } 200 } 201 if (delay_return && 202 !bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && 203 e->e_class >= 0 && 204 strcmp(e->e_from.q_paddr, "<>") != 0 && 205 strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 && 206 (strlen(e->e_from.q_paddr) <= 8 || 207 strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0)) 208 { 209 (void) sprintf(buf, 210 "Warning: cannot send message for %s", 211 pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE)); 212 if (e->e_message != NULL) 213 free(e->e_message); 214 e->e_message = newstr(buf); 215 message(buf); 216 e->e_flags |= EF_WARNING; 217 failure_return = TRUE; 218 } 219 fprintf(e->e_xfp, 220 "Warning: message still undelivered after %s\n", 221 pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE)); 222 fprintf(e->e_xfp, "Will keep trying until message is %s old\n", 223 pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE)); 224 } 225 226 if (tTd(50, 2)) 227 printf("failure_return=%d success_return=%d queueit=%d\n", 228 failure_return, success_return, queueit); 229 230 /* 231 ** Send back return receipts as requested. 232 */ 233 234 /* 235 if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags) 236 && !bitset(PRIV_NORECEIPTS, PrivacyFlags)) 237 */ 238 if (e->e_receiptto == NULL) 239 e->e_receiptto = e->e_from.q_paddr; 240 if (success_return && strcmp(e->e_receiptto, "<>") != 0) 241 { 242 auto ADDRESS *rlist = NULL; 243 244 e->e_flags |= EF_SENDRECEIPT; 245 (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, e); 246 (void) returntosender("Return receipt", rlist, return_yes, e); 247 } 248 e->e_flags &= ~EF_SENDRECEIPT; 249 250 /* 251 ** Arrange to send error messages if there are fatal errors. 252 */ 253 254 if (failure_return && e->e_errormode != EM_QUIET) 255 savemail(e); 256 257 /* 258 ** Arrange to send warning messages to postmaster as requested. 259 */ 260 261 if (bitset(EF_PM_NOTIFY, e->e_flags) && PostMasterCopy != NULL && 262 !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0) 263 { 264 auto ADDRESS *rlist = NULL; 265 266 (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, e); 267 (void) returntosender(e->e_message, rlist, FALSE, e); 268 } 269 270 /* 271 ** Instantiate or deinstantiate the queue. 272 */ 273 274 if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) || 275 bitset(EF_CLRQUEUE, e->e_flags)) 276 { 277 if (tTd(50, 1)) 278 printf("\n===== Dropping [dq]f%s (queueit=%d, e_flags=%x) =====\n\n", 279 e->e_id, queueit, e->e_flags); 280 if (e->e_df != NULL) 281 xunlink(e->e_df); 282 xunlink(queuename(e, 'q')); 283 284 #ifdef LOG 285 if (LogLevel > 10) 286 syslog(LOG_INFO, "%s: done", id); 287 #endif 288 } 289 else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) 290 { 291 #ifdef QUEUE 292 queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE); 293 #else /* QUEUE */ 294 syserr("554 dropenvelope: queueup"); 295 #endif /* QUEUE */ 296 } 297 298 /* now unlock the job */ 299 closexscript(e); 300 unlockqueue(e); 301 302 /* make sure that this envelope is marked unused */ 303 if (e->e_dfp != NULL) 304 (void) xfclose(e->e_dfp, "dropenvelope", e->e_df); 305 e->e_dfp = NULL; 306 e->e_id = e->e_df = NULL; 307 } 308 /* 309 ** CLEARENVELOPE -- clear an envelope without unlocking 310 ** 311 ** This is normally used by a child process to get a clean 312 ** envelope without disturbing the parent. 313 ** 314 ** Parameters: 315 ** e -- the envelope to clear. 316 ** fullclear - if set, the current envelope is total 317 ** garbage and should be ignored; otherwise, 318 ** release any resources it may indicate. 319 ** 320 ** Returns: 321 ** none. 322 ** 323 ** Side Effects: 324 ** Closes files associated with the envelope. 325 ** Marks the envelope as unallocated. 326 */ 327 328 void 329 clearenvelope(e, fullclear) 330 register ENVELOPE *e; 331 bool fullclear; 332 { 333 register HDR *bh; 334 register HDR **nhp; 335 extern ENVELOPE BlankEnvelope; 336 337 if (!fullclear) 338 { 339 /* clear out any file information */ 340 if (e->e_xfp != NULL) 341 (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id); 342 if (e->e_dfp != NULL) 343 (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df); 344 e->e_xfp = e->e_dfp = NULL; 345 } 346 347 /* now clear out the data */ 348 STRUCTCOPY(BlankEnvelope, *e); 349 if (Verbose) 350 e->e_sendmode = SM_DELIVER; 351 bh = BlankEnvelope.e_header; 352 nhp = &e->e_header; 353 while (bh != NULL) 354 { 355 *nhp = (HDR *) xalloc(sizeof *bh); 356 bcopy((char *) bh, (char *) *nhp, sizeof *bh); 357 bh = bh->h_link; 358 nhp = &(*nhp)->h_link; 359 } 360 } 361 /* 362 ** INITSYS -- initialize instantiation of system 363 ** 364 ** In Daemon mode, this is done in the child. 365 ** 366 ** Parameters: 367 ** none. 368 ** 369 ** Returns: 370 ** none. 371 ** 372 ** Side Effects: 373 ** Initializes the system macros, some global variables, 374 ** etc. In particular, the current time in various 375 ** forms is set. 376 */ 377 378 void 379 initsys(e) 380 register ENVELOPE *e; 381 { 382 char cbuf[5]; /* holds hop count */ 383 char pbuf[10]; /* holds pid */ 384 #ifdef TTYNAME 385 static char ybuf[60]; /* holds tty id */ 386 register char *p; 387 #endif /* TTYNAME */ 388 extern char *ttyname(); 389 extern void settime(); 390 extern char Version[]; 391 392 /* 393 ** Give this envelope a reality. 394 ** I.e., an id, a transcript, and a creation time. 395 */ 396 397 openxscript(e); 398 e->e_ctime = curtime(); 399 400 /* 401 ** Set OutChannel to something useful if stdout isn't it. 402 ** This arranges that any extra stuff the mailer produces 403 ** gets sent back to the user on error (because it is 404 ** tucked away in the transcript). 405 */ 406 407 if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && 408 e->e_xfp != NULL) 409 OutChannel = e->e_xfp; 410 411 /* 412 ** Set up some basic system macros. 413 */ 414 415 /* process id */ 416 (void) sprintf(pbuf, "%d", getpid()); 417 define('p', newstr(pbuf), e); 418 419 /* hop count */ 420 (void) sprintf(cbuf, "%d", e->e_hopcount); 421 define('c', newstr(cbuf), e); 422 423 /* time as integer, unix time, arpa time */ 424 settime(e); 425 426 #ifdef TTYNAME 427 /* tty name */ 428 if (macvalue('y', e) == NULL) 429 { 430 p = ttyname(2); 431 if (p != NULL) 432 { 433 if (strrchr(p, '/') != NULL) 434 p = strrchr(p, '/') + 1; 435 (void) strcpy(ybuf, p); 436 define('y', ybuf, e); 437 } 438 } 439 #endif /* TTYNAME */ 440 } 441 /* 442 ** SETTIME -- set the current time. 443 ** 444 ** Parameters: 445 ** none. 446 ** 447 ** Returns: 448 ** none. 449 ** 450 ** Side Effects: 451 ** Sets the various time macros -- $a, $b, $d, $t. 452 */ 453 454 void 455 settime(e) 456 register ENVELOPE *e; 457 { 458 register char *p; 459 auto time_t now; 460 char tbuf[20]; /* holds "current" time */ 461 char dbuf[30]; /* holds ctime(tbuf) */ 462 register struct tm *tm; 463 extern char *arpadate(); 464 extern struct tm *gmtime(); 465 466 now = curtime(); 467 tm = gmtime(&now); 468 (void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900, 469 tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); 470 define('t', newstr(tbuf), e); 471 (void) strcpy(dbuf, ctime(&now)); 472 p = strchr(dbuf, '\n'); 473 if (p != NULL) 474 *p = '\0'; 475 define('d', newstr(dbuf), e); 476 p = arpadate(dbuf); 477 p = newstr(p); 478 if (macvalue('a', e) == NULL) 479 define('a', p, e); 480 define('b', p, e); 481 } 482 /* 483 ** OPENXSCRIPT -- Open transcript file 484 ** 485 ** Creates a transcript file for possible eventual mailing or 486 ** sending back. 487 ** 488 ** Parameters: 489 ** e -- the envelope to create the transcript in/for. 490 ** 491 ** Returns: 492 ** none 493 ** 494 ** Side Effects: 495 ** Creates the transcript file. 496 */ 497 498 #ifndef O_APPEND 499 #define O_APPEND 0 500 #endif 501 502 void 503 openxscript(e) 504 register ENVELOPE *e; 505 { 506 register char *p; 507 int fd; 508 509 if (e->e_xfp != NULL) 510 return; 511 p = queuename(e, 'x'); 512 fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644); 513 if (fd < 0) 514 { 515 syserr("Can't create transcript file %s", p); 516 fd = open("/dev/null", O_WRONLY, 0644); 517 if (fd < 0) 518 syserr("!Can't open /dev/null"); 519 } 520 e->e_xfp = fdopen(fd, "w"); 521 if (e->e_xfp == NULL) 522 { 523 syserr("!Can't create transcript stream %s", p); 524 } 525 if (tTd(46, 9)) 526 { 527 printf("openxscript(%s):\n ", p); 528 dumpfd(fileno(e->e_xfp), TRUE, FALSE); 529 } 530 } 531 /* 532 ** CLOSEXSCRIPT -- close the transcript file. 533 ** 534 ** Parameters: 535 ** e -- the envelope containing the transcript to close. 536 ** 537 ** Returns: 538 ** none. 539 ** 540 ** Side Effects: 541 ** none. 542 */ 543 544 void 545 closexscript(e) 546 register ENVELOPE *e; 547 { 548 if (e->e_xfp == NULL) 549 return; 550 (void) xfclose(e->e_xfp, "closexscript", e->e_id); 551 e->e_xfp = NULL; 552 } 553 /* 554 ** SETSENDER -- set the person who this message is from 555 ** 556 ** Under certain circumstances allow the user to say who 557 ** s/he is (using -f or -r). These are: 558 ** 1. The user's uid is zero (root). 559 ** 2. The user's login name is in an approved list (typically 560 ** from a network server). 561 ** 3. The address the user is trying to claim has a 562 ** "!" character in it (since #2 doesn't do it for 563 ** us if we are dialing out for UUCP). 564 ** A better check to replace #3 would be if the 565 ** effective uid is "UUCP" -- this would require me 566 ** to rewrite getpwent to "grab" uucp as it went by, 567 ** make getname more nasty, do another passwd file 568 ** scan, or compile the UID of "UUCP" into the code, 569 ** all of which are reprehensible. 570 ** 571 ** Assuming all of these fail, we figure out something 572 ** ourselves. 573 ** 574 ** Parameters: 575 ** from -- the person we would like to believe this message 576 ** is from, as specified on the command line. 577 ** e -- the envelope in which we would like the sender set. 578 ** delimptr -- if non-NULL, set to the location of the 579 ** trailing delimiter. 580 ** internal -- set if this address is coming from an internal 581 ** source such as an owner alias. 582 ** 583 ** Returns: 584 ** none. 585 ** 586 ** Side Effects: 587 ** sets sendmail's notion of who the from person is. 588 */ 589 590 void 591 setsender(from, e, delimptr, internal) 592 char *from; 593 register ENVELOPE *e; 594 char **delimptr; 595 bool internal; 596 { 597 register char **pvp; 598 char *realname = NULL; 599 register struct passwd *pw; 600 char delimchar; 601 char *bp; 602 char buf[MAXNAME + 2]; 603 char pvpbuf[PSBUFSIZE]; 604 extern struct passwd *getpwnam(); 605 extern char *FullName; 606 607 if (tTd(45, 1)) 608 printf("setsender(%s)\n", from == NULL ? "" : from); 609 610 /* 611 ** Figure out the real user executing us. 612 ** Username can return errno != 0 on non-errors. 613 */ 614 615 if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP || 616 OpMode == MD_ARPAFTP || OpMode == MD_DAEMON) 617 realname = from; 618 if (realname == NULL || realname[0] == '\0') 619 realname = username(); 620 621 if (ConfigLevel < 2) 622 SuprErrs = TRUE; 623 624 delimchar = internal ? '\0' : ' '; 625 e->e_from.q_flags = QBADADDR; 626 if (from == NULL || 627 parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, 628 delimchar, delimptr, e) == NULL || 629 bitset(QBADADDR, e->e_from.q_flags) || 630 e->e_from.q_mailer == ProgMailer || 631 e->e_from.q_mailer == FileMailer || 632 e->e_from.q_mailer == InclMailer) 633 { 634 /* log garbage addresses for traceback */ 635 # ifdef LOG 636 if (from != NULL && LogLevel > 2) 637 { 638 char *p; 639 char ebuf[MAXNAME * 2 + 2]; 640 641 p = macvalue('_', e); 642 if (p == NULL) 643 { 644 char *host = RealHostName; 645 if (host == NULL) 646 host = MyHostName; 647 (void) sprintf(ebuf, "%s@%s", realname, host); 648 p = ebuf; 649 } 650 syslog(LOG_NOTICE, 651 "setsender: %s: invalid or unparseable, received from %s", 652 shortenstring(from, 83), p); 653 } 654 # endif /* LOG */ 655 if (from != NULL) 656 { 657 if (!bitset(QBADADDR, e->e_from.q_flags)) 658 { 659 /* it was a bogus mailer in the from addr */ 660 usrerr("553 Invalid sender address"); 661 } 662 SuprErrs = TRUE; 663 } 664 if (from == realname || 665 parseaddr(from = newstr(realname), &e->e_from, 666 RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL) 667 { 668 char nbuf[100]; 669 670 SuprErrs = TRUE; 671 expand("\201n", nbuf, &nbuf[sizeof nbuf], e); 672 if (parseaddr(from = newstr(nbuf), &e->e_from, 673 RF_COPYALL, ' ', NULL, e) == NULL && 674 parseaddr(from = "postmaster", &e->e_from, 675 RF_COPYALL, ' ', NULL, e) == NULL) 676 syserr("553 setsender: can't even parse postmaster!"); 677 } 678 } 679 else 680 FromFlag = TRUE; 681 e->e_from.q_flags |= QDONTSEND; 682 if (tTd(45, 5)) 683 { 684 printf("setsender: QDONTSEND "); 685 printaddr(&e->e_from, FALSE); 686 } 687 SuprErrs = FALSE; 688 689 # ifdef USERDB 690 if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags)) 691 { 692 register char *p; 693 extern char *udbsender(); 694 695 p = udbsender(e->e_from.q_user); 696 if (p != NULL) 697 from = p; 698 } 699 # endif /* USERDB */ 700 701 if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags)) 702 { 703 if (!internal) 704 { 705 /* if the user already given fullname don't redefine */ 706 if (FullName == NULL) 707 FullName = macvalue('x', e); 708 if (FullName != NULL && FullName[0] == '\0') 709 FullName = NULL; 710 } 711 712 if ((pw = getpwnam(e->e_from.q_user)) != NULL) 713 { 714 /* 715 ** Process passwd file entry. 716 */ 717 718 /* extract home directory */ 719 if (strcmp(pw->pw_dir, "/") == 0) 720 e->e_from.q_home = newstr(""); 721 else 722 e->e_from.q_home = newstr(pw->pw_dir); 723 define('z', e->e_from.q_home, e); 724 725 /* extract user and group id */ 726 e->e_from.q_uid = pw->pw_uid; 727 e->e_from.q_gid = pw->pw_gid; 728 e->e_from.q_flags |= QGOODUID; 729 730 /* extract full name from passwd file */ 731 if (FullName == NULL && pw->pw_gecos != NULL && 732 strcmp(pw->pw_name, e->e_from.q_user) == 0 && 733 !internal) 734 { 735 buildfname(pw->pw_gecos, e->e_from.q_user, buf); 736 if (buf[0] != '\0') 737 FullName = newstr(buf); 738 } 739 } 740 if (FullName != NULL && !internal) 741 define('x', FullName, e); 742 } 743 else if (!internal && OpMode != MD_DAEMON) 744 { 745 if (e->e_from.q_home == NULL) 746 { 747 e->e_from.q_home = getenv("HOME"); 748 if (e->e_from.q_home != NULL && 749 strcmp(e->e_from.q_home, "/") == 0) 750 e->e_from.q_home++; 751 } 752 e->e_from.q_uid = RealUid; 753 e->e_from.q_gid = RealGid; 754 e->e_from.q_flags |= QGOODUID; 755 } 756 757 /* 758 ** Rewrite the from person to dispose of possible implicit 759 ** links in the net. 760 */ 761 762 pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL); 763 if (pvp == NULL) 764 { 765 /* don't need to give error -- prescan did that already */ 766 # ifdef LOG 767 if (LogLevel > 2) 768 syslog(LOG_NOTICE, "cannot prescan from (%s)", from); 769 # endif 770 finis(); 771 } 772 /* 773 (void) rewrite(pvp, 3, 0, e); 774 (void) rewrite(pvp, 1, 0, e); 775 (void) rewrite(pvp, 4, 0, e); 776 */ 777 bp = buf + 1; 778 cataddr(pvp, NULL, bp, sizeof buf - 2, '\0'); 779 if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags)) 780 { 781 /* heuristic: route-addr: add angle brackets */ 782 strcat(bp, ">"); 783 *--bp = '<'; 784 } 785 e->e_sender = newstr(bp); 786 define('f', e->e_sender, e); 787 788 /* save the domain spec if this mailer wants it */ 789 if (e->e_from.q_mailer != NULL && 790 bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags)) 791 { 792 extern char **copyplist(); 793 794 while (*pvp != NULL && strcmp(*pvp, "@") != 0) 795 pvp++; 796 if (*pvp != NULL) 797 e->e_fromdomain = copyplist(pvp, TRUE); 798 } 799 } 800