Commit | Line | Data |
---|---|---|
d185cb11 | 1 | /* |
dc45ba8c | 2 | * Copyright (c) 1983 Eric P. Allman |
31de980b KB |
3 | * Copyright (c) 1988, 1993 |
4 | * The Regents of the University of California. All rights reserved. | |
bee79b64 | 5 | * |
417f7a11 | 6 | * %sccs.include.redist.c% |
bee79b64 | 7 | */ |
d185cb11 DF |
8 | |
9 | #ifndef lint | |
7d858063 | 10 | static char sccsid[] = "@(#)collect.c 8.26 (Berkeley) %G%"; |
bee79b64 | 11 | #endif /* not lint */ |
d185cb11 | 12 | |
b8020f57 | 13 | # include <errno.h> |
96faada8 | 14 | # include "sendmail.h" |
cb590f52 | 15 | |
cb590f52 | 16 | /* |
a530c75f | 17 | ** COLLECT -- read & parse message header & make temp file. |
cb590f52 EA |
18 | ** |
19 | ** Creates a temporary file name and copies the standard | |
7338e3d4 EA |
20 | ** input to that file. Leading UNIX-style "From" lines are |
21 | ** stripped off (after important information is extracted). | |
cb590f52 EA |
22 | ** |
23 | ** Parameters: | |
c23930c0 | 24 | ** fp -- file to read. |
17df0fcb EA |
25 | ** from -- the person we think it may be from. If |
26 | ** there is a "From" line, we will replace | |
27 | ** the name of the person by this. If NULL, | |
28 | ** do no such replacement. | |
cb590f52 EA |
29 | ** |
30 | ** Returns: | |
17df0fcb EA |
31 | ** Name of the "from" person extracted from the |
32 | ** arpanet header. | |
cb590f52 EA |
33 | ** |
34 | ** Side Effects: | |
35 | ** Temp file is created and filled. | |
dc39c568 | 36 | ** The from person may be set. |
cb590f52 EA |
37 | */ |
38 | ||
fd540fcc EA |
39 | char *CollectErrorMessage; |
40 | bool CollectErrno; | |
41 | ||
0d721ffb EA |
42 | static jmp_buf CtxCollectTimeout; |
43 | static int collecttimeout(); | |
44 | static bool CollectProgress; | |
45 | static EVENT *CollectTimeout; | |
46 | ||
47 | /* values for input state machine */ | |
48 | #define IS_NORM 0 /* middle of line */ | |
49 | #define IS_BOL 1 /* beginning of line */ | |
50 | #define IS_DOT 2 /* read a dot at beginning of line */ | |
51 | #define IS_DOTCR 3 /* read ".\r" at beginning of line */ | |
52 | #define IS_CR 4 /* read a carriage return */ | |
53 | ||
54 | /* values for message state machine */ | |
55 | #define MS_UFROM 0 /* reading Unix from line */ | |
56 | #define MS_HEADER 1 /* reading message header */ | |
57 | #define MS_BODY 2 /* reading message body */ | |
58 | ||
59 | ||
17df0fcb EA |
60 | maketemp(from) |
61 | char *from; | |
cb590f52 EA |
62 | { |
63 | register FILE *tf; | |
6f121a53 | 64 | bool ignrdot = smtpmode ? FALSE : IgnrDot; |
77ca787d | 65 | time_t dbto = smtpmode ? TimeOuts.to_datablock : 0; |
0d721ffb EA |
66 | register char *bp; |
67 | register int c; | |
fe3849ea | 68 | bool inputerr = FALSE; |
c23930c0 | 69 | bool headeronly = FALSE; |
0d721ffb EA |
70 | char *buf; |
71 | int buflen; | |
72 | int istate; | |
73 | int mstate; | |
74 | char *pbp; | |
75 | char peekbuf[8]; | |
76 | char bufbuf[MAXLINE]; | |
0d721ffb | 77 | extern bool isheader(); |
17df0fcb | 78 | extern char *index(); |
cb590f52 | 79 | |
fd540fcc EA |
80 | CollectErrorMessage = NULL; |
81 | CollectErrno = 0; | |
c23930c0 EA |
82 | if (hdrp == NULL) |
83 | hdrp = &e->e_header; | |
84 | else | |
85 | headeronly = TRUE; | |
fd540fcc | 86 | |
cb590f52 EA |
87 | /* |
88 | ** Create the temp file name and create the file. | |
89 | */ | |
90 | ||
c23930c0 | 91 | if (!headeronly) |
cb590f52 | 92 | { |
f009d24b EA |
93 | struct stat stbuf; |
94 | ||
c23930c0 EA |
95 | e->e_df = queuename(e, 'd'); |
96 | e->e_df = newstr(e->e_df); | |
97 | if ((tf = dfopen(e->e_df, O_WRONLY|O_CREAT|O_TRUNC, FileMode)) == NULL) | |
98 | { | |
99 | syserr("Cannot create %s", e->e_df); | |
100 | e->e_flags |= EF_NORETURN; | |
101 | finis(); | |
102 | } | |
f009d24b EA |
103 | if (fstat(fileno(tf), &stbuf) < 0) |
104 | e->e_dfino = -1; | |
105 | else | |
bb4fde22 EA |
106 | { |
107 | e->e_dfdev = stbuf.st_dev; | |
f009d24b | 108 | e->e_dfino = stbuf.st_ino; |
bb4fde22 | 109 | } |
c23930c0 | 110 | HasEightBits = FALSE; |
cb590f52 EA |
111 | } |
112 | ||
d6b27179 EA |
113 | /* |
114 | ** Tell ARPANET to go ahead. | |
115 | */ | |
116 | ||
6f121a53 | 117 | if (smtpmode) |
b6edea3d | 118 | message("354 Enter mail, end with \".\" on a line by itself"); |
d6b27179 | 119 | |
74c5fe7c | 120 | /* |
0d721ffb EA |
121 | ** Read the message. |
122 | ** | |
123 | ** This is done using two interleaved state machines. | |
124 | ** The input state machine is looking for things like | |
125 | ** hidden dots; the message state machine is handling | |
126 | ** the larger picture (e.g., header versus body). | |
74c5fe7c EA |
127 | */ |
128 | ||
0d721ffb EA |
129 | buf = bp = bufbuf; |
130 | buflen = sizeof bufbuf; | |
131 | pbp = peekbuf; | |
132 | istate = IS_BOL; | |
133 | mstate = SaveFrom ? MS_HEADER : MS_UFROM; | |
134 | CollectProgress = FALSE; | |
1a12c7d6 | 135 | |
0d721ffb EA |
136 | /* if transmitting binary, don't map NL to EOL */ |
137 | if (e->e_bodytype != NULL && strcasecmp(e->e_bodytype, "8BITMIME") == 0) | |
138 | e->e_flags |= EF_NL_NOT_EOL; | |
cb590f52 | 139 | |
0d721ffb | 140 | if (dbto != 0) |
cb590f52 | 141 | { |
0d721ffb EA |
142 | /* handle possible input timeout */ |
143 | if (setjmp(CtxCollectTimeout) != 0) | |
a909e430 | 144 | { |
0d721ffb EA |
145 | #ifdef LOG |
146 | syslog(LOG_NOTICE, | |
147 | "timeout waiting for input from %s during message collect", | |
148 | CurHostName ? CurHostName : "<local machine>"); | |
149 | #endif | |
150 | errno = 0; | |
151 | usrerr("451 timeout waiting for input during message collect"); | |
a909e430 | 152 | goto readerr; |
0d721ffb EA |
153 | } |
154 | CollectTimeout = setevent(dbto, collecttimeout, dbto); | |
155 | } | |
76f46f56 | 156 | |
0d721ffb EA |
157 | for (;;) |
158 | { | |
159 | if (tTd(30, 35)) | |
160 | printf("top, istate=%d, mstate=%d\n", istate, mstate); | |
a909e430 | 161 | for (;;) |
cb590f52 | 162 | { |
0d721ffb EA |
163 | if (pbp > peekbuf) |
164 | c = *--pbp; | |
165 | else | |
7378b013 | 166 | { |
0d721ffb EA |
167 | while (!feof(InChannel) && !ferror(InChannel)) |
168 | { | |
169 | errno = 0; | |
170 | c = fgetc(InChannel); | |
171 | if (errno != EINTR) | |
172 | break; | |
173 | clearerr(InChannel); | |
174 | } | |
175 | CollectProgress = TRUE; | |
176 | if (TrafficLogFile != NULL) | |
177 | { | |
178 | if (istate == IS_BOL) | |
179 | fprintf(TrafficLogFile, "%05d <<< ", | |
180 | getpid()); | |
181 | if (c == EOF) | |
182 | fprintf(TrafficLogFile, "[EOF]\n"); | |
183 | else | |
184 | fputc(c, TrafficLogFile); | |
185 | } | |
186 | if (c == EOF) | |
187 | goto readerr; | |
188 | if (SevenBitInput) | |
189 | c &= 0x7f; | |
190 | else | |
191 | HasEightBits |= bitset(0x80, c); | |
192 | e->e_msgsize++; | |
7378b013 | 193 | } |
0d721ffb EA |
194 | if (tTd(30, 94)) |
195 | printf("istate=%d, c=%c (0x%x)\n", | |
196 | istate, c, c); | |
197 | switch (istate) | |
198 | { | |
199 | case IS_BOL: | |
200 | if (c == '.') | |
201 | { | |
202 | istate = IS_DOT; | |
203 | continue; | |
204 | } | |
205 | break; | |
a909e430 | 206 | |
0d721ffb EA |
207 | case IS_DOT: |
208 | if (c == '\n' && !ignrdot && | |
209 | !bitset(EF_NL_NOT_EOL, e->e_flags)) | |
210 | goto readerr; | |
211 | else if (c == '\r' && | |
212 | !bitset(EF_CRLF_NOT_EOL, e->e_flags)) | |
213 | { | |
214 | istate = IS_DOTCR; | |
215 | continue; | |
216 | } | |
217 | else if (c != '.' || | |
218 | (OpMode != MD_SMTP && | |
219 | OpMode != MD_DAEMON && | |
220 | OpMode != MD_ARPAFTP)) | |
221 | { | |
222 | *pbp++ = c; | |
223 | c = '.'; | |
224 | } | |
1a12c7d6 | 225 | break; |
a909e430 | 226 | |
0d721ffb EA |
227 | case IS_DOTCR: |
228 | if (c == '\n') | |
229 | goto readerr; | |
230 | else | |
231 | { | |
232 | /* push back the ".\rx" */ | |
233 | *pbp++ = c; | |
234 | *pbp++ = '\r'; | |
235 | c = '.'; | |
236 | } | |
237 | break; | |
a909e430 | 238 | |
0d721ffb | 239 | case IS_CR: |
8eea9dcb EA |
240 | if (c == '\n') |
241 | istate = IS_BOL; | |
242 | else | |
0d721ffb EA |
243 | { |
244 | ungetc(c, InChannel); | |
245 | c = '\r'; | |
8eea9dcb | 246 | istate = IS_NORM; |
0d721ffb | 247 | } |
8eea9dcb | 248 | goto bufferchar; |
0d721ffb | 249 | } |
f9e990ef | 250 | |
8eea9dcb | 251 | if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags)) |
a909e430 | 252 | { |
0d721ffb EA |
253 | istate = IS_CR; |
254 | continue; | |
a909e430 | 255 | } |
0d721ffb EA |
256 | else if (c == '\n' && !bitset(EF_NL_NOT_EOL, e->e_flags)) |
257 | istate = IS_BOL; | |
258 | else | |
259 | istate = IS_NORM; | |
a909e430 | 260 | |
8eea9dcb | 261 | bufferchar: |
0d721ffb EA |
262 | if (mstate == MS_BODY) |
263 | { | |
264 | /* just put the character out */ | |
2ccb80de EA |
265 | if (MaxMessageSize <= 0 || |
266 | e->e_msgsize <= MaxMessageSize) | |
267 | fputc(c, tf); | |
0d721ffb EA |
268 | continue; |
269 | } | |
c23930c0 | 270 | |
0d721ffb EA |
271 | /* header -- buffer up */ |
272 | if (bp >= &buf[buflen - 2]) | |
273 | { | |
274 | char *obuf; | |
275 | ||
276 | if (mstate != MS_HEADER) | |
277 | break; | |
278 | ||
279 | /* out of space for header */ | |
280 | obuf = buf; | |
281 | if (buflen < MEMCHUNKSIZE) | |
282 | buflen *= 2; | |
283 | else | |
284 | buflen += MEMCHUNKSIZE; | |
285 | buf = xalloc(buflen); | |
286 | bcopy(obuf, buf, bp - obuf); | |
287 | bp = &buf[bp - obuf]; | |
288 | if (obuf != bufbuf) | |
289 | free(obuf); | |
290 | } | |
291 | *bp++ = c; | |
292 | if (istate == IS_BOL) | |
293 | break; | |
294 | } | |
295 | *bp = '\0'; | |
1a12c7d6 | 296 | |
0d721ffb EA |
297 | nextstate: |
298 | if (tTd(30, 35)) | |
299 | printf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", | |
300 | istate, mstate, buf); | |
301 | switch (mstate) | |
302 | { | |
303 | case MS_UFROM: | |
304 | mstate = MS_HEADER; | |
305 | if (strncmp(buf, "From ", 5) == 0) | |
306 | { | |
c9845a7c | 307 | bp = buf; |
0d721ffb EA |
308 | eatfrom(buf, e); |
309 | continue; | |
310 | } | |
311 | /* fall through */ | |
cb590f52 | 312 | |
0d721ffb EA |
313 | case MS_HEADER: |
314 | if (!isheader(buf)) | |
315 | { | |
316 | mstate = MS_BODY; | |
317 | goto nextstate; | |
318 | } | |
71326571 | 319 | |
0d721ffb EA |
320 | /* check for possible continuation line */ |
321 | do | |
322 | { | |
323 | clearerr(InChannel); | |
324 | errno = 0; | |
325 | c = fgetc(InChannel); | |
326 | } while (errno == EINTR); | |
327 | if (c != EOF) | |
328 | ungetc(c, InChannel); | |
329 | if (c == ' ' || c == '\t') | |
330 | { | |
331 | /* yep -- defer this */ | |
332 | continue; | |
333 | } | |
2768afe3 | 334 | |
0d721ffb EA |
335 | /* trim off trailing CRLF or NL */ |
336 | if (*--bp != '\n' || *--bp != '\r') | |
337 | bp++; | |
338 | *bp = '\0'; | |
339 | if (bitset(H_EOH, chompheader(buf, FALSE, e))) | |
340 | mstate = MS_BODY; | |
1a12c7d6 EA |
341 | break; |
342 | ||
0d721ffb EA |
343 | case MS_BODY: |
344 | if (tTd(30, 1)) | |
345 | printf("EOH\n"); | |
346 | if (headeronly) | |
347 | goto readerr; | |
348 | bp = buf; | |
cbdb7357 | 349 | |
0d721ffb EA |
350 | /* toss blank line */ |
351 | if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) && | |
352 | bp[0] == '\r' && bp[1] == '\n') || | |
353 | (!bitset(EF_NL_NOT_EOL, e->e_flags) && | |
354 | bp[0] == '\n')) | |
355 | { | |
356 | break; | |
357 | } | |
71326571 | 358 | |
0d721ffb | 359 | /* if not a blank separator, write it out */ |
2ccb80de EA |
360 | if (MaxMessageSize <= 0 || |
361 | e->e_msgsize <= MaxMessageSize) | |
362 | { | |
363 | while (*bp != '\0') | |
364 | fputc(*bp++, tf); | |
365 | } | |
0d721ffb EA |
366 | break; |
367 | } | |
368 | bp = buf; | |
fe3849ea | 369 | } |
a909e430 KB |
370 | |
371 | readerr: | |
c23930c0 EA |
372 | if ((feof(fp) && smtpmode) || ferror(fp)) |
373 | { | |
7378b013 EA |
374 | if (tTd(30, 1)) |
375 | printf("collect: read error\n"); | |
fe3849ea EA |
376 | inputerr = TRUE; |
377 | } | |
378 | ||
0ab15a80 | 379 | /* reset global timer */ |
0d721ffb | 380 | clrevent(CollectTimeout); |
0ab15a80 | 381 | |
c23930c0 EA |
382 | if (headeronly) |
383 | return; | |
384 | ||
385 | if (tf != NULL) | |
eb1ada3c | 386 | { |
c23930c0 EA |
387 | if (fflush(tf) != 0) |
388 | tferror(tf, e); | |
389 | if (fsync(fileno(tf)) < 0 || fclose(tf) < 0) | |
390 | { | |
391 | tferror(tf, e); | |
392 | finis(); | |
393 | } | |
eb1ada3c | 394 | } |
1a12c7d6 | 395 | |
fd540fcc | 396 | if (CollectErrorMessage != NULL && Errors <= 0) |
b65a52af | 397 | { |
fd540fcc EA |
398 | if (CollectErrno != 0) |
399 | { | |
400 | errno = CollectErrno; | |
401 | syserr(CollectErrorMessage, e->e_df); | |
402 | finis(); | |
403 | } | |
404 | usrerr(CollectErrorMessage); | |
405 | } | |
406 | else if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) | |
407 | { | |
408 | /* An EOF when running SMTP is an error */ | |
5973222c | 409 | char *host; |
fe3849ea | 410 | char *problem; |
1c7897ef | 411 | |
5973222c EA |
412 | host = RealHostName; |
413 | if (host == NULL) | |
414 | host = "localhost"; | |
415 | ||
c23930c0 | 416 | if (feof(fp)) |
fe3849ea | 417 | problem = "unexpected close"; |
c23930c0 | 418 | else if (ferror(fp)) |
fe3849ea EA |
419 | problem = "I/O error"; |
420 | else | |
421 | problem = "read timeout"; | |
2e15a2d8 | 422 | # ifdef LOG |
c23930c0 | 423 | if (LogLevel > 0 && feof(fp)) |
ab4889ea | 424 | syslog(LOG_NOTICE, |
67d76dc4 EA |
425 | "collect: %s on connection from %s, sender=%s: %s\n", |
426 | problem, host, e->e_from.q_paddr, errstring(errno)); | |
2e15a2d8 | 427 | # endif |
c23930c0 | 428 | if (feof(fp)) |
90f66104 EA |
429 | usrerr("451 collect: %s on connection from %s, from=%s", |
430 | problem, host, e->e_from.q_paddr); | |
431 | else | |
432 | syserr("451 collect: %s on connection from %s, from=%s", | |
fe3849ea | 433 | problem, host, e->e_from.q_paddr); |
b65a52af EA |
434 | |
435 | /* don't return an error indication */ | |
a4076aed EA |
436 | e->e_to = NULL; |
437 | e->e_flags &= ~EF_FATALERRS; | |
1023828f | 438 | e->e_flags |= EF_CLRQUEUE; |
b65a52af EA |
439 | |
440 | /* and don't try to deliver the partial message either */ | |
fe3849ea EA |
441 | if (InChild) |
442 | ExitStat = EX_QUIT; | |
b65a52af EA |
443 | finis(); |
444 | } | |
0e33b011 | 445 | |
1a12c7d6 EA |
446 | /* |
447 | ** Find out some information from the headers. | |
2f0c5bd8 | 448 | ** Examples are who is the from person & the date. |
1a12c7d6 EA |
449 | */ |
450 | ||
959cf51d | 451 | eatheader(e, !requeueflag); |
9678c96d | 452 | |
f50419dd EA |
453 | /* collect statistics */ |
454 | if (OpMode != MD_VERIFY) | |
455 | markstats(e, (ADDRESS *) NULL); | |
456 | ||
75a2bcaf EA |
457 | /* |
458 | ** Add an Apparently-To: line if we have no recipient lines. | |
459 | */ | |
1a12c7d6 | 460 | |
c23930c0 EA |
461 | if (hvalue("to", e->e_header) == NULL && |
462 | hvalue("cc", e->e_header) == NULL && | |
463 | hvalue("bcc", e->e_header) == NULL && | |
464 | hvalue("apparently-to", e->e_header) == NULL) | |
f0375650 EA |
465 | { |
466 | register ADDRESS *q; | |
467 | ||
468 | /* create an Apparently-To: field */ | |
469 | /* that or reject the message.... */ | |
a4076aed | 470 | for (q = e->e_sendqueue; q != NULL; q = q->q_next) |
f0375650 | 471 | { |
755d533c EA |
472 | if (q->q_alias != NULL) |
473 | continue; | |
9678c96d | 474 | if (tTd(30, 3)) |
f0375650 | 475 | printf("Adding Apparently-To: %s\n", q->q_paddr); |
c23930c0 | 476 | addheader("Apparently-To", q->q_paddr, &e->e_header); |
f0375650 EA |
477 | } |
478 | } | |
479 | ||
213020d2 EA |
480 | /* check for message too large */ |
481 | if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize) | |
482 | { | |
483 | usrerr("552 Message exceeds maximum fixed size (%ld)", | |
484 | MaxMessageSize); | |
485 | } | |
486 | ||
e3c84ea8 EA |
487 | /* check for illegal 8-bit data */ |
488 | if (HasEightBits) | |
489 | { | |
490 | e->e_flags |= EF_HAS8BIT; | |
7d858063 | 491 | if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode)) |
e3c84ea8 EA |
492 | usrerr("554 Eight bit data not allowed"); |
493 | } | |
494 | ||
a4076aed | 495 | if ((e->e_dfp = fopen(e->e_df, "r")) == NULL) |
e0539260 EA |
496 | { |
497 | /* we haven't acked receipt yet, so just chuck this */ | |
a4076aed | 498 | syserr("Cannot reopen %s", e->e_df); |
e0539260 EA |
499 | finis(); |
500 | } | |
1a12c7d6 | 501 | } |
a909e430 | 502 | |
a909e430 | 503 | |
0d721ffb EA |
504 | static |
505 | collecttimeout(timeout) | |
506 | time_t timeout; | |
507 | { | |
508 | /* if no progress was made, die now */ | |
509 | if (!CollectProgress) | |
510 | longjmp(CtxCollectTimeout, 1); | |
a909e430 | 511 | |
0d721ffb EA |
512 | /* otherwise reset the timeout */ |
513 | CollectTimeout = setevent(timeout, collecttimeout, timeout); | |
514 | CollectProgress = FALSE; | |
a909e430 KB |
515 | } |
516 | \f/* | |
83f057f2 EA |
517 | ** TFERROR -- signal error on writing the temporary file. |
518 | ** | |
519 | ** Parameters: | |
520 | ** tf -- the file pointer for the temporary file. | |
521 | ** | |
522 | ** Returns: | |
523 | ** none. | |
524 | ** | |
525 | ** Side Effects: | |
526 | ** Gives an error message. | |
527 | ** Arranges for following output to go elsewhere. | |
528 | */ | |
529 | ||
a4076aed | 530 | tferror(tf, e) |
83f057f2 | 531 | FILE *tf; |
a4076aed | 532 | register ENVELOPE *e; |
83f057f2 | 533 | { |
fd540fcc | 534 | CollectErrno = errno; |
83f057f2 EA |
535 | if (errno == ENOSPC) |
536 | { | |
5825c126 EA |
537 | struct stat st; |
538 | long avail; | |
539 | long bsize; | |
540 | ||
2bade550 | 541 | e->e_flags |= EF_NORETURN; |
5825c126 EA |
542 | if (fstat(fileno(tf), &st) < 0) |
543 | st.st_size = 0; | |
a4076aed | 544 | (void) freopen(e->e_df, "w", tf); |
5825c126 EA |
545 | if (st.st_size <= 0) |
546 | fprintf(tf, "\n*** Mail could not be accepted"); | |
547 | else if (sizeof st.st_size > sizeof (long)) | |
548 | fprintf(tf, "\n*** Mail of at least %qd bytes could not be accepted\n", | |
549 | st.st_size); | |
550 | else | |
551 | fprintf(tf, "\n*** Mail of at least %ld bytes could not be accepted\n", | |
552 | st.st_size); | |
553 | fprintf(tf, "*** at %s due to lack of disk space for temp file.\n", | |
554 | MyHostName); | |
555 | avail = freespace(QueueDir, &bsize); | |
556 | if (avail > 0) | |
557 | { | |
558 | if (bsize > 1024) | |
559 | avail *= bsize / 1024; | |
560 | else if (bsize < 1024) | |
561 | avail /= 1024 / bsize; | |
562 | fprintf(tf, "*** Currently, %ld kilobytes are available for mail temp files.\n", | |
563 | avail); | |
564 | } | |
fd540fcc | 565 | CollectErrorMessage = "452 Out of disk space for temp file"; |
83f057f2 EA |
566 | } |
567 | else | |
fd540fcc EA |
568 | { |
569 | CollectErrorMessage = "cannot write message body to disk (%s)"; | |
570 | } | |
83f057f2 EA |
571 | (void) freopen("/dev/null", "w", tf); |
572 | } | |
573 | \f/* | |
1a12c7d6 EA |
574 | ** EATFROM -- chew up a UNIX style from line and process |
575 | ** | |
576 | ** This does indeed make some assumptions about the format | |
577 | ** of UNIX messages. | |
578 | ** | |
579 | ** Parameters: | |
580 | ** fm -- the from line. | |
581 | ** | |
582 | ** Returns: | |
583 | ** none. | |
584 | ** | |
585 | ** Side Effects: | |
586 | ** extracts what information it can from the header, | |
2f0c5bd8 | 587 | ** such as the date. |
1a12c7d6 EA |
588 | */ |
589 | ||
a4758674 EA |
590 | # ifndef NOTUNIX |
591 | ||
823c5e31 EA |
592 | char *DowList[] = |
593 | { | |
594 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL | |
595 | }; | |
596 | ||
1a12c7d6 EA |
597 | char *MonthList[] = |
598 | { | |
599 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
600 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", | |
601 | NULL | |
602 | }; | |
603 | ||
a4076aed | 604 | eatfrom(fm, e) |
1a12c7d6 | 605 | char *fm; |
a4076aed | 606 | register ENVELOPE *e; |
1a12c7d6 EA |
607 | { |
608 | register char *p; | |
609 | register char **dt; | |
610 | ||
9678c96d | 611 | if (tTd(30, 2)) |
823c5e31 | 612 | printf("eatfrom(%s)\n", fm); |
823c5e31 | 613 | |
1a12c7d6 EA |
614 | /* find the date part */ |
615 | p = fm; | |
616 | while (*p != '\0') | |
617 | { | |
618 | /* skip a word */ | |
619 | while (*p != '\0' && *p != ' ') | |
34fe0a9b | 620 | p++; |
1a12c7d6 | 621 | while (*p == ' ') |
34fe0a9b | 622 | p++; |
2bee003d EA |
623 | if (!(isascii(*p) && isupper(*p)) || |
624 | p[3] != ' ' || p[13] != ':' || p[16] != ':') | |
1a12c7d6 EA |
625 | continue; |
626 | ||
627 | /* we have a possible date */ | |
823c5e31 | 628 | for (dt = DowList; *dt != NULL; dt++) |
1a12c7d6 EA |
629 | if (strncmp(*dt, p, 3) == 0) |
630 | break; | |
823c5e31 EA |
631 | if (*dt == NULL) |
632 | continue; | |
1a12c7d6 | 633 | |
823c5e31 EA |
634 | for (dt = MonthList; *dt != NULL; dt++) |
635 | if (strncmp(*dt, &p[4], 3) == 0) | |
636 | break; | |
1a12c7d6 EA |
637 | if (*dt != NULL) |
638 | break; | |
639 | } | |
640 | ||
54d35e43 | 641 | if (*p != '\0') |
1a12c7d6 | 642 | { |
2f0c5bd8 | 643 | char *q; |
e863b1fa | 644 | extern char *arpadate(); |
2f0c5bd8 | 645 | |
1a12c7d6 | 646 | /* we have found a date */ |
2f0c5bd8 | 647 | q = xalloc(25); |
03388044 | 648 | (void) strncpy(q, p, 25); |
2f0c5bd8 | 649 | q[24] = '\0'; |
e863b1fa | 650 | q = arpadate(q); |
a4076aed | 651 | define('a', newstr(q), e); |
1a12c7d6 EA |
652 | } |
653 | } | |
a4758674 | 654 | |
f3d8f6d6 | 655 | # endif /* NOTUNIX */ |