11392Seric # include <stdio.h>
21392Seric # include <ctype.h>
31439Seric # include <errno.h>
41392Seric # include "dlvrmail.h"
51392Seric 
6*1819Seric static char	SccsId[] = "@(#)collect.c	2.1.1.1	11/20/80";
71392Seric 
81392Seric /*
91392Seric **  MAKETEMP -- read & parse message header & make temp file.
101392Seric **
111392Seric **	Creates a temporary file name and copies the standard
121392Seric **	input to that file.  While it is doing it, it looks for
131392Seric **	"From:" and "Sender:" fields to use as the from-person
141392Seric **	(but only if the -a flag is specified).  It prefers to
151392Seric **	to use the "Sender:" field.
161392Seric **
171392Seric **	MIT seems to like to produce "Sent-By:" fields instead
181392Seric **	of "Sender:" fields.  We used to catch this, but it turns
191392Seric **	out that the "Sent-By:" field doesn't always correspond
201392Seric **	to someone real ("___057", for instance), as required by
211392Seric **	the protocol.  So we limp by.....
221392Seric **
231392Seric **	Parameters:
241392Seric **		none
251392Seric **
261392Seric **	Returns:
271392Seric **		Name of temp file.
281392Seric **
291392Seric **	Side Effects:
301392Seric **		Temp file is created and filled.
311392Seric **
321392Seric **	Called By:
331392Seric **		main
341392Seric **
351392Seric **	Notes:
361392Seric **		This is broken off from main largely so that the
371392Seric **		temp buffer can be deallocated.
381392Seric */
391392Seric 
401624Seric char	MsgId[MAXNAME];		/* message-id, determined or created */
411624Seric long	MsgSize;		/* size of message in bytes */
421397Seric 
431392Seric char *
441392Seric maketemp()
451392Seric {
461392Seric 	register FILE *tf;
471392Seric 	char buf[MAXFIELD+1];
481392Seric 	static char fbuf[sizeof buf];
491392Seric 	extern char *prescan();
501392Seric 	extern char *matchhdr();
511392Seric 	register char *p;
521392Seric 	register bool inheader;
531392Seric 	bool firstline;
541392Seric 	char c;
551439Seric 	extern int errno;
561392Seric 
571392Seric 	/*
581392Seric 	**  Create the temp file name and create the file.
591392Seric 	*/
601392Seric 
611392Seric 	mktemp(InFileName);
621392Seric 	close(creat(InFileName, 0600));
631392Seric 	if ((tf = fopen(InFileName, "w")) == NULL)
641392Seric 	{
651392Seric 		syserr("Cannot create %s", InFileName);
661392Seric 		return (NULL);
671392Seric 	}
681392Seric 
691392Seric 	/*
701392Seric 	**  Copy stdin to temp file & do message editting.
711392Seric 	**	From person gets copied into fbuf.  At the end of
721392Seric 	**	this loop, if fbuf[0] == '\0' then there was no
731392Seric 	**	recognized from person in the message.  We also
741392Seric 	**	save the message id in MsgId.  The
751392Seric 	**	flag 'inheader' keeps track of whether we are
761392Seric 	**	in the header or in the body of the message.
771392Seric 	**	The flag 'firstline' is only true on the first
781392Seric 	**	line of a message.
791392Seric 	**	To keep certain mailers from getting confused,
801392Seric 	**	and to keep the output clean, lines that look
811392Seric 	**	like UNIX "From" lines are deleted in the header,
821392Seric 	**	and prepended with ">" in the body.
831392Seric 	*/
841392Seric 
851392Seric 	inheader = TRUE;
861392Seric 	firstline = TRUE;
871392Seric 	fbuf[0] = '\0';
881392Seric 	while (fgets(buf, sizeof buf, stdin) != NULL)
891392Seric 	{
901392Seric 		if (inheader && isalnum(buf[0]))
911392Seric 		{
921392Seric 			/* get the rest of this field */
931392Seric 			while ((c = getc(stdin)) == ' ' || c == '\t')
941392Seric 			{
951392Seric 				p = &buf[strlen(buf)];
961392Seric 				*p++ = c;
971392Seric 				if (fgets(p, sizeof buf - (p - buf), stdin) == NULL)
981392Seric 					break;
991392Seric 			}
1001587Seric 			if (c != EOF)
1011587Seric 				ungetc(c, stdin);
1021392Seric 		}
1031392Seric 
1041392Seric 		if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
1051392Seric 			break;
1061392Seric 
1071392Seric 		/* are we still in the header? */
1081392Seric 		if ((buf[0] == '\n' || buf[0] == '\0') && inheader)
1091392Seric 		{
1101392Seric 			inheader = FALSE;
1111392Seric 			if (MsgId[0] == '\0')
1121392Seric 			{
1131392Seric 				makemsgid();
1141392Seric 				if (UseMsgId)
1151392Seric 					fprintf(tf, "Message-Id: <%s>\n", MsgId);
1161392Seric 			}
1171392Seric # ifdef DEBUG
1181392Seric 			if (Debug)
1191392Seric 				printf("EOH\n");
1201392Seric # endif DEBUG
1211392Seric 		}
1221392Seric 
1231392Seric 		/* Hide UNIX-like From lines */
124*1819Seric 		if (strncmp(buf, "From ", 5) == 0)
1251392Seric 		{
1261392Seric 			if (firstline && !SaveFrom)
127*1819Seric 			{
128*1819Seric 				savedate(buf);
1291392Seric 				continue;
130*1819Seric 			}
1311392Seric 			fputs(">", tf);
1321624Seric 			MsgSize++;
1331392Seric 		}
1341392Seric 
1351392Seric 		if (inheader && !isspace(buf[0]))
1361392Seric 		{
1371392Seric 			/* find out if this is really a header */
1381392Seric 			for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++)
1391392Seric 				continue;
1401392Seric 			while (*p != ':' && isspace(*p))
1411392Seric 				p++;
1421392Seric 			if (*p != ':')
1431392Seric 			{
1441392Seric 				inheader = FALSE;
1451392Seric # ifdef DEBUG
1461392Seric 				if (Debug)
1471392Seric 					printf("EOH?\n");
1481392Seric # endif DEBUG
1491392Seric 			}
1501392Seric 		}
1511392Seric 
1521392Seric 		if (inheader)
1531392Seric 		{
1541392Seric 			/* find the sender */
1551392Seric 			p = matchhdr(buf, "sender");
1561392Seric 			if (p == NULL && fbuf[0] == '\0')
1571392Seric 				p = matchhdr(buf, "from");
1581392Seric 			if (p != NULL)
1591392Seric 				prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0');
1601392Seric 
1611392Seric 			/* find the message id */
1621392Seric 			p = matchhdr(buf, "message-id");
1631392Seric 			if (p != NULL && MsgId[0] == '\0')
1641392Seric 				prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0');
1651392Seric 		}
1661624Seric 		MsgSize += strlen(buf);
1671392Seric 		fputs(buf, tf);
1681392Seric 		firstline = FALSE;
1691392Seric 		if (ferror(tf))
1701392Seric 		{
1711439Seric 			if (errno == ENOSPC)
1721439Seric 			{
1731439Seric 				freopen(InFileName, "w", tf);
1741439Seric 				fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
1751439Seric 				syserr("Out of disk space for temp file");
1761439Seric 			}
1771439Seric 			else
1781439Seric 				syserr("Cannot write %s", InFileName);
1791439Seric 			freopen("/dev/null", "w", tf);
1801392Seric 		}
1811392Seric 	}
1821392Seric 	fclose(tf);
1831392Seric 	if (MsgId[0] == '\0')
1841392Seric 		makemsgid();
1851392Seric 	if (freopen(InFileName, "r", stdin) == NULL)
1861392Seric 		syserr("Cannot reopen %s", InFileName);
1871392Seric 	return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL);
1881392Seric }
1891392Seric /*
1901392Seric **  MAKEMSGID -- Compute a message id for this process.
1911392Seric **
1921392Seric **	This routine creates a message id for a message if
1931392Seric **	it did not have one already.  If the MESSAGEID compile
1941392Seric **	flag is set, the messageid will be added to any message
1951392Seric **	that does not already have one.  Currently it is more
1961392Seric **	of an artifact, but I suggest that if you are hacking,
1971392Seric **	you leave it in -- I may want to use it someday if
1981392Seric **	duplicate messages turn out to be a problem.
1991392Seric **
2001392Seric **	Parameters:
2011392Seric **		none.
2021392Seric **
2031392Seric **	Returns:
2041392Seric **		none.
2051392Seric **
2061392Seric **	Side Effects:
2071392Seric **		Stores a message-id into MsgId.
2081392Seric **
2091392Seric **	Called By:
2101392Seric **		maketemp
2111392Seric */
2121392Seric 
2131392Seric makemsgid()
2141392Seric {
2151392Seric 	auto long t;
2161392Seric 	extern char *MyLocName;
2171392Seric 	extern char *ArpaHost;
2181392Seric 
2191392Seric 	time(&t);
2201392Seric 	sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost);
2211392Seric }
222*1819Seric /*
223*1819Seric **  SAVEDATE -- find and save date field from a "From" line
224*1819Seric **
225*1819Seric **	This will be used by putheader when a From line is created.
226*1819Seric **
227*1819Seric **	Parameters:
228*1819Seric **		buf -- a "From" line.
229*1819Seric **
230*1819Seric **	Returns:
231*1819Seric **		none.
232*1819Seric **
233*1819Seric **	Side Effects:
234*1819Seric **		Saves the "date" part (with newline) in SentDate.
235*1819Seric */
236*1819Seric 
237*1819Seric char	SentDate[30];
238*1819Seric 
239*1819Seric savedate(buf)
240*1819Seric 	char *buf;
241*1819Seric {
242*1819Seric 	register char *p;
243*1819Seric 
244*1819Seric 	for (p = buf; p != '\0'; p++)
245*1819Seric 	{
246*1819Seric 		if (*p != ' ')
247*1819Seric 			continue;
248*1819Seric 		if (strncmp(p, " Sun ", 5) == 0 ||
249*1819Seric 		    strncmp(p, " Mon ", 5) == 0 ||
250*1819Seric 		    strncmp(p, " Tue ", 5) == 0 ||
251*1819Seric 		    strncmp(p, " Wed ", 5) == 0 ||
252*1819Seric 		    strncmp(p, " Thu ", 5) == 0 ||
253*1819Seric 		    strncmp(p, " Fri ", 5) == 0 ||
254*1819Seric 		    strncmp(p, " Sat ", 5) == 0)
255*1819Seric 		{
256*1819Seric 			if (p[4] != ' ' || p[8] != ' ' || p[11] != ' ' ||
257*1819Seric 			    p[14] != ':' || p[17] != ':' || p[20] != ' ')
258*1819Seric 				continue;
259*1819Seric 			strncpy(SentDate, ++p, 25);
260*1819Seric 			SentDate[24] = '\n';
261*1819Seric 			SentDate[25] = '\0';
262*1819Seric 			return;
263*1819Seric 		}
264*1819Seric 	}
265*1819Seric }
266