Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.3 / lib / bind / irs / gethostent_r.c
1 /*
2  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (c) 1998-1999 by Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static const char rcsid[] = "$Id: gethostent_r.c,v 1.4.206.4 2005/09/03 12:47:38 marka Exp $";
20 #endif /* LIBC_SCCS and not lint */
21
22 #include <port_before.h>
23 #if !defined(_REENTRANT) || !defined(DO_PTHREADS)
24         static int gethostent_r_not_required = 0;
25 #else
26 #include <errno.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <netinet/in.h>
31 #include <netdb.h>
32 #include <sys/param.h>
33 #include <port_after.h>
34
35 #ifdef HOST_R_RETURN
36
37 static HOST_R_RETURN 
38 copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS);
39
40 HOST_R_RETURN
41 gethostbyname_r(const char *name,  struct hostent *hptr, HOST_R_ARGS) {
42         struct hostent *he = gethostbyname(name);
43 #ifdef HOST_R_SETANSWER
44         int n = 0;
45 #endif
46
47 #ifdef HOST_R_ERRNO
48         HOST_R_ERRNO;
49 #endif
50
51 #ifdef HOST_R_SETANSWER
52         if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
53                 *answerp = NULL;
54         else
55                 *answerp = hptr;
56         
57         return (n);
58 #else
59         if (he == NULL)
60                 return (HOST_R_BAD);
61
62         return (copy_hostent(he, hptr, HOST_R_COPY));
63 #endif
64 }
65
66 HOST_R_RETURN
67 gethostbyaddr_r(const char *addr, int len, int type,
68                 struct hostent *hptr, HOST_R_ARGS) {
69         struct hostent *he = gethostbyaddr(addr, len, type);
70 #ifdef HOST_R_SETANSWER
71         int n = 0;
72 #endif
73
74 #ifdef HOST_R_ERRNO
75         HOST_R_ERRNO;
76 #endif
77
78 #ifdef HOST_R_SETANSWER
79         if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
80                 *answerp = NULL;
81         else
82                 *answerp = hptr;
83         
84         return (n);
85 #else
86         if (he == NULL)
87                 return (HOST_R_BAD);
88
89         return (copy_hostent(he, hptr, HOST_R_COPY));
90 #endif
91 }
92
93 /*
94  *      These assume a single context is in operation per thread.
95  *      If this is not the case we will need to call irs directly
96  *      rather than through the base functions.
97  */
98
99 HOST_R_RETURN
100 gethostent_r(struct hostent *hptr, HOST_R_ARGS) {
101         struct hostent *he = gethostent();
102 #ifdef HOST_R_SETANSWER
103         int n = 0;
104 #endif
105
106 #ifdef HOST_R_ERRNO
107         HOST_R_ERRNO;
108 #endif
109
110 #ifdef HOST_R_SETANSWER
111         if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0)
112                 *answerp = NULL;
113         else
114                 *answerp = hptr;
115         
116         return (n);
117 #else
118         if (he == NULL)
119                 return (HOST_R_BAD);
120
121         return (copy_hostent(he, hptr, HOST_R_COPY));
122 #endif
123 }
124
125 HOST_R_SET_RETURN
126 #ifdef HOST_R_ENT_ARGS
127 sethostent_r(int stay_open, HOST_R_ENT_ARGS)
128 #else
129 sethostent_r(int stay_open)
130 #endif
131 {
132 #ifdef HOST_R_ENT_ARGS
133         UNUSED(hdptr);
134 #endif
135         sethostent(stay_open);
136 #ifdef  HOST_R_SET_RESULT
137         return (HOST_R_SET_RESULT);
138 #endif
139 }
140
141 HOST_R_END_RETURN
142 #ifdef HOST_R_ENT_ARGS
143 endhostent_r(HOST_R_ENT_ARGS)
144 #else
145 endhostent_r(void)
146 #endif
147 {
148 #ifdef HOST_R_ENT_ARGS
149         UNUSED(hdptr);
150 #endif
151         endhostent();
152         HOST_R_END_RESULT(HOST_R_OK);
153 }
154
155 /* Private */
156
157 #ifndef HOSTENT_DATA
158 static HOST_R_RETURN
159 copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
160         char *cp;
161         char **ptr;
162         int i, n;
163         int nptr, len;
164
165         /* Find out the amount of space required to store the answer. */
166         nptr = 2; /* NULL ptrs */
167         len = (char *)ALIGN(buf) - buf;
168         for (i = 0; he->h_addr_list[i]; i++, nptr++) {
169                 len += he->h_length;
170         }
171         for (i = 0; he->h_aliases[i]; i++, nptr++) {
172                 len += strlen(he->h_aliases[i]) + 1;
173         }
174         len += strlen(he->h_name) + 1;
175         len += nptr * sizeof(char*);
176         
177         if (len > buflen) {
178                 errno = ERANGE;
179                 return (HOST_R_BAD);
180         }
181
182         /* copy address size and type */
183         hptr->h_addrtype = he->h_addrtype;
184         n = hptr->h_length = he->h_length;
185
186         ptr = (char **)ALIGN(buf);
187         cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
188
189         /* copy address list */
190         hptr->h_addr_list = ptr;
191         for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
192                 memcpy(cp, he->h_addr_list[i], n);
193                 hptr->h_addr_list[i] = cp;
194                 cp += n;
195         }
196         hptr->h_addr_list[i] = NULL;
197         ptr++;
198
199         /* copy official name */
200         n = strlen(he->h_name) + 1;
201         strcpy(cp, he->h_name);
202         hptr->h_name = cp;
203         cp += n;
204
205         /* copy aliases */
206         hptr->h_aliases = ptr;
207         for (i = 0 ; he->h_aliases[i]; i++) {
208                 n = strlen(he->h_aliases[i]) + 1;
209                 strcpy(cp, he->h_aliases[i]);
210                 hptr->h_aliases[i] = cp;
211                 cp += n;
212         }
213         hptr->h_aliases[i] = NULL;
214
215         return (HOST_R_OK);
216 }
217 #else /* !HOSTENT_DATA */
218 static int
219 copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) {
220         char *cp, *eob;
221         int i, n;
222
223         /* copy address size and type */
224         hptr->h_addrtype = he->h_addrtype;
225         n = hptr->h_length = he->h_length;
226
227         /* copy up to first 35 addresses */
228         i = 0;
229         cp = hdptr->hostbuf;
230         eob = hdptr->hostbuf + sizeof(hdptr->hostbuf);
231         hptr->h_addr_list = hdptr->h_addr_ptrs;
232         while (he->h_addr_list[i] && i < (_MAXADDRS)) {
233                 if (n < (eob - cp)) {
234                         memcpy(cp, he->h_addr_list[i], n);
235                         hptr->h_addr_list[i] = cp;
236                         cp += n;
237                 } else {
238                         break;
239                 }
240                 i++;
241         }
242         hptr->h_addr_list[i] = NULL;
243
244         /* copy official name */
245         if ((n = strlen(he->h_name) + 1) < (eob - cp)) {
246                 strcpy(cp, he->h_name);
247                 hptr->h_name = cp;
248                 cp += n;
249         } else {
250                 return (-1);
251         }
252
253         /* copy aliases */
254         i = 0;
255         hptr->h_aliases = hdptr->host_aliases;
256         while (he->h_aliases[i] && i < (_MAXALIASES-1)) {
257                 if ((n = strlen(he->h_aliases[i]) + 1) < (eob - cp)) {
258                         strcpy(cp, he->h_aliases[i]);
259                         hptr->h_aliases[i] = cp;
260                         cp += n;
261                 } else {
262                         break;
263                 }
264                 i++;
265         }
266         hptr->h_aliases[i] = NULL;
267
268         return (HOST_R_OK);
269 }
270 #endif /* !HOSTENT_DATA */
271 #else /* HOST_R_RETURN */
272         static int gethostent_r_unknown_system = 0;
273 #endif /* HOST_R_RETURN */
274 #endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */