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