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.
12 #include <h/addrsbr.h>
16 ** High level parsing of addresses:
18 ** The routines in sbr/mf.c parse the syntactic representations of
19 ** addresses. The routines in sbr/addrsbr.c associate semantics with those
22 ** A full 822-style parser is called for syntax recongition. This breaks
23 ** each address into its components. Note however that no semantics are
24 ** assumed about the parts or their totality. This means that implicit
25 ** hostnames aren't made explicit, and explicit hostnames aren't expanded
26 ** to their "official" represenations.
28 ** To summarize, when we're all done, here's what MH knows about the address:
29 ** type: local or network
30 ** host: not locally defaulted, not explicitly expanded
36 static char *pers = NULL;
37 static char *mbox = NULL;
38 static char *host = NULL;
39 static char *route = NULL;
40 static char *grp = NULL;
41 static char *note = NULL;
42 static char err[BUFSIZ];
43 static char adr[BUFSIZ];
51 pers = mbox = host = route = grp = note = NULL;
54 if ((ap = getadrx(addrs ? addrs : "")) == NULL)
57 strncpy(adr, ap->text, sizeof(adr));
65 if (ap->err && *ap->err)
66 strncpy(err, ap->err, sizeof(err));
73 getm(char *str, char *dfhost, int dftype, int wanthost, char *eresult)
81 if (wanthost == AD_HOST)
82 admonish(NULL, "bad address '%s' - %s", str, err);
85 if (pers == NULL && mbox == NULL && host == NULL && route == NULL
88 strcpy(eresult, "null address");
90 if (wanthost == AD_HOST)
91 admonish(NULL, "null address '%s'", str);
94 if (mbox == NULL && grp == NULL) {
96 strcpy(eresult, "no mailbox in address");
97 else if (wanthost == AD_HOST)
98 admonish(NULL, "no mailbox in address '%s'", str);
102 if (dfhost == NULL) {
103 dfhost = LocalName();
107 mp = (struct mailname *) mh_xcalloc((size_t) 1, sizeof(*mp));
110 strcpy(eresult, "insufficient memory to represent address");
111 else if (wanthost == AD_HOST)
112 adios(EX_OSERR, NULL, "insufficient memory to represent address");
117 mp->m_text = getcpy(str);
119 mp->m_pers = getcpy(pers);
122 mp->m_type = BADHOST;
125 mp->m_gname = getcpy(grp);
127 mp->m_note = getcpy(note);
132 mp->m_mbox = getcpy(mbox);
133 mp->m_host = getcpy(host);
136 mp->m_mbox = getcpy(mbox);
137 if (route == NULL && dftype == LOCALHOST) {
141 mp->m_host = route ? NULL : getcpy(dfhost);
142 mp->m_type = route ? NETHOST : dftype;
147 if (wanthost == AD_NHST)
148 mp->m_type = !mh_strcasecmp(LocalName(), mp->m_host)
149 ? LOCALHOST : NETHOST;
151 mp->m_type = mh_strcasecmp(LocalName(), mp->m_host) ? NETHOST : LOCALHOST;
155 mp->m_path = getcpy(route);
158 mp->m_gname = getcpy(grp);
160 mp->m_note = getcpy(note);
167 mnfree(struct mailname *mp)
191 #define empty(s) ((s) ? (s) : "")
194 adrformat(struct mailname *mp)
196 static char addr[BUFSIZ];
197 static char buffer[BUFSIZ];
200 strncpy(addr, mp->m_mbox ? mp->m_mbox : "", sizeof(addr));
202 snprintf(addr, sizeof(addr), mp->m_host ? "%s%s@%s" : "%s%s",
203 empty(mp->m_path), empty(mp->m_mbox), mp->m_host);
205 if (mp->m_pers || mp->m_path) {
207 snprintf(buffer, sizeof(buffer), "%s %s <%s>",
208 legal_person(mp->m_pers ? mp->m_pers : mp->m_mbox),
211 snprintf(buffer, sizeof(buffer), "%s <%s>",
212 legal_person(mp->m_pers ? mp->m_pers : mp->m_mbox),
214 } else if (mp->m_note)
215 snprintf(buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
217 strncpy(buffer, addr, sizeof(buffer));
224 #define W_MBEG 0x0001
225 #define W_MEND 0x0002
226 #define W_MBOX (W_MBEG | W_MEND)
227 #define W_HBEG 0x0004
228 #define W_HEND 0x0008
229 #define W_HOST (W_HBEG | W_HEND)
230 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
233 ** Check if this is my address
237 ismymbox(struct mailname *np)
245 static char *am = NULL;
246 static struct mailname mq;
249 ** If this is the first call, initialize
250 ** list of alternate mailboxes.
254 mq.m_mbox = getusername();
255 if ((am = context_find("alternate-mailboxes")) == NULL)
260 while ((cp = getname(am))) {
261 if ((mp->m_next = getm(cp, NULL, 0, AD_NAME, NULL)) == NULL) {
262 admonish(NULL, "illegal address: %s", cp);
267 if (*mp->m_mbox == '*') {
268 mp->m_type |= W_MBEG;
271 if (*(cp = mp->m_mbox + strlen(mp->m_mbox) - 1) == '*') {
272 mp->m_type |= W_MEND;
276 if (*mp->m_host == '*') {
277 mp->m_type |= W_HBEG;
280 if (*(cp = mp->m_host + strlen(mp->m_host) - 1) == '*') {
281 mp->m_type |= W_HEND;
285 if ((cp = getenv("MHWDEBUG")) && *cp)
286 fprintf(stderr, "mbox=\"%s\" host=\"%s\" %s\n",
287 mp->m_mbox, mp->m_host,
288 snprintb(buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
292 advise(NULL, "please fix the profile entry %s",
293 "alternate-mailboxes");
297 if (np == NULL) /* XXX */
300 switch (np->m_type) {
302 len = strlen(cp = LocalName());
303 if (!uprf(np->m_host, cp) || np->m_host[len] != '.')
309 if (!mh_strcasecmp(np->m_mbox, mq.m_mbox))
318 ** Now scan through list of alternate
319 ** mailboxes, and check for a match.
321 for (mp = &mq; mp->m_next;) {
325 if ((len = strlen(cp = np->m_mbox))
326 < (i = strlen(pp = mp->m_mbox)))
328 switch (mp->m_type & W_MBOX) {
330 if (mh_strcasecmp(cp, pp))
334 if (mh_strcasecmp(cp + len - i, pp))
341 case W_MBEG | W_MEND:
342 if (stringdex(pp, cp) < 0)
349 if (np->m_host == NULL)
351 if ((len = strlen(cp = np->m_host))
352 < (i = strlen(pp = mp->m_host)))
354 switch (mp->m_type & W_HOST) {
356 if (mh_strcasecmp(cp, pp))
360 if (mh_strcasecmp (cp + len - i, pp))
367 case W_HBEG | W_HEND:
368 if (stringdex(pp, cp) < 0)
379 * Insert mailname after element and returns the
380 * number of parsed addresses. element is set to
381 * the last parsed addresse.
384 getmboxes(char *line, struct mailname **element)
386 struct mailname *mp, *next;
390 next = (*element)->m_next;
392 while ((cp = getname(line))) {
393 mp = getm(cp, NULL, 0, AD_HOST, NULL);
394 (*element)->m_next = mp;
399 (*element)->m_next = next;