1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)headers.c	8.54 (Berkeley) 04/03/95";
11 #endif /* not lint */
12 
13 # include <errno.h>
14 # include "sendmail.h"
15 
16 /*
17 **  CHOMPHEADER -- process and save a header line.
18 **
19 **	Called by collect and by readcf to deal with header lines.
20 **
21 **	Parameters:
22 **		line -- header as a text line.
23 **		def -- if set, this is a default value.
24 **		hdrp -- a pointer to the place to save the header.
25 **		e -- the envelope including this header.
26 **
27 **	Returns:
28 **		flags for this header.
29 **
30 **	Side Effects:
31 **		The header is saved on the header list.
32 **		Contents of 'line' are destroyed.
33 */
34 
35 chompheader(line, def, hdrp, e)
36 	char *line;
37 	bool def;
38 	HDR **hdrp;
39 	register ENVELOPE *e;
40 {
41 	register char *p;
42 	register HDR *h;
43 	HDR **hp;
44 	char *fname;
45 	char *fvalue;
46 	struct hdrinfo *hi;
47 	bool cond = FALSE;
48 	bool headeronly;
49 	BITMAP mopts;
50 	char buf[MAXNAME + 1];
51 
52 	if (tTd(31, 6))
53 		printf("chompheader: %s\n", line);
54 
55 	headeronly = hdrp != NULL;
56 	if (!headeronly)
57 		hdrp = &e->e_header;
58 
59 	/* strip off options */
60 	clrbitmap(mopts);
61 	p = line;
62 	if (*p == '?')
63 	{
64 		/* have some */
65 		register char *q = strchr(p + 1, *p);
66 
67 		if (q != NULL)
68 		{
69 			*q++ = '\0';
70 			while (*++p != '\0')
71 				setbitn(*p, mopts);
72 			p = q;
73 		}
74 		else
75 			syserr("553 header syntax error, line \"%s\"", line);
76 		cond = TRUE;
77 	}
78 
79 	/* find canonical name */
80 	fname = p;
81 	while (isascii(*p) && isgraph(*p) && *p != ':')
82 		p++;
83 	fvalue = p;
84 	while (isascii(*p) && isspace(*p))
85 		p++;
86 	if (*p++ != ':' || fname == fvalue)
87 	{
88 		syserr("553 header syntax error, line \"%s\"", line);
89 		return (0);
90 	}
91 	*fvalue = '\0';
92 	fvalue = p;
93 
94 	/* strip field value on front */
95 	if (*fvalue == ' ')
96 		fvalue++;
97 
98 	/* see if it is a known type */
99 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
100 	{
101 		if (strcasecmp(hi->hi_field, fname) == 0)
102 			break;
103 	}
104 
105 	if (tTd(31, 9))
106 	{
107 		if (hi->hi_field == NULL)
108 			printf("no header match\n");
109 		else
110 			printf("header match, hi_flags=%x\n", hi->hi_flags);
111 	}
112 
113 	/* see if this is a resent message */
114 	if (!def && !headeronly && bitset(H_RESENT, hi->hi_flags))
115 		e->e_flags |= EF_RESENT;
116 
117 	/* if this is an Errors-To: header keep track of it now */
118 	if (UseErrorsTo && !def && !headeronly &&
119 	    bitset(H_ERRORSTO, hi->hi_flags))
120 		(void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
121 
122 	/* if this means "end of header" quit now */
123 	if (bitset(H_EOH, hi->hi_flags))
124 		return (hi->hi_flags);
125 
126 	/*
127 	**  Drop explicit From: if same as what we would generate.
128 	**  This is to make MH (which doesn't always give a full name)
129 	**  insert the full name information in all circumstances.
130 	*/
131 
132 	p = "resent-from";
133 	if (!bitset(EF_RESENT, e->e_flags))
134 		p += 7;
135 	if (!def && !headeronly && !bitset(EF_QUEUERUN, e->e_flags) &&
136 	    strcasecmp(fname, p) == 0)
137 	{
138 		if (tTd(31, 2))
139 		{
140 			printf("comparing header from (%s) against default (%s or %s)\n",
141 				fvalue, e->e_from.q_paddr, e->e_from.q_user);
142 		}
143 		if (e->e_from.q_paddr != NULL &&
144 		    (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
145 		     strcmp(fvalue, e->e_from.q_user) == 0))
146 			return (hi->hi_flags);
147 #ifdef MAYBENEXTRELEASE		/* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */
148 #ifdef USERDB
149 		else
150 		{
151 			auto ADDRESS a;
152 			char *fancy;
153 			bool oldSuprErrs = SuprErrs;
154 			extern char *crackaddr();
155 			extern char *udbsender();
156 
157 			/*
158 			**  Try doing USERDB rewriting even on fully commented
159 			**  names; this saves the "comment" information (such
160 			**  as full name) and rewrites the electronic part.
161 			**
162 			** XXX	This code doesn't belong here -- parsing should
163 			** XXX	not be done during collect() phase because
164 			** XXX	error messages can confuse the SMTP phase.
165 			** XXX	Setting SuprErrs is a crude hack around this
166 			** XXX	problem.
167 			*/
168 
169 			if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
170 				SuprErrs = TRUE;
171 			fancy = crackaddr(fvalue);
172 			if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL &&
173 			    bitnset(M_CHECKUDB, a.q_mailer->m_flags) &&
174 			    (p = udbsender(a.q_user)) != NULL)
175 			{
176 				char *oldg = macvalue('g', e);
177 
178 				define('g', p, e);
179 				expand(fancy, buf, sizeof buf, e);
180 				define('g', oldg, e);
181 				fvalue = buf;
182 			}
183 			SuprErrs = oldSuprErrs;
184 		}
185 #endif
186 #endif
187 	}
188 
189 	/* delete default value for this header */
190 	for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
191 	{
192 		if (strcasecmp(fname, h->h_field) == 0 &&
193 		    bitset(H_DEFAULT, h->h_flags) &&
194 		    !bitset(H_FORCE, h->h_flags))
195 			h->h_value = NULL;
196 	}
197 
198 	/* create a new node */
199 	h = (HDR *) xalloc(sizeof *h);
200 	h->h_field = newstr(fname);
201 	h->h_value = newstr(fvalue);
202 	h->h_link = NULL;
203 	bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
204 	*hp = h;
205 	h->h_flags = hi->hi_flags;
206 	if (def)
207 		h->h_flags |= H_DEFAULT;
208 	if (cond)
209 		h->h_flags |= H_CHECK;
210 
211 	/* hack to see if this is a new format message */
212 	if (!def && !headeronly && bitset(H_RCPT|H_FROM, h->h_flags) &&
213 	    (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
214 	     strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
215 	{
216 		e->e_flags &= ~EF_OLDSTYLE;
217 	}
218 
219 	return (h->h_flags);
220 }
221 /*
222 **  ADDHEADER -- add a header entry to the end of the queue.
223 **
224 **	This bypasses the special checking of chompheader.
225 **
226 **	Parameters:
227 **		field -- the name of the header field.
228 **		value -- the value of the field.
229 **		hp -- an indirect pointer to the header structure list.
230 **
231 **	Returns:
232 **		none.
233 **
234 **	Side Effects:
235 **		adds the field on the list of headers for this envelope.
236 */
237 
238 addheader(field, value, hdrlist)
239 	char *field;
240 	char *value;
241 	HDR **hdrlist;
242 {
243 	register HDR *h;
244 	register struct hdrinfo *hi;
245 	HDR **hp;
246 
247 	/* find info struct */
248 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
249 	{
250 		if (strcasecmp(field, hi->hi_field) == 0)
251 			break;
252 	}
253 
254 	/* find current place in list -- keep back pointer? */
255 	for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
256 	{
257 		if (strcasecmp(field, h->h_field) == 0)
258 			break;
259 	}
260 
261 	/* allocate space for new header */
262 	h = (HDR *) xalloc(sizeof *h);
263 	h->h_field = field;
264 	h->h_value = newstr(value);
265 	h->h_link = *hp;
266 	h->h_flags = hi->hi_flags | H_DEFAULT;
267 	clrbitmap(h->h_mflags);
268 	*hp = h;
269 }
270 /*
271 **  HVALUE -- return value of a header.
272 **
273 **	Only "real" fields (i.e., ones that have not been supplied
274 **	as a default) are used.
275 **
276 **	Parameters:
277 **		field -- the field name.
278 **		header -- the header list.
279 **
280 **	Returns:
281 **		pointer to the value part.
282 **		NULL if not found.
283 **
284 **	Side Effects:
285 **		none.
286 */
287 
288 char *
289 hvalue(field, header)
290 	char *field;
291 	HDR *header;
292 {
293 	register HDR *h;
294 
295 	for (h = header; h != NULL; h = h->h_link)
296 	{
297 		if (!bitset(H_DEFAULT, h->h_flags) &&
298 		    strcasecmp(h->h_field, field) == 0)
299 			return (h->h_value);
300 	}
301 	return (NULL);
302 }
303 /*
304 **  ISHEADER -- predicate telling if argument is a header.
305 **
306 **	A line is a header if it has a single word followed by
307 **	optional white space followed by a colon.
308 **
309 **	Header fields beginning with two dashes, although technically
310 **	permitted by RFC822, are automatically rejected in order
311 **	to make MIME work out.  Without this we could have a technically
312 **	legal header such as ``--"foo:bar"'' that would also be a legal
313 **	MIME separator.
314 **
315 **	Parameters:
316 **		h -- string to check for possible headerness.
317 **
318 **	Returns:
319 **		TRUE if h is a header.
320 **		FALSE otherwise.
321 **
322 **	Side Effects:
323 **		none.
324 */
325 
326 bool
327 isheader(h)
328 	char *h;
329 {
330 	register char *s = h;
331 
332 	if (s[0] == '-' && s[1] == '-')
333 		return FALSE;
334 
335 	while (*s > ' ' && *s != ':' && *s != '\0')
336 		s++;
337 
338 	if (h == s)
339 		return FALSE;
340 
341 	/* following technically violates RFC822 */
342 	while (isascii(*s) && isspace(*s))
343 		s++;
344 
345 	return (*s == ':');
346 }
347 /*
348 **  EATHEADER -- run through the stored header and extract info.
349 **
350 **	Parameters:
351 **		e -- the envelope to process.
352 **		full -- if set, do full processing (e.g., compute
353 **			message priority).
354 **
355 **	Returns:
356 **		none.
357 **
358 **	Side Effects:
359 **		Sets a bunch of global variables from information
360 **			in the collected header.
361 **		Aborts the message if the hop count is exceeded.
362 */
363 
364 eatheader(e, full)
365 	register ENVELOPE *e;
366 	bool full;
367 {
368 	register HDR *h;
369 	register char *p;
370 	int hopcnt = 0;
371 	char *msgid;
372 	char buf[MAXLINE];
373 
374 	/*
375 	**  Set up macros for possible expansion in headers.
376 	*/
377 
378 	define('f', e->e_sender, e);
379 	define('g', e->e_sender, e);
380 	if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
381 		define('u', e->e_origrcpt, e);
382 	else
383 		define('u', NULL, e);
384 
385 	/* full name of from person */
386 	p = hvalue("full-name", e->e_header);
387 	if (p != NULL)
388 		define('x', p, e);
389 
390 	if (tTd(32, 1))
391 		printf("----- collected header -----\n");
392 	msgid = "<none>";
393 	for (h = e->e_header; h != NULL; h = h->h_link)
394 	{
395 		if (h->h_value == NULL)
396 		{
397 			if (tTd(32, 1))
398 				printf("%s: <NULL>\n", h->h_field);
399 			continue;
400 		}
401 
402 		/* do early binding */
403 		if (bitset(H_DEFAULT, h->h_flags))
404 		{
405 			expand(h->h_value, buf, sizeof buf, e);
406 			if (buf[0] != '\0')
407 			{
408 				h->h_value = newstr(buf);
409 				h->h_flags &= ~H_DEFAULT;
410 			}
411 		}
412 
413 		if (tTd(32, 1))
414 		{
415 			printf("%s: ", h->h_field);
416 			xputs(h->h_value);
417 			printf("\n");
418 		}
419 
420 		/* count the number of times it has been processed */
421 		if (bitset(H_TRACE, h->h_flags))
422 			hopcnt++;
423 
424 		/* send to this person if we so desire */
425 		if (GrabTo && bitset(H_RCPT, h->h_flags) &&
426 		    !bitset(H_DEFAULT, h->h_flags) &&
427 		    (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
428 		{
429 			int saveflags = e->e_flags;
430 
431 			(void) sendtolist(h->h_value, NULLADDR,
432 					  &e->e_sendqueue, 0, e);
433 
434 			/* delete fatal errors generated by this address */
435 			if (!GrabTo && !bitset(EF_FATALERRS, saveflags))
436 				e->e_flags &= ~EF_FATALERRS;
437 		}
438 
439 		/* save the message-id for logging */
440 		if (full && strcasecmp(h->h_field, "message-id") == 0)
441 		{
442 			msgid = h->h_value;
443 			while (isascii(*msgid) && isspace(*msgid))
444 				msgid++;
445 		}
446 
447 		/* see if this is a return-receipt header */
448 		if (bitset(H_RECEIPTTO, h->h_flags))
449 			e->e_receiptto = h->h_value;
450 	}
451 	if (tTd(32, 1))
452 		printf("----------------------------\n");
453 
454 	/* if we are just verifying (that is, sendmail -t -bv), drop out now */
455 	if (OpMode == MD_VERIFY)
456 		return;
457 
458 	/* store hop count */
459 	if (hopcnt > e->e_hopcount)
460 		e->e_hopcount = hopcnt;
461 
462 	/* message priority */
463 	p = hvalue("precedence", e->e_header);
464 	if (p != NULL)
465 		e->e_class = priencode(p);
466 	if (full)
467 	{
468 		e->e_msgpriority = e->e_msgsize
469 				 - e->e_class * WkClassFact
470 				 + e->e_nrcpts * WkRecipFact;
471 		if (e->e_class < 0)
472 			e->e_timeoutclass = TOC_NONURGENT;
473 		else if (e->e_class > 0)
474 			e->e_timeoutclass = TOC_URGENT;
475 	}
476 
477 	/* message timeout priority */
478 	p = hvalue("priority", e->e_header);
479 	if (full && p != NULL)
480 	{
481 		/* (this should be in the configuration file) */
482 		if (strcasecmp(p, "urgent"))
483 			e->e_timeoutclass = TOC_URGENT;
484 		else if (strcasecmp(p, "normal"))
485 			e->e_timeoutclass = TOC_NORMAL;
486 		else if (strcasecmp(p, "non-urgent"))
487 			e->e_timeoutclass = TOC_NONURGENT;
488 	}
489 
490 	/* date message originated */
491 	p = hvalue("posted-date", e->e_header);
492 	if (p == NULL)
493 		p = hvalue("date", e->e_header);
494 	if (p != NULL)
495 		define('a', p, e);
496 
497 	/*
498 	**  From person in antiquated ARPANET mode
499 	**	required by UK Grey Book e-mail gateways (sigh)
500 	*/
501 
502 	if (OpMode == MD_ARPAFTP)
503 	{
504 		register struct hdrinfo *hi;
505 
506 		for (hi = HdrInfo; hi->hi_field != NULL; hi++)
507 		{
508 			if (bitset(H_FROM, hi->hi_flags) &&
509 			    (!bitset(H_RESENT, hi->hi_flags) ||
510 			     bitset(EF_RESENT, e->e_flags)) &&
511 			    (p = hvalue(hi->hi_field, e->e_header)) != NULL)
512 				break;
513 		}
514 		if (hi->hi_field != NULL)
515 		{
516 			if (tTd(32, 2))
517 				printf("eatheader: setsender(*%s == %s)\n",
518 					hi->hi_field, p);
519 			setsender(p, e, NULL, TRUE);
520 		}
521 	}
522 
523 	/*
524 	**  Log collection information.
525 	*/
526 
527 # ifdef LOG
528 	if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
529 		logsender(e, msgid);
530 # endif /* LOG */
531 	e->e_flags &= ~EF_LOGSENDER;
532 }
533 /*
534 **  LOGSENDER -- log sender information
535 **
536 **	Parameters:
537 **		e -- the envelope to log
538 **		msgid -- the message id
539 **
540 **	Returns:
541 **		none
542 */
543 
544 logsender(e, msgid)
545 	register ENVELOPE *e;
546 	char *msgid;
547 {
548 # ifdef LOG
549 	char *name;
550 	register char *sbp;
551 	register char *p;
552 	int l;
553 	char hbuf[MAXNAME + 1];
554 	char sbuf[MAXLINE + 1];
555 	char mbuf[MAXNAME + 1];
556 
557 	/* don't allow newlines in the message-id */
558 	if (msgid != NULL)
559 	{
560 		l = strlen(msgid);
561 		if (l > sizeof mbuf - 1)
562 			l = sizeof mbuf - 1;
563 		bcopy(msgid, mbuf, l);
564 		mbuf[l] = '\0';
565 		p = mbuf;
566 		while ((p = strchr(p, '\n')) != NULL)
567 			*p++ = ' ';
568 	}
569 
570 	if (bitset(EF_RESPONSE, e->e_flags))
571 		name = "[RESPONSE]";
572 	else if ((name = macvalue('_', e)) != NULL)
573 		;
574 	else if (RealHostName == NULL)
575 		name = "localhost";
576 	else if (RealHostName[0] == '[')
577 		name = RealHostName;
578 	else
579 	{
580 		name = hbuf;
581 		(void) sprintf(hbuf, "%.80s", RealHostName);
582 		if (RealHostAddr.sa.sa_family != 0)
583 		{
584 			p = &hbuf[strlen(hbuf)];
585 			(void) sprintf(p, " (%s)",
586 				anynet_ntoa(&RealHostAddr));
587 		}
588 	}
589 
590 	/* some versions of syslog only take 5 printf args */
591 #  if (SYSLOG_BUFSIZE) >= 256
592 	sbp = sbuf;
593 	sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d",
594 	    e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
595 	    e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts);
596 	sbp += strlen(sbp);
597 	if (msgid != NULL)
598 	{
599 		sprintf(sbp, ", msgid=%.100s", mbuf);
600 		sbp += strlen(sbp);
601 	}
602 	if (e->e_bodytype != NULL)
603 	{
604 		(void) sprintf(sbp, ", bodytype=%.20s", e->e_bodytype);
605 		sbp += strlen(sbp);
606 	}
607 	p = macvalue('r', e);
608 	if (p != NULL)
609 		(void) sprintf(sbp, ", proto=%.20s", p);
610 	syslog(LOG_INFO, "%s: %s, relay=%s",
611 	    e->e_id, sbuf, name);
612 
613 #  else			/* short syslog buffer */
614 
615 	syslog(LOG_INFO, "%s: from=%s",
616 		e->e_id, e->e_from.q_paddr == NULL ? "<NONE>" :
617 				shortenstring(e->e_from.q_paddr, 83));
618 	syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d",
619 		e->e_id, e->e_msgsize, e->e_class,
620 		e->e_msgpriority, e->e_nrcpts);
621 	if (msgid != NULL)
622 		syslog(LOG_INFO, "%s: msgid=%s", e->e_id, mbuf);
623 	sbp = sbuf;
624 	sprintf(sbp, "%s:", e->e_id);
625 	sbp += strlen(sbp);
626 	if (e->e_bodytype != NULL)
627 	{
628 		sprintf(sbp, " bodytype=%s,", e->e_bodytype);
629 		sbp += strlen(sbp);
630 	}
631 	p = macvalue('r', e);
632 	if (p != NULL)
633 	{
634 		sprintf(sbp, " proto=%s,", p);
635 		sbp += strlen(sbp);
636 	}
637 	syslog(LOG_INFO, "%s relay=%s", sbuf, name);
638 #  endif
639 # endif
640 }
641 /*
642 **  PRIENCODE -- encode external priority names into internal values.
643 **
644 **	Parameters:
645 **		p -- priority in ascii.
646 **
647 **	Returns:
648 **		priority as a numeric level.
649 **
650 **	Side Effects:
651 **		none.
652 */
653 
654 priencode(p)
655 	char *p;
656 {
657 	register int i;
658 
659 	for (i = 0; i < NumPriorities; i++)
660 	{
661 		if (!strcasecmp(p, Priorities[i].pri_name))
662 			return (Priorities[i].pri_val);
663 	}
664 
665 	/* unknown priority */
666 	return (0);
667 }
668 /*
669 **  CRACKADDR -- parse an address and turn it into a macro
670 **
671 **	This doesn't actually parse the address -- it just extracts
672 **	it and replaces it with "$g".  The parse is totally ad hoc
673 **	and isn't even guaranteed to leave something syntactically
674 **	identical to what it started with.  However, it does leave
675 **	something semantically identical.
676 **
677 **	This algorithm has been cleaned up to handle a wider range
678 **	of cases -- notably quoted and backslash escaped strings.
679 **	This modification makes it substantially better at preserving
680 **	the original syntax.
681 **
682 **	Parameters:
683 **		addr -- the address to be cracked.
684 **
685 **	Returns:
686 **		a pointer to the new version.
687 **
688 **	Side Effects:
689 **		none.
690 **
691 **	Warning:
692 **		The return value is saved in local storage and should
693 **		be copied if it is to be reused.
694 */
695 
696 char *
697 crackaddr(addr)
698 	register char *addr;
699 {
700 	register char *p;
701 	register char c;
702 	int cmtlev;
703 	int realcmtlev;
704 	int anglelev, realanglelev;
705 	int copylev;
706 	bool qmode;
707 	bool realqmode;
708 	bool skipping;
709 	bool putgmac = FALSE;
710 	bool quoteit = FALSE;
711 	bool gotangle = FALSE;
712 	register char *bp;
713 	char *buflim;
714 	static char buf[MAXNAME + 1];
715 
716 	if (tTd(33, 1))
717 		printf("crackaddr(%s)\n", addr);
718 
719 	/* strip leading spaces */
720 	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
721 		addr++;
722 
723 	/*
724 	**  Start by assuming we have no angle brackets.  This will be
725 	**  adjusted later if we find them.
726 	*/
727 
728 	bp = buf;
729 	buflim = &buf[sizeof buf - 5];
730 	p = addr;
731 	copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
732 	qmode = realqmode = FALSE;
733 
734 	while ((c = *p++) != '\0')
735 	{
736 		/*
737 		**  If the buffer is overful, go into a special "skipping"
738 		**  mode that tries to keep legal syntax but doesn't actually
739 		**  output things.
740 		*/
741 
742 		skipping = bp >= buflim;
743 
744 		if (copylev > 0 && !skipping)
745 			*bp++ = c;
746 
747 		/* check for backslash escapes */
748 		if (c == '\\')
749 		{
750 			/* arrange to quote the address */
751 			if (cmtlev <= 0 && !qmode)
752 				quoteit = TRUE;
753 
754 			if ((c = *p++) == '\0')
755 			{
756 				/* too far */
757 				p--;
758 				goto putg;
759 			}
760 			if (copylev > 0 && !skipping)
761 				*bp++ = c;
762 			goto putg;
763 		}
764 
765 		/* check for quoted strings */
766 		if (c == '"' && cmtlev <= 0)
767 		{
768 			qmode = !qmode;
769 			if (copylev > 0 && !skipping)
770 				realqmode = !realqmode;
771 			continue;
772 		}
773 		if (qmode)
774 			goto putg;
775 
776 		/* check for comments */
777 		if (c == '(')
778 		{
779 			cmtlev++;
780 
781 			/* allow space for closing paren */
782 			if (!skipping)
783 			{
784 				buflim--;
785 				realcmtlev++;
786 				if (copylev++ <= 0)
787 				{
788 					*bp++ = ' ';
789 					*bp++ = c;
790 				}
791 			}
792 		}
793 		if (cmtlev > 0)
794 		{
795 			if (c == ')')
796 			{
797 				cmtlev--;
798 				copylev--;
799 				if (!skipping)
800 				{
801 					realcmtlev--;
802 					buflim++;
803 				}
804 			}
805 			continue;
806 		}
807 		else if (c == ')')
808 		{
809 			/* syntax error: unmatched ) */
810 			if (copylev > 0 && !skipping)
811 				bp--;
812 		}
813 
814 		/* check for characters that may have to be quoted */
815 		if (strchr(".'@,;:\\()[]", c) != NULL)
816 		{
817 			/*
818 			**  If these occur as the phrase part of a <>
819 			**  construct, but are not inside of () or already
820 			**  quoted, they will have to be quoted.  Note that
821 			**  now (but don't actually do the quoting).
822 			*/
823 
824 			if (cmtlev <= 0 && !qmode)
825 				quoteit = TRUE;
826 		}
827 
828 		/* check for angle brackets */
829 		if (c == '<')
830 		{
831 			register char *q;
832 
833 			/* assume first of two angles is bogus */
834 			if (gotangle)
835 				quoteit = TRUE;
836 			gotangle = TRUE;
837 
838 			/* oops -- have to change our mind */
839 			anglelev = 1;
840 			if (!skipping)
841 				realanglelev = 1;
842 
843 			bp = buf;
844 			if (quoteit)
845 			{
846 				*bp++ = '"';
847 
848 				/* back up over the '<' and any spaces */
849 				--p;
850 				while (isascii(*--p) && isspace(*p))
851 					continue;
852 				p++;
853 			}
854 			for (q = addr; q < p; )
855 			{
856 				c = *q++;
857 				if (bp < buflim)
858 				{
859 					if (quoteit && c == '"')
860 						*bp++ = '\\';
861 					*bp++ = c;
862 				}
863 			}
864 			if (quoteit)
865 			{
866 				if (bp == &buf[1])
867 					bp--;
868 				else
869 					*bp++ = '"';
870 				while ((c = *p++) != '<')
871 				{
872 					if (bp < buflim)
873 						*bp++ = c;
874 				}
875 				*bp++ = c;
876 			}
877 			copylev = 0;
878 			putgmac = quoteit = FALSE;
879 			continue;
880 		}
881 
882 		if (c == '>')
883 		{
884 			if (anglelev > 0)
885 			{
886 				anglelev--;
887 				if (!skipping)
888 				{
889 					realanglelev--;
890 					buflim++;
891 				}
892 			}
893 			else if (!skipping)
894 			{
895 				/* syntax error: unmatched > */
896 				if (copylev > 0)
897 					bp--;
898 				quoteit = TRUE;
899 				continue;
900 			}
901 			if (copylev++ <= 0)
902 				*bp++ = c;
903 			continue;
904 		}
905 
906 		/* must be a real address character */
907 	putg:
908 		if (copylev <= 0 && !putgmac)
909 		{
910 			*bp++ = MACROEXPAND;
911 			*bp++ = 'g';
912 			putgmac = TRUE;
913 		}
914 	}
915 
916 	/* repair any syntactic damage */
917 	if (realqmode)
918 		*bp++ = '"';
919 	while (realcmtlev-- > 0)
920 		*bp++ = ')';
921 	while (realanglelev-- > 0)
922 		*bp++ = '>';
923 	*bp++ = '\0';
924 
925 	if (tTd(33, 1))
926 		printf("crackaddr=>`%s'\n", buf);
927 
928 	return (buf);
929 }
930 /*
931 **  PUTHEADER -- put the header part of a message from the in-core copy
932 **
933 **	Parameters:
934 **		mci -- the connection information.
935 **		h -- the header to put.
936 **		e -- envelope to use.
937 **
938 **	Returns:
939 **		none.
940 **
941 **	Side Effects:
942 **		none.
943 */
944 
945 /*
946  * Macro for fast max (not available in e.g. DG/UX, 386/ix).
947  */
948 #ifndef MAX
949 # define MAX(a,b) (((a)>(b))?(a):(b))
950 #endif
951 
952 putheader(mci, h, e)
953 	register MCI *mci;
954 	register HDR *h;
955 	register ENVELOPE *e;
956 {
957 	char buf[MAX(MAXLINE,BUFSIZ)];
958 	char obuf[MAXLINE];
959 
960 	if (tTd(34, 1))
961 		printf("--- putheader, mailer = %s ---\n",
962 			mci->mci_mailer->m_name);
963 
964 	mci->mci_flags |= MCIF_INHEADER;
965 	for (; h != NULL; h = h->h_link)
966 	{
967 		register char *p;
968 		extern bool bitintersect();
969 
970 		if (tTd(34, 11))
971 		{
972 			printf("  %s: ", h->h_field);
973 			xputs(h->h_value);
974 		}
975 
976 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
977 		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags))
978 		{
979 			if (tTd(34, 11))
980 				printf(" (skipped)\n");
981 			continue;
982 		}
983 
984 		/* handle Resent-... headers specially */
985 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
986 		{
987 			if (tTd(34, 11))
988 				printf(" (skipped (resent))\n");
989 			continue;
990 		}
991 
992 		/* suppress return receipts if requested */
993 		if (bitset(H_RECEIPTTO, h->h_flags) &&
994 		    bitset(EF_NORECEIPT, e->e_flags))
995 		{
996 			if (tTd(34, 11))
997 				printf(" (skipped (receipt))\n");
998 			continue;
999 		}
1000 
1001 		/* suppress Content-Transfer-Encoding: if we are MIMEing */
1002 		if (bitset(H_CTE, h->h_flags) &&
1003 		    bitset(MCIF_CVT8TO7, mci->mci_flags))
1004 		{
1005 			if (tTd(34, 11))
1006 				printf(" (skipped (content-transfer-encoding))\n");
1007 			continue;
1008 		}
1009 
1010 		/* macro expand value if generated internally */
1011 		p = h->h_value;
1012 		if (bitset(H_DEFAULT, h->h_flags))
1013 		{
1014 			expand(p, buf, sizeof buf, e);
1015 			p = buf;
1016 			if (p == NULL || *p == '\0')
1017 			{
1018 				if (tTd(34, 11))
1019 					printf(" (skipped -- null value)\n");
1020 				continue;
1021 			}
1022 		}
1023 
1024 		if (tTd(34, 11))
1025 			printf("\n");
1026 
1027 		if (bitset(H_STRIPVAL, h->h_flags))
1028 		{
1029 			/* empty field */
1030 			(void) sprintf(obuf, "%s:", h->h_field);
1031 			putline(obuf, mci);
1032 		}
1033 		else if (bitset(H_FROM|H_RCPT, h->h_flags))
1034 		{
1035 			/* address field */
1036 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1037 
1038 			if (bitset(H_FROM, h->h_flags))
1039 				oldstyle = FALSE;
1040 			commaize(h, p, oldstyle, mci, e);
1041 		}
1042 		else
1043 		{
1044 			/* vanilla header line */
1045 			register char *nlp;
1046 
1047 			(void) sprintf(obuf, "%s: ", h->h_field);
1048 			while ((nlp = strchr(p, '\n')) != NULL)
1049 			{
1050 				*nlp = '\0';
1051 				(void) strcat(obuf, p);
1052 				*nlp = '\n';
1053 				putline(obuf, mci);
1054 				p = ++nlp;
1055 				obuf[0] = '\0';
1056 			}
1057 			(void) strcat(obuf, p);
1058 			putline(obuf, mci);
1059 		}
1060 	}
1061 
1062 	/*
1063 	**  If we are converting this to a MIME message, add the
1064 	**  MIME headers.
1065 	*/
1066 
1067 	if (bitset(MM_MIME8BIT, MimeMode) &&
1068 	    bitset(EF_HAS8BIT, e->e_flags) &&
1069 	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
1070 	    !bitset(MCIF_CVT8TO7, mci->mci_flags))
1071 	{
1072 		if (hvalue("MIME-Version", e->e_header) == NULL)
1073 			putline("MIME-Version: 1.0", mci);
1074 		if (hvalue("Content-Type", e->e_header) == NULL)
1075 		{
1076 			sprintf(obuf, "Content-Type: text/plain; charset=%s",
1077 				defcharset(e));
1078 			putline(obuf, mci);
1079 		}
1080 		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
1081 			putline("Content-Transfer-Encoding: 8bit", mci);
1082 	}
1083 }
1084 /*
1085 **  COMMAIZE -- output a header field, making a comma-translated list.
1086 **
1087 **	Parameters:
1088 **		h -- the header field to output.
1089 **		p -- the value to put in it.
1090 **		oldstyle -- TRUE if this is an old style header.
1091 **		mci -- the connection information.
1092 **		e -- the envelope containing the message.
1093 **
1094 **	Returns:
1095 **		none.
1096 **
1097 **	Side Effects:
1098 **		outputs "p" to file "fp".
1099 */
1100 
1101 void
1102 commaize(h, p, oldstyle, mci, e)
1103 	register HDR *h;
1104 	register char *p;
1105 	bool oldstyle;
1106 	register MCI *mci;
1107 	register ENVELOPE *e;
1108 {
1109 	register char *obp;
1110 	int opos;
1111 	int omax;
1112 	bool firstone = TRUE;
1113 	char obuf[MAXLINE + 3];
1114 
1115 	/*
1116 	**  Output the address list translated by the
1117 	**  mailer and with commas.
1118 	*/
1119 
1120 	if (tTd(14, 2))
1121 		printf("commaize(%s: %s)\n", h->h_field, p);
1122 
1123 	obp = obuf;
1124 	(void) sprintf(obp, "%s: ", h->h_field);
1125 	opos = strlen(h->h_field) + 2;
1126 	obp += opos;
1127 	omax = mci->mci_mailer->m_linelimit - 2;
1128 	if (omax < 0 || omax > 78)
1129 		omax = 78;
1130 
1131 	/*
1132 	**  Run through the list of values.
1133 	*/
1134 
1135 	while (*p != '\0')
1136 	{
1137 		register char *name;
1138 		register int c;
1139 		char savechar;
1140 		int flags;
1141 		auto int stat;
1142 
1143 		/*
1144 		**  Find the end of the name.  New style names
1145 		**  end with a comma, old style names end with
1146 		**  a space character.  However, spaces do not
1147 		**  necessarily delimit an old-style name -- at
1148 		**  signs mean keep going.
1149 		*/
1150 
1151 		/* find end of name */
1152 		while ((isascii(*p) && isspace(*p)) || *p == ',')
1153 			p++;
1154 		name = p;
1155 		for (;;)
1156 		{
1157 			auto char *oldp;
1158 			char pvpbuf[PSBUFSIZE];
1159 
1160 			(void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
1161 				       sizeof pvpbuf, &oldp, NULL);
1162 			p = oldp;
1163 
1164 			/* look to see if we have an at sign */
1165 			while (*p != '\0' && isascii(*p) && isspace(*p))
1166 				p++;
1167 
1168 			if (*p != '@')
1169 			{
1170 				p = oldp;
1171 				break;
1172 			}
1173 			p += *p == '@' ? 1 : 2;
1174 			while (*p != '\0' && isascii(*p) && isspace(*p))
1175 				p++;
1176 		}
1177 		/* at the end of one complete name */
1178 
1179 		/* strip off trailing white space */
1180 		while (p >= name &&
1181 		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1182 			p--;
1183 		if (++p == name)
1184 			continue;
1185 		savechar = *p;
1186 		*p = '\0';
1187 
1188 		/* translate the name to be relative */
1189 		flags = RF_HEADERADDR|RF_ADDDOMAIN;
1190 		if (bitset(H_FROM, h->h_flags))
1191 			flags |= RF_SENDERADDR;
1192 #ifdef USERDB
1193 		else if (e->e_from.q_mailer != NULL &&
1194 			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
1195 		{
1196 			extern char *udbsender();
1197 
1198 			name = udbsender(name);
1199 		}
1200 #endif
1201 		stat = EX_OK;
1202 		name = remotename(name, mci->mci_mailer, flags, &stat, e);
1203 		if (*name == '\0')
1204 		{
1205 			*p = savechar;
1206 			continue;
1207 		}
1208 
1209 		/* output the name with nice formatting */
1210 		opos += strlen(name);
1211 		if (!firstone)
1212 			opos += 2;
1213 		if (opos > omax && !firstone)
1214 		{
1215 			(void) strcpy(obp, ",\n");
1216 			putline(obuf, mci);
1217 			obp = obuf;
1218 			(void) strcpy(obp, "        ");
1219 			opos = strlen(obp);
1220 			obp += opos;
1221 			opos += strlen(name);
1222 		}
1223 		else if (!firstone)
1224 		{
1225 			(void) strcpy(obp, ", ");
1226 			obp += 2;
1227 		}
1228 
1229 		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
1230 			*obp++ = c;
1231 		firstone = FALSE;
1232 		*p = savechar;
1233 	}
1234 	(void) strcpy(obp, "\n");
1235 	putline(obuf, mci);
1236 }
1237 /*
1238 **  COPYHEADER -- copy header list
1239 **
1240 **	This routine is the equivalent of newstr for header lists
1241 **
1242 **	Parameters:
1243 **		header -- list of header structures to copy.
1244 **
1245 **	Returns:
1246 **		a copy of 'header'.
1247 **
1248 **	Side Effects:
1249 **		none.
1250 */
1251 
1252 HDR *
1253 copyheader(header)
1254 	register HDR *header;
1255 {
1256 	register HDR *newhdr;
1257 	HDR *ret;
1258 	register HDR **tail = &ret;
1259 
1260 	while (header != NULL)
1261 	{
1262 		newhdr = (HDR *) xalloc(sizeof(HDR));
1263 		STRUCTCOPY(*header, *newhdr);
1264 		*tail = newhdr;
1265 		tail = &newhdr->h_link;
1266 		header = header->h_link;
1267 	}
1268 	*tail = NULL;
1269 
1270 	return ret;
1271 }
1272