3 * addrsbr.c -- parse addresses 822-style
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];
74 extern boolean username_extension_masquerading; /* defined in mts.c */
80 char *getusername (void);
88 pers = mbox = host = route = grp = note = NULL;
91 if ((ap = getadrx (addrs ? addrs : "")) == NULL)
94 strncpy (adr, ap->text, sizeof(adr));
102 if (ap->err && *ap->err)
103 strncpy (err, ap->err, sizeof(err));
110 getm (char *str, char *dfhost, int dftype, int wanthost, char *eresult)
116 #endif /* not DUMB */
120 strcpy (eresult, err);
122 if (wanthost == AD_HOST)
123 admonish (NULL, "bad address '%s' - %s", str, err);
127 && mbox == NULL && host == NULL && route == NULL
130 strcpy (eresult, "null address");
132 if (wanthost == AD_HOST)
133 admonish (NULL, "null address '%s'", str);
136 if (mbox == NULL && grp == NULL) {
138 strcpy (eresult, "no mailbox in address");
140 if (wanthost == AD_HOST)
141 admonish (NULL, "no mailbox in address '%s'", str);
145 if (dfhost == NULL) {
146 dfhost = LocalName ();
150 mp = (struct mailname *) calloc ((size_t) 1, sizeof(*mp));
153 strcpy (eresult, "insufficient memory to represent address");
155 if (wanthost == AD_HOST)
156 adios (NULL, "insufficient memory to represent address");
161 mp->m_text = getcpy (str);
163 mp->m_pers = getcpy (pers);
166 mp->m_type = BADHOST;
169 mp->m_gname = getcpy (grp);
171 mp->m_note = getcpy (note);
176 mp->m_mbox = getcpy (mbox);
177 mp->m_host = getcpy (host);
180 if ((pp = strchr(mbox, '!'))) {
182 mp->m_mbox = getcpy (pp);
183 mp->m_host = getcpy (mbox);
184 mp->m_type = UUCPHOST;
188 mp->m_mbox = getcpy (mbox);
190 if (route == NULL && dftype == LOCALHOST) {
197 mp->m_host = route ? NULL : getcpy (dfhost);
198 mp->m_type = route ? NETHOST : dftype;
204 if (wanthost == AD_NHST)
205 mp->m_type = !strcasecmp (LocalName (), mp->m_host)
206 ? LOCALHOST : NETHOST;
209 mp->m_type = strcasecmp (LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
212 if (pp = OfficialName (mp->m_host)) {
215 mp->m_host = getcpy (pp);
216 mp->m_type = strcasecmp (LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
219 if (dp = strchr(mp->m_host, '.')) {
221 if (pp = OfficialName (mp->m_host))
225 mp->m_type = BADHOST;
227 #endif /* not DUMB */
231 mp->m_path = getcpy (route);
234 mp->m_gname = getcpy (grp);
236 mp->m_note = getcpy (note);
243 mnfree (struct mailname *mp)
267 #define empty(s) ((s) ? (s) : "")
270 auxformat (struct mailname *mp, int extras)
272 static char addr[BUFSIZ];
273 static char buffer[BUFSIZ];
277 strncpy (addr, mp->m_mbox ? mp->m_mbox : "", sizeof(addr));
282 if (mp->m_type != UUCPHOST)
283 snprintf (addr, sizeof(addr), mp->m_host ? "%s%s@%s" : "%s%s",
284 empty(mp->m_path), empty(mp->m_mbox), mp->m_host);
286 #endif /* not BANG */
287 snprintf (addr, sizeof(addr), "%s!%s", mp->m_host, mp->m_mbox);
292 if (mp->m_pers || mp->m_path) {
294 snprintf (buffer, sizeof(buffer), "%s %s <%s>",
295 legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox),
298 snprintf (buffer, sizeof(buffer), "%s <%s>",
299 legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox),
304 snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
306 strncpy (buffer, addr, sizeof(buffer));
313 * address specific "sprintf"
317 adrsprintf (char *username, char *domain)
320 static char addr[BUFSIZ];
322 if (username == NULL)
323 username = getusername();
325 if (username_extension_masquerading) {
326 /* mts.conf contains "masquerade:[...]username_extension[...]", so tack
327 on the value of the $USERNAME_EXTENSION environment variable, if set,
329 char* extension = getenv("USERNAME_EXTENSION");
330 static char username_with_extension[BUFSIZ];
332 if (extension != NULL && *extension != '\0') {
333 snprintf_return = snprintf(username_with_extension,
334 sizeof(username_with_extension),
335 "%s%s", username, extension);
337 if (snprintf_return < 0 ||
338 snprintf_return >= sizeof(username_with_extension))
339 adios(NULL, "snprintf() error writing username (%d chars) and"
340 " $USERNAME_EXTENSION (%d chars) to array of BUFSIZ (%d)"
342 strlen(username), strlen(extension), BUFSIZ);
344 username = username_with_extension;
353 domain = LocalName();
356 snprintf_return = snprintf (addr, sizeof(addr), "%s@%s", username, domain);
358 snprintf_return = snprintf (addr, sizeof(addr), "%s!%s", domain, username);
361 if (snprintf_return < 0 || snprintf_return >= sizeof(addr))
362 adios(NULL, "snprintf() error writing username (%d chars), domain (%d"
363 " chars), and 1 separator char to array of BUFSIZ (%d) chars",
364 strlen(username), strlen(domain), BUFSIZ);
371 #define W_MBEG 0x0001
372 #define W_MEND 0x0002
373 #define W_MBOX (W_MBEG | W_MEND)
374 #define W_HBEG 0x0004
375 #define W_HEND 0x0008
376 #define W_HOST (W_HBEG | W_HEND)
377 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
380 * Check if this is my address
384 ismymbox (struct mailname *np)
392 static char *am = NULL;
393 static struct mailname mq={NULL};
396 * If this is the first call, initialize
397 * list of alternate mailboxes.
401 mq.m_mbox = getusername ();
402 if ((am = context_find ("alternate-mailboxes")) == NULL)
407 while ((cp = getname (am))) {
408 if ((mp->m_next = getm (cp, NULL, 0, AD_NAME, NULL)) == NULL) {
409 admonish (NULL, "illegal address: %s", cp);
414 if (*mp->m_mbox == '*') {
415 mp->m_type |= W_MBEG;
418 if (*(cp = mp->m_mbox + strlen (mp->m_mbox) - 1) == '*') {
419 mp->m_type |= W_MEND;
423 if (*mp->m_host == '*') {
424 mp->m_type |= W_HBEG;
427 if (*(cp = mp->m_host + strlen (mp->m_host) - 1) == '*') {
428 mp->m_type |= W_HEND;
432 if ((cp = getenv ("MHWDEBUG")) && *cp)
433 fprintf (stderr, "mbox=\"%s\" host=\"%s\" %s\n",
434 mp->m_mbox, mp->m_host,
435 snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
439 advise (NULL, "please fix the %s: entry in your %s file",
440 "alternate-mailboxes", mh_profile);
444 if (np == NULL) /* XXX */
447 switch (np->m_type) {
449 len = strlen (cp = LocalName ());
450 if (!uprf (np->m_host, cp) || np->m_host[len] != '.')
455 if (strcasecmp (np->m_host, SystemName()))
459 if (!strcasecmp (np->m_mbox, mq.m_mbox))
468 * Now scan through list of alternate
469 * mailboxes, and check for a match.
471 for (mp = &mq; mp->m_next;) {
475 if ((len = strlen (cp = np->m_mbox))
476 < (i = strlen (pp = mp->m_mbox)))
478 switch (mp->m_type & W_MBOX) {
480 if (strcasecmp (cp, pp))
484 if (strcasecmp (cp + len - i, pp))
491 case W_MBEG | W_MEND:
492 if (stringdex (pp, cp) < 0)
499 if (np->m_host == NULL)
501 if ((len = strlen (cp = np->m_host))
502 < (i = strlen (pp = mp->m_host)))
504 switch (mp->m_type & W_HOST) {
506 if (strcasecmp (cp, pp))
510 if (strcasecmp (cp + len - i, pp))
517 case W_HBEG | W_HEND:
518 if (stringdex (pp, cp) < 0)