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