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: }

Defined functions

adrsprintf defined in line 615; never used
auxformat defined in line 540; never used
getm defined in line 316; used 4 times
getname defined in line 108; used 6 times
mnfree defined in line 510; used 3 times

Defined variables

adr defined in line 101; used 9 times
adrtext defined in line 88; used 2 times
err defined in line 99; used 17 times
grp defined in line 96; used 8 times
host defined in line 94; used 10 times
ingrp defined in line 90; used 4 times
mbox defined in line 93; used 15 times
note defined in line 97; used 7 times
pers defined in line 92; used 6 times
route defined in line 95; used 8 times

Defined macros

COM defined in line 148; used 7 times
EOA defined in line 150; used 5 times
ERR defined in line 149; used 5 times
MF defined in line 82; used 4 times
NORMAL defined in line 146; used 13 times
QS defined in line 147; used 5 times
REALLYDUMB defined in line 610; used 3 times
UucpChan defined in line 83; used 2 times
WBITS defined in line 653; used 1 times
W_HBEG defined in line 650; used 3 times
W_HEND defined in line 651; used 2 times
W_HOST defined in line 652; used 1 times
W_MBEG defined in line 647; used 5 times
W_MBOX defined in line 649; used 1 times
W_MEND defined in line 648; used 3 times
W_NIL defined in line 646; used 2 times
Last modified: 1986-04-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2510
Valid CSS Valid XHTML 1.0 Strict