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