3 * addrsbr.c -- parse addresses 822-style
10 #include <zotnet/mf/mf.h>
12 /* High level parsing of addresses:
14 The routines in zotnet/mf/mf.c parse the syntactic representations of
15 addresses. The routines in sbr/addrsbr.c associate semantics with those
18 If #ifdef DUMB is in effect, a full 822-style parser is called
19 for syntax recongition. This breaks each address into its components.
20 Note however that no semantics are assumed about the parts or their
21 totality. This means that implicit hostnames aren't made explicit,
22 and explicit hostnames aren't expanded to their "official" represenations.
24 If DUMB is not in effect, then this module does some
25 high-level thinking about what the addresses are.
29 string%<uucp>@<local> -> string
31 2. for non-MMDF systems:
33 string@host.<uucp> -> host!string
35 3. for any system, an address interpreted relative to the local host:
37 string@<uucp> -> string
39 For cases (1) and (3) above, the leftmost host is extracted. If it's not
40 present, the local host is used. If the tests above fail, the address is
41 considered to be a real 822-style address.
43 If an explicit host is not present, then MH checks for a bang to indicate
44 an explicit UUCP-style address. If so, this is noted. If not, the host is
45 defaulted, typically to the local host. The lack of an explict host is
48 If an explicit 822-style host is present, then MH checks to see if it
49 can expand this to the official name for the host. If the hostname is
50 unknown, the address is so typed.
52 To summarize, when we're all done, here's what MH knows about the address:
54 DUMB - type: local, uucp, or network
55 host: not locally defaulted, not explicitly expanded
58 other - type: local, uucp, network, unknown
64 static char *pers = NULL;
65 static char *mbox = NULL;
66 static char *host = NULL;
67 static char *route = NULL;
68 static char *grp = NULL;
69 static char *note = NULL;
70 static char err[BUFSIZ];
71 static char adr[BUFSIZ];
76 char *getusername (void);
84 pers = mbox = host = route = grp = note = NULL;
87 if ((ap = getadrx (addrs ? addrs : "")) == NULL)
90 strncpy (adr, ap->text, sizeof(adr));
98 if (ap->err && *ap->err)
99 strncpy (err, ap->err, sizeof(err));
106 getm (char *str, char *dfhost, int dftype, int wanthost, char *eresult)
112 #endif /* not DUMB */
116 strcpy (eresult, err);
118 if (wanthost == AD_HOST)
119 admonish (NULL, "bad address '%s' - %s", str, err);
123 && mbox == NULL && host == NULL && route == NULL
126 strcpy (eresult, "null address");
128 if (wanthost == AD_HOST)
129 admonish (NULL, "null address '%s'", str);
132 if (mbox == NULL && grp == NULL) {
134 strcpy (eresult, "no mailbox in address");
136 if (wanthost == AD_HOST)
137 admonish (NULL, "no mailbox in address '%s'", str);
141 if (dfhost == NULL) {
142 dfhost = LocalName ();
146 mp = (struct mailname *) calloc ((size_t) 1, sizeof(*mp));
149 strcpy (eresult, "insufficient memory to represent address");
151 if (wanthost == AD_HOST)
152 adios (NULL, "insufficient memory to represent address");
157 mp->m_text = getcpy (str);
159 mp->m_pers = getcpy (pers);
162 mp->m_type = BADHOST;
165 mp->m_gname = getcpy (grp);
167 mp->m_note = getcpy (note);
172 mp->m_mbox = getcpy (mbox);
173 mp->m_host = getcpy (host);
176 if ((pp = strchr(mbox, '!'))) {
178 mp->m_mbox = getcpy (pp);
179 mp->m_host = getcpy (mbox);
180 mp->m_type = UUCPHOST;
184 mp->m_mbox = getcpy (mbox);
186 if (route == NULL && dftype == LOCALHOST) {
193 mp->m_host = route ? NULL : getcpy (dfhost);
194 mp->m_type = route ? NETHOST : dftype;
200 if (wanthost == AD_NHST)
201 mp->m_type = !strcasecmp (LocalName (), mp->m_host)
202 ? LOCALHOST : NETHOST;
205 mp->m_type = strcasecmp (LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
208 if (pp = OfficialName (mp->m_host)) {
211 mp->m_host = getcpy (pp);
212 mp->m_type = strcasecmp (LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
215 if (dp = strchr(mp->m_host, '.')) {
217 if (pp = OfficialName (mp->m_host))
221 mp->m_type = BADHOST;
223 #endif /* not DUMB */
227 mp->m_path = getcpy (route);
230 mp->m_gname = getcpy (grp);
232 mp->m_note = getcpy (note);
239 mnfree (struct mailname *mp)
263 #define empty(s) ((s) ? (s) : "")
266 auxformat (struct mailname *mp, int extras)
268 static char addr[BUFSIZ];
269 static char buffer[BUFSIZ];
273 strncpy (addr, mp->m_mbox ? mp->m_mbox : "", sizeof(addr));
278 if (mp->m_type != UUCPHOST)
279 snprintf (addr, sizeof(addr), mp->m_host ? "%s%s@%s" : "%s%s",
280 empty(mp->m_path), empty(mp->m_mbox), mp->m_host);
282 #endif /* not BANG */
283 snprintf (addr, sizeof(addr), "%s!%s", mp->m_host, mp->m_mbox);
288 if (mp->m_pers || mp->m_path)
290 snprintf (buffer, sizeof(buffer), "%s %s <%s>",
291 legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox),
294 snprintf (buffer, sizeof(buffer), "%s <%s>",
295 legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox),
299 snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
301 strncpy (buffer, addr, sizeof(buffer));
308 * address specific "sprintf"
312 adrsprintf (char *local, char *domain)
314 static char addr[BUFSIZ];
318 return getusername ();
320 #endif /* REALLYDUMB */
321 local = getusername ();
327 #endif /* REALLYDUMB */
328 domain = LocalName ();
331 snprintf (addr, sizeof(addr), "%s@%s", local, domain);
333 snprintf (addr, sizeof(addr), "%s!%s", domain, local);
341 #define W_MBEG 0x0001
342 #define W_MEND 0x0002
343 #define W_MBOX (W_MBEG | W_MEND)
344 #define W_HBEG 0x0004
345 #define W_HEND 0x0008
346 #define W_HOST (W_HBEG | W_HEND)
347 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
350 * Check if this is my address
354 ismymbox (struct mailname *np)
362 static char *am = NULL;
363 static struct mailname mq={NULL};
366 * If this is the first call, initialize
367 * list of alternate mailboxes.
371 mq.m_mbox = getusername ();
372 if ((am = context_find ("alternate-mailboxes")) == NULL)
377 while ((cp = getname (am))) {
378 if ((mp->m_next = getm (cp, NULL, 0, AD_NAME, NULL)) == NULL) {
379 admonish (NULL, "illegal address: %s", cp);
384 if (*mp->m_mbox == '*') {
385 mp->m_type |= W_MBEG;
388 if (*(cp = mp->m_mbox + strlen (mp->m_mbox) - 1) == '*') {
389 mp->m_type |= W_MEND;
393 if (*mp->m_host == '*') {
394 mp->m_type |= W_HBEG;
397 if (*(cp = mp->m_host + strlen (mp->m_host) - 1) == '*') {
398 mp->m_type |= W_HEND;
402 if ((cp = getenv ("MHWDEBUG")) && *cp)
403 fprintf (stderr, "mbox=\"%s\" host=\"%s\" %s\n",
404 mp->m_mbox, mp->m_host,
405 snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
409 advise (NULL, "please fix the %s: entry in your %s file",
410 "alternate-mailboxes", mh_profile);
414 if (np == NULL) /* XXX */
417 switch (np->m_type) {
419 len = strlen (cp = LocalName ());
420 if (!uprf (np->m_host, cp) || np->m_host[len] != '.')
425 if (strcasecmp (np->m_host, SystemName()))
429 if (!strcasecmp (np->m_mbox, mq.m_mbox))
438 * Now scan through list of alternate
439 * mailboxes, and check for a match.
441 for (mp = &mq; mp->m_next;) {
445 if ((len = strlen (cp = np->m_mbox))
446 < (i = strlen (pp = mp->m_mbox)))
448 switch (mp->m_type & W_MBOX) {
450 if (strcasecmp (cp, pp))
454 if (strcasecmp (cp + len - i, pp))
461 case W_MBEG | W_MEND:
462 if (stringdex (pp, cp) < 0)
469 if (np->m_host == NULL)
471 if ((len = strlen (cp = np->m_host))
472 < (i = strlen (pp = mp->m_host)))
474 switch (mp->m_type & W_HOST) {
476 if (strcasecmp (cp, pp))
480 if (strcasecmp (cp + len - i, pp))
487 case W_HBEG | W_HEND:
488 if (stringdex (pp, cp) < 0)