collect.c revision 43730
1191005Sdelphij/* 2204977Simp * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 331899Ssef * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 431899Ssef * Copyright (c) 1988, 1993 531899Ssef * The Regents of the University of California. All rights reserved. 631899Ssef * 731899Ssef * By using this file, you agree to the terms and conditions set 831899Ssef * forth in the LICENSE file which can be found at the top level of 931899Ssef * the sendmail distribution. 1031899Ssef * 1131899Ssef */ 1231899Ssef 1331899Ssef#ifndef lint 1431899Ssefstatic char sccsid[] = "@(#)collect.c 8.93 (Berkeley) 1/26/1999"; 1531899Ssef#endif /* not lint */ 1631899Ssef 1731899Ssef# include <errno.h> 1831899Ssef# include "sendmail.h" 1931899Ssef 2031899Ssef/* 2131899Ssef** COLLECT -- read & parse message header & make temp file. 2231899Ssef** 2331899Ssef** Creates a temporary file name and copies the standard 2431899Ssef** input to that file. Leading UNIX-style "From" lines are 2531899Ssef** stripped off (after important information is extracted). 2631899Ssef** 2731899Ssef** Parameters: 2831899Ssef** fp -- file to read. 2931899Ssef** smtpmode -- if set, we are running SMTP: give an RFC821 3031899Ssef** style message to say we are ready to collect 3131899Ssef** input, and never ignore a single dot to mean 32119852Scharnier** end of message. 33119852Scharnier** hdrp -- the location to stash the header. 3432275Scharnier** e -- the current envelope. 3531899Ssef** 36222103Sbcr** Returns: 3731567Ssef** none. 3831567Ssef** 3931567Ssef** Side Effects: 4031567Ssef** Temp file is created and filled. 4185301Sdes** The from person may be set. 42123916Scracauer*/ 43104581Smike 44123916Scracauerstatic jmp_buf CtxCollectTimeout; 45168569Sdelphijstatic void collecttimeout __P((time_t)); 46191005Sdelphijstatic bool CollectProgress; 4785301Sdesstatic EVENT *CollectTimeout; 4832275Scharnier 49200462Sdelphij/* values for input state machine */ 50200462Sdelphij#define IS_NORM 0 /* middle of line */ 5132275Scharnier#define IS_BOL 1 /* beginning of line */ 5231567Ssef#define IS_DOT 2 /* read a dot at beginning of line */ 5331567Ssef#define IS_DOTCR 3 /* read ".\r" at beginning of line */ 5431567Ssef#define IS_CR 4 /* read a carriage return */ 55101423Smdodd 5631579Speter/* values for message state machine */ 5731567Ssef#define MS_UFROM 0 /* reading Unix from line */ 58101282Smdodd#define MS_HEADER 1 /* reading message header */ 5987703Smarkm#define MS_BODY 2 /* reading message body */ 60192025Sdds#define MS_DISCARD 3 /* discarding rest of message */ 6131567Ssef 62240005Szontvoid 6331567Ssefcollect(fp, smtpmode, hdrp, e) 64144177Salfred FILE *fp; 6532275Scharnier bool smtpmode; 6632275Scharnier HDR **hdrp; 67144177Salfred register ENVELOPE *e; 68192025Sdds{ 69192025Sdds register FILE *volatile tf; 70144177Salfred volatile bool ignrdot = smtpmode ? FALSE : IgnrDot; 7131567Ssef volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0; 7231567Ssef register char *volatile bp; 7338897Ssef volatile int c = EOF; 7438897Ssef volatile bool inputerr = FALSE; 7538897Ssef bool headeronly; 7638897Ssef char *volatile buf; 77228396Sed volatile int buflen; 78144177Salfred volatile int istate; 79144177Salfred volatile int mstate; 80144177Salfred u_char *volatile pbp; 8131567Ssef int hdrslen = 0; 82130394Sdwmalone u_char peekbuf[8]; 83144177Salfred char dfname[MAXQFNAME]; 84179051Sjhb char bufbuf[MAXLINE]; 85179051Sjhb extern bool isheader __P((char *)); 86130394Sdwmalone extern void tferror __P((FILE *volatile, ENVELOPE *)); 8739908Ssef 88144177Salfred headeronly = hdrp != NULL; 89144177Salfred 90144177Salfred /* 91144177Salfred ** Create the temp file name and create the file. 9239908Ssef */ 93106716Smarcel 94144177Salfred if (!headeronly) 95106716Smarcel { 96154047Sgrehan int tfd; 97154047Sgrehan struct stat stbuf; 98154047Sgrehan 99211935Snwhitehorn strcpy(dfname, queuename(e, 'd')); 100211935Snwhitehorn tfd = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode, SFF_ANYFILE); 101154047Sgrehan if (tfd < 0 || (tf = fdopen(tfd, "w")) == NULL) 102211935Snwhitehorn { 103101320Sjake syserr("Cannot create %s", dfname); 104144177Salfred e->e_flags |= EF_NO_BODY_RETN; 105101320Sjake finis(TRUE, ExitStat); 106188628Simp } 107188628Simp if (fstat(fileno(tf), &stbuf) < 0) 108188628Simp e->e_dfino = -1; 109188628Simp else 110188628Simp { 111144177Salfred e->e_dfdev = stbuf.st_dev; 11231567Ssef e->e_dfino = stbuf.st_ino; 11331567Ssef } 11431567Ssef HasEightBits = FALSE; 11531567Ssef e->e_msgsize = 0; 116240005Szont e->e_flags |= EF_HAS_DF; 11731567Ssef } 11831567Ssef 11931567Ssef /* 120144177Salfred ** Tell ARPANET to go ahead. 121144177Salfred */ 122144177Salfred 123240005Szont if (smtpmode) 124240005Szont message("354 Enter mail, end with \".\" on a line by itself"); 125240005Szont 126144177Salfred if (tTd(30, 2)) 12731567Ssef printf("collect\n"); 128240005Szont 129168569Sdelphij /* 130168569Sdelphij ** Read the message. 131168569Sdelphij ** 132168569Sdelphij ** This is done using two interleaved state machines. 133168569Sdelphij ** The input state machine is looking for things like 134168569Sdelphij ** hidden dots; the message state machine is handling 135168569Sdelphij ** the larger picture (e.g., header versus body). 13631567Ssef */ 137144177Salfred 138240005Szont buf = bp = bufbuf; 139144177Salfred buflen = sizeof bufbuf; 14031567Ssef pbp = peekbuf; 141144177Salfred istate = IS_BOL; 142144177Salfred mstate = SaveFrom ? MS_HEADER : MS_UFROM; 143144177Salfred CollectProgress = FALSE; 144144177Salfred 145144177Salfred if (dbto != 0) 146144177Salfred { 14731567Ssef /* handle possible input timeout */ 14831567Ssef if (setjmp(CtxCollectTimeout) != 0) 149132306Salfred { 150132306Salfred if (LogLevel > 2) 151132306Salfred sm_syslog(LOG_NOTICE, e->e_id, 152132306Salfred "timeout waiting for input from %s during message collect", 153132306Salfred CurHostName ? CurHostName : "<local machine>"); 154132306Salfred errno = 0; 155132306Salfred usrerr("451 timeout waiting for input during message collect"); 156218285Sjilles goto readerr; 157132306Salfred } 158132306Salfred CollectTimeout = setevent(dbto, collecttimeout, dbto); 159132306Salfred } 160132306Salfred 161132306Salfred for (;;) 162132306Salfred { 16332275Scharnier if (tTd(30, 35)) 164144177Salfred printf("top, istate=%d, mstate=%d\n", istate, mstate); 165144177Salfred for (;;) 166144177Salfred { 167240005Szont if (pbp > peekbuf) 168144178Salfred c = *--pbp; 169144177Salfred else 170240005Szont { 171240005Szont while (!feof(fp) && !ferror(fp)) 172240005Szont { 17331567Ssef errno = 0; 174144178Salfred c = getc(fp); 175144178Salfred if (errno != EINTR) 176144178Salfred break; 177144177Salfred clearerr(fp); 178192153Sdelphij } 179144177Salfred CollectProgress = TRUE; 180192153Sdelphij if (TrafficLogFile != NULL && !headeronly) 181192153Sdelphij { 182144177Salfred if (istate == IS_BOL) 183153963Sbrian fprintf(TrafficLogFile, "%05d <<< ", 184168569Sdelphij (int) getpid()); 185168569Sdelphij if (c == EOF) 186168569Sdelphij fprintf(TrafficLogFile, "[EOF]\n"); 187192025Sdds else 188144177Salfred putc(c, TrafficLogFile); 189144177Salfred } 190144177Salfred if (c == EOF) 191171055Sdelphij goto readerr; 192240005Szont if (SevenBitInput) 193171055Sdelphij c &= 0x7f; 194171055Sdelphij else 195171055Sdelphij HasEightBits |= bitset(0x80, c); 196144177Salfred } 197144177Salfred if (tTd(30, 94)) 198144177Salfred printf("istate=%d, c=%c (0x%x)\n", 199144177Salfred istate, c, c); 200144177Salfred switch (istate) 201144177Salfred { 202144177Salfred case IS_BOL: 203192025Sdds if (c == '.') 204192025Sdds { 205192025Sdds istate = IS_DOT; 206144177Salfred continue; 207144177Salfred } 208144177Salfred break; 209144177Salfred 210144177Salfred case IS_DOT: 211144177Salfred if (c == '\n' && !ignrdot && 212144177Salfred !bitset(EF_NL_NOT_EOL, e->e_flags)) 213144177Salfred goto readerr; 214144177Salfred else if (c == '\r' && 215144177Salfred !bitset(EF_CRLF_NOT_EOL, e->e_flags)) 216144177Salfred { 217144177Salfred istate = IS_DOTCR; 218153963Sbrian continue; 219153963Sbrian } 220153963Sbrian else if (c != '.' || 221240005Szont (OpMode != MD_SMTP && 222144177Salfred OpMode != MD_DAEMON && 223144177Salfred OpMode != MD_ARPAFTP)) 224144177Salfred { 225144177Salfred *pbp++ = c; 226144177Salfred c = '.'; 227144177Salfred } 22831567Ssef break; 229144177Salfred 230144177Salfred case IS_DOTCR: 231144177Salfred if (c == '\n' && !ignrdot) 232144177Salfred goto readerr; 23331567Ssef else 234144177Salfred { 235144177Salfred /* push back the ".\rx" */ 236144177Salfred *pbp++ = c; 237215235Sjh *pbp++ = '\r'; 238215235Sjh c = '.'; 239215235Sjh } 240215235Sjh break; 241215235Sjh 242215235Sjh case IS_CR: 243215235Sjh if (c == '\n') 244144177Salfred istate = IS_BOL; 24532275Scharnier else 246144177Salfred { 247144177Salfred ungetc(c, fp); 248144177Salfred c = '\r'; 249144177Salfred istate = IS_NORM; 250144177Salfred } 251144177Salfred goto bufferchar; 25231567Ssef } 253144177Salfred 254144177Salfred if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags)) 255144177Salfred { 256144177Salfred istate = IS_CR; 257144177Salfred continue; 258144177Salfred } 259144177Salfred else if (c == '\n' && !bitset(EF_NL_NOT_EOL, e->e_flags)) 260168569Sdelphij istate = IS_BOL; 261144177Salfred else 262144177Salfred istate = IS_NORM; 263144177Salfred 264144177Salfredbufferchar: 26531567Ssef if (!headeronly) 26631567Ssef e->e_msgsize++; 267144177Salfred switch (mstate) 268144177Salfred { 269144177Salfred case MS_BODY: 270144177Salfred /* just put the character out */ 27131567Ssef if (MaxMessageSize <= 0 || 272101283Smdodd e->e_msgsize <= MaxMessageSize) 273168569Sdelphij putc(c, tf); 274168569Sdelphij 275144178Salfred /* fall through */ 276144177Salfred 277144177Salfred case MS_DISCARD: 278144177Salfred continue; 279144177Salfred } 280144177Salfred 28131567Ssef /* header -- buffer up */ 282144177Salfred if (bp >= &buf[buflen - 2]) 283101285Smdodd { 284144177Salfred char *obuf; 285158630Spav 286168569Sdelphij if (mstate != MS_HEADER) 28731567Ssef break; 288240005Szont 289168569Sdelphij /* out of space for header */ 290168569Sdelphij obuf = buf; 291168569Sdelphij if (buflen < MEMCHUNKSIZE) 292168569Sdelphij buflen *= 2; 293168569Sdelphij else 294168569Sdelphij buflen += MEMCHUNKSIZE; 295168569Sdelphij buf = xalloc(buflen); 296168569Sdelphij bcopy(obuf, buf, bp - obuf); 29731567Ssef bp = &buf[bp - obuf]; 298168569Sdelphij if (obuf != bufbuf) 299168569Sdelphij free(obuf); 300168569Sdelphij } 301240005Szont if (c >= 0200 && c <= 0237) 302240005Szont { 303101283Smdodd#if 0 /* causes complaints -- figure out something for 8.9 */ 304168569Sdelphij usrerr("Illegal character 0x%x in header", c); 305168569Sdelphij#endif 306168569Sdelphij } 307168569Sdelphij else if (c != '\0') 308168569Sdelphij { 309168569Sdelphij *bp++ = c; 310168569Sdelphij if (MaxHeadersLength > 0 && 311168569Sdelphij ++hdrslen > MaxHeadersLength) 312168569Sdelphij { 313144177Salfred sm_syslog(LOG_NOTICE, e->e_id, 314144177Salfred "headers too large (%d max) from %s during message collect", 315168569Sdelphij MaxHeadersLength, 316168569Sdelphij CurHostName != NULL ? CurHostName : "localhost"); 317168569Sdelphij errno = 0; 318168569Sdelphij e->e_flags |= EF_CLRQUEUE; 319168569Sdelphij e->e_status = "5.6.0"; 320144177Salfred usrerr("552 Headers too large (%d max)", 321168569Sdelphij MaxHeadersLength); 322168569Sdelphij mstate = MS_DISCARD; 323168569Sdelphij } 324168569Sdelphij } 325168569Sdelphij if (istate == IS_BOL) 326168569Sdelphij break; 327168569Sdelphij } 328168569Sdelphij *bp = '\0'; 329168569Sdelphij 330144177Salfrednextstate: 331168569Sdelphij if (tTd(30, 35)) 332168569Sdelphij printf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", 333168569Sdelphij istate, mstate, buf); 334168569Sdelphij switch (mstate) 335168569Sdelphij { 336168569Sdelphij case MS_UFROM: 337168569Sdelphij mstate = MS_HEADER; 338168569Sdelphij#ifndef NOTUNIX 339168569Sdelphij if (strncmp(buf, "From ", 5) == 0) 340168569Sdelphij { 341168569Sdelphij extern void eatfrom __P((char *volatile, ENVELOPE *)); 342168569Sdelphij 343168569Sdelphij bp = buf; 344168569Sdelphij eatfrom(buf, e); 345192025Sdds continue; 346192025Sdds } 347168569Sdelphij#endif 348168569Sdelphij /* fall through */ 349168569Sdelphij 350168569Sdelphij case MS_HEADER: 351168569Sdelphij if (!isheader(buf)) 352168569Sdelphij { 353168569Sdelphij mstate = MS_BODY; 354168569Sdelphij goto nextstate; 355168569Sdelphij } 356168569Sdelphij 357168569Sdelphij /* check for possible continuation line */ 358240005Szont do 359240005Szont { 360240005Szont clearerr(fp); 361240005Szont errno = 0; 362168569Sdelphij c = getc(fp); 363168569Sdelphij } while (errno == EINTR); 364168569Sdelphij if (c != EOF) 365168569Sdelphij ungetc(c, fp); 366168569Sdelphij if (c == ' ' || c == '\t') 367168569Sdelphij { 368144177Salfred /* yep -- defer this */ 369168569Sdelphij continue; 370191005Sdelphij } 371240005Szont 372191005Sdelphij /* trim off trailing CRLF or NL */ 373191005Sdelphij if (*--bp != '\n' || *--bp != '\r') 374191005Sdelphij bp++; 375240005Szont *bp = '\0'; 376191005Sdelphij 377240005Szont if (bitset(H_EOH, chompheader(buf, FALSE, hdrp, e))) 378240005Szont { 379192025Sdds mstate = MS_BODY; 380192025Sdds goto nextstate; 381192025Sdds } 382144177Salfred break; 38331567Ssef 384 case MS_BODY: 385 if (tTd(30, 1)) 386 printf("EOH\n"); 387 if (headeronly) 388 goto readerr; 389 bp = buf; 390 391 /* toss blank line */ 392 if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) && 393 bp[0] == '\r' && bp[1] == '\n') || 394 (!bitset(EF_NL_NOT_EOL, e->e_flags) && 395 bp[0] == '\n')) 396 { 397 break; 398 } 399 400 /* if not a blank separator, write it out */ 401 if (MaxMessageSize <= 0 || 402 e->e_msgsize <= MaxMessageSize) 403 { 404 while (*bp != '\0') 405 putc(*bp++, tf); 406 } 407 break; 408 } 409 bp = buf; 410 } 411 412readerr: 413 if ((feof(fp) && smtpmode) || ferror(fp)) 414 { 415 const char *errmsg = errstring(errno); 416 417 if (tTd(30, 1)) 418 printf("collect: premature EOM: %s\n", errmsg); 419 if (LogLevel >= 2) 420 sm_syslog(LOG_WARNING, e->e_id, 421 "collect: premature EOM: %s", errmsg); 422 inputerr = TRUE; 423 } 424 425 /* reset global timer */ 426 clrevent(CollectTimeout); 427 428 if (headeronly) 429 return; 430 431 if (tf != NULL && 432 (fflush(tf) != 0 || ferror(tf) || 433 (SuperSafe && fsync(fileno(tf)) < 0) || 434 fclose(tf) < 0)) 435 { 436 tferror(tf, e); 437 flush_errors(TRUE); 438 finis(TRUE, ExitStat); 439 } 440 441 /* An EOF when running SMTP is an error */ 442 if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 443 { 444 char *host; 445 char *problem; 446 447 host = RealHostName; 448 if (host == NULL) 449 host = "localhost"; 450 451 if (feof(fp)) 452 problem = "unexpected close"; 453 else if (ferror(fp)) 454 problem = "I/O error"; 455 else 456 problem = "read timeout"; 457 if (LogLevel > 0 && feof(fp)) 458 sm_syslog(LOG_NOTICE, e->e_id, 459 "collect: %s on connection from %.100s, sender=%s: %s", 460 problem, host, 461 shortenstring(e->e_from.q_paddr, MAXSHORTSTR), 462 errstring(errno)); 463 if (feof(fp)) 464 usrerr("451 collect: %s on connection from %s, from=%s", 465 problem, host, 466 shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); 467 else 468 syserr("451 collect: %s on connection from %s, from=%s", 469 problem, host, 470 shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); 471 472 /* don't return an error indication */ 473 e->e_to = NULL; 474 e->e_flags &= ~EF_FATALERRS; 475 e->e_flags |= EF_CLRQUEUE; 476 477 /* and don't try to deliver the partial message either */ 478 if (InChild) 479 ExitStat = EX_QUIT; 480 finis(TRUE, ExitStat); 481 } 482 483 /* 484 ** Find out some information from the headers. 485 ** Examples are who is the from person & the date. 486 */ 487 488 eatheader(e, TRUE); 489 490 if (GrabTo && e->e_sendqueue == NULL) 491 usrerr("No recipient addresses found in header"); 492 493 /* collect statistics */ 494 if (OpMode != MD_VERIFY) 495 markstats(e, (ADDRESS *) NULL, FALSE); 496 497#if _FFR_DSN_RRT_OPTION 498 /* 499 ** If we have a Return-Receipt-To:, turn it into a DSN. 500 */ 501 502 if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL) 503 { 504 ADDRESS *q; 505 506 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 507 if (!bitset(QHASNOTIFY, q->q_flags)) 508 q->q_flags |= QHASNOTIFY|QPINGONSUCCESS; 509 } 510#endif 511 512 /* 513 ** Add an Apparently-To: line if we have no recipient lines. 514 */ 515 516 if (hvalue("to", e->e_header) != NULL || 517 hvalue("cc", e->e_header) != NULL || 518 hvalue("apparently-to", e->e_header) != NULL) 519 { 520 /* have a valid recipient header -- delete Bcc: headers */ 521 e->e_flags |= EF_DELETE_BCC; 522 } 523 else if (hvalue("bcc", e->e_header) == NULL) 524 { 525 /* no valid recipient headers */ 526 register ADDRESS *q; 527 char *hdr = NULL; 528 529 /* create an Apparently-To: field */ 530 /* that or reject the message.... */ 531 switch (NoRecipientAction) 532 { 533 case NRA_ADD_APPARENTLY_TO: 534 hdr = "Apparently-To"; 535 break; 536 537 case NRA_ADD_TO: 538 hdr = "To"; 539 break; 540 541 case NRA_ADD_BCC: 542 addheader("Bcc", " ", &e->e_header); 543 break; 544 545 case NRA_ADD_TO_UNDISCLOSED: 546 addheader("To", "undisclosed-recipients:;", &e->e_header); 547 break; 548 } 549 550 if (hdr != NULL) 551 { 552 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 553 { 554 if (q->q_alias != NULL) 555 continue; 556 if (tTd(30, 3)) 557 printf("Adding %s: %s\n", 558 hdr, q->q_paddr); 559 addheader(hdr, q->q_paddr, &e->e_header); 560 } 561 } 562 } 563 564 /* check for message too large */ 565 if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize) 566 { 567 e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE; 568 e->e_status = "5.2.3"; 569 usrerr("552 Message exceeds maximum fixed size (%ld)", 570 MaxMessageSize); 571 if (LogLevel > 6) 572 sm_syslog(LOG_NOTICE, e->e_id, 573 "message size (%ld) exceeds maximum (%ld)", 574 e->e_msgsize, MaxMessageSize); 575 } 576 577 /* check for illegal 8-bit data */ 578 if (HasEightBits) 579 { 580 e->e_flags |= EF_HAS8BIT; 581 if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) && 582 !bitset(EF_IS_MIME, e->e_flags)) 583 { 584 e->e_status = "5.6.1"; 585 usrerr("554 Eight bit data not allowed"); 586 } 587 } 588 else 589 { 590 /* if it claimed to be 8 bits, well, it lied.... */ 591 if (e->e_bodytype != NULL && 592 strcasecmp(e->e_bodytype, "8BITMIME") == 0) 593 e->e_bodytype = "7BIT"; 594 } 595 596 if ((e->e_dfp = fopen(dfname, "r")) == NULL) 597 { 598 /* we haven't acked receipt yet, so just chuck this */ 599 syserr("Cannot reopen %s", dfname); 600 finis(TRUE, ExitStat); 601 } 602} 603 604 605static void 606collecttimeout(timeout) 607 time_t timeout; 608{ 609 /* if no progress was made, die now */ 610 if (!CollectProgress) 611 longjmp(CtxCollectTimeout, 1); 612 613 /* otherwise reset the timeout */ 614 CollectTimeout = setevent(timeout, collecttimeout, timeout); 615 CollectProgress = FALSE; 616} 617/* 618** TFERROR -- signal error on writing the temporary file. 619** 620** Parameters: 621** tf -- the file pointer for the temporary file. 622** e -- the current envelope. 623** 624** Returns: 625** none. 626** 627** Side Effects: 628** Gives an error message. 629** Arranges for following output to go elsewhere. 630*/ 631 632void 633tferror(tf, e) 634 FILE *volatile tf; 635 register ENVELOPE *e; 636{ 637 setstat(EX_IOERR); 638 if (errno == ENOSPC) 639 { 640#if STAT64 > 0 641 struct stat64 st; 642#else 643 struct stat st; 644#endif 645 long avail; 646 long bsize; 647 extern long freediskspace __P((char *, long *)); 648 649 e->e_flags |= EF_NO_BODY_RETN; 650 651 if ( 652#if STAT64 > 0 653 fstat64(fileno(tf), &st) 654#else 655 fstat(fileno(tf), &st) 656#endif 657 < 0) 658 st.st_size = 0; 659 (void) freopen(queuename(e, 'd'), "w", tf); 660 if (st.st_size <= 0) 661 fprintf(tf, "\n*** Mail could not be accepted"); 662 else if (sizeof st.st_size > sizeof (long)) 663 fprintf(tf, "\n*** Mail of at least %s bytes could not be accepted\n", 664 quad_to_string(st.st_size)); 665 else 666 fprintf(tf, "\n*** Mail of at least %lu bytes could not be accepted\n", 667 (unsigned long) st.st_size); 668 fprintf(tf, "*** at %s due to lack of disk space for temp file.\n", 669 MyHostName); 670 avail = freediskspace(QueueDir, &bsize); 671 if (avail > 0) 672 { 673 if (bsize > 1024) 674 avail *= bsize / 1024; 675 else if (bsize < 1024) 676 avail /= 1024 / bsize; 677 fprintf(tf, "*** Currently, %ld kilobytes are available for mail temp files.\n", 678 avail); 679 } 680 e->e_status = "4.3.1"; 681 usrerr("452 Out of disk space for temp file"); 682 } 683 else 684 syserr("collect: Cannot write tf%s", e->e_id); 685 if (freopen("/dev/null", "w", tf) == NULL) 686 sm_syslog(LOG_ERR, e->e_id, 687 "tferror: freopen(\"/dev/null\") failed: %s", 688 errstring(errno)); 689} 690/* 691** EATFROM -- chew up a UNIX style from line and process 692** 693** This does indeed make some assumptions about the format 694** of UNIX messages. 695** 696** Parameters: 697** fm -- the from line. 698** 699** Returns: 700** none. 701** 702** Side Effects: 703** extracts what information it can from the header, 704** such as the date. 705*/ 706 707# ifndef NOTUNIX 708 709char *DowList[] = 710{ 711 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 712}; 713 714char *MonthList[] = 715{ 716 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 717 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 718 NULL 719}; 720 721void 722eatfrom(fm, e) 723 char *volatile fm; 724 register ENVELOPE *e; 725{ 726 register char *p; 727 register char **dt; 728 729 if (tTd(30, 2)) 730 printf("eatfrom(%s)\n", fm); 731 732 /* find the date part */ 733 p = fm; 734 while (*p != '\0') 735 { 736 /* skip a word */ 737 while (*p != '\0' && *p != ' ') 738 p++; 739 while (*p == ' ') 740 p++; 741 if (!(isascii(*p) && isupper(*p)) || 742 p[3] != ' ' || p[13] != ':' || p[16] != ':') 743 continue; 744 745 /* we have a possible date */ 746 for (dt = DowList; *dt != NULL; dt++) 747 if (strncmp(*dt, p, 3) == 0) 748 break; 749 if (*dt == NULL) 750 continue; 751 752 for (dt = MonthList; *dt != NULL; dt++) 753 if (strncmp(*dt, &p[4], 3) == 0) 754 break; 755 if (*dt != NULL) 756 break; 757 } 758 759 if (*p != '\0') 760 { 761 char *q; 762 763 /* we have found a date */ 764 q = xalloc(25); 765 (void) strncpy(q, p, 25); 766 q[24] = '\0'; 767 q = arpadate(q); 768 define('a', newstr(q), e); 769 } 770} 771 772# endif /* NOTUNIX */ 773