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.56 (Berkeley) 04/09/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 	bool gotcolon = FALSE;
713 	register char *bp;
714 	char *buflim;
715 	char *bufhead;
716 	char *addrhead;
717 	static char buf[MAXNAME + 1];
718 
719 	if (tTd(33, 1))
720 		printf("crackaddr(%s)\n", addr);
721 
722 	/* strip leading spaces */
723 	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
724 		addr++;
725 
726 	/*
727 	**  Start by assuming we have no angle brackets.  This will be
728 	**  adjusted later if we find them.
729 	*/
730 
731 	bp = bufhead = buf;
732 	buflim = &buf[sizeof buf - 5];
733 	p = addrhead = addr;
734 	copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
735 	qmode = realqmode = FALSE;
736 
737 	while ((c = *p++) != '\0')
738 	{
739 		/*
740 		**  If the buffer is overful, go into a special "skipping"
741 		**  mode that tries to keep legal syntax but doesn't actually
742 		**  output things.
743 		*/
744 
745 		skipping = bp >= buflim;
746 
747 		if (copylev > 0 && !skipping)
748 			*bp++ = c;
749 
750 		/* check for backslash escapes */
751 		if (c == '\\')
752 		{
753 			/* arrange to quote the address */
754 			if (cmtlev <= 0 && !qmode)
755 				quoteit = TRUE;
756 
757 			if ((c = *p++) == '\0')
758 			{
759 				/* too far */
760 				p--;
761 				goto putg;
762 			}
763 			if (copylev > 0 && !skipping)
764 				*bp++ = c;
765 			goto putg;
766 		}
767 
768 		/* check for quoted strings */
769 		if (c == '"' && cmtlev <= 0)
770 		{
771 			qmode = !qmode;
772 			if (copylev > 0 && !skipping)
773 				realqmode = !realqmode;
774 			continue;
775 		}
776 		if (qmode)
777 			goto putg;
778 
779 		/* check for comments */
780 		if (c == '(')
781 		{
782 			cmtlev++;
783 
784 			/* allow space for closing paren */
785 			if (!skipping)
786 			{
787 				buflim--;
788 				realcmtlev++;
789 				if (copylev++ <= 0)
790 				{
791 					*bp++ = ' ';
792 					*bp++ = c;
793 				}
794 			}
795 		}
796 		if (cmtlev > 0)
797 		{
798 			if (c == ')')
799 			{
800 				cmtlev--;
801 				copylev--;
802 				if (!skipping)
803 				{
804 					realcmtlev--;
805 					buflim++;
806 				}
807 			}
808 			continue;
809 		}
810 		else if (c == ')')
811 		{
812 			/* syntax error: unmatched ) */
813 			if (copylev > 0 && !skipping)
814 				bp--;
815 		}
816 
817 		/* check for group: list; syntax */
818 		if (c == ':' && anglelev <= 0 && !gotcolon && !ColonOkInAddr)
819 		{
820 			register char *q;
821 
822 			if (*p == ':')
823 			{
824 				/* special case -- :: syntax */
825 				if (cmtlev <= 0 && !qmode)
826 					quoteit = TRUE;
827 				if (copylev > 0 && !skipping)
828 				{
829 					*bp++ = c;
830 					*bp++ = c;
831 				}
832 				p++;
833 				goto putg;
834 			}
835 
836 			gotcolon = TRUE;
837 
838 			bp = bufhead;
839 			if (quoteit)
840 			{
841 				*bp++ = '"';
842 
843 				/* back up over the ':' and any spaces */
844 				--p;
845 				while (isascii(*--p) && isspace(*p))
846 					continue;
847 				p++;
848 			}
849 			for (q = addrhead; q < p; )
850 			{
851 				c = *q++;
852 				if (bp < buflim)
853 				{
854 					if (quoteit && c == '"')
855 						*bp++ = '\\';
856 					*bp++ = c;
857 				}
858 			}
859 			if (quoteit)
860 			{
861 				if (bp == &bufhead[1])
862 					bp--;
863 				else
864 					*bp++ = '"';
865 				while ((c = *p++) != ':')
866 				{
867 					if (bp < buflim)
868 						*bp++ = c;
869 				}
870 				*bp++ = c;
871 			}
872 
873 			/* any trailing white space is part of group: */
874 			while (isascii(*p) && isspace(*p) && bp < buflim)
875 				*bp++ = *p++;
876 			copylev = 0;
877 			putgmac = quoteit = FALSE;
878 			bufhead = bp;
879 			addrhead = p;
880 			continue;
881 		}
882 
883 		if (c == ';' && copylev <= 0 && !ColonOkInAddr)
884 		{
885 			register char *q = p;
886 
887 			if (bp < buflim)
888 				*bp++ = c;
889 		}
890 
891 		/* check for characters that may have to be quoted */
892 		if (strchr(".'@,;:\\()[]", c) != NULL)
893 		{
894 			/*
895 			**  If these occur as the phrase part of a <>
896 			**  construct, but are not inside of () or already
897 			**  quoted, they will have to be quoted.  Note that
898 			**  now (but don't actually do the quoting).
899 			*/
900 
901 			if (cmtlev <= 0 && !qmode)
902 				quoteit = TRUE;
903 		}
904 
905 		/* check for angle brackets */
906 		if (c == '<')
907 		{
908 			register char *q;
909 
910 			/* assume first of two angles is bogus */
911 			if (gotangle)
912 				quoteit = TRUE;
913 			gotangle = TRUE;
914 
915 			/* oops -- have to change our mind */
916 			anglelev = 1;
917 			if (!skipping)
918 				realanglelev = 1;
919 
920 			bp = bufhead;
921 			if (quoteit)
922 			{
923 				*bp++ = '"';
924 
925 				/* back up over the '<' and any spaces */
926 				--p;
927 				while (isascii(*--p) && isspace(*p))
928 					continue;
929 				p++;
930 			}
931 			for (q = addrhead; q < p; )
932 			{
933 				c = *q++;
934 				if (bp < buflim)
935 				{
936 					if (quoteit && c == '"')
937 						*bp++ = '\\';
938 					*bp++ = c;
939 				}
940 			}
941 			if (quoteit)
942 			{
943 				if (bp == &buf[1])
944 					bp--;
945 				else
946 					*bp++ = '"';
947 				while ((c = *p++) != '<')
948 				{
949 					if (bp < buflim)
950 						*bp++ = c;
951 				}
952 				*bp++ = c;
953 			}
954 			copylev = 0;
955 			putgmac = quoteit = FALSE;
956 			continue;
957 		}
958 
959 		if (c == '>')
960 		{
961 			if (anglelev > 0)
962 			{
963 				anglelev--;
964 				if (!skipping)
965 				{
966 					realanglelev--;
967 					buflim++;
968 				}
969 			}
970 			else if (!skipping)
971 			{
972 				/* syntax error: unmatched > */
973 				if (copylev > 0)
974 					bp--;
975 				quoteit = TRUE;
976 				continue;
977 			}
978 			if (copylev++ <= 0)
979 				*bp++ = c;
980 			continue;
981 		}
982 
983 		/* must be a real address character */
984 	putg:
985 		if (copylev <= 0 && !putgmac)
986 		{
987 			*bp++ = MACROEXPAND;
988 			*bp++ = 'g';
989 			putgmac = TRUE;
990 		}
991 	}
992 
993 	/* repair any syntactic damage */
994 	if (realqmode)
995 		*bp++ = '"';
996 	while (realcmtlev-- > 0)
997 		*bp++ = ')';
998 	while (realanglelev-- > 0)
999 		*bp++ = '>';
1000 	*bp++ = '\0';
1001 
1002 	if (tTd(33, 1))
1003 		printf("crackaddr=>`%s'\n", buf);
1004 
1005 	return (buf);
1006 }
1007 /*
1008 **  PUTHEADER -- put the header part of a message from the in-core copy
1009 **
1010 **	Parameters:
1011 **		mci -- the connection information.
1012 **		h -- the header to put.
1013 **		e -- envelope to use.
1014 **
1015 **	Returns:
1016 **		none.
1017 **
1018 **	Side Effects:
1019 **		none.
1020 */
1021 
1022 /*
1023  * Macro for fast max (not available in e.g. DG/UX, 386/ix).
1024  */
1025 #ifndef MAX
1026 # define MAX(a,b) (((a)>(b))?(a):(b))
1027 #endif
1028 
1029 putheader(mci, h, e)
1030 	register MCI *mci;
1031 	register HDR *h;
1032 	register ENVELOPE *e;
1033 {
1034 	char buf[MAX(MAXLINE,BUFSIZ)];
1035 	char obuf[MAXLINE];
1036 
1037 	if (tTd(34, 1))
1038 		printf("--- putheader, mailer = %s ---\n",
1039 			mci->mci_mailer->m_name);
1040 
1041 	mci->mci_flags |= MCIF_INHEADER;
1042 	for (; h != NULL; h = h->h_link)
1043 	{
1044 		register char *p;
1045 		extern bool bitintersect();
1046 
1047 		if (tTd(34, 11))
1048 		{
1049 			printf("  %s: ", h->h_field);
1050 			xputs(h->h_value);
1051 		}
1052 
1053 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
1054 		    !bitintersect(h->h_mflags, mci->mci_mailer->m_flags))
1055 		{
1056 			if (tTd(34, 11))
1057 				printf(" (skipped)\n");
1058 			continue;
1059 		}
1060 
1061 		/* handle Resent-... headers specially */
1062 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
1063 		{
1064 			if (tTd(34, 11))
1065 				printf(" (skipped (resent))\n");
1066 			continue;
1067 		}
1068 
1069 		/* suppress return receipts if requested */
1070 		if (bitset(H_RECEIPTTO, h->h_flags) &&
1071 		    bitset(EF_NORECEIPT, e->e_flags))
1072 		{
1073 			if (tTd(34, 11))
1074 				printf(" (skipped (receipt))\n");
1075 			continue;
1076 		}
1077 
1078 		/* suppress Content-Transfer-Encoding: if we are MIMEing */
1079 		if (bitset(H_CTE, h->h_flags) &&
1080 		    bitset(MCIF_CVT8TO7, mci->mci_flags))
1081 		{
1082 			if (tTd(34, 11))
1083 				printf(" (skipped (content-transfer-encoding))\n");
1084 			continue;
1085 		}
1086 
1087 		/* macro expand value if generated internally */
1088 		p = h->h_value;
1089 		if (bitset(H_DEFAULT, h->h_flags))
1090 		{
1091 			expand(p, buf, sizeof buf, e);
1092 			p = buf;
1093 			if (p == NULL || *p == '\0')
1094 			{
1095 				if (tTd(34, 11))
1096 					printf(" (skipped -- null value)\n");
1097 				continue;
1098 			}
1099 		}
1100 
1101 		if (tTd(34, 11))
1102 			printf("\n");
1103 
1104 		if (bitset(H_STRIPVAL, h->h_flags))
1105 		{
1106 			/* empty field */
1107 			(void) sprintf(obuf, "%s:", h->h_field);
1108 			putline(obuf, mci);
1109 		}
1110 		else if (bitset(H_FROM|H_RCPT, h->h_flags))
1111 		{
1112 			/* address field */
1113 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1114 
1115 			if (bitset(H_FROM, h->h_flags))
1116 				oldstyle = FALSE;
1117 			commaize(h, p, oldstyle, mci, e);
1118 		}
1119 		else
1120 		{
1121 			/* vanilla header line */
1122 			register char *nlp;
1123 
1124 			(void) sprintf(obuf, "%s: ", h->h_field);
1125 			while ((nlp = strchr(p, '\n')) != NULL)
1126 			{
1127 				*nlp = '\0';
1128 				(void) strcat(obuf, p);
1129 				*nlp = '\n';
1130 				putline(obuf, mci);
1131 				p = ++nlp;
1132 				obuf[0] = '\0';
1133 			}
1134 			(void) strcat(obuf, p);
1135 			putline(obuf, mci);
1136 		}
1137 	}
1138 
1139 	/*
1140 	**  If we are converting this to a MIME message, add the
1141 	**  MIME headers.
1142 	*/
1143 
1144 	if (bitset(MM_MIME8BIT, MimeMode) &&
1145 	    bitset(EF_HAS8BIT, e->e_flags) &&
1146 	    !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
1147 	    !bitset(MCIF_CVT8TO7, mci->mci_flags))
1148 	{
1149 		if (hvalue("MIME-Version", e->e_header) == NULL)
1150 			putline("MIME-Version: 1.0", mci);
1151 		if (hvalue("Content-Type", e->e_header) == NULL)
1152 		{
1153 			sprintf(obuf, "Content-Type: text/plain; charset=%s",
1154 				defcharset(e));
1155 			putline(obuf, mci);
1156 		}
1157 		if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
1158 			putline("Content-Transfer-Encoding: 8bit", mci);
1159 	}
1160 }
1161 /*
1162 **  COMMAIZE -- output a header field, making a comma-translated list.
1163 **
1164 **	Parameters:
1165 **		h -- the header field to output.
1166 **		p -- the value to put in it.
1167 **		oldstyle -- TRUE if this is an old style header.
1168 **		mci -- the connection information.
1169 **		e -- the envelope containing the message.
1170 **
1171 **	Returns:
1172 **		none.
1173 **
1174 **	Side Effects:
1175 **		outputs "p" to file "fp".
1176 */
1177 
1178 void
1179 commaize(h, p, oldstyle, mci, e)
1180 	register HDR *h;
1181 	register char *p;
1182 	bool oldstyle;
1183 	register MCI *mci;
1184 	register ENVELOPE *e;
1185 {
1186 	register char *obp;
1187 	int opos;
1188 	int omax;
1189 	bool firstone = TRUE;
1190 	char obuf[MAXLINE + 3];
1191 
1192 	/*
1193 	**  Output the address list translated by the
1194 	**  mailer and with commas.
1195 	*/
1196 
1197 	if (tTd(14, 2))
1198 		printf("commaize(%s: %s)\n", h->h_field, p);
1199 
1200 	obp = obuf;
1201 	(void) sprintf(obp, "%s: ", h->h_field);
1202 	opos = strlen(h->h_field) + 2;
1203 	obp += opos;
1204 	omax = mci->mci_mailer->m_linelimit - 2;
1205 	if (omax < 0 || omax > 78)
1206 		omax = 78;
1207 
1208 	/*
1209 	**  Run through the list of values.
1210 	*/
1211 
1212 	while (*p != '\0')
1213 	{
1214 		register char *name;
1215 		register int c;
1216 		char savechar;
1217 		int flags;
1218 		auto int stat;
1219 
1220 		/*
1221 		**  Find the end of the name.  New style names
1222 		**  end with a comma, old style names end with
1223 		**  a space character.  However, spaces do not
1224 		**  necessarily delimit an old-style name -- at
1225 		**  signs mean keep going.
1226 		*/
1227 
1228 		/* find end of name */
1229 		while ((isascii(*p) && isspace(*p)) || *p == ',')
1230 			p++;
1231 		name = p;
1232 		for (;;)
1233 		{
1234 			auto char *oldp;
1235 			char pvpbuf[PSBUFSIZE];
1236 
1237 			(void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
1238 				       sizeof pvpbuf, &oldp, NULL);
1239 			p = oldp;
1240 
1241 			/* look to see if we have an at sign */
1242 			while (*p != '\0' && isascii(*p) && isspace(*p))
1243 				p++;
1244 
1245 			if (*p != '@')
1246 			{
1247 				p = oldp;
1248 				break;
1249 			}
1250 			p += *p == '@' ? 1 : 2;
1251 			while (*p != '\0' && isascii(*p) && isspace(*p))
1252 				p++;
1253 		}
1254 		/* at the end of one complete name */
1255 
1256 		/* strip off trailing white space */
1257 		while (p >= name &&
1258 		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
1259 			p--;
1260 		if (++p == name)
1261 			continue;
1262 		savechar = *p;
1263 		*p = '\0';
1264 
1265 		/* translate the name to be relative */
1266 		flags = RF_HEADERADDR|RF_ADDDOMAIN;
1267 		if (bitset(H_FROM, h->h_flags))
1268 			flags |= RF_SENDERADDR;
1269 #ifdef USERDB
1270 		else if (e->e_from.q_mailer != NULL &&
1271 			 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
1272 		{
1273 			extern char *udbsender();
1274 
1275 			name = udbsender(name);
1276 		}
1277 #endif
1278 		stat = EX_OK;
1279 		name = remotename(name, mci->mci_mailer, flags, &stat, e);
1280 		if (*name == '\0')
1281 		{
1282 			*p = savechar;
1283 			continue;
1284 		}
1285 
1286 		/* output the name with nice formatting */
1287 		opos += strlen(name);
1288 		if (!firstone)
1289 			opos += 2;
1290 		if (opos > omax && !firstone)
1291 		{
1292 			(void) strcpy(obp, ",\n");
1293 			putline(obuf, mci);
1294 			obp = obuf;
1295 			(void) strcpy(obp, "        ");
1296 			opos = strlen(obp);
1297 			obp += opos;
1298 			opos += strlen(name);
1299 		}
1300 		else if (!firstone)
1301 		{
1302 			(void) strcpy(obp, ", ");
1303 			obp += 2;
1304 		}
1305 
1306 		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
1307 			*obp++ = c;
1308 		firstone = FALSE;
1309 		*p = savechar;
1310 	}
1311 	(void) strcpy(obp, "\n");
1312 	putline(obuf, mci);
1313 }
1314 /*
1315 **  COPYHEADER -- copy header list
1316 **
1317 **	This routine is the equivalent of newstr for header lists
1318 **
1319 **	Parameters:
1320 **		header -- list of header structures to copy.
1321 **
1322 **	Returns:
1323 **		a copy of 'header'.
1324 **
1325 **	Side Effects:
1326 **		none.
1327 */
1328 
1329 HDR *
1330 copyheader(header)
1331 	register HDR *header;
1332 {
1333 	register HDR *newhdr;
1334 	HDR *ret;
1335 	register HDR **tail = &ret;
1336 
1337 	while (header != NULL)
1338 	{
1339 		newhdr = (HDR *) xalloc(sizeof(HDR));
1340 		STRUCTCOPY(*header, *newhdr);
1341 		*tail = newhdr;
1342 		tail = &newhdr->h_link;
1343 		header = header->h_link;
1344 	}
1345 	*tail = NULL;
1346 
1347 	return ret;
1348 }
1349