]> diplodocus.org Git - nmh/blob - sbr/addrsbr.c
new.c: Order two return statements to match comment.
[nmh] / sbr / addrsbr.c
1 /* addrsbr.c -- parse addresses 822-style
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include <h/mh.h>
9 #include <h/addrsbr.h>
10 #include <h/mf.h>
11 #include <h/mts.h>
12 #include <h/utils.h>
13
14 /* High level parsing of addresses:
15
16 The routines in sbr/mf.c parse the syntactic representations of
17 addresses. The routines in sbr/addrsbr.c associate semantics with those
18 addresses.
19
20 The comments below are left in for historical purposes; DUMB and
21 REALLYDUMB are now the default in the code.
22
23 If #ifdef DUMB is in effect, a full 822-style parser is called
24 for syntax recognition. This breaks each address into its components.
25 Note however that no semantics are assumed about the parts or their
26 totality. This means that implicit hostnames aren't made explicit,
27 and explicit hostnames aren't expanded to their "official" representations.
28
29 If DUMB is not in effect, then this module does some
30 high-level thinking about what the addresses are.
31
32 1. for MMDF systems:
33
34 string%<uucp>@<local> -> string
35
36 2. for non-MMDF systems:
37
38 string@host.<uucp> -> host!string
39
40 3. for any system, an address interpreted relative to the local host:
41
42 string@<uucp> -> string
43
44 For cases (1) and (3) above, the leftmost host is extracted. If it's not
45 present, the local host is used. If the tests above fail, the address is
46 considered to be a real 822-style address.
47
48 If an explicit host is not present, then MH checks for a bang to indicate
49 an explicit UUCP-style address. If so, this is noted. If not, the host is
50 defaulted, typically to the local host. The lack of an explicit host is
51 also noted.
52
53 If an explicit 822-style host is present, then MH checks to see if it
54 can expand this to the official name for the host. If the hostname is
55 unknown, the address is so typed.
56
57 To summarize, when we're all done, here's what MH knows about the address:
58
59 DUMB - type: local, uucp, or network
60 host: not locally defaulted, not explicitly expanded
61 everything else
62
63 other - type: local, uucp, network, unknown
64 everything else
65 */
66
67
68 static int ingrp = 0;
69 static char *pers = NULL;
70 static char *mbox = NULL;
71 static char *host = NULL;
72 static char *route = NULL;
73 static char *grp = NULL;
74 static char *note = NULL;
75 static char err[BUFSIZ];
76 static char adr[BUFSIZ];
77 static int eai = 0;
78
79 void
80 enable_eai(void) {
81 eai = 1;
82 }
83
84
85 char *
86 getname (const char *addrs)
87 {
88 struct adrx *ap;
89 pers = mbox = host = route = grp = note = NULL;
90 err[0] = '\0';
91
92 if ((ap = getadrx (FENDNULL(addrs), eai)) == NULL) {
93 return NULL;
94 }
95
96 strncpy (adr, ap->text, sizeof(adr));
97 pers = ap->pers;
98 mbox = ap->mbox;
99 host = ap->host;
100 route = ap->path;
101 grp = ap->grp;
102 ingrp = ap->ingrp;
103 note = ap->note;
104 if (ap->err && *ap->err)
105 strncpy (err, ap->err, sizeof(err));
106
107 return adr;
108 }
109
110
111 struct mailname *
112 getm (char *str, char *dfhost, int dftype, char *eresult, size_t eresultsize)
113 {
114 char *pp;
115 struct mailname *mp;
116
117 if (err[0]) {
118 if (eresult) {
119 strncpy (eresult, err, eresultsize);
120 eresult[eresultsize - 1] = '\0';
121 }
122 return NULL;
123 }
124 if (pers == NULL
125 && mbox == NULL && host == NULL && route == NULL
126 && grp == NULL) {
127 if (eresult) {
128 strncpy (eresult, "null address", eresultsize);
129 eresult[eresultsize - 1] = '\0';
130 }
131 return NULL;
132 }
133 if (mbox == NULL && grp == NULL) {
134 if (eresult) {
135 strncpy (eresult, "no mailbox in address", eresultsize);
136 eresult[eresultsize - 1] = '\0';
137 }
138 return NULL;
139 }
140
141 if (dfhost == NULL) {
142 dfhost = LocalName (0);
143 dftype = LOCALHOST;
144 }
145
146 NEW0(mp);
147 mp->m_next = NULL;
148 mp->m_text = getcpy (str);
149 if (pers)
150 mp->m_pers = mh_xstrdup(pers);
151
152 if (mbox == NULL) {
153 mp->m_type = BADHOST;
154 mp->m_nohost = 1;
155 mp->m_ingrp = ingrp;
156 mp->m_gname = getcpy (grp);
157 if (note)
158 mp->m_note = mh_xstrdup(note);
159 return mp;
160 }
161
162 if (host) {
163 mp->m_mbox = getcpy (mbox);
164 mp->m_host = mh_xstrdup(host);
165 mp->m_type =
166 strcasecmp (LocalName(0), mp->m_host) ? NETHOST : LOCALHOST;
167 } else {
168 if ((pp = strchr(mbox, '!'))) {
169 *pp++ = '\0';
170 mp->m_mbox = mh_xstrdup(pp);
171 mp->m_host = getcpy (mbox);
172 mp->m_type = UUCPHOST;
173 } else {
174 mp->m_nohost = 1;
175 mp->m_mbox = getcpy (mbox);
176 if (route == NULL && dftype == LOCALHOST) {
177 mp->m_host = NULL;
178 mp->m_type = dftype;
179 } else {
180 mp->m_host = route ? NULL : getcpy (dfhost);
181 mp->m_type = route ? NETHOST : dftype;
182 }
183 }
184 }
185
186 /* For alternate mailboxes, m_type gets overwritten in ismymbox ()
187 to support wild-card matching. */
188
189 if (route)
190 mp->m_path = mh_xstrdup(route);
191 mp->m_ingrp = ingrp;
192 if (grp)
193 mp->m_gname = mh_xstrdup(grp);
194 if (note)
195 mp->m_note = mh_xstrdup(note);
196
197 return mp;
198 }
199
200
201 void
202 mnfree (struct mailname *mp)
203 {
204 if (!mp)
205 return;
206
207 free(mp->m_text);
208 free(mp->m_pers);
209 free(mp->m_mbox);
210 free(mp->m_host);
211 free(mp->m_path);
212 free(mp->m_gname);
213 free(mp->m_note);
214
215 free(mp);
216 }
217
218
219 char *
220 auxformat (struct mailname *mp, int extras)
221 {
222 static char addr[BUFSIZ];
223 static char buffer[BUFSIZ];
224
225 if (mp->m_nohost)
226 strncpy (addr, FENDNULL(mp->m_mbox), sizeof(addr));
227 else if (mp->m_type != UUCPHOST) {
228 if (mp->m_host)
229 snprintf (addr, sizeof(addr), "%s%s@%s", FENDNULL(mp->m_path),
230 FENDNULL(mp->m_mbox), mp->m_host);
231 else snprintf (addr, sizeof(addr), "%s%s", FENDNULL(mp->m_path),
232 FENDNULL(mp->m_mbox));
233 } else
234 snprintf (addr, sizeof(addr), "%s!%s", mp->m_host, mp->m_mbox);
235
236 if (!extras)
237 return addr;
238
239 if (mp->m_pers || mp->m_path) {
240 if (mp->m_note)
241 snprintf (buffer, sizeof(buffer), "%s %s <%s>",
242 legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox),
243 mp->m_note, addr);
244 else
245 snprintf (buffer, sizeof(buffer), "%s <%s>",
246 legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox),
247 addr);
248 } else if (mp->m_note)
249 snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
250 else
251 strncpy (buffer, addr, sizeof(buffer));
252
253 return buffer;
254 }
255
256
257 #define W_NIL 0x0000
258 #define W_MBEG 0x0001
259 #define W_MEND 0x0002
260 #define W_MBOX (W_MBEG | W_MEND)
261 #define W_HBEG 0x0004
262 #define W_HEND 0x0008
263 #define W_HOST (W_HBEG | W_HEND)
264 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
265
266 /*
267 * Check if this is my address
268 */
269
270 int
271 ismymbox (struct mailname *np)
272 {
273 int oops;
274 int len, i;
275 char *cp;
276 char *pp;
277 char buffer[BUFSIZ];
278 struct mailname *mp;
279 static char *am = NULL;
280 static struct mailname mq;
281 static int localmailbox = 0;
282
283 /*
284 * If this is the first call, initialize
285 * list of alternate mailboxes.
286 */
287 if (am == NULL) {
288 mq.m_next = NULL;
289 mq.m_mbox = getusername ();
290
291 if ((am = context_find ("local-mailbox"))) {
292
293 localmailbox++;
294
295 if ((cp = getname(am)) == NULL) {
296 inform("Unable to find address in local-mailbox, continuing...");
297 return 0;
298 }
299
300 if ((mq.m_next = getm (cp, NULL, 0, NULL, 0)) == NULL) {
301 inform("invalid entry in local-mailbox: %s, continuing...", cp);
302 return 0;
303 }
304
305 /* Sigh, it turns out that the address parser gets messed up
306 * if you don't call getname() until it returns NULL. */
307 while (getname(am) != NULL)
308 ;
309 }
310
311 if ((am = context_find ("alternate-mailboxes")) == NULL)
312 am = getusername();
313 else {
314 mp = mq.m_next ? mq.m_next : &mq;
315 oops = 0;
316 while ((cp = getname (am))) {
317 if ((mp->m_next = getm (cp, NULL, 0, NULL, 0)) == NULL) {
318 inform("illegal address: %s, continuing...", cp);
319 oops++;
320 } else {
321 mp = mp->m_next;
322 mp->m_type = W_NIL;
323 if (*mp->m_mbox == '*') {
324 mp->m_type |= W_MBEG;
325 mp->m_mbox++;
326 }
327 if (*(cp = mp->m_mbox + strlen (mp->m_mbox) - 1) == '*') {
328 mp->m_type |= W_MEND;
329 *cp = '\0';
330 }
331 if (mp->m_host) {
332 if (*mp->m_host == '*') {
333 mp->m_type |= W_HBEG;
334 mp->m_host++;
335 }
336 if (*(cp = mp->m_host + strlen (mp->m_host) - 1) == '*') {
337 mp->m_type |= W_HEND;
338 *cp = '\0';
339 }
340 }
341 }
342 }
343 if (oops)
344 inform("please fix the %s: entry in your %s file",
345 "alternate-mailboxes", mh_profile);
346 }
347
348 if ((cp = getenv ("MHWDEBUG")) && *cp) {
349 for (mp = &mq; mp; mp = mp->m_next) {
350 fprintf (stderr, "Local- or Alternate-Mailbox: text=\"%s\" "
351 "mbox=\"%s\" host=\"%s\" %s\n",
352 FENDNULL(mp->m_text), mp->m_mbox,
353 FENDNULL(mp->m_host),
354 snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type,
355 WBITS));
356 }
357 }
358 }
359
360 if (np == NULL) /* XXX */
361 return 0;
362
363 /*
364 * Don't perform this "local" test if we have a Local-Mailbox set
365 */
366
367 if (! localmailbox)
368 switch (np->m_type) {
369 case NETHOST:
370 len = strlen (cp = LocalName (0));
371 if (!uprf (np->m_host, cp) || np->m_host[len] != '.')
372 break;
373 goto local_test;
374
375 case UUCPHOST:
376 if (strcasecmp (np->m_host, SystemName()))
377 break;
378 /* FALLTHRU */
379 case LOCALHOST:
380 local_test: ;
381 if (!strcasecmp (np->m_mbox, mq.m_mbox))
382 return 1;
383 break;
384
385 default:
386 break;
387 }
388
389 /*
390 * Now scan through list of alternate
391 * mailboxes, and check for a match.
392 */
393 for (mp = &mq; mp->m_next;) {
394 mp = mp->m_next;
395 if (!np->m_mbox)
396 continue;
397 if ((len = strlen (cp = np->m_mbox))
398 < (i = strlen (pp = mp->m_mbox)))
399 continue;
400 switch (mp->m_type & W_MBOX) {
401 case W_NIL:
402 if (strcasecmp (cp, pp))
403 continue;
404 break;
405 case W_MBEG:
406 if (strcasecmp (cp + len - i, pp))
407 continue;
408 break;
409 case W_MEND:
410 if (!uprf (cp, pp))
411 continue;
412 break;
413 case W_MBEG | W_MEND:
414 if (stringdex (pp, cp) < 0)
415 continue;
416 break;
417 }
418
419 if (mp->m_nohost)
420 return 1;
421 if (np->m_host == NULL || mp->m_host == NULL)
422 continue;
423 if ((len = strlen (cp = np->m_host))
424 < (i = strlen (pp = mp->m_host)))
425 continue;
426 switch (mp->m_type & W_HOST) {
427 case W_NIL:
428 if (strcasecmp (cp, pp))
429 continue;
430 break;
431 case W_HBEG:
432 if (strcasecmp (cp + len - i, pp))
433 continue;
434 break;
435 case W_HEND:
436 if (!uprf (cp, pp))
437 continue;
438 break;
439 case W_HBEG | W_HEND:
440 if (stringdex (pp, cp) < 0)
441 continue;
442 break;
443 }
444 return 1;
445 }
446
447 return 0;
448 }