908e6194d469989546ddb7394cf3644c42974e64
[mmh] / mts / smtp / hosts.c
1
2 /*
3  * hosts.c -- find out the official name of a host
4  *
5  * $Id$
6  *
7  * This code is Copyright (c) 2002, by the authors of nmh.  See the
8  * COPYRIGHT file in the root directory of the nmh distribution for
9  * complete copyright information.
10  */
11
12 /*
13  * In the SendMail world, we really don't know what the valid
14  * hosts are.  We could poke around in the sendmail.cf file, but
15  * that still isn't a guarantee.  As a result, we'll say that
16  * everything is a valid host, and let SendMail worry about it.
17  */
18
19 #include <h/mh.h>
20 #include <h/mts.h>
21 #include <netdb.h>
22
23 static struct host {
24     char *h_name;
25     char **h_aliases;
26     struct host *h_next;
27 } hosts;
28
29
30 /*
31  * static prototypes
32  */
33 static int init_hs(void);
34
35
36 char *
37 OfficialName (char *name)
38 {
39     unsigned char *p;
40     char *q, site[BUFSIZ];
41     struct addrinfo hints, *res;
42
43     static char buffer[BUFSIZ];
44     char **r;
45     struct host *h;
46
47     for (p = name, q = site; *p && (q - site < sizeof(site) - 1); p++, q++)
48         *q = isupper (*p) ? tolower (*p) : *p;
49     *q = '\0';
50     q = site;
51
52     if (!mh_strcasecmp (LocalName(), site))
53         return LocalName();
54
55     memset(&hints, 0, sizeof(hints));
56     hints.ai_flags = AI_CANONNAME;
57     hints.ai_family = PF_UNSPEC;
58
59     if (getaddrinfo(q, NULL, &hints, &res) == 0) {
60         strncpy (buffer, res->ai_canonname, sizeof(buffer));
61         buffer[sizeof(buffer) - 1] = '\0';
62         freeaddrinfo(res);
63         return buffer;
64     }
65     if (hosts.h_name || init_hs ()) {
66         for (h = hosts.h_next; h; h = h->h_next)
67             if (!mh_strcasecmp (h->h_name, q)) {
68                 return h->h_name;
69             } else {
70                 for (r = h->h_aliases; *r; r++)
71                     if (!mh_strcasecmp (*r, q))
72                         return h->h_name;
73             }
74     }
75
76     strncpy (buffer, site, sizeof(buffer));
77     return buffer;
78 }
79
80 /*
81  * Use hostable as an exception file for those hosts that aren't
82  * on the Internet (listed in /etc/hosts).  These are usually
83  * PhoneNet and UUCP sites.
84  */
85
86 #define NALIASES 50
87
88 static int
89 init_hs (void)
90 {
91     unsigned char  *cp;
92     char *dp, **q, **r;
93     char buffer[BUFSIZ], *aliases[NALIASES];
94     register struct host *h;
95     register FILE  *fp;
96
97     if ((fp = fopen (hostable, "r")) == NULL)
98         return 0;
99
100     h = &hosts;
101     while (fgets (buffer, sizeof(buffer), fp) != NULL) {
102         if ((cp = strchr(buffer, '#')))
103             *cp = 0;
104         if ((cp = strchr(buffer, '\n')))
105             *cp = 0;
106         for (cp = buffer; *cp; cp++)
107             if (isspace (*cp))
108                 *cp = ' ';
109         for (cp = buffer; isspace (*cp); cp++)
110             continue;
111         if (*cp == 0)
112             continue;
113
114         q = aliases;
115         if ((cp = strchr(dp = cp, ' '))) {
116             *cp = 0;
117             for (cp++; *cp; cp++) {
118                 while (isspace (*cp))
119                     cp++;
120                 if (*cp == 0)
121                     break;
122                 if ((cp = strchr(*q++ = cp, ' ')))
123                     *cp = 0;
124                 else
125                     break;
126                 if (q >= aliases + NALIASES)
127                     break;
128             }
129         }
130
131         *q = 0;
132
133         h->h_next = (struct host *) calloc (1, sizeof(*h));
134         h = h->h_next;
135         h->h_name = getcpy (dp);
136         r = h->h_aliases =
137                 (char **) calloc ((size_t) (q - aliases + 1), sizeof(*q));
138         for (q = aliases; *q; q++)
139             *r++ = getcpy (*q);
140         *r = 0;
141     }
142
143     fclose (fp);
144     return 1;
145 }