fname, rs, l, MAXNAME);
fname, rs, l, MAXNAME - 1);
chompheader(line, pflag, hdrp, e)	char *line;	int pflag;	HDR **hdrp;	register ENVELOPE *e;{	u_char mid = '\0';	register char *p;	register HDR *h;	HDR **hp;	char *fname;	char *fvalue;	bool cond = FALSE;	bool dropfrom;	bool headeronly;	STAB *s;	struct hdrinfo *hi;	bool nullheader = FALSE;	BITMAP256 mopts;	if (tTd(31, 6))	{		dprintf("chompheader: ");		xputs(line);		dprintf("\n");	}	headeronly = hdrp != NULL;	if (!headeronly)		hdrp = &e->e_header;	/* strip off options */	clrbitmap(mopts);	p = line;	if (!bitset(pflag, CHHDR_USER) && *p == '?')	{		int c;		register char *q;		q = strchr(++p, '?');		if (q == NULL)			goto hse;		*q = '\0';		c = *p & 0377;		/* possibly macro conditional */		if (c == MACROEXPAND)		{			/* catch ?$? */			if (*++p == '\0')			{				*q = '?';				goto hse;			}			mid = (u_char) *p++;			/* catch ?$abc? */			if (*p != '\0')			{				*q = '?';				goto hse;			}		}		else if (*p == '$')		{			/* catch ?$? */			if (*++p == '\0')			{				*q = '?';				goto hse;			}			mid = (u_char)macid(p, NULL);			if (bitset(0200, mid))				p += strlen(macname(mid)) + 2;			else				p++;			/* catch ?$abc? */			if (*p != '\0')			{				*q = '?';				goto hse;			}		}		else		{			while (*p != '\0')			{				if (!isascii(*p))				{					*q = '?';					goto hse;				}				setbitn(bitidx(*p), mopts);				cond = TRUE;				p++;			}		}		p = q + 1;	}	/* find canonical name */	fname = p;	while (isascii(*p) && isgraph(*p) && *p != ':')		p++;	fvalue = p;	while (isascii(*p) && isspace(*p))		p++;	if (*p++ != ':' || fname == fvalue)	{hse:		syserr("553 5.3.0 header syntax error, line \"%s\"", line);		return 0;	}	*fvalue = '\0';	/* strip field value on front */	if (*p == ' ')		p++;	fvalue = p;	/* if the field is null, go ahead and use the default */	while (isascii(*p) && isspace(*p))		p++;	if (*p == '\0')		nullheader = TRUE;	/* security scan: long field names are end-of-header */	if (strlen(fname) > 100)		return H_EOH;	/* check to see if it represents a ruleset call */	if (bitset(pflag, CHHDR_DEF))	{		char hbuf[50];		(void) expand(fvalue, hbuf, sizeof hbuf, e);		for (p = hbuf; isascii(*p) && isspace(*p); )			p++;		if ((*p++ & 0377) == CALLSUBR)		{			auto char *endp;			bool strc;			strc = *p == '+';	/* strip comments? */			if (strc)				++p;			if (strtorwset(p, &endp, ST_ENTER) > 0)			{				*endp = '\0';				s = stab(fname, ST_HEADER, ST_ENTER);				s->s_header.hi_ruleset = newstr(p);				if (!strc)					s->s_header.hi_flags |= H_STRIPCOMM;			}			return 0;		}	}	/* see if it is a known type */	s = stab(fname, ST_HEADER, ST_FIND);	if (s != NULL)		hi = &s->s_header;	else		hi = &NormalHeader;	if (tTd(31, 9))	{		if (s == NULL)			dprintf("no header flags match\n");		else			dprintf("header match, flags=%lx, ruleset=%s\n",				hi->hi_flags,				hi->hi_ruleset == NULL ? "<NULL>" : hi->hi_ruleset);	}	/* see if this is a resent message */	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&	    bitset(H_RESENT, hi->hi_flags))		e->e_flags |= EF_RESENT;	/* if this is an Errors-To: header keep track of it now */	if (UseErrorsTo && !bitset(pflag, CHHDR_DEF) && !headeronly &&	    bitset(H_ERRORSTO, hi->hi_flags))		(void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);	/* if this means "end of header" quit now */	if (!headeronly && bitset(H_EOH, hi->hi_flags))		return hi->hi_flags;	/*	**  Horrible hack to work around problem with Lotus Notes SMTP	**  mail gateway, which generates From: headers with newlines in	**  them and the <address> on the second line.  Although this is	**  legal RFC 822, many MUAs don't handle this properly and thus	**  never find the actual address.	*/	if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader)	{		while ((p = strchr(fvalue, '\n')) != NULL)			*p = ' ';	}	/*	**  If there is a check ruleset, verify it against the header.	*/	if (bitset(pflag, CHHDR_CHECK))	{		bool stripcom = FALSE;		char *rs;		/* no ruleset? look for default */		rs = hi->hi_ruleset;		if (rs == NULL)		{			s = stab("*", ST_HEADER, ST_FIND);			if (s != NULL)			{				rs = (&s->s_header)->hi_ruleset;				stripcom = bitset((&s->s_header)->hi_flags,						  H_STRIPCOMM);			}		}		else			stripcom = bitset(hi->hi_flags, H_STRIPCOMM);		if (rs != NULL)		{			int l;			char qval[MAXNAME];			char hlen[16];			char *sp, *dp;			dp = qval;			l = 0;			dp[l++] = '"';			for (sp = fvalue; *sp != '\0' && l < MAXNAME - 2; sp++)			{				switch(*sp)				{				  case '\011': /* ht */				  case '\012': /* nl */				  case '\013': /* vt */				  case '\014': /* np */				  case '\015': /* cr */					dp[l++] = ' ';					break;				  case '"':					dp[l++] = '\\';					/* FALLTHROUGH */				  default:					dp[l++] = *sp;					break;				}			}			dp[l++] = '"';			dp[l++] = '\0';			l = strlen(fvalue);			snprintf(hlen, sizeof hlen, "%d", l);			define(macid("{hdrlen}", NULL), newstr(hlen), e);			if (l >= MAXNAME)			{				if (LogLevel > 9)					sm_syslog(LOG_WARNING, e->e_id,						  "Warning: truncated header '%s' before check with '%s' len=%d max=%d",						  fname, rs, l, MAXNAME);			}			if ((sp = macvalue(macid("{currHeader}", NULL), e)) !=			    NULL)				free(sp);			define(macid("{currHeader}", NULL), newstr(qval), e);			define(macid("{hdr_name}", NULL), newstr(fname), e);			(void) rscheck(rs, fvalue, NULL, e, stripcom, TRUE, 4,				       NULL);		}	}	/*	**  Drop explicit From: if same as what we would generate.	**  This is to make MH (which doesn't always give a full name)	**  insert the full name information in all circumstances.	*/	dropfrom = FALSE;	p = "resent-from";	if (!bitset(EF_RESENT, e->e_flags))		p += 7;	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&	    !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0)	{		if (tTd(31, 2))		{			dprintf("comparing header from (%s) against default (%s or %s)\n",				fvalue, e->e_from.q_paddr, e->e_from.q_user);		}		if (e->e_from.q_paddr != NULL &&		    e->e_from.q_mailer != NULL &&		    bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) &&		    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||		     strcmp(fvalue, e->e_from.q_user) == 0))			dropfrom = TRUE;	}	/* delete default value for this header */	for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)	{		if (strcasecmp(fname, h->h_field) == 0 &&		    !bitset(H_USER, h->h_flags) &&		    !bitset(H_FORCE, h->h_flags))		{			if (nullheader)			{				/* user-supplied value was null */				return 0;			}			if (dropfrom)			{				/* make this look like the user entered it */				h->h_flags |= H_USER;				return hi->hi_flags;			}			h->h_value = NULL;			if (!cond)			{				/* copy conditions from default case */				memmove((char *)mopts, (char *)h->h_mflags,					sizeof mopts);			}			h->h_macro = mid;		}	}	/* create a new node */	h = (HDR *) xalloc(sizeof *h);	h->h_field = newstr(fname);	h->h_value = newstr(fvalue);	h->h_link = NULL;	memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts);	h->h_macro = mid;	*hp = h;	h->h_flags = hi->hi_flags;	if (bitset(pflag, CHHDR_USER) || bitset(pflag, CHHDR_QUEUE))		h->h_flags |= H_USER;	/* strip EOH flag if parsing MIME headers */	if (headeronly)		h->h_flags &= ~H_EOH;	if (bitset(pflag, CHHDR_DEF))		h->h_flags |= H_DEFAULT;	if (cond || mid != '\0')		h->h_flags |= H_CHECK;	/* hack to see if this is a new format message */	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&	    bitset(H_RCPT|H_FROM, h->h_flags) &&	    (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||	     strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))	{		e->e_flags &= ~EF_OLDSTYLE;	}	return h->h_flags;}