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