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