|
|
1.1 root 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". - [email protected]).
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.