1 # include "sendmail.h" 2 3 SCCSID(@(#)parseaddr.c 3.51 09/05/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 (MATCHZANY, MATCHANY, 383 ** MATCHONE, MATCHCLASS) then the address in avp matched is 384 ** saved away 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 or MATCHZANY we just extend the match and start 390 ** over again. 391 ** 392 ** When we finally match, we rewrite the address vector 393 ** and try over again. 394 ** 395 ** Parameters: 396 ** pvp -- pointer to token vector. 397 ** 398 ** Returns: 399 ** none. 400 ** 401 ** Side Effects: 402 ** pvp is modified. 403 */ 404 405 struct match 406 { 407 char **first; /* first token matched */ 408 char **last; /* last token matched */ 409 }; 410 411 # define MAXMATCH 9 /* max params per rewrite */ 412 413 414 rewrite(pvp, ruleset) 415 char **pvp; 416 int ruleset; 417 { 418 register char *ap; /* address pointer */ 419 register char *rp; /* rewrite pointer */ 420 register char **avp; /* address vector pointer */ 421 register char **rvp; /* rewrite vector pointer */ 422 register struct match *mlp; /* cur ptr into mlist */ 423 register struct rewrite *rwr; /* pointer to current rewrite rule */ 424 struct match mlist[MAXMATCH]; /* stores match on LHS */ 425 char *npvp[MAXATOM+1]; /* temporary space for rebuild */ 426 extern bool sameword(); 427 428 # ifdef DEBUG 429 if (tTd(21, 9)) 430 { 431 printf("rewrite: ruleset %d, original pvp:\n", ruleset); 432 printav(pvp); 433 } 434 # endif DEBUG 435 436 /* 437 ** Run through the list of rewrite rules, applying 438 ** any that match. 439 */ 440 441 for (rwr = RewriteRules[ruleset]; rwr != NULL; ) 442 { 443 # ifdef DEBUG 444 if (tTd(21, 12)) 445 { 446 printf("-----trying rule:\n"); 447 printav(rwr->r_lhs); 448 } 449 # endif DEBUG 450 451 /* try to match on this rule */ 452 mlp = mlist; 453 rvp = rwr->r_lhs; 454 avp = pvp; 455 while ((ap = *avp) != NULL || *rvp != NULL) 456 { 457 rp = *rvp; 458 # ifdef DEBUG 459 if (tTd(21, 35)) 460 { 461 printf("ap=\""); 462 xputs(ap); 463 printf("\", rp=\""); 464 xputs(rp); 465 printf("\"\n"); 466 } 467 # endif DEBUG 468 if (rp == NULL) 469 { 470 /* end-of-pattern before end-of-address */ 471 goto backup; 472 } 473 if (ap == NULL && *rp != MATCHZANY) 474 { 475 /* end-of-input */ 476 break; 477 } 478 479 switch (*rp) 480 { 481 register STAB *s; 482 register int class; 483 484 case MATCHCLASS: 485 /* match any token in a class */ 486 class = rp[1]; 487 if (!isalpha(class)) 488 goto backup; 489 if (isupper(class)) 490 class -= 'A'; 491 else 492 class -= 'a'; 493 s = stab(ap, ST_CLASS, ST_FIND); 494 if (s == NULL || (s->s_class & (1L << class)) == 0) 495 goto backup; 496 497 /* explicit fall-through */ 498 499 case MATCHONE: 500 case MATCHANY: 501 /* match exactly one token */ 502 mlp->first = avp; 503 mlp->last = avp++; 504 mlp++; 505 break; 506 507 case MATCHZANY: 508 /* match zero or more tokens */ 509 mlp->first = avp; 510 mlp->last = avp - 1; 511 mlp++; 512 break; 513 514 default: 515 /* must have exact match */ 516 if (!sameword(rp, ap)) 517 goto backup; 518 avp++; 519 break; 520 } 521 522 /* successful match on this token */ 523 rvp++; 524 continue; 525 526 backup: 527 /* match failed -- back up */ 528 while (--rvp >= rwr->r_lhs) 529 { 530 rp = *rvp; 531 if (*rp == MATCHANY || *rp == MATCHZANY) 532 { 533 /* extend binding and continue */ 534 avp = ++mlp[-1].last; 535 avp++; 536 rvp++; 537 break; 538 } 539 avp--; 540 if (*rp == MATCHONE || *rp == MATCHCLASS) 541 { 542 /* back out binding */ 543 mlp--; 544 } 545 } 546 547 if (rvp < rwr->r_lhs) 548 { 549 /* total failure to match */ 550 break; 551 } 552 } 553 554 /* 555 ** See if we successfully matched 556 */ 557 558 if (rvp >= rwr->r_lhs && *rvp == NULL) 559 { 560 rvp = rwr->r_rhs; 561 # ifdef DEBUG 562 if (tTd(21, 12)) 563 { 564 printf("-----rule matches:\n"); 565 printav(rvp); 566 } 567 # endif DEBUG 568 569 /* see if this is a "subroutine" call */ 570 rp = *rvp; 571 if (*rp == CALLSUBR) 572 { 573 rp = *++rvp; 574 # ifdef DEBUG 575 if (tTd(21, 2)) 576 printf("-----callsubr %s\n", rp); 577 # endif DEBUG 578 rewrite(pvp, atoi(rp)); 579 rwr = rwr->r_next; 580 continue; 581 } 582 583 /* substitute */ 584 for (rvp = rwr->r_rhs, avp = npvp; *rvp != NULL; rvp++) 585 { 586 rp = *rvp; 587 if (*rp == MATCHREPL) 588 { 589 register struct match *m; 590 register char **pp; 591 592 m = &mlist[rp[1] - '1']; 593 # ifdef DEBUG 594 if (tTd(21, 15)) 595 { 596 printf("$%c:", rp[1]); 597 pp = m->first; 598 while (pp <= m->last) 599 { 600 printf(" %x=\"", *pp); 601 (void) fflush(stdout); 602 printf("%s\"", *pp++); 603 } 604 printf("\n"); 605 } 606 # endif DEBUG 607 pp = m->first; 608 while (pp <= m->last) 609 { 610 if (avp >= &npvp[MAXATOM]) 611 { 612 syserr("rewrite: expansion too long"); 613 return; 614 } 615 *avp++ = *pp++; 616 } 617 } 618 else 619 { 620 if (avp >= &npvp[MAXATOM]) 621 { 622 syserr("rewrite: expansion too long"); 623 return; 624 } 625 *avp++ = rp; 626 } 627 } 628 *avp++ = NULL; 629 bmove((char *) npvp, (char *) pvp, (avp - npvp) * sizeof *avp); 630 # ifdef DEBUG 631 if (tTd(21, 4)) 632 { 633 char **vp; 634 635 printf("rewritten as `"); 636 for (vp = pvp; *vp != NULL; vp++) 637 { 638 if (vp != pvp) 639 printf("_"); 640 xputs(*vp); 641 } 642 printf("'\n"); 643 } 644 # endif DEBUG 645 if (**pvp == CANONNET || **pvp == CANONUSER) 646 break; 647 } 648 else 649 { 650 # ifdef DEBUG 651 if (tTd(21, 10)) 652 printf("----- rule fails\n"); 653 # endif DEBUG 654 rwr = rwr->r_next; 655 } 656 } 657 } 658 /* 659 ** BUILDADDR -- build address from token vector. 660 ** 661 ** Parameters: 662 ** tv -- token vector. 663 ** a -- pointer to address descriptor to fill. 664 ** If NULL, one will be allocated. 665 ** 666 ** Returns: 667 ** NULL if there was an error. 668 ** 'a' otherwise. 669 ** 670 ** Side Effects: 671 ** fills in 'a' 672 */ 673 674 ADDRESS * 675 buildaddr(tv, a) 676 register char **tv; 677 register ADDRESS *a; 678 { 679 static char buf[MAXNAME]; 680 struct mailer **mp; 681 register struct mailer *m; 682 extern bool sameword(); 683 684 if (a == NULL) 685 a = (ADDRESS *) xalloc(sizeof *a); 686 clear((char *) a, sizeof *a); 687 688 /* figure out what net/mailer to use */ 689 if (**tv != CANONNET) 690 { 691 syserr("buildaddr: no net"); 692 return (NULL); 693 } 694 tv++; 695 if (sameword(*tv, "error")) 696 { 697 if (**++tv != CANONUSER) 698 syserr("buildaddr: error: no user"); 699 buf[0] = '\0'; 700 while (*++tv != NULL) 701 { 702 if (buf[0] != '\0') 703 (void) strcat(buf, " "); 704 (void) strcat(buf, *tv); 705 } 706 usrerr(buf); 707 return (NULL); 708 } 709 for (mp = Mailer; (m = *mp++) != NULL; ) 710 { 711 if (sameword(m->m_name, *tv)) 712 break; 713 } 714 if (m == NULL) 715 { 716 syserr("buildaddr: unknown net %s", *tv); 717 return (NULL); 718 } 719 a->q_mailer = m; 720 721 /* figure out what host (if any) */ 722 tv++; 723 if (!bitset(M_LOCAL, m->m_flags)) 724 { 725 if (**tv++ != CANONHOST) 726 { 727 syserr("buildaddr: no host"); 728 return (NULL); 729 } 730 buf[0] = '\0'; 731 while (*tv != NULL && **tv != CANONUSER) 732 (void) strcat(buf, *tv++); 733 a->q_host = newstr(buf); 734 } 735 else 736 a->q_host = NULL; 737 738 /* figure out the user */ 739 if (**tv != CANONUSER) 740 { 741 syserr("buildaddr: no user"); 742 return (NULL); 743 } 744 cataddr(++tv, buf, sizeof buf); 745 a->q_user = buf; 746 747 return (a); 748 } 749 /* 750 ** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs) 751 ** 752 ** Parameters: 753 ** pvp -- parameter vector to rebuild. 754 ** buf -- buffer to build the string into. 755 ** sz -- size of buf. 756 ** 757 ** Returns: 758 ** none. 759 ** 760 ** Side Effects: 761 ** Destroys buf. 762 */ 763 764 cataddr(pvp, buf, sz) 765 char **pvp; 766 char *buf; 767 register int sz; 768 { 769 bool oatomtok = FALSE; 770 bool natomtok = FALSE; 771 register int i; 772 register char *p; 773 774 p = buf; 775 sz--; 776 if (*pvp != NULL && **pvp == CANONUSER) 777 pvp++; 778 while (*pvp != NULL && (i = strlen(*pvp)) < sz) 779 { 780 natomtok = (toktype(**pvp) == ATOM); 781 if (oatomtok && natomtok) 782 *p++ = SPACESUB; 783 (void) strcpy(p, *pvp); 784 oatomtok = natomtok; 785 p += i; 786 sz -= i; 787 pvp++; 788 } 789 *p = '\0'; 790 } 791 /* 792 ** SAMEADDR -- Determine if two addresses are the same 793 ** 794 ** This is not just a straight comparison -- if the mailer doesn't 795 ** care about the host we just ignore it, etc. 796 ** 797 ** Parameters: 798 ** a, b -- pointers to the internal forms to compare. 799 ** wildflg -- if TRUE, 'a' may have no user specified, 800 ** in which case it is to match anything. 801 ** 802 ** Returns: 803 ** TRUE -- they represent the same mailbox. 804 ** FALSE -- they don't. 805 ** 806 ** Side Effects: 807 ** none. 808 */ 809 810 bool 811 sameaddr(a, b, wildflg) 812 register ADDRESS *a; 813 register ADDRESS *b; 814 bool wildflg; 815 { 816 /* if they don't have the same mailer, forget it */ 817 if (a->q_mailer != b->q_mailer) 818 return (FALSE); 819 820 /* if the user isn't the same, we can drop out */ 821 if ((!wildflg || a->q_user[0] != '\0') && strcmp(a->q_user, b->q_user) != 0) 822 return (FALSE); 823 824 /* if the mailer ignores hosts, we have succeeded! */ 825 if (bitset(M_LOCAL, a->q_mailer->m_flags)) 826 return (TRUE); 827 828 /* otherwise compare hosts (but be careful for NULL ptrs) */ 829 if (a->q_host == NULL || b->q_host == NULL) 830 return (FALSE); 831 if (strcmp(a->q_host, b->q_host) != 0) 832 return (FALSE); 833 834 return (TRUE); 835 } 836 /* 837 ** PRINTADDR -- print address (for debugging) 838 ** 839 ** Parameters: 840 ** a -- the address to print 841 ** follow -- follow the q_next chain. 842 ** 843 ** Returns: 844 ** none. 845 ** 846 ** Side Effects: 847 ** none. 848 */ 849 850 # ifdef DEBUG 851 852 printaddr(a, follow) 853 register ADDRESS *a; 854 bool follow; 855 { 856 bool first = TRUE; 857 858 while (a != NULL) 859 { 860 first = FALSE; 861 printf("%x=", a); 862 (void) fflush(stdout); 863 printf("%s: mailer %d (%s), host `%s', user `%s'\n", a->q_paddr, 864 a->q_mailer->m_mno, a->q_mailer->m_name, a->q_host, a->q_user); 865 printf("\tnext=%x, flags=%o, rmailer %d, alias %x\n", a->q_next, 866 a->q_flags, a->q_rmailer, a->q_alias); 867 printf("\thome=\"%s\", fullname=\"%s\"\n", a->q_home, a->q_fullname); 868 869 if (!follow) 870 return; 871 a = a->q_next; 872 } 873 if (first) 874 printf("[NULL]\n"); 875 } 876 877 # endif DEBUG 878 /* 879 ** REMOTENAME -- return the name relative to the current mailer 880 ** 881 ** Parameters: 882 ** name -- the name to translate. 883 ** force -- if set, forces rewriting even if the mailer 884 ** does not request it. Used for rewriting 885 ** sender addresses. 886 ** 887 ** Returns: 888 ** the text string representing this address relative to 889 ** the receiving mailer. 890 ** 891 ** Side Effects: 892 ** none. 893 ** 894 ** Warnings: 895 ** The text string returned is tucked away locally; 896 ** copy it if you intend to save it. 897 */ 898 899 char * 900 remotename(name, m, force) 901 char *name; 902 struct mailer *m; 903 bool force; 904 { 905 static char buf[MAXNAME]; 906 char lbuf[MAXNAME]; 907 extern char *macvalue(); 908 char *oldf = macvalue('f'); 909 char *oldg = macvalue('g'); 910 extern char **prescan(); 911 register char **pvp; 912 extern ADDRESS *buildaddr(); 913 extern char *crackaddr(); 914 char *fancy; 915 916 # ifdef DEBUG 917 if (tTd(12, 1)) 918 printf("remotename(%s)\n", name); 919 # endif DEBUG 920 921 /* 922 ** First put this address into canonical form. 923 ** First turn it into a macro. 924 ** Then run it through ruleset 4. 925 ** If the mailer defines a rewriting set, run it through 926 ** there next. 927 ** The intent is that ruleset 4 puts the name into a 928 ** canonical form; the mailer's ruleset then 929 ** does any customization. 930 */ 931 932 /* save away the extraneous pretty stuff */ 933 fancy = crackaddr(name); 934 935 /* now run through ruleset four */ 936 pvp = prescan(name, '\0'); 937 if (pvp == NULL) 938 return (name); 939 rewrite(pvp, 4); 940 if (m->m_rwset > 0) 941 rewrite(pvp, m->m_rwset); 942 943 /* 944 ** See if this mailer wants the name to be rewritten. There are 945 ** many problems here, owing to the standards for doing replies. 946 ** In general, these names should only be rewritten if we are 947 ** sending to another host that runs sendmail. 948 */ 949 950 if (bitset(M_RELRCPT, m->m_flags) && !force) 951 { 952 /* 953 ** Do general rewriting of name. 954 ** This will also take care of doing global name 955 ** translation. 956 */ 957 958 rewrite(pvp, 1); 959 rewrite(pvp, 3); 960 961 /* make the name relative to the receiving mailer */ 962 cataddr(pvp, lbuf, sizeof lbuf); 963 define('f', lbuf); 964 expand(m->m_from, buf, &buf[sizeof buf - 1], CurEnv); 965 966 /* rewrite to get rid of garbage we added in the expand above */ 967 pvp = prescan(buf, '\0'); 968 if (pvp == NULL) 969 return (name); 970 rewrite(pvp, 2); 971 } 972 973 /* now add any comment info we had before back */ 974 cataddr(pvp, lbuf, sizeof lbuf); 975 define('g', lbuf); 976 expand(fancy, buf, &buf[sizeof buf - 1], CurEnv); 977 978 define('f', oldf); 979 define('g', oldg); 980 981 # ifdef DEBUG 982 if (tTd(12, 1)) 983 printf("remotename => `%s'\n", buf); 984 # endif DEBUG 985 return (buf); 986 } 987 /* 988 ** CANONNAME -- make name canonical 989 ** 990 ** This is used for SMTP and misc. printing. Given a print 991 ** address, it strips out comments, etc., and puts on exactly 992 ** one set of brackets. 993 ** 994 ** Parameters: 995 ** name -- the name to make canonical. 996 ** 997 ** Returns: 998 ** pointer to canonical name. 999 ** 1000 ** Side Effects: 1001 ** none. 1002 ** 1003 ** Warning: 1004 ** result is saved in static buf; future calls will trash it. 1005 */ 1006 1007 char * 1008 canonname(name) 1009 char *name; 1010 { 1011 static char nbuf[MAXNAME + 2]; 1012 register char **pvp; 1013 1014 pvp = prescan(name, '\0'); 1015 rewrite(pvp, 4); 1016 cataddr(pvp, nbuf + 1, MAXNAME); 1017 nbuf[0] = '<'; 1018 strcat(nbuf, ">"); 1019 return (nbuf); 1020 } 1021