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.
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 ** A full 822-style parser is called for syntax recongition. This breaks
22 ** each address into its components. Note however that no semantics are
23 ** assumed about the parts or their totality. This means that implicit
24 ** hostnames aren't made explicit, and explicit hostnames aren't expanded
25 ** to their "official" represenations.
27 ** To summarize, when we're all done, here's what MH knows about the address:
28 ** type: local or network
29 ** host: not locally defaulted, not explicitly expanded
35 static char *pers = NULL;
36 static char *mbox = NULL;
37 static char *host = NULL;
38 static char *route = NULL;
39 static char *grp = NULL;
40 static char *note = NULL;
41 static char err[BUFSIZ];
42 static char adr[BUFSIZ];
50 pers = mbox = host = route = grp = note = NULL;
53 if ((ap = getadrx(addrs ? addrs : "")) == NULL)
56 strncpy(adr, ap->text, sizeof(adr));
64 if (ap->err && *ap->err)
65 strncpy(err, ap->err, sizeof(err));
72 getm(char *str, char *dfhost, int dftype, int wanthost, char *eresult)
80 if (wanthost == AD_HOST)
81 admonish(NULL, "bad address '%s' - %s", str, err);
84 if (pers == NULL && mbox == NULL && host == NULL && route == NULL
87 strcpy(eresult, "null address");
89 if (wanthost == AD_HOST)
90 admonish(NULL, "null address '%s'", str);
93 if (mbox == NULL && grp == NULL) {
95 strcpy(eresult, "no mailbox in address");
96 else if (wanthost == AD_HOST)
97 admonish(NULL, "no mailbox in address '%s'", str);
101 if (dfhost == NULL) {
102 dfhost = LocalName();
106 mp = (struct mailname *) calloc((size_t) 1, sizeof(*mp));
109 strcpy(eresult, "insufficient memory to represent address");
110 else if (wanthost == AD_HOST)
111 adios(EX_OSERR, NULL, "insufficient memory to represent address");
116 mp->m_text = getcpy(str);
118 mp->m_pers = getcpy(pers);
121 mp->m_type = BADHOST;
124 mp->m_gname = getcpy(grp);
126 mp->m_note = getcpy(note);
131 mp->m_mbox = getcpy(mbox);
132 mp->m_host = getcpy(host);
135 mp->m_mbox = getcpy(mbox);
136 if (route == NULL && dftype == LOCALHOST) {
140 mp->m_host = route ? NULL : getcpy(dfhost);
141 mp->m_type = route ? NETHOST : dftype;
146 if (wanthost == AD_NHST)
147 mp->m_type = !mh_strcasecmp(LocalName(), mp->m_host)
148 ? LOCALHOST : NETHOST;
150 mp->m_type = mh_strcasecmp(LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
154 mp->m_path = getcpy(route);
157 mp->m_gname = getcpy(grp);
159 mp->m_note = getcpy(note);
166 mnfree(struct mailname *mp)
190 #define empty(s) ((s) ? (s) : "")
193 adrformat(struct mailname *mp)
195 static char addr[BUFSIZ];
196 static char buffer[BUFSIZ];
199 strncpy(addr, mp->m_mbox ? mp->m_mbox : "", sizeof(addr));
201 snprintf(addr, sizeof(addr), mp->m_host ? "%s%s@%s" : "%s%s",
202 empty(mp->m_path), empty(mp->m_mbox), mp->m_host);
204 if (mp->m_pers || mp->m_path) {
206 snprintf(buffer, sizeof(buffer), "%s %s <%s>",
207 legal_person(mp->m_pers ? mp->m_pers : mp->m_mbox),
210 snprintf(buffer, sizeof(buffer), "%s <%s>",
211 legal_person(mp->m_pers ? mp->m_pers : mp->m_mbox),
213 } else if (mp->m_note)
214 snprintf(buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
216 strncpy(buffer, addr, sizeof(buffer));
223 #define W_MBEG 0x0001
224 #define W_MEND 0x0002
225 #define W_MBOX (W_MBEG | W_MEND)
226 #define W_HBEG 0x0004
227 #define W_HEND 0x0008
228 #define W_HOST (W_HBEG | W_HEND)
229 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
232 ** Check if this is my address
236 ismymbox(struct mailname *np)
244 static char *am = NULL;
245 static struct mailname mq;
248 ** If this is the first call, initialize
249 ** list of alternate mailboxes.
253 mq.m_mbox = getusername();
254 if ((am = context_find("alternate-mailboxes")) == NULL)
259 while ((cp = getname(am))) {
260 if ((mp->m_next = getm(cp, NULL, 0, AD_NAME, NULL)) == NULL) {
261 admonish(NULL, "illegal address: %s", cp);
266 if (*mp->m_mbox == '*') {
267 mp->m_type |= W_MBEG;
270 if (*(cp = mp->m_mbox + strlen(mp->m_mbox) - 1) == '*') {
271 mp->m_type |= W_MEND;
275 if (*mp->m_host == '*') {
276 mp->m_type |= W_HBEG;
279 if (*(cp = mp->m_host + strlen(mp->m_host) - 1) == '*') {
280 mp->m_type |= W_HEND;
284 if ((cp = getenv("MHWDEBUG")) && *cp)
285 fprintf(stderr, "mbox=\"%s\" host=\"%s\" %s\n",
286 mp->m_mbox, mp->m_host,
287 snprintb(buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
291 advise(NULL, "please fix the profile entry %s",
292 "alternate-mailboxes");
296 if (np == NULL) /* XXX */
299 switch (np->m_type) {
301 len = strlen(cp = LocalName());
302 if (!uprf(np->m_host, cp) || np->m_host[len] != '.')
308 if (!mh_strcasecmp(np->m_mbox, mq.m_mbox))
317 ** Now scan through list of alternate
318 ** mailboxes, and check for a match.
320 for (mp = &mq; mp->m_next;) {
324 if ((len = strlen(cp = np->m_mbox))
325 < (i = strlen(pp = mp->m_mbox)))
327 switch (mp->m_type & W_MBOX) {
329 if (mh_strcasecmp(cp, pp))
333 if (mh_strcasecmp(cp + len - i, pp))
340 case W_MBEG | W_MEND:
341 if (stringdex(pp, cp) < 0)
348 if (np->m_host == NULL)
350 if ((len = strlen(cp = np->m_host))
351 < (i = strlen(pp = mp->m_host)))
353 switch (mp->m_type & W_HOST) {
355 if (mh_strcasecmp(cp, pp))
359 if (mh_strcasecmp (cp + len - i, pp))
366 case W_HBEG | W_HEND:
367 if (stringdex(pp, cp) < 0)
378 * Insert mailname after element and returns the
379 * number of parsed addresses. element is set to
380 * the last parsed addresse.
383 getmboxes(char *line, struct mailname **element)
385 struct mailname *mp, *next;
389 next = (*element)->m_next;
391 while ((cp = getname(line))) {
392 mp = getm(cp, NULL, 0, AD_HOST, NULL);
393 (*element)->m_next = mp;
398 (*element)->m_next = next;