]> diplodocus.org Git - nmh/blob - sbr/addrsbr.c
Put in a prototype for client() to get rid of the "default prototype" warning.
[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 }
298 else
299 if (mp->m_note)
300 snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note);
301 else
302 strncpy (buffer, addr, sizeof(buffer));
303
304 return buffer;
305 }
306
307
308 /*
309 * address specific "sprintf"
310 */
311
312 char *
313 adrsprintf (char *local, char *domain)
314 {
315 static char addr[BUFSIZ];
316
317 if (local == NULL)
318 #ifdef REALLYDUMB
319 return getusername ();
320 else
321 #endif /* REALLYDUMB */
322 local = getusername ();
323
324 if (domain == NULL)
325 #ifdef REALLYDUMB
326 return local;
327 else
328 #endif /* REALLYDUMB */
329 domain = LocalName ();
330
331 #ifndef BANG
332 snprintf (addr, sizeof(addr), "%s@%s", local, domain);
333 #else /* BANG */
334 snprintf (addr, sizeof(addr), "%s!%s", domain, local);
335 #endif /* BANG */
336
337 return addr;
338 }
339
340
341 #define W_NIL 0x0000
342 #define W_MBEG 0x0001
343 #define W_MEND 0x0002
344 #define W_MBOX (W_MBEG | W_MEND)
345 #define W_HBEG 0x0004
346 #define W_HEND 0x0008
347 #define W_HOST (W_HBEG | W_HEND)
348 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
349
350 /*
351 * Check if this is my address
352 */
353
354 int
355 ismymbox (struct mailname *np)
356 {
357 int oops;
358 register int len, i;
359 register char *cp;
360 register char *pp;
361 char buffer[BUFSIZ];
362 struct mailname *mp;
363 static char *am = NULL;
364 static struct mailname mq={NULL};
365
366 /*
367 * If this is the first call, initialize
368 * list of alternate mailboxes.
369 */
370 if (am == NULL) {
371 mq.m_next = NULL;
372 mq.m_mbox = getusername ();
373 if ((am = context_find ("alternate-mailboxes")) == NULL)
374 am = getusername();
375 else {
376 mp = &mq;
377 oops = 0;
378 while ((cp = getname (am))) {
379 if ((mp->m_next = getm (cp, NULL, 0, AD_NAME, NULL)) == NULL) {
380 admonish (NULL, "illegal address: %s", cp);
381 oops++;
382 } else {
383 mp = mp->m_next;
384 mp->m_type = W_NIL;
385 if (*mp->m_mbox == '*') {
386 mp->m_type |= W_MBEG;
387 mp->m_mbox++;
388 }
389 if (*(cp = mp->m_mbox + strlen (mp->m_mbox) - 1) == '*') {
390 mp->m_type |= W_MEND;
391 *cp = '\0';
392 }
393 if (mp->m_host) {
394 if (*mp->m_host == '*') {
395 mp->m_type |= W_HBEG;
396 mp->m_host++;
397 }
398 if (*(cp = mp->m_host + strlen (mp->m_host) - 1) == '*') {
399 mp->m_type |= W_HEND;
400 *cp = '\0';
401 }
402 }
403 if ((cp = getenv ("MHWDEBUG")) && *cp)
404 fprintf (stderr, "mbox=\"%s\" host=\"%s\" %s\n",
405 mp->m_mbox, mp->m_host,
406 snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS));
407 }
408 }
409 if (oops)
410 advise (NULL, "please fix the %s: entry in your %s file",
411 "alternate-mailboxes", mh_profile);
412 }
413 }
414
415 if (np == NULL) /* XXX */
416 return 0;
417
418 switch (np->m_type) {
419 case NETHOST:
420 len = strlen (cp = LocalName ());
421 if (!uprf (np->m_host, cp) || np->m_host[len] != '.')
422 break;
423 goto local_test;
424
425 case UUCPHOST:
426 if (strcasecmp (np->m_host, SystemName()))
427 break; /* fall */
428 case LOCALHOST:
429 local_test: ;
430 if (!strcasecmp (np->m_mbox, mq.m_mbox))
431 return 1;
432 break;
433
434 default:
435 break;
436 }
437
438 /*
439 * Now scan through list of alternate
440 * mailboxes, and check for a match.
441 */
442 for (mp = &mq; mp->m_next;) {
443 mp = mp->m_next;
444 if (!np->m_mbox)
445 continue;
446 if ((len = strlen (cp = np->m_mbox))
447 < (i = strlen (pp = mp->m_mbox)))
448 continue;
449 switch (mp->m_type & W_MBOX) {
450 case W_NIL:
451 if (strcasecmp (cp, pp))
452 continue;
453 break;
454 case W_MBEG:
455 if (strcasecmp (cp + len - i, pp))
456 continue;
457 break;
458 case W_MEND:
459 if (!uprf (cp, pp))
460 continue;
461 break;
462 case W_MBEG | W_MEND:
463 if (stringdex (pp, cp) < 0)
464 continue;
465 break;
466 }
467
468 if (mp->m_nohost)
469 return 1;
470 if (np->m_host == NULL)
471 continue;
472 if ((len = strlen (cp = np->m_host))
473 < (i = strlen (pp = mp->m_host)))
474 continue;
475 switch (mp->m_type & W_HOST) {
476 case W_NIL:
477 if (strcasecmp (cp, pp))
478 continue;
479 break;
480 case W_HBEG:
481 if (strcasecmp (cp + len - i, pp))
482 continue;
483 break;
484 case W_HEND:
485 if (!uprf (cp, pp))
486 continue;
487 break;
488 case W_HBEG | W_HEND:
489 if (stringdex (pp, cp) < 0)
490 continue;
491 break;
492 }
493 return 1;
494 }
495
496 return 0;
497 }