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	11/05/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 (buf[0] == 'F' && buf[1] == 'r' && buf[2] == 'o' &&
125 		    buf[3] == 'm' && buf[4] == ' ')
126 		{
127 			if (firstline && !SaveFrom)
128 				continue;
129 			fputs(">", tf);
130 			MsgSize++;
131 		}
132 
133 		if (inheader && !isspace(buf[0]))
134 		{
135 			/* find out if this is really a header */
136 			for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++)
137 				continue;
138 			while (*p != ':' && isspace(*p))
139 				p++;
140 			if (*p != ':')
141 			{
142 				inheader = FALSE;
143 # ifdef DEBUG
144 				if (Debug)
145 					printf("EOH?\n");
146 # endif DEBUG
147 			}
148 		}
149 
150 		if (inheader)
151 		{
152 			/* find the sender */
153 			p = matchhdr(buf, "sender");
154 			if (p == NULL && fbuf[0] == '\0')
155 				p = matchhdr(buf, "from");
156 			if (p != NULL)
157 				prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0');
158 
159 			/* find the message id */
160 			p = matchhdr(buf, "message-id");
161 			if (p != NULL && MsgId[0] == '\0')
162 				prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0');
163 		}
164 		MsgSize += strlen(buf);
165 		fputs(buf, tf);
166 		firstline = FALSE;
167 		if (ferror(tf))
168 		{
169 			if (errno == ENOSPC)
170 			{
171 				freopen(InFileName, "w", tf);
172 				fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
173 				syserr("Out of disk space for temp file");
174 			}
175 			else
176 				syserr("Cannot write %s", InFileName);
177 			freopen("/dev/null", "w", tf);
178 		}
179 	}
180 	fclose(tf);
181 	if (MsgId[0] == '\0')
182 		makemsgid();
183 	if (freopen(InFileName, "r", stdin) == NULL)
184 		syserr("Cannot reopen %s", InFileName);
185 	return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL);
186 }
187 /*
188 **  MAKEMSGID -- Compute a message id for this process.
189 **
190 **	This routine creates a message id for a message if
191 **	it did not have one already.  If the MESSAGEID compile
192 **	flag is set, the messageid will be added to any message
193 **	that does not already have one.  Currently it is more
194 **	of an artifact, but I suggest that if you are hacking,
195 **	you leave it in -- I may want to use it someday if
196 **	duplicate messages turn out to be a problem.
197 **
198 **	Parameters:
199 **		none.
200 **
201 **	Returns:
202 **		none.
203 **
204 **	Side Effects:
205 **		Stores a message-id into MsgId.
206 **
207 **	Called By:
208 **		maketemp
209 */
210 
211 makemsgid()
212 {
213 	auto long t;
214 	extern char *MyLocName;
215 	extern char *ArpaHost;
216 
217 	time(&t);
218 	sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost);
219 }
220