]> Pileus Git - ~andy/fetchmail/blob - libesmtp/gethostbyname.c
Credit John Beck's fixes.
[~andy/fetchmail] / libesmtp / gethostbyname.c
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  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #define _SVID_SOURCE    1       /* Need this to get gethostbyname_r() */
27
28 #include <assert.h>
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <netdb.h>
33 #include <errno.h>
34
35 #include "gethostbyname.h"
36
37 #if HAVE_GETIPNODEBYNAME
38
39 void
40 free_ghbnctx (struct ghbnctx *ctx)
41 {
42   assert (ctx != NULL);
43
44   if (ctx->hostent != NULL)
45     freehostent (ctx->hostent);
46 }
47
48 struct hostent *
49 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
50 {
51   assert (ctx != NULL);
52
53   memset (ctx, 0, sizeof (struct ghbnctx));
54   ctx->hostent = getipnodebyname (host, AF_UNSPEC, AI_ADDRCONFIG, &ctx->h_err);
55   return ctx->hostent;
56 }
57
58 int
59 h_error_ctx (struct ghbnctx *ctx)
60 {
61   assert (ctx != NULL);
62
63   return ctx->h_err;
64 }
65
66 #elif HAVE_GETHOSTBYNAME_R == 6
67
68 void
69 free_ghbnctx (struct ghbnctx *ctx)
70 {
71   assert (ctx != NULL);
72
73   if (ctx->hostbuf != NULL)
74     free (ctx->hostbuf);
75 }
76
77 struct hostent *
78 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
79 {
80   struct hostent *hp;
81   char *tmp;
82   int err;
83
84   assert (ctx != NULL);
85
86   memset (ctx, 0, sizeof (struct ghbnctx));
87   ctx->hostbuf_len = 2048;
88   if ((ctx->hostbuf = (char *)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 = (char *)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 }
112
113 int
114 h_error_ctx (struct ghbnctx *ctx)
115 {
116   assert (ctx != NULL);
117
118   return ctx->h_err;
119 }
120
121 #elif HAVE_GETHOSTBYNAME_R == 5
122
123 void
124 free_ghbnctx (struct ghbnctx *ctx)
125 {
126   assert (ctx != NULL);
127
128   if (ctx->hostbuf != NULL)
129     free (ctx->hostbuf);
130 }
131
132 struct hostent *
133 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
134 {
135   struct hostent *hp;
136   char *tmp;
137
138   assert (ctx != NULL);
139
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 }
161
162 int
163 h_error_ctx (struct ghbnctx *ctx)
164 {
165   assert (ctx != NULL);
166
167   return ctx->h_err;
168 }
169
170 #elif HAVE_GETHOSTBYNAME_R == 3
171
172 void
173 free_ghbnctx (struct ghbnctx *ctx)
174 {
175   assert (ctx != NULL);
176
177   /* FIXME: does this need to do anything? */
178 }
179
180 struct hostent *
181 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
182 {
183   assert (ctx != NULL);
184
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 }
192   
193 int
194 h_error_ctx (struct ghbnctx *ctx)
195 {
196   assert (ctx != NULL);
197
198   return ctx->h_err;
199 }
200
201 #else
202
203 void
204 free_ghbnctx (struct ghbnctx *ctx )
205 {
206   assert (ctx != NULL);
207 }
208
209 struct hostent *
210 gethostbyname_ctx (const char *host, struct ghbnctx *ctx)
211 {
212   struct hostent *hp;
213
214   hp = gethostbyname (host);
215   if (hp == NULL)
216     ctx->h_err = h_errno;
217   return hp;
218 }
219
220 int
221 h_error_ctx (struct ghbnctx *ctx)
222 {
223   assert (ctx != NULL);
224
225   return ctx->h_err;
226 }
227
228 #endif