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