0
|
1 /* addrsbr.c - parse addresses 822-style */
|
|
2 #ifndef lint
|
|
3 static char ident[] = "@(#)$Id$";
|
|
4 #endif /* lint */
|
|
5
|
|
6 #include "../h/mh.h"
|
|
7 #include "../h/addrsbr.h"
|
|
8 #include "../zotnet/mf.h"
|
|
9 #include <stdio.h>
|
|
10 #ifdef BERK
|
|
11 #include <ctype.h>
|
|
12 #endif /* BERK */
|
|
13
|
|
14 /* High level parsing of addresses:
|
|
15
|
|
16 The routines in zotnet/mf/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 BERK is in effect, the routines in mf.c aren't called and only
|
|
21 the most rudimentary syntax parse is done. The parse is not 822-conformant.
|
|
22 This causes problems as there is no semantics associated with the address
|
|
23 at all--it's just a string. (the author of the BERK code disagrees with
|
|
24 the preceding, of course. BERK solves problems for incoming mail
|
|
25 because it will accept damn near any address. BERK was intended to be
|
|
26 used when spost is the interface to the mail delivery system which means
|
|
27 all outgoing address interpretation is left to sendmail. It is possible,
|
|
28 though unlikely, for BERK address parsing to interact poorly with
|
|
29 "post". - van@monet.berkeley.edu).
|
|
30
|
|
31 Instead, if #ifdef DUMB is in effect, a full 822-style parser is called
|
|
32 for syntax recongition. This breaks each address into its components.
|
|
33 Note however that no semantics are assumed about the parts or their
|
|
34 totality. This means that implicit hostnames aren't made explicit,
|
|
35 and explicit hostnames aren't expanded to their "official" represenations.
|
|
36
|
|
37 If neither BERK nor DUMB is in effect, then this module does some
|
|
38 high-level thinking about what the addresses are. If #ifdef MF is in
|
|
39 effect, then MH will deduce UUCP-style addressing masquerading as
|
|
40 822-style addresses.
|
|
41
|
|
42 1. for MMDF systems:
|
|
43
|
|
44 string%<uucp>@<local> -> string
|
|
45
|
|
46 2. for non-MMDF systems:
|
|
47
|
|
48 string@host.<uucp> -> host!string
|
|
49
|
|
50 3. for any system, an address interpreted relative to the local host:
|
|
51
|
|
52 string@<uucp> -> string
|
|
53
|
|
54 For cases (1) and (3) above, the leftmost host is extracted. If it's not
|
|
55 present, the local host is used. If #ifdef MF is not in effect or the
|
|
56 tests above fail, the address is considered to be a real 822-style address.
|
|
57
|
|
58 If an explicit host is not present, then MH checks for a bang to indicate
|
|
59 an explicit UUCP-style address. If so, this is noted. If not, the host is
|
|
60 defaulted, typically to the local host. The lack of an explict host is
|
|
61 also noted.
|
|
62
|
|
63 If an explicit 822-style host is present, then MH checks to see if it
|
|
64 can expand this to the official name for the host. If the hostname is
|
|
65 unknown, the address is so typed.
|
|
66
|
|
67 To summarize, when we're all done, here's what MH knows about the address:
|
|
68
|
|
69 BERK - type: local
|
|
70 nohost: set if no '@' or '!' in mailbox
|
|
71 text: exact copy of address
|
|
72 mbox: lowercase version of mailbox
|
|
73
|
|
74 DUMB - type: local, uucp, or network
|
|
75 host: not locally defaulted, not explicitly expanded
|
|
76 everything else
|
|
77
|
|
78 other - type: local, uucp, network, unknown
|
|
79 everything else
|
|
80 */
|
|
81
|
|
82 /* */
|
|
83
|
|
84 #if !defined(DUMB) && defined(SENDMTS) && !defined(BANG)
|
|
85 #define MF
|
|
86 #define UucpChan() "UUCP"
|
|
87 #endif /* MF */
|
|
88
|
|
89 #ifdef BERK
|
|
90 static char *err = NULL;
|
|
91 static char adrtext[BUFSIZ];
|
|
92 #else /* not BERK */
|
|
93 static int ingrp = 0;
|
|
94
|
|
95 static char *pers = NULL;
|
|
96 static char *mbox = NULL;
|
|
97 static char *host = NULL;
|
|
98 static char *route = NULL;
|
|
99 static char *grp = NULL;
|
|
100 static char *note = NULL;
|
|
101
|
|
102 static char err[BUFSIZ];
|
|
103 #endif /* not BERK */
|
|
104 static char adr[BUFSIZ];
|
|
105
|
|
106
|
|
107 char *getusr ();
|
|
108
|
|
109 /* */
|
|
110
|
|
111 char *getname (addrs)
|
|
112 register char *addrs;
|
|
113 {
|
|
114 #ifdef BERK
|
|
115 /*
|
|
116 * Berkeley uses a very simple parser since Sendmail does all the work.
|
|
117 * The only thing that does address parsing if BERK is defined is the
|
|
118 * routine "ismybox" used by "scan" & "repl" to identify the current
|
|
119 * users maildrop.
|
|
120 *
|
|
121 * This routine does essentially the same address interpretation as the
|
|
122 * routine "prescan" in "sendmail". The intent is that MH should
|
|
123 * make minimum assumptions about address forms since it doesn't
|
|
124 * have access to the information in the sendmail config file
|
|
125 * (God forbid that anything but sendmail has to deal with a sendmail
|
|
126 * config file) and, therefore, hasn't the faintest idea of what will
|
|
127 * or won't be a legal address.
|
|
128 *
|
|
129 * Since this parse is only used by "ismybox" and repl, it just does
|
|
130 * two things: split multiple addr on a line into separate addresses and
|
|
131 * locate the "mailbox" portion of an address. The parse uses rfc-822
|
|
132 * metacharacters and quoting but is much less restrictive that rfc-822.
|
|
133 * In detail, `,' or eos terminate addresses. "Empty" addresses
|
|
134 * (e.g., `,,') are ignored. Double quote ("), backslash, left & right
|
|
135 * paren and left and right angle brackets are metacharacters. Left &
|
|
136 * right parens must balance as must left & right angle brackets. Any
|
|
137 * metacharacter may be escaped by preceding it with a backslash.
|
|
138 * Any text between parens is considered a comment and ignored (i.e.,
|
|
139 * only `(', `)' and `\' are metacharacters following a `('). Text
|
|
140 * between double quotes is considered escaped (i.e., only `"' and
|
|
141 * `\' are metacharacters following a `"'). The `mailbox' portion
|
|
142 * of an address is the non-comment text between angle-brackets if
|
|
143 * the address contains any angle brackets. Otherwise, it is all the
|
|
144 * non-comment text. Blanks, tabs & newlines will not be included
|
|
145 * in the mailbox portion of an address unless they are escaped.
|
|
146 */
|
|
147
|
|
148 /* Scanner states */
|
|
149 #define NORMAL (0<<8)
|
|
150 #define QS (1<<8) /* in quoted string */
|
|
151 #define COM (2<<8) /* in comment (...) */
|
|
152 #define ERR (3<<8) /* found an error */
|
|
153 #define EOA (4<<8) /* end of address */
|
|
154
|
|
155 static char *saved_addr = NULL; /* saved address line ptr */
|
|
156 static char *adr_ptr = NULL; /* where to start looking for
|
|
157 next address on line */
|
|
158 register char *nxtout = adr; /* where to put next character of
|
|
159 `mailbox' part of address */
|
|
160 register unsigned char c;
|
|
161 register int state = NORMAL;
|
|
162 register char *adrcopy = adrtext; /* where to put next character of
|
|
163 address */
|
|
164 register int lbcnt = 0; /* number of unmatched "(" */
|
|
165 register int lpcnt = 0; /* number of unmatched "<" */
|
|
166
|
|
167 err = NULL;
|
|
168 if (! addrs) {
|
|
169 adr_ptr = NULL;
|
|
170 return NULL;
|
|
171 }
|
|
172 if (adr_ptr)
|
|
173 addrs = adr_ptr;
|
|
174 else
|
|
175 addrs = saved_addr = getcpy(addrs ? addrs : "");
|
|
176
|
|
177 /* skip any leading whitespace or commas. */
|
|
178 while ( (c = *addrs++) == ',' || isspace(c))
|
|
179 ;
|
|
180
|
|
181 *nxtout = *adrcopy = '\0';
|
|
182 while (state != EOA) {
|
|
183 *adrcopy++ = c;
|
|
184 if (state != COM)
|
|
185 *nxtout++ = (isalpha(c) && isupper (c)) ? tolower (c) : c;
|
|
186 switch (state+c) {
|
|
187
|
|
188 case NORMAL+'\n': /* discard newlines */
|
|
189 case QS+'\n':
|
|
190 case ERR+'\n':
|
|
191 --nxtout;
|
|
192 --adrcopy;
|
|
193 break;
|
|
194 case COM+'\n':
|
|
195 --adrcopy;
|
|
196 break;
|
|
197
|
|
198 case NORMAL+' ': /* skip unquoted whitespace */
|
|
199 case NORMAL+'\t':
|
|
200 --nxtout;
|
|
201 break;
|
|
202
|
|
203 case NORMAL+'"': /* start quoted string */
|
|
204 state = QS;
|
|
205 break;
|
|
206
|
|
207 case QS+'"': /* end quoted string */
|
|
208 state = NORMAL;
|
|
209 break;
|
|
210
|
|
211 case NORMAL+'<':
|
|
212 nxtout = adr; /* start over accumulating address */
|
|
213 lbcnt++;
|
|
214 break;
|
|
215
|
|
216 case NORMAL+'>':
|
|
217 --lbcnt;
|
|
218 if (lbcnt < 0) {
|
|
219 state = ERR;
|
|
220 err = "extra >";
|
|
221 } else
|
|
222 *(nxtout-1) = '\0';
|
|
223 break;
|
|
224
|
|
225 case NORMAL+'(':
|
|
226 state = COM;
|
|
227 --nxtout;
|
|
228 case COM+'(':
|
|
229 lpcnt++;
|
|
230 break;
|
|
231
|
|
232 case COM+')':
|
|
233 --lpcnt;
|
|
234 if (lpcnt < 0) {
|
|
235 state = ERR;
|
|
236 err = "extra )";
|
|
237 } else if (lpcnt == 0)
|
|
238 state = NORMAL;
|
|
239 break;
|
|
240
|
|
241 case NORMAL+'\\':
|
|
242 case QS+'\\':
|
|
243 case COM+'\\':
|
|
244 if ((c = *addrs++) == '\n' || c == '\0') {
|
|
245 state = EOA;
|
|
246 err = "illegal \\";
|
|
247 }
|
|
248 *adrcopy++ = c;
|
|
249 *nxtout++ = (isalpha(c) && isupper (c)) ? tolower (c) : c;
|
|
250 break;
|
|
251
|
|
252 case NORMAL+',':
|
|
253 case ERR+',':
|
|
254 case NORMAL+'\0':
|
|
255 case ERR+'\0':
|
|
256 state = EOA;
|
|
257 if (lbcnt)
|
|
258 err = "missing >";
|
|
259 break;
|
|
260
|
|
261 case COM+'\0':
|
|
262 state = EOA;
|
|
263 err = "missing )";
|
|
264 if (nxtout == adr)
|
|
265 nxtout++;
|
|
266 break;
|
|
267
|
|
268 case QS+'\0':
|
|
269 state = EOA;
|
|
270 err = "missing \"";
|
|
271 break;
|
|
272 }
|
|
273 if (c != '\0')
|
|
274 c = *addrs++;
|
|
275 }
|
|
276 /*
|
|
277 * at this point adr contains the `mailbox' part of the address
|
|
278 * in lower case & minus any comment or unquoted whitespace.
|
|
279 * adrtext contains an exact copy of the address and
|
|
280 * addr points to where we should start scanning next time.
|
|
281 */
|
|
282 *(nxtout-1) = *(adrcopy-1) = '\0';
|
|
283 if (*adr && !err) {
|
|
284 adr_ptr = addrs-1;
|
|
285 return adrtext;
|
|
286 } else {
|
|
287 free (saved_addr);
|
|
288 adr_ptr = NULL;
|
|
289 return NULL;
|
|
290 }
|
|
291 #else /* not BERK */
|
|
292 register struct adrx *ap;
|
|
293
|
|
294 pers = mbox = host = route = grp = note = NULL;
|
|
295 err[0] = '\0';
|
|
296
|
|
297 if ((ap = getadrx (addrs ? addrs : "")) == NULL)
|
|
298 return NULL;
|
|
299
|
|
300 (void) strcpy (adr, ap -> text);
|
|
301 pers = ap -> pers;
|
|
302 mbox = ap -> mbox;
|
|
303 host = ap -> host;
|
|
304 route = ap -> path;
|
|
305 grp = ap -> grp;
|
|
306 ingrp = ap -> ingrp;
|
|
307 note = ap -> note;
|
|
308 if (ap -> err && *ap -> err)
|
|
309 (void) strcpy (err, ap -> err);
|
|
310
|
|
311 return adr;
|
|
312 #endif /* not BERK */
|
|
313 }
|
|
314
|
|
315 /* */
|
|
316
|
|
317 #ifdef BERK
|
|
318 /* ARGSUSED */
|
|
319 #endif /* BERK */
|
|
320
|
|
321 struct mailname *getm (str, dfhost, dftype, wanthost, eresult)
|
|
322 register char *str,
|
|
323 *eresult;
|
|
324 char *dfhost;
|
|
325 int dftype,
|
|
326 wanthost;
|
|
327 {
|
|
328 #ifndef BERK
|
|
329 register char *pp;
|
|
330 #ifndef DUMB
|
|
331 register char *dp;
|
|
332 #endif /* not DUMB */
|
|
333 #ifdef MF
|
|
334 char *up = UucpChan ();
|
|
335 #endif /* MF */
|
|
336 #endif /* not BERK */
|
|
337 register struct mailname *mp;
|
|
338
|
|
339 if (err && err[0]) {
|
|
340 if (eresult)
|
|
341 (void) strcpy (eresult, err);
|
|
342 else
|
|
343 if (wanthost == AD_HOST)
|
|
344 admonish (NULLCP, "bad address '%s' - %s", str, err);
|
|
345 return NULL;
|
|
346 }
|
|
347 #ifdef BERK
|
|
348 if (str == NULL || *str == '\0') {
|
|
349 #else /* not BERK */
|
|
350 if (pers == NULL
|
|
351 && mbox == NULL && host == NULL && route == NULL
|
|
352 && grp == NULL) {
|
|
353 #endif /* not BERK */
|
|
354 if (eresult)
|
|
355 (void) strcpy (eresult, "null address");
|
|
356 else
|
|
357 if (wanthost == AD_HOST)
|
|
358 admonish (NULLCP, "null address '%s'", str);
|
|
359 return NULL;
|
|
360 }
|
|
361 #ifndef BERK
|
|
362 if (mbox == NULL && grp == NULL) {
|
|
363 if (eresult)
|
|
364 (void) strcpy (eresult, "no mailbox in address");
|
|
365 else
|
|
366 if (wanthost == AD_HOST)
|
|
367 admonish (NULLCP, "no mailbox in address '%s'", str);
|
|
368 return NULL;
|
|
369 }
|
|
370
|
|
371 if (dfhost == NULL) {
|
|
372 dfhost = LocalName ();
|
|
373 dftype = LOCALHOST;
|
|
374 }
|
|
375 #endif /* not BERK */
|
|
376
|
|
377 mp = (struct mailname *) calloc ((unsigned) 1, sizeof *mp);
|
|
378 if (mp == NULL) {
|
|
379 if (eresult)
|
|
380 (void) strcpy (eresult, "insufficient memory to represent address");
|
|
381 else
|
|
382 if (wanthost == AD_HOST)
|
|
383 adios (NULLCP, "insufficient memory to represent address");
|
|
384 return NULL;
|
|
385 }
|
|
386
|
|
387 mp -> m_next = NULL;
|
|
388 mp -> m_text = getcpy (str);
|
|
389 #ifdef BERK
|
|
390 mp -> m_type = LOCALHOST;
|
|
391 mp -> m_mbox = getcpy (adr);
|
|
392 if (!index (adr, '@') && !index (adr, '!'))
|
|
393 mp -> m_nohost = 1;
|
|
394 #else /* not BERK */
|
|
395 if (pers)
|
|
396 mp -> m_pers = getcpy (pers);
|
|
397
|
|
398 if (mbox == NULL) {
|
|
399 mp -> m_type = BADHOST;
|
|
400 mp -> m_nohost = 1;
|
|
401 mp -> m_ingrp = ingrp;
|
|
402 mp -> m_gname = getcpy (grp);
|
|
403 if (note)
|
|
404 mp -> m_note = getcpy (note);
|
|
405 return mp;
|
|
406 }
|
|
407
|
|
408 /* */
|
|
409
|
|
410 if (host) {
|
|
411 #ifdef MF
|
|
412 #ifdef MMDFMTS
|
|
413 if (up && uleq (host, LocalName ())
|
|
414 && (pp = rindex (mbox, '%'))
|
|
415 && uleq (up, pp + 1)) {/* uucpaddr%<uucp>@<local> */
|
|
416 *pp = NULL;
|
|
417 goto get_uucp;
|
|
418 }
|
|
419 #else /* not MMDFMTS */
|
|
420 if (up && (pp = index (host, '.'))
|
|
421 && uleq (up, pp + 1)) {/* uucpaddr@host.<uucp> */
|
|
422 *pp = NULL;
|
|
423 mp -> m_host = getcpy (host);
|
|
424 mp -> m_mbox = getcpy (mbox);
|
|
425 mp -> m_type = UUCPHOST;
|
|
426 goto got_host;
|
|
427 }
|
|
428 #endif /* not MMDFMTS */
|
|
429 if (up && uleq (dfhost, LocalName ())
|
|
430 && uleq (up, host)) {/* uucpaddr@<uucp> [local] */
|
|
431 if (pp = index (mbox, '!')) {
|
|
432 *pp++ = NULL;
|
|
433 mp -> m_host = getcpy (mbox);
|
|
434 mp -> m_mbox = getcpy (pp);
|
|
435 }
|
|
436 else {
|
|
437 mp -> m_host = getcpy (SystemName ());
|
|
438 mp -> m_mbox = getcpy (mbox);
|
|
439 }
|
|
440 mp -> m_type = UUCPHOST;
|
|
441 goto got_host;
|
|
442 }
|
|
443 #endif /* MF */
|
|
444 mp -> m_mbox = getcpy (mbox);
|
|
445 mp -> m_host = getcpy (host);
|
|
446 }
|
|
447 else {
|
|
448 if (pp = index (mbox, '!')) {
|
|
449 *pp++ = '\0';
|
|
450 mp -> m_mbox = getcpy (pp);
|
|
451 mp -> m_host = getcpy (mbox);
|
|
452 mp -> m_type = UUCPHOST;
|
|
453 }
|
|
454 else {
|
|
455 mp -> m_nohost = 1;
|
|
456 mp -> m_mbox = getcpy (mbox);
|
|
457 #ifdef DUMB
|
|
458 if (route == NULL && dftype == LOCALHOST) {
|
|
459 mp -> m_host = NULLCP;
|
|
460 mp -> m_type = dftype;
|
|
461 }
|
|
462 else
|
|
463 #endif /* DUMB */
|
|
464 {
|
|
465 mp -> m_host = route ? NULLCP : getcpy (dfhost);
|
|
466 mp -> m_type = route ? NETHOST : dftype;
|
|
467 }
|
|
468 }
|
|
469 goto got_host;
|
|
470 }
|
|
471
|
|
472 /* */
|
|
473
|
|
474 if (wanthost == AD_NHST)
|
|
475 mp -> m_type = uleq (LocalName (), mp -> m_host)
|
|
476 ? LOCALHOST : NETHOST;
|
|
477 #ifdef DUMB
|
|
478 else
|
|
479 mp -> m_type = uleq (LocalName (), mp -> m_host) ? LOCALHOST
|
|
480 : NETHOST;
|
|
481 #else /* not DUMB */
|
|
482 else
|
|
483 if (pp = OfficialName (mp -> m_host)) {
|
|
484 got_real_host: ;
|
|
485 free (mp -> m_host);
|
|
486 mp -> m_host = getcpy (pp);
|
|
487 mp -> m_type = uleq (LocalName (), mp -> m_host) ? LOCALHOST
|
|
488 : NETHOST;
|
|
489 }
|
|
490 else {
|
|
491 if (dp = index (mp -> m_host, '.')) {
|
|
492 *dp = NULL;
|
|
493 if (pp = OfficialName (mp -> m_host))
|
|
494 goto got_real_host;
|
|
495 *dp = '.';
|
|
496 }
|
|
497 mp -> m_type = BADHOST;
|
|
498 }
|
|
499 #endif /* not DUMB */
|
|
500
|
|
501 got_host: ;
|
|
502 if (route)
|
|
503 mp -> m_path = getcpy (route);
|
|
504 mp -> m_ingrp = ingrp;
|
|
505 if (grp)
|
|
506 mp -> m_gname = getcpy (grp);
|
|
507 if (note)
|
|
508 mp -> m_note = getcpy (note);
|
|
509 #endif /* not BERK */
|
|
510
|
|
511 return mp;
|
|
512 }
|
|
513
|
|
514 /* */
|
|
515
|
|
516 void mnfree (mp)
|
|
517 register struct mailname *mp;
|
|
518 {
|
|
519 if (!mp)
|
|
520 return;
|
|
521
|
|
522 if (mp -> m_text)
|
|
523 free (mp -> m_text);
|
|
524 if (mp -> m_pers)
|
|
525 free (mp -> m_pers);
|
|
526 if (mp -> m_mbox)
|
|
527 free (mp -> m_mbox);
|
|
528 if (mp -> m_host)
|
|
529 free (mp -> m_host);
|
|
530 if (mp -> m_path)
|
|
531 free (mp -> m_path);
|
|
532 if (mp -> m_gname)
|
|
533 free (mp -> m_gname);
|
|
534 if (mp -> m_note)
|
|
535 free (mp -> m_note);
|
|
536 #ifdef MHMTS
|
|
537 if (mp -> m_aka)
|
|
538 free (mp -> m_aka);
|
|
539 #endif /* MHMTS */
|
|
540
|
|
541 free ((char *) mp);
|
|
542 }
|
|
543
|
|
544 /* */
|
|
545
|
|
546 char *auxformat (mp, extras)
|
|
547 register struct mailname *mp;
|
|
548 int extras;
|
|
549 {
|
|
550 #ifndef BERK
|
|
551 #ifdef MF
|
|
552 char *up = UucpChan ();
|
|
553 #endif /* MF */
|
|
554 static char addr[BUFSIZ];
|
|
555 #endif /* not BERK */
|
|
556 static char buffer[BUFSIZ];
|
|
557
|
|
558 #ifdef BERK
|
|
559 /* this "if" is a crufty hack to handle "visible" aliases */
|
|
560 if (mp->m_pers && !extras)
|
|
561 (void) sprintf (buffer, "%s <%s>", mp->m_pers, mp->m_mbox);
|
|
562 else
|
|
563 (void) strcpy (buffer, mp -> m_text);
|
|
564 #else /* not BERK */
|
|
565
|
|
566 #ifdef MF
|
|
567 if (up && mp -> m_type == UUCPHOST)
|
|
568 #ifdef MMDFMTS
|
|
569 (void) sprintf (addr, "%s!%s%%%s@%s", mp -> m_host, mp -> m_mbox,
|
|
570 up, LocalName ());
|
|
571 #else /* not MMDFMTS */
|
|
572 (void) sprintf (addr, "%s@%s.%s", mp -> m_mbox, mp -> m_host, up);
|
|
573 #endif /* not MMDFMTS */
|
|
574 else
|
|
575 #endif /* MF */
|
|
576
|
|
577 #ifdef DUMB
|
|
578 if (mp -> m_nohost)
|
|
579 (void) strcpy (addr, mp -> m_mbox ? mp -> m_mbox : "");
|
|
580 else
|
|
581 #endif /* DUMB */
|
|
582
|
|
583 #ifndef BANG
|
|
584 if (mp -> m_type != UUCPHOST)
|
|
585 (void) sprintf (addr, mp -> m_host ? "%s%s@%s" : "%s%s",
|
|
586 mp -> m_path ? mp -> m_path : "", mp -> m_mbox, mp -> m_host);
|
|
587 else
|
|
588 #endif /* not BANG */
|
|
589 (void) sprintf (addr, "%s!%s", mp -> m_host, mp -> m_mbox);
|
|
590
|
|
591 if (!extras)
|
|
592 return addr;
|
|
593
|
|
594 if (mp -> m_pers || mp -> m_path)
|
|
595 if (mp -> m_note)
|
|
596 (void) sprintf (buffer, "%s %s <%s>",
|
|
597 legal_person (mp -> m_pers ? mp -> m_pers : mp -> m_mbox),
|
|
598 mp -> m_note, addr);
|
|
599 else
|
|
600 (void) sprintf (buffer, "%s <%s>",
|
|
601 legal_person (mp -> m_pers ? mp -> m_pers : mp -> m_mbox),
|
|
602 addr);
|
|
603 else
|
|
604 if (mp -> m_note)
|
|
605 (void) sprintf (buffer, "%s %s", addr, mp -> m_note);
|
|
606 else
|
|
607 (void) strcpy (buffer, addr);
|
|
608 #endif /* not BERK */
|
|
609
|
|
610 return buffer;
|
|
611 }
|
|
612
|
|
613 /* */
|
|
614
|
|
615 #if defined(BERK) || (defined(DUMB) && !defined(MMDFMTS) && !defined(SMTP))
|
|
616 #define REALLYDUMB
|
|
617 #else
|
|
618 #undef REALLYDUMB
|
|
619 #endif
|
|
620
|
|
621 char *adrsprintf (local, domain)
|
|
622 char *local,
|
|
623 *domain;
|
|
624 {
|
|
625 static char addr[BUFSIZ];
|
|
626
|
|
627 if (local == NULL)
|
|
628 #ifdef REALLYDUMB
|
|
629 return getusr ();
|
|
630 else
|
|
631 #endif /* REALLYDUMB */
|
|
632 local = getusr ();
|
|
633
|
|
634 if (domain == NULL)
|
|
635 #ifdef REALLYDUMB
|
|
636 return local;
|
|
637 else
|
|
638 #endif /* REALLYDUMB */
|
|
639 domain = LocalName ();
|
|
640
|
|
641 #ifndef BANG
|
|
642 (void) sprintf (addr, "%s@%s", local, domain);
|
|
643 #else /* BANG */
|
|
644 (void) sprintf (addr, "%s!%s", domain, local);
|
|
645 #endif /* BANG */
|
|
646
|
|
647 return addr;
|
|
648 }
|
|
649
|
|
650 /* */
|
|
651
|
|
652 #define W_NIL 0x0000
|
|
653 #define W_MBEG 0x0001
|
|
654 #define W_MEND 0x0002
|
|
655 #define W_MBOX (W_MBEG | W_MEND)
|
|
656 #define W_HBEG 0x0004
|
|
657 #define W_HEND 0x0008
|
|
658 #define W_HOST (W_HBEG | W_HEND)
|
|
659 #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND"
|
|
660
|
|
661
|
|
662 int ismymbox (np)
|
|
663 register struct mailname *np;
|
|
664 {
|
|
665 int oops;
|
|
666 register int len,
|
|
667 i;
|
|
668 register char *cp;
|
|
669 #ifndef BERK
|
|
670 register char *pp;
|
|
671 char buffer[BUFSIZ];
|
|
672 #endif /* not BERK */
|
|
673 register struct mailname *mp;
|
|
674 static char *am = NULL;
|
|
675 static struct mailname mq={NULL};
|
|
676
|
|
677 /* if this is the first call, init. alternate mailboxes list */
|
|
678 if (am == NULL) {
|
|
679 mq.m_next = NULL;
|
|
680 mq.m_mbox = getusr ();
|
|
681 if ((am = m_find ("alternate-mailboxes")) == NULL)
|
|
682 am = getusr ();
|
|
683 else {
|
|
684 mp = &mq;
|
|
685 oops = 0;
|
|
686 while (cp = getname (am))
|
|
687 if ((mp -> m_next = getm (cp, NULLCP, 0, AD_NAME, NULLCP))
|
|
688 == NULL)
|
|
689 admonish (NULLCP, "illegal address: %s", cp), oops++;
|
|
690 else {
|
|
691 mp = mp -> m_next;
|
|
692 mp -> m_type = W_NIL;
|
|
693 #ifdef BERK
|
|
694 /* check for wildcards on the mailbox name and
|
|
695 set m_type accordingly. */
|
|
696 mp -> m_ingrp = strlen (mp -> m_mbox);
|
|
697 if (*(mp -> m_mbox) == '*') {
|
|
698 mp -> m_type |= W_MBEG;
|
|
699 mp -> m_mbox++;
|
|
700 --mp -> m_ingrp;
|
|
701 }
|
|
702 if (mp -> m_mbox[mp -> m_ingrp - 1] == '*') {
|
|
703 mp -> m_type |= W_MEND;
|
|
704 mp -> m_ingrp--;
|
|
705 mp -> m_mbox[mp -> m_ingrp] = 0;
|
|
706 }
|
|
707 #else /* not BERK */
|
|
708 /* owing to screwy munging, wildcarding is a great idea
|
|
709 even under #ifndef BERK, so... */
|
|
710 mp -> m_type = W_NIL;
|
|
711 if (*mp -> m_mbox == '*')
|
|
712 mp -> m_type |= W_MBEG, mp -> m_mbox++;
|
|
713 if (*(cp = mp -> m_mbox + strlen (mp -> m_mbox) - 1)
|
|
714 == '*')
|
|
715 mp -> m_type |= W_MEND, *cp = '\0';
|
|
716 if (mp -> m_host) {
|
|
717 if (*mp -> m_host == '*')
|
|
718 mp -> m_type |= W_HBEG, mp -> m_host++;
|
|
719 if (*(cp = mp -> m_host + strlen (mp -> m_host) - 1)
|
|
720 == '*')
|
|
721 mp -> m_type |= W_HEND, *cp = '\0';
|
|
722 }
|
|
723 if ((cp = getenv ("MHWDEBUG")) && *cp)
|
|
724 fprintf (stderr, "mbox=\"%s\" host=\"%s\" %s\n",
|
|
725 mp -> m_mbox, mp -> m_host,
|
|
726 sprintb (buffer, (unsigned) mp -> m_type, WBITS));
|
|
727 #endif /* not BERK */
|
|
728 }
|
|
729 if (oops)
|
|
730 advise (NULLCP, "please fix the %s: entry in your %s file",
|
|
731 "alternate-mailboxes", mh_profile);
|
|
732 }
|
|
733 }
|
|
734 if (np == NULL) /* XXX */
|
|
735 return 0;
|
|
736
|
|
737 #ifdef BERK
|
|
738 cp = np -> m_mbox;
|
|
739 if (strcmp (cp, mq.m_mbox) == 0)
|
|
740 return 1;
|
|
741 #else /* not BERK */
|
|
742 switch (np -> m_type) {
|
|
743 case NETHOST:
|
|
744 len = strlen (cp = LocalName ());
|
|
745 if (!uprf (np -> m_host, cp) || np -> m_host[len] != '.')
|
|
746 break;
|
|
747 goto local_test;
|
|
748
|
|
749 case UUCPHOST:
|
|
750 if (!uleq (np -> m_host, SystemName ()))
|
|
751 break; /* fall */
|
|
752 case LOCALHOST:
|
|
753 local_test: ;
|
|
754 if (uleq (np -> m_mbox, mq.m_mbox))
|
|
755 return 1;
|
|
756 break;
|
|
757
|
|
758 default:
|
|
759 break;
|
|
760 }
|
|
761 #endif /* not BERK */
|
|
762
|
|
763 #ifdef BERK
|
|
764 len = strlen (cp);
|
|
765 for (mp = &mq; mp = mp -> m_next;)
|
|
766 if (len >= mp -> m_ingrp)
|
|
767 switch (mp -> m_type) {
|
|
768 case W_NIL: /* no wildcards */
|
|
769 if (strcmp (cp, mp -> m_mbox) == 0)
|
|
770 return 1;
|
|
771 break;
|
|
772
|
|
773 case W_MBEG: /* wildcard at beginning */
|
|
774 if (strcmp (&cp[len - mp -> m_ingrp], mp -> m_mbox) == 0)
|
|
775 return 1;
|
|
776 break;
|
|
777
|
|
778 case W_MEND: /* wildcard at end */
|
|
779 if (strncmp (cp, mp -> m_mbox, mp -> m_ingrp) == 0)
|
|
780 return 1;
|
|
781 break;
|
|
782
|
|
783 case W_MBEG | W_MEND: /* wildcard at beginning & end */
|
|
784 for (i = 0; i <= len - mp -> m_ingrp; i++)
|
|
785 if (strncmp (&cp[i], mp -> m_mbox, mp -> m_ingrp) == 0)
|
|
786 return 1;
|
|
787 }
|
|
788 #else /* not BERK */
|
|
789 for (mp = &mq; mp = mp -> m_next;) {
|
|
790 if (np -> m_mbox == NULL)
|
|
791 continue;
|
|
792 if ((len = strlen (cp = np -> m_mbox))
|
|
793 < (i = strlen (pp = mp -> m_mbox)))
|
|
794 continue;
|
|
795 switch (mp -> m_type & W_MBOX) {
|
|
796 case W_NIL:
|
|
797 if (!uleq (cp, pp))
|
|
798 continue;
|
|
799 break;
|
|
800 case W_MBEG:
|
|
801 if (!uleq (cp + len - i, pp))
|
|
802 continue;
|
|
803 break;
|
|
804 case W_MEND:
|
|
805 if (!uprf (cp, pp))
|
|
806 continue;
|
|
807 break;
|
|
808 case W_MBEG | W_MEND:
|
|
809 if (stringdex (pp, cp) < 0)
|
|
810 continue;
|
|
811 break;
|
|
812 }
|
|
813
|
|
814 if (mp -> m_nohost)
|
|
815 return 1;
|
|
816 if (np -> m_host == NULL)
|
|
817 continue;
|
|
818 if ((len = strlen (cp = np -> m_host))
|
|
819 < (i = strlen (pp = mp -> m_host)))
|
|
820 continue;
|
|
821 switch (mp -> m_type & W_HOST) {
|
|
822 case W_NIL:
|
|
823 if (!uleq (cp, pp))
|
|
824 continue;
|
|
825 break;
|
|
826 case W_HBEG:
|
|
827 if (!uleq (cp + len - i, pp))
|
|
828 continue;
|
|
829 break;
|
|
830 case W_HEND:
|
|
831 if (!uprf (cp, pp))
|
|
832 continue;
|
|
833 break;
|
|
834 case W_HBEG | W_HEND:
|
|
835 if (stringdex (pp, cp) < 0)
|
|
836 continue;
|
|
837 break;
|
|
838 }
|
|
839 return 1;
|
|
840 }
|
|
841 #endif /* not BERK */
|
|
842
|
|
843 return 0;
|
|
844 }
|