14091Seric # include <errno.h>
24091Seric # include "sendmail.h"
34091Seric 
4*4319Seric static char	SccsId[] = "@(#)headers.c	3.6	09/06/81";
54091Seric 
64091Seric /*
74091Seric **  CHOMPHEADER -- process and save a header line.
84091Seric **
94091Seric **	Called by collect and by readcf to deal with header lines.
104091Seric **
114091Seric **	Parameters:
124091Seric **		line -- header as a text line.
134091Seric **		def -- if set, this is a default value.
144091Seric **
154091Seric **	Returns:
164091Seric **		flags for this header.
174091Seric **
184091Seric **	Side Effects:
194091Seric **		The header is saved on the header list.
20*4319Seric **		Contents of 'line' are destroyed.
214091Seric */
224091Seric 
234091Seric chompheader(line, def)
244091Seric 	char *line;
254091Seric 	bool def;
264091Seric {
274091Seric 	register char *p;
284091Seric 	register HDR *h;
294091Seric 	HDR **hp;
304091Seric 	extern bool isheader();
314091Seric 	char *fname;
324091Seric 	char *fvalue;
334091Seric 	struct hdrinfo *hi;
344091Seric 
354091Seric 	/* strip off trailing newline */
364091Seric 	p = rindex(line, '\n');
374091Seric 	if (p != NULL)
384091Seric 		*p = '\0';
394091Seric 
404091Seric 	/* find canonical name */
414091Seric 	fname = line;
424091Seric 	p = index(line, ':');
434091Seric 	fvalue = &p[1];
444091Seric 	while (isspace(*--p))
454091Seric 		continue;
464091Seric 	*++p = '\0';
474091Seric 	makelower(fname);
484091Seric 
494211Seric 	/* hack, hack -- save the old From: address */
504211Seric 	if (!def && strcmp(fname, "from") == 0)
514211Seric 		fname = "original-from";
524211Seric 
534091Seric 	/* strip field value on front */
544091Seric 	if (*fvalue == ' ')
554091Seric 		fvalue++;
564091Seric 
574091Seric 	/* search header list for this header */
584091Seric 	for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link)
594091Seric 	{
604150Seric 		if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) &&
614150Seric 		    !bitset(H_FORCE, h->h_flags))
624091Seric 			break;
634091Seric 	}
644091Seric 
654091Seric 	/* see if it is a known type */
664091Seric 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
674091Seric 	{
684091Seric 		if (strcmp(hi->hi_field, fname) == 0)
694091Seric 			break;
704091Seric 	}
714091Seric 
724091Seric 	/* if this means "end of header" quit now */
734091Seric 	if (bitset(H_EOH, hi->hi_flags))
744091Seric 		return (hi->hi_flags);
754091Seric 
764091Seric 	/* create/fill in a new node */
774091Seric 	if (h == NULL)
784091Seric 	{
794091Seric 		/* create a new node */
804091Seric 		*hp = h = (HDR *) xalloc(sizeof *h);
814091Seric 		h->h_field = newstr(fname);
824091Seric 		h->h_value = NULL;
834091Seric 		h->h_link = NULL;
844091Seric 		h->h_flags = hi->hi_flags;
854091Seric 		h->h_mflags = hi->hi_mflags;
864091Seric 	}
874091Seric 	if (def)
884091Seric 		h->h_flags |= H_DEFAULT;
894091Seric 	else
904091Seric 		h->h_flags &= ~H_CHECK;
914091Seric 	if (h->h_value != NULL)
924091Seric 		free(h->h_value);
934091Seric 	h->h_value = newstr(fvalue);
944224Seric 	if (!def && GrabTo && bitset(H_ADDR, h->h_flags))
954224Seric 		sendto(h->h_value, 0);
964091Seric 
974091Seric 	return (h->h_flags);
984091Seric }
994091Seric /*
1004091Seric **  HVALUE -- return value of a header.
1014091Seric **
1024091Seric **	Only "real" fields (i.e., ones that have not been supplied
1034091Seric **	as a default) are used.
1044091Seric **
1054091Seric **	Parameters:
1064091Seric **		field -- the field name.
1074091Seric **
1084091Seric **	Returns:
1094091Seric **		pointer to the value part.
1104091Seric **		NULL if not found.
1114091Seric **
1124091Seric **	Side Effects:
1134091Seric **		sets the H_USED bit in the header if found.
1144091Seric */
1154091Seric 
1164091Seric char *
1174091Seric hvalue(field)
1184091Seric 	char *field;
1194091Seric {
1204091Seric 	register HDR *h;
1214091Seric 
1224091Seric 	for (h = Header; h != NULL; h = h->h_link)
1234091Seric 	{
1244091Seric 		if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
1254091Seric 		{
1264091Seric 			h->h_flags |= H_USED;
1274091Seric 			return (h->h_value);
1284091Seric 		}
1294091Seric 	}
1304091Seric 	return (NULL);
1314091Seric }
1324091Seric /*
1334091Seric **  ISHEADER -- predicate telling if argument is a header.
1344091Seric **
135*4319Seric **	A line is a header if it has a single word followed by
136*4319Seric **	optional white space followed by a colon.
137*4319Seric **
1384091Seric **	Parameters:
1394091Seric **		s -- string to check for possible headerness.
1404091Seric **
1414091Seric **	Returns:
1424091Seric **		TRUE if s is a header.
1434091Seric **		FALSE otherwise.
1444091Seric **
1454091Seric **	Side Effects:
1464091Seric **		none.
147*4319Seric **
148*4319Seric **	Bugs:
149*4319Seric **		According to RFC733, there should be a newline
150*4319Seric **		permitted after the word but before the colon.
151*4319Seric **		We don't seem to support that.....
1524091Seric */
1534091Seric 
1544091Seric bool
1554091Seric isheader(s)
1564091Seric 	register char *s;
1574091Seric {
1584091Seric 	if (!isalnum(*s))
1594091Seric 		return (FALSE);
1604091Seric 	while (!isspace(*s) && *s != ':')
1614091Seric 		s++;
1624091Seric 	while (isspace(*s))
1634091Seric 		s++;
1644091Seric 	return (*s == ':');
1654091Seric }
166