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