1: /* addrsbr.c - parse addresses 822-style */ 2: 3: #include "../h/mh.h" 4: #include "../h/addrsbr.h" 5: #include "../zotnet/mf.h" 6: #include <stdio.h> 7: #ifdef BERK 8: #include <ctype.h> 9: #endif BERK 10: 11: /* High level parsing of addresses: 12: 13: The routines in zotnet/mf/mf.c parse the syntactic representations of 14: addresses. The routines in uip/addrsbr.c associate semantics with those 15: addresses. 16: 17: If #ifdef BERK is in effect, the routines in mf.c aren't called and only 18: the most rudimentary syntax parse is done. The parse is not 822-conformant. 19: This causes problems as there is no semantics associated with the address 20: at all--it's just a string. (the author of the BERK code disagrees with 21: the preceding, of course. BERK solves problems for incoming mail 22: because it will accept damn near any address. BERK was intended to be 23: used when spost is the interface to the mail delivery system which means 24: all outgoing address interpretation is left to sendmail. It is possible, 25: though unlikely, for BERK address parsing to interact poorly with 26: "post". - van@monet.berkeley.edu). 27: 28: Instead, if #ifdef DUMB is in effect, a full 822-style parser is called 29: for syntax recongition. This breaks each address into its components. 30: Note however that no semantics are assumed about the parts or their 31: totality. This means that implicit hostnames aren't made explicit, 32: and explicit hostnames aren't expanded to their "official" represenations. 33: 34: If neither BERK nor DUMB is in effect, then this module does some 35: high-level thinking about what the addresses are. If #ifdef MF is in 36: effect, then MH will deduce UUCP-style addressing masquerading as 37: 822-style addresses. 38: 39: 1. for MMDF systems: 40: 41: string%<uucp>@<local> -> string 42: 43: 2. for non-MMDF systems: 44: 45: string@host.<uucp> -> host!string 46: 47: 3. for any system, an address interpreted relative to the local host: 48: 49: string@<uucp> -> string 50: 51: For cases (1) and (3) above, the leftmost host is extracted. If it's not 52: present, the local host is used. If #ifdef MF is not in effect or the 53: tests above fail, the address is considered to be a real 822-style address. 54: 55: If an explicit host is not present, then MH checks for a bang to indicate 56: an explicit UUCP-style address. If so, this is noted. If not, the host is 57: defaulted, typically to the local host. The lack of an explict host is 58: also noted. 59: 60: If an explicit 822-style host is present, then MH checks to see if it 61: can expand this to the official name for the host. If the hostname is 62: unknown, the address is so typed. 63: 64: To summarize, when we're all done, here's what MH knows about the address: 65: 66: BERK - type: local 67: nohost: set if no '@' or '!' in mailbox 68: text: exact copy of address 69: mbox: lowercase version of mailbox 70: 71: DUMB - type: local, uucp, or network 72: host: not locally defaulted, not explicitly expanded 73: everything else 74: 75: other - type: local, uucp, network, unknown 76: everything else 77: */ 78: 79: /* */ 80: 81: #if !defined(DUMB) && defined(SENDMTS) && !defined(BANG) 82: #define MF 83: #define UucpChan() "UUCP" 84: #endif MF 85: 86: #ifdef BERK 87: static char *err = NULL; 88: static char adrtext[BUFSIZ]; 89: #else not BERK 90: static int ingrp = 0; 91: 92: static char *pers = NULL; 93: static char *mbox = NULL; 94: static char *host = NULL; 95: static char *route = NULL; 96: static char *grp = NULL; 97: static char *note = NULL; 98: 99: static char err[BUFSIZ]; 100: #endif not BERK 101: static char adr[BUFSIZ]; 102: 103: 104: char *getusr (); 105: 106: /* */ 107: 108: char *getname (addrs) 109: register char *addrs; 110: { 111: #ifdef BERK 112: /* 113: * Berkeley uses a very simple parser since Sendmail does all the work. 114: * The only thing that does address parsing if BERK is defined is the 115: * routine "ismybox" used by "scan" & "repl" to identify the current 116: * users maildrop. 117: * 118: * This routine does essentially the same address interpretation as the 119: * routine "prescan" in "sendmail". The intent is that MH should 120: * make minimum assumptions about address forms since it doesn't 121: * have access to the information in the sendmail config file 122: * (God forbid that anything but sendmail has to deal with a sendmail 123: * config file) and, therefore, hasn't the faintest idea of what will 124: * or won't be a legal address. 125: * 126: * Since this parse is only used by "ismybox" and repl, it just does 127: * two things: split multiple addr on a line into separate addresses and 128: * locate the "mailbox" portion of an address. The parse uses rfc-822 129: * metacharacters and quoting but is much less restrictive that rfc-822. 130: * In detail, `,' or eos terminate addresses. "Empty" addresses 131: * (e.g., `,,') are ignored. Double quote ("), backslash, left & right 132: * paren and left and right angle brackets are metacharacters. Left & 133: * right parens must balance as must left & right angle brackets. Any 134: * metacharacter may be escaped by preceding it with a backslash. 135: * Any text between parens is considered a comment and ignored (i.e., 136: * only `(', `)' and `\' are metacharacters following a `('). Text 137: * between double quotes is considered escaped (i.e., only `"' and 138: * `\' are metacharacters following a `"'). The `mailbox' portion 139: * of an address is the non-comment text between angle-brackets if 140: * the address contains any angle brackets. Otherwise, it is all the 141: * non-comment text. Blanks, tabs & newlines will not be included 142: * in the mailbox portion of an address unless they are escaped. 143: */ 144: 145: /* Scanner states */ 146: #define NORMAL (0<<8) 147: #define QS (1<<8) /* in quoted string */ 148: #define COM (2<<8) /* in comment (...) */ 149: #define ERR (3<<8) /* found an error */ 150: #define EOA (4<<8) /* end of address */ 151: 152: static char *saved_addr = NULL; /* saved address line ptr */ 153: static char *adr_ptr = NULL; /* where to start looking for 154: next address on line */ 155: register char *nxtout = adr; /* where to put next character of 156: `mailbox' part of address */ 157: register char c; 158: register int state = NORMAL; 159: register char *adrcopy = adrtext; /* where to put next character of 160: address */ 161: register int lbcnt = 0; /* number of unmatched "(" */ 162: register int lpcnt = 0; /* number of unmatched "<" */ 163: 164: err = NULL; 165: if (! addrs) { 166: adr_ptr = NULL; 167: return NULL; 168: } 169: if (adr_ptr) 170: addrs = adr_ptr; 171: else 172: addrs = saved_addr = getcpy(addrs); 173: 174: /* skip any leading whitespace or commas. */ 175: while ( (c = *addrs++) == ',' || isspace(c)) 176: ; 177: 178: *nxtout = *adrcopy = '\0'; 179: while (state != EOA) { 180: *adrcopy++ = c; 181: if (state != COM) 182: *nxtout++ = isupper (c) ? tolower (c) : c; 183: switch (state+c) { 184: 185: case NORMAL+'\n': /* discard newlines */ 186: case QS+'\n': 187: case COM+'\n': 188: case ERR+'\n': 189: --nxtout; 190: --adrcopy; 191: break; 192: 193: case NORMAL+' ': /* skip unquoted whitespace */ 194: case NORMAL+'\t': 195: --nxtout; 196: break; 197: 198: case NORMAL+'"': /* start quoted string */ 199: state = QS; 200: break; 201: 202: case QS+'"': /* end quoted string */ 203: state = NORMAL; 204: break; 205: 206: case NORMAL+'<': 207: nxtout = adr; /* start over accumulating address */ 208: lbcnt++; 209: break; 210: 211: case NORMAL+'>': 212: --lbcnt; 213: if (lbcnt < 0) { 214: state = ERR; 215: err = "extra >"; 216: } else 217: *(nxtout-1) = '\0'; 218: break; 219: 220: case NORMAL+'(': 221: state = COM; 222: --nxtout; 223: case COM+'(': 224: lpcnt++; 225: break; 226: 227: case COM+')': 228: --lpcnt; 229: if (lpcnt < 0) { 230: state = ERR; 231: err = "extra )"; 232: } else if (lpcnt == 0) 233: state = NORMAL; 234: break; 235: 236: case NORMAL+'\\': 237: case QS+'\\': 238: case COM+'\\': 239: if ((c = *addrs++) == '\n' || c == '\0') { 240: state = EOA; 241: err = "illegal \\"; 242: } 243: *adrcopy++ = c; 244: *nxtout++ = isupper (c) ? tolower (c) : c; 245: break; 246: 247: case NORMAL+',': 248: case ERR+',': 249: case NORMAL+'\0': 250: case ERR+'\0': 251: state = EOA; 252: if (lbcnt) 253: err = "missing >"; 254: break; 255: 256: case COM+'\0': 257: state = EOA; 258: err = "missing )"; 259: if (nxtout == adr) 260: nxtout++; 261: break; 262: 263: case QS+'\0': 264: state = EOA; 265: err = "missing \""; 266: break; 267: } 268: if (c != '\0') 269: c = *addrs++; 270: } 271: /* 272: * at this point adr contains the `mailbox' part of the address 273: * in lower case & minus any comment or unquoted whitespace. 274: * adrtext contains an exact copy of the address and 275: * addr points to where we should start scanning next time. 276: */ 277: *(nxtout-1) = *(adrcopy-1) = '\0'; 278: if (*adr && !err) { 279: adr_ptr = addrs-1; 280: return adrtext; 281: } else { 282: free (saved_addr); 283: adr_ptr = NULL; 284: return NULL; 285: } 286: #else not BERK 287: register struct adrx *ap; 288: 289: pers = mbox = host = route = grp = note = NULL; 290: err[0] = NULL; 291: 292: if ((ap = getadrx (addrs)) == NULL) 293: return NULL; 294: 295: (void) strcpy (adr, ap -> text); 296: pers = ap -> pers; 297: mbox = ap -> mbox; 298: host = ap -> host; 299: route = ap -> path; 300: grp = ap -> grp; 301: ingrp = ap -> ingrp; 302: note = ap -> note; 303: if (ap -> err && *ap -> err) 304: (void) strcpy (err, ap -> err); 305: 306: return adr; 307: #endif not BERK 308: } 309: 310: /* */ 311: 312: #ifdef BERK 313: /* ARGSUSED */ 314: #endif BERK 315: 316: struct mailname *getm (str, dfhost, dftype, wanthost, eresult) 317: register char *str, 318: *eresult; 319: char *dfhost; 320: int dftype, 321: wanthost; 322: { 323: #ifndef BERK 324: register char *pp; 325: #ifndef DUMB 326: register char *dp; 327: #endif not DUMB 328: #ifdef MF 329: char *up = UucpChan (); 330: #endif MF 331: #endif not BERK 332: register struct mailname *mp; 333: 334: if (err && err[0]) { 335: if (eresult) 336: (void) strcpy (eresult, err); 337: else 338: if (wanthost == AD_HOST) 339: admonish (NULLCP, "bad address '%s' - %s", str, err); 340: return NULL; 341: } 342: #ifdef BERK 343: if (str == NULL || *str == '\0') { 344: #else not BERK 345: if (pers == NULL 346: && mbox == NULL && host == NULL && route == NULL 347: && grp == NULL) { 348: #endif not BERK 349: if (eresult) 350: (void) strcpy (eresult, "null address"); 351: else 352: if (wanthost == AD_HOST) 353: admonish (NULLCP, "null address '%s'", str); 354: return NULL; 355: } 356: #ifndef BERK 357: if (mbox == NULL && grp == NULL) { 358: if (eresult) 359: (void) strcpy (eresult, "no mailbox in address"); 360: else 361: if (wanthost == AD_HOST) 362: admonish (NULLCP, "no mailbox in address '%s'", str); 363: return NULL; 364: } 365: 366: if (dfhost == NULL) { 367: dfhost = LocalName (); 368: dftype = LOCALHOST; 369: } 370: #endif not BERK 371: 372: mp = (struct mailname *) calloc ((unsigned) 1, sizeof *mp); 373: if (mp == NULL) { 374: if (eresult) 375: (void) strcpy (eresult, "insufficient memory to represent address"); 376: else 377: if (wanthost == AD_HOST) 378: adios (NULLCP, "insufficient memory to represent address"); 379: return NULL; 380: } 381: 382: mp -> m_text = getcpy (str); 383: #ifdef BERK 384: mp -> m_type = LOCALHOST; 385: mp -> m_mbox = getcpy (adr); 386: if (!index (adr, '@') && !index (adr, '!')) 387: mp -> m_nohost = 1; 388: #else not BERK 389: if (pers) 390: mp -> m_pers = getcpy (pers); 391: 392: if (mbox == NULL) { 393: mp -> m_type = BADHOST; 394: mp -> m_nohost = 1; 395: mp -> m_ingrp = ingrp; 396: mp -> m_gname = getcpy (grp); 397: if (note) 398: mp -> m_note = getcpy (note); 399: return mp; 400: } 401: 402: /* */ 403: 404: if (host) { 405: #ifdef MF 406: #ifdef MMDFMTS 407: if (up && uleq (host, LocalName ()) 408: && (pp = rindex (mbox, '%')) 409: && uleq (up, pp + 1)) {/* uucpaddr%<uucp>@<local> */ 410: *pp = NULL; 411: goto get_uucp; 412: } 413: #else not MMDFMTS 414: if (up && (pp = index (host, '.')) 415: && uleq (up, pp + 1)) {/* uucpaddr@host.<uucp> */ 416: *pp = NULL; 417: mp -> m_host = getcpy (host); 418: mp -> m_mbox = getcpy (mbox); 419: mp -> m_type = UUCPHOST; 420: goto got_host; 421: } 422: #endif not MMDFMTS 423: if (up && uleq (dfhost, LocalName ()) 424: && uleq (up, host)) {/* uucpaddr@<uucp> [local] */ 425: if (pp = index (mbox, '!')) { 426: *pp++ = NULL; 427: mp -> m_host = getcpy (mbox); 428: mp -> m_mbox = getcpy (pp); 429: } 430: else { 431: mp -> m_host = getcpy (SystemName ()); 432: mp -> m_mbox = getcpy (mbox); 433: } 434: mp -> m_type = UUCPHOST; 435: goto got_host; 436: } 437: #endif MF 438: mp -> m_mbox = getcpy (mbox); 439: mp -> m_host = getcpy (host); 440: } 441: else { 442: if (pp = index (mbox, '!')) { 443: *pp++ = NULL; 444: mp -> m_mbox = getcpy (pp); 445: mp -> m_host = getcpy (mbox); 446: mp -> m_type = UUCPHOST; 447: } 448: else { 449: mp -> m_nohost = 1; 450: mp -> m_mbox = getcpy (mbox); 451: #ifdef DUMB 452: if (route == NULL && dftype == LOCALHOST) { 453: mp -> m_host = NULLCP; 454: mp -> m_type = dftype; 455: } 456: else 457: #endif DUMB 458: { 459: mp -> m_host = route ? NULLCP : getcpy (dfhost); 460: mp -> m_type = route ? NETHOST : dftype; 461: } 462: } 463: goto got_host; 464: } 465: 466: /* */ 467: 468: if (wanthost == AD_NHST) 469: mp -> m_type = uleq (LocalName (), mp -> m_host) 470: ? LOCALHOST : NETHOST; 471: #ifdef DUMB 472: else 473: mp -> m_type = uleq (LocalName (), mp -> m_host) ? LOCALHOST 474: : NETHOST; 475: #else not DUMB 476: else 477: if (pp = OfficialName (mp -> m_host)) { 478: got_real_host: ; 479: free (mp -> m_host); 480: mp -> m_host = getcpy (pp); 481: mp -> m_type = uleq (LocalName (), mp -> m_host) ? LOCALHOST 482: : NETHOST; 483: } 484: else { 485: if (dp = index (mp -> m_host, '.')) { 486: *dp = NULL; 487: if (pp = OfficialName (mp -> m_host)) 488: goto got_real_host; 489: *dp = '.'; 490: } 491: mp -> m_type = BADHOST; 492: } 493: #endif not DUMB 494: 495: got_host: ; 496: if (route) 497: mp -> m_path = getcpy (route); 498: mp -> m_ingrp = ingrp; 499: if (grp) 500: mp -> m_gname = getcpy (grp); 501: if (note) 502: mp -> m_note = getcpy (note); 503: #endif not BERK 504: 505: return mp; 506: } 507: 508: /* */ 509: 510: void mnfree (mp) 511: register struct mailname *mp; 512: { 513: if (!mp) 514: return; 515: 516: if (mp -> m_text) 517: free (mp -> m_text); 518: if (mp -> m_pers) 519: free (mp -> m_pers); 520: if (mp -> m_mbox) 521: free (mp -> m_mbox); 522: if (mp -> m_host) 523: free (mp -> m_host); 524: if (mp -> m_path) 525: free (mp -> m_path); 526: if (mp -> m_gname) 527: free (mp -> m_gname); 528: if (mp -> m_note) 529: free (mp -> m_note); 530: #ifdef MHMTS 531: if (mp -> m_aka) 532: free (mp -> m_aka); 533: #endif MHMTS 534: 535: free ((char *) mp); 536: } 537: 538: /* */ 539: 540: char *auxformat (mp, extras) 541: register struct mailname *mp; 542: int extras; 543: { 544: #ifndef BERK 545: #ifdef MF 546: char *up = UucpChan (); 547: #endif MF 548: static char addr[BUFSIZ]; 549: #endif not BERK 550: static char buffer[BUFSIZ]; 551: 552: #ifdef BERK 553: /* this "if" is a crufty hack to handle "visible" aliases */ 554: if (mp->m_pers && !extras) 555: (void) sprintf (buffer, "%s <%s>", mp->m_pers, mp->m_mbox); 556: else 557: (void) strcpy (buffer, mp -> m_text); 558: #else not BERK 559: 560: #ifdef MF 561: if (up && mp -> m_type == UUCPHOST) 562: #ifdef MMDFMTS 563: (void) sprintf (addr, "%s!%s%%%s@%s", mp -> m_host, mp -> m_mbox, 564: up, LocalName ()); 565: #else not MMDFMTS 566: (void) sprintf (addr, "%s@%s.%s", mp -> m_mbox, mp -> m_host, up); 567: #endif not MMDFMTS 568: else 569: #endif MF 570: 571: #ifdef DUMB 572: if (mp -> m_nohost) 573: (void) strcpy (addr, mp -> m_mbox ? mp -> m_mbox : ""); 574: else 575: #endif DUMB 576: 577: #ifndef BANG 578: if (mp -> m_type != UUCPHOST) 579: (void) sprintf (addr, mp -> m_host ? "%s%s@%s" : "%s%s", 580: mp -> m_path ? mp -> m_path : "", mp -> m_mbox, mp -> m_host); 581: else 582: #endif not BANG 583: (void) sprintf (addr, "%s!%s", mp -> m_host, mp -> m_mbox); 584: 585: if (!extras) 586: return addr; 587: 588: if (mp -> m_pers || mp -> m_path) 589: if (mp -> m_note) 590: (void) sprintf (buffer, "%s %s <%s>", 591: legal_person (mp -> m_pers ? mp -> m_pers : mp -> m_mbox), 592: mp -> m_note, addr); 593: else 594: (void) sprintf (buffer, "%s <%s>", 595: legal_person (mp -> m_pers ? mp -> m_pers : mp -> m_mbox), 596: addr); 597: else 598: if (mp -> m_note) 599: (void) sprintf (buffer, "%s %s", addr, mp -> m_note); 600: else 601: (void) strcpy (buffer, addr); 602: #endif not BERK 603: 604: return buffer; 605: } 606: 607: /* */ 608: 609: #if defined(BERK) || (defined(DUMB) && !defined(MMDFMTS) && !defined(SMTP)) 610: #define REALLYDUMB 611: #else 612: #undef REALLYDUMB 613: #endif 614: 615: char *adrsprintf (local, domain) 616: char *local, 617: *domain; 618: { 619: static char addr[BUFSIZ]; 620: 621: if (local == NULL) 622: #ifdef REALLYDUMB 623: return getusr (); 624: else 625: #endif REALLYDUMB 626: local = getusr (); 627: 628: if (domain == NULL) 629: #ifdef REALLYDUMB 630: return local; 631: else 632: #endif REALLYDUMB 633: domain = LocalName (); 634: 635: #ifndef BANG 636: (void) sprintf (addr, "%s@%s", local, domain); 637: #else BANG 638: (void) sprintf (addr, "%s!%s", domain, local); 639: #endif BANG 640: 641: return addr; 642: } 643: 644: /* */ 645: 646: #define W_NIL 0x0000 647: #define W_MBEG 0x0001 648: #define W_MEND 0x0002 649: #define W_MBOX (W_MBEG | W_MEND) 650: #define W_HBEG 0x0004 651: #define W_HEND 0x0008 652: #define W_HOST (W_HBEG | W_HEND) 653: #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND" 654: 655: 656: int ismymbox (np) 657: register struct mailname *np; 658: { 659: int oops; 660: register int len, 661: i; 662: register char *cp; 663: #ifndef BERK 664: register char *pp; 665: char buffer[BUFSIZ]; 666: #endif not BERK 667: register struct mailname *mp; 668: static char *am = NULL; 669: static struct mailname mq; 670: 671: /* if this is the first call, init. alternate mailboxes list */ 672: if (am == NULL) { 673: mq.m_next = NULL; 674: mq.m_mbox = getusr (); 675: if ((am = m_find ("alternate-mailboxes")) == NULL) 676: am = getusr (); 677: else { 678: mp = &mq; 679: oops = 0; 680: while (cp = getname (am)) 681: if ((mp -> m_next = getm (cp, NULLCP, 0, AD_NAME, NULLCP)) 682: == NULL) 683: admonish (NULLCP, "illegal address: %s", cp), oops++; 684: else { 685: mp = mp -> m_next; 686: mp -> m_type = W_NIL; 687: #ifdef BERK 688: /* check for wildcards on the mailbox name and 689: set m_type accordingly. */ 690: mp -> m_ingrp = strlen (mp -> m_mbox); 691: if (*(mp -> m_mbox) == '*') { 692: mp -> m_type |= W_MBEG; 693: mp -> m_mbox++; 694: --mp -> m_ingrp; 695: } 696: if (mp -> m_mbox[mp -> m_ingrp - 1] == '*') { 697: mp -> m_type |= W_MEND; 698: mp -> m_ingrp--; 699: mp -> m_mbox[mp -> m_ingrp] = NULL; 700: } 701: #else not BERK 702: /* owing to screwy munging, wildcarding is a great idea 703: even under #ifndef BERK, so... */ 704: mp -> m_type = W_NIL; 705: if (*mp -> m_mbox == '*') 706: mp -> m_type |= W_MBEG, mp -> m_mbox++; 707: if (*(cp = mp -> m_mbox + strlen (mp -> m_mbox) - 1) 708: == '*') 709: mp -> m_type |= W_MEND, *cp = NULL; 710: if (mp -> m_host) { 711: if (*mp -> m_host == '*') 712: mp -> m_type |= W_HBEG, mp -> m_host++; 713: if (*(cp = mp -> m_host + strlen (mp -> m_host) - 1) 714: == '*') 715: mp -> m_type |= W_HEND, *cp = NULL; 716: } 717: if ((cp = getenv ("MHWDEBUG")) && *cp) 718: fprintf (stderr, "mbox=\"%s\" host=\"%s\" %s\n", 719: mp -> m_mbox, mp -> m_host, 720: sprintb (buffer, (unsigned) mp -> m_type, WBITS)); 721: #endif not BERK 722: } 723: if (oops) 724: advise (NULLCP, "please fix the %s: entry in your %s file", 725: "alternate-mailboxes", mh_profile); 726: } 727: } 728: if (np == NULL) /* XXX */ 729: return 0; 730: 731: #ifdef BERK 732: cp = np -> m_mbox; 733: if (strcmp (cp, mq.m_mbox) == 0) 734: return 1; 735: #else not BERK 736: switch (np -> m_type) { 737: case NETHOST: 738: len = strlen (cp = LocalName ()); 739: if (uprf (np -> m_host, cp) || np -> m_host[len] != '.') 740: break; 741: goto local_test; 742: 743: case UUCPHOST: 744: if (!uleq (np -> m_host, SystemName ())) 745: break; /* fall */ 746: case LOCALHOST: 747: local_test: ; 748: if (uleq (np -> m_mbox, mq.m_text)) 749: return 1; 750: break; 751: 752: default: 753: break; 754: } 755: #endif not BERK 756: 757: #ifdef BERK 758: len = strlen (cp); 759: for (mp = &mq; mp = mp -> m_next;) 760: if (len >= mp -> m_ingrp) 761: switch (mp -> m_type) { 762: case W_NIL: /* no wildcards */ 763: if (strcmp (cp, mp -> m_mbox) == 0) 764: return 1; 765: break; 766: 767: case W_MBEG: /* wildcard at beginning */ 768: if (strcmp (&cp[len - mp -> m_ingrp], mp -> m_mbox) == 0) 769: return 1; 770: break; 771: 772: case W_MEND: /* wildcard at end */ 773: if (strncmp (cp, mp -> m_mbox, mp -> m_ingrp) == 0) 774: return 1; 775: break; 776: 777: case W_MBEG | W_MEND: /* wildcard at beginning & end */ 778: for (i = 0; i <= len - mp -> m_ingrp; i++) 779: if (strncmp (&cp[i], mp -> m_mbox, mp -> m_ingrp) == 0) 780: return 1; 781: } 782: #else not BERK 783: for (mp = &mq; mp = mp -> m_next;) { 784: if ((len = strlen (cp = np -> m_mbox)) 785: < (i = strlen (pp = mp -> m_mbox))) 786: continue; 787: switch (mp -> m_type & W_MBOX) { 788: case W_NIL: 789: if (!uleq (cp, pp)) 790: continue; 791: break; 792: case W_MBEG: 793: if (!uleq (cp + len - i, pp)) 794: continue; 795: break; 796: case W_MEND: 797: if (!uprf (cp, pp)) 798: continue; 799: break; 800: case W_MBEG | W_MEND: 801: if (stringdex (pp, cp) < 0) 802: continue; 803: break; 804: } 805: 806: if (mp -> m_nohost) 807: return 1; 808: if ((len = strlen (cp = np -> m_host)) 809: < (i = strlen (pp = mp -> m_host))) 810: continue; 811: switch (mp -> m_type & W_HOST) { 812: case W_NIL: 813: if (!uleq (cp, pp)) 814: continue; 815: break; 816: case W_HBEG: 817: if (!uleq (cp + len - i, pp)) 818: continue; 819: break; 820: case W_HEND: 821: if (!uprf (cp, pp)) 822: continue; 823: break; 824: case W_HBEG | W_HEND: 825: if (stringdex (pp, cp) < 0) 826: continue; 827: break; 828: } 829: return 1; 830: } 831: #endif not BERK 832: 833: return 0; 834: }