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