]> git.sur5r.net Git - openldap/blob - libraries/libldap/util-int.c
Fix typo in previous commit.
[openldap] / libraries / libldap / util-int.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /*
6  * util-int.c   Various functions to replace missing threadsafe ones.
7  *                                Without the real *_r funcs, things will
8  *                                work, but might not be threadsafe. 
9  * 
10  * Written by Bart Hartgers.
11  *
12  * Copyright 1998, A. Hartgers, All rights reserved.
13  * This software is not subject to any license of Eindhoven University of
14  * Technology, since it was written in my spare time.
15  *                      
16  * Redistribution and use in source and binary forms are permitted only
17  * as authorized by the OpenLDAP Public License.  A copy of this
18  * license is available at http://www.OpenLDAP.org/license.html or
19  * in file LICENSE in the top-level directory of the distribution.
20  */ 
21
22
23 #include "portable.h"
24
25 #include <stdlib.h>
26
27 #include <ac/errno.h>
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31
32 #include "ldap-int.h"
33
34 #if defined( LDAP_R_COMPILE )
35 # include <ldap_pvt_thread.h>
36 #else
37 # undef HAVE_REENTRANT_FUNCTIONS
38 #endif
39
40 #if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \
41         && defined( CTIME_R_NARGS )
42 #       define USE_CTIME_R
43 #endif
44
45 #ifdef LDAP_R_COMPILE
46 # ifndef USE_CTIME_R
47         static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex;
48 # endif
49 # ifndef HAVE_GETHOSTBYNAME_R
50         static ldap_pvt_thread_mutex_t ldap_int_gethostbyname_mutex;
51 # endif
52 # ifndef HAVE_GETHOSTBYADDR_R
53         static ldap_pvt_thread_mutex_t ldap_int_gethostbyaddr_mutex;
54 # endif
55 #endif /* LDAP_R_COMPILE */
56
57 char *ldap_pvt_ctime( const time_t *tp, char *buf )
58 {
59 #ifdef USE_CTIME_R
60 # if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2)
61         choke me!  nargs should have 2 or 3
62 # elif CTIME_R_NARGS > 2
63         return ctime_r(tp,buf,26);
64 # else
65         return ctime_r(tp,buf);
66 # endif   
67
68 #else
69 # ifdef LDAP_R_COMPILE
70         ldap_pvt_thread_mutex_lock( &ldap_int_ctime_mutex );
71 # endif
72         memcpy( buf, ctime(tp), 26 );
73 # ifdef LDAP_R_COMPILE
74         ldap_pvt_thread_mutex_unlock( &ldap_int_ctime_mutex );
75 # endif
76         return buf;
77 #endif  
78 }
79
80 #define BUFSTART 1024
81 #define BUFMAX (32*1024)
82
83 static char *safe_realloc( char **buf, int len );
84 static int copy_hostent( struct hostent *res, char **buf, struct hostent * src );
85
86 int ldap_pvt_gethostbyname_a(
87         const char *name, 
88         struct hostent *resbuf,
89         char **buf,
90         struct hostent **result,
91         int *herrno_ptr )
92 {
93 #if defined( HAVE_GETHOSTBYNAME_R )
94
95 # if (GETHOSTBYNAME_R_NARGS > 6) || (GETHOSTBYNAME_R_NARGS < 5)
96     Ouch! gethostbyname_r() must have either 5 or 6 args
97 #endif
98
99 # define NEED_SAFE_REALLOC 1   
100         int r=-1;
101         int buflen=BUFSTART;
102         *buf = NULL;
103         for(;buflen<BUFMAX;) {
104                 if (safe_realloc( buf, buflen )==NULL)
105                         return r;
106
107 #if (GETHOSTBYNAME_R_NARGS < 6)
108                 r = ((*result=gethostbyname_r( name, resbuf, *buf,\
109                                                buflen, herrno_ptr ))== NULL) ?\
110                     -1 : 0;
111 #else
112                 r = gethostbyname_r( name, resbuf, *buf,
113                         buflen, result, herrno_ptr );
114 #endif
115
116                 Debug( LDAP_DEBUG_TRACE, "ldap_pvt_gethostbyname_a: host=%s, r=%d\n",\
117                        name, r, 0 );
118
119 #ifdef NETDB_INTERNAL
120                 if ((r<0) &&
121                         (*herrno_ptr==NETDB_INTERNAL) &&
122                         (errno==ERANGE))
123                 {
124                         buflen*=2;
125                         continue;
126                 }
127 #endif
128                 return r;
129         }
130         return -1;
131 #elif defined( LDAP_R_COMPILE )
132 # define NEED_COPY_HOSTENT   
133         struct hostent *he;
134         int     retval;
135         
136         ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyname_mutex );
137         
138         he = gethostbyname( name );
139         
140         if (he==NULL) {
141                 *herrno_ptr = h_errno;
142                 retval = -1;
143         } else if (copy_hostent( resbuf, buf, he )<0) {
144                 *herrno_ptr = -1;
145                 retval = -1;
146         } else {
147                 *result = resbuf;
148                 retval = 0;
149         }
150         
151         ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyname_mutex );
152         
153         return retval;
154 #else   
155         *result = gethostbyname( name );
156
157         if (*result!=NULL) {
158                 return 0;
159         }
160
161         *herrno_ptr = h_errno;
162         
163         return -1;
164 #endif  
165 }
166          
167 int ldap_pvt_gethostbyaddr_a(
168         const char *addr,
169         int len,
170         int type,
171         struct hostent *resbuf,
172         char **buf,
173         struct hostent **result,
174         int *herrno_ptr )
175 {
176 #if defined( HAVE_GETHOSTBYADDR_R )
177
178 #if (GETHOSTBYADDR_R_NARGS > 8) || (GETHOSTBYADDR_R_NARGS < 7)
179     Ouch! gethostbyaddr_r() must have either 7 or 8 args
180 #endif
181
182 # undef NEED_SAFE_REALLOC
183 # define NEED_SAFE_REALLOC   
184         int r=-1;
185         int buflen=BUFSTART;
186         *buf = NULL;   
187         for(;buflen<BUFMAX;) {
188                 if (safe_realloc( buf, buflen )==NULL)
189                         return r;
190 #if (GETHOSTBYADDR_R_NARGS < 8)
191                 r = ((*result=gethostbyaddr_r( addr, len, type,
192                                                resbuf, *buf, buflen, 
193                                                herrno_ptr )) == NULL) ?\
194                     -1 : 0;
195 #else
196                 r = gethostbyaddr_r( addr, len, type,
197                         resbuf, *buf, buflen, 
198                         result, herrno_ptr );
199 #endif
200
201 #ifdef NETDB_INTERNAL
202                 if ((r<0) &&
203                         (*herrno_ptr==NETDB_INTERNAL) &&
204                         (errno==ERANGE))
205                 {
206                         buflen*=2;
207                         continue;
208                 }
209 #endif
210                 return r;
211         }
212         return -1;
213 #elif defined( LDAP_R_COMPILE )
214 # undef NEED_COPY_HOSTENT
215 # define NEED_COPY_HOSTENT   
216         struct hostent *he;
217         int     retval;
218         
219         ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyaddr_mutex );
220         
221         he = gethostbyaddr( addr, len, type );
222         
223         if (he==NULL) {
224                 *herrno_ptr = h_errno;
225                 retval = -1;
226         } else if (copy_hostent( resbuf, buf, he )<0) {
227                 *herrno_ptr = -1;
228                 retval = -1;
229         } else {
230                 *result = resbuf;
231                 retval = 0;
232         }
233         
234         ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyaddr_mutex );
235         
236         return retval;   
237 #else /* gethostbyaddr() */
238         *result = gethostbyaddr( addr, len, type );
239
240         if (*result!=NULL) {
241                 return 0;
242         }
243         return -1;
244 #endif  
245 }
246 /* 
247  * ldap_pvt_init_utils() should be called before any other function.
248  */
249
250 void ldap_pvt_init_utils( void )
251 {
252         static int done=0;
253         if (done)
254           return;
255         done=1;
256
257 #ifdef LDAP_R_COMPILE
258
259 #if !defined( USE_CTIME_R ) && !defined( HAVE_REENTRANT_FUNCTIONS )
260         ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex );
261 #endif
262
263 #if !defined( HAVE_GETHOSTBYNAME_R )
264         ldap_pvt_thread_mutex_init( &ldap_int_gethostbyname_mutex );
265 #endif
266
267 #if !defined( HAVE_GETHOSTBYADDR_R )
268         ldap_pvt_thread_mutex_init( &ldap_int_gethostbyaddr_mutex );
269 #endif
270
271         /* call other module init functions here... */
272 #endif
273 }
274
275 #if defined( NEED_COPY_HOSTENT )
276 # undef NEED_SAFE_REALLOC
277 #define NEED_SAFE_REALLOC
278
279 static char *cpy_aliases( char ***tgtio, char *buf, char **src )
280 {
281         int len;
282         char **tgt=*tgtio;
283         for( ; (*src) ; src++ ) {
284                 len = strlen( *src ) + 1;
285                 memcpy( buf, *src, len );
286                 *tgt++=buf;
287                 buf+=len;
288         }
289         *tgtio=tgt;   
290         return buf;
291 }
292
293 static char *cpy_addresses( char ***tgtio, char *buf, char **src, int len )
294 {
295         char **tgt=*tgtio;
296         for( ; (*src) ; src++ ) {
297                 memcpy( buf, *src, len );
298                 *tgt++=buf;
299                 buf+=len;
300         }
301         *tgtio=tgt;      
302         return buf;
303 }
304
305 static int copy_hostent( struct hostent *res, char **buf, struct hostent * src )
306 {
307         char    **p;
308         char    **tp;
309         char    *tbuf;
310         int     name_len;
311         int     n_alias;
312         int     total_alias_len;
313         int     n_addr;
314         int     total_addr_len;
315         int     total_len;
316           
317         /* calculate the size needed for the buffer */
318         name_len = strlen( src->h_name ) + 1;
319         
320         for( n_alias=total_alias_len=0, p=src->h_aliases; (*p) ; p++ ) {
321                 total_alias_len += strlen( *p ) + 1;
322                 n_alias++; 
323         }
324
325         for( n_addr=0, p=src->h_addr_list; (*p) ; p++ ) {
326                 n_addr++;
327         }
328         total_addr_len = n_addr * src->h_length;
329         
330         total_len = (n_alias + n_addr + 2) * sizeof( char * ) +
331                 total_addr_len + total_alias_len + name_len;
332         
333         if (safe_realloc( buf, total_len )) {                    
334                 tp = (char **) *buf;
335                 tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * );
336                 memcpy( res, src, sizeof( struct hostent ) );
337                 /* first the name... */
338                 memcpy( tbuf, src->h_name, name_len );
339                 res->h_name = tbuf; tbuf+=name_len;
340                 /* now the aliases */
341                 res->h_aliases = tp;
342                 tbuf = cpy_aliases( &tp, tbuf, src->h_aliases );
343                 *tp++=NULL;
344                 /* finally the addresses */
345                 res->h_addr_list = tp;
346                 tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length );
347                 *tp++=NULL;
348                 return 0;
349         }
350         return -1;
351 }
352 #endif
353
354 #if defined( NEED_SAFE_REALLOC )
355 static char *safe_realloc( char **buf, int len )
356 {
357         char *tmpbuf;
358         tmpbuf = realloc( *buf, len );
359         if (tmpbuf) {
360                 *buf=tmpbuf;
361         } 
362         return tmpbuf;
363 }
364 #endif
365
366