collect.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:18k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 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. #ifndef lint
  14. static char id[] = "@(#)$Id: collect.c,v 8.130 1999/12/06 21:48:49 ca Exp $";
  15. #endif /* ! lint */
  16. #include <sendmail.h>
  17. static void collecttimeout __P((time_t));
  18. static void dferror __P((FILE *volatile, char *, ENVELOPE *));
  19. static void eatfrom __P((char *volatile, ENVELOPE *));
  20. /*
  21. **  COLLECT -- read & parse message header & make temp file.
  22. **
  23. ** Creates a temporary file name and copies the standard
  24. ** input to that file.  Leading UNIX-style "From" lines are
  25. ** stripped off (after important information is extracted).
  26. **
  27. ** Parameters:
  28. ** fp -- file to read.
  29. ** smtpmode -- if set, we are running SMTP: give an RFC821
  30. ** style message to say we are ready to collect
  31. ** input, and never ignore a single dot to mean
  32. ** end of message.
  33. ** hdrp -- the location to stash the header.
  34. ** e -- the current envelope.
  35. **
  36. ** Returns:
  37. ** none.
  38. **
  39. ** Side Effects:
  40. ** Temp file is created and filled.
  41. ** The from person may be set.
  42. */
  43. static jmp_buf CtxCollectTimeout;
  44. static bool CollectProgress;
  45. static EVENT *CollectTimeout;
  46. /* values for input state machine */
  47. #define IS_NORM 0 /* middle of line */
  48. #define IS_BOL 1 /* beginning of line */
  49. #define IS_DOT 2 /* read a dot at beginning of line */
  50. #define IS_DOTCR 3 /* read ".r" at beginning of line */
  51. #define IS_CR 4 /* read a carriage return */
  52. /* values for message state machine */
  53. #define MS_UFROM 0 /* reading Unix from line */
  54. #define MS_HEADER 1 /* reading message header */
  55. #define MS_BODY 2 /* reading message body */
  56. #define MS_DISCARD 3 /* discarding rest of message */
  57. void
  58. collect(fp, smtpmode, hdrp, e)
  59. FILE *fp;
  60. bool smtpmode;
  61. HDR **hdrp;
  62. register ENVELOPE *e;
  63. {
  64. register FILE *volatile df;
  65. volatile bool ignrdot = smtpmode ? FALSE : IgnrDot;
  66. volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0;
  67. register char *volatile bp;
  68. volatile int c = EOF;
  69. volatile bool inputerr = FALSE;
  70. bool headeronly;
  71. char *volatile buf;
  72. volatile int buflen;
  73. volatile int istate;
  74. volatile int mstate;
  75. volatile int hdrslen = 0;
  76. volatile int numhdrs = 0;
  77. volatile int dfd;
  78. volatile int afd;
  79. volatile int chompflags = CHHDR_CHECK;
  80. volatile int rstat = EX_OK;
  81. u_char *volatile pbp;
  82. u_char peekbuf[8];
  83. char hsize[16];
  84. char hnum[16];
  85. char dfname[MAXPATHLEN];
  86. char bufbuf[MAXLINE];
  87. headeronly = hdrp != NULL;
  88. /*
  89. **  Create the temp file name and create the file.
  90. */
  91. if (!headeronly)
  92. {
  93. struct stat stbuf;
  94. (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname);
  95. df = bfopen(dfname, FileMode, DataFileBufferSize, SFF_OPENASROOT);
  96. if (df == NULL)
  97. {
  98. syserr("Cannot create %s", dfname);
  99. e->e_flags |= EF_NO_BODY_RETN;
  100. finis(TRUE, ExitStat);
  101. /* NOTREACHED */
  102. }
  103. dfd = fileno(df);
  104. if (dfd < 0 || fstat(dfd, &stbuf) < 0)
  105. e->e_dfino = -1;
  106. else
  107. {
  108. e->e_dfdev = stbuf.st_dev;
  109. e->e_dfino = stbuf.st_ino;
  110. }
  111. HasEightBits = FALSE;
  112. e->e_msgsize = 0;
  113. e->e_flags |= EF_HAS_DF;
  114. }
  115. /*
  116. **  Tell ARPANET to go ahead.
  117. */
  118. if (smtpmode)
  119. message("354 Enter mail, end with "." on a line by itself");
  120. if (tTd(30, 2))
  121. dprintf("collectn");
  122. /*
  123. **  Read the message.
  124. **
  125. ** This is done using two interleaved state machines.
  126. ** The input state machine is looking for things like
  127. ** hidden dots; the message state machine is handling
  128. ** the larger picture (e.g., header versus body).
  129. */
  130. buf = bp = bufbuf;
  131. buflen = sizeof bufbuf;
  132. pbp = peekbuf;
  133. istate = IS_BOL;
  134. mstate = SaveFrom ? MS_HEADER : MS_UFROM;
  135. CollectProgress = FALSE;
  136. if (dbto != 0)
  137. {
  138. /* handle possible input timeout */
  139. if (setjmp(CtxCollectTimeout) != 0)
  140. {
  141. if (LogLevel > 2)
  142. sm_syslog(LOG_NOTICE, e->e_id,
  143.     "timeout waiting for input from %s during message collect",
  144.     CurHostName ? CurHostName : "<local machine>");
  145. errno = 0;
  146. usrerr("451 4.4.1 timeout waiting for input during message collect");
  147. goto readerr;
  148. }
  149. CollectTimeout = setevent(dbto, collecttimeout, dbto);
  150. }
  151. for (;;)
  152. {
  153. if (tTd(30, 35))
  154. dprintf("top, istate=%d, mstate=%dn", istate, mstate);
  155. for (;;)
  156. {
  157. if (pbp > peekbuf)
  158. c = *--pbp;
  159. else
  160. {
  161. while (!feof(fp) && !ferror(fp))
  162. {
  163. errno = 0;
  164. c = getc(fp);
  165. if (errno != EINTR)
  166. break;
  167. clearerr(fp);
  168. }
  169. CollectProgress = TRUE;
  170. if (TrafficLogFile != NULL && !headeronly)
  171. {
  172. if (istate == IS_BOL)
  173. (void) fprintf(TrafficLogFile, "%05d <<< ",
  174. (int) getpid());
  175. if (c == EOF)
  176. (void) fprintf(TrafficLogFile, "[EOF]n");
  177. else
  178. (void) putc(c, TrafficLogFile);
  179. }
  180. if (c == EOF)
  181. goto readerr;
  182. if (SevenBitInput)
  183. c &= 0x7f;
  184. else
  185. HasEightBits |= bitset(0x80, c);
  186. }
  187. if (tTd(30, 94))
  188. dprintf("istate=%d, c=%c (0x%x)n",
  189. istate, (char) c, c);
  190. switch (istate)
  191. {
  192.   case IS_BOL:
  193. if (c == '.')
  194. {
  195. istate = IS_DOT;
  196. continue;
  197. }
  198. break;
  199.   case IS_DOT:
  200. if (c == 'n' && !ignrdot &&
  201.     !bitset(EF_NL_NOT_EOL, e->e_flags))
  202. goto readerr;
  203. else if (c == 'r' &&
  204.  !bitset(EF_CRLF_NOT_EOL, e->e_flags))
  205. {
  206. istate = IS_DOTCR;
  207. continue;
  208. }
  209. else if (c != '.' ||
  210.  (OpMode != MD_SMTP &&
  211.   OpMode != MD_DAEMON &&
  212.   OpMode != MD_ARPAFTP))
  213. {
  214. *pbp++ = c;
  215. c = '.';
  216. }
  217. break;
  218.   case IS_DOTCR:
  219. if (c == 'n' && !ignrdot)
  220. goto readerr;
  221. else
  222. {
  223. /* push back the ".rx" */
  224. *pbp++ = c;
  225. *pbp++ = 'r';
  226. c = '.';
  227. }
  228. break;
  229.   case IS_CR:
  230. if (c == 'n')
  231. istate = IS_BOL;
  232. else
  233. {
  234. (void) ungetc(c, fp);
  235. c = 'r';
  236. istate = IS_NORM;
  237. }
  238. goto bufferchar;
  239. }
  240. if (c == 'r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags))
  241. {
  242. istate = IS_CR;
  243. continue;
  244. }
  245. else if (c == 'n' && !bitset(EF_NL_NOT_EOL, e->e_flags))
  246. istate = IS_BOL;
  247. else
  248. istate = IS_NORM;
  249. bufferchar:
  250. if (!headeronly)
  251. e->e_msgsize++;
  252. switch (mstate)
  253. {
  254.   case MS_BODY:
  255. /* just put the character out */
  256. if (MaxMessageSize <= 0 ||
  257.     e->e_msgsize <= MaxMessageSize)
  258. (void) putc(c, df);
  259. /* FALLTHROUGH */
  260.   case MS_DISCARD:
  261. continue;
  262. }
  263. /* header -- buffer up */
  264. if (bp >= &buf[buflen - 2])
  265. {
  266. char *obuf;
  267. if (mstate != MS_HEADER)
  268. break;
  269. /* out of space for header */
  270. obuf = buf;
  271. if (buflen < MEMCHUNKSIZE)
  272. buflen *= 2;
  273. else
  274. buflen += MEMCHUNKSIZE;
  275. buf = xalloc(buflen);
  276. memmove(buf, obuf, bp - obuf);
  277. bp = &buf[bp - obuf];
  278. if (obuf != bufbuf)
  279. free(obuf);
  280. }
  281. if (c >= 0200 && c <= 0237)
  282. {
  283. #if 0 /* causes complaints -- figure out something for 8.11 */
  284. usrerr("Illegal character 0x%x in header", c);
  285. #else /* 0 */
  286. /* EMPTY */
  287. #endif /* 0 */
  288. }
  289. else if (c != '')
  290. {
  291. *bp++ = c;
  292. if (MaxHeadersLength > 0 &&
  293.     ++hdrslen > MaxHeadersLength)
  294. {
  295. sm_syslog(LOG_NOTICE, e->e_id,
  296.   "headers too large (%d max) from %s during message collect",
  297.   MaxHeadersLength,
  298.   CurHostName != NULL ? CurHostName : "localhost");
  299. errno = 0;
  300. e->e_flags |= EF_CLRQUEUE;
  301. e->e_status = "5.6.0";
  302. usrerrenh(e->e_status,
  303.   "552 Headers too large (%d max)",
  304.   MaxHeadersLength);
  305. mstate = MS_DISCARD;
  306. }
  307. }
  308. if (istate == IS_BOL)
  309. break;
  310. }
  311. *bp = '';
  312. nextstate:
  313. if (tTd(30, 35))
  314. dprintf("nextstate, istate=%d, mstate=%d, line = "%s"n",
  315. istate, mstate, buf);
  316. switch (mstate)
  317. {
  318.   case MS_UFROM:
  319. mstate = MS_HEADER;
  320. #ifndef NOTUNIX
  321. if (strncmp(buf, "From ", 5) == 0)
  322. {
  323. bp = buf;
  324. eatfrom(buf, e);
  325. continue;
  326. }
  327. #endif /* ! NOTUNIX */
  328. /* FALLTHROUGH */
  329.   case MS_HEADER:
  330. if (!isheader(buf))
  331. {
  332. mstate = MS_BODY;
  333. goto nextstate;
  334. }
  335. /* check for possible continuation line */
  336. do
  337. {
  338. clearerr(fp);
  339. errno = 0;
  340. c = getc(fp);
  341. } while (errno == EINTR);
  342. if (c != EOF)
  343. (void) ungetc(c, fp);
  344. if (c == ' ' || c == 't')
  345. {
  346. /* yep -- defer this */
  347. continue;
  348. }
  349. /* trim off trailing CRLF or NL */
  350. if (*--bp != 'n' || *--bp != 'r')
  351. bp++;
  352. *bp = '';
  353. if (bitset(H_EOH, chompheader(buf, (int *)&chompflags,
  354.       hdrp, e)))
  355. {
  356. mstate = MS_BODY;
  357. goto nextstate;
  358. }
  359. numhdrs++;
  360. break;
  361.   case MS_BODY:
  362. if (tTd(30, 1))
  363. dprintf("EOHn");
  364. if (headeronly)
  365. goto readerr;
  366. /* call the end-of-header check ruleset */
  367. snprintf(hnum, sizeof hnum, "%d", numhdrs);
  368. snprintf(hsize, sizeof hsize, "%d", hdrslen);
  369. if (tTd(30, 10))
  370. dprintf("collect: rscheck("check_eoh", "%s $| %s")n",
  371. hnum, hsize);
  372. rstat = rscheck("check_eoh", hnum, hsize, e, FALSE,
  373. TRUE);
  374. bp = buf;
  375. /* toss blank line */
  376. if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) &&
  377. bp[0] == 'r' && bp[1] == 'n') ||
  378.     (!bitset(EF_NL_NOT_EOL, e->e_flags) &&
  379. bp[0] == 'n'))
  380. {
  381. break;
  382. }
  383. /* if not a blank separator, write it out */
  384. if (MaxMessageSize <= 0 ||
  385.     e->e_msgsize <= MaxMessageSize)
  386. {
  387. while (*bp != '')
  388. (void) putc(*bp++, df);
  389. }
  390. break;
  391. }
  392. bp = buf;
  393. }
  394. readerr:
  395. if ((feof(fp) && smtpmode) || ferror(fp))
  396. {
  397. const char *errmsg = errstring(errno);
  398. if (tTd(30, 1))
  399. dprintf("collect: premature EOM: %sn", errmsg);
  400. if (LogLevel >= 2)
  401. sm_syslog(LOG_WARNING, e->e_id,
  402. "collect: premature EOM: %s", errmsg);
  403. inputerr = TRUE;
  404. }
  405. /* reset global timer */
  406. clrevent(CollectTimeout);
  407. if (headeronly)
  408. return;
  409. if (df == NULL)
  410. {
  411. /* skip next few clauses */
  412. /* EMPTY */
  413. }
  414. else if (fflush(df) != 0 || ferror(df))
  415. {
  416. dferror(df, "fflush||ferror", e);
  417. flush_errors(TRUE);
  418. finis(TRUE, ExitStat);
  419. /* NOTREACHED */
  420. }
  421. else if (!SuperSafe)
  422. {
  423. /* skip next few clauses */
  424. /* EMPTY */
  425. }
  426. else if ((afd = fileno(df)) >= 0 && fsync(afd) < 0)
  427. {
  428. dferror(df, "fsync", e);
  429. flush_errors(TRUE);
  430. finis(TRUE, ExitStat);
  431. /* NOTREACHED */
  432. }
  433. else if (bfcommit(df) < 0)
  434. {
  435. int save_errno = errno;
  436. if (save_errno == EEXIST)
  437. {
  438. char *dfile;
  439. struct stat st;
  440. dfile = queuename(e, 'd');
  441. if (stat(dfile, &st) < 0)
  442. st.st_size = -1;
  443. errno = EEXIST;
  444. syserr("collect: bfcommit(%s): already on disk, size = %ld",
  445.        dfile, st.st_size);
  446. dfd = fileno(df);
  447. if (dfd >= 0)
  448. dumpfd(dfd, TRUE, TRUE);
  449. }
  450. errno = save_errno;
  451. dferror(df, "bfcommit", e);
  452. flush_errors(TRUE);
  453. finis(save_errno != EEXIST, ExitStat);
  454. }
  455. else if (bfclose(df) < 0)
  456. {
  457. dferror(df, "bfclose", e);
  458. flush_errors(TRUE);
  459. finis(TRUE, ExitStat);
  460. /* NOTREACHED */
  461. }
  462. else
  463. {
  464. /* everything is happily flushed to disk */
  465. df = NULL;
  466. }
  467. /* An EOF when running SMTP is an error */
  468. if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
  469. {
  470. char *host;
  471. char *problem;
  472. host = RealHostName;
  473. if (host == NULL)
  474. host = "localhost";
  475. if (feof(fp))
  476. problem = "unexpected close";
  477. else if (ferror(fp))
  478. problem = "I/O error";
  479. else
  480. problem = "read timeout";
  481. if (LogLevel > 0 && feof(fp))
  482. sm_syslog(LOG_NOTICE, e->e_id,
  483.     "collect: %s on connection from %.100s, sender=%s: %s",
  484.     problem, host,
  485.     shortenstring(e->e_from.q_paddr, MAXSHORTSTR),
  486.     errstring(errno));
  487. if (feof(fp))
  488. usrerr("451 4.4.1 collect: %s on connection from %s, from=%s",
  489. problem, host,
  490. shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
  491. else
  492. syserr("451 4.4.1 collect: %s on connection from %s, from=%s",
  493. problem, host,
  494. shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
  495. /* don't return an error indication */
  496. e->e_to = NULL;
  497. e->e_flags &= ~EF_FATALERRS;
  498. e->e_flags |= EF_CLRQUEUE;
  499. /* and don't try to deliver the partial message either */
  500. if (InChild)
  501. ExitStat = EX_QUIT;
  502. finis(TRUE, ExitStat);
  503. /* NOTREACHED */
  504. }
  505. /*
  506. **  Find out some information from the headers.
  507. ** Examples are who is the from person & the date.
  508. */
  509. eatheader(e, TRUE);
  510. if (GrabTo && e->e_sendqueue == NULL)
  511. usrerr("No recipient addresses found in header");
  512. /* collect statistics */
  513. if (OpMode != MD_VERIFY)
  514. markstats(e, (ADDRESS *) NULL, FALSE);
  515. /*
  516. **  If we have a Return-Receipt-To:, turn it into a DSN.
  517. */
  518. if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL)
  519. {
  520. ADDRESS *q;
  521. for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  522. if (!bitset(QHASNOTIFY, q->q_flags))
  523. q->q_flags |= QHASNOTIFY|QPINGONSUCCESS;
  524. }
  525. /*
  526. **  Add an Apparently-To: line if we have no recipient lines.
  527. */
  528. if (hvalue("to", e->e_header) != NULL ||
  529.     hvalue("cc", e->e_header) != NULL ||
  530.     hvalue("apparently-to", e->e_header) != NULL)
  531. {
  532. /* have a valid recipient header -- delete Bcc: headers */
  533. e->e_flags |= EF_DELETE_BCC;
  534. }
  535. else if (hvalue("bcc", e->e_header) == NULL)
  536. {
  537. /* no valid recipient headers */
  538. register ADDRESS *q;
  539. char *hdr = NULL;
  540. /* create an Apparently-To: field */
  541. /*    that or reject the message.... */
  542. switch (NoRecipientAction)
  543. {
  544.   case NRA_ADD_APPARENTLY_TO:
  545. hdr = "Apparently-To";
  546. break;
  547.   case NRA_ADD_TO:
  548. hdr = "To";
  549. break;
  550.   case NRA_ADD_BCC:
  551. addheader("Bcc", " ", &e->e_header);
  552. break;
  553.   case NRA_ADD_TO_UNDISCLOSED:
  554. addheader("To", "undisclosed-recipients:;", &e->e_header);
  555. break;
  556. }
  557. if (hdr != NULL)
  558. {
  559. for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  560. {
  561. if (q->q_alias != NULL)
  562. continue;
  563. if (tTd(30, 3))
  564. dprintf("Adding %s: %sn",
  565. hdr, q->q_paddr);
  566. addheader(hdr, q->q_paddr, &e->e_header);
  567. }
  568. }
  569. }
  570. /* check for message too large */
  571. if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize)
  572. {
  573. e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE;
  574. e->e_status = "5.2.3";
  575. usrerrenh(e->e_status,
  576.   "552 Message exceeds maximum fixed size (%ld)",
  577.   MaxMessageSize);
  578. if (LogLevel > 6)
  579. sm_syslog(LOG_NOTICE, e->e_id,
  580. "message size (%ld) exceeds maximum (%ld)",
  581. e->e_msgsize, MaxMessageSize);
  582. }
  583. /* check for illegal 8-bit data */
  584. if (HasEightBits)
  585. {
  586. e->e_flags |= EF_HAS8BIT;
  587. if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) &&
  588.     !bitset(EF_IS_MIME, e->e_flags))
  589. {
  590. e->e_status = "5.6.1";
  591. usrerrenh(e->e_status, "554 Eight bit data not allowed");
  592. }
  593. }
  594. else
  595. {
  596. /* if it claimed to be 8 bits, well, it lied.... */
  597. if (e->e_bodytype != NULL &&
  598.     strcasecmp(e->e_bodytype, "8BITMIME") == 0)
  599. e->e_bodytype = "7BIT";
  600. }
  601. if (SuperSafe)
  602. {
  603. if ((e->e_dfp = fopen(dfname, "r")) == NULL)
  604. {
  605. /* we haven't acked receipt yet, so just chuck this */
  606. syserr("Cannot reopen %s", dfname);
  607. finis(TRUE, ExitStat);
  608. /* NOTREACHED */
  609. }
  610. }
  611. else
  612. e->e_dfp = df;
  613. if (e->e_dfp == NULL)
  614. syserr("!collect: no e_dfp");
  615. }
  616. static void
  617. collecttimeout(timeout)
  618. time_t timeout;
  619. {
  620. /* if no progress was made, die now */
  621. if (!CollectProgress)
  622. longjmp(CtxCollectTimeout, 1);
  623. /* otherwise reset the timeout */
  624. CollectTimeout = setevent(timeout, collecttimeout, timeout);
  625. CollectProgress = FALSE;
  626. }
  627. /*
  628. **  DFERROR -- signal error on writing the data file.
  629. **
  630. ** Parameters:
  631. ** df -- the file pointer for the data file.
  632. ** msg -- detailed message.
  633. ** e -- the current envelope.
  634. **
  635. ** Returns:
  636. ** none.
  637. **
  638. ** Side Effects:
  639. ** Gives an error message.
  640. ** Arranges for following output to go elsewhere.
  641. */
  642. static void
  643. dferror(df, msg, e)
  644. FILE *volatile df;
  645. char *msg;
  646. register ENVELOPE *e;
  647. {
  648. char *dfname;
  649. dfname = queuename(e, 'd');
  650. setstat(EX_IOERR);
  651. if (errno == ENOSPC)
  652. {
  653. #if STAT64 > 0
  654. struct stat64 st;
  655. #else /* STAT64 > 0 */
  656. struct stat st;
  657. #endif /* STAT64 > 0 */
  658. long avail;
  659. long bsize;
  660. e->e_flags |= EF_NO_BODY_RETN;
  661. if (
  662. #if STAT64 > 0
  663.     fstat64(fileno(df), &st)
  664. #else /* STAT64 > 0 */
  665.     fstat(fileno(df), &st)
  666. #endif /* STAT64 > 0 */
  667.     < 0)
  668.   st.st_size = 0;
  669. (void) freopen(dfname, "w", df);
  670. if (st.st_size <= 0)
  671. fprintf(df, "n*** Mail could not be accepted");
  672. /*CONSTCOND*/
  673. else if (sizeof st.st_size > sizeof (long))
  674. fprintf(df, "n*** Mail of at least %s bytes could not be acceptedn",
  675. quad_to_string(st.st_size));
  676. else
  677. fprintf(df, "n*** Mail of at least %lu bytes could not be acceptedn",
  678. (unsigned long) st.st_size);
  679. fprintf(df, "*** at %s due to lack of disk space for temp file.n",
  680. MyHostName);
  681. avail = freediskspace(qid_printqueue(e->e_queuedir), &bsize);
  682. if (avail > 0)
  683. {
  684. if (bsize > 1024)
  685. avail *= bsize / 1024;
  686. else if (bsize < 1024)
  687. avail /= 1024 / bsize;
  688. fprintf(df, "*** Currently, %ld kilobytes are available for mail temp files.n",
  689. avail);
  690. }
  691. e->e_status = "4.3.1";
  692. usrerrenh(e->e_status, "452 Out of disk space for temp file");
  693. }
  694. else
  695. syserr("collect: Cannot write %s (%s, uid=%d)",
  696. dfname, msg, geteuid());
  697. if (freopen("/dev/null", "w", df) == NULL)
  698. sm_syslog(LOG_ERR, e->e_id,
  699.   "dferror: freopen("/dev/null") failed: %s",
  700.   errstring(errno));
  701. }
  702. /*
  703. **  EATFROM -- chew up a UNIX style from line and process
  704. **
  705. ** This does indeed make some assumptions about the format
  706. ** of UNIX messages.
  707. **
  708. ** Parameters:
  709. ** fm -- the from line.
  710. **
  711. ** Returns:
  712. ** none.
  713. **
  714. ** Side Effects:
  715. ** extracts what information it can from the header,
  716. ** such as the date.
  717. */
  718. #ifndef NOTUNIX
  719. static char *DowList[] =
  720. {
  721. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
  722. };
  723. static char *MonthList[] =
  724. {
  725. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  726. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  727. NULL
  728. };
  729. static void
  730. eatfrom(fm, e)
  731. char *volatile fm;
  732. register ENVELOPE *e;
  733. {
  734. register char *p;
  735. register char **dt;
  736. if (tTd(30, 2))
  737. dprintf("eatfrom(%s)n", fm);
  738. /* find the date part */
  739. p = fm;
  740. while (*p != '')
  741. {
  742. /* skip a word */
  743. while (*p != '' && *p != ' ')
  744. p++;
  745. while (*p == ' ')
  746. p++;
  747. if (!(isascii(*p) && isupper(*p)) ||
  748.     p[3] != ' ' || p[13] != ':' || p[16] != ':')
  749. continue;
  750. /* we have a possible date */
  751. for (dt = DowList; *dt != NULL; dt++)
  752. if (strncmp(*dt, p, 3) == 0)
  753. break;
  754. if (*dt == NULL)
  755. continue;
  756. for (dt = MonthList; *dt != NULL; dt++)
  757. if (strncmp(*dt, &p[4], 3) == 0)
  758. break;
  759. if (*dt != NULL)
  760. break;
  761. }
  762. if (*p != '')
  763. {
  764. char *q;
  765. /* we have found a date */
  766. q = xalloc(25);
  767. (void) strlcpy(q, p, 25);
  768. q = arpadate(q);
  769. define('a', newstr(q), e);
  770. }
  771. }
  772. #endif /* ! NOTUNIX */