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