Initial import from FreeBSD RELENG_4:
[games.git] / lib / libcr / net / gethostnamadr.c
1 /*-
2  * Copyright (c) 1994, Garrett Wollman
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #if defined(LIBC_SCCS) && !defined(lint)
27 static char sccsid[] = "@(#)$FreeBSD: src/lib/libc/net/gethostnamadr.c,v 1.15.2.2 2001/03/05 10:40:42 obrien Exp $";
28 static char rcsid[] = "$FreeBSD: src/lib/libc/net/gethostnamadr.c,v 1.15.2.2 2001/03/05 10:40:42 obrien Exp $";
29 #endif /* LIBC_SCCS and not lint */
30
31 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <netdb.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <string.h>
39 #include <arpa/nameser.h>               /* XXX hack for _res */
40 #include <resolv.h>                     /* XXX hack for _res */
41
42 #define _PATH_HOSTCONF  "/etc/host.conf"
43
44 enum service_type {
45   SERVICE_NONE = 0,
46   SERVICE_BIND,
47   SERVICE_HOSTS,
48   SERVICE_NIS };
49 #define SERVICE_MAX     SERVICE_NIS
50
51 static struct {
52   const char *name;
53   enum service_type type;
54 } service_names[] = {
55   { "hosts", SERVICE_HOSTS },
56   { "/etc/hosts", SERVICE_HOSTS },
57   { "hosttable", SERVICE_HOSTS },
58   { "htable", SERVICE_HOSTS },
59   { "bind", SERVICE_BIND },
60   { "dns", SERVICE_BIND },
61   { "domain", SERVICE_BIND },
62   { "yp", SERVICE_NIS },
63   { "yellowpages", SERVICE_NIS },
64   { "nis", SERVICE_NIS },
65   { 0, SERVICE_NONE }
66 };
67
68 static enum service_type service_order[SERVICE_MAX + 1];
69 static int service_done = 0;
70
71 static enum service_type
72 get_service_name(const char *name) {
73         int i;
74         for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
75                 if(!strcasecmp(name, service_names[i].name)) {
76                         return service_names[i].type;
77                 }
78         }
79         return SERVICE_NONE;
80 }
81
82 static void
83 init_services()
84 {
85         char *cp, *p, buf[BUFSIZ];
86         register int cc = 0;
87         FILE *fd;
88
89         if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) {
90                                 /* make some assumptions */
91                 service_order[0] = SERVICE_BIND;
92                 service_order[1] = SERVICE_HOSTS;
93                 service_order[2] = SERVICE_NONE;
94         } else {
95                 while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
96                         if(buf[0] == '#')
97                                 continue;
98
99                         p = buf;
100                         while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
101                                 ;
102                         if (cp == NULL)
103                                 continue;
104                         do {
105                                 if (isalpha((unsigned char)cp[0])) {
106                                         service_order[cc] = get_service_name(cp);
107                                         if(service_order[cc] != SERVICE_NONE)
108                                                 cc++;
109                                 }
110                                 while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
111                                         ;
112                         } while(cp != NULL && cc < SERVICE_MAX);
113                 }
114                 service_order[cc] = SERVICE_NONE;
115                 fclose(fd);
116         }
117         service_done = 1;
118 }
119
120 struct hostent *
121 gethostbyname(const char *name)
122 {
123         struct hostent *hp;
124
125         if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
126                 h_errno = NETDB_INTERNAL;
127                 return (NULL);
128         }
129         if (_res.options & RES_USE_INET6) {             /* XXX */
130                 hp = gethostbyname2(name, AF_INET6);    /* XXX */
131                 if (hp)                                 /* XXX */
132                         return (hp);                    /* XXX */
133         }                                               /* XXX */
134         return (gethostbyname2(name, AF_INET));
135 }
136
137 struct hostent *
138 gethostbyname2(const char *name, int type)
139 {
140         struct hostent *hp = 0;
141         int nserv = 0;
142
143         if (!service_done)
144                 init_services();
145
146         while (!hp) {
147                 switch (service_order[nserv]) {
148                       case SERVICE_NONE:
149                         return NULL;
150                       case SERVICE_HOSTS:
151                         hp = _gethostbyhtname(name, type);
152                         break;
153                       case SERVICE_BIND:
154                         hp = _gethostbydnsname(name, type);
155                         break;
156                       case SERVICE_NIS:
157                         hp = _gethostbynisname(name, type);
158                         break;
159                 }
160                 nserv++;
161         }
162         return hp;
163 }
164
165 struct hostent *
166 gethostbyaddr(const char *addr, int len, int type)
167 {
168         struct hostent *hp = 0;
169         int nserv = 0;
170
171         if (!service_done)
172                 init_services();
173
174         while (!hp) {
175                 switch (service_order[nserv]) {
176                       case SERVICE_NONE:
177                         return 0;
178                       case SERVICE_HOSTS:
179                         hp = _gethostbyhtaddr(addr, len, type);
180                         break;
181                       case SERVICE_BIND:
182                         hp = _gethostbydnsaddr(addr, len, type);
183                         break;
184                       case SERVICE_NIS:
185                         hp = _gethostbynisaddr(addr, len, type);
186                         break;
187                 }
188                 nserv++;
189         }
190         return hp;
191 }
192
193 #ifdef _THREAD_SAFE
194 struct hostent_data;
195
196 /*
197  * Temporary function (not thread safe)
198  */
199 int gethostbyaddr_r(const char *addr, int len, int type,
200         struct hostent *result, struct hostent_data *buffer)
201 {
202         struct hostent *hp;
203         int ret;
204         if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
205                 ret = -1;
206         } else {
207                 memcpy(result, hp, sizeof(struct hostent));
208                 ret = 0;
209         }
210         return(ret);
211 }
212 #endif
213
214 void
215 sethostent(stayopen)
216         int stayopen;
217 {
218         _sethosthtent(stayopen);
219         _sethostdnsent(stayopen);
220 }
221
222 void
223 endhostent()
224 {
225         _endhosthtent();
226         _endhostdnsent();
227 }