1 # include <stdio.h>
2 # include <ctype.h>
3 # include <errno.h>
4 # include "sendmail.h"
5 
6 static char	SccsId[] = "@(#)collect.c	3.13	08/17/81";
7 
8 /*
9 **  COLLECT -- read & parse message header & make temp file.
10 **
11 **	Creates a temporary file name and copies the standard
12 **	input to that file.  While it is doing it, it looks for
13 **	"From:" and "Sender:" fields to use as the from-person
14 **	(but only if the -a flag is specified).  It prefers to
15 **	to use the "Sender:" field.
16 **
17 **	MIT seems to like to produce "Sent-By:" fields instead
18 **	of "Sender:" fields.  We used to catch this, but it turns
19 **	out that the "Sent-By:" field doesn't always correspond
20 **	to someone real ("___057", for instance), as required by
21 **	the protocol.  So we limp by.....
22 **
23 **	Parameters:
24 **		none
25 **
26 **	Returns:
27 **		Name of temp file.
28 **
29 **	Side Effects:
30 **		Temp file is created and filled.
31 **
32 **	Called By:
33 **		main
34 **
35 **	Notes:
36 **		This is broken off from main largely so that the
37 **		temp buffer can be deallocated.
38 */
39 
40 long	MsgSize;		/* size of message in bytes */
41 
42 char *
43 collect()
44 {
45 	register FILE *tf;
46 	char buf[MAXFIELD+1];
47 	register char *p;
48 	char c;
49 	extern bool isheader();
50 	char *xfrom;
51 	extern char *hvalue();
52 	extern char *mktemp();
53 	extern char *capitalize();
54 # ifdef DEBUG
55 	HDR *h;
56 # endif
57 
58 	/*
59 	**  Create the temp file name and create the file.
60 	*/
61 
62 	(void) mktemp(InFileName);
63 	(void) close(creat(InFileName, 0600));
64 	if ((tf = fopen(InFileName, "w")) == NULL)
65 	{
66 		syserr("Cannot create %s", InFileName);
67 		return (NULL);
68 	}
69 
70 	/* try to read a UNIX-style From line */
71 	if (fgets(buf, sizeof buf, stdin) == NULL)
72 		return (NULL);
73 	if (strncmp(buf, "From ", 5) == 0)
74 	{
75 		eatfrom(buf);
76 		(void) fgets(buf, sizeof buf, stdin);
77 	}
78 
79 	/*
80 	**  Copy stdin to temp file & do message editting.
81 	**	To keep certain mailers from getting confused,
82 	**	and to keep the output clean, lines that look
83 	**	like UNIX "From" lines are deleted in the header,
84 	**	and prepended with ">" in the body.
85 	*/
86 
87 	for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin))
88 	{
89 		/* see if the header is over */
90 		if (!isheader(buf))
91 			break;
92 
93 		/* get the rest of this field */
94 		while ((c = getc(stdin)) == ' ' || c == '\t')
95 		{
96 			p = &buf[strlen(buf)];
97 			*p++ = c;
98 			if (fgets(p, sizeof buf - (p - buf), stdin) == NULL)
99 				break;
100 		}
101 		if (!feof(stdin))
102 			(void) ungetc(c, stdin);
103 
104 		MsgSize += strlen(buf);
105 
106 		/*
107 		**  Snarf header away.
108 		*/
109 
110 		if (bitset(H_EOH, chompheader(buf, FALSE)))
111 			break;
112 	}
113 
114 # ifdef DEBUG
115 	if (Debug)
116 		printf("EOH\n");
117 # endif DEBUG
118 
119 	/* throw away a blank line */
120 	if (buf[0] == '\n')
121 		(void) fgets(buf, sizeof buf, stdin);
122 
123 	/*
124 	**  Collect the body of the message.
125 	*/
126 
127 	for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin) != NULL)
128 	{
129 		/* check for end-of-message */
130 		if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
131 			break;
132 
133 		/* Hide UNIX-like From lines */
134 		if (strncmp(buf, "From ", 5) == 0)
135 		{
136 			fputs(">", tf);
137 			MsgSize++;
138 		}
139 		MsgSize += strlen(buf);
140 		fputs(buf, tf);
141 		if (ferror(tf))
142 		{
143 			if (errno == ENOSPC)
144 			{
145 				(void) freopen(InFileName, "w", tf);
146 				fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
147 				syserr("Out of disk space for temp file");
148 			}
149 			else
150 				syserr("Cannot write %s", InFileName);
151 			(void) freopen("/dev/null", "w", tf);
152 		}
153 	}
154 	(void) fclose(tf);
155 
156 	/*
157 	**  Find out some information from the headers.
158 	**	Examples are who is the from person & the date.
159 	*/
160 
161 	/* from person */
162 	xfrom = hvalue("sender");
163 	if (xfrom == NULL)
164 		xfrom = hvalue("from");
165 
166 	/* full name of from person */
167 	p = hvalue("full-name");
168 	if (p != NULL)
169 		define('x', p);
170 
171 	/* date message originated */
172 	p = hvalue("posted-date");
173 	if (p == NULL)
174 		p = hvalue("date");
175 	if (p != NULL)
176 	{
177 		define('a', p);
178 		/* we don't have a good way to do canonical conversion ....
179 		define('d', newstr(arpatounix(p)));
180 		.... so we will ignore the problem for the time being */
181 	}
182 
183 	if (freopen(InFileName, "r", stdin) == NULL)
184 		syserr("Cannot reopen %s", InFileName);
185 
186 # ifdef DEBUG
187 	if (Debug)
188 	{
189 		printf("----- collected header -----\n");
190 		for (h = Header; h != NULL; h = h->h_link)
191 			printf("%s: %s\n", capitalize(h->h_field), h->h_value);
192 		printf("----------------------------\n");
193 	}
194 # endif DEBUG
195 	return (ArpaFmt ? xfrom : NULL);
196 }
197 /*
198 **  EATFROM -- chew up a UNIX style from line and process
199 **
200 **	This does indeed make some assumptions about the format
201 **	of UNIX messages.
202 **
203 **	Parameters:
204 **		fm -- the from line.
205 **
206 **	Returns:
207 **		none.
208 **
209 **	Side Effects:
210 **		extracts what information it can from the header,
211 **		such as the date.
212 */
213 
214 char	*MonthList[] =
215 {
216 	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
217 	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
218 	NULL
219 };
220 
221 eatfrom(fm)
222 	char *fm;
223 {
224 	register char *p;
225 	register char **dt;
226 
227 	/* find the date part */
228 	p = fm;
229 	while (*p != '\0')
230 	{
231 		/* skip a word */
232 		while (*p != '\0' && *p != ' ')
233 			*p++;
234 		while (*p == ' ')
235 			*p++;
236 		if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':')
237 			continue;
238 
239 		/* we have a possible date */
240 		for (dt = MonthList; *dt != NULL; dt++)
241 			if (strncmp(*dt, p, 3) == 0)
242 				break;
243 
244 		if (*dt != NULL)
245 			break;
246 	}
247 
248 	if (*p != NULL)
249 	{
250 		char *q;
251 
252 		/* we have found a date */
253 		q = xalloc(25);
254 		strncpy(q, p, 25);
255 		q[24] = '\0';
256 		define('d', q);
257 	}
258 }
259