14091Seric # include <errno.h>
24091Seric # include "sendmail.h"
34091Seric 
4*4211Seric static char	SccsId[] = "@(#)headers.c	3.4	08/22/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.
204091Seric */
214091Seric 
224091Seric chompheader(line, def)
234091Seric 	char *line;
244091Seric 	bool def;
254091Seric {
264091Seric 	register char *p;
274091Seric 	register HDR *h;
284091Seric 	HDR **hp;
294091Seric 	extern bool isheader();
304091Seric 	char *fname;
314091Seric 	char *fvalue;
324091Seric 	struct hdrinfo *hi;
334091Seric 
344091Seric 	/* strip off trailing newline */
354091Seric 	p = rindex(line, '\n');
364091Seric 	if (p != NULL)
374091Seric 		*p = '\0';
384091Seric 
394091Seric 	/* find canonical name */
404091Seric 	fname = line;
414091Seric 	p = index(line, ':');
424091Seric 	fvalue = &p[1];
434091Seric 	while (isspace(*--p))
444091Seric 		continue;
454091Seric 	*++p = '\0';
464091Seric 	makelower(fname);
474091Seric 
48*4211Seric 	/* hack, hack -- save the old From: address */
49*4211Seric 	if (!def && strcmp(fname, "from") == 0)
50*4211Seric 		fname = "original-from";
51*4211Seric 
524091Seric 	/* strip field value on front */
534091Seric 	if (*fvalue == ' ')
544091Seric 		fvalue++;
554091Seric 
564091Seric 	/* search header list for this header */
574091Seric 	for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link)
584091Seric 	{
594150Seric 		if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) &&
604150Seric 		    !bitset(H_FORCE, h->h_flags))
614091Seric 			break;
624091Seric 	}
634091Seric 
644091Seric 	/* see if it is a known type */
654091Seric 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
664091Seric 	{
674091Seric 		if (strcmp(hi->hi_field, fname) == 0)
684091Seric 			break;
694091Seric 	}
704091Seric 
714091Seric 	/* if this means "end of header" quit now */
724091Seric 	if (bitset(H_EOH, hi->hi_flags))
734091Seric 		return (hi->hi_flags);
744091Seric 
754091Seric 	/* create/fill in a new node */
764091Seric 	if (h == NULL)
774091Seric 	{
784091Seric 		/* create a new node */
794091Seric 		*hp = h = (HDR *) xalloc(sizeof *h);
804091Seric 		h->h_field = newstr(fname);
814091Seric 		h->h_value = NULL;
824091Seric 		h->h_link = NULL;
834091Seric 		h->h_flags = hi->hi_flags;
844091Seric 		h->h_mflags = hi->hi_mflags;
854091Seric 	}
864091Seric 	if (def)
874091Seric 		h->h_flags |= H_DEFAULT;
884091Seric 	else
894091Seric 		h->h_flags &= ~H_CHECK;
904091Seric 	if (h->h_value != NULL)
914091Seric 		free(h->h_value);
924091Seric 	h->h_value = newstr(fvalue);
934091Seric 
944091Seric 	return (h->h_flags);
954091Seric }
964091Seric /*
974091Seric **  HVALUE -- return value of a header.
984091Seric **
994091Seric **	Only "real" fields (i.e., ones that have not been supplied
1004091Seric **	as a default) are used.
1014091Seric **
1024091Seric **	Parameters:
1034091Seric **		field -- the field name.
1044091Seric **
1054091Seric **	Returns:
1064091Seric **		pointer to the value part.
1074091Seric **		NULL if not found.
1084091Seric **
1094091Seric **	Side Effects:
1104091Seric **		sets the H_USED bit in the header if found.
1114091Seric */
1124091Seric 
1134091Seric char *
1144091Seric hvalue(field)
1154091Seric 	char *field;
1164091Seric {
1174091Seric 	register HDR *h;
1184091Seric 
1194091Seric 	for (h = Header; h != NULL; h = h->h_link)
1204091Seric 	{
1214091Seric 		if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
1224091Seric 		{
1234091Seric 			h->h_flags |= H_USED;
1244091Seric 			return (h->h_value);
1254091Seric 		}
1264091Seric 	}
1274091Seric 	return (NULL);
1284091Seric }
1294091Seric /*
1304091Seric **  ISHEADER -- predicate telling if argument is a header.
1314091Seric **
1324091Seric **	Parameters:
1334091Seric **		s -- string to check for possible headerness.
1344091Seric **
1354091Seric **	Returns:
1364091Seric **		TRUE if s is a header.
1374091Seric **		FALSE otherwise.
1384091Seric **
1394091Seric **	Side Effects:
1404091Seric **		none.
1414091Seric */
1424091Seric 
1434091Seric bool
1444091Seric isheader(s)
1454091Seric 	register char *s;
1464091Seric {
1474091Seric 	if (!isalnum(*s))
1484091Seric 		return (FALSE);
1494091Seric 	while (!isspace(*s) && *s != ':')
1504091Seric 		s++;
1514091Seric 	while (isspace(*s))
1524091Seric 		s++;
1534091Seric 	return (*s == ':');
1544091Seric }
155