1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)headers.c	6.35 (Berkeley) 05/27/93";
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 **		e -- the envelope including this header.
25 **
26 **	Returns:
27 **		flags for this header.
28 **
29 **	Side Effects:
30 **		The header is saved on the header list.
31 **		Contents of 'line' are destroyed.
32 */
33 
34 chompheader(line, def, e)
35 	char *line;
36 	bool def;
37 	register ENVELOPE *e;
38 {
39 	register char *p;
40 	register HDR *h;
41 	HDR **hp;
42 	char *fname;
43 	char *fvalue;
44 	struct hdrinfo *hi;
45 	bool cond = FALSE;
46 	BITMAP mopts;
47 
48 	if (tTd(31, 6))
49 		printf("chompheader: %s\n", line);
50 
51 	/* strip off options */
52 	clrbitmap(mopts);
53 	p = line;
54 	if (*p == '?')
55 	{
56 		/* have some */
57 		register char *q = strchr(p + 1, *p);
58 
59 		if (q != NULL)
60 		{
61 			*q++ = '\0';
62 			while (*++p != '\0')
63 				setbitn(*p, mopts);
64 			p = q;
65 		}
66 		else
67 			usrerr("553 header syntax error, line \"%s\"", line);
68 		cond = TRUE;
69 	}
70 
71 	/* find canonical name */
72 	fname = p;
73 	p = strchr(p, ':');
74 	if (p == NULL)
75 	{
76 		syserr("553 header syntax error, line \"%s\"", line);
77 		return (0);
78 	}
79 	fvalue = &p[1];
80 	while (isascii(*--p) && isspace(*p))
81 		continue;
82 	*++p = '\0';
83 
84 	/* strip field value on front */
85 	if (*fvalue == ' ')
86 		fvalue++;
87 
88 	/* see if it is a known type */
89 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
90 	{
91 		if (strcasecmp(hi->hi_field, fname) == 0)
92 			break;
93 	}
94 
95 	/* see if this is a resent message */
96 	if (!def && bitset(H_RESENT, hi->hi_flags))
97 		e->e_flags |= EF_RESENT;
98 
99 	/* if this means "end of header" quit now */
100 	if (bitset(H_EOH, hi->hi_flags))
101 		return (hi->hi_flags);
102 
103 	/* drop explicit From: if same as what we would generate -- for MH */
104 	p = "resent-from";
105 	if (!bitset(EF_RESENT, e->e_flags))
106 		p += 7;
107 	if (!def && !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0)
108 	{
109 		if (e->e_from.q_paddr != NULL &&
110 		    strcmp(fvalue, e->e_from.q_paddr) == 0)
111 			return (hi->hi_flags);
112 	}
113 
114 	/* delete default value for this header */
115 	for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link)
116 	{
117 		if (strcasecmp(fname, h->h_field) == 0 &&
118 		    bitset(H_DEFAULT, h->h_flags) &&
119 		    !bitset(H_FORCE, h->h_flags))
120 			h->h_value = NULL;
121 	}
122 
123 	/* create a new node */
124 	h = (HDR *) xalloc(sizeof *h);
125 	h->h_field = newstr(fname);
126 	h->h_value = NULL;
127 	h->h_link = NULL;
128 	bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
129 	*hp = h;
130 	h->h_flags = hi->hi_flags;
131 	if (def)
132 		h->h_flags |= H_DEFAULT;
133 	if (cond)
134 		h->h_flags |= H_CHECK;
135 	if (h->h_value != NULL)
136 		free((char *) h->h_value);
137 	h->h_value = newstr(fvalue);
138 
139 	/* hack to see if this is a new format message */
140 	if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
141 	    (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
142 	     strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
143 	{
144 		e->e_flags &= ~EF_OLDSTYLE;
145 	}
146 
147 	return (h->h_flags);
148 }
149 /*
150 **  ADDHEADER -- add a header entry to the end of the queue.
151 **
152 **	This bypasses the special checking of chompheader.
153 **
154 **	Parameters:
155 **		field -- the name of the header field.
156 **		value -- the value of the field.
157 **		e -- the envelope to add them to.
158 **
159 **	Returns:
160 **		none.
161 **
162 **	Side Effects:
163 **		adds the field on the list of headers for this envelope.
164 */
165 
166 addheader(field, value, e)
167 	char *field;
168 	char *value;
169 	ENVELOPE *e;
170 {
171 	register HDR *h;
172 	register struct hdrinfo *hi;
173 	HDR **hp;
174 
175 	/* find info struct */
176 	for (hi = HdrInfo; hi->hi_field != NULL; hi++)
177 	{
178 		if (strcasecmp(field, hi->hi_field) == 0)
179 			break;
180 	}
181 
182 	/* find current place in list -- keep back pointer? */
183 	for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link)
184 	{
185 		if (strcasecmp(field, h->h_field) == 0)
186 			break;
187 	}
188 
189 	/* allocate space for new header */
190 	h = (HDR *) xalloc(sizeof *h);
191 	h->h_field = field;
192 	h->h_value = newstr(value);
193 	h->h_link = *hp;
194 	h->h_flags = hi->hi_flags | H_DEFAULT;
195 	clrbitmap(h->h_mflags);
196 	*hp = h;
197 }
198 /*
199 **  HVALUE -- return value of a header.
200 **
201 **	Only "real" fields (i.e., ones that have not been supplied
202 **	as a default) are used.
203 **
204 **	Parameters:
205 **		field -- the field name.
206 **		e -- the envelope containing the header.
207 **
208 **	Returns:
209 **		pointer to the value part.
210 **		NULL if not found.
211 **
212 **	Side Effects:
213 **		none.
214 */
215 
216 char *
217 hvalue(field, e)
218 	char *field;
219 	register ENVELOPE *e;
220 {
221 	register HDR *h;
222 
223 	for (h = e->e_header; h != NULL; h = h->h_link)
224 	{
225 		if (!bitset(H_DEFAULT, h->h_flags) &&
226 		    strcasecmp(h->h_field, field) == 0)
227 			return (h->h_value);
228 	}
229 	return (NULL);
230 }
231 /*
232 **  ISHEADER -- predicate telling if argument is a header.
233 **
234 **	A line is a header if it has a single word followed by
235 **	optional white space followed by a colon.
236 **
237 **	Parameters:
238 **		s -- string to check for possible headerness.
239 **
240 **	Returns:
241 **		TRUE if s is a header.
242 **		FALSE otherwise.
243 **
244 **	Side Effects:
245 **		none.
246 */
247 
248 bool
249 isheader(s)
250 	register char *s;
251 {
252 	while (*s > ' ' && *s != ':' && *s != '\0')
253 		s++;
254 
255 	/* following technically violates RFC822 */
256 	while (isascii(*s) && isspace(*s))
257 		s++;
258 
259 	return (*s == ':');
260 }
261 /*
262 **  EATHEADER -- run through the stored header and extract info.
263 **
264 **	Parameters:
265 **		e -- the envelope to process.
266 **		full -- if set, do full processing (e.g., compute
267 **			message priority).
268 **
269 **	Returns:
270 **		none.
271 **
272 **	Side Effects:
273 **		Sets a bunch of global variables from information
274 **			in the collected header.
275 **		Aborts the message if the hop count is exceeded.
276 */
277 
278 eatheader(e, full)
279 	register ENVELOPE *e;
280 	bool full;
281 {
282 	register HDR *h;
283 	register char *p;
284 	int hopcnt = 0;
285 	char *msgid;
286 	char buf[MAXLINE];
287 
288 	/*
289 	**  Set up macros for possible expansion in headers.
290 	*/
291 
292 	define('f', e->e_sender, e);
293 	define('g', e->e_sender, e);
294 
295 	if (tTd(32, 1))
296 		printf("----- collected header -----\n");
297 	msgid = "<none>";
298 	for (h = e->e_header; h != NULL; h = h->h_link)
299 	{
300 		/* do early binding */
301 		if (bitset(H_DEFAULT, h->h_flags) && h->h_value != NULL)
302 		{
303 			expand(h->h_value, buf, &buf[sizeof buf], e);
304 			if (buf[0] != '\0')
305 			{
306 				h->h_value = newstr(buf);
307 				h->h_flags &= ~H_DEFAULT;
308 			}
309 		}
310 
311 		if (tTd(32, 1))
312 			printf("%s: %s\n", h->h_field, h->h_value);
313 
314 		/* count the number of times it has been processed */
315 		if (bitset(H_TRACE, h->h_flags))
316 			hopcnt++;
317 
318 		/* send to this person if we so desire */
319 		if (GrabTo && bitset(H_RCPT, h->h_flags) &&
320 		    !bitset(H_DEFAULT, h->h_flags) &&
321 		    (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
322 		{
323 			(void) sendtolist(h->h_value, (ADDRESS *) NULL,
324 					  &e->e_sendqueue, e);
325 		}
326 
327 		/* save the message-id for logging */
328 		if (full && h->h_value != NULL &&
329 		    strcasecmp(h->h_field, "message-id") == 0)
330 		{
331 			msgid = h->h_value;
332 			while (isascii(*msgid) && isspace(*msgid))
333 				msgid++;
334 		}
335 
336 		/* see if this is a return-receipt header */
337 		if (bitset(H_RECEIPTTO, h->h_flags))
338 			e->e_receiptto = h->h_value;
339 
340 		/* see if this is an errors-to header */
341 		if (bitset(H_ERRORSTO, h->h_flags))
342 			(void) sendtolist(h->h_value, (ADDRESS *) NULL,
343 					  &e->e_errorqueue, e);
344 	}
345 	if (tTd(32, 1))
346 		printf("----------------------------\n");
347 
348 	/* if we are just verifying (that is, sendmail -t -bv), drop out now */
349 	if (OpMode == MD_VERIFY)
350 		return;
351 
352 	/* store hop count */
353 	if (hopcnt > e->e_hopcount)
354 		e->e_hopcount = hopcnt;
355 
356 	/* message priority */
357 	p = hvalue("precedence", e);
358 	if (p != NULL)
359 		e->e_class = priencode(p);
360 	if (full)
361 		e->e_msgpriority = e->e_msgsize
362 				 - e->e_class * WkClassFact
363 				 + e->e_nrcpts * WkRecipFact;
364 
365 	/* full name of from person */
366 	p = hvalue("full-name", e);
367 	if (p != NULL)
368 		define('x', p, e);
369 
370 	/* date message originated */
371 	p = hvalue("posted-date", e);
372 	if (p == NULL)
373 		p = hvalue("date", e);
374 	if (p != NULL)
375 		define('a', p, e);
376 
377 	/*
378 	**  Log collection information.
379 	*/
380 
381 # ifdef LOG
382 	if (full && LogLevel > 4)
383 	{
384 		char *name;
385 		char hbuf[MAXNAME];
386 		char sbuf[MAXLINE];
387 
388 		if (bitset(EF_RESPONSE, e->e_flags))
389 			name = "[RESPONSE]";
390 		else if ((name = macvalue('_', e)) != NULL)
391 			;
392 		else if (RealHostName[0] == '[')
393 			name = RealHostName;
394 		else
395 		{
396 			name = hbuf;
397 			(void) sprintf(hbuf, "%.80s", RealHostName);
398 			if (RealHostAddr.sa.sa_family != 0)
399 			{
400 				p = &hbuf[strlen(hbuf)];
401 				(void) sprintf(p, " (%s)",
402 					anynet_ntoa(&RealHostAddr));
403 			}
404 		}
405 
406 		/* some versions of syslog only take 5 printf args */
407 		sprintf(sbuf, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d, msgid=%.100s",
408 		    e->e_from.q_paddr, e->e_msgsize, e->e_class,
409 		    e->e_msgpriority, e->e_nrcpts, msgid);
410 		syslog(LOG_INFO, "%s: %s, relay=%s",
411 		    e->e_id, sbuf, name);
412 	}
413 # endif /* LOG */
414 }
415 /*
416 **  PRIENCODE -- encode external priority names into internal values.
417 **
418 **	Parameters:
419 **		p -- priority in ascii.
420 **
421 **	Returns:
422 **		priority as a numeric level.
423 **
424 **	Side Effects:
425 **		none.
426 */
427 
428 priencode(p)
429 	char *p;
430 {
431 	register int i;
432 
433 	for (i = 0; i < NumPriorities; i++)
434 	{
435 		if (!strcasecmp(p, Priorities[i].pri_name))
436 			return (Priorities[i].pri_val);
437 	}
438 
439 	/* unknown priority */
440 	return (0);
441 }
442 /*
443 **  CRACKADDR -- parse an address and turn it into a macro
444 **
445 **	This doesn't actually parse the address -- it just extracts
446 **	it and replaces it with "$g".  The parse is totally ad hoc
447 **	and isn't even guaranteed to leave something syntactically
448 **	identical to what it started with.  However, it does leave
449 **	something semantically identical.
450 **
451 **	This algorithm has been cleaned up to handle a wider range
452 **	of cases -- notably quoted and backslash escaped strings.
453 **	This modification makes it substantially better at preserving
454 **	the original syntax.
455 **
456 **	Parameters:
457 **		addr -- the address to be cracked.
458 **
459 **	Returns:
460 **		a pointer to the new version.
461 **
462 **	Side Effects:
463 **		none.
464 **
465 **	Warning:
466 **		The return value is saved in local storage and should
467 **		be copied if it is to be reused.
468 */
469 
470 char *
471 crackaddr(addr)
472 	register char *addr;
473 {
474 	register char *p;
475 	register char c;
476 	int cmtlev;
477 	int realcmtlev;
478 	int anglelev, realanglelev;
479 	int copylev;
480 	bool qmode;
481 	bool realqmode;
482 	bool skipping;
483 	bool putgmac = FALSE;
484 	bool quoteit = FALSE;
485 	register char *bp;
486 	char *buflim;
487 	static char buf[MAXNAME];
488 
489 	if (tTd(33, 1))
490 		printf("crackaddr(%s)\n", addr);
491 
492 	/* strip leading spaces */
493 	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
494 		addr++;
495 
496 	/*
497 	**  Start by assuming we have no angle brackets.  This will be
498 	**  adjusted later if we find them.
499 	*/
500 
501 	bp = buf;
502 	buflim = &buf[sizeof buf - 5];
503 	p = addr;
504 	copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
505 	qmode = realqmode = FALSE;
506 
507 	while ((c = *p++) != '\0')
508 	{
509 		/*
510 		**  If the buffer is overful, go into a special "skipping"
511 		**  mode that tries to keep legal syntax but doesn't actually
512 		**  output things.
513 		*/
514 
515 		skipping = bp >= buflim;
516 
517 		if (copylev > 0 && !skipping)
518 			*bp++ = c;
519 
520 		/* check for backslash escapes */
521 		if (c == '\\')
522 		{
523 			/* arrange to quote the address */
524 			if (cmtlev <= 0 && !qmode)
525 				quoteit = TRUE;
526 
527 			if ((c = *p++) == '\0')
528 			{
529 				/* too far */
530 				p--;
531 				goto putg;
532 			}
533 			if (copylev > 0 && !skipping)
534 				*bp++ = c;
535 			goto putg;
536 		}
537 
538 		/* check for quoted strings */
539 		if (c == '"')
540 		{
541 			qmode = !qmode;
542 			if (copylev > 0 && !skipping)
543 				realqmode = !realqmode;
544 			continue;
545 		}
546 		if (qmode)
547 			goto putg;
548 
549 		/* check for comments */
550 		if (c == '(')
551 		{
552 			cmtlev++;
553 
554 			/* allow space for closing paren */
555 			if (!skipping)
556 			{
557 				buflim--;
558 				realcmtlev++;
559 				if (copylev++ <= 0)
560 				{
561 					*bp++ = ' ';
562 					*bp++ = c;
563 				}
564 			}
565 		}
566 		if (cmtlev > 0)
567 		{
568 			if (c == ')')
569 			{
570 				cmtlev--;
571 				copylev--;
572 				if (!skipping)
573 				{
574 					realcmtlev--;
575 					buflim++;
576 				}
577 			}
578 			continue;
579 		}
580 		else if (c == ')')
581 		{
582 			/* syntax error: unmatched ) */
583 			if (!skipping)
584 				bp--;
585 		}
586 
587 
588 		/* check for characters that may have to be quoted */
589 		if (strchr(".'@,;:\\()", c) != NULL)
590 		{
591 			/*
592 			**  If these occur as the phrase part of a <>
593 			**  construct, but are not inside of () or already
594 			**  quoted, they will have to be quoted.  Note that
595 			**  now (but don't actually do the quoting).
596 			*/
597 
598 			if (cmtlev <= 0 && !qmode)
599 				quoteit = TRUE;
600 		}
601 
602 		/* check for angle brackets */
603 		if (c == '<')
604 		{
605 			register char *q;
606 
607 			/* oops -- have to change our mind */
608 			anglelev++;
609 			if (!skipping)
610 				realanglelev++;
611 
612 			bp = buf;
613 			if (quoteit)
614 			{
615 				*bp++ = '"';
616 
617 				/* back up over the '<' and any spaces */
618 				--p;
619 				while (isascii(*--p) && isspace(*p))
620 					continue;
621 				p++;
622 			}
623 			for (q = addr; q < p; )
624 			{
625 				c = *q++;
626 				if (bp < buflim)
627 				{
628 					if (quoteit && c == '"')
629 						*bp++ = '\\';
630 					*bp++ = c;
631 				}
632 			}
633 			if (quoteit)
634 			{
635 				*bp++ = '"';
636 				while ((c = *p++) != '<')
637 				{
638 					if (bp < buflim)
639 						*bp++ = c;
640 				}
641 				*bp++ = c;
642 			}
643 			copylev = 0;
644 			putgmac = quoteit = FALSE;
645 			continue;
646 		}
647 
648 		if (c == '>')
649 		{
650 			if (anglelev > 0)
651 			{
652 				anglelev--;
653 				if (!skipping)
654 				{
655 					realanglelev--;
656 					buflim++;
657 				}
658 			}
659 			else if (!skipping)
660 			{
661 				/* syntax error: unmatched > */
662 				if (copylev > 0)
663 					bp--;
664 				continue;
665 			}
666 			if (copylev++ <= 0)
667 				*bp++ = c;
668 			continue;
669 		}
670 
671 		/* must be a real address character */
672 	putg:
673 		if (copylev <= 0 && !putgmac)
674 		{
675 			*bp++ = MACROEXPAND;
676 			*bp++ = 'g';
677 			putgmac = TRUE;
678 		}
679 	}
680 
681 	/* repair any syntactic damage */
682 	if (realqmode)
683 		*bp++ = '"';
684 	while (realcmtlev-- > 0)
685 		*bp++ = ')';
686 	while (realanglelev-- > 0)
687 		*bp++ = '>';
688 	*bp++ = '\0';
689 
690 	if (tTd(33, 1))
691 		printf("crackaddr=>`%s'\n", buf);
692 
693 	return (buf);
694 }
695 /*
696 **  PUTHEADER -- put the header part of a message from the in-core copy
697 **
698 **	Parameters:
699 **		fp -- file to put it on.
700 **		m -- mailer to use.
701 **		e -- envelope to use.
702 **
703 **	Returns:
704 **		none.
705 **
706 **	Side Effects:
707 **		none.
708 */
709 
710 /*
711  * Macro for fast max (not available in e.g. DG/UX, 386/ix).
712  */
713 #ifndef MAX
714 # define MAX(a,b) (((a)>(b))?(a):(b))
715 #endif
716 
717 putheader(fp, m, e)
718 	register FILE *fp;
719 	register MAILER *m;
720 	register ENVELOPE *e;
721 {
722 	char buf[MAX(MAXLINE,BUFSIZ)];
723 	register HDR *h;
724 	char obuf[MAXLINE];
725 
726 	if (tTd(34, 1))
727 		printf("--- putheader, mailer = %s ---\n", m->m_name);
728 
729 	for (h = e->e_header; h != NULL; h = h->h_link)
730 	{
731 		register char *p;
732 		extern bool bitintersect();
733 
734 		if (tTd(34, 11))
735 		{
736 			printf("  %s: ", h->h_field);
737 			xputs(h->h_value);
738 		}
739 
740 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
741 		    !bitintersect(h->h_mflags, m->m_flags))
742 		{
743 			if (tTd(34, 11))
744 				printf(" (skipped)\n");
745 			continue;
746 		}
747 
748 		/* handle Resent-... headers specially */
749 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
750 		{
751 			if (tTd(34, 11))
752 				printf(" (skipped (resent))\n");
753 			continue;
754 		}
755 		if (tTd(34, 11))
756 			printf("\n");
757 
758 		p = h->h_value;
759 		if (bitset(H_DEFAULT, h->h_flags))
760 		{
761 			/* macro expand value if generated internally */
762 			expand(p, buf, &buf[sizeof buf], e);
763 			p = buf;
764 			if (p == NULL || *p == '\0')
765 				continue;
766 		}
767 
768 		if (bitset(H_FROM|H_RCPT, h->h_flags))
769 		{
770 			/* address field */
771 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
772 
773 			if (bitset(H_FROM, h->h_flags))
774 				oldstyle = FALSE;
775 			commaize(h, p, fp, oldstyle, m, e);
776 		}
777 		else
778 		{
779 			/* vanilla header line */
780 			register char *nlp;
781 
782 			(void) sprintf(obuf, "%s: ", h->h_field);
783 			while ((nlp = strchr(p, '\n')) != NULL)
784 			{
785 				*nlp = '\0';
786 				(void) strcat(obuf, p);
787 				*nlp = '\n';
788 				putline(obuf, fp, m);
789 				p = ++nlp;
790 				obuf[0] = '\0';
791 			}
792 			(void) strcat(obuf, p);
793 			putline(obuf, fp, m);
794 		}
795 	}
796 }
797 /*
798 **  COMMAIZE -- output a header field, making a comma-translated list.
799 **
800 **	Parameters:
801 **		h -- the header field to output.
802 **		p -- the value to put in it.
803 **		fp -- file to put it to.
804 **		oldstyle -- TRUE if this is an old style header.
805 **		m -- a pointer to the mailer descriptor.  If NULL,
806 **			don't transform the name at all.
807 **		e -- the envelope containing the message.
808 **
809 **	Returns:
810 **		none.
811 **
812 **	Side Effects:
813 **		outputs "p" to file "fp".
814 */
815 
816 commaize(h, p, fp, oldstyle, m, e)
817 	register HDR *h;
818 	register char *p;
819 	FILE *fp;
820 	bool oldstyle;
821 	register MAILER *m;
822 	register ENVELOPE *e;
823 {
824 	register char *obp;
825 	int opos;
826 	bool firstone = TRUE;
827 	char obuf[MAXLINE + 3];
828 
829 	/*
830 	**  Output the address list translated by the
831 	**  mailer and with commas.
832 	*/
833 
834 	if (tTd(14, 2))
835 		printf("commaize(%s: %s)\n", h->h_field, p);
836 
837 	obp = obuf;
838 	(void) sprintf(obp, "%s: ", h->h_field);
839 	opos = strlen(h->h_field) + 2;
840 	obp += opos;
841 
842 	/*
843 	**  Run through the list of values.
844 	*/
845 
846 	while (*p != '\0')
847 	{
848 		register char *name;
849 		register int c;
850 		char savechar;
851 		int flags;
852 		auto int stat;
853 
854 		/*
855 		**  Find the end of the name.  New style names
856 		**  end with a comma, old style names end with
857 		**  a space character.  However, spaces do not
858 		**  necessarily delimit an old-style name -- at
859 		**  signs mean keep going.
860 		*/
861 
862 		/* find end of name */
863 		while ((isascii(*p) && isspace(*p)) || *p == ',')
864 			p++;
865 		name = p;
866 		for (;;)
867 		{
868 			auto char *oldp;
869 			char pvpbuf[PSBUFSIZE];
870 
871 			(void) prescan(p, oldstyle ? ' ' : ',', pvpbuf, &oldp);
872 			p = oldp;
873 
874 			/* look to see if we have an at sign */
875 			while (*p != '\0' && isascii(*p) && isspace(*p))
876 				p++;
877 
878 			if (*p != '@')
879 			{
880 				p = oldp;
881 				break;
882 			}
883 			p += *p == '@' ? 1 : 2;
884 			while (*p != '\0' && isascii(*p) && isspace(*p))
885 				p++;
886 		}
887 		/* at the end of one complete name */
888 
889 		/* strip off trailing white space */
890 		while (p >= name &&
891 		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
892 			p--;
893 		if (++p == name)
894 			continue;
895 		savechar = *p;
896 		*p = '\0';
897 
898 		/* translate the name to be relative */
899 		flags = RF_HEADERADDR|RF_ADDDOMAIN;
900 		if (bitset(H_FROM, h->h_flags))
901 			flags |= RF_SENDERADDR;
902 		stat = EX_OK;
903 		name = remotename(name, m, flags, &stat, e);
904 		if (*name == '\0')
905 		{
906 			*p = savechar;
907 			continue;
908 		}
909 
910 		/* output the name with nice formatting */
911 		opos += strlen(name);
912 		if (!firstone)
913 			opos += 2;
914 		if (opos > 78 && !firstone)
915 		{
916 			(void) strcpy(obp, ",\n");
917 			putline(obuf, fp, m);
918 			obp = obuf;
919 			(void) sprintf(obp, "        ");
920 			opos = strlen(obp);
921 			obp += opos;
922 			opos += strlen(name);
923 		}
924 		else if (!firstone)
925 		{
926 			(void) sprintf(obp, ", ");
927 			obp += 2;
928 		}
929 
930 		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
931 			*obp++ = c;
932 		firstone = FALSE;
933 		*p = savechar;
934 	}
935 	(void) strcpy(obp, "\n");
936 	putline(obuf, fp, m);
937 }
938 /*
939 **  COPYHEADER -- copy header list
940 **
941 **	This routine is the equivalent of newstr for header lists
942 **
943 **	Parameters:
944 **		header -- list of header structures to copy.
945 **
946 **	Returns:
947 **		a copy of 'header'.
948 **
949 **	Side Effects:
950 **		none.
951 */
952 
953 HDR *
954 copyheader(header)
955 	register HDR *header;
956 {
957 	register HDR *newhdr;
958 	HDR *ret;
959 	register HDR **tail = &ret;
960 
961 	while (header != NULL)
962 	{
963 		newhdr = (HDR *) xalloc(sizeof(HDR));
964 		STRUCTCOPY(*header, *newhdr);
965 		*tail = newhdr;
966 		tail = &newhdr->h_link;
967 		header = header->h_link;
968 	}
969 	*tail = NULL;
970 
971 	return ret;
972 }
973