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