2 ** addrsbr.c -- parse addresses 822-style
4 ** This code is Copyright (c) 2002, by the authors of nmh. See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
10 #include <h/addrsbr.h>
14 ** High level parsing of addresses:
16 ** The routines in sbr/mf.c parse the syntactic representations of
17 ** addresses. The routines in sbr/addrsbr.c associate semantics with those
20 ** A full 822-style parser is called for syntax recongition. This breaks
21 ** each address into its components. Note however that no semantics are
22 ** assumed about the parts or their totality. This means that implicit
23 ** hostnames aren't made explicit, and explicit hostnames aren't expanded
24 ** to their "official" represenations.
26 ** To summarize, when we're all done, here's what MH knows about the address:
27 ** type: local or network
28 ** host: not locally defaulted, not explicitly expanded
34 static char *pers = NULL;
35 static char *mbox = NULL;
36 static char *host = NULL;
37 static char *route = NULL;
38 static char *grp = NULL;
39 static char *note = NULL;
40 static char err[BUFSIZ];
41 static char adr[BUFSIZ];
49 pers = mbox = host = route = grp = note = NULL;
52 if ((ap = getadrx(addrs ? addrs : "")) == NULL)
55 strncpy(adr, ap->text, sizeof(adr));
63 if (ap->err && *ap->err)
64 strncpy(err, ap->err, sizeof(err));
71 getm(char *str, char *dfhost, int dftype, int wanthost, char *eresult)
79 if (wanthost == AD_HOST)
80 admonish(NULL, "bad address '%s' - %s", str, err);
83 if (pers == NULL && mbox == NULL && host == NULL && route == NULL
86 strcpy(eresult, "null address");
88 if (wanthost == AD_HOST)
89 admonish(NULL, "null address '%s'", str);
92 if (mbox == NULL && grp == NULL) {
94 strcpy(eresult, "no mailbox in address");
95 else if (wanthost == AD_HOST)
96 admonish(NULL, "no mailbox in address '%s'", str);
100 if (dfhost == NULL) {
101 dfhost = LocalName();
105 mp = (struct mailname *) calloc((size_t) 1, sizeof(*mp));
108 strcpy(eresult, "insufficient memory to represent address");
109 else if (wanthost == AD_HOST)
110 adios(NULL, "insufficient memory to represent address");
115 mp->m_text = getcpy(str);
117 mp->m_pers = getcpy(pers);
120 mp->m_type = BADHOST;
123 mp->m_gname = getcpy(grp);
125 mp->m_note = getcpy(note);
130 mp->m_mbox = getcpy(mbox);
131 mp->m_host = getcpy(host);
134 mp->m_mbox = getcpy(mbox);
135 if (route == NULL && dftype == LOCALHOST) {
139 mp->m_host = route ? NULL : getcpy(dfhost);
140 mp->m_type = route ? NETHOST : dftype;
145 if (wanthost == AD_NHST)
146 mp->m_type = !mh_strcasecmp(LocalName(), mp->m_host)
147 ? LOCALHOST : NETHOST;
149 mp->m_type = mh_strcasecmp(LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
153 mp->m_path = getcpy(route);
156 mp->m_gname = getcpy(grp);
158 mp->m_note = getcpy(note);
165 mnfree(struct mailname *mp)
189 #define empty(s) ((s) ? (s) : "")
192 adrformat(struct mailname *mp)
194 static char addr[BUFSIZ];
195 static char buffer[BUFSIZ];
198 strncpy(addr, mp->m_mbox ? mp->m_mbox : "", sizeof(addr));
200 snprintf(addr, sizeof(addr), mp->m_host ? "%s%s@%s" : "%s%s",
201 empty(mp->m_path), empty(mp->m_mbox), mp->m_host);
203 if (mp->m_pers || mp->m_path) {
205 snprintf(buffer, sizeof(buffer), "%s %s <%s>",
206 legal_person(mp->m_pers ? mp->m_pers : mp->m_mbox),
209 snprintf(buffer, sizeof(buffer), "%s <%s>",
210 legal_person(mp->m_pers ? mp->m_pers : mp->m_mbox),
212 } else if (mp->m_note)
213 snprintf(buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
215 strncpy(buffer, addr, sizeof(buffer));
222 #define W_MBEG 0x0001
223 #define W_MEND 0x0002
224 #define W_MBOX (W_MBEG | W_MEND)
225 #define W_HBEG 0x0004
226 #define W_HEND 0x0008
227 #define W_HOST (W_HBEG | W_HEND)
228 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
231 ** Check if this is my address
235 ismymbox(struct mailname *np)
243 static char *am = NULL;
244 static struct mailname mq={NULL};
247 ** If this is the first call, initialize
248 ** list of alternate mailboxes.
252 mq.m_mbox = getusername();
253 if ((am = context_find("alternate-mailboxes")) == NULL)
258 while ((cp = getname(am))) {
259 if ((mp->m_next = getm(cp, NULL, 0, AD_NAME, NULL)) == NULL) {
260 admonish(NULL, "illegal address: %s", cp);
265 if (*mp->m_mbox == '*') {
266 mp->m_type |= W_MBEG;
269 if (*(cp = mp->m_mbox + strlen(mp->m_mbox) - 1) == '*') {
270 mp->m_type |= W_MEND;
274 if (*mp->m_host == '*') {
275 mp->m_type |= W_HBEG;
278 if (*(cp = mp->m_host + strlen(mp->m_host) - 1) == '*') {
279 mp->m_type |= W_HEND;
283 if ((cp = getenv("MHWDEBUG")) && *cp)
284 fprintf(stderr, "mbox=\"%s\" host=\"%s\" %s\n",
285 mp->m_mbox, mp->m_host,
286 snprintb(buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
290 advise(NULL, "please fix the profile entry %s",
291 "alternate-mailboxes");
295 if (np == NULL) /* XXX */
298 switch (np->m_type) {
300 len = strlen(cp = LocalName());
301 if (!uprf(np->m_host, cp) || np->m_host[len] != '.')
307 if (!mh_strcasecmp(np->m_mbox, mq.m_mbox))
316 ** Now scan through list of alternate
317 ** mailboxes, and check for a match.
319 for (mp = &mq; mp->m_next;) {
323 if ((len = strlen(cp = np->m_mbox))
324 < (i = strlen(pp = mp->m_mbox)))
326 switch (mp->m_type & W_MBOX) {
328 if (mh_strcasecmp(cp, pp))
332 if (mh_strcasecmp(cp + len - i, pp))
339 case W_MBEG | W_MEND:
340 if (stringdex(pp, cp) < 0)
347 if (np->m_host == NULL)
349 if ((len = strlen(cp = np->m_host))
350 < (i = strlen(pp = mp->m_host)))
352 switch (mp->m_type & W_HOST) {
354 if (mh_strcasecmp(cp, pp))
358 if (mh_strcasecmp (cp + len - i, pp))
365 case W_HBEG | W_HEND:
366 if (stringdex(pp, cp) < 0)