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),
300 snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
302 strncpy (buffer, addr, sizeof(buffer));
309 * address specific "sprintf"
313 adrsprintf (char *local, char *domain)
315 static char addr[BUFSIZ];
319 return getusername ();
321 #endif /* REALLYDUMB */
322 local = getusername ();
328 #endif /* REALLYDUMB */
329 domain = LocalName ();
332 snprintf (addr, sizeof(addr), "%s@%s", local, domain);
334 snprintf (addr, sizeof(addr), "%s!%s", domain, local);
342 #define W_MBEG 0x0001
343 #define W_MEND 0x0002
344 #define W_MBOX (W_MBEG | W_MEND)
345 #define W_HBEG 0x0004
346 #define W_HEND 0x0008
347 #define W_HOST (W_HBEG | W_HEND)
348 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
351 * Check if this is my address
355 ismymbox (struct mailname *np)
363 static char *am = NULL;
364 static struct mailname mq={NULL};
367 * If this is the first call, initialize
368 * list of alternate mailboxes.
372 mq.m_mbox = getusername ();
373 if ((am = context_find ("alternate-mailboxes")) == NULL)
378 while ((cp = getname (am))) {
379 if ((mp->m_next = getm (cp, NULL, 0, AD_NAME, NULL)) == NULL) {
380 admonish (NULL, "illegal address: %s", cp);
385 if (*mp->m_mbox == '*') {
386 mp->m_type |= W_MBEG;
389 if (*(cp = mp->m_mbox + strlen (mp->m_mbox) - 1) == '*') {
390 mp->m_type |= W_MEND;
394 if (*mp->m_host == '*') {
395 mp->m_type |= W_HBEG;
398 if (*(cp = mp->m_host + strlen (mp->m_host) - 1) == '*') {
399 mp->m_type |= W_HEND;
403 if ((cp = getenv ("MHWDEBUG")) && *cp)
404 fprintf (stderr, "mbox=\"%s\" host=\"%s\" %s\n",
405 mp->m_mbox, mp->m_host,
406 snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
410 advise (NULL, "please fix the %s: entry in your %s file",
411 "alternate-mailboxes", mh_profile);
415 if (np == NULL) /* XXX */
418 switch (np->m_type) {
420 len = strlen (cp = LocalName ());
421 if (!uprf (np->m_host, cp) || np->m_host[len] != '.')
426 if (strcasecmp (np->m_host, SystemName()))
430 if (!strcasecmp (np->m_mbox, mq.m_mbox))
439 * Now scan through list of alternate
440 * mailboxes, and check for a match.
442 for (mp = &mq; mp->m_next;) {
446 if ((len = strlen (cp = np->m_mbox))
447 < (i = strlen (pp = mp->m_mbox)))
449 switch (mp->m_type & W_MBOX) {
451 if (strcasecmp (cp, pp))
455 if (strcasecmp (cp + len - i, pp))
462 case W_MBEG | W_MEND:
463 if (stringdex (pp, cp) < 0)
470 if (np->m_host == NULL)
472 if ((len = strlen (cp = np->m_host))
473 < (i = strlen (pp = mp->m_host)))
475 switch (mp->m_type & W_HOST) {
477 if (strcasecmp (cp, pp))
481 if (strcasecmp (cp + len - i, pp))
488 case W_HBEG | W_HEND:
489 if (stringdex (pp, cp) < 0)