1 /* 2 * Copyright (c) 1998-2002 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 14 #include <sendmail.h> 15 16 SM_RCSID("@(#)$Id: collect.c,v 8.242 2002/05/10 15:40:09 ca Exp $") 17 18 static void collecttimeout __P((time_t)); 19 static void dferror __P((SM_FILE_T *volatile, char *, ENVELOPE *)); 20 static void eatfrom __P((char *volatile, ENVELOPE *)); 21 static void collect_doheader __P((ENVELOPE *)); 22 static SM_FILE_T *collect_dfopen __P((ENVELOPE *)); 23 static SM_FILE_T *collect_eoh __P((ENVELOPE *, int, int)); 24 25 /* 26 ** COLLECT_EOH -- end-of-header processing in collect() 27 ** 28 ** Called by collect() when it encounters the blank line 29 ** separating the header from the message body, or when it 30 ** encounters EOF in a message that contains only a header. 31 ** 32 ** Parameters: 33 ** e -- envelope 34 ** numhdrs -- number of headers 35 ** hdrslen -- length of headers 36 ** 37 ** Results: 38 ** NULL, or handle to open data file 39 ** 40 ** Side Effects: 41 ** end-of-header check ruleset is invoked. 42 ** envelope state is updated. 43 ** headers may be added and deleted. 44 ** selects the queue. 45 ** opens the data file. 46 */ 47 48 static SM_FILE_T * 49 collect_eoh(e, numhdrs, hdrslen) 50 ENVELOPE *e; 51 int numhdrs; 52 int hdrslen; 53 { 54 char hnum[16]; 55 char hsize[16]; 56 57 /* call the end-of-header check ruleset */ 58 (void) sm_snprintf(hnum, sizeof hnum, "%d", numhdrs); 59 (void) sm_snprintf(hsize, sizeof hsize, "%d", hdrslen); 60 if (tTd(30, 10)) 61 sm_dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n", 62 hnum, hsize); 63 (void) rscheck("check_eoh", hnum, hsize, e, false, true, 3, NULL, 64 e->e_id); 65 66 /* 67 ** Process the header, 68 ** select the queue, open the data file. 69 */ 70 71 collect_doheader(e); 72 return collect_dfopen(e); 73 } 74 75 /* 76 ** COLLECT_DOHEADER -- process header in collect() 77 ** 78 ** Called by collect() after it has finished parsing the header, 79 ** but before it selects the queue and creates the data file. 80 ** The results of processing the header will affect queue selection. 81 ** 82 ** Parameters: 83 ** e -- envelope 84 ** 85 ** Results: 86 ** none. 87 ** 88 ** Side Effects: 89 ** envelope state is updated. 90 ** headers may be added and deleted. 91 */ 92 93 static void 94 collect_doheader(e) 95 ENVELOPE *e; 96 { 97 /* 98 ** Find out some information from the headers. 99 ** Examples are who is the from person & the date. 100 */ 101 102 eatheader(e, true, false); 103 104 if (GrabTo && e->e_sendqueue == NULL) 105 usrerr("No recipient addresses found in header"); 106 107 /* 108 ** If we have a Return-Receipt-To:, turn it into a DSN. 109 */ 110 111 if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL) 112 { 113 ADDRESS *q; 114 115 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 116 if (!bitset(QHASNOTIFY, q->q_flags)) 117 q->q_flags |= QHASNOTIFY|QPINGONSUCCESS; 118 } 119 120 /* 121 ** Add an appropriate recipient line if we have none. 122 */ 123 124 if (hvalue("to", e->e_header) != NULL || 125 hvalue("cc", e->e_header) != NULL || 126 hvalue("apparently-to", e->e_header) != NULL) 127 { 128 /* have a valid recipient header -- delete Bcc: headers */ 129 e->e_flags |= EF_DELETE_BCC; 130 } 131 else if (hvalue("bcc", e->e_header) == NULL) 132 { 133 /* no valid recipient headers */ 134 register ADDRESS *q; 135 char *hdr = NULL; 136 137 /* create a recipient field */ 138 switch (NoRecipientAction) 139 { 140 case NRA_ADD_APPARENTLY_TO: 141 hdr = "Apparently-To"; 142 break; 143 144 case NRA_ADD_TO: 145 hdr = "To"; 146 break; 147 148 case NRA_ADD_BCC: 149 addheader("Bcc", " ", 0, e); 150 break; 151 152 case NRA_ADD_TO_UNDISCLOSED: 153 addheader("To", "undisclosed-recipients:;", 0, e); 154 break; 155 } 156 157 if (hdr != NULL) 158 { 159 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 160 { 161 if (q->q_alias != NULL) 162 continue; 163 if (tTd(30, 3)) 164 sm_dprintf("Adding %s: %s\n", 165 hdr, q->q_paddr); 166 addheader(hdr, q->q_paddr, 0, e); 167 } 168 } 169 } 170 } 171 172 /* 173 ** COLLECT_DFOPEN -- open the message data file 174 ** 175 ** Called by collect() after it has finished processing the header. 176 ** Queue selection occurs at this point, possibly based on the 177 ** envelope's recipient list and on header information. 178 ** 179 ** Parameters: 180 ** e -- envelope 181 ** 182 ** Results: 183 ** NULL, or a pointer to an open data file, 184 ** into which the message body will be written by collect(). 185 ** 186 ** Side Effects: 187 ** Calls syserr, sets EF_FATALERRS and returns NULL 188 ** if there is insufficient disk space. 189 ** Aborts process if data file could not be opened. 190 ** Otherwise, the queue is selected, 191 ** e->e_{dfino,dfdev,msgsize,flags} are updated, 192 ** and a pointer to an open data file is returned. 193 */ 194 195 static SM_FILE_T * 196 collect_dfopen(e) 197 ENVELOPE *e; 198 { 199 MODE_T oldumask = 0; 200 int dfd; 201 struct stat stbuf; 202 SM_FILE_T *df; 203 char *dfname; 204 205 if (!setnewqueue(e)) 206 return NULL; 207 208 dfname = queuename(e, DATAFL_LETTER); 209 if (bitset(S_IWGRP, QueueFileMode)) 210 oldumask = umask(002); 211 df = bfopen(dfname, QueueFileMode, DataFileBufferSize, 212 SFF_OPENASROOT); 213 if (bitset(S_IWGRP, QueueFileMode)) 214 (void) umask(oldumask); 215 if (df == NULL) 216 { 217 syserr("@Cannot create %s", dfname); 218 e->e_flags |= EF_NO_BODY_RETN; 219 flush_errors(true); 220 finis(true, true, ExitStat); 221 /* NOTREACHED */ 222 } 223 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL); 224 if (dfd < 0 || fstat(dfd, &stbuf) < 0) 225 e->e_dfino = -1; 226 else 227 { 228 e->e_dfdev = stbuf.st_dev; 229 e->e_dfino = stbuf.st_ino; 230 } 231 e->e_flags |= EF_HAS_DF; 232 return df; 233 } 234 235 /* 236 ** COLLECT -- read & parse message header & make temp file. 237 ** 238 ** Creates a temporary file name and copies the standard 239 ** input to that file. Leading UNIX-style "From" lines are 240 ** stripped off (after important information is extracted). 241 ** 242 ** Parameters: 243 ** fp -- file to read. 244 ** smtpmode -- if set, we are running SMTP: give an RFC821 245 ** style message to say we are ready to collect 246 ** input, and never ignore a single dot to mean 247 ** end of message. 248 ** hdrp -- the location to stash the header. 249 ** e -- the current envelope. 250 ** 251 ** Returns: 252 ** none. 253 ** 254 ** Side Effects: 255 ** If successful, 256 ** - Data file is created and filled, and e->e_dfp is set. 257 ** - The from person may be set. 258 ** If the "enough disk space" check fails, 259 ** - syserr is called. 260 ** - e->e_dfp is NULL. 261 ** - e->e_flags & EF_FATALERRS is set. 262 ** - collect() returns. 263 ** If data file cannot be created, the process is terminated. 264 */ 265 266 static jmp_buf CtxCollectTimeout; 267 static bool volatile CollectProgress; 268 static SM_EVENT *volatile CollectTimeout = NULL; 269 270 /* values for input state machine */ 271 #define IS_NORM 0 /* middle of line */ 272 #define IS_BOL 1 /* beginning of line */ 273 #define IS_DOT 2 /* read a dot at beginning of line */ 274 #define IS_DOTCR 3 /* read ".\r" at beginning of line */ 275 #define IS_CR 4 /* read a carriage return */ 276 277 /* values for message state machine */ 278 #define MS_UFROM 0 /* reading Unix from line */ 279 #define MS_HEADER 1 /* reading message header */ 280 #define MS_BODY 2 /* reading message body */ 281 #define MS_DISCARD 3 /* discarding rest of message */ 282 283 void 284 collect(fp, smtpmode, hdrp, e) 285 SM_FILE_T *fp; 286 bool smtpmode; 287 HDR **hdrp; 288 register ENVELOPE *e; 289 { 290 register SM_FILE_T *volatile df; 291 volatile bool ignrdot; 292 volatile time_t dbto; 293 register char *volatile bp; 294 volatile int c; 295 volatile bool inputerr; 296 bool headeronly; 297 char *volatile buf; 298 volatile int buflen; 299 volatile int istate; 300 volatile int mstate; 301 volatile int hdrslen; 302 volatile int numhdrs; 303 volatile int afd; 304 unsigned char *volatile pbp; 305 unsigned char peekbuf[8]; 306 char bufbuf[MAXLINE]; 307 308 df = NULL; 309 ignrdot = smtpmode ? false : IgnrDot; 310 dbto = smtpmode ? TimeOuts.to_datablock : 0; 311 c = SM_IO_EOF; 312 inputerr = false; 313 headeronly = hdrp != NULL; 314 hdrslen = 0; 315 numhdrs = 0; 316 HasEightBits = false; 317 buf = bp = bufbuf; 318 buflen = sizeof bufbuf; 319 pbp = peekbuf; 320 istate = IS_BOL; 321 mstate = SaveFrom ? MS_HEADER : MS_UFROM; 322 CollectProgress = false; 323 324 /* 325 ** Tell ARPANET to go ahead. 326 */ 327 328 if (smtpmode) 329 message("354 Enter mail, end with \".\" on a line by itself"); 330 331 if (tTd(30, 2)) 332 sm_dprintf("collect\n"); 333 334 /* 335 ** Read the message. 336 ** 337 ** This is done using two interleaved state machines. 338 ** The input state machine is looking for things like 339 ** hidden dots; the message state machine is handling 340 ** the larger picture (e.g., header versus body). 341 */ 342 343 if (dbto != 0) 344 { 345 /* handle possible input timeout */ 346 if (setjmp(CtxCollectTimeout) != 0) 347 { 348 if (LogLevel > 2) 349 sm_syslog(LOG_NOTICE, e->e_id, 350 "timeout waiting for input from %s during message collect", 351 CURHOSTNAME); 352 errno = 0; 353 usrerr("451 4.4.1 timeout waiting for input during message collect"); 354 goto readerr; 355 } 356 CollectTimeout = sm_setevent(dbto, collecttimeout, dbto); 357 } 358 359 e->e_msgsize = 0; 360 for (;;) 361 { 362 if (tTd(30, 35)) 363 sm_dprintf("top, istate=%d, mstate=%d\n", istate, 364 mstate); 365 for (;;) 366 { 367 if (pbp > peekbuf) 368 c = *--pbp; 369 else 370 { 371 while (!sm_io_eof(fp) && !sm_io_error(fp)) 372 { 373 errno = 0; 374 c = sm_io_getc(fp, SM_TIME_DEFAULT); 375 if (c == SM_IO_EOF && errno == EINTR) 376 { 377 /* Interrupted, retry */ 378 sm_io_clearerr(fp); 379 continue; 380 } 381 break; 382 } 383 CollectProgress = true; 384 if (TrafficLogFile != NULL && !headeronly) 385 { 386 if (istate == IS_BOL) 387 (void) sm_io_fprintf(TrafficLogFile, 388 SM_TIME_DEFAULT, 389 "%05d <<< ", 390 (int) CurrentPid); 391 if (c == SM_IO_EOF) 392 (void) sm_io_fprintf(TrafficLogFile, 393 SM_TIME_DEFAULT, 394 "[EOF]\n"); 395 else 396 (void) sm_io_putc(TrafficLogFile, 397 SM_TIME_DEFAULT, 398 c); 399 } 400 if (c == SM_IO_EOF) 401 goto readerr; 402 if (SevenBitInput) 403 c &= 0x7f; 404 else 405 HasEightBits |= bitset(0x80, c); 406 } 407 if (tTd(30, 94)) 408 sm_dprintf("istate=%d, c=%c (0x%x)\n", 409 istate, (char) c, c); 410 switch (istate) 411 { 412 case IS_BOL: 413 if (c == '.') 414 { 415 istate = IS_DOT; 416 continue; 417 } 418 break; 419 420 case IS_DOT: 421 if (c == '\n' && !ignrdot && 422 !bitset(EF_NL_NOT_EOL, e->e_flags)) 423 goto readerr; 424 else if (c == '\r' && 425 !bitset(EF_CRLF_NOT_EOL, e->e_flags)) 426 { 427 istate = IS_DOTCR; 428 continue; 429 } 430 else if (ignrdot || 431 (c != '.' && 432 OpMode != MD_SMTP && 433 OpMode != MD_DAEMON && 434 OpMode != MD_ARPAFTP)) 435 436 { 437 *pbp++ = c; 438 c = '.'; 439 } 440 break; 441 442 case IS_DOTCR: 443 if (c == '\n' && !ignrdot) 444 goto readerr; 445 else 446 { 447 /* push back the ".\rx" */ 448 *pbp++ = c; 449 if (OpMode != MD_SMTP && 450 OpMode != MD_DAEMON && 451 OpMode != MD_ARPAFTP) 452 { 453 *pbp++ = '\r'; 454 c = '.'; 455 } 456 else 457 c = '\r'; 458 } 459 break; 460 461 case IS_CR: 462 if (c == '\n') 463 istate = IS_BOL; 464 else 465 { 466 (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, 467 c); 468 c = '\r'; 469 istate = IS_NORM; 470 } 471 goto bufferchar; 472 } 473 474 if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags)) 475 { 476 istate = IS_CR; 477 continue; 478 } 479 else if (c == '\n' && !bitset(EF_NL_NOT_EOL, 480 e->e_flags)) 481 istate = IS_BOL; 482 else 483 istate = IS_NORM; 484 485 bufferchar: 486 if (!headeronly) 487 { 488 /* no overflow? */ 489 if (e->e_msgsize >= 0) 490 { 491 e->e_msgsize++; 492 if (MaxMessageSize > 0 && 493 !bitset(EF_TOOBIG, e->e_flags) && 494 e->e_msgsize > MaxMessageSize) 495 e->e_flags |= EF_TOOBIG; 496 } 497 } 498 switch (mstate) 499 { 500 case MS_BODY: 501 /* just put the character out */ 502 if (!bitset(EF_TOOBIG, e->e_flags)) 503 (void) sm_io_putc(df, SM_TIME_DEFAULT, 504 c); 505 506 /* FALLTHROUGH */ 507 508 case MS_DISCARD: 509 continue; 510 } 511 512 /* header -- buffer up */ 513 if (bp >= &buf[buflen - 2]) 514 { 515 char *obuf; 516 517 if (mstate != MS_HEADER) 518 break; 519 520 /* out of space for header */ 521 obuf = buf; 522 if (buflen < MEMCHUNKSIZE) 523 buflen *= 2; 524 else 525 buflen += MEMCHUNKSIZE; 526 buf = xalloc(buflen); 527 memmove(buf, obuf, bp - obuf); 528 bp = &buf[bp - obuf]; 529 if (obuf != bufbuf) 530 sm_free(obuf); /* XXX */ 531 } 532 533 /* 534 ** XXX Notice: the logic here is broken. 535 ** An input to sendmail that doesn't contain a 536 ** header but starts immediately with the body whose 537 ** first line contain characters which match the 538 ** following "if" will cause problems: those 539 ** characters will NOT appear in the output... 540 ** Do we care? 541 */ 542 543 if (c >= 0200 && c <= 0237) 544 { 545 #if 0 /* causes complaints -- figure out something for 8.n+1 */ 546 usrerr("Illegal character 0x%x in header", c); 547 #else /* 0 */ 548 /* EMPTY */ 549 #endif /* 0 */ 550 } 551 else if (c != '\0') 552 { 553 *bp++ = c; 554 ++hdrslen; 555 if (!headeronly && 556 MaxHeadersLength > 0 && 557 hdrslen > MaxHeadersLength) 558 { 559 sm_syslog(LOG_NOTICE, e->e_id, 560 "headers too large (%d max) from %s during message collect", 561 MaxHeadersLength, 562 CURHOSTNAME); 563 errno = 0; 564 e->e_flags |= EF_CLRQUEUE; 565 e->e_status = "5.6.0"; 566 usrerrenh(e->e_status, 567 "552 Headers too large (%d max)", 568 MaxHeadersLength); 569 mstate = MS_DISCARD; 570 } 571 } 572 if (istate == IS_BOL) 573 break; 574 } 575 *bp = '\0'; 576 577 nextstate: 578 if (tTd(30, 35)) 579 sm_dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", 580 istate, mstate, buf); 581 switch (mstate) 582 { 583 case MS_UFROM: 584 mstate = MS_HEADER; 585 #ifndef NOTUNIX 586 if (strncmp(buf, "From ", 5) == 0) 587 { 588 bp = buf; 589 eatfrom(buf, e); 590 continue; 591 } 592 #endif /* ! NOTUNIX */ 593 /* FALLTHROUGH */ 594 595 case MS_HEADER: 596 if (!isheader(buf)) 597 { 598 mstate = MS_BODY; 599 goto nextstate; 600 } 601 602 /* check for possible continuation line */ 603 do 604 { 605 sm_io_clearerr(fp); 606 errno = 0; 607 c = sm_io_getc(fp, SM_TIME_DEFAULT); 608 } while (c == SM_IO_EOF && errno == EINTR); 609 if (c != SM_IO_EOF) 610 (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c); 611 if (c == ' ' || c == '\t') 612 { 613 /* yep -- defer this */ 614 continue; 615 } 616 617 /* trim off trailing CRLF or NL */ 618 if (*--bp != '\n' || *--bp != '\r') 619 bp++; 620 *bp = '\0'; 621 622 if (bitset(H_EOH, chompheader(buf, 623 CHHDR_CHECK | CHHDR_USER, 624 hdrp, e))) 625 { 626 mstate = MS_BODY; 627 goto nextstate; 628 } 629 numhdrs++; 630 break; 631 632 case MS_BODY: 633 if (tTd(30, 1)) 634 sm_dprintf("EOH\n"); 635 636 if (headeronly) 637 goto readerr; 638 639 df = collect_eoh(e, numhdrs, hdrslen); 640 if (df == NULL) 641 e->e_flags |= EF_TOOBIG; 642 643 bp = buf; 644 645 /* toss blank line */ 646 if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) && 647 bp[0] == '\r' && bp[1] == '\n') || 648 (!bitset(EF_NL_NOT_EOL, e->e_flags) && 649 bp[0] == '\n')) 650 { 651 break; 652 } 653 654 /* if not a blank separator, write it out */ 655 if (!bitset(EF_TOOBIG, e->e_flags)) 656 { 657 while (*bp != '\0') 658 (void) sm_io_putc(df, SM_TIME_DEFAULT, 659 *bp++); 660 } 661 break; 662 } 663 bp = buf; 664 } 665 666 readerr: 667 if ((sm_io_eof(fp) && smtpmode) || sm_io_error(fp)) 668 { 669 const char *errmsg; 670 671 if (sm_io_eof(fp)) 672 errmsg = "unexpected close"; 673 else 674 errmsg = sm_errstring(errno); 675 if (tTd(30, 1)) 676 sm_dprintf("collect: premature EOM: %s\n", errmsg); 677 if (LogLevel > 1) 678 sm_syslog(LOG_WARNING, e->e_id, 679 "collect: premature EOM: %s", errmsg); 680 inputerr = true; 681 } 682 683 /* reset global timer */ 684 if (CollectTimeout != NULL) 685 sm_clrevent(CollectTimeout); 686 687 if (headeronly) 688 return; 689 690 if (mstate != MS_BODY) 691 { 692 /* no body or discard, so we never opened the data file */ 693 SM_ASSERT(df == NULL); 694 df = collect_eoh(e, numhdrs, hdrslen); 695 } 696 697 if (df == NULL) 698 { 699 /* skip next few clauses */ 700 /* EMPTY */ 701 } 702 else if (sm_io_flush(df, SM_TIME_DEFAULT) != 0 || sm_io_error(df)) 703 { 704 dferror(df, "sm_io_flush||sm_io_error", e); 705 flush_errors(true); 706 finis(true, true, ExitStat); 707 /* NOTREACHED */ 708 } 709 else if (SuperSafe != SAFE_REALLY) 710 { 711 /* skip next few clauses */ 712 /* EMPTY */ 713 } 714 else if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0 && errno != EINVAL) 715 { 716 int save_errno = errno; 717 718 if (save_errno == EEXIST) 719 { 720 char *dfile; 721 struct stat st; 722 int dfd; 723 724 dfile = queuename(e, DATAFL_LETTER); 725 if (stat(dfile, &st) < 0) 726 st.st_size = -1; 727 errno = EEXIST; 728 syserr("@collect: bfcommit(%s): already on disk, size = %ld", 729 dfile, (long) st.st_size); 730 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL); 731 if (dfd >= 0) 732 dumpfd(dfd, true, true); 733 } 734 errno = save_errno; 735 dferror(df, "bfcommit", e); 736 flush_errors(true); 737 finis(save_errno != EEXIST, true, ExitStat); 738 } 739 else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) >= 0 && 740 fsync(afd) < 0) 741 { 742 dferror(df, "fsync", e); 743 flush_errors(true); 744 finis(true, true, ExitStat); 745 /* NOTREACHED */ 746 } 747 else if (sm_io_close(df, SM_TIME_DEFAULT) < 0) 748 { 749 dferror(df, "sm_io_close", e); 750 flush_errors(true); 751 finis(true, true, ExitStat); 752 /* NOTREACHED */ 753 } 754 else 755 { 756 /* everything is happily flushed to disk */ 757 df = NULL; 758 759 /* remove from available space in filesystem */ 760 updfs(e, false, true); 761 } 762 763 /* An EOF when running SMTP is an error */ 764 if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 765 { 766 char *host; 767 char *problem; 768 769 host = RealHostName; 770 if (host == NULL) 771 host = "localhost"; 772 773 if (sm_io_eof(fp)) 774 problem = "unexpected close"; 775 else if (sm_io_error(fp)) 776 problem = "I/O error"; 777 else 778 problem = "read timeout"; 779 if (LogLevel > 0 && sm_io_eof(fp)) 780 sm_syslog(LOG_NOTICE, e->e_id, 781 "collect: %s on connection from %.100s, sender=%s", 782 problem, host, 783 shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); 784 if (sm_io_eof(fp)) 785 usrerr("451 4.4.1 collect: %s on connection from %s, from=%s", 786 problem, host, 787 shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); 788 else 789 syserr("451 4.4.1 collect: %s on connection from %s, from=%s", 790 problem, host, 791 shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); 792 793 /* don't return an error indication */ 794 e->e_to = NULL; 795 e->e_flags &= ~EF_FATALERRS; 796 e->e_flags |= EF_CLRQUEUE; 797 798 finis(true, true, ExitStat); 799 /* NOTREACHED */ 800 } 801 802 /* Log collection information. */ 803 if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) 804 { 805 logsender(e, e->e_msgid); 806 e->e_flags &= ~EF_LOGSENDER; 807 } 808 809 /* check for message too large */ 810 if (bitset(EF_TOOBIG, e->e_flags)) 811 { 812 e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE; 813 if (!bitset(EF_FATALERRS, e->e_flags)) 814 { 815 e->e_status = "5.2.3"; 816 usrerrenh(e->e_status, 817 "552 Message exceeds maximum fixed size (%ld)", 818 MaxMessageSize); 819 if (LogLevel > 6) 820 sm_syslog(LOG_NOTICE, e->e_id, 821 "message size (%ld) exceeds maximum (%ld)", 822 e->e_msgsize, MaxMessageSize); 823 } 824 } 825 826 /* check for illegal 8-bit data */ 827 if (HasEightBits) 828 { 829 e->e_flags |= EF_HAS8BIT; 830 if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) && 831 !bitset(EF_IS_MIME, e->e_flags)) 832 { 833 e->e_status = "5.6.1"; 834 usrerrenh(e->e_status, "554 Eight bit data not allowed"); 835 } 836 } 837 else 838 { 839 /* if it claimed to be 8 bits, well, it lied.... */ 840 if (e->e_bodytype != NULL && 841 sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) 842 e->e_bodytype = "7BIT"; 843 } 844 845 if (SuperSafe == SAFE_REALLY && !bitset(EF_FATALERRS, e->e_flags)) 846 { 847 char *dfname = queuename(e, DATAFL_LETTER); 848 if ((e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname, 849 SM_IO_RDONLY, NULL)) == NULL) 850 { 851 /* we haven't acked receipt yet, so just chuck this */ 852 syserr("@Cannot reopen %s", dfname); 853 finis(true, true, ExitStat); 854 /* NOTREACHED */ 855 } 856 } 857 else 858 e->e_dfp = df; 859 860 /* collect statistics */ 861 if (OpMode != MD_VERIFY) 862 markstats(e, (ADDRESS *) NULL, STATS_NORMAL); 863 } 864 865 static void 866 collecttimeout(timeout) 867 time_t timeout; 868 { 869 int save_errno = errno; 870 871 /* 872 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 873 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 874 ** DOING. 875 */ 876 877 if (CollectProgress) 878 { 879 /* reset the timeout */ 880 CollectTimeout = sm_sigsafe_setevent(timeout, collecttimeout, 881 timeout); 882 CollectProgress = false; 883 } 884 else 885 { 886 /* event is done */ 887 CollectTimeout = NULL; 888 } 889 890 /* if no progress was made or problem resetting event, die now */ 891 if (CollectTimeout == NULL) 892 { 893 errno = ETIMEDOUT; 894 longjmp(CtxCollectTimeout, 1); 895 } 896 errno = save_errno; 897 } 898 /* 899 ** DFERROR -- signal error on writing the data file. 900 ** 901 ** Called by collect(). Collect() always terminates the process 902 ** immediately after calling dferror(), which means that the SMTP 903 ** session will be terminated, which means that any error message 904 ** issued by dferror must be a 421 error, as per RFC 821. 905 ** 906 ** Parameters: 907 ** df -- the file pointer for the data file. 908 ** msg -- detailed message. 909 ** e -- the current envelope. 910 ** 911 ** Returns: 912 ** none. 913 ** 914 ** Side Effects: 915 ** Gives an error message. 916 ** Arranges for following output to go elsewhere. 917 */ 918 919 static void 920 dferror(df, msg, e) 921 SM_FILE_T *volatile df; 922 char *msg; 923 register ENVELOPE *e; 924 { 925 char *dfname; 926 927 dfname = queuename(e, DATAFL_LETTER); 928 setstat(EX_IOERR); 929 if (errno == ENOSPC) 930 { 931 #if STAT64 > 0 932 struct stat64 st; 933 #else /* STAT64 > 0 */ 934 struct stat st; 935 #endif /* STAT64 > 0 */ 936 long avail; 937 long bsize; 938 939 e->e_flags |= EF_NO_BODY_RETN; 940 941 if ( 942 #if STAT64 > 0 943 fstat64(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st) 944 #else /* STAT64 > 0 */ 945 fstat(sm_io_getinfo(df, SM_IO_WHAT_FD, NULL), &st) 946 #endif /* STAT64 > 0 */ 947 < 0) 948 st.st_size = 0; 949 (void) sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, dfname, 950 SM_IO_WRONLY, NULL, df); 951 if (st.st_size <= 0) 952 (void) sm_io_fprintf(df, SM_TIME_DEFAULT, 953 "\n*** Mail could not be accepted"); 954 else 955 (void) sm_io_fprintf(df, SM_TIME_DEFAULT, 956 "\n*** Mail of at least %llu bytes could not be accepted\n", 957 (ULONGLONG_T) st.st_size); 958 (void) sm_io_fprintf(df, SM_TIME_DEFAULT, 959 "*** at %s due to lack of disk space for temp file.\n", 960 MyHostName); 961 avail = freediskspace(qid_printqueue(e->e_qgrp, e->e_qdir), 962 &bsize); 963 if (avail > 0) 964 { 965 if (bsize > 1024) 966 avail *= bsize / 1024; 967 else if (bsize < 1024) 968 avail /= 1024 / bsize; 969 (void) sm_io_fprintf(df, SM_TIME_DEFAULT, 970 "*** Currently, %ld kilobytes are available for mail temp files.\n", 971 avail); 972 } 973 #if 0 974 /* Wrong response code; should be 421. */ 975 e->e_status = "4.3.1"; 976 usrerrenh(e->e_status, "452 Out of disk space for temp file"); 977 #else /* 0 */ 978 syserr("421 4.3.1 Out of disk space for temp file"); 979 #endif /* 0 */ 980 } 981 else 982 syserr("421 4.3.0 collect: Cannot write %s (%s, uid=%d, gid=%d)", 983 dfname, msg, (int) geteuid(), (int) getegid()); 984 if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL, 985 SM_IO_WRONLY, NULL, df) == NULL) 986 sm_syslog(LOG_ERR, e->e_id, 987 "dferror: sm_io_reopen(\"/dev/null\") failed: %s", 988 sm_errstring(errno)); 989 } 990 /* 991 ** EATFROM -- chew up a UNIX style from line and process 992 ** 993 ** This does indeed make some assumptions about the format 994 ** of UNIX messages. 995 ** 996 ** Parameters: 997 ** fm -- the from line. 998 ** 999 ** Returns: 1000 ** none. 1001 ** 1002 ** Side Effects: 1003 ** extracts what information it can from the header, 1004 ** such as the date. 1005 */ 1006 1007 #ifndef NOTUNIX 1008 1009 static char *DowList[] = 1010 { 1011 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 1012 }; 1013 1014 static char *MonthList[] = 1015 { 1016 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1017 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 1018 NULL 1019 }; 1020 1021 static void 1022 eatfrom(fm, e) 1023 char *volatile fm; 1024 register ENVELOPE *e; 1025 { 1026 register char *p; 1027 register char **dt; 1028 1029 if (tTd(30, 2)) 1030 sm_dprintf("eatfrom(%s)\n", fm); 1031 1032 /* find the date part */ 1033 p = fm; 1034 while (*p != '\0') 1035 { 1036 /* skip a word */ 1037 while (*p != '\0' && *p != ' ') 1038 p++; 1039 while (*p == ' ') 1040 p++; 1041 if (strlen(p) < 17) 1042 { 1043 /* no room for the date */ 1044 return; 1045 } 1046 if (!(isascii(*p) && isupper(*p)) || 1047 p[3] != ' ' || p[13] != ':' || p[16] != ':') 1048 continue; 1049 1050 /* we have a possible date */ 1051 for (dt = DowList; *dt != NULL; dt++) 1052 if (strncmp(*dt, p, 3) == 0) 1053 break; 1054 if (*dt == NULL) 1055 continue; 1056 1057 for (dt = MonthList; *dt != NULL; dt++) 1058 { 1059 if (strncmp(*dt, &p[4], 3) == 0) 1060 break; 1061 } 1062 if (*dt != NULL) 1063 break; 1064 } 1065 1066 if (*p != '\0') 1067 { 1068 char *q, buf[25]; 1069 1070 /* we have found a date */ 1071 (void) sm_strlcpy(buf, p, sizeof(buf)); 1072 q = arpadate(buf); 1073 macdefine(&e->e_macro, A_TEMP, 'a', q); 1074 } 1075 } 1076 #endif /* ! NOTUNIX */ 1077