13312Seric # include "sendmail.h" 2297Seric 3*4443Seric static char SccsId[] = "@(#)parseaddr.c 3.27 09/28/81"; 4407Seric 5297Seric /* 6297Seric ** PARSE -- Parse an address 7297Seric ** 8297Seric ** Parses an address and breaks it up into three parts: a 9297Seric ** net to transmit the message on, the host to transmit it 10297Seric ** to, and a user on that host. These are loaded into an 112973Seric ** ADDRESS header with the values squirreled away if necessary. 12297Seric ** The "user" part may not be a real user; the process may 13297Seric ** just reoccur on that machine. For example, on a machine 14297Seric ** with an arpanet connection, the address 15297Seric ** csvax.bill@berkeley 16297Seric ** will break up to a "user" of 'csvax.bill' and a host 17297Seric ** of 'berkeley' -- to be transmitted over the arpanet. 18297Seric ** 19297Seric ** Parameters: 20297Seric ** addr -- the address to parse. 21297Seric ** a -- a pointer to the address descriptor buffer. 22297Seric ** If NULL, a header will be created. 23297Seric ** copyf -- determines what shall be copied: 24297Seric ** -1 -- don't copy anything. The printname 25297Seric ** (q_paddr) is just addr, and the 26297Seric ** user & host are allocated internally 27297Seric ** to parse. 28297Seric ** 0 -- copy out the parsed user & host, but 29297Seric ** don't copy the printname. 30297Seric ** +1 -- copy everything. 31297Seric ** 32297Seric ** Returns: 33297Seric ** A pointer to the address descriptor header (`a' if 34297Seric ** `a' is non-NULL). 35297Seric ** NULL on error. 36297Seric ** 37297Seric ** Side Effects: 38297Seric ** none 39297Seric */ 40297Seric 413380Seric # define DELIMCHARS "$()<>,;\\\"\r\n" /* word delimiters */ 422091Seric 432973Seric ADDRESS * 44297Seric parse(addr, a, copyf) 45297Seric char *addr; 462973Seric register ADDRESS *a; 47297Seric int copyf; 48297Seric { 493149Seric register char **pvp; 503149Seric register struct mailer *m; 513149Seric extern char **prescan(); 523149Seric extern ADDRESS *buildaddr(); 53297Seric 54297Seric /* 55297Seric ** Initialize and prescan address. 56297Seric */ 57297Seric 58297Seric To = addr; 593188Seric # ifdef DEBUG 603188Seric if (Debug) 613188Seric printf("\n--parse(%s)\n", addr); 623188Seric # endif DEBUG 633188Seric 643149Seric pvp = prescan(addr, '\0'); 653149Seric if (pvp == NULL) 66297Seric return (NULL); 67297Seric 68297Seric /* 693149Seric ** Apply rewriting rules. 70297Seric */ 71297Seric 724070Seric rewrite(pvp, 0); 73297Seric 743149Seric /* 753149Seric ** See if we resolved to a real mailer. 763149Seric */ 77297Seric 783149Seric if (pvp[0][0] != CANONNET) 793149Seric { 803149Seric setstat(EX_USAGE); 813149Seric usrerr("cannot resolve name"); 823149Seric return (NULL); 83297Seric } 84297Seric 85297Seric /* 863149Seric ** Build canonical address from pvp. 87297Seric */ 88297Seric 893149Seric a = buildaddr(pvp, a); 904279Seric if (a == NULL) 914279Seric return (NULL); 923149Seric m = Mailer[a->q_mailer]; 93297Seric 94297Seric /* 953149Seric ** Make local copies of the host & user and then 963149Seric ** transport them out. 97297Seric */ 98297Seric 99297Seric if (copyf > 0) 1002973Seric a->q_paddr = newstr(addr); 101297Seric else 102297Seric a->q_paddr = addr; 103297Seric 1043149Seric if (copyf >= 0) 105297Seric { 1063149Seric if (a->q_host != NULL) 1073149Seric a->q_host = newstr(a->q_host); 108297Seric else 1093149Seric a->q_host = ""; 1103149Seric if (a->q_user != a->q_paddr) 1113149Seric a->q_user = newstr(a->q_user); 112297Seric } 113297Seric 114297Seric /* 115297Seric ** Do UPPER->lower case mapping unless inhibited. 116297Seric */ 117297Seric 1183149Seric if (!bitset(M_HST_UPPER, m->m_flags)) 119297Seric makelower(a->q_host); 1203149Seric if (!bitset(M_USR_UPPER, m->m_flags)) 121297Seric makelower(a->q_user); 122297Seric 123297Seric /* 124297Seric ** Compute return value. 125297Seric */ 126297Seric 127297Seric # ifdef DEBUG 1281583Seric if (Debug) 129*4443Seric { 130*4443Seric printf("parse-->"); 131*4443Seric printaddr(a, FALSE); 132*4443Seric } 133297Seric # endif DEBUG 134297Seric 135297Seric return (a); 136297Seric } 137297Seric /* 138297Seric ** PRESCAN -- Prescan name and make it canonical 139297Seric ** 140297Seric ** Scans a name and turns it into canonical form. This involves 141297Seric ** deleting blanks, comments (in parentheses), and turning the 142297Seric ** word "at" into an at-sign ("@"). The name is copied as this 143297Seric ** is done; it is legal to copy a name onto itself, since this 144297Seric ** process can only make things smaller. 145297Seric ** 146297Seric ** This routine knows about quoted strings and angle brackets. 147297Seric ** 148297Seric ** There are certain subtleties to this routine. The one that 149297Seric ** comes to mind now is that backslashes on the ends of names 150297Seric ** are silently stripped off; this is intentional. The problem 151297Seric ** is that some versions of sndmsg (like at LBL) set the kill 152297Seric ** character to something other than @ when reading addresses; 153297Seric ** so people type "csvax.eric\@berkeley" -- which screws up the 154297Seric ** berknet mailer. 155297Seric ** 156297Seric ** Parameters: 157297Seric ** addr -- the name to chomp. 158297Seric ** delim -- the delimiter for the address, normally 159297Seric ** '\0' or ','; \0 is accepted in any case. 160297Seric ** are moving in place; set buflim to high core. 161297Seric ** 162297Seric ** Returns: 1633149Seric ** A pointer to a vector of tokens. 164297Seric ** NULL on error. 165297Seric ** 166297Seric ** Side Effects: 1673149Seric ** none. 168297Seric */ 169297Seric 1703149Seric # define OPER 1 1713149Seric # define ATOM 2 1723149Seric # define EOTOK 3 1733149Seric # define QSTRING 4 1743149Seric # define SPACE 5 1753149Seric # define DOLLAR 6 1763149Seric # define GETONE 7 1774424Seric # define MACRO 8 1783149Seric 1793149Seric char ** 1803149Seric prescan(addr, delim) 181297Seric char *addr; 182297Seric char delim; 183297Seric { 184297Seric register char *p; 1853149Seric static char buf[MAXNAME+MAXATOM]; 1863149Seric static char *av[MAXATOM+1]; 1873149Seric char **avp; 188297Seric bool bslashmode; 189297Seric int cmntcnt; 190297Seric int brccnt; 191297Seric register char c; 1923149Seric char *tok; 193297Seric register char *q; 1943149Seric register int state; 1953149Seric int nstate; 1964085Seric extern char lower(); 197297Seric 198297Seric q = buf; 1993149Seric bslashmode = FALSE; 200297Seric cmntcnt = brccnt = 0; 2013149Seric avp = av; 2023149Seric state = OPER; 2033149Seric for (p = addr; *p != '\0' && *p != delim; ) 204297Seric { 2053149Seric /* read a token */ 2063149Seric tok = q; 2073149Seric while ((c = *p++) != '\0' && c != delim) 208297Seric { 2093149Seric /* chew up special characters */ 2104100Seric c &= ~0200; 2113149Seric *q = '\0'; 2123149Seric if (bslashmode) 2133149Seric { 2143149Seric c |= 0200; 2153149Seric bslashmode = FALSE; 2163149Seric } 2173149Seric else if (c == '\\') 2183149Seric { 2193149Seric bslashmode = TRUE; 2203149Seric continue; 2213149Seric } 2224100Seric else if (c == '"') 2234100Seric { 2244100Seric if (state == QSTRING) 2254100Seric state = OPER; 2264100Seric else 2274100Seric state = QSTRING; 2284100Seric break; 2294100Seric } 2303149Seric 2314424Seric if (c == '$' && delim == '\t') 2324424Seric nstate = DOLLAR; 2334424Seric else 2344424Seric nstate = toktype(c); 2353149Seric switch (state) 2363149Seric { 2373149Seric case QSTRING: /* in quoted string */ 2383149Seric break; 2393149Seric 2403149Seric case ATOM: /* regular atom */ 2414228Seric if (nstate != ATOM) 2423149Seric { 2433149Seric state = EOTOK; 2443149Seric p--; 2453149Seric } 2463149Seric break; 2473149Seric 2483149Seric case GETONE: /* grab one character */ 2493149Seric state = OPER; 2503149Seric break; 2513149Seric 2523149Seric case EOTOK: /* after atom or q-string */ 2533149Seric state = nstate; 2543149Seric if (state == SPACE) 2553149Seric continue; 2563149Seric break; 2573149Seric 2583149Seric case SPACE: /* linear white space */ 2593149Seric state = nstate; 2604228Seric break; 2613149Seric 2623149Seric case OPER: /* operator */ 2633149Seric if (nstate == SPACE) 2643149Seric continue; 2653149Seric state = nstate; 2663149Seric break; 2673149Seric 2683149Seric case DOLLAR: /* $- etc. */ 2693149Seric state = OPER; 2703149Seric switch (c) 2713149Seric { 2723149Seric case '$': /* literal $ */ 2733149Seric break; 2743149Seric 2753149Seric case '+': /* match anything */ 2763149Seric c = MATCHANY; 2773149Seric state = GETONE; 2783149Seric break; 2793149Seric 2803149Seric case '-': /* match one token */ 2813149Seric c = MATCHONE; 2823149Seric state = GETONE; 2833149Seric break; 2843149Seric 2854060Seric case '=': /* match one token of class */ 2864060Seric c = MATCHCLASS; 2874060Seric state = GETONE; 2884060Seric break; 2894060Seric 2903149Seric case '#': /* canonical net name */ 2913149Seric c = CANONNET; 2923149Seric break; 2933149Seric 2943149Seric case '@': /* canonical host name */ 2953149Seric c = CANONHOST; 2963149Seric break; 2973149Seric 2983149Seric case ':': /* canonical user name */ 2993149Seric c = CANONUSER; 3003149Seric break; 3013149Seric 3023149Seric default: 3034424Seric state = MACRO; 3043149Seric break; 3053149Seric } 3063149Seric break; 3073149Seric 3083149Seric default: 3093149Seric syserr("prescan: unknown state %d", state); 3103149Seric } 3113149Seric 3124228Seric if (state == EOTOK || state == SPACE) 3133149Seric break; 3144424Seric if (state == DOLLAR) 3153149Seric continue; 3163149Seric 3173149Seric /* squirrel it away */ 3183149Seric if (q >= &buf[sizeof buf - 5]) 3193149Seric { 3203149Seric usrerr("Address too long"); 3213149Seric return (NULL); 3223149Seric } 3234424Seric if (state == MACRO) 3244424Seric { 3254424Seric char mbuf[3]; 3264424Seric 3274424Seric mbuf[0] = '$'; 3284424Seric mbuf[1] = c; 3294424Seric mbuf[2] = '\0'; 3304424Seric (void) expand(mbuf, q, &buf[sizeof buf - 5]); 3314424Seric q += strlen(q); 3324424Seric state = EOTOK; 3334424Seric break; 3344424Seric } 3353149Seric *q++ = c; 3363149Seric 3373149Seric /* decide whether this represents end of token */ 3383149Seric if (state == OPER) 3393149Seric break; 340297Seric } 3413149Seric if (c == '\0' || c == delim) 3423149Seric p--; 3433149Seric 3443149Seric /* new token */ 3453149Seric if (tok == q) 346297Seric continue; 3473149Seric *q++ = '\0'; 3483149Seric 3493149Seric c = tok[0]; 3503149Seric if (c == '(') 3511378Seric { 352297Seric cmntcnt++; 3531378Seric continue; 3541378Seric } 355297Seric else if (c == ')') 356297Seric { 357297Seric if (cmntcnt <= 0) 358297Seric { 359297Seric usrerr("Unbalanced ')'"); 360297Seric return (NULL); 361297Seric } 362297Seric else 363297Seric { 364297Seric cmntcnt--; 365297Seric continue; 366297Seric } 367297Seric } 3683149Seric else if (cmntcnt > 0) 3692091Seric continue; 3703149Seric 3714385Seric if (avp >= &av[MAXATOM]) 3724385Seric { 3734385Seric syserr("prescan: too many tokens"); 3744385Seric return (NULL); 3754385Seric } 3763149Seric *avp++ = tok; 3773149Seric 3783149Seric /* we prefer <> specs */ 3793149Seric if (c == '<') 380297Seric { 3812092Seric if (brccnt < 0) 3822092Seric { 3832092Seric usrerr("multiple < spec"); 3842092Seric return (NULL); 3852092Seric } 386297Seric brccnt++; 387297Seric if (brccnt == 1) 388297Seric { 389297Seric /* we prefer using machine readable name */ 390297Seric q = buf; 391297Seric *q = '\0'; 3923149Seric avp = av; 393297Seric continue; 394297Seric } 395297Seric } 396297Seric else if (c == '>') 397297Seric { 398297Seric if (brccnt <= 0) 399297Seric { 400297Seric usrerr("Unbalanced `>'"); 401297Seric return (NULL); 402297Seric } 403297Seric else 404297Seric brccnt--; 405297Seric if (brccnt <= 0) 4062092Seric { 4072092Seric brccnt = -1; 408297Seric continue; 4092092Seric } 410297Seric } 4113149Seric } 4123149Seric *avp = NULL; 4133149Seric if (cmntcnt > 0) 4143149Seric usrerr("Unbalanced '('"); 4153149Seric else if (brccnt > 0) 4163149Seric usrerr("Unbalanced '<'"); 4173149Seric else if (state == QSTRING) 4183149Seric usrerr("Unbalanced '\"'"); 4193149Seric else if (av[0] != NULL) 4203149Seric return (av); 4213149Seric return (NULL); 4223149Seric } 4233149Seric /* 4243149Seric ** TOKTYPE -- return token type 4253149Seric ** 4263149Seric ** Parameters: 4273149Seric ** c -- the character in question. 4283149Seric ** 4293149Seric ** Returns: 4303149Seric ** Its type. 4313149Seric ** 4323149Seric ** Side Effects: 4333149Seric ** none. 4343149Seric */ 435297Seric 4363149Seric toktype(c) 4373149Seric register char c; 4383149Seric { 4393380Seric static char buf[50]; 4403382Seric static bool firstime = TRUE; 4413380Seric 4423382Seric if (firstime) 4433380Seric { 4443382Seric firstime = FALSE; 4454085Seric (void) expand("$o", buf, &buf[sizeof buf - 1]); 4463380Seric strcat(buf, DELIMCHARS); 4473380Seric } 4484100Seric if (!isascii(c)) 4494100Seric return (ATOM); 4503149Seric if (isspace(c)) 4513149Seric return (SPACE); 4523380Seric if (iscntrl(c) || index(buf, c) != NULL) 4533149Seric return (OPER); 4543149Seric return (ATOM); 4553149Seric } 4563149Seric /* 4573149Seric ** REWRITE -- apply rewrite rules to token vector. 4583149Seric ** 4593149Seric ** Parameters: 4603149Seric ** pvp -- pointer to token vector. 4613149Seric ** 4623149Seric ** Returns: 4633149Seric ** none. 4643149Seric ** 4653149Seric ** Side Effects: 4663149Seric ** pvp is modified. 4673149Seric */ 4682091Seric 4693149Seric struct match 4703149Seric { 4713149Seric char **firsttok; /* first token matched */ 4723149Seric char **lasttok; /* last token matched */ 4733149Seric char name; /* name of parameter */ 4743149Seric }; 4753149Seric 4763149Seric # define MAXMATCH 8 /* max params per rewrite */ 4773149Seric 4783149Seric 4794070Seric rewrite(pvp, ruleset) 4803149Seric char **pvp; 4814070Seric int ruleset; 4823149Seric { 4833149Seric register char *ap; /* address pointer */ 4843149Seric register char *rp; /* rewrite pointer */ 4853149Seric register char **avp; /* address vector pointer */ 4863149Seric register char **rvp; /* rewrite vector pointer */ 4873149Seric struct rewrite *rwr; 4883149Seric struct match mlist[MAXMATCH]; 4893149Seric char *npvp[MAXATOM+1]; /* temporary space for rebuild */ 4904060Seric extern bool sameword(); 4913149Seric 4924100Seric # ifdef DEBUG 4934228Seric if (Debug > 9) 4943149Seric { 4953149Seric printf("rewrite: original pvp:\n"); 4963149Seric printav(pvp); 4973149Seric } 4984100Seric # endif DEBUG 4993149Seric 5003149Seric /* 5013149Seric ** Run through the list of rewrite rules, applying 5023149Seric ** any that match. 5033149Seric */ 5043149Seric 5054070Seric for (rwr = RewriteRules[ruleset]; rwr != NULL; ) 5063149Seric { 5074100Seric # ifdef DEBUG 5084100Seric if (Debug > 10) 509297Seric { 5103149Seric printf("-----trying rule:\n"); 5113149Seric printav(rwr->r_lhs); 5123149Seric } 5134100Seric # endif DEBUG 5143149Seric 5153149Seric /* try to match on this rule */ 5163149Seric clrmatch(mlist); 5173149Seric for (rvp = rwr->r_lhs, avp = pvp; *avp != NULL; ) 5183149Seric { 5193149Seric ap = *avp; 5203149Seric rp = *rvp; 5213149Seric 5223149Seric if (rp == NULL) 523297Seric { 5243149Seric /* end-of-pattern before end-of-address */ 5253149Seric goto fail; 526297Seric } 5273149Seric 5283149Seric switch (*rp) 5293149Seric { 5304060Seric register STAB *s; 5314060Seric register int class; 5324060Seric 5333149Seric case MATCHONE: 5343149Seric /* match exactly one token */ 5353149Seric setmatch(mlist, rp[1], avp, avp); 5363149Seric break; 5373149Seric 5383149Seric case MATCHANY: 5393149Seric /* match any number of tokens */ 5404085Seric setmatch(mlist, rp[1], (char **) NULL, avp); 5413149Seric break; 5423149Seric 5434060Seric case MATCHCLASS: 5444060Seric /* match any token in a class */ 5454060Seric class = rp[1]; 5464060Seric if (!isalpha(class)) 5474060Seric goto fail; 5484060Seric if (isupper(class)) 5494060Seric class -= 'A'; 5504060Seric else 5514060Seric class -= 'a'; 5524100Seric s = stab(ap, ST_CLASS, ST_FIND); 5534060Seric if (s == NULL || (s->s_class & (1 << class)) == 0) 5544060Seric goto fail; 5554060Seric break; 5564060Seric 5573149Seric default: 5583149Seric /* must have exact match */ 5594060Seric if (!sameword(rp, ap)) 5604060Seric goto fail; 5613149Seric break; 5623149Seric } 5633149Seric 5643149Seric /* successful match on this token */ 5653149Seric avp++; 5663149Seric rvp++; 5673149Seric continue; 5683149Seric 5693149Seric fail: 5703149Seric /* match failed -- back up */ 5713149Seric while (--rvp >= rwr->r_lhs) 5723149Seric { 5733149Seric rp = *rvp; 5743149Seric if (*rp == MATCHANY) 5753149Seric break; 5763149Seric 5773149Seric /* can't extend match: back up everything */ 5783149Seric avp--; 5793149Seric 5803149Seric if (*rp == MATCHONE) 5813149Seric { 5823149Seric /* undo binding */ 5834085Seric setmatch(mlist, rp[1], (char **) NULL, (char **) NULL); 5843149Seric } 5853149Seric } 5863149Seric 5873149Seric if (rvp < rwr->r_lhs) 5883149Seric { 5893149Seric /* total failure to match */ 5903149Seric break; 5913149Seric } 592297Seric } 5933149Seric 5943149Seric /* 5953149Seric ** See if we successfully matched 5963149Seric */ 5973149Seric 5983149Seric if (rvp >= rwr->r_lhs && *rvp == NULL) 5993149Seric { 6004100Seric # ifdef DEBUG 6014100Seric if (Debug > 10) 6023149Seric { 6033149Seric printf("-----rule matches:\n"); 6043149Seric printav(rwr->r_rhs); 6053149Seric } 6064100Seric # endif DEBUG 6073149Seric 6083149Seric /* substitute */ 6093149Seric for (rvp = rwr->r_rhs, avp = npvp; *rvp != NULL; rvp++) 6103149Seric { 6113149Seric rp = *rvp; 6123149Seric if (*rp == MATCHANY) 6133149Seric { 6143149Seric register struct match *m; 6153149Seric register char **pp; 6163149Seric extern struct match *findmatch(); 6173149Seric 6183149Seric m = findmatch(mlist, rp[1]); 6193149Seric if (m != NULL) 6203149Seric { 6213149Seric pp = m->firsttok; 6223149Seric do 6233149Seric { 6244385Seric if (avp >= &npvp[MAXATOM]) 6254385Seric { 6264385Seric syserr("rewrite: expansion too long"); 6274385Seric return; 6284385Seric } 6293149Seric *avp++ = *pp; 6303149Seric } while (pp++ != m->lasttok); 6313149Seric } 6323149Seric } 6333149Seric else 6344385Seric { 6354385Seric if (avp >= &npvp[MAXATOM]) 6364385Seric { 6374385Seric syserr("rewrite: expansion too long"); 6384385Seric return; 6394385Seric } 6403149Seric *avp++ = rp; 6414385Seric } 6423149Seric } 6433149Seric *avp++ = NULL; 6444085Seric bmove((char *) npvp, (char *) pvp, (avp - npvp) * sizeof *avp); 6453149Seric # ifdef DEBUG 6464228Seric if (Debug > 3) 6473149Seric { 6483188Seric char **vp; 6493188Seric 6503188Seric printf("rewritten as `"); 6513188Seric for (vp = pvp; *vp != NULL; vp++) 6524228Seric { 6534228Seric if (vp != pvp) 6544228Seric printf("_"); 6553188Seric xputs(*vp); 6564228Seric } 6573188Seric printf("'\n"); 6583149Seric } 6593149Seric # endif DEBUG 6603149Seric if (pvp[0][0] == CANONNET) 6613149Seric break; 6623149Seric } 6633149Seric else 6643149Seric { 6654100Seric # ifdef DEBUG 6664100Seric if (Debug > 10) 6673149Seric printf("----- rule fails\n"); 6684100Seric # endif DEBUG 6693149Seric rwr = rwr->r_next; 6703149Seric } 671297Seric } 6723149Seric } 6733149Seric /* 6743149Seric ** SETMATCH -- set parameter value in match vector 6753149Seric ** 6763149Seric ** Parameters: 6773149Seric ** mlist -- list of match values. 6783149Seric ** name -- the character name of this parameter. 6793149Seric ** first -- the first location of the replacement. 6803149Seric ** last -- the last location of the replacement. 6813149Seric ** 6823149Seric ** If last == NULL, delete this entry. 6833149Seric ** If first == NULL, extend this entry (or add it if 6843149Seric ** it does not exist). 6853149Seric ** 6863149Seric ** Returns: 6873149Seric ** nothing. 6883149Seric ** 6893149Seric ** Side Effects: 6903149Seric ** munges with mlist. 6913149Seric */ 6923149Seric 6933149Seric setmatch(mlist, name, first, last) 6943149Seric struct match *mlist; 6953149Seric char name; 6963149Seric char **first; 6973149Seric char **last; 6983149Seric { 6993149Seric register struct match *m; 7003149Seric struct match *nullm = NULL; 7013149Seric 7023149Seric for (m = mlist; m < &mlist[MAXMATCH]; m++) 7033149Seric { 7043149Seric if (m->name == name) 7053149Seric break; 7063149Seric if (m->name == '\0') 7073149Seric nullm = m; 7083149Seric } 7093149Seric 7103149Seric if (m >= &mlist[MAXMATCH]) 7113149Seric m = nullm; 7123149Seric 7133149Seric if (last == NULL) 7143149Seric { 7153149Seric m->name = '\0'; 7163149Seric return; 7173149Seric } 7183149Seric 7193149Seric if (m->name == '\0') 7203149Seric { 7213149Seric if (first == NULL) 7223149Seric m->firsttok = last; 7233149Seric else 7243149Seric m->firsttok = first; 7253149Seric } 7263149Seric m->name = name; 7273149Seric m->lasttok = last; 7283149Seric } 7293149Seric /* 7303149Seric ** FINDMATCH -- find match in mlist 7313149Seric ** 7323149Seric ** Parameters: 7333149Seric ** mlist -- list to search. 7343149Seric ** name -- name to find. 7353149Seric ** 7363149Seric ** Returns: 7373149Seric ** pointer to match structure. 7383149Seric ** NULL if no match. 7393149Seric ** 7403149Seric ** Side Effects: 7413149Seric ** none. 7423149Seric */ 7433149Seric 7443149Seric struct match * 7453149Seric findmatch(mlist, name) 7463149Seric struct match *mlist; 7473149Seric char name; 7483149Seric { 7493149Seric register struct match *m; 7503149Seric 7513149Seric for (m = mlist; m < &mlist[MAXMATCH]; m++) 7523149Seric { 7533149Seric if (m->name == name) 7543149Seric return (m); 7553149Seric } 7563149Seric 757297Seric return (NULL); 758297Seric } 7593149Seric /* 7603149Seric ** CLRMATCH -- clear match list 7613149Seric ** 7623149Seric ** Parameters: 7633149Seric ** mlist -- list to clear. 7643149Seric ** 7653149Seric ** Returns: 7663149Seric ** none. 7673149Seric ** 7683149Seric ** Side Effects: 7693149Seric ** mlist is cleared. 7703149Seric */ 7713149Seric 7723149Seric clrmatch(mlist) 7733149Seric struct match *mlist; 7743149Seric { 7753149Seric register struct match *m; 7763149Seric 7773149Seric for (m = mlist; m < &mlist[MAXMATCH]; m++) 7783149Seric m->name = '\0'; 7793149Seric } 7803149Seric /* 7813149Seric ** BUILDADDR -- build address from token vector. 7823149Seric ** 7833149Seric ** Parameters: 7843149Seric ** tv -- token vector. 7853149Seric ** a -- pointer to address descriptor to fill. 7863149Seric ** If NULL, one will be allocated. 7873149Seric ** 7883149Seric ** Returns: 7894279Seric ** NULL if there was an error. 7904279Seric ** 'a' otherwise. 7913149Seric ** 7923149Seric ** Side Effects: 7933149Seric ** fills in 'a' 7943149Seric */ 7953149Seric 7963149Seric ADDRESS * 7973149Seric buildaddr(tv, a) 7983149Seric register char **tv; 7993149Seric register ADDRESS *a; 8003149Seric { 8013149Seric register int i; 8023149Seric static char buf[MAXNAME]; 8033149Seric struct mailer **mp; 8043149Seric register struct mailer *m; 8053149Seric 8063149Seric if (a == NULL) 8073149Seric a = (ADDRESS *) xalloc(sizeof *a); 8083188Seric a->q_flags = 0; 8094079Seric a->q_home = NULL; 8103149Seric 8113149Seric /* figure out what net/mailer to use */ 8123149Seric if (**tv != CANONNET) 8134279Seric { 8143149Seric syserr("buildaddr: no net"); 8154279Seric return (NULL); 8164279Seric } 8173149Seric tv++; 8184279Seric if (strcmp(*tv, "error") == 0) 8194279Seric { 8204279Seric if (**++tv != CANONUSER) 8214279Seric syserr("buildaddr: error: no user"); 8224279Seric buf[0] = '\0'; 8234279Seric while (*++tv != NULL) 8244279Seric { 8254279Seric if (buf[0] != '\0') 8264279Seric strcat(buf, " "); 8274279Seric strcat(buf, *tv); 8284279Seric } 8294279Seric usrerr(buf); 8304279Seric return (NULL); 8314279Seric } 8323154Seric for (mp = Mailer, i = 0; (m = *mp++) != NULL; i++) 8333149Seric { 8343149Seric if (strcmp(m->m_name, *tv) == 0) 8353149Seric break; 8363149Seric } 8373149Seric if (m == NULL) 8384279Seric { 8393149Seric syserr("buildaddr: unknown net %s", *tv); 8404279Seric return (NULL); 8414279Seric } 8423149Seric a->q_mailer = i; 8433149Seric 8443149Seric /* figure out what host (if any) */ 8453149Seric tv++; 8464195Seric if (!bitset(M_LOCAL, m->m_flags)) 8473149Seric { 8483149Seric if (**tv != CANONHOST) 8494279Seric { 8503149Seric syserr("buildaddr: no host"); 8514279Seric return (NULL); 8524279Seric } 8533149Seric tv++; 8543149Seric a->q_host = *tv; 8553149Seric tv++; 8563149Seric } 8573149Seric else 8583149Seric a->q_host = NULL; 8593149Seric 8603149Seric /* figure out the user */ 8613149Seric if (**tv != CANONUSER) 8624279Seric { 8633149Seric syserr("buildaddr: no user"); 8644279Seric return (NULL); 8654279Seric } 8664228Seric cataddr(++tv, buf, sizeof buf); 8673149Seric a->q_user = buf; 8683149Seric 8693149Seric return (a); 8703149Seric } 8713188Seric /* 8724228Seric ** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs) 8734228Seric ** 8744228Seric ** Parameters: 8754228Seric ** pvp -- parameter vector to rebuild. 8764228Seric ** buf -- buffer to build the string into. 8774228Seric ** sz -- size of buf. 8784228Seric ** 8794228Seric ** Returns: 8804228Seric ** none. 8814228Seric ** 8824228Seric ** Side Effects: 8834228Seric ** Destroys buf. 8844228Seric */ 8854228Seric 8864228Seric cataddr(pvp, buf, sz) 8874228Seric char **pvp; 8884228Seric char *buf; 8894228Seric register int sz; 8904228Seric { 8914228Seric bool oatomtok = FALSE; 8924228Seric bool natomtok = FALSE; 8934228Seric register int i; 8944228Seric register char *p; 8954228Seric 8964228Seric p = buf; 8974228Seric sz--; 8984228Seric while (*pvp != NULL && (i = strlen(*pvp)) < sz) 8994228Seric { 9004228Seric natomtok = (toktype(**pvp) == ATOM); 9014228Seric if (oatomtok && natomtok) 9024228Seric *p++ = SPACESUB; 9034228Seric (void) strcpy(p, *pvp); 9044228Seric oatomtok = natomtok; 9054228Seric p += i; 9064228Seric sz -= i; 9074228Seric pvp++; 9084228Seric } 9094228Seric *p = '\0'; 9104228Seric } 9114228Seric /* 9123188Seric ** SAMEADDR -- Determine if two addresses are the same 9133188Seric ** 9143188Seric ** This is not just a straight comparison -- if the mailer doesn't 9153188Seric ** care about the host we just ignore it, etc. 9163188Seric ** 9173188Seric ** Parameters: 9183188Seric ** a, b -- pointers to the internal forms to compare. 9193188Seric ** wildflg -- if TRUE, 'a' may have no user specified, 9203188Seric ** in which case it is to match anything. 9213188Seric ** 9223188Seric ** Returns: 9233188Seric ** TRUE -- they represent the same mailbox. 9243188Seric ** FALSE -- they don't. 9253188Seric ** 9263188Seric ** Side Effects: 9273188Seric ** none. 9283188Seric */ 9293188Seric 9303188Seric bool 9313188Seric sameaddr(a, b, wildflg) 9323188Seric register ADDRESS *a; 9333188Seric register ADDRESS *b; 9343188Seric bool wildflg; 9353188Seric { 9363188Seric /* if they don't have the same mailer, forget it */ 9373188Seric if (a->q_mailer != b->q_mailer) 9383188Seric return (FALSE); 9393188Seric 9403188Seric /* if the user isn't the same, we can drop out */ 9413188Seric if ((!wildflg || a->q_user[0] != '\0') && strcmp(a->q_user, b->q_user) != 0) 9423188Seric return (FALSE); 9433188Seric 9443188Seric /* if the mailer ignores hosts, we have succeeded! */ 9454195Seric if (bitset(M_LOCAL, Mailer[a->q_mailer]->m_flags)) 9463188Seric return (TRUE); 9473188Seric 9483188Seric /* otherwise compare hosts (but be careful for NULL ptrs) */ 9493188Seric if (a->q_host == NULL || b->q_host == NULL) 9503188Seric return (FALSE); 9513188Seric if (strcmp(a->q_host, b->q_host) != 0) 9523188Seric return (FALSE); 9533188Seric 9543188Seric return (TRUE); 9553188Seric } 9563234Seric /* 9573234Seric ** PRINTADDR -- print address (for debugging) 9583234Seric ** 9593234Seric ** Parameters: 9603234Seric ** a -- the address to print 9613234Seric ** follow -- follow the q_next chain. 9623234Seric ** 9633234Seric ** Returns: 9643234Seric ** none. 9653234Seric ** 9663234Seric ** Side Effects: 9673234Seric ** none. 9683234Seric */ 9693234Seric 9704317Seric # ifdef DEBUG 9714317Seric 9723234Seric printaddr(a, follow) 9733234Seric register ADDRESS *a; 9743234Seric bool follow; 9753234Seric { 9763234Seric while (a != NULL) 9773234Seric { 978*4443Seric printf("%x=", a); 9794085Seric (void) fflush(stdout); 9803234Seric printf("%s: mailer %d (%s), host `%s', user `%s'\n", a->q_paddr, 9813234Seric a->q_mailer, Mailer[a->q_mailer]->m_name, a->q_host, a->q_user); 982*4443Seric printf("\tnext=%x, flags=%o, rmailer %d\n", a->q_next, 9833234Seric a->q_flags, a->q_rmailer); 9843234Seric 9853234Seric if (!follow) 9863234Seric return; 9873234Seric a = a->q_next; 9883234Seric } 989*4443Seric if (!follow) 990*4443Seric printf("[NULL]\n"); 9913234Seric } 9924317Seric 9934317Seric # endif DEBUG 994