1 /*
2 * This file is a ghastly hack because nobody can agree on
3 * gethostbyname_r()'s prototype.
4 *
5 * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #define _SVID_SOURCE 1 /* Need this to get gethostbyname_r() */
28 #include <assert.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <netdb.h>
33 #include <errno.h>
35 #include "gethostbyname.h"
37 #if HAVE_GETIPNODEBYNAME
39 void
40 free_ghbnctx (struct ghbnctx *ctx)
41 {
42 assert (ctx != NULL);
44 if (ctx->hostent != NULL)
45 freehostent (ctx->hostent);
46 }
48 struct hostent *
49 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
50 {
51 assert (ctx != NULL);
53 memset (ctx, 0, sizeof (struct ghbnctx));
54 ctx->hostent = getipnodebyname (host, AF_UNSPEC, AI_ADDRCONFIG, &ctx->h_err);
55 return ctx->hostent;
56 }
58 int
59 h_error_ctx (struct ghbnctx *ctx)
60 {
61 assert (ctx != NULL);
63 return ctx->h_err;
64 }
66 #elif HAVE_GETHOSTBYNAME_R == 6
68 void
69 free_ghbnctx (struct ghbnctx *ctx)
70 {
71 assert (ctx != NULL);
73 if (ctx->hostbuf != NULL)
74 free (ctx->hostbuf);
75 }
77 struct hostent *
78 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
79 {
80 struct hostent *hp;
81 char *tmp;
82 int err;
84 assert (ctx != NULL);
86 memset (ctx, 0, sizeof (struct ghbnctx));
87 ctx->hostbuf_len = 2048;
88 if ((ctx->hostbuf = malloc (ctx->hostbuf_len)) == NULL)
89 {
90 errno = ENOMEM;
91 return NULL;
92 }
93 while ((err = gethostbyname_r (host,
94 &ctx->hostent, ctx->hostbuf, ctx->hostbuf_len,
95 &hp, &ctx->h_err)) == ERANGE)
96 {
97 ctx->hostbuf_len += 1024;
98 if ((tmp = realloc (ctx->hostbuf, ctx->hostbuf_len)) == NULL)
99 {
100 errno = ENOMEM;
101 return NULL;
102 }
103 ctx->hostbuf = tmp;
104 }
105 if (err != 0)
106 {
107 errno = err;
108 return NULL;
109 }
110 return hp;
111 }
113 int
114 h_error_ctx (struct ghbnctx *ctx)
115 {
116 assert (ctx != NULL);
118 return ctx->h_err;
119 }
121 #elif HAVE_GETHOSTBYNAME_R == 5
123 void
124 free_ghbnctx (struct ghbnctx *ctx)
125 {
126 assert (ctx != NULL);
128 if (ctx->hostbuf != NULL)
129 free (ctx->hostbuf);
130 }
132 struct hostent *
133 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
134 {
135 struct hostent *hp;
136 char *tmp;
138 assert (ctx != NULL);
140 memset (ctx, 0, sizeof (struct ghbnctx));
141 ctx->hostbuf_len = 2048;
142 if ((ctx->hostbuf = malloc (ctx->hostbuf_len)) == NULL)
143 {
144 errno = ENOMEM;
145 return NULL;
146 }
147 while ((hp = gethostbyname_r (host, &ctx->hostent,
148 ctx->hostbuf, ctx->hostbuf_len,
149 &ctx->h_err)) == NULL && errno == ERANGE)
150 {
151 ctx->hostbuf_len += 1024;
152 if ((tmp = realloc (ctx->hostbuf, ctx->hostbuf_len)) == NULL)
153 {
154 errno = ENOMEM;
155 return NULL;
156 }
157 ctx->hostbuf = tmp;
158 }
159 return hp;
160 }
162 int
163 h_error_ctx (struct ghbnctx *ctx)
164 {
165 assert (ctx != NULL);
167 return ctx->h_err;
168 }
170 #elif HAVE_GETHOSTBYNAME_R == 3
172 void
173 free_ghbnctx (struct ghbnctx *ctx)
174 {
175 assert (ctx != NULL);
177 /* FIXME: does this need to do anything? */
178 }
180 struct hostent *
181 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
182 {
183 assert (ctx != NULL);
185 if (!gethostbyname_r (host, &ctx->hostent, &ctx->hostent_data))
186 {
187 ctx->h_err = h_errno; /* FIXME: is this correct? */
188 return NULL;
189 }
190 return &ctx->hostent;
191 }
193 int
194 h_error_ctx (struct ghbnctx *ctx)
195 {
196 assert (ctx != NULL);
198 return ctx->h_err;
199 }
201 #else
203 void
204 free_ghbnctx (struct ghbnctx *ctx __attribute__ ((unused)))
205 {
206 assert (ctx != NULL);
207 }
209 struct hostent *
210 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
211 {
212 struct hostent *hp;
214 hp = gethostbyname (host);
215 if (hp == NULL)
216 ctx->h_err = h_errno;
217 return hp;
218 }
220 int
221 h_error_ctx (struct ghbnctx *ctx)
222 {
223 assert (ctx != NULL);
225 return ctx->h_err;
226 }
228 #endif