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