Eliminated unsued sigset_t variables set and oset.
[mmh] / 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 }