fixes in setproctitle to avoid problems with titles longer than
[unix-history] / usr / src / usr.sbin / sendmail / src / collect.c
CommitLineData
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 12static 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
40maketemp(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
239tferror(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
271char *DowList[] =
272{
273 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
274};
275
1a12c7d6
EA
276char *MonthList[] =
277{
278 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
279 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
280 NULL
281};
282
283eatfrom(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