]>
diplodocus.org Git - nmh/blob - sbr/addrsbr.c
3 * addrsbr.c -- parse addresses 822-style
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
11 #include <h/addrsbr.h>
15 /* High level parsing of addresses:
17 The routines in sbr/mf.c parse the syntactic representations of
18 addresses. The routines in sbr/addrsbr.c associate semantics with those
21 The comments below are left in for historical purposes; DUMB and
22 REALLYDUMB are now the default in the code.
24 If #ifdef DUMB is in effect, a full 822-style parser is called
25 for syntax recongition. This breaks each address into its components.
26 Note however that no semantics are assumed about the parts or their
27 totality. This means that implicit hostnames aren't made explicit,
28 and explicit hostnames aren't expanded to their "official" represenations.
30 If DUMB is not in effect, then this module does some
31 high-level thinking about what the addresses are.
35 string%<uucp>@<local> -> string
37 2. for non-MMDF systems:
39 string@host.<uucp> -> host!string
41 3. for any system, an address interpreted relative to the local host:
43 string@<uucp> -> string
45 For cases (1) and (3) above, the leftmost host is extracted. If it's not
46 present, the local host is used. If the tests above fail, the address is
47 considered to be a real 822-style address.
49 If an explicit host is not present, then MH checks for a bang to indicate
50 an explicit UUCP-style address. If so, this is noted. If not, the host is
51 defaulted, typically to the local host. The lack of an explict host is
54 If an explicit 822-style host is present, then MH checks to see if it
55 can expand this to the official name for the host. If the hostname is
56 unknown, the address is so typed.
58 To summarize, when we're all done, here's what MH knows about the address:
60 DUMB - type: local, uucp, or network
61 host: not locally defaulted, not explicitly expanded
64 other - type: local, uucp, network, unknown
70 static char *pers
= NULL
;
71 static char *mbox
= NULL
;
72 static char *host
= NULL
;
73 static char *route
= NULL
;
74 static char *grp
= NULL
;
75 static char *note
= NULL
;
76 static char err
[BUFSIZ
];
77 static char adr
[BUFSIZ
];
81 getname (const char *addrs
)
85 pers
= mbox
= host
= route
= grp
= note
= NULL
;
88 if ((ap
= getadrx (addrs
? addrs
: "")) == NULL
)
91 strncpy (adr
, ap
->text
, sizeof(adr
));
99 if (ap
->err
&& *ap
->err
)
100 strncpy (err
, ap
->err
, sizeof(err
));
107 getm (char *str
, char *dfhost
, int dftype
, char *eresult
, size_t eresultsize
)
114 strncpy (eresult
, err
, eresultsize
);
115 eresult
[eresultsize
- 1] = '\0';
120 && mbox
== NULL
&& host
== NULL
&& route
== NULL
123 strncpy (eresult
, "null address", eresultsize
);
124 eresult
[eresultsize
- 1] = '\0';
128 if (mbox
== NULL
&& grp
== NULL
) {
130 strncpy (eresult
, "no mailbox in address", eresultsize
);
131 eresult
[eresultsize
- 1] = '\0';
136 if (dfhost
== NULL
) {
137 dfhost
= LocalName (0);
141 mp
= (struct mailname
*) calloc ((size_t) 1, sizeof(*mp
));
144 strncpy (eresult
, "insufficient memory to represent address",
146 eresult
[eresultsize
- 1] = '\0';
152 mp
->m_text
= getcpy (str
);
154 mp
->m_pers
= getcpy (pers
);
157 mp
->m_type
= BADHOST
;
160 mp
->m_gname
= getcpy (grp
);
162 mp
->m_note
= getcpy (note
);
167 mp
->m_mbox
= getcpy (mbox
);
168 mp
->m_host
= getcpy (host
);
170 strcasecmp (LocalName(0), mp
->m_host
) ? NETHOST
: LOCALHOST
;
172 if ((pp
= strchr(mbox
, '!'))) {
174 mp
->m_mbox
= getcpy (pp
);
175 mp
->m_host
= getcpy (mbox
);
176 mp
->m_type
= UUCPHOST
;
179 mp
->m_mbox
= getcpy (mbox
);
180 if (route
== NULL
&& dftype
== LOCALHOST
) {
184 mp
->m_host
= route
? NULL
: getcpy (dfhost
);
185 mp
->m_type
= route
? NETHOST
: dftype
;
190 /* For alternate mailboxes, m_type gets overwritten in ismymbox ()
191 to support wild-card matching. */
194 mp
->m_path
= getcpy (route
);
197 mp
->m_gname
= getcpy (grp
);
199 mp
->m_note
= getcpy (note
);
206 mnfree (struct mailname
*mp
)
230 #define empty(s) ((s) ? (s) : "")
233 auxformat (struct mailname
*mp
, int extras
)
235 static char addr
[BUFSIZ
];
236 static char buffer
[BUFSIZ
];
239 strncpy (addr
, mp
->m_mbox
? mp
->m_mbox
: "", sizeof(addr
));
242 if (mp
->m_type
!= UUCPHOST
) {
244 snprintf (addr
, sizeof(addr
), "%s%s@%s", empty(mp
->m_path
),
245 empty(mp
->m_mbox
), mp
->m_host
);
246 else snprintf (addr
, sizeof(addr
), "%s%s", empty(mp
->m_path
),
249 snprintf (addr
, sizeof(addr
), "%s!%s", mp
->m_host
, mp
->m_mbox
);
254 if (mp
->m_pers
|| mp
->m_path
) {
256 snprintf (buffer
, sizeof(buffer
), "%s %s <%s>",
257 legal_person (mp
->m_pers
? mp
->m_pers
: mp
->m_mbox
),
260 snprintf (buffer
, sizeof(buffer
), "%s <%s>",
261 legal_person (mp
->m_pers
? mp
->m_pers
: mp
->m_mbox
),
266 snprintf (buffer
, sizeof(buffer
), "%s %s", addr
, mp
->m_note
);
268 strncpy (buffer
, addr
, sizeof(buffer
));
275 #define W_MBEG 0x0001
276 #define W_MEND 0x0002
277 #define W_MBOX (W_MBEG | W_MEND)
278 #define W_HBEG 0x0004
279 #define W_HEND 0x0008
280 #define W_HOST (W_HBEG | W_HEND)
281 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
284 * Check if this is my address
288 ismymbox (struct mailname
*np
)
296 static char *am
= NULL
;
297 static struct mailname mq
;
298 static int localmailbox
= 0;
301 * If this is the first call, initialize
302 * list of alternate mailboxes.
306 mq
.m_mbox
= getusername ();
308 if ((am
= context_find ("local-mailbox"))) {
312 if ((cp
= getname(am
)) == NULL
) {
313 admonish (NULL
, "Unable to find address in local-mailbox");
317 if ((mq
.m_next
= getm (cp
, NULL
, 0, NULL
, 0)) == NULL
) {
318 admonish (NULL
, "invalid entry in local-mailbox: %s", cp
);
323 * Sigh, it turns out that the address parser gets messed up
324 * if you don't call getname() until it returns NULL.
327 while ((cp
= getname(am
)) != NULL
)
331 if ((am
= context_find ("alternate-mailboxes")) == NULL
)
334 mp
= mq
.m_next
? mq
.m_next
: &mq
;
336 while ((cp
= getname (am
))) {
337 if ((mp
->m_next
= getm (cp
, NULL
, 0, NULL
, 0)) == NULL
) {
338 admonish (NULL
, "illegal address: %s", cp
);
343 if (*mp
->m_mbox
== '*') {
344 mp
->m_type
|= W_MBEG
;
347 if (*(cp
= mp
->m_mbox
+ strlen (mp
->m_mbox
) - 1) == '*') {
348 mp
->m_type
|= W_MEND
;
352 if (*mp
->m_host
== '*') {
353 mp
->m_type
|= W_HBEG
;
356 if (*(cp
= mp
->m_host
+ strlen (mp
->m_host
) - 1) == '*') {
357 mp
->m_type
|= W_HEND
;
364 advise (NULL
, "please fix the %s: entry in your %s file",
365 "alternate-mailboxes", mh_profile
);
368 if ((cp
= getenv ("MHWDEBUG")) && *cp
) {
369 for (mp
= &mq
; mp
; mp
= mp
->m_next
) {
370 fprintf (stderr
, "Local- or Alternate-Mailbox: text=\"%s\" "
371 "mbox=\"%s\" host=\"%s\" %s\n",
372 mp
->m_text
? mp
->m_text
: "", mp
->m_mbox
,
373 mp
->m_host
? mp
->m_host
: "",
374 snprintb (buffer
, sizeof(buffer
), (unsigned) mp
->m_type
,
380 if (np
== NULL
) /* XXX */
384 * Don't perform this "local" test if we have a Local-Mailbox set
388 switch (np
->m_type
) {
390 len
= strlen (cp
= LocalName (0));
391 if (!uprf (np
->m_host
, cp
) || np
->m_host
[len
] != '.')
396 if (strcasecmp (np
->m_host
, SystemName()))
400 if (!strcasecmp (np
->m_mbox
, mq
.m_mbox
))
409 * Now scan through list of alternate
410 * mailboxes, and check for a match.
412 for (mp
= &mq
; mp
->m_next
;) {
415 continue; if ((len
= strlen (cp
= np
->m_mbox
))
416 < (i
= strlen (pp
= mp
->m_mbox
)))
418 switch (mp
->m_type
& W_MBOX
) {
420 if (strcasecmp (cp
, pp
))
424 if (strcasecmp (cp
+ len
- i
, pp
))
431 case W_MBEG
| W_MEND
:
432 if (stringdex (pp
, cp
) < 0)
439 if (np
->m_host
== NULL
)
441 if ((len
= strlen (cp
= np
->m_host
))
442 < (i
= strlen (pp
= mp
->m_host
)))
444 switch (mp
->m_type
& W_HOST
) {
446 if (strcasecmp (cp
, pp
))
450 if (strcasecmp (cp
+ len
- i
, pp
))
457 case W_HBEG
| W_HEND
:
458 if (stringdex (pp
, cp
) < 0)