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