14091Seric # include <errno.h>
24091Seric # include "sendmail.h"
34091Seric 
4*4372Seric static char	SccsId[] = "@(#)headers.c	3.7	09/12/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.
204319Seric **		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 
494091Seric 	/* strip field value on front */
504091Seric 	if (*fvalue == ' ')
514091Seric 		fvalue++;
524091Seric 
53*4372Seric 	/* hack, hack -- save From: line specially */
54*4372Seric 	if (!def && strcmp(fname, "from") == 0)
55*4372Seric 	{
56*4372Seric 		OrigFrom = newstr(fvalue);
57*4372Seric 		return (0);
58*4372Seric 	}
59*4372Seric 
604091Seric 	/* search header list for this header */
614091Seric 	for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link)
624091Seric 	{
634150Seric 		if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) &&
644150Seric 		    !bitset(H_FORCE, h->h_flags))
654091Seric 			break;
664091Seric 	}
674091Seric 
684091Seric 	/* see if it is a known type */
694091Seric 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
704091Seric 	{
714091Seric 		if (strcmp(hi->hi_field, fname) == 0)
724091Seric 			break;
734091Seric 	}
744091Seric 
754091Seric 	/* if this means "end of header" quit now */
764091Seric 	if (bitset(H_EOH, hi->hi_flags))
774091Seric 		return (hi->hi_flags);
784091Seric 
794091Seric 	/* create/fill in a new node */
804091Seric 	if (h == NULL)
814091Seric 	{
824091Seric 		/* create a new node */
834091Seric 		*hp = h = (HDR *) xalloc(sizeof *h);
844091Seric 		h->h_field = newstr(fname);
854091Seric 		h->h_value = NULL;
864091Seric 		h->h_link = NULL;
874091Seric 		h->h_flags = hi->hi_flags;
884091Seric 		h->h_mflags = hi->hi_mflags;
894091Seric 	}
904091Seric 	if (def)
914091Seric 		h->h_flags |= H_DEFAULT;
924091Seric 	else
934091Seric 		h->h_flags &= ~H_CHECK;
944091Seric 	if (h->h_value != NULL)
954091Seric 		free(h->h_value);
964091Seric 	h->h_value = newstr(fvalue);
974224Seric 	if (!def && GrabTo && bitset(H_ADDR, h->h_flags))
984224Seric 		sendto(h->h_value, 0);
994091Seric 
1004091Seric 	return (h->h_flags);
1014091Seric }
1024091Seric /*
1034091Seric **  HVALUE -- return value of a header.
1044091Seric **
1054091Seric **	Only "real" fields (i.e., ones that have not been supplied
1064091Seric **	as a default) are used.
1074091Seric **
1084091Seric **	Parameters:
1094091Seric **		field -- the field name.
1104091Seric **
1114091Seric **	Returns:
1124091Seric **		pointer to the value part.
1134091Seric **		NULL if not found.
1144091Seric **
1154091Seric **	Side Effects:
1164091Seric **		sets the H_USED bit in the header if found.
1174091Seric */
1184091Seric 
1194091Seric char *
1204091Seric hvalue(field)
1214091Seric 	char *field;
1224091Seric {
1234091Seric 	register HDR *h;
1244091Seric 
1254091Seric 	for (h = Header; h != NULL; h = h->h_link)
1264091Seric 	{
1274091Seric 		if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
1284091Seric 		{
1294091Seric 			h->h_flags |= H_USED;
1304091Seric 			return (h->h_value);
1314091Seric 		}
1324091Seric 	}
1334091Seric 	return (NULL);
1344091Seric }
1354091Seric /*
1364091Seric **  ISHEADER -- predicate telling if argument is a header.
1374091Seric **
1384319Seric **	A line is a header if it has a single word followed by
1394319Seric **	optional white space followed by a colon.
1404319Seric **
1414091Seric **	Parameters:
1424091Seric **		s -- string to check for possible headerness.
1434091Seric **
1444091Seric **	Returns:
1454091Seric **		TRUE if s is a header.
1464091Seric **		FALSE otherwise.
1474091Seric **
1484091Seric **	Side Effects:
1494091Seric **		none.
1504319Seric **
1514319Seric **	Bugs:
1524319Seric **		According to RFC733, there should be a newline
1534319Seric **		permitted after the word but before the colon.
1544319Seric **		We don't seem to support that.....
1554091Seric */
1564091Seric 
1574091Seric bool
1584091Seric isheader(s)
1594091Seric 	register char *s;
1604091Seric {
1614091Seric 	if (!isalnum(*s))
1624091Seric 		return (FALSE);
1634091Seric 	while (!isspace(*s) && *s != ':')
1644091Seric 		s++;
1654091Seric 	while (isspace(*s))
1664091Seric 		s++;
1674091Seric 	return (*s == ':');
1684091Seric }
169