1*4091Seric # include <stdio.h>
2*4091Seric # include <ctype.h>
3*4091Seric # include <errno.h>
4*4091Seric # include "sendmail.h"
5*4091Seric 
6*4091Seric static char	SccsId[] = "@(#)headers.c	3.1	08/09/81";
7*4091Seric 
8*4091Seric /*
9*4091Seric **  CHOMPHEADER -- process and save a header line.
10*4091Seric **
11*4091Seric **	Called by collect and by readcf to deal with header lines.
12*4091Seric **
13*4091Seric **	Parameters:
14*4091Seric **		line -- header as a text line.
15*4091Seric **		def -- if set, this is a default value.
16*4091Seric **
17*4091Seric **	Returns:
18*4091Seric **		flags for this header.
19*4091Seric **
20*4091Seric **	Side Effects:
21*4091Seric **		The header is saved on the header list.
22*4091Seric */
23*4091Seric 
24*4091Seric chompheader(line, def)
25*4091Seric 	char *line;
26*4091Seric 	bool def;
27*4091Seric {
28*4091Seric 	register char *p;
29*4091Seric 	register HDR *h;
30*4091Seric 	HDR **hp;
31*4091Seric 	extern bool isheader();
32*4091Seric 	char *fname;
33*4091Seric 	char *fvalue;
34*4091Seric 	struct hdrinfo *hi;
35*4091Seric 
36*4091Seric 	/* strip off trailing newline */
37*4091Seric 	p = rindex(line, '\n');
38*4091Seric 	if (p != NULL)
39*4091Seric 		*p = '\0';
40*4091Seric 
41*4091Seric 	/* find canonical name */
42*4091Seric 	fname = line;
43*4091Seric 	p = index(line, ':');
44*4091Seric 	fvalue = &p[1];
45*4091Seric 	while (isspace(*--p))
46*4091Seric 		continue;
47*4091Seric 	*++p = '\0';
48*4091Seric 	makelower(fname);
49*4091Seric 
50*4091Seric 	/* strip field value on front */
51*4091Seric 	if (*fvalue == ' ')
52*4091Seric 		fvalue++;
53*4091Seric 
54*4091Seric 	/* search header list for this header */
55*4091Seric 	for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link)
56*4091Seric 	{
57*4091Seric 		if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags))
58*4091Seric 			break;
59*4091Seric 	}
60*4091Seric 
61*4091Seric 	/* see if it is a known type */
62*4091Seric 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
63*4091Seric 	{
64*4091Seric 		if (strcmp(hi->hi_field, fname) == 0)
65*4091Seric 			break;
66*4091Seric 	}
67*4091Seric 
68*4091Seric 	/* if this means "end of header" quit now */
69*4091Seric 	if (bitset(H_EOH, hi->hi_flags))
70*4091Seric 		return (hi->hi_flags);
71*4091Seric 
72*4091Seric 	/* create/fill in a new node */
73*4091Seric 	if (h == NULL)
74*4091Seric 	{
75*4091Seric 		/* create a new node */
76*4091Seric 		*hp = h = (HDR *) xalloc(sizeof *h);
77*4091Seric 		h->h_field = newstr(fname);
78*4091Seric 		h->h_value = NULL;
79*4091Seric 		h->h_link = NULL;
80*4091Seric 		h->h_flags = hi->hi_flags;
81*4091Seric 		h->h_mflags = hi->hi_mflags;
82*4091Seric 	}
83*4091Seric 	if (def)
84*4091Seric 		h->h_flags |= H_DEFAULT;
85*4091Seric 	else
86*4091Seric 		h->h_flags &= ~H_CHECK;
87*4091Seric 	if (h->h_value != NULL)
88*4091Seric 		free(h->h_value);
89*4091Seric 	h->h_value = newstr(fvalue);
90*4091Seric 
91*4091Seric 	return (h->h_flags);
92*4091Seric }
93*4091Seric /*
94*4091Seric **  HVALUE -- return value of a header.
95*4091Seric **
96*4091Seric **	Only "real" fields (i.e., ones that have not been supplied
97*4091Seric **	as a default) are used.
98*4091Seric **
99*4091Seric **	Parameters:
100*4091Seric **		field -- the field name.
101*4091Seric **
102*4091Seric **	Returns:
103*4091Seric **		pointer to the value part.
104*4091Seric **		NULL if not found.
105*4091Seric **
106*4091Seric **	Side Effects:
107*4091Seric **		sets the H_USED bit in the header if found.
108*4091Seric */
109*4091Seric 
110*4091Seric char *
111*4091Seric hvalue(field)
112*4091Seric 	char *field;
113*4091Seric {
114*4091Seric 	register HDR *h;
115*4091Seric 
116*4091Seric 	for (h = Header; h != NULL; h = h->h_link)
117*4091Seric 	{
118*4091Seric 		if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
119*4091Seric 		{
120*4091Seric 			h->h_flags |= H_USED;
121*4091Seric 			return (h->h_value);
122*4091Seric 		}
123*4091Seric 	}
124*4091Seric 	return (NULL);
125*4091Seric }
126*4091Seric /*
127*4091Seric **  ISHEADER -- predicate telling if argument is a header.
128*4091Seric **
129*4091Seric **	Parameters:
130*4091Seric **		s -- string to check for possible headerness.
131*4091Seric **
132*4091Seric **	Returns:
133*4091Seric **		TRUE if s is a header.
134*4091Seric **		FALSE otherwise.
135*4091Seric **
136*4091Seric **	Side Effects:
137*4091Seric **		none.
138*4091Seric */
139*4091Seric 
140*4091Seric bool
141*4091Seric isheader(s)
142*4091Seric 	register char *s;
143*4091Seric {
144*4091Seric 	if (!isalnum(*s))
145*4091Seric 		return (FALSE);
146*4091Seric 	while (!isspace(*s) && *s != ':')
147*4091Seric 		s++;
148*4091Seric 	while (isspace(*s))
149*4091Seric 		s++;
150*4091Seric 	return (*s == ':');
151*4091Seric }
152