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.34 (Berkeley) 05/11/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 		extern char *macvalue();
388 
389 		if (bitset(EF_RESPONSE, e->e_flags))
390 			name = "[RESPONSE]";
391 		else if ((name = macvalue('_', e)) != NULL)
392 			;
393 		else if (RealHostName[0] == '[')
394 			name = RealHostName;
395 		else
396 		{
397 			extern char *anynet_ntoa();
398 
399 			name = hbuf;
400 			(void) sprintf(hbuf, "%.80s", RealHostName);
401 			if (RealHostAddr.sa.sa_family != 0)
402 			{
403 				p = &hbuf[strlen(hbuf)];
404 				(void) sprintf(p, " (%s)",
405 					anynet_ntoa(&RealHostAddr));
406 			}
407 		}
408 
409 		/* some versions of syslog only take 5 printf args */
410 		sprintf(sbuf, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d, msgid=%.100s",
411 		    e->e_from.q_paddr, e->e_msgsize, e->e_class,
412 		    e->e_msgpriority, e->e_nrcpts, msgid);
413 		syslog(LOG_INFO, "%s: %s, relay=%s",
414 		    e->e_id, sbuf, name);
415 	}
416 # endif /* LOG */
417 }
418 /*
419 **  PRIENCODE -- encode external priority names into internal values.
420 **
421 **	Parameters:
422 **		p -- priority in ascii.
423 **
424 **	Returns:
425 **		priority as a numeric level.
426 **
427 **	Side Effects:
428 **		none.
429 */
430 
431 priencode(p)
432 	char *p;
433 {
434 	register int i;
435 
436 	for (i = 0; i < NumPriorities; i++)
437 	{
438 		if (!strcasecmp(p, Priorities[i].pri_name))
439 			return (Priorities[i].pri_val);
440 	}
441 
442 	/* unknown priority */
443 	return (0);
444 }
445 /*
446 **  CRACKADDR -- parse an address and turn it into a macro
447 **
448 **	This doesn't actually parse the address -- it just extracts
449 **	it and replaces it with "$g".  The parse is totally ad hoc
450 **	and isn't even guaranteed to leave something syntactically
451 **	identical to what it started with.  However, it does leave
452 **	something semantically identical.
453 **
454 **	This algorithm has been cleaned up to handle a wider range
455 **	of cases -- notably quoted and backslash escaped strings.
456 **	This modification makes it substantially better at preserving
457 **	the original syntax.
458 **
459 **	Parameters:
460 **		addr -- the address to be cracked.
461 **
462 **	Returns:
463 **		a pointer to the new version.
464 **
465 **	Side Effects:
466 **		none.
467 **
468 **	Warning:
469 **		The return value is saved in local storage and should
470 **		be copied if it is to be reused.
471 */
472 
473 char *
474 crackaddr(addr)
475 	register char *addr;
476 {
477 	register char *p;
478 	register char c;
479 	int cmtlev;
480 	int realcmtlev;
481 	int anglelev, realanglelev;
482 	int copylev;
483 	bool qmode;
484 	bool realqmode;
485 	bool skipping;
486 	bool putgmac = FALSE;
487 	bool quoteit = FALSE;
488 	register char *bp;
489 	char *buflim;
490 	static char buf[MAXNAME];
491 
492 	if (tTd(33, 1))
493 		printf("crackaddr(%s)\n", addr);
494 
495 	/* strip leading spaces */
496 	while (*addr != '\0' && isascii(*addr) && isspace(*addr))
497 		addr++;
498 
499 	/*
500 	**  Start by assuming we have no angle brackets.  This will be
501 	**  adjusted later if we find them.
502 	*/
503 
504 	bp = buf;
505 	buflim = &buf[sizeof buf - 5];
506 	p = addr;
507 	copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
508 	qmode = realqmode = FALSE;
509 
510 	while ((c = *p++) != '\0')
511 	{
512 		/*
513 		**  If the buffer is overful, go into a special "skipping"
514 		**  mode that tries to keep legal syntax but doesn't actually
515 		**  output things.
516 		*/
517 
518 		skipping = bp >= buflim;
519 
520 		if (copylev > 0 && !skipping)
521 			*bp++ = c;
522 
523 		/* check for backslash escapes */
524 		if (c == '\\')
525 		{
526 			/* arrange to quote the address */
527 			if (cmtlev <= 0 && !qmode)
528 				quoteit = TRUE;
529 
530 			if ((c = *p++) == '\0')
531 			{
532 				/* too far */
533 				p--;
534 				goto putg;
535 			}
536 			if (copylev > 0 && !skipping)
537 				*bp++ = c;
538 			goto putg;
539 		}
540 
541 		/* check for quoted strings */
542 		if (c == '"')
543 		{
544 			qmode = !qmode;
545 			if (copylev > 0 && !skipping)
546 				realqmode = !realqmode;
547 			continue;
548 		}
549 		if (qmode)
550 			goto putg;
551 
552 		/* check for comments */
553 		if (c == '(')
554 		{
555 			cmtlev++;
556 
557 			/* allow space for closing paren */
558 			if (!skipping)
559 			{
560 				buflim--;
561 				realcmtlev++;
562 				if (copylev++ <= 0)
563 				{
564 					*bp++ = ' ';
565 					*bp++ = c;
566 				}
567 			}
568 		}
569 		if (cmtlev > 0)
570 		{
571 			if (c == ')')
572 			{
573 				cmtlev--;
574 				copylev--;
575 				if (!skipping)
576 				{
577 					realcmtlev--;
578 					buflim++;
579 				}
580 			}
581 			continue;
582 		}
583 		else if (c == ')')
584 		{
585 			/* syntax error: unmatched ) */
586 			if (!skipping)
587 				bp--;
588 		}
589 
590 
591 		/* check for characters that may have to be quoted */
592 		if (strchr(".'@,;:\\()", c) != NULL)
593 		{
594 			/*
595 			**  If these occur as the phrase part of a <>
596 			**  construct, but are not inside of () or already
597 			**  quoted, they will have to be quoted.  Note that
598 			**  now (but don't actually do the quoting).
599 			*/
600 
601 			if (cmtlev <= 0 && !qmode)
602 				quoteit = TRUE;
603 		}
604 
605 		/* check for angle brackets */
606 		if (c == '<')
607 		{
608 			register char *q;
609 
610 			/* oops -- have to change our mind */
611 			anglelev++;
612 			if (!skipping)
613 				realanglelev++;
614 
615 			bp = buf;
616 			if (quoteit)
617 			{
618 				*bp++ = '"';
619 
620 				/* back up over the '<' and any spaces */
621 				--p;
622 				while (isascii(*--p) && isspace(*p))
623 					continue;
624 				p++;
625 			}
626 			for (q = addr; q < p; )
627 			{
628 				c = *q++;
629 				if (bp < buflim)
630 				{
631 					if (quoteit && c == '"')
632 						*bp++ = '\\';
633 					*bp++ = c;
634 				}
635 			}
636 			if (quoteit)
637 			{
638 				*bp++ = '"';
639 				while ((c = *p++) != '<')
640 				{
641 					if (bp < buflim)
642 						*bp++ = c;
643 				}
644 				*bp++ = c;
645 			}
646 			copylev = 0;
647 			putgmac = quoteit = FALSE;
648 			continue;
649 		}
650 
651 		if (c == '>')
652 		{
653 			if (anglelev > 0)
654 			{
655 				anglelev--;
656 				if (!skipping)
657 				{
658 					realanglelev--;
659 					buflim++;
660 				}
661 			}
662 			else if (!skipping)
663 			{
664 				/* syntax error: unmatched > */
665 				if (copylev > 0)
666 					bp--;
667 				continue;
668 			}
669 			if (copylev++ <= 0)
670 				*bp++ = c;
671 			continue;
672 		}
673 
674 		/* must be a real address character */
675 	putg:
676 		if (copylev <= 0 && !putgmac)
677 		{
678 			*bp++ = MACROEXPAND;
679 			*bp++ = 'g';
680 			putgmac = TRUE;
681 		}
682 	}
683 
684 	/* repair any syntactic damage */
685 	if (realqmode)
686 		*bp++ = '"';
687 	while (realcmtlev-- > 0)
688 		*bp++ = ')';
689 	while (realanglelev-- > 0)
690 		*bp++ = '>';
691 	*bp++ = '\0';
692 
693 	if (tTd(33, 1))
694 		printf("crackaddr=>`%s'\n", buf);
695 
696 	return (buf);
697 }
698 /*
699 **  PUTHEADER -- put the header part of a message from the in-core copy
700 **
701 **	Parameters:
702 **		fp -- file to put it on.
703 **		m -- mailer to use.
704 **		e -- envelope to use.
705 **
706 **	Returns:
707 **		none.
708 **
709 **	Side Effects:
710 **		none.
711 */
712 
713 /*
714  * Macro for fast max (not available in e.g. DG/UX, 386/ix).
715  */
716 #ifndef MAX
717 # define MAX(a,b) (((a)>(b))?(a):(b))
718 #endif
719 
720 putheader(fp, m, e)
721 	register FILE *fp;
722 	register MAILER *m;
723 	register ENVELOPE *e;
724 {
725 	char buf[MAX(MAXLINE,BUFSIZ)];
726 	register HDR *h;
727 	char obuf[MAXLINE];
728 
729 	if (tTd(34, 1))
730 		printf("--- putheader, mailer = %s ---\n", m->m_name);
731 
732 	for (h = e->e_header; h != NULL; h = h->h_link)
733 	{
734 		register char *p;
735 		extern bool bitintersect();
736 
737 		if (tTd(34, 11))
738 		{
739 			printf("  %s: ", h->h_field);
740 			xputs(h->h_value);
741 		}
742 
743 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
744 		    !bitintersect(h->h_mflags, m->m_flags))
745 		{
746 			if (tTd(34, 11))
747 				printf(" (skipped)\n");
748 			continue;
749 		}
750 
751 		/* handle Resent-... headers specially */
752 		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
753 		{
754 			if (tTd(34, 11))
755 				printf(" (skipped (resent))\n");
756 			continue;
757 		}
758 		if (tTd(34, 11))
759 			printf("\n");
760 
761 		p = h->h_value;
762 		if (bitset(H_DEFAULT, h->h_flags))
763 		{
764 			/* macro expand value if generated internally */
765 			expand(p, buf, &buf[sizeof buf], e);
766 			p = buf;
767 			if (p == NULL || *p == '\0')
768 				continue;
769 		}
770 
771 		if (bitset(H_FROM|H_RCPT, h->h_flags))
772 		{
773 			/* address field */
774 			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
775 
776 			if (bitset(H_FROM, h->h_flags))
777 				oldstyle = FALSE;
778 			commaize(h, p, fp, oldstyle, m, e);
779 		}
780 		else
781 		{
782 			/* vanilla header line */
783 			register char *nlp;
784 
785 			(void) sprintf(obuf, "%s: ", h->h_field);
786 			while ((nlp = strchr(p, '\n')) != NULL)
787 			{
788 				*nlp = '\0';
789 				(void) strcat(obuf, p);
790 				*nlp = '\n';
791 				putline(obuf, fp, m);
792 				p = ++nlp;
793 				obuf[0] = '\0';
794 			}
795 			(void) strcat(obuf, p);
796 			putline(obuf, fp, m);
797 		}
798 	}
799 }
800 /*
801 **  COMMAIZE -- output a header field, making a comma-translated list.
802 **
803 **	Parameters:
804 **		h -- the header field to output.
805 **		p -- the value to put in it.
806 **		fp -- file to put it to.
807 **		oldstyle -- TRUE if this is an old style header.
808 **		m -- a pointer to the mailer descriptor.  If NULL,
809 **			don't transform the name at all.
810 **		e -- the envelope containing the message.
811 **
812 **	Returns:
813 **		none.
814 **
815 **	Side Effects:
816 **		outputs "p" to file "fp".
817 */
818 
819 commaize(h, p, fp, oldstyle, m, e)
820 	register HDR *h;
821 	register char *p;
822 	FILE *fp;
823 	bool oldstyle;
824 	register MAILER *m;
825 	register ENVELOPE *e;
826 {
827 	register char *obp;
828 	int opos;
829 	bool firstone = TRUE;
830 	char obuf[MAXLINE + 3];
831 
832 	/*
833 	**  Output the address list translated by the
834 	**  mailer and with commas.
835 	*/
836 
837 	if (tTd(14, 2))
838 		printf("commaize(%s: %s)\n", h->h_field, p);
839 
840 	obp = obuf;
841 	(void) sprintf(obp, "%s: ", h->h_field);
842 	opos = strlen(h->h_field) + 2;
843 	obp += opos;
844 
845 	/*
846 	**  Run through the list of values.
847 	*/
848 
849 	while (*p != '\0')
850 	{
851 		register char *name;
852 		register int c;
853 		char savechar;
854 		int flags;
855 		auto int stat;
856 		extern char *remotename();
857 
858 		/*
859 		**  Find the end of the name.  New style names
860 		**  end with a comma, old style names end with
861 		**  a space character.  However, spaces do not
862 		**  necessarily delimit an old-style name -- at
863 		**  signs mean keep going.
864 		*/
865 
866 		/* find end of name */
867 		while ((isascii(*p) && isspace(*p)) || *p == ',')
868 			p++;
869 		name = p;
870 		for (;;)
871 		{
872 			auto char *oldp;
873 			char pvpbuf[PSBUFSIZE];
874 			extern char **prescan();
875 
876 			(void) prescan(p, oldstyle ? ' ' : ',', pvpbuf, &oldp);
877 			p = oldp;
878 
879 			/* look to see if we have an at sign */
880 			while (*p != '\0' && isascii(*p) && isspace(*p))
881 				p++;
882 
883 			if (*p != '@')
884 			{
885 				p = oldp;
886 				break;
887 			}
888 			p += *p == '@' ? 1 : 2;
889 			while (*p != '\0' && isascii(*p) && isspace(*p))
890 				p++;
891 		}
892 		/* at the end of one complete name */
893 
894 		/* strip off trailing white space */
895 		while (p >= name &&
896 		       ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
897 			p--;
898 		if (++p == name)
899 			continue;
900 		savechar = *p;
901 		*p = '\0';
902 
903 		/* translate the name to be relative */
904 		flags = RF_HEADERADDR|RF_ADDDOMAIN;
905 		if (bitset(H_FROM, h->h_flags))
906 			flags |= RF_SENDERADDR;
907 		stat = EX_OK;
908 		name = remotename(name, m, flags, &stat, e);
909 		if (*name == '\0')
910 		{
911 			*p = savechar;
912 			continue;
913 		}
914 
915 		/* output the name with nice formatting */
916 		opos += strlen(name);
917 		if (!firstone)
918 			opos += 2;
919 		if (opos > 78 && !firstone)
920 		{
921 			(void) strcpy(obp, ",\n");
922 			putline(obuf, fp, m);
923 			obp = obuf;
924 			(void) sprintf(obp, "        ");
925 			opos = strlen(obp);
926 			obp += opos;
927 			opos += strlen(name);
928 		}
929 		else if (!firstone)
930 		{
931 			(void) sprintf(obp, ", ");
932 			obp += 2;
933 		}
934 
935 		while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
936 			*obp++ = c;
937 		firstone = FALSE;
938 		*p = savechar;
939 	}
940 	(void) strcpy(obp, "\n");
941 	putline(obuf, fp, m);
942 }
943 /*
944 **  COPYHEADER -- copy header list
945 **
946 **	This routine is the equivalent of newstr for header lists
947 **
948 **	Parameters:
949 **		header -- list of header structures to copy.
950 **
951 **	Returns:
952 **		a copy of 'header'.
953 **
954 **	Side Effects:
955 **		none.
956 */
957 
958 HDR *
959 copyheader(header)
960 	register HDR *header;
961 {
962 	register HDR *newhdr;
963 	HDR *ret;
964 	register HDR **tail = &ret;
965 
966 	while (header != NULL)
967 	{
968 		newhdr = (HDR *) xalloc(sizeof(HDR));
969 		STRUCTCOPY(*header, *newhdr);
970 		*tail = newhdr;
971 		tail = &newhdr->h_link;
972 		header = header->h_link;
973 	}
974 	*tail = NULL;
975 
976 	return ret;
977 }
978