2nd try adding CVS id.
[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 #include <sys/types.h>
20
21 #if !defined(WIN32) || defined(WATT32)
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <netdb.h>
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "ares.h"
34 #include "ares_private.h"
35 #include "inet_net_pton.h"
36
37 int ares__get_hostent(FILE *fp, int family, struct hostent **host)
38 {
39   char *line = NULL, *p, *q, *canonical, **alias;
40   int status, linesize, end_at_hostname, naliases;
41   struct in_addr addr;
42   struct in6_addr addr6;
43   int addrlen = sizeof(struct in_addr);
44   struct hostent *hostent = NULL;
45
46   while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
47     {
48       /* Skip comment lines; terminate line at comment character. */
49       if (*line == '#' || !*line)
50         continue;
51       p = strchr(line, '#');
52       if (p)
53         *p = 0;
54
55       /* Get the address part. */
56       p = line;
57       while (*p && !isspace((unsigned char)*p))
58         p++;
59       if (!*p)
60         continue;
61       *p = 0;
62       addr.s_addr = inet_addr(line);
63       if (addr.s_addr == INADDR_NONE)
64        {
65           if (ares_inet_pton(AF_INET6, line, &addr6) > 0)
66             {
67               if (family != AF_INET6)
68                 continue;
69               addrlen = sizeof(struct in6_addr);
70             }
71           else
72             continue;
73        }
74       else if (family != AF_INET)
75         continue;
76
77       /* Get the canonical hostname. */
78       p++;
79       while (isspace((unsigned char)*p))
80         p++;
81       if (!*p)
82         continue;
83       q = p;
84       while (*q && !isspace((unsigned char)*q))
85         q++;
86       end_at_hostname = (*q == 0);
87       *q = 0;
88       canonical = p;
89
90       naliases = 0;
91       if (!end_at_hostname)
92         {
93           /* Count the aliases. */
94           p = q + 1;
95           while (isspace((unsigned char)*p))
96             p++;
97           while (*p)
98             {
99               while (*p && !isspace((unsigned char)*p))
100                 p++;
101               while (isspace((unsigned char)*p))
102                 p++;
103               naliases++;
104             }
105         }
106
107       /* Allocate memory for the host structure. */
108       hostent = malloc(sizeof(struct hostent));
109       if (!hostent)
110         break;
111       hostent->h_aliases = NULL;
112       hostent->h_addr_list = NULL;
113       hostent->h_name = strdup(canonical);
114       if (!hostent->h_name)
115         break;
116       hostent->h_addr_list = malloc(2 * sizeof(char *));
117       if (!hostent->h_addr_list)
118         break;
119       hostent->h_addr_list[0] = malloc(addrlen);
120       if (!hostent->h_addr_list[0])
121         break;
122       hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
123       if (!hostent->h_aliases)
124         break;
125
126       /* Copy in aliases. */
127       naliases = 0;
128       if (!end_at_hostname)
129         {
130           p = canonical + strlen(canonical) + 1;
131           while (isspace((unsigned char)*p))
132             p++;
133           while (*p)
134             {
135               q = p;
136               while (*q && !isspace((unsigned char)*q))
137                 q++;
138               hostent->h_aliases[naliases] = malloc(q - p + 1);
139               if (hostent->h_aliases[naliases] == NULL)
140                 break;
141               memcpy(hostent->h_aliases[naliases], p, q - p);
142               hostent->h_aliases[naliases][q - p] = 0;
143               p = q;
144               while (isspace((unsigned char)*p))
145                 p++;
146               naliases++;
147             }
148           if (*p)
149             break;
150         }
151       hostent->h_aliases[naliases] = NULL;
152
153       hostent->h_addrtype = family;
154       hostent->h_length = addrlen;
155       if (family == AF_INET)
156         memcpy(hostent->h_addr_list[0], &addr, addrlen);
157       else if (family == AF_INET6)
158         memcpy(hostent->h_addr_list[0], &addr6, addrlen);
159       hostent->h_addr_list[1] = NULL;
160       *host = hostent;
161       free(line);
162       return ARES_SUCCESS;
163     }
164   if(line)
165     free(line);
166
167   if (status == ARES_SUCCESS)
168     {
169       /* Memory allocation failure; clean up. */
170       if (hostent)
171         {
172           if(hostent->h_name)
173             free((char *) hostent->h_name);
174           if (hostent->h_aliases)
175             {
176               for (alias = hostent->h_aliases; *alias; alias++)
177                 free(*alias);
178             }
179           if(hostent->h_aliases)
180             free(hostent->h_aliases);
181           if (hostent->h_addr_list && hostent->h_addr_list[0])
182             free(hostent->h_addr_list[0]);
183           if(hostent->h_addr_list)
184             free(hostent->h_addr_list);
185           free(hostent);
186         }
187       return ARES_ENOMEM;
188     }
189
190   return status;
191 }