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