1 # include <stdio.h>
2 # include <ctype.h>
3 # include <errno.h>
4 # include "dlvrmail.h"
5 
6 static char	SccsId[] = "@(#)collect.c	2.1.1.1	11/20/80";
7 
8 /*
9 **  MAKETEMP -- 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 char	MsgId[MAXNAME];		/* message-id, determined or created */
41 long	MsgSize;		/* size of message in bytes */
42 
43 char *
44 maketemp()
45 {
46 	register FILE *tf;
47 	char buf[MAXFIELD+1];
48 	static char fbuf[sizeof buf];
49 	extern char *prescan();
50 	extern char *matchhdr();
51 	register char *p;
52 	register bool inheader;
53 	bool firstline;
54 	char c;
55 	extern int errno;
56 
57 	/*
58 	**  Create the temp file name and create the file.
59 	*/
60 
61 	mktemp(InFileName);
62 	close(creat(InFileName, 0600));
63 	if ((tf = fopen(InFileName, "w")) == NULL)
64 	{
65 		syserr("Cannot create %s", InFileName);
66 		return (NULL);
67 	}
68 
69 	/*
70 	**  Copy stdin to temp file & do message editting.
71 	**	From person gets copied into fbuf.  At the end of
72 	**	this loop, if fbuf[0] == '\0' then there was no
73 	**	recognized from person in the message.  We also
74 	**	save the message id in MsgId.  The
75 	**	flag 'inheader' keeps track of whether we are
76 	**	in the header or in the body of the message.
77 	**	The flag 'firstline' is only true on the first
78 	**	line of a message.
79 	**	To keep certain mailers from getting confused,
80 	**	and to keep the output clean, lines that look
81 	**	like UNIX "From" lines are deleted in the header,
82 	**	and prepended with ">" in the body.
83 	*/
84 
85 	inheader = TRUE;
86 	firstline = TRUE;
87 	fbuf[0] = '\0';
88 	while (fgets(buf, sizeof buf, stdin) != NULL)
89 	{
90 		if (inheader && isalnum(buf[0]))
91 		{
92 			/* get the rest of this field */
93 			while ((c = getc(stdin)) == ' ' || c == '\t')
94 			{
95 				p = &buf[strlen(buf)];
96 				*p++ = c;
97 				if (fgets(p, sizeof buf - (p - buf), stdin) == NULL)
98 					break;
99 			}
100 			if (c != EOF)
101 				ungetc(c, stdin);
102 		}
103 
104 		if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
105 			break;
106 
107 		/* are we still in the header? */
108 		if ((buf[0] == '\n' || buf[0] == '\0') && inheader)
109 		{
110 			inheader = FALSE;
111 			if (MsgId[0] == '\0')
112 			{
113 				makemsgid();
114 				if (UseMsgId)
115 					fprintf(tf, "Message-Id: <%s>\n", MsgId);
116 			}
117 # ifdef DEBUG
118 			if (Debug)
119 				printf("EOH\n");
120 # endif DEBUG
121 		}
122 
123 		/* Hide UNIX-like From lines */
124 		if (strncmp(buf, "From ", 5) == 0)
125 		{
126 			if (firstline && !SaveFrom)
127 			{
128 				savedate(buf);
129 				continue;
130 			}
131 			fputs(">", tf);
132 			MsgSize++;
133 		}
134 
135 		if (inheader && !isspace(buf[0]))
136 		{
137 			/* find out if this is really a header */
138 			for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++)
139 				continue;
140 			while (*p != ':' && isspace(*p))
141 				p++;
142 			if (*p != ':')
143 			{
144 				inheader = FALSE;
145 # ifdef DEBUG
146 				if (Debug)
147 					printf("EOH?\n");
148 # endif DEBUG
149 			}
150 		}
151 
152 		if (inheader)
153 		{
154 			/* find the sender */
155 			p = matchhdr(buf, "sender");
156 			if (p == NULL && fbuf[0] == '\0')
157 				p = matchhdr(buf, "from");
158 			if (p != NULL)
159 				prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0');
160 
161 			/* find the message id */
162 			p = matchhdr(buf, "message-id");
163 			if (p != NULL && MsgId[0] == '\0')
164 				prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0');
165 		}
166 		MsgSize += strlen(buf);
167 		fputs(buf, tf);
168 		firstline = FALSE;
169 		if (ferror(tf))
170 		{
171 			if (errno == ENOSPC)
172 			{
173 				freopen(InFileName, "w", tf);
174 				fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
175 				syserr("Out of disk space for temp file");
176 			}
177 			else
178 				syserr("Cannot write %s", InFileName);
179 			freopen("/dev/null", "w", tf);
180 		}
181 	}
182 	fclose(tf);
183 	if (MsgId[0] == '\0')
184 		makemsgid();
185 	if (freopen(InFileName, "r", stdin) == NULL)
186 		syserr("Cannot reopen %s", InFileName);
187 	return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL);
188 }
189 /*
190 **  MAKEMSGID -- Compute a message id for this process.
191 **
192 **	This routine creates a message id for a message if
193 **	it did not have one already.  If the MESSAGEID compile
194 **	flag is set, the messageid will be added to any message
195 **	that does not already have one.  Currently it is more
196 **	of an artifact, but I suggest that if you are hacking,
197 **	you leave it in -- I may want to use it someday if
198 **	duplicate messages turn out to be a problem.
199 **
200 **	Parameters:
201 **		none.
202 **
203 **	Returns:
204 **		none.
205 **
206 **	Side Effects:
207 **		Stores a message-id into MsgId.
208 **
209 **	Called By:
210 **		maketemp
211 */
212 
213 makemsgid()
214 {
215 	auto long t;
216 	extern char *MyLocName;
217 	extern char *ArpaHost;
218 
219 	time(&t);
220 	sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost);
221 }
222 /*
223 **  SAVEDATE -- find and save date field from a "From" line
224 **
225 **	This will be used by putheader when a From line is created.
226 **
227 **	Parameters:
228 **		buf -- a "From" line.
229 **
230 **	Returns:
231 **		none.
232 **
233 **	Side Effects:
234 **		Saves the "date" part (with newline) in SentDate.
235 */
236 
237 char	SentDate[30];
238 
239 savedate(buf)
240 	char *buf;
241 {
242 	register char *p;
243 
244 	for (p = buf; p != '\0'; p++)
245 	{
246 		if (*p != ' ')
247 			continue;
248 		if (strncmp(p, " Sun ", 5) == 0 ||
249 		    strncmp(p, " Mon ", 5) == 0 ||
250 		    strncmp(p, " Tue ", 5) == 0 ||
251 		    strncmp(p, " Wed ", 5) == 0 ||
252 		    strncmp(p, " Thu ", 5) == 0 ||
253 		    strncmp(p, " Fri ", 5) == 0 ||
254 		    strncmp(p, " Sat ", 5) == 0)
255 		{
256 			if (p[4] != ' ' || p[8] != ' ' || p[11] != ' ' ||
257 			    p[14] != ':' || p[17] != ':' || p[20] != ' ')
258 				continue;
259 			strncpy(SentDate, ++p, 25);
260 			SentDate[24] = '\n';
261 			SentDate[25] = '\0';
262 			return;
263 		}
264 	}
265 }
266