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