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