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