Fixed mhlist -verbose to work with all content types [Bug #35219].
[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 <sys/socket.h>
20 #include <netdb.h>
21
22 static struct host {
23     char *h_name;
24     char **h_aliases;
25     struct host *h_next;
26 } hosts;
27
28
29 /*
30  * static prototypes
31  */
32 static int init_hs(void);
33
34
35 char *
36 OfficialName (char *name)
37 {
38     unsigned char *p;
39     char *q, site[BUFSIZ];
40     struct addrinfo hints, *res;
41
42     static char buffer[BUFSIZ];
43     char **r;
44     struct host *h;
45
46     for (p = name, q = site; *p && (q - site < (int)sizeof(site) - 1); p++, q++)
47         *q = isupper (*p) ? tolower (*p) : *p;
48     *q = '\0';
49     q = site;
50
51     if (!mh_strcasecmp (LocalName(1), site))
52         return LocalName(1);
53
54     memset(&hints, 0, sizeof(hints));
55     hints.ai_flags = AI_CANONNAME;
56     hints.ai_family = PF_UNSPEC;
57
58     if (getaddrinfo(q, NULL, &hints, &res) == 0) {
59         strncpy (buffer, res->ai_canonname, sizeof(buffer));
60         buffer[sizeof(buffer) - 1] = '\0';
61         freeaddrinfo(res);
62         return buffer;
63     }
64     if (hosts.h_name || init_hs ()) {
65         for (h = hosts.h_next; h; h = h->h_next)
66             if (!mh_strcasecmp (h->h_name, q)) {
67                 return h->h_name;
68             } else {
69                 for (r = h->h_aliases; *r; r++)
70                     if (!mh_strcasecmp (*r, q))
71                         return h->h_name;
72             }
73     }
74
75     strncpy (buffer, site, sizeof(buffer));
76     return buffer;
77 }
78
79 /*
80  * Use hostable as an exception file for those hosts that aren't
81  * on the Internet (listed in /etc/hosts).  These are usually
82  * PhoneNet and UUCP sites.
83  */
84
85 #define NALIASES 50
86
87 static int
88 init_hs (void)
89 {
90     unsigned char  *cp;
91     char *dp, **q, **r;
92     char buffer[BUFSIZ], *aliases[NALIASES];
93     register struct host *h;
94     register FILE  *fp;
95
96     if ((fp = fopen (hostable, "r")) == NULL)
97         return 0;
98
99     h = &hosts;
100     while (fgets (buffer, sizeof(buffer), fp) != NULL) {
101         if ((cp = strchr(buffer, '#')))
102             *cp = 0;
103         if ((cp = strchr(buffer, '\n')))
104             *cp = 0;
105         for (cp = buffer; *cp; cp++)
106             if (isspace (*cp))
107                 *cp = ' ';
108         for (cp = buffer; isspace (*cp); cp++)
109             continue;
110         if (*cp == 0)
111             continue;
112
113         q = aliases;
114         if ((cp = strchr(dp = cp, ' '))) {
115             *cp = 0;
116             for (cp++; *cp; cp++) {
117                 while (isspace (*cp))
118                     cp++;
119                 if (*cp == 0)
120                     break;
121                 if ((cp = strchr(*q++ = cp, ' ')))
122                     *cp = 0;
123                 else
124                     break;
125                 if (q >= aliases + NALIASES)
126                     break;
127             }
128         }
129
130         *q = 0;
131
132         h->h_next = (struct host *) calloc (1, sizeof(*h));
133         h = h->h_next;
134         h->h_name = getcpy (dp);
135         r = h->h_aliases =
136                 (char **) calloc ((size_t) (q - aliases + 1), sizeof(*q));
137         for (q = aliases; *q; q++)
138             *r++ = getcpy (*q);
139         *r = 0;
140     }
141
142     fclose (fp);
143     return 1;
144 }