|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Eric P. Allman
3: * Copyright (c) 1988 Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms are permitted
7: * provided that the above copyright notice and this paragraph are
8: * duplicated in all such forms and that any documentation,
9: * advertising materials, and other materials related to such
10: * distribution and use acknowledge that the software was developed
11: * by the University of California, Berkeley. The name of the
12: * University may not be used to endorse or promote products derived
13: * from this software without specific prior written permission.
14: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17: */
18:
19: #ifndef lint
20: static char sccsid[] = "@(#)collect.c 5.4 (Berkeley) 6/30/88";
21: #endif /* not lint */
22:
23: # include <errno.h>
24: # include "sendmail.h"
25:
26: /*
27: ** COLLECT -- read & parse message header & make temp file.
28: **
29: ** Creates a temporary file name and copies the standard
30: ** input to that file. Leading UNIX-style "From" lines are
31: ** stripped off (after important information is extracted).
32: **
33: ** Parameters:
34: ** sayok -- if set, give an ARPANET style message
35: ** to say we are ready to collect input.
36: **
37: ** Returns:
38: ** none.
39: **
40: ** Side Effects:
41: ** Temp file is created and filled.
42: ** The from person may be set.
43: */
44:
45: collect(sayok)
46: bool sayok;
47: {
48: register FILE *tf;
49: char buf[MAXFIELD+2];
50: register char *p;
51: extern char *hvalue();
52:
53: /*
54: ** Create the temp file name and create the file.
55: */
56:
57: CurEnv->e_df = newstr(queuename(CurEnv, 'd'));
58: if ((tf = dfopen(CurEnv->e_df, "w")) == NULL)
59: {
60: syserr("Cannot create %s", CurEnv->e_df);
61: NoReturn = TRUE;
62: finis();
63: }
64: (void) chmod(CurEnv->e_df, FileMode);
65:
66: /*
67: ** Tell ARPANET to go ahead.
68: */
69:
70: if (sayok)
71: message("354", "Enter mail, end with \".\" on a line by itself");
72:
73: /*
74: ** Try to read a UNIX-style From line
75: */
76:
77: (void) sfgets(buf, sizeof buf, InChannel);
78: fixcrlf(buf, FALSE);
79: # ifndef NOTUNIX
80: if (!SaveFrom && strncmp(buf, "From ", 5) == 0)
81: {
82: eatfrom(buf);
83: (void) sfgets(buf, sizeof buf, InChannel);
84: fixcrlf(buf, FALSE);
85: }
86: # endif NOTUNIX
87:
88: /*
89: ** Copy InChannel to temp file & do message editing.
90: ** To keep certain mailers from getting confused,
91: ** and to keep the output clean, lines that look
92: ** like UNIX "From" lines are deleted in the header.
93: */
94:
95: do
96: {
97: int c;
98: extern bool isheader();
99:
100: /* drop out on error */
101: if (ferror(InChannel))
102: break;
103:
104: /* if the line is too long, throw the rest away */
105: if (index(buf, '\n') == NULL)
106: {
107: while ((c = getc(InChannel)) != '\n' && c != EOF)
108: continue;
109: /* give an error? */
110: }
111:
112: fixcrlf(buf, TRUE);
113:
114: /* see if the header is over */
115: if (!isheader(buf))
116: break;
117:
118: /* get the rest of this field */
119: while ((c = getc(InChannel)) == ' ' || c == '\t')
120: {
121: p = &buf[strlen(buf)];
122: *p++ = '\n';
123: *p++ = c;
124: if (sfgets(p, MAXFIELD - (p - buf), InChannel) == NULL)
125: break;
126: fixcrlf(p, TRUE);
127: }
128: if (!feof(InChannel) && !ferror(InChannel))
129: (void) ungetc(c, InChannel);
130:
131: CurEnv->e_msgsize += strlen(buf);
132:
133: /*
134: ** Snarf header away.
135: */
136:
137: if (bitset(H_EOH, chompheader(buf, FALSE)))
138: break;
139: } while (sfgets(buf, MAXFIELD, InChannel) != NULL);
140:
141: # ifdef DEBUG
142: if (tTd(30, 1))
143: printf("EOH\n");
144: # endif DEBUG
145:
146: /* throw away a blank line */
147: if (buf[0] == '\0')
148: (void) sfgets(buf, MAXFIELD, InChannel);
149:
150: /*
151: ** Collect the body of the message.
152: */
153:
154: do
155: {
156: register char *bp = buf;
157:
158: fixcrlf(buf, TRUE);
159:
160: /* check for end-of-message */
161: if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
162: break;
163:
164: /* check for transparent dot */
165: if (OpMode == MD_SMTP && !IgnrDot && bp[0] == '.' && bp[1] == '.')
166: bp++;
167:
168: /*
169: ** Figure message length, output the line to the temp
170: ** file, and insert a newline if missing.
171: */
172:
173: CurEnv->e_msgsize += strlen(bp) + 1;
174: fputs(bp, tf);
175: fputs("\n", tf);
176: if (ferror(tf))
177: tferror(tf);
178: } while (sfgets(buf, MAXFIELD, InChannel) != NULL);
179: if (fflush(tf) != 0)
180: tferror(tf);
181: (void) fclose(tf);
182:
183: /* An EOF when running SMTP is an error */
184: if ((feof(InChannel) || ferror(InChannel)) && OpMode == MD_SMTP)
185: {
186: syserr("collect: unexpected close, from=%s", CurEnv->e_from.q_paddr);
187:
188: /* don't return an error indication */
189: CurEnv->e_to = NULL;
190: CurEnv->e_flags &= ~EF_FATALERRS;
191:
192: /* and don't try to deliver the partial message either */
193: finis();
194: }
195:
196: /*
197: ** Find out some information from the headers.
198: ** Examples are who is the from person & the date.
199: */
200:
201: eatheader(CurEnv);
202:
203: /*
204: ** Add an Apparently-To: line if we have no recipient lines.
205: */
206:
207: if (hvalue("to") == NULL && hvalue("cc") == NULL &&
208: hvalue("bcc") == NULL && hvalue("apparently-to") == NULL)
209: {
210: register ADDRESS *q;
211:
212: /* create an Apparently-To: field */
213: /* that or reject the message.... */
214: for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next)
215: {
216: if (q->q_alias != NULL)
217: continue;
218: # ifdef DEBUG
219: if (tTd(30, 3))
220: printf("Adding Apparently-To: %s\n", q->q_paddr);
221: # endif DEBUG
222: addheader("apparently-to", q->q_paddr, CurEnv);
223: }
224: }
225:
226: if ((CurEnv->e_dfp = fopen(CurEnv->e_df, "r")) == NULL)
227: syserr("Cannot reopen %s", CurEnv->e_df);
228: }
229: /*
230: ** TFERROR -- signal error on writing the temporary file.
231: **
232: ** Parameters:
233: ** tf -- the file pointer for the temporary file.
234: **
235: ** Returns:
236: ** none.
237: **
238: ** Side Effects:
239: ** Gives an error message.
240: ** Arranges for following output to go elsewhere.
241: */
242:
243: tferror(tf)
244: FILE *tf;
245: {
246: if (errno == ENOSPC)
247: {
248: (void) freopen(CurEnv->e_df, "w", tf);
249: fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
250: usrerr("452 Out of disk space for temp file");
251: }
252: else
253: syserr("collect: Cannot write %s", CurEnv->e_df);
254: (void) freopen("/dev/null", "w", tf);
255: }
256: /*
257: ** EATFROM -- chew up a UNIX style from line and process
258: **
259: ** This does indeed make some assumptions about the format
260: ** of UNIX messages.
261: **
262: ** Parameters:
263: ** fm -- the from line.
264: **
265: ** Returns:
266: ** none.
267: **
268: ** Side Effects:
269: ** extracts what information it can from the header,
270: ** such as the date.
271: */
272:
273: # ifndef NOTUNIX
274:
275: char *DowList[] =
276: {
277: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
278: };
279:
280: char *MonthList[] =
281: {
282: "Jan", "Feb", "Mar", "Apr", "May", "Jun",
283: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
284: NULL
285: };
286:
287: eatfrom(fm)
288: char *fm;
289: {
290: register char *p;
291: register char **dt;
292:
293: # ifdef DEBUG
294: if (tTd(30, 2))
295: printf("eatfrom(%s)\n", fm);
296: # endif DEBUG
297:
298: /* find the date part */
299: p = fm;
300: while (*p != '\0')
301: {
302: /* skip a word */
303: while (*p != '\0' && *p != ' ')
304: p++;
305: while (*p == ' ')
306: p++;
307: if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':')
308: continue;
309:
310: /* we have a possible date */
311: for (dt = DowList; *dt != NULL; dt++)
312: if (strncmp(*dt, p, 3) == 0)
313: break;
314: if (*dt == NULL)
315: continue;
316:
317: for (dt = MonthList; *dt != NULL; dt++)
318: if (strncmp(*dt, &p[4], 3) == 0)
319: break;
320: if (*dt != NULL)
321: break;
322: }
323:
324: if (*p != NULL)
325: {
326: char *q;
327: extern char *arpadate();
328:
329: /* we have found a date */
330: q = xalloc(25);
331: (void) strncpy(q, p, 25);
332: q[24] = '\0';
333: define('d', q, CurEnv);
334: q = arpadate(q);
335: define('a', newstr(q), CurEnv);
336: }
337: }
338:
339: # endif NOTUNIX
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.