1 # include "sendmail.h"
2 
3 SCCSID(@(#)parseaddr.c	3.48		08/25/82);
4 
5 /*
6 **  PARSE -- Parse an address
7 **
8 **	Parses an address and breaks it up into three parts: a
9 **	net to transmit the message on, the host to transmit it
10 **	to, and a user on that host.  These are loaded into an
11 **	ADDRESS header with the values squirreled away if necessary.
12 **	The "user" part may not be a real user; the process may
13 **	just reoccur on that machine.  For example, on a machine
14 **	with an arpanet connection, the address
15 **		csvax.bill@berkeley
16 **	will break up to a "user" of 'csvax.bill' and a host
17 **	of 'berkeley' -- to be transmitted over the arpanet.
18 **
19 **	Parameters:
20 **		addr -- the address to parse.
21 **		a -- a pointer to the address descriptor buffer.
22 **			If NULL, a header will be created.
23 **		copyf -- determines what shall be copied:
24 **			-1 -- don't copy anything.  The printname
25 **				(q_paddr) is just addr, and the
26 **				user & host are allocated internally
27 **				to parse.
28 **			0 -- copy out the parsed user & host, but
29 **				don't copy the printname.
30 **			+1 -- copy everything.
31 **
32 **	Returns:
33 **		A pointer to the address descriptor header (`a' if
34 **			`a' is non-NULL).
35 **		NULL on error.
36 **
37 **	Side Effects:
38 **		none
39 */
40 
41 # define DELIMCHARS	"$()<>,;\\\"\r\n"	/* word delimiters */
42 
43 ADDRESS *
44 parse(addr, a, copyf)
45 	char *addr;
46 	register ADDRESS *a;
47 	int copyf;
48 {
49 	register char **pvp;
50 	register struct mailer *m;
51 	extern char **prescan();
52 	extern ADDRESS *buildaddr();
53 	static char nbuf[MAXNAME];
54 
55 	/*
56 	**  Initialize and prescan address.
57 	*/
58 
59 	CurEnv->e_to = addr;
60 # ifdef DEBUG
61 	if (tTd(20, 1))
62 		printf("\n--parse(%s)\n", addr);
63 # endif DEBUG
64 
65 	pvp = prescan(addr, '\0');
66 	if (pvp == NULL)
67 		return (NULL);
68 
69 	/*
70 	**  Apply rewriting rules.
71 	**	Ruleset 4 rewrites the address into a form that will
72 	**		be reflected in the outgoing message.  It must
73 	**		not resolve.
74 	**	Ruleset 0 does basic parsing.  It must resolve.
75 	*/
76 
77 	rewrite(pvp, 4);
78 	rewrite(pvp, 0);
79 
80 	/*
81 	**  See if we resolved to a real mailer.
82 	*/
83 
84 	if (pvp[0][0] != CANONNET)
85 	{
86 		setstat(EX_USAGE);
87 		usrerr("cannot resolve name");
88 		return (NULL);
89 	}
90 
91 	/*
92 	**  Build canonical address from pvp.
93 	*/
94 
95 	a = buildaddr(pvp, a);
96 	if (a == NULL)
97 		return (NULL);
98 	m = a->q_mailer;
99 
100 	/*
101 	**  Make local copies of the host & user and then
102 	**  transport them out.
103 	*/
104 
105 	if (copyf > 0)
106 		a->q_paddr = newstr(addr);
107 	else
108 		a->q_paddr = addr;
109 	if (copyf >= 0)
110 	{
111 		if (a->q_host != NULL)
112 			a->q_host = newstr(a->q_host);
113 		else
114 			a->q_host = "";
115 		if (a->q_user != a->q_paddr)
116 			a->q_user = newstr(a->q_user);
117 	}
118 
119 	/*
120 	**  Do UPPER->lower case mapping unless inhibited.
121 	*/
122 
123 	if (!bitset(M_HST_UPPER, m->m_flags))
124 		makelower(a->q_host);
125 	if (!bitset(M_USR_UPPER, m->m_flags))
126 		makelower(a->q_user);
127 
128 	/*
129 	**  Compute return value.
130 	*/
131 
132 # ifdef DEBUG
133 	if (tTd(20, 1))
134 	{
135 		printf("parse-->");
136 		printaddr(a, FALSE);
137 	}
138 # endif DEBUG
139 
140 	return (a);
141 }
142 /*
143 **  PRESCAN -- Prescan name and make it canonical
144 **
145 **	Scans a name and turns it into canonical form.  This involves
146 **	deleting blanks, comments (in parentheses), and turning the
147 **	word "at" into an at-sign ("@").  The name is copied as this
148 **	is done; it is legal to copy a name onto itself, since this
149 **	process can only make things smaller.
150 **
151 **	This routine knows about quoted strings and angle brackets.
152 **
153 **	There are certain subtleties to this routine.  The one that
154 **	comes to mind now is that backslashes on the ends of names
155 **	are silently stripped off; this is intentional.  The problem
156 **	is that some versions of sndmsg (like at LBL) set the kill
157 **	character to something other than @ when reading addresses;
158 **	so people type "csvax.eric\@berkeley" -- which screws up the
159 **	berknet mailer.
160 **
161 **	Parameters:
162 **		addr -- the name to chomp.
163 **		delim -- the delimiter for the address, normally
164 **			'\0' or ','; \0 is accepted in any case.
165 **			are moving in place; set buflim to high core.
166 **
167 **	Returns:
168 **		A pointer to a vector of tokens.
169 **		NULL on error.
170 **
171 **	Side Effects:
172 **		none.
173 */
174 
175 # define OPER		1
176 # define ATOM		2
177 # define EOTOK		3
178 # define QSTRING	4
179 # define SPACE		5
180 # define ONEMORE	6
181 # define GETONE		7
182 # define MACRO		8
183 
184 char **
185 prescan(addr, delim)
186 	char *addr;
187 	char delim;
188 {
189 	register char *p;
190 	static char buf[MAXNAME+MAXATOM];
191 	static char *av[MAXATOM+1];
192 	char **avp;
193 	bool bslashmode;
194 	int cmntcnt;
195 	register char c;
196 	char *tok;
197 	register char *q;
198 	register int state;
199 	int nstate;
200 	extern char lower();
201 
202 	q = buf;
203 	bslashmode = FALSE;
204 	cmntcnt = 0;
205 	avp = av;
206 	state = OPER;
207 	for (p = addr; *p != '\0' && *p != delim; )
208 	{
209 		/* read a token */
210 		tok = q;
211 		while ((c = *p++) != '\0' && c != delim)
212 		{
213 			/* chew up special characters */
214 			c &= ~0200;
215 			*q = '\0';
216 			if (bslashmode)
217 			{
218 				c |= 0200;
219 				bslashmode = FALSE;
220 			}
221 			else if (c == '\\')
222 			{
223 				bslashmode = TRUE;
224 				continue;
225 			}
226 			else if (c == '"')
227 			{
228 				if (state == QSTRING)
229 					state = OPER;
230 				else
231 					state = QSTRING;
232 				break;
233 			}
234 
235 			nstate = toktype(c);
236 			switch (state)
237 			{
238 			  case QSTRING:		/* in quoted string */
239 				break;
240 
241 			  case ATOM:		/* regular atom */
242 				if (nstate != ATOM)
243 				{
244 					state = EOTOK;
245 					p--;
246 				}
247 				break;
248 
249 			  case GETONE:		/* grab one character */
250 				state = OPER;
251 				break;
252 
253 			  case EOTOK:		/* after atom or q-string */
254 				state = nstate;
255 				if (state == SPACE)
256 					continue;
257 				break;
258 
259 			  case SPACE:		/* linear white space */
260 				state = nstate;
261 				break;
262 
263 			  case OPER:		/* operator */
264 				if (nstate == SPACE)
265 					continue;
266 				state = nstate;
267 				break;
268 
269 			  case ONEMORE:		/* $- etc. */
270 				state = GETONE;
271 				break;
272 
273 			  default:
274 				syserr("prescan: unknown state %d", state);
275 			}
276 
277 			if (state == EOTOK || state == SPACE)
278 				break;
279 
280 			/* squirrel it away */
281 			if (q >= &buf[sizeof buf - 5])
282 			{
283 				usrerr("Address too long");
284 				return (NULL);
285 			}
286 			*q++ = c;
287 
288 			/* decide whether this represents end of token */
289 			if (state == OPER || state == GETONE)
290 				break;
291 		}
292 		if (c == '\0' || c == delim)
293 			p--;
294 
295 		/* new token */
296 		if (tok == q)
297 			continue;
298 		*q++ = '\0';
299 
300 		c = tok[0];
301 		if (c == '(')
302 		{
303 			cmntcnt++;
304 			continue;
305 		}
306 		else if (c == ')')
307 		{
308 			if (cmntcnt <= 0)
309 			{
310 				usrerr("Unbalanced ')'");
311 				return (NULL);
312 			}
313 			else
314 			{
315 				cmntcnt--;
316 				continue;
317 			}
318 		}
319 		else if (cmntcnt > 0)
320 			continue;
321 
322 		if (avp >= &av[MAXATOM])
323 		{
324 			syserr("prescan: too many tokens");
325 			return (NULL);
326 		}
327 		*avp++ = tok;
328 	}
329 	*avp = NULL;
330 	if (cmntcnt > 0)
331 		usrerr("Unbalanced '('");
332 	else if (state == QSTRING)
333 		usrerr("Unbalanced '\"'");
334 	else if (av[0] != NULL)
335 		return (av);
336 	return (NULL);
337 }
338 /*
339 **  TOKTYPE -- return token type
340 **
341 **	Parameters:
342 **		c -- the character in question.
343 **
344 **	Returns:
345 **		Its type.
346 **
347 **	Side Effects:
348 **		none.
349 */
350 
351 toktype(c)
352 	register char c;
353 {
354 	static char buf[50];
355 	static bool firstime = TRUE;
356 
357 	if (firstime)
358 	{
359 		firstime = FALSE;
360 		expand("$o", buf, &buf[sizeof buf - 1], CurEnv);
361 		(void) strcat(buf, DELIMCHARS);
362 	}
363 	if (c == MATCHCLASS || c == MATCHREPL)
364 		return (ONEMORE);
365 	if (!isascii(c))
366 		return (ATOM);
367 	if (isspace(c))
368 		return (SPACE);
369 	if (iscntrl(c) || index(buf, c) != NULL)
370 		return (OPER);
371 	return (ATOM);
372 }
373 /*
374 **  REWRITE -- apply rewrite rules to token vector.
375 **
376 **	This routine is an ordered production system.  Each rewrite
377 **	rule has a LHS (called the pattern) and a RHS (called the
378 **	rewrite); 'rwr' points the the current rewrite rule.
379 **
380 **	For each rewrite rule, 'avp' points the address vector we
381 **	are trying to match against, and 'pvp' points to the pattern.
382 **	If pvp points to a special match value (MATCHANY, MATCHONE,
383 **	MATCHCLASS) then the address in avp matched is saved away
384 **	in the match vector (pointed to by 'mvp').
385 **
386 **	When a match between avp & pvp does not match, we try to
387 **	back out.  If we back up over a MATCHONE or a MATCHCLASS
388 **	we must also back out the match in mvp.  If we reach a
389 **	MATCHANY we just extend the match and start over again.
390 **
391 **	When we finally match, we rewrite the address vector
392 **	and try over again.
393 **
394 **	Parameters:
395 **		pvp -- pointer to token vector.
396 **
397 **	Returns:
398 **		none.
399 **
400 **	Side Effects:
401 **		pvp is modified.
402 */
403 
404 struct match
405 {
406 	char	**first;	/* first token matched */
407 	char	**last;		/* last token matched */
408 };
409 
410 # define MAXMATCH	9	/* max params per rewrite */
411 
412 
413 rewrite(pvp, ruleset)
414 	char **pvp;
415 	int ruleset;
416 {
417 	register char *ap;		/* address pointer */
418 	register char *rp;		/* rewrite pointer */
419 	register char **avp;		/* address vector pointer */
420 	register char **rvp;		/* rewrite vector pointer */
421 	struct rewrite *rwr;		/* pointer to current rewrite rule */
422 	struct match mlist[MAXMATCH];	/* stores match on LHS */
423 	struct match *mlp;		/* cur ptr into mlist */
424 	char *npvp[MAXATOM+1];		/* temporary space for rebuild */
425 	extern bool sameword();
426 
427 # ifdef DEBUG
428 	if (tTd(21, 9))
429 	{
430 		printf("rewrite: original pvp:\n");
431 		printav(pvp);
432 	}
433 # endif DEBUG
434 
435 	/*
436 	**  Run through the list of rewrite rules, applying
437 	**	any that match.
438 	*/
439 
440 	for (rwr = RewriteRules[ruleset]; rwr != NULL; )
441 	{
442 # ifdef DEBUG
443 		if (tTd(21, 12))
444 		{
445 			printf("-----trying rule:\n");
446 			printav(rwr->r_lhs);
447 		}
448 # endif DEBUG
449 
450 		/* try to match on this rule */
451 		mlp = mlist;
452 		for (rvp = rwr->r_lhs, avp = pvp; *avp != NULL; )
453 		{
454 			ap = *avp;
455 			rp = *rvp;
456 
457 			if (rp == NULL)
458 			{
459 				/* end-of-pattern before end-of-address */
460 				goto fail;
461 			}
462 
463 			switch (*rp)
464 			{
465 				register STAB *s;
466 				register int class;
467 
468 			  case MATCHCLASS:
469 				/* match any token in a class */
470 				class = rp[1];
471 				if (!isalpha(class))
472 					goto fail;
473 				if (isupper(class))
474 					class -= 'A';
475 				else
476 					class -= 'a';
477 				s = stab(ap, ST_CLASS, ST_FIND);
478 				if (s == NULL || (s->s_class & (1L << class)) == 0)
479 					goto fail;
480 
481 				/* explicit fall-through */
482 
483 			  case MATCHONE:
484 			  case MATCHANY:
485 				/* match exactly one token */
486 				mlp->first = mlp->last = avp++;
487 				mlp++;
488 				break;
489 
490 			  default:
491 				/* must have exact match */
492 				if (!sameword(rp, ap))
493 					goto fail;
494 				avp++;
495 				break;
496 			}
497 
498 			/* successful match on this token */
499 			rvp++;
500 			continue;
501 
502 		  fail:
503 			/* match failed -- back up */
504 			while (--rvp >= rwr->r_lhs)
505 			{
506 				rp = *rvp;
507 				if (*rp == MATCHANY)
508 				{
509 					/* extend binding and continue */
510 					mlp[-1].last = avp++;
511 					rvp++;
512 					break;
513 				}
514 				avp--;
515 				if (*rp == MATCHONE || *rp == MATCHCLASS)
516 				{
517 					/* back out binding */
518 					mlp--;
519 				}
520 			}
521 
522 			if (rvp < rwr->r_lhs)
523 			{
524 				/* total failure to match */
525 				break;
526 			}
527 		}
528 
529 		/*
530 		**  See if we successfully matched
531 		*/
532 
533 		if (rvp >= rwr->r_lhs && *rvp == NULL)
534 		{
535 # ifdef DEBUG
536 			if (tTd(21, 12))
537 			{
538 				printf("-----rule matches:\n");
539 				printav(rwr->r_rhs);
540 			}
541 # endif DEBUG
542 
543 			/* substitute */
544 			for (rvp = rwr->r_rhs, avp = npvp; *rvp != NULL; rvp++)
545 			{
546 				rp = *rvp;
547 				if (*rp == MATCHREPL)
548 				{
549 					register struct match *m;
550 					register char **pp;
551 
552 					m = &mlist[rp[1] - '1'];
553 # ifdef DEBUG
554 					if (tTd(21, 15))
555 					{
556 						printf("$%c:", rp[1]);
557 						pp = m->first;
558 						do
559 						{
560 							printf(" %x=\"", *pp);
561 							(void) fflush(stdout);
562 							printf("%s\"", *pp);
563 						} while (pp++ != m->last);
564 						printf("\n");
565 					}
566 # endif DEBUG
567 					pp = m->first;
568 					do
569 					{
570 						if (avp >= &npvp[MAXATOM])
571 						{
572 							syserr("rewrite: expansion too long");
573 							return;
574 						}
575 						*avp++ = *pp;
576 					} while (pp++ != m->last);
577 				}
578 				else
579 				{
580 					if (avp >= &npvp[MAXATOM])
581 					{
582 						syserr("rewrite: expansion too long");
583 						return;
584 					}
585 					*avp++ = rp;
586 				}
587 			}
588 			*avp++ = NULL;
589 			bmove((char *) npvp, (char *) pvp, (avp - npvp) * sizeof *avp);
590 # ifdef DEBUG
591 			if (tTd(21, 4))
592 			{
593 				char **vp;
594 
595 				printf("rewritten as `");
596 				for (vp = pvp; *vp != NULL; vp++)
597 				{
598 					if (vp != pvp)
599 						printf("_");
600 					xputs(*vp);
601 				}
602 				printf("'\n");
603 			}
604 # endif DEBUG
605 			if (pvp[0][0] == CANONNET)
606 				break;
607 		}
608 		else
609 		{
610 # ifdef DEBUG
611 			if (tTd(21, 10))
612 				printf("----- rule fails\n");
613 # endif DEBUG
614 			rwr = rwr->r_next;
615 		}
616 	}
617 }
618 /*
619 **  BUILDADDR -- build address from token vector.
620 **
621 **	Parameters:
622 **		tv -- token vector.
623 **		a -- pointer to address descriptor to fill.
624 **			If NULL, one will be allocated.
625 **
626 **	Returns:
627 **		NULL if there was an error.
628 **		'a' otherwise.
629 **
630 **	Side Effects:
631 **		fills in 'a'
632 */
633 
634 ADDRESS *
635 buildaddr(tv, a)
636 	register char **tv;
637 	register ADDRESS *a;
638 {
639 	static char buf[MAXNAME];
640 	struct mailer **mp;
641 	register struct mailer *m;
642 	extern bool sameword();
643 
644 	if (a == NULL)
645 		a = (ADDRESS *) xalloc(sizeof *a);
646 	clear((char *) a, sizeof *a);
647 
648 	/* figure out what net/mailer to use */
649 	if (**tv != CANONNET)
650 	{
651 		syserr("buildaddr: no net");
652 		return (NULL);
653 	}
654 	tv++;
655 	if (sameword(*tv, "error"))
656 	{
657 		if (**++tv != CANONUSER)
658 			syserr("buildaddr: error: no user");
659 		buf[0] = '\0';
660 		while (*++tv != NULL)
661 		{
662 			if (buf[0] != '\0')
663 				(void) strcat(buf, " ");
664 			(void) strcat(buf, *tv);
665 		}
666 		usrerr(buf);
667 		return (NULL);
668 	}
669 	for (mp = Mailer; (m = *mp++) != NULL; )
670 	{
671 		if (sameword(m->m_name, *tv))
672 			break;
673 	}
674 	if (m == NULL)
675 	{
676 		syserr("buildaddr: unknown net %s", *tv);
677 		return (NULL);
678 	}
679 	a->q_mailer = m;
680 
681 	/* figure out what host (if any) */
682 	tv++;
683 	if (!bitset(M_LOCAL, m->m_flags))
684 	{
685 		if (**tv++ != CANONHOST)
686 		{
687 			syserr("buildaddr: no host");
688 			return (NULL);
689 		}
690 		buf[0] = '\0';
691 		while (*tv != NULL && **tv != CANONUSER)
692 			(void) strcat(buf, *tv++);
693 		a->q_host = newstr(buf);
694 	}
695 	else
696 		a->q_host = NULL;
697 
698 	/* figure out the user */
699 	if (**tv != CANONUSER)
700 	{
701 		syserr("buildaddr: no user");
702 		return (NULL);
703 	}
704 	cataddr(++tv, buf, sizeof buf);
705 	a->q_user = buf;
706 
707 	return (a);
708 }
709 /*
710 **  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
711 **
712 **	Parameters:
713 **		pvp -- parameter vector to rebuild.
714 **		buf -- buffer to build the string into.
715 **		sz -- size of buf.
716 **
717 **	Returns:
718 **		none.
719 **
720 **	Side Effects:
721 **		Destroys buf.
722 */
723 
724 cataddr(pvp, buf, sz)
725 	char **pvp;
726 	char *buf;
727 	register int sz;
728 {
729 	bool oatomtok = FALSE;
730 	bool natomtok = FALSE;
731 	register int i;
732 	register char *p;
733 
734 	p = buf;
735 	sz--;
736 	while (*pvp != NULL && (i = strlen(*pvp)) < sz)
737 	{
738 		natomtok = (toktype(**pvp) == ATOM);
739 		if (oatomtok && natomtok)
740 			*p++ = SPACESUB;
741 		(void) strcpy(p, *pvp);
742 		oatomtok = natomtok;
743 		p += i;
744 		sz -= i;
745 		pvp++;
746 	}
747 	*p = '\0';
748 }
749 /*
750 **  SAMEADDR -- Determine if two addresses are the same
751 **
752 **	This is not just a straight comparison -- if the mailer doesn't
753 **	care about the host we just ignore it, etc.
754 **
755 **	Parameters:
756 **		a, b -- pointers to the internal forms to compare.
757 **		wildflg -- if TRUE, 'a' may have no user specified,
758 **			in which case it is to match anything.
759 **
760 **	Returns:
761 **		TRUE -- they represent the same mailbox.
762 **		FALSE -- they don't.
763 **
764 **	Side Effects:
765 **		none.
766 */
767 
768 bool
769 sameaddr(a, b, wildflg)
770 	register ADDRESS *a;
771 	register ADDRESS *b;
772 	bool wildflg;
773 {
774 	/* if they don't have the same mailer, forget it */
775 	if (a->q_mailer != b->q_mailer)
776 		return (FALSE);
777 
778 	/* if the user isn't the same, we can drop out */
779 	if ((!wildflg || a->q_user[0] != '\0') && strcmp(a->q_user, b->q_user) != 0)
780 		return (FALSE);
781 
782 	/* if the mailer ignores hosts, we have succeeded! */
783 	if (bitset(M_LOCAL, a->q_mailer->m_flags))
784 		return (TRUE);
785 
786 	/* otherwise compare hosts (but be careful for NULL ptrs) */
787 	if (a->q_host == NULL || b->q_host == NULL)
788 		return (FALSE);
789 	if (strcmp(a->q_host, b->q_host) != 0)
790 		return (FALSE);
791 
792 	return (TRUE);
793 }
794 /*
795 **  PRINTADDR -- print address (for debugging)
796 **
797 **	Parameters:
798 **		a -- the address to print
799 **		follow -- follow the q_next chain.
800 **
801 **	Returns:
802 **		none.
803 **
804 **	Side Effects:
805 **		none.
806 */
807 
808 # ifdef DEBUG
809 
810 printaddr(a, follow)
811 	register ADDRESS *a;
812 	bool follow;
813 {
814 	bool first = TRUE;
815 
816 	while (a != NULL)
817 	{
818 		first = FALSE;
819 		printf("%x=", a);
820 		(void) fflush(stdout);
821 		printf("%s: mailer %d (%s), host `%s', user `%s'\n", a->q_paddr,
822 		       a->q_mailer->m_mno, a->q_mailer->m_name, a->q_host, a->q_user);
823 		printf("\tnext=%x, flags=%o, rmailer %d, alias %x\n", a->q_next,
824 		       a->q_flags, a->q_rmailer, a->q_alias);
825 		printf("\thome=\"%s\", fullname=\"%s\"\n", a->q_home, a->q_fullname);
826 
827 		if (!follow)
828 			return;
829 		a = a->q_next;
830 	}
831 	if (first)
832 		printf("[NULL]\n");
833 }
834 
835 # endif DEBUG
836 /*
837 **  REMOTENAME -- return the name relative to the current mailer
838 **
839 **	Parameters:
840 **		name -- the name to translate.
841 **		force -- if set, forces rewriting even if the mailer
842 **			does not request it.  Used for rewriting
843 **			sender addresses.
844 **
845 **	Returns:
846 **		the text string representing this address relative to
847 **			the receiving mailer.
848 **
849 **	Side Effects:
850 **		none.
851 **
852 **	Warnings:
853 **		The text string returned is tucked away locally;
854 **			copy it if you intend to save it.
855 */
856 
857 char *
858 remotename(name, m, force)
859 	char *name;
860 	struct mailer *m;
861 	bool force;
862 {
863 	static char buf[MAXNAME];
864 	char lbuf[MAXNAME];
865 	extern char *macvalue();
866 	char *oldf = macvalue('f');
867 	char *oldg = macvalue('g');
868 	extern char **prescan();
869 	register char **pvp;
870 	extern ADDRESS *buildaddr();
871 	extern char *crackaddr();
872 	char *fancy;
873 
874 # ifdef DEBUG
875 	if (tTd(12, 1))
876 		printf("remotename(%s)\n", name);
877 # endif DEBUG
878 
879 	/*
880 	**  First put this address into canonical form.
881 	**	First turn it into a macro.
882 	**	Then run it through ruleset 4.
883 	*/
884 
885 	/* save away the extraneous pretty stuff */
886 	fancy = crackaddr(name);
887 
888 	/* now run through ruleset four */
889 	pvp = prescan(name, '\0');
890 	if (pvp == NULL)
891 		return (name);
892 	rewrite(pvp, 4);
893 
894 	/*
895 	**  See if this mailer wants the name to be rewritten.  There are
896 	**  many problems here, owing to the standards for doing replies.
897 	**  In general, these names should only be rewritten if we are
898 	**  sending to another host that runs sendmail.
899 	*/
900 
901 	if (bitset(M_RELRCPT, m->m_flags) && !force)
902 	{
903 		/*
904 		**  Do general rewriting of name.
905 		**	This will also take care of doing global name
906 		**	translation.
907 		*/
908 
909 		rewrite(pvp, 1);
910 		rewrite(pvp, 3);
911 
912 		/* make the name relative to the receiving mailer */
913 		cataddr(pvp, lbuf, sizeof lbuf);
914 		define('f', lbuf);
915 		expand(m->m_from, buf, &buf[sizeof buf - 1], CurEnv);
916 
917 		/* rewrite to get rid of garbage we added in the expand above */
918 		pvp = prescan(buf, '\0');
919 		if (pvp == NULL)
920 			return (name);
921 		rewrite(pvp, 2);
922 	}
923 
924 	/* now add any comment info we had before back */
925 	cataddr(pvp, lbuf, sizeof lbuf);
926 	define('g', lbuf);
927 	expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);
928 
929 	define('f', oldf);
930 	define('g', oldg);
931 
932 # ifdef DEBUG
933 	if (tTd(12, 1))
934 		printf("remotename => `%s'\n", buf);
935 # endif DEBUG
936 	return (buf);
937 }
938 /*
939 **  CANONNAME -- make name canonical
940 **
941 **	This is used for SMTP and misc. printing.  Given a print
942 **	address, it strips out comments, etc., and puts on exactly
943 **	one set of brackets.
944 **
945 **	Parameters:
946 **		name -- the name to make canonical.
947 **
948 **	Returns:
949 **		pointer to canonical name.
950 **
951 **	Side Effects:
952 **		none.
953 **
954 **	Warning:
955 **		result is saved in static buf; future calls will trash it.
956 */
957 
958 char *
959 canonname(name)
960 	char *name;
961 {
962 	static char nbuf[MAXNAME + 2];
963 
964 	if (name[0] == '<')
965 		return (name);
966 	strcpy(nbuf, "<");
967 	strcat(nbuf, name);
968 	strcat(nbuf, ">");
969 	return (nbuf);
970 }
971