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