source: trunk/third/nmh/sbr/addrsbr.c @ 12455

Revision 12455, 10.6 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12454, which included commits to RCS files with non-trunk default branches.
Line 
1
2/*
3 * addrsbr.c -- parse addresses 822-style
4 *
5 * $Id: addrsbr.c,v 1.1.1.1 1999-02-07 18:14:07 danw Exp $
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
63static int  ingrp = 0;
64static char *pers = NULL;
65static char *mbox = NULL;
66static char *host = NULL;
67static char *route = NULL;
68static char *grp = NULL;
69static char *note = NULL;
70static char err[BUFSIZ];
71static char adr[BUFSIZ];
72
73/*
74 * external prototypes
75 */
76char *getusername (void);
77
78
79char *
80getname (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
105struct mailname *
106getm (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
225got_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
238void
239mnfree (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
265char *
266auxformat (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
311char *
312adrsprintf (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
353int
354ismymbox (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:
428local_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}
Note: See TracBrowser for help on using the repository browser.