1 # include <stdio.h>
2 # include <ctype.h>
3 # include "dlvrmail.h"
4 
5 static char	SccsId[] = "@(#)collect.c	1.3	10/11/80";
6 
7 /*
8 **  MAKETEMP -- read & parse message header & make temp file.
9 **
10 **	Creates a temporary file name and copies the standard
11 **	input to that file.  While it is doing it, it looks for
12 **	"From:" and "Sender:" fields to use as the from-person
13 **	(but only if the -a flag is specified).  It prefers to
14 **	to use the "Sender:" field.
15 **
16 **	MIT seems to like to produce "Sent-By:" fields instead
17 **	of "Sender:" fields.  We used to catch this, but it turns
18 **	out that the "Sent-By:" field doesn't always correspond
19 **	to someone real ("___057", for instance), as required by
20 **	the protocol.  So we limp by.....
21 **
22 **	Parameters:
23 **		none
24 **
25 **	Returns:
26 **		Name of temp file.
27 **
28 **	Side Effects:
29 **		Temp file is created and filled.
30 **
31 **	Called By:
32 **		main
33 **
34 **	Notes:
35 **		This is broken off from main largely so that the
36 **		temp buffer can be deallocated.
37 */
38 
39 char	MsgId[MAXNAME];
40 
41 char *
42 maketemp()
43 {
44 	register FILE *tf;
45 	char buf[MAXFIELD+1];
46 	static char fbuf[sizeof buf];
47 	extern char *prescan();
48 	extern char *matchhdr();
49 	register char *p;
50 	register bool inheader;
51 	bool firstline;
52 	char c;
53 
54 	/*
55 	**  Create the temp file name and create the file.
56 	*/
57 
58 	mktemp(InFileName);
59 	close(creat(InFileName, 0600));
60 	if ((tf = fopen(InFileName, "w")) == NULL)
61 	{
62 		syserr("Cannot create %s", InFileName);
63 		return (NULL);
64 	}
65 
66 	/*
67 	**  Copy stdin to temp file & do message editting.
68 	**	From person gets copied into fbuf.  At the end of
69 	**	this loop, if fbuf[0] == '\0' then there was no
70 	**	recognized from person in the message.  We also
71 	**	save the message id in MsgId.  The
72 	**	flag 'inheader' keeps track of whether we are
73 	**	in the header or in the body of the message.
74 	**	The flag 'firstline' is only true on the first
75 	**	line of a message.
76 	**	To keep certain mailers from getting confused,
77 	**	and to keep the output clean, lines that look
78 	**	like UNIX "From" lines are deleted in the header,
79 	**	and prepended with ">" in the body.
80 	*/
81 
82 	inheader = TRUE;
83 	firstline = TRUE;
84 	fbuf[0] = '\0';
85 	while (fgets(buf, sizeof buf, stdin) != NULL)
86 	{
87 		if (inheader && isalnum(buf[0]))
88 		{
89 			/* get the rest of this field */
90 			while ((c = getc(stdin)) == ' ' || c == '\t')
91 			{
92 				p = &buf[strlen(buf)];
93 				*p++ = c;
94 				if (fgets(p, sizeof buf - (p - buf), stdin) == NULL)
95 					break;
96 			}
97 			ungetc(c, stdin);
98 		}
99 
100 		if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
101 			break;
102 
103 		/* are we still in the header? */
104 		if ((buf[0] == '\n' || buf[0] == '\0') && inheader)
105 		{
106 			inheader = FALSE;
107 			if (MsgId[0] == '\0')
108 			{
109 				makemsgid();
110 				if (UseMsgId)
111 					fprintf(tf, "Message-Id: <%s>\n", MsgId);
112 			}
113 # ifdef DEBUG
114 			if (Debug)
115 				printf("EOH\n");
116 # endif DEBUG
117 		}
118 
119 		/* Hide UNIX-like From lines */
120 		if (buf[0] == 'F' && buf[1] == 'r' && buf[2] == 'o' &&
121 		    buf[3] == 'm' && buf[4] == ' ')
122 		{
123 			if (firstline && !SaveFrom)
124 				continue;
125 			fputs(">", tf);
126 		}
127 
128 		if (inheader && !isspace(buf[0]))
129 		{
130 			/* find out if this is really a header */
131 			for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++)
132 				continue;
133 			while (*p != ':' && isspace(*p))
134 				p++;
135 			if (*p != ':')
136 			{
137 				inheader = FALSE;
138 # ifdef DEBUG
139 				if (Debug)
140 					printf("EOH?\n");
141 # endif DEBUG
142 			}
143 		}
144 
145 		if (inheader)
146 		{
147 			/* find the sender */
148 			p = matchhdr(buf, "sender");
149 			if (p == NULL && fbuf[0] == '\0')
150 				p = matchhdr(buf, "from");
151 			if (p != NULL)
152 				prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0');
153 
154 			/* find the message id */
155 			p = matchhdr(buf, "message-id");
156 			if (p != NULL && MsgId[0] == '\0')
157 				prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0');
158 		}
159 		fputs(buf, tf);
160 		firstline = FALSE;
161 		if (ferror(tf))
162 		{
163 			syserr("Cannot write %s", InFileName);
164 			clearerr(tf);
165 			break;
166 		}
167 	}
168 	fclose(tf);
169 	if (MsgId[0] == '\0')
170 		makemsgid();
171 	if (freopen(InFileName, "r", stdin) == NULL)
172 		syserr("Cannot reopen %s", InFileName);
173 	return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL);
174 }
175 /*
176 **  MAKEMSGID -- Compute a message id for this process.
177 **
178 **	This routine creates a message id for a message if
179 **	it did not have one already.  If the MESSAGEID compile
180 **	flag is set, the messageid will be added to any message
181 **	that does not already have one.  Currently it is more
182 **	of an artifact, but I suggest that if you are hacking,
183 **	you leave it in -- I may want to use it someday if
184 **	duplicate messages turn out to be a problem.
185 **
186 **	Parameters:
187 **		none.
188 **
189 **	Returns:
190 **		none.
191 **
192 **	Side Effects:
193 **		Stores a message-id into MsgId.
194 **
195 **	Called By:
196 **		maketemp
197 */
198 
199 makemsgid()
200 {
201 	auto long t;
202 	extern char *MyLocName;
203 	extern char *ArpaHost;
204 
205 	time(&t);
206 	sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost);
207 }
208