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