xref: /freebsd/contrib/sendmail/src/headers.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /*
2  * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
3  *	All rights reserved.
4  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5  * Copyright (c) 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * By using this file, you agree to the terms and conditions set
9  * forth in the LICENSE file which can be found at the top level of
10  * the sendmail distribution.
11  *
12  */
13 
14 #ifndef lint
15 static char id[] = "@(#)$Id: headers.c,v 8.203.4.13 2001/05/03 17:24:06 gshapiro Exp $";
16 #endif /* ! lint */
17 
18 /* $FreeBSD$ */
19 
20 #include <sendmail.h>
21 
22 static size_t	fix_mime_header __P((char *));
23 static int	priencode __P((char *));
24 static void	put_vanilla_header __P((HDR *, char *, MCI *));
25 
26 /*
27 **  SETUPHEADERS -- initialize headers in symbol table
28 **
29 **	Parameters:
30 **		none
31 **
32 **	Returns:
33 **		none
34 */
35 
36 void
37 setupheaders()
38 {
39 	struct hdrinfo *hi;
40 	STAB *s;
41 
42 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
43 	{
44 		s = stab(hi->hi_field, ST_HEADER, ST_ENTER);
45 		s->s_header.hi_flags = hi->hi_flags;
46 		s->s_header.hi_ruleset = NULL;
47 	}
48 }
49 /*
50 **  CHOMPHEADER -- process and save a header line.
51 **
52 **	Called by collect, readcf, and readqf to deal with header lines.
53 **
54 **	Parameters:
55 **		line -- header as a text line.
56 **		pflag -- flags for chompheader() (from sendmail.h)
57 **		hdrp -- a pointer to the place to save the header.
58 **		e -- the envelope including this header.
59 **
60 **	Returns:
61 **		flags for this header.
62 **
63 **	Side Effects:
64 **		The header is saved on the header list.
65 **		Contents of 'line' are destroyed.
66 */
67 
68 static struct hdrinfo	NormalHeader =	{ NULL, 0, NULL };
69 
70 u_long
71 chompheader(line, pflag, hdrp, e)
72 	char *line;
73 	int pflag;
74 	HDR **hdrp;
75 	register ENVELOPE *e;
76 {
77 	u_char mid = '\0';
78 	register char *p;
79 	register HDR *h;
80 	HDR **hp;
81 	char *fname;
82 	char *fvalue;
83 	bool cond = FALSE;
84 	bool dropfrom;
85 	bool headeronly;
86 	STAB *s;
87 	struct hdrinfo *hi;
88 	bool nullheader = FALSE;
89 	BITMAP256 mopts;
90 
91 	if (tTd(31, 6))
92 	{
93 		dprintf("chompheader: ");
94 		xputs(line);
95 		dprintf("\n");
96 	}
97 
98 	headeronly = hdrp != NULL;
99 	if (!headeronly)
100 		hdrp = &e->e_header;
101 
102 	/* strip off options */
103 	clrbitmap(mopts);
104 	p = line;
105 	if (!bitset(pflag, CHHDR_USER) && *p == '?')
106 	{
107 		int c;
108 		register char *q;
109 
110 		q = strchr(++p, '?');
111 		if (q == NULL)
112 			goto hse;
113 
114 		*q = '\0';
115 		c = *p & 0377;
116 
117 		/* possibly macro conditional */
118 		if (c == MACROEXPAND)
119 		{
120 			/* catch ?$? */
121 			if (*++p == '\0')
122 			{
123 				*q = '?';
124 				goto hse;
125 			}
126 
127 			mid = (u_char) *p++;
128 
129 			/* catch ?$abc? */
130 			if (*p != '\0')
131 			{
132 				*q = '?';
133 				goto hse;
134 			}
135 		}
136 		else if (*p == '$')
137 		{
138 			/* catch ?$? */
139 			if (*++p == '\0')
140 			{
141 				*q = '?';
142 				goto hse;
143 			}
144 
145 			mid = (u_char)macid(p, NULL);
146 			if (bitset(0200, mid))
147 				p += strlen(macname(mid)) + 2;
148 			else
149 				p++;
150 
151 			/* catch ?$abc? */
152 			if (*p != '\0')
153 			{
154 				*q = '?';
155 				goto hse;
156 			}
157 
158 		}
159 		else
160 		{
161 			while (*p != '\0')
162 			{
163 				if (!isascii(*p))
164 				{
165 					*q = '?';
166 					goto hse;
167 				}
168 
169 				setbitn(bitidx(*p), mopts);
170 				cond = TRUE;
171 				p++;
172 			}
173 		}
174 		p = q + 1;
175 	}
176 
177 	/* find canonical name */
178 	fname = p;
179 	while (isascii(*p) && isgraph(*p) && *p != ':')
180 		p++;
181 	fvalue = p;
182 	while (isascii(*p) && isspace(*p))
183 		p++;
184 	if (*p++ != ':' || fname == fvalue)
185 	{
186 hse:
187 		syserr("553 5.3.0 header syntax error, line \"%s\"", line);
188 		return 0;
189 	}
190 	*fvalue = '\0';
191 
192 	/* strip field value on front */
193 	if (*p == ' ')
194 		p++;
195 	fvalue = p;
196 
197 	/* if the field is null, go ahead and use the default */
198 	while (isascii(*p) && isspace(*p))
199 		p++;
200 	if (*p == '\0')
201 		nullheader = TRUE;
202 
203 	/* security scan: long field names are end-of-header */
204 	if (strlen(fname) > 100)
205 		return H_EOH;
206 
207 	/* check to see if it represents a ruleset call */
208 	if (bitset(pflag, CHHDR_DEF))
209 	{
210 		char hbuf[50];
211 
212 		(void) expand(fvalue, hbuf, sizeof hbuf, e);
213 		for (p = hbuf; isascii(*p) && isspace(*p); )
214 			p++;
215 		if ((*p++ & 0377) == CALLSUBR)
216 		{
217 			auto char *endp;
218 			bool strc;
219 
220 			strc = *p == '+';	/* strip comments? */
221 			if (strc)
222 				++p;
223 			if (strtorwset(p, &endp, ST_ENTER) > 0)
224 			{
225 				*endp = '\0';
226 				s = stab(fname, ST_HEADER, ST_ENTER);
227 				s->s_header.hi_ruleset = newstr(p);
228 				if (!strc)
229 					s->s_header.hi_flags |= H_STRIPCOMM;
230 			}
231 			return 0;
232 		}
233 	}
234 
235 	/* see if it is a known type */
236 	s = stab(fname, ST_HEADER, ST_FIND);
237 	if (s != NULL)
238 		hi = &s->s_header;
239 	else
240 		hi = &NormalHeader;
241 
242 	if (tTd(31, 9))
243 	{
244 		if (s == NULL)
245 			dprintf("no header flags match\n");
246 		else
247 			dprintf("header match, flags=%lx, ruleset=%s\n",
248 				hi->hi_flags,
249 				hi->hi_ruleset == NULL ? "<NULL>" : hi->hi_ruleset);
250 	}
251 
252 	/* see if this is a resent message */
253 	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
254 	    bitset(H_RESENT, hi->hi_flags))
255 		e->e_flags |= EF_RESENT;
256 
257 	/* if this is an Errors-To: header keep track of it now */
258 	if (UseErrorsTo && !bitset(pflag, CHHDR_DEF) && !headeronly &&
259 	    bitset(H_ERRORSTO, hi->hi_flags))
260 		(void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
261 
262 	/* if this means "end of header" quit now */
263 	if (!headeronly && bitset(H_EOH, hi->hi_flags))
264 		return hi->hi_flags;
265 
266 	/*
267 	**  Horrible hack to work around problem with Lotus Notes SMTP
268 	**  mail gateway, which generates From: headers with newlines in
269 	**  them and the <address> on the second line.  Although this is
270 	**  legal RFC 822, many MUAs don't handle this properly and thus
271 	**  never find the actual address.
272 	*/
273 
274 	if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader)
275 	{
276 		while ((p = strchr(fvalue, '\n')) != NULL)
277 			*p = ' ';
278 	}
279 
280 	/*
281 	**  If there is a check ruleset, verify it against the header.
282 	*/
283 
284 	if (bitset(pflag, CHHDR_CHECK))
285 	{
286 		bool stripcom = FALSE;
287 		char *rs;
288 
289 		/* no ruleset? look for default */
290 		rs = hi->hi_ruleset;
291 		if (rs == NULL)
292 		{
293 			s = stab("*", ST_HEADER, ST_FIND);
294 			if (s != NULL)
295 			{
296 				rs = (&s->s_header)->hi_ruleset;
297 				stripcom = bitset((&s->s_header)->hi_flags,
298 						  H_STRIPCOMM);
299 			}
300 		}
301 		else
302 			stripcom = bitset(hi->hi_flags, H_STRIPCOMM);
303 		if (rs != NULL)
304 		{
305 			int l;
306 			char qval[MAXNAME];
307 			char hlen[16];
308 			char *sp, *dp;
309 
310 			dp = qval;
311 			l = 0;
312 			dp[l++] = '"';
313 			for (sp = fvalue; *sp != '\0' && l < MAXNAME - 3; sp++)
314 			{
315 				switch(*sp)
316 				{
317 				  case '\011': /* ht */
318 				  case '\012': /* nl */
319 				  case '\013': /* vt */
320 				  case '\014': /* np */
321 				  case '\015': /* cr */
322 					dp[l++] = ' ';
323 					break;
324 				  case '"':
325 					dp[l++] = '\\';
326 					/* FALLTHROUGH */
327 				  default:
328 					dp[l++] = *sp;
329 					break;
330 				}
331 			}
332 			dp[l++] = '"';
333 			dp[l++] = '\0';
334 			l = strlen(fvalue);
335 			snprintf(hlen, sizeof hlen, "%d", l);
336 			define(macid("{hdrlen}", NULL), newstr(hlen), e);
337 			if (l >= MAXNAME)
338 			{
339 				if (LogLevel > 9)
340 					sm_syslog(LOG_WARNING, e->e_id,
341 						  "Warning: truncated header '%s' before check with '%s' len=%d max=%d",
342 						  fname, rs, l, MAXNAME - 1);
343 			}
344 			if ((sp = macvalue(macid("{currHeader}", NULL), e)) !=
345 			    NULL)
346 				sm_free(sp);
347 			define(macid("{currHeader}", NULL), newstr(qval), e);
348 			define(macid("{hdr_name}", NULL), newstr(fname), e);
349 			(void) rscheck(rs, fvalue, NULL, e, stripcom, TRUE, 4,
350 				       NULL);
351 		}
352 	}
353 
354 	/*
355 	**  Drop explicit From: if same as what we would generate.
356 	**  This is to make MH (which doesn't always give a full name)
357 	**  insert the full name information in all circumstances.
358 	*/
359 
360 	dropfrom = FALSE;
361 	p = "resent-from";
362 	if (!bitset(EF_RESENT, e->e_flags))
363 		p += 7;
364 	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
365 	    !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0)
366 	{
367 		if (tTd(31, 2))
368 		{
369 			dprintf("comparing header from (%s) against default (%s or %s)\n",
370 				fvalue, e->e_from.q_paddr, e->e_from.q_user);
371 		}
372 		if (e->e_from.q_paddr != NULL &&
373 		    e->e_from.q_mailer != NULL &&
374 		    bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) &&
375 		    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
376 		     strcmp(fvalue, e->e_from.q_user) == 0))
377 			dropfrom = TRUE;
378 	}
379 
380 	/* delete default value for this header */
381 	for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
382 	{
383 		if (strcasecmp(fname, h->h_field) == 0 &&
384 		    !bitset(H_USER, h->h_flags) &&
385 		    !bitset(H_FORCE, h->h_flags))
386 		{
387 			if (nullheader)
388 			{
389 				/* user-supplied value was null */
390 				return 0;
391 			}
392 			if (dropfrom)
393 			{
394 				/* make this look like the user entered it */
395 				h->h_flags |= H_USER;
396 				return hi->hi_flags;
397 			}
398 			h->h_value = NULL;
399 			if (!cond)
400 			{
401 				/* copy conditions from default case */
402 				memmove((char *)mopts, (char *)h->h_mflags,
403 					sizeof mopts);
404 			}
405 			h->h_macro = mid;
406 		}
407 	}
408 
409 	/* create a new node */
410 	h = (HDR *) xalloc(sizeof *h);
411 	h->h_field = newstr(fname);
412 	h->h_value = newstr(fvalue);
413 	h->h_link = NULL;
414 	memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts);
415 	h->h_macro = mid;
416 	*hp = h;
417 	h->h_flags = hi->hi_flags;
418 	if (bitset(pflag, CHHDR_USER) || bitset(pflag, CHHDR_QUEUE))
419 		h->h_flags |= H_USER;
420 
421 	/* strip EOH flag if parsing MIME headers */
422 	if (headeronly)
423 		h->h_flags &= ~H_EOH;
424 	if (bitset(pflag, CHHDR_DEF))
425 		h->h_flags |= H_DEFAULT;
426 	if (cond || mid != '\0')
427 		h->h_flags |= H_CHECK;
428 
429 	/* hack to see if this is a new format message */
430 	if (!bitset(pflag, CHHDR_DEF) && !headeronly &&
431 	    bitset(H_RCPT|H_FROM, h->h_flags) &&
432 	    (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
433 	     strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
434 	{
435 		e->e_flags &= ~EF_OLDSTYLE;
436 	}
437 
438 	return h->h_flags;
439 }
440 /*
441 **  ADDHEADER -- add a header entry to the end of the queue.
442 **
443 **	This bypasses the special checking of chompheader.
444 **
445 **	Parameters:
446 **		field -- the name of the header field.
447 **		value -- the value of the field.
448 **		flags -- flags to add to h_flags.
449 **		hdrlist -- an indirect pointer to the header structure list.
450 **
451 **	Returns:
452 **		none.
453 **
454 **	Side Effects:
455 **		adds the field on the list of headers for this envelope.
456 */
457 
458 void
459 addheader(field, value, flags, hdrlist)
460 	char *field;
461 	char *value;
462 	int flags;
463 	HDR **hdrlist;
464 {
465 	register HDR *h;
466 	STAB *s;
467 	HDR **hp;
468 
469 	/* find info struct */
470 	s = stab(field, ST_HEADER, ST_FIND);
471 
472 	/* find current place in list -- keep back pointer? */
473 	for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
474 	{
475 		if (strcasecmp(field, h->h_field) == 0)
476 			break;
477 	}
478 
479 	/* allocate space for new header */
480 	h = (HDR *) xalloc(sizeof *h);
481 	h->h_field = field;
482 	h->h_value = newstr(value);
483 	h->h_link = *hp;
484 	h->h_flags = flags;
485 	if (s != NULL)
486 		h->h_flags |= s->s_header.hi_flags;
487 	clrbitmap(h->h_mflags);
488 	h->h_macro = '\0';
489 	*hp = h;
490 }
491 /*
492 **  HVALUE -- return value of a header.
493 **
494 **	Only "real" fields (i.e., ones that have not been supplied
495 **	as a default) are used.
496 **
497 **	Parameters:
498 **		field -- the field name.
499 **		header -- the header list.
500 **
501 **	Returns:
502 **		pointer to the value part.
503 **		NULL if not found.
504 **
505 **	Side Effects:
506 **		none.
507 */
508 
509 char *
510 hvalue(field, header)
511 	char *field;
512 	HDR *header;
513 {
514 	register HDR *h;
515 
516 	for (h = header; h != NULL; h = h->h_link)
517 	{
518 		if (!bitset(H_DEFAULT, h->h_flags) &&
519 		    strcasecmp(h->h_field, field) == 0)
520 			return h->h_value;
521 	}
522 	return NULL;
523 }
524 /*
525 **  ISHEADER -- predicate telling if argument is a header.
526 **
527 **	A line is a header if it has a single word followed by
528 **	optional white space followed by a colon.
529 **
530 **	Header fields beginning with two dashes, although technically
531 **	permitted by RFC822, are automatically rejected in order
532 **	to make MIME work out.  Without this we could have a technically
533 **	legal header such as ``--"foo:bar"'' that would also be a legal
534 **	MIME separator.
535 **
536 **	Parameters:
537 **		h -- string to check for possible headerness.
538 **
539 **	Returns:
540 **		TRUE if h is a header.
541 **		FALSE otherwise.
542 **
543 **	Side Effects:
544 **		none.
545 */
546 
547 bool
548 isheader(h)
549 	char *h;
550 {
551 	register char *s = h;
552 
553 	if (s[0] == '-' && s[1] == '-')
554 		return FALSE;
555 
556 	while (*s > ' ' && *s != ':' && *s != '\0')
557 		s++;
558 
559 	if (h == s)
560 		return FALSE;
561 
562 	/* following technically violates RFC822 */
563 	while (isascii(*s) && isspace(*s))
564 		s++;
565 
566 	return (*s == ':');
567 }
568 /*
569 **  EATHEADER -- run through the stored header and extract info.
570 **
571 **	Parameters:
572 **		e -- the envelope to process.
573 **		full -- if set, do full processing (e.g., compute
574 **			message priority).  This should not be set
575 **			when reading a queue file because some info
576 **			needed to compute the priority is wrong.
577 **
578 **	Returns:
579 **		none.
580 **
581 **	Side Effects:
582 **		Sets a bunch of global variables from information
583 **			in the collected header.
584 **		Aborts the message if the hop count is exceeded.
585 */
586 
587 void
588 eatheader(e, full)
589 	register ENVELOPE *e;
590 	bool full;
591 {
592 	register HDR *h;
593 	register char *p;
594 	int hopcnt = 0;
595 	char *msgid;
596 	char buf[MAXLINE];
597 
598 	/*
599 	**  Set up macros for possible expansion in headers.
600 	*/
601 
602 	define('f', e->e_sender, e);
603 	define('g', e->e_sender, e);
604 	if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
605 		define('u', e->e_origrcpt, e);
606 	else
607 		define('u', NULL, e);
608 
609 	/* full name of from person */
610 	p = hvalue("full-name", e->e_header);
611 	if (p != NULL)
612 	{
613 		if (!rfc822_string(p))
614 		{
615 			/*
616 			**  Quote a full name with special characters
617 			**  as a comment so crackaddr() doesn't destroy
618 			**  the name portion of the address.
619 			*/
620 			p = addquotes(p);
621 		}
622 		define('x', p, e);
623 	}
624 
625 	if (tTd(32, 1))
626 		dprintf("----- collected header -----\n");
627 	msgid = NULL;
628 	for (h = e->e_header; h != NULL; h = h->h_link)
629 	{
630 		if (tTd(32, 1))
631 			dprintf("%s: ", h->h_field);
632 		if (h->h_value == NULL)
633 		{
634 			if (tTd(32, 1))
635 				dprintf("<NULL>\n");
636 			continue;
637 		}
638 
639 		/* do early binding */
640 		if (bitset(H_DEFAULT, h->h_flags) &&
641 		    !bitset(H_BINDLATE, h->h_flags))
642 		{
643 			if (tTd(32, 1))
644 			{
645 				dprintf("(");
646 				xputs(h->h_value);
647 				dprintf(") ");
648 			}
649 			expand(h->h_value, buf, sizeof buf, e);
650 			if (buf[0] != '\0')
651 			{
652 				if (bitset(H_FROM, h->h_flags))
653 					expand(crackaddr(buf), buf, sizeof buf, e);
654 				h->h_value = newstr(buf);
655 				h->h_flags &= ~H_DEFAULT;
656 			}
657 		}
658 
659 		if (tTd(32, 1))
660 		{
661 			xputs(h->h_value);
662 			dprintf("\n");
663 		}
664 
665 		/* count the number of times it has been processed */
666 		if (bitset(H_TRACE, h->h_flags))
667 			hopcnt++;
668 
669 		/* send to this person if we so desire */
670 		if (GrabTo && bitset(H_RCPT, h->h_flags) &&
671 		    !bitset(H_DEFAULT, h->h_flags) &&
672 		    (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
673 		{
674 #if 0
675 			int saveflags = e->e_flags;
676 #endif /* 0 */
677 
678 			(void) sendtolist(h->h_value, NULLADDR,
679 					  &e->e_sendqueue, 0, e);
680 
681 #if 0
682 			/*
683 			**  Change functionality so a fatal error on an
684 			**  address doesn't affect the entire envelope.
685 			*/
686 
687 			/* delete fatal errors generated by this address */
688 			if (!bitset(EF_FATALERRS, saveflags))
689 				e->e_flags &= ~EF_FATALERRS;
690 #endif /* 0 */
691 		}
692 
693 		/* save the message-id for logging */
694 		p = "resent-message-id";
695 		if (!bitset(EF_RESENT, e->e_flags))
696 			p += 7;
697 		if (strcasecmp(h->h_field, p) == 0)
698 		{
699 			msgid = h->h_value;
700 			while (isascii(*msgid) && isspace(*msgid))
701 				msgid++;
702 		}
703 	}
704 	if (tTd(32, 1))
705 		dprintf("----------------------------\n");
706 
707 	/* if we are just verifying (that is, sendmail -t -bv), drop out now */
708 	if (OpMode == MD_VERIFY)
709 		return;
710 
711 	/* store hop count */
712 	if (hopcnt > e->e_hopcount)
713 		e->e_hopcount = hopcnt;
714 
715 	/* message priority */
716 	p = hvalue("precedence", e->e_header);
717 	if (p != NULL)
718 		e->e_class = priencode(p);
719 	if (e->e_class < 0)
720 		e->e_timeoutclass = TOC_NONURGENT;
721 	else if (e->e_class > 0)
722 		e->e_timeoutclass = TOC_URGENT;
723 	if (full)
724 	{
725 		e->e_msgpriority = e->e_msgsize
726 				 - e->e_class * WkClassFact
727 				 + e->e_nrcpts * WkRecipFact;
728 	}
729 
730 	/* message timeout priority */
731 	p = hvalue("priority", e->e_header);
732 	if (p != NULL)
733 	{
734 		/* (this should be in the configuration file) */
735 		if (strcasecmp(p, "urgent") == 0)
736 			e->e_timeoutclass = TOC_URGENT;
737 		else if (strcasecmp(p, "normal") == 0)
738 			e->e_timeoutclass = TOC_NORMAL;
739 		else if (strcasecmp(p, "non-urgent") == 0)
740 			e->e_timeoutclass = TOC_NONURGENT;
741 	}
742 
743 	/* date message originated */
744 	p = hvalue("posted-date", e->e_header);
745 	if (p == NULL)
746 		p = hvalue("date", e->e_header);
747 	if (p != NULL)
748 		define('a', p, e);
749 
750 	/* check to see if this is a MIME message */
751 	if ((e->e_bodytype != NULL &&
752 	     strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
753 	    hvalue("MIME-Version", e->e_header) != NULL)
754 	{
755 		e->e_flags |= EF_IS_MIME;
756 		if (HasEightBits)
757 			e->e_bodytype = "8BITMIME";
758 	}
759 	else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
760 	{
761 		/* this may be an RFC 1049 message */
762 		p = strpbrk(p, ";/");
763 		if (p == NULL || *p == ';')
764 		{
765 			/* yep, it is */
766 			e->e_flags |= EF_DONT_MIME;
767 		}
768 	}
769 
770 	/*
771 	**  From person in antiquated ARPANET mode
772 	**	required by UK Grey Book e-mail gateways (sigh)
773 	*/
774 
775 	if (OpMode == MD_ARPAFTP)
776 	{
777 		register struct hdrinfo *hi;
778 
779 		for (hi = HdrInfo; hi->hi_field != NULL; hi++)
780 		{
781 			if (bitset(H_FROM, hi->hi_flags) &&
782 			    (!bitset(H_RESENT, hi->hi_flags) ||
783 			     bitset(EF_RESENT, e->e_flags)) &&
784 			    (p = hvalue(hi->hi_field, e->e_header)) != NULL)
785 				break;
786 		}
787 		if (hi->hi_field != NULL)
788 		{
789 			if (tTd(32, 2))
790 				dprintf("eatheader: setsender(*%s == %s)\n",
791 					hi->hi_field, p);
792 			setsender(p, e, NULL, '\0', TRUE);
793 		}
794 	}
795 
796 	/*
797 	**  Log collection information.
798 	*/
799 
800 	if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
801 		logsender(e, msgid);
802 	e->e_flags &= ~EF_LOGSENDER;
803 }
804 /*
805 **  LOGSENDER -- log sender information
806 **
807 **	Parameters:
808 **		e -- the envelope to log
809 **		msgid -- the message id
810 **
811 **	Returns:
812 **		none
813 */
814 
815 void
816 logsender(e, msgid)
817 	register ENVELOPE *e;
818 	char *msgid;
819 {
820 	char *name;
821 	register char *sbp;
822 	register char *p;
823 	int l;
824 	char hbuf[MAXNAME + 1];
825 	char sbuf[MAXLINE + 1];
826 	char mbuf[MAXNAME + 1];
827 
828 	/* don't allow newlines in the message-id */
829 	if (msgid != NULL)
830 	{
831 		l = strlen(msgid);
832 		if (l > sizeof mbuf - 1)
833 			l = sizeof mbuf - 1;
834 		memmove(mbuf, msgid, l);
835 		mbuf[l] = '\0';
836 		p = mbuf;
837 		while ((p = strchr(p, '\n')) != NULL)
838 			*p++ = ' ';
839 	}
840 
841 	if (bitset(EF_RESPONSE, e->e_flags))
842 		name = "[RESPONSE]";
843 	else if ((name = macvalue('_', e)) != NULL)
844 		/* EMPTY */
845 		;
846 	else if (RealHostName == NULL)
847 		name = "localhost";
848 	else if (RealHostName[0] == '[')
849 		name = RealHostName;
850 	else
851 	{
852 		name = hbuf;
853 		(void) snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName);
854 		if (RealHostAddr.sa.sa_family != 0)
855 		{
856 			p = &hbuf[strlen(hbuf)];
857 			(void) snprintf(p, SPACELEFT(hbuf, p), " (%.100s)",
858 				anynet_ntoa(&RealHostAddr));
859 		}
860 	}
861 
862 	/* some versions of syslog only take 5 printf args */
863 #if (SYSLOG_BUFSIZE) >= 256
864 	sbp = sbuf;
865 	snprintf(sbp, SPACELEFT(sbuf, sbp),
866 	    "from=%.200s, size=%ld, class=%d, nrcpts=%d",
867 	    e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
868 	    e->e_msgsize, e->e_class, e->e_nrcpts);
869 	sbp += strlen(sbp);
870 	if (msgid != NULL)
871 	{
872 		snprintf(sbp, SPACELEFT(sbuf, sbp), ", msgid=%.100s", mbuf);
873 		sbp += strlen(sbp);
874 	}
875 	if (e->e_bodytype != NULL)
876 	{
877 		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", bodytype=%.20s",
878 			e->e_bodytype);
879 		sbp += strlen(sbp);
880 	}
881 	p = macvalue('r', e);
882 	if (p != NULL)
883 	{
884 		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p);
885 		sbp += strlen(sbp);
886 	}
887 	p = macvalue(macid("{daemon_name}", NULL), e);
888 	if (p != NULL)
889 	{
890 		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", daemon=%.20s", p);
891 		sbp += strlen(sbp);
892 	}
893 # if SASL
894 	p = macvalue(macid("{auth_type}", NULL), e);
895 	if (p != NULL)
896 	{
897 		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", mech=%.12s", p);
898 		sbp += strlen(sbp);
899 	}
900 	p = macvalue(macid("{auth_author}", NULL), e);
901 	if (p != NULL)
902 	{
903 		(void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", auth=%.30s", p);
904 		sbp += strlen(sbp);
905 	}
906 # endif /* SASL */
907 	sm_syslog(LOG_INFO, e->e_id,
908 		  "%.850s, relay=%.100s",
909 		  sbuf, name);
910 
911 #else /* (SYSLOG_BUFSIZE) >= 256 */
912 
913 	sm_syslog(LOG_INFO, e->e_id,
914 		  "from=%s",
915 		  e->e_from.q_paddr == NULL ? "<NONE>"
916 					    : shortenstring(e->e_from.q_paddr, 83));
917 	sm_syslog(LOG_INFO, e->e_id,
918 		  "size=%ld, class=%ld, nrcpts=%d",
919 		  e->e_msgsize, e->e_class, e->e_nrcpts);
920 	if (msgid != NULL)
921 		sm_syslog(LOG_INFO, e->e_id,
922 			  "msgid=%s",
923 			  shortenstring(mbuf, 83));
924 	sbp = sbuf;
925 	*sbp = '\0';
926 	if (e->e_bodytype != NULL)
927 	{
928 		snprintf(sbp, SPACELEFT(sbuf, sbp), "bodytype=%.20s, ", e->e_bodytype);
929 		sbp += strlen(sbp);
930 	}
931 	p = macvalue('r', e);
932 	if (p != NULL)
933 	{
934 		snprintf(sbp, SPACELEFT(sbuf, sbp), "proto=%.20s, ", p);
935 		sbp += strlen(sbp);
936 	}
937 	sm_syslog(LOG_INFO, e->e_id,
938 		  "%.400srelay=%.100s", sbuf, name);
939 #endif /* (SYSLOG_BUFSIZE) >= 256 */
940 }
941 /*
942 **  PRIENCODE -- encode external priority names into internal values.
943 **
944 **	Parameters:
945 **		p -- priority in ascii.
946 **
947 **	Returns:
948 **		priority as a numeric level.
949 **
950 **	Side Effects:
951 **		none.
952 */
953 
954 static int
955 priencode(p)
956 	char *p;
957 {
958 	register int i;
959 
960 	for (i = 0; i < NumPriorities; i++)
961 	{
962 		if (strcasecmp(p, Priorities[i].pri_name) == 0)
963 			return Priorities[i].pri_val;
964 	}
965 
966 	/* unknown priority */
967 	return 0;
968 }
969 /*
970 **  CRACKADDR -- parse an address and turn it into a macro
971 **
972 **	This doesn't actually parse the address -- it just extracts
973 **	it and replaces it with "$g".  The parse is totally ad hoc
974 **	and isn't even guaranteed to leave something syntactically
975 **	identical to what it started with.  However, it does leave
976 **	something semantically identical.
977 **
978 **	This algorithm has been cleaned up to handle a wider range
979 **	of cases -- notably quoted and backslash escaped strings.
980 **	This modification makes it substantially better at preserving
981 **	the original syntax.
982 **
983 **	Parameters:
984 **		addr -- the address to be cracked.
985 **
986 **	Returns:
987 **		a pointer to the new version.
988 **
989 **	Side Effects:
990 **		none.
991 **
992 **	Warning:
993 **		The return value is saved in local storage and should
994 **		be copied if it is to be reused.
995 */
996 
997 char *
998 crackaddr(addr)
999 	register char *addr;
1000 {
1001 	register char *p;
1002 	register char c;
1003 	int cmtlev;
1004 	int realcmtlev;
1005 	int anglelev, realanglelev;
1006 	int copylev;
1007 	int bracklev;
1008 	bool qmode;
1009 	bool realqmode;
1010 	bool skipping;
1011 	bool putgmac = FALSE;
1012 	bool quoteit = FALSE;
1013 	bool gotangle = FALSE;
1014 	bool gotcolon = FALSE;
1015 	register char *bp;
1016 	char *buflim;
1017 	char *bufhead;
1018 	char *addrhead;
1019 	static char buf[MAXNAME + 1];
1020 
1021 	if (tTd(33, 1))
1022 		dprintf("crackaddr(%s)\n", addr);
1023 
1024 	/* strip leading spaces */
1025 	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
1026 		addr++;
1027 
1028 	/*
1029 	**  Start by assuming we have no angle brackets.  This will be
1030 	**  adjusted later if we find them.
1031 	*/
1032 
1033 	bp = bufhead = buf;
1034 	buflim = &buf[sizeof buf - 7];
1035 	p = addrhead = addr;
1036 	copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
1037 	bracklev = 0;
1038 	qmode = realqmode = FALSE;
1039 
1040 	while ((c = *p++) != '\0')
1041 	{
1042 		/*
1043 		**  If the buffer is overful, go into a special "skipping"
1044 		**  mode that tries to keep legal syntax but doesn't actually
1045 		**  output things.
1046 		*/
1047 
1048 		skipping = bp >= buflim;
1049 
1050 		if (copylev > 0 && !skipping)
1051 			*bp++ = c;
1052 
1053 		/* check for backslash escapes */
1054 		if (c == '\\')
1055 		{
1056 			/* arrange to quote the address */
1057 			if (cmtlev <= 0 && !qmode)
1058 				quoteit = TRUE;
1059 
1060 			if ((c = *p++) == '\0')
1061 			{
1062 				/* too far */
1063 				p--;
1064 				goto putg;
1065 			}
1066 			if (copylev > 0 && !skipping)
1067 				*bp++ = c;
1068 			goto putg;
1069 		}
1070 
1071 		/* check for quoted strings */
1072 		if (c == '"' && cmtlev <= 0)
1073 		{
1074 			qmode = !qmode;
1075 			if (copylev > 0 && !skipping)
1076 				realqmode = !realqmode;
1077 			continue;
1078 		}
1079 		if (qmode)
1080 			goto putg;
1081 
1082 		/* check for comments */
1083 		if (c == '(')
1084 		{
1085 			cmtlev++;
1086 
1087 			/* allow space for closing paren */
1088 			if (!skipping)
1089 			{
1090 				buflim--;
1091 				realcmtlev++;
1092 				if (copylev++ <= 0)
1093 				{
1094 					if (bp != bufhead)
1095 						*bp++ = ' ';
1096 					*bp++ = c;
1097 				}
1098 			}
1099 		}
1100 		if (cmtlev > 0)
1101 		{
1102 			if (c == ')')
1103 			{
1104 				cmtlev--;
1105 				copylev--;
1106 				if (!skipping)
1107 				{
1108 					realcmtlev--;
1109 					buflim++;
1110 				}
1111 			}
1112 			continue;
1113 		}
1114 		else if (c == ')')
1115 		{
1116 			/* syntax error: unmatched ) */
1117 			if (copylev > 0 && !skipping)
1118 				bp--;
1119 		}
1120 
1121 		/* count nesting on [ ... ] (for IPv6 domain literals) */
1122 		if (c == '[')
1123 			bracklev++;
1124 		else if (c == ']')
1125 			bracklev--;
1126 
1127 		/* check for group: list; syntax */
1128 		if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
1129 		    !gotcolon && !ColonOkInAddr)
1130 		{
1131 			register char *q;
1132 
1133 			/*
1134 			**  Check for DECnet phase IV ``::'' (host::user)
1135 			**  or **  DECnet phase V ``:.'' syntaxes.  The latter
1136 			**  covers ``user@DEC:.tay.myhost'' and
1137 			**  ``DEC:.tay.myhost::user'' syntaxes (bletch).
1138 			*/
1139 
1140 			if (*p == ':' || *p == '.')
1141 			{
1142 				if (cmtlev <= 0 && !qmode)
1143 					quoteit = TRUE;
1144 				if (copylev > 0 && !skipping)
1145 				{
1146 					*bp++ = c;
1147 					*bp++ = *p;
1148 				}
1149 				p++;
1150 				goto putg;
1151 			}
1152 
1153 			gotcolon = TRUE;
1154 
1155 			bp = bufhead;
1156 			if (quoteit)
1157 			{
1158 				*bp++ = '"';
1159 
1160 				/* back up over the ':' and any spaces */
1161 				--p;
1162 				while (isascii(*--p) && isspace(*p))
1163 					continue;
1164 				p++;
1165 			}
1166 			for (q = addrhead; q < p; )
1167 			{
1168 				c = *q++;
1169 				if (bp < buflim)
1170 				{
1171 					if (quoteit && c == '"')
1172 						*bp++ = '\\';
1173 					*bp++ = c;
1174 				}
1175 			}
1176 			if (quoteit)
1177 			{
1178 				if (bp == &bufhead[1])
1179 					bp--;
1180 				else
1181 					*bp++ = '"';
1182 				while ((c = *p++) != ':')
1183 				{
1184 					if (bp < buflim)
1185 						*bp++ = c;
1186 				}
1187 				*bp++ = c;
1188 			}
1189 
1190 			/* any trailing white space is part of group: */
1191 			while (isascii(*p) && isspace(*p) && bp < buflim)
1192 				*bp++ = *p++;
1193 			copylev = 0;
1194 			putgmac = quoteit = FALSE;
1195 			bufhead = bp;
1196 			addrhead = p;
1197 			continue;
1198 		}
1199 
1200 		if (c == ';' && copylev <= 0 && !ColonOkInAddr)
1201 		{
1202 			if (bp < buflim)
1203 				*bp++ = c;
1204 		}
1205 
1206 		/* check for characters that may have to be quoted */
1207 		if (strchr(MustQuoteChars, c) != NULL)
1208 		{
1209 			/*
1210 			**  If these occur as the phrase part of a <>
1211 			**  construct, but are not inside of () or already
1212 			**  quoted, they will have to be quoted.  Note that
1213 			**  now (but don't actually do the quoting).
1214 			*/
1215 
1216 			if (cmtlev <= 0 && !qmode)
1217 				quoteit = TRUE;
1218 		}
1219 
1220 		/* check for angle brackets */
1221 		if (c == '<')
1222 		{
1223 			register char *q;
1224 
1225 			/* assume first of two angles is bogus */
1226 			if (gotangle)
1227 				quoteit = TRUE;
1228 			gotangle = TRUE;
1229 
1230 			/* oops -- have to change our mind */
1231 			anglelev = 1;
1232 			if (!skipping)
1233 				realanglelev = 1;
1234 
1235 			bp = bufhead;
1236 			if (quoteit)
1237 			{
1238 				*bp++ = '"';
1239 
1240 				/* back up over the '<' and any spaces */
1241 				--p;
1242 				while (isascii(*--p) && isspace(*p))
1243 					continue;
1244 				p++;
1245 			}
1246 			for (q = addrhead; q < p; )
1247 			{
1248 				c = *q++;
1249 				if (bp < buflim)
1250 				{
1251 					if (quoteit && c == '"')
1252 						*bp++ = '\\';
1253 					*bp++ = c;
1254 				}
1255 			}
1256 			if (quoteit)
1257 			{
1258 				if (bp == &buf[1])
1259 					bp--;
1260 				else
1261 					*bp++ = '"';
1262 				while ((c = *p++) != '<')
1263 				{
1264 					if (bp < buflim)
1265 						*bp++ = c;
1266 				}
1267 				*bp++ = c;
1268 			}
1269 			copylev = 0;
1270 			putgmac = quoteit = FALSE;
1271 			continue;
1272 		}
1273 
1274 		if (c == '>')
1275 		{
1276 			if (anglelev > 0)
1277 			{
1278 				anglelev--;
1279 				if (!skipping)
1280 				{
1281 					realanglelev--;
1282 					buflim++;
1283 				}
1284 			}
1285 			else if (!skipping)
1286 			{
1287 				/* syntax error: unmatched > */
1288 				if (copylev > 0)
1289 					bp--;
1290 				quoteit = TRUE;
1291 				continue;
1292 			}
1293 			if (copylev++ <= 0)
1294 				*bp++ = c;
1295 			continue;
1296 		}
1297 
1298 		/* must be a real address character */
1299 	putg:
1300 		if (copylev <= 0 && !putgmac)
1301 		{
1302 			if (bp > bufhead && bp[-1] == ')')
1303 				*bp++ = ' ';
1304 			*bp++ = MACROEXPAND;
1305 			*bp++ = 'g';
1306 			putgmac = TRUE;
1307 		}
1308 	}
1309 
1310 	/* repair any syntactic damage */
1311 	if (realqmode)
1312 		*bp++ = '"';
1313 	while (realcmtlev-- > 0)
1314 		*bp++ = ')';
1315 	while (realanglelev-- > 0)
1316 		*bp++ = '>';
1317 	*bp++ = '\0';
1318 
1319 	if (tTd(33, 1))
1320 	{
1321 		dprintf("crackaddr=>`");
1322 		xputs(buf);
1323 		dprintf("'\n");
1324 	}
1325 
1326 	return buf;
1327 }
1328 /*
1329 **  PUTHEADER -- put the header part of a message from the in-core copy
1330 **
1331 **	Parameters:
1332 **		mci -- the connection information.
1333 **		hdr -- the header to put.
1334 **		e -- envelope to use.
1335 **		flags -- MIME conversion flags.
1336 **
1337 **	Returns:
1338 **		none.
1339 **
1340 **	Side Effects:
1341 **		none.
1342 */
1343 
1344 /*
1345  * Macro for fast max (not available in e.g. DG/UX, 386/ix).
1346  */
1347 #ifndef MAX
1348 # define MAX(a,b) (((a)>(b))?(a):(b))
1349 #endif /* ! MAX */
1350 
1351 void
1352 putheader(mci, hdr, e, flags)
1353 	register MCI *mci;
1354 	HDR *hdr;
1355 	register ENVELOPE *e;
1356 	int flags;
1357 {
1358 	register HDR *h;
1359 	char buf[MAX(MAXLINE,BUFSIZ)];
1360 	char obuf[MAXLINE];
1361 
1362 	if (tTd(34, 1))
1363 		dprintf("--- putheader, mailer = %s ---\n",
1364 			mci->mci_mailer->m_name);
1365 
1366 	/*
1367 	**  If we're in MIME mode, we're not really in the header of the
1368 	**  message, just the header of one of the parts of the body of
1369 	**  the message.  Therefore MCIF_INHEADER should not be turned on.
1370 	*/
1371 
1372 	if (!bitset(MCIF_INMIME, mci->mci_flags))
1373 		mci->mci_flags |= MCIF_INHEADER;
1374 
1375 	for (h = hdr; h != NULL; h = h->h_link)
1376 	{
1377 		register char *p = h->h_value;
1378 
1379 		if (tTd(34, 11))
1380 		{
1381 			dprintf("  %s: ", h->h_field);
1382 			xputs(p);
1383 		}
1384 
1385 		/* Skip empty headers */
1386 		if (h->h_value == NULL)
1387 			continue;
1388 
1389 		/* heuristic shortening of MIME fields to avoid MUA overflows */
1390 		if (MaxMimeFieldLength > 0 &&
1391 		    wordinclass(h->h_field,
1392 				macid("{checkMIMEFieldHeaders}", NULL)))
1393 		{
1394 			size_t len;
1395 
1396 			len = fix_mime_header(h->h_value);
1397 			if (len > 0)
1398 			{
1399 				sm_syslog(LOG_ALERT, e->e_id,
1400 					  "Truncated MIME %s header due to field size (length = %ld) (possible attack)",
1401 					  h->h_field, (unsigned long) len);
1402 				if (tTd(34, 11))
1403 					dprintf("  truncated MIME %s header due to field size  (length = %ld) (possible attack)\n",
1404 						h->h_field,
1405 						(unsigned long) len);
1406 			}
1407 		}
1408 
1409 		if (MaxMimeHeaderLength > 0 &&
1410 		    wordinclass(h->h_field,
1411 				macid("{checkMIMETextHeaders}", NULL)))
1412 		{
1413 			size_t len;
1414 
1415 			len = strlen(h->h_value);
1416 			if (len > (size_t) MaxMimeHeaderLength)
1417 			{
1418 				h->h_value[MaxMimeHeaderLength - 1] = '\0';
1419 				sm_syslog(LOG_ALERT, e->e_id,
1420 					  "Truncated long MIME %s header (length = %ld) (possible attack)",
1421 					  h->h_field, (unsigned long) len);
1422 				if (tTd(34, 11))
1423 					dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1424 						h->h_field,
1425 						(unsigned long) len);
1426 			}
1427 		}
1428 
1429 		if (MaxMimeHeaderLength > 0 &&
1430 		    wordinclass(h->h_field,
1431 				macid("{checkMIMEHeaders}", NULL)))
1432 		{
1433 			size_t len;
1434 
1435 			len = strlen(h->h_value);
1436 			if (shorten_rfc822_string(h->h_value,
1437 						  MaxMimeHeaderLength))
1438 			{
1439 				sm_syslog(LOG_ALERT, e->e_id,
1440 					  "Truncated long MIME %s header (length = %ld) (possible attack)",
1441 					  h->h_field, (unsigned long) len);
1442 				if (tTd(34, 11))
1443 					dprintf("  truncated long MIME %s header (length = %ld) (possible attack)\n",
1444 						h->h_field,
1445 						(unsigned long) len);
1446 			}
1447 		}
1448 
1449 		/*
1450 		**  Suppress Content-Transfer-Encoding: if we are MIMEing
1451 		**  and we are potentially converting from 8 bit to 7 bit
1452 		**  MIME.  If converting, add a new CTE header in
1453 		**  mime8to7().
1454 		*/
1455 		if (bitset(H_CTE, h->h_flags) &&
1456 		    bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME,
1457 			   mci->mci_flags) &&
1458 		    !bitset(M87F_NO8TO7, flags))
1459 		{
1460 			if (tTd(34, 11))
1461 				dprintf(" (skipped (content-transfer-encoding))\n");
1462 			continue;
1463 		}
1464 
1465 		if (bitset(MCIF_INMIME, mci->mci_flags))
1466 		{
1467 			if (tTd(34, 11))
1468 				dprintf("\n");
1469 			put_vanilla_header(h, p, mci);
1470 			continue;
1471 		}
1472 
1473 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
1474 		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) &&
1475 		    (h->h_macro == '\0' ||
1476 		     macvalue(bitidx(h->h_macro), e) == NULL))
1477 		{
1478 			if (tTd(34, 11))
1479 				dprintf(" (skipped)\n");
1480 			continue;
1481 		}
1482 
1483 		/* handle Resent-... headers specially */
1484 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
1485 		{
1486 			if (tTd(34, 11))
1487 				dprintf(" (skipped (resent))\n");
1488 			continue;
1489 		}
1490 
1491 		/* suppress return receipts if requested */
1492 		if (bitset(H_RECEIPTTO, h->h_flags) &&
1493 		    (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags)))
1494 		{
1495 			if (tTd(34, 11))
1496 				dprintf(" (skipped (receipt))\n");
1497 			continue;
1498 		}
1499 
1500 		/* macro expand value if generated internally */
1501 		if (bitset(H_DEFAULT, h->h_flags) ||
1502 		    bitset(H_BINDLATE, h->h_flags))
1503 		{
1504 			expand(p, buf, sizeof buf, e);
1505 			p = buf;
1506 			if (*p == '\0')
1507 			{
1508 				if (tTd(34, 11))
1509 					dprintf(" (skipped -- null value)\n");
1510 				continue;
1511 			}
1512 		}
1513 
1514 		if (bitset(H_BCC, h->h_flags))
1515 		{
1516 			/* Bcc: field -- either truncate or delete */
1517 			if (bitset(EF_DELETE_BCC, e->e_flags))
1518 			{
1519 				if (tTd(34, 11))
1520 					dprintf(" (skipped -- bcc)\n");
1521 			}
1522 			else
1523 			{
1524 				/* no other recipient headers: truncate value */
1525 				(void) snprintf(obuf, sizeof obuf, "%s:",
1526 					h->h_field);
1527 				putline(obuf, mci);
1528 			}
1529 			continue;
1530 		}
1531 
1532 		if (tTd(34, 11))
1533 			dprintf("\n");
1534 
1535 		if (bitset(H_FROM|H_RCPT, h->h_flags))
1536 		{
1537 			/* address field */
1538 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1539 
1540 			if (bitset(H_FROM, h->h_flags))
1541 				oldstyle = FALSE;
1542 			commaize(h, p, oldstyle, mci, e);
1543 		}
1544 		else
1545 		{
1546 			put_vanilla_header(h, p, mci);
1547 		}
1548 	}
1549 
1550 	/*
1551 	**  If we are converting this to a MIME message, add the
1552 	**  MIME headers (but not in MIME mode!).
1553 	*/
1554 
1555 #if MIME8TO7
1556 	if (bitset(MM_MIME8BIT, MimeMode) &&
1557 	    bitset(EF_HAS8BIT, e->e_flags) &&
1558 	    !bitset(EF_DONT_MIME, e->e_flags) &&
1559 	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
1560 	    !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) &&
1561 	    hvalue("MIME-Version", e->e_header) == NULL)
1562 	{
1563 		putline("MIME-Version: 1.0", mci);
1564 		if (hvalue("Content-Type", e->e_header) == NULL)
1565 		{
1566 			snprintf(obuf, sizeof obuf,
1567 				"Content-Type: text/plain; charset=%s",
1568 				defcharset(e));
1569 			putline(obuf, mci);
1570 		}
1571 		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
1572 			putline("Content-Transfer-Encoding: 8bit", mci);
1573 	}
1574 #endif /* MIME8TO7 */
1575 }
1576 /*
1577 **  PUT_VANILLA_HEADER -- output a fairly ordinary header
1578 **
1579 **	Parameters:
1580 **		h -- the structure describing this header
1581 **		v -- the value of this header
1582 **		mci -- the connection info for output
1583 **
1584 **	Returns:
1585 **		none.
1586 */
1587 
1588 static void
1589 put_vanilla_header(h, v, mci)
1590 	HDR *h;
1591 	char *v;
1592 	MCI *mci;
1593 {
1594 	register char *nlp;
1595 	register char *obp;
1596 	int putflags;
1597 	char obuf[MAXLINE];
1598 
1599 	putflags = PXLF_HEADER;
1600 	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1601 		putflags |= PXLF_STRIP8BIT;
1602 	(void) snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field);
1603 	obp = obuf + strlen(obuf);
1604 	while ((nlp = strchr(v, '\n')) != NULL)
1605 	{
1606 		int l;
1607 
1608 		l = nlp - v;
1609 		if (SPACELEFT(obuf, obp) - 1 < (size_t)l)
1610 			l = SPACELEFT(obuf, obp) - 1;
1611 
1612 		snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
1613 		putxline(obuf, strlen(obuf), mci, putflags);
1614 		v += l + 1;
1615 		obp = obuf;
1616 		if (*v != ' ' && *v != '\t')
1617 			*obp++ = ' ';
1618 	}
1619 	snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
1620 		(int) sizeof obuf - (obp - obuf) - 1, v);
1621 	putxline(obuf, strlen(obuf), mci, putflags);
1622 }
1623 /*
1624 **  COMMAIZE -- output a header field, making a comma-translated list.
1625 **
1626 **	Parameters:
1627 **		h -- the header field to output.
1628 **		p -- the value to put in it.
1629 **		oldstyle -- TRUE if this is an old style header.
1630 **		mci -- the connection information.
1631 **		e -- the envelope containing the message.
1632 **
1633 **	Returns:
1634 **		none.
1635 **
1636 **	Side Effects:
1637 **		outputs "p" to file "fp".
1638 */
1639 
1640 void
1641 commaize(h, p, oldstyle, mci, e)
1642 	register HDR *h;
1643 	register char *p;
1644 	bool oldstyle;
1645 	register MCI *mci;
1646 	register ENVELOPE *e;
1647 {
1648 	register char *obp;
1649 	int opos;
1650 	int omax;
1651 	bool firstone = TRUE;
1652 	int putflags = PXLF_HEADER;
1653 	char obuf[MAXLINE + 3];
1654 
1655 	/*
1656 	**  Output the address list translated by the
1657 	**  mailer and with commas.
1658 	*/
1659 
1660 	if (tTd(14, 2))
1661 		dprintf("commaize(%s: %s)\n", h->h_field, p);
1662 
1663 	if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags))
1664 		putflags |= PXLF_STRIP8BIT;
1665 
1666 	obp = obuf;
1667 	(void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", h->h_field);
1668 	opos = strlen(h->h_field) + 2;
1669 	if (opos > 202)
1670 		opos = 202;
1671 	obp += opos;
1672 	omax = mci->mci_mailer->m_linelimit - 2;
1673 	if (omax < 0 || omax > 78)
1674 		omax = 78;
1675 
1676 	/*
1677 	**  Run through the list of values.
1678 	*/
1679 
1680 	while (*p != '\0')
1681 	{
1682 		register char *name;
1683 		register int c;
1684 		char savechar;
1685 		int flags;
1686 		auto int status;
1687 
1688 		/*
1689 		**  Find the end of the name.  New style names
1690 		**  end with a comma, old style names end with
1691 		**  a space character.  However, spaces do not
1692 		**  necessarily delimit an old-style name -- at
1693 		**  signs mean keep going.
1694 		*/
1695 
1696 		/* find end of name */
1697 		while ((isascii(*p) && isspace(*p)) || *p == ',')
1698 			p++;
1699 		name = p;
1700 		for (;;)
1701 		{
1702 			auto char *oldp;
1703 			char pvpbuf[PSBUFSIZE];
1704 
1705 			(void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
1706 				       sizeof pvpbuf, &oldp, NULL);
1707 			p = oldp;
1708 
1709 			/* look to see if we have an at sign */
1710 			while (*p != '\0' && isascii(*p) && isspace(*p))
1711 				p++;
1712 
1713 			if (*p != '@')
1714 			{
1715 				p = oldp;
1716 				break;
1717 			}
1718 			p += *p == '@' ? 1 : 2;
1719 			while (*p != '\0' && isascii(*p) && isspace(*p))
1720 				p++;
1721 		}
1722 		/* at the end of one complete name */
1723 
1724 		/* strip off trailing white space */
1725 		while (p >= name &&
1726 		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1727 			p--;
1728 		if (++p == name)
1729 			continue;
1730 		savechar = *p;
1731 		*p = '\0';
1732 
1733 		/* translate the name to be relative */
1734 		flags = RF_HEADERADDR|RF_ADDDOMAIN;
1735 		if (bitset(H_FROM, h->h_flags))
1736 			flags |= RF_SENDERADDR;
1737 #if USERDB
1738 		else if (e->e_from.q_mailer != NULL &&
1739 			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
1740 		{
1741 			char *q;
1742 
1743 			q = udbsender(name);
1744 			if (q != NULL)
1745 				name = q;
1746 		}
1747 #endif /* USERDB */
1748 		status = EX_OK;
1749 		name = remotename(name, mci->mci_mailer, flags, &status, e);
1750 		if (*name == '\0')
1751 		{
1752 			*p = savechar;
1753 			continue;
1754 		}
1755 		name = denlstring(name, FALSE, TRUE);
1756 
1757 		/*
1758 		**  record data progress so DNS timeouts
1759 		**  don't cause DATA timeouts
1760 		*/
1761 
1762 		DataProgress = TRUE;
1763 
1764 		/* output the name with nice formatting */
1765 		opos += strlen(name);
1766 		if (!firstone)
1767 			opos += 2;
1768 		if (opos > omax && !firstone)
1769 		{
1770 			snprintf(obp, SPACELEFT(obuf, obp), ",\n");
1771 			putxline(obuf, strlen(obuf), mci, putflags);
1772 			obp = obuf;
1773 			(void) strlcpy(obp, "        ", sizeof obp);
1774 			opos = strlen(obp);
1775 			obp += opos;
1776 			opos += strlen(name);
1777 		}
1778 		else if (!firstone)
1779 		{
1780 			snprintf(obp, SPACELEFT(obuf, obp), ", ");
1781 			obp += 2;
1782 		}
1783 
1784 		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
1785 			*obp++ = c;
1786 		firstone = FALSE;
1787 		*p = savechar;
1788 	}
1789 	*obp = '\0';
1790 	putxline(obuf, strlen(obuf), mci, putflags);
1791 }
1792 /*
1793 **  COPYHEADER -- copy header list
1794 **
1795 **	This routine is the equivalent of newstr for header lists
1796 **
1797 **	Parameters:
1798 **		header -- list of header structures to copy.
1799 **
1800 **	Returns:
1801 **		a copy of 'header'.
1802 **
1803 **	Side Effects:
1804 **		none.
1805 */
1806 
1807 HDR *
1808 copyheader(header)
1809 	register HDR *header;
1810 {
1811 	register HDR *newhdr;
1812 	HDR *ret;
1813 	register HDR **tail = &ret;
1814 
1815 	while (header != NULL)
1816 	{
1817 		newhdr = (HDR *) xalloc(sizeof *newhdr);
1818 		STRUCTCOPY(*header, *newhdr);
1819 		*tail = newhdr;
1820 		tail = &newhdr->h_link;
1821 		header = header->h_link;
1822 	}
1823 	*tail = NULL;
1824 
1825 	return ret;
1826 }
1827 /*
1828 **  FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header
1829 **
1830 **	Run through all of the parameters of a MIME header and
1831 **	possibly truncate and rebalance the parameter according
1832 **	to MaxMimeFieldLength.
1833 **
1834 **	Parameters:
1835 **		string -- the full header
1836 **
1837 **	Returns:
1838 **		length of last offending field, 0 if all ok.
1839 **
1840 **	Side Effects:
1841 **		string modified in place
1842 */
1843 
1844 static size_t
1845 fix_mime_header(string)
1846 	char *string;
1847 {
1848 	char *begin = string;
1849 	char *end;
1850 	size_t len = 0;
1851 	size_t retlen = 0;
1852 
1853 	if (string == NULL || *string == '\0')
1854 		return 0;
1855 
1856 	/* Split on each ';' */
1857 	while ((end = find_character(begin, ';')) != NULL)
1858 	{
1859 		char save = *end;
1860 		char *bp;
1861 
1862 		*end = '\0';
1863 
1864 		len = strlen(begin);
1865 
1866 		/* Shorten individual parameter */
1867 		if (shorten_rfc822_string(begin, MaxMimeFieldLength))
1868 			retlen = len;
1869 
1870 		/* Collapse the possibly shortened string with rest */
1871 		bp = begin + strlen(begin);
1872 		if (bp != end)
1873 		{
1874 			char *ep = end;
1875 
1876 			*end = save;
1877 			end = bp;
1878 
1879 			/* copy character by character due to overlap */
1880 			while (*ep != '\0')
1881 				*bp++ = *ep++;
1882 			*bp = '\0';
1883 		}
1884 		else
1885 			*end = save;
1886 		if (*end == '\0')
1887 			break;
1888 
1889 		/* Move past ';' */
1890 		begin = end + 1;
1891 	}
1892 	return retlen;
1893 }
1894