Support Watt-32 under Win32.
[platform/upstream/c-ares.git] / ares__get_hostent.c
1 /* $Id$ */
2
3 /* Copyright 1998 by the Massachusetts Institute of Technology.
4  *
5  * Permission to use, copy, modify, and distribute this
6  * software and its documentation for any purpose and without
7  * fee is hereby granted, provided that the above copyright
8  * notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting
10  * documentation, and that the name of M.I.T. not be used in
11  * advertising or publicity pertaining to distribution of the
12  * software without specific, written prior permission.
13  * M.I.T. makes no representations about the suitability of
14  * this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  */
17
18 #include "setup.h"
19
20 #if !defined(WIN32) || defined(WATT32)
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <netdb.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31
32 #include "ares.h"
33 #include "ares_private.h"
34 #include "inet_net_pton.h"
35
36 int ares__get_hostent(FILE *fp, int family, struct hostent **host)
37 {
38   char *line = NULL, *p, *q, *canonical, **alias;
39   int status, linesize, end_at_hostname, naliases;
40   struct in_addr addr;
41   struct in6_addr addr6;
42   int addrlen = sizeof(struct in_addr);
43   struct hostent *hostent = NULL;
44
45   while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
46     {
47       /* Skip comment lines; terminate line at comment character. */
48       if (*line == '#' || !*line)
49         continue;
50       p = strchr(line, '#');
51       if (p)
52         *p = 0;
53
54       /* Get the address part. */
55       p = line;
56       while (*p && !ISSPACE(*p))
57         p++;
58       if (!*p)
59         continue;
60       *p = 0;
61       addr.s_addr = inet_addr(line);
62       if (addr.s_addr == INADDR_NONE)
63        {
64           if (ares_inet_pton(AF_INET6, line, &addr6) > 0)
65             {
66               if (family != AF_INET6)
67                 continue;
68               addrlen = sizeof(struct in6_addr);
69             }
70           else
71             continue;
72        }
73       else if (family != AF_INET)
74         continue;
75
76       /* Get the canonical hostname. */
77       p++;
78       while (ISSPACE(*p))
79         p++;
80       if (!*p)
81         continue;
82       q = p;
83       while (*q && !ISSPACE(*q))
84         q++;
85       end_at_hostname = (*q == 0);
86       *q = 0;
87       canonical = p;
88
89       naliases = 0;
90       if (!end_at_hostname)
91         {
92           /* Count the aliases. */
93           p = q + 1;
94           while (ISSPACE(*p))
95             p++;
96           while (*p)
97             {
98               while (*p && !ISSPACE(*p))
99                 p++;
100               while (ISSPACE(*p))
101                 p++;
102               naliases++;
103             }
104         }
105
106       /* Allocate memory for the host structure. */
107       hostent = malloc(sizeof(struct hostent));
108       if (!hostent)
109         break;
110       hostent->h_aliases = NULL;
111       hostent->h_addr_list = NULL;
112       hostent->h_name = strdup(canonical);
113       if (!hostent->h_name)
114         break;
115       hostent->h_addr_list = malloc(2 * sizeof(char *));
116       if (!hostent->h_addr_list)
117         break;
118       hostent->h_addr_list[0] = malloc(addrlen);
119       if (!hostent->h_addr_list[0])
120         break;
121       hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
122       if (!hostent->h_aliases)
123         break;
124
125       /* Copy in aliases. */
126       naliases = 0;
127       if (!end_at_hostname)
128         {
129           p = canonical + strlen(canonical) + 1;
130           while (ISSPACE(*p))
131             p++;
132           while (*p)
133             {
134               q = p;
135               while (*q && !ISSPACE(*q))
136                 q++;
137               hostent->h_aliases[naliases] = malloc(q - p + 1);
138               if (hostent->h_aliases[naliases] == NULL)
139                 break;
140               memcpy(hostent->h_aliases[naliases], p, q - p);
141               hostent->h_aliases[naliases][q - p] = 0;
142               p = q;
143               while (ISSPACE(*p))
144                 p++;
145               naliases++;
146             }
147           if (*p)
148             break;
149         }
150       hostent->h_aliases[naliases] = NULL;
151
152       hostent->h_addrtype = family;
153       hostent->h_length = addrlen;
154       if (family == AF_INET)
155         memcpy(hostent->h_addr_list[0], &addr, addrlen);
156       else if (family == AF_INET6)
157         memcpy(hostent->h_addr_list[0], &addr6, addrlen);
158       hostent->h_addr_list[1] = NULL;
159       *host = hostent;
160       free(line);
161       return ARES_SUCCESS;
162     }
163   if(line)
164     free(line);
165
166   if (status == ARES_SUCCESS)
167     {
168       /* Memory allocation failure; clean up. */
169       if (hostent)
170         {
171           if(hostent->h_name)
172             free((char *) hostent->h_name);
173           if (hostent->h_aliases)
174             {
175               for (alias = hostent->h_aliases; *alias; alias++)
176                 free(*alias);
177             }
178           if(hostent->h_aliases)
179             free(hostent->h_aliases);
180           if (hostent->h_addr_list && hostent->h_addr_list[0])
181             free(hostent->h_addr_list[0]);
182           if(hostent->h_addr_list)
183             free(hostent->h_addr_list);
184           free(hostent);
185         }
186       *host = NULL;
187       return ARES_ENOMEM;
188     }
189
190   return status;
191 }