]> git.sur5r.net Git - openldap/blob - libraries/libldap/util-int.c
Move libldap/strdup.c to string.c.
[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 work, but won't be
8  *                                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 #include "portable.h"
23
24 #include <stdlib.h>
25
26 #include <ac/errno.h>
27 #include <ac/socket.h>
28 #include <ac/string.h>
29 #include <ac/time.h>
30
31 #include "ldap-int.h"
32
33 #if defined( LDAP_R_COMPILE )
34 # include <ldap_pvt_thread.h>
35 # if !defined( HAVE_REENTRANT_FUNCTIONS )
36 #  if !defined( HAVE_CTIME_R )
37 #   define LDAP_INT_CTIME_MUTEX 1
38 #  endif
39 #  if !defined( HAVE_GETHOSTBYNAME_R )
40 #   define LDAP_INT_GETHOSTBYNAME_MUTEX 1
41 #  endif
42 #  if !defined( HAVE_GETHOSTBYADDR_R )
43 #   define LDAP_INT_GETHOSTBYADDR_MUTEX 1
44 #  endif
45 # endif /* defined( HAVE_REENTRANT_FUNCTIONS ) */
46
47 #if defined( LDAP_INT_CTIME_MUTEX )
48 static ldap_pvt_thread_mutex_t ldap_int_ctime_mutex;
49 #endif
50 #if defined( LDAP_INT_GETHOSTBYNAME_MUTEX )
51 static ldap_pvt_thread_mutex_t ldap_int_gethostbyname_mutex;
52 #endif
53 #if defined( LDAP_INT_GETHOSTBYADDR_MUTEX )
54 static ldap_pvt_thread_mutex_t ldap_int_gethostbyaddr_mutex;
55 #endif
56 #else /* LDAP_R_COMPILE */
57 #undef HAVE_REENTRANT_FUNCTIONS
58 #endif
59
60 char *ldap_pvt_ctime( const time_t *tp, char *buf )
61 {
62 #if (defined( HAVE_CTIME_R ) || defined( HAVE_REENTRANT_FUNCTIONS)) \
63         && defined( CTIME_R_NARGS )
64 # if (CTIME_R_NARGS > 3) || (CTIME_R_NARGS < 2)
65         choke me!  nargs should have 2 or 3
66 # elif CTIME_R_NARGS > 2
67         return ctime_r(tp,buf,26);
68 # else
69         return ctime_r(tp,buf);
70 # endif   
71 #else
72 # if defined( LDAP_INT_CTIME_MUTEX )
73         ldap_pvt_thread_mutex_lock( &ldap_int_ctime_mutex );
74 # endif 
75         memcpy( buf, ctime(tp), 26 );
76 # if defined( LDAP_INT_CTIME_MUTEX )
77         ldap_pvt_thread_mutex_unlock( &ldap_int_ctime_mutex );
78 # endif 
79         return buf;
80 #endif  
81 }
82
83 #define BUFSTART 1024
84 #define BUFMAX (32*1024)
85
86 static char *safe_realloc( char **buf, int len );
87 static int copy_hostent( struct hostent *res, char **buf, struct hostent * src );
88
89 int ldap_pvt_gethostbyname_a(
90         const char *name, 
91         struct hostent *resbuf,
92         char **buf,
93         struct hostent **result,
94         int *herrno_ptr )
95 {
96 #if defined( HAVE_GETHOSTBYNAME_R ) || defined( HAVE_REENTRANT_FUNCTIONS )
97 # define NEED_SAFE_REALLOC 1   
98         int r=-1;
99         int buflen=BUFSTART;
100         *buf = NULL;
101         for(;buflen<BUFMAX;) {
102                 if (safe_realloc( buf, buflen )==NULL)
103                         return r;
104                 r = gethostbyname_r( name, resbuf, *buf,
105                         buflen, result, herrno_ptr );
106 #ifdef NETDB_INTERNAL
107                 if ((r<0) &&
108                         (*herrno_ptr==NETDB_INTERNAL) &&
109                         (errno==ERANGE))
110                 {
111                         buflen*=2;
112                         continue;
113                 }
114 #endif
115                 return r;
116         }
117         return -1;
118 #elif defined( LDAP_INT_GETHOSTBYNAME_MUTEX )
119 # define NEED_COPY_HOSTENT   
120         struct hostent *he;
121         int     retval;
122         
123         ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyname_mutex );
124         
125         he = gethostbyname( name );
126         
127         if (he==NULL) {
128                 *herrno_ptr = h_errno;
129                 retval = -1;
130         } else if (copy_hostent( resbuf, buf, he )<0) {
131                 *herrno_ptr = -1;
132                 retval = -1;
133         } else {
134                 *result = resbuf;
135                 retval = 0;
136         }
137         
138         ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyname_mutex );
139         
140         return retval;
141 #else   
142         *result = gethostbyname( name );
143
144         if (*result!=NULL) {
145                 return 0;
146         }
147
148         *herrno_ptr = h_errno;
149         
150         return -1;
151 #endif  
152 }
153          
154 int ldap_pvt_gethostbyaddr_a(
155         const char *addr,
156         int len,
157         int type,
158         struct hostent *resbuf,
159         char **buf,
160         struct hostent **result,
161         int *herrno_ptr )
162 {
163 #if defined( HAVE_GETHOSTBYADDR_R ) || defined( HAVE_REENTRANT_FUNCTIONS )
164 # undef NEED_SAFE_REALLOC
165 # define NEED_SAFE_REALLOC   
166         int r=-1;
167         int buflen=BUFSTART;
168         *buf = NULL;   
169         for(;buflen<BUFMAX;) {
170                 if (safe_realloc( buf, buflen )==NULL)
171                         return r;
172                 r = gethostbyaddr_r( addr, len, type,
173                         resbuf, *buf, buflen, 
174                         result, herrno_ptr );
175 #ifdef NETDB_INTERNAL
176                 if ((r<0) &&
177                         (*herrno_ptr==NETDB_INTERNAL) &&
178                         (errno==ERANGE))
179                 {
180                         buflen*=2;
181                         continue;
182                 }
183 #endif
184                 return r;
185         }
186         return -1;
187 #elif defined( LDAP_INT_GETHOSTBYADDR_MUTEX )
188 # undef NEED_COPY_HOSTENT
189 # define NEED_COPY_HOSTENT   
190         struct hostent *he;
191         int     retval;
192         
193         ldap_pvt_thread_mutex_lock( &ldap_int_gethostbyaddr_mutex );
194         
195         he = gethostbyaddr( addr, len, type );
196         
197         if (he==NULL) {
198                 *herrno_ptr = h_errno;
199                 retval = -1;
200         } else if (copy_hostent( resbuf, buf, he )<0) {
201                 *herrno_ptr = -1;
202                 retval = -1;
203         } else {
204                 *result = resbuf;
205                 retval = 0;
206         }
207         
208         ldap_pvt_thread_mutex_unlock( &ldap_int_gethostbyaddr_mutex );
209         
210         return retval;   
211 #else /* gethostbyaddr() */
212         *result = gethostbyaddr( addr, len, type );
213
214         if (*result!=NULL) {
215                 return 0;
216         }
217         return -1;
218 #endif  
219 }
220 /* 
221  * ldap_pvt_init_utils() should be called before any other function.
222  */
223
224 void ldap_pvt_init_utils( void )
225 {
226         static int done=0;
227         if (done)
228           return;
229         done=1;
230 #if defined( LDAP_INT_CTIME_MUTEX )
231         ldap_pvt_thread_mutex_init( &ldap_int_ctime_mutex, NULL );
232 #endif  
233 #if defined( LDAP_INT_GETHOSTBYNAME_MUTEX )
234         ldap_pvt_thread_mutex_init( &ldap_int_gethostbyname_mutex, NULL );
235 #endif
236 #if defined( LDAP_INT_GETHOSTBYADDR_MUTEX )
237         ldap_pvt_thread_mutex_init( &ldap_int_gethostbyaddr_mutex, NULL );
238 #endif
239 #if defined( LDAP_R_COMPILE )
240         /* call other module init functions here... */
241 #endif  
242 }
243
244 #if defined( NEED_COPY_HOSTENT )
245 # undef NEED_SAFE_REALLOC
246 #define NEED_SAFE_REALLOC
247
248 static char *cpy_aliases( char ***tgtio, char *buf, char **src )
249 {
250         int len;
251         char **tgt=*tgtio;
252         for( ; (*src) ; src++ ) {
253                 len = strlen( *src ) + 1;
254                 memcpy( buf, *src, len );
255                 *tgt++=buf;
256                 buf+=len;
257         }
258         *tgtio=tgt;   
259         return buf;
260 }
261
262 static char *cpy_addresses( char ***tgtio, char *buf, char **src, int len )
263 {
264         char **tgt=*tgtio;
265         for( ; (*src) ; src++ ) {
266                 memcpy( buf, *src, len );
267                 *tgt++=buf;
268                 buf+=len;
269         }
270         *tgtio=tgt;      
271         return buf;
272 }
273
274 static int copy_hostent( struct hostent *res, char **buf, struct hostent * src )
275 {
276         char    **p;
277         char    **tp;
278         char    *tbuf;
279         int     name_len;
280         int     n_alias;
281         int     total_alias_len;
282         int     n_addr;
283         int     total_addr_len;
284         int     total_len;
285           
286         /* calculate the size needed for the buffer */
287         name_len = strlen( src->h_name ) + 1;
288         
289         for( n_alias=total_alias_len=0, p=src->h_aliases; (*p) ; p++ ) {
290                 total_alias_len += strlen( *p ) + 1;
291                 n_alias++;
292         }
293
294         for( n_addr=0, p=src->h_addr_list; (*p) ; p++ ) {
295                 n_addr++;
296         }
297         total_addr_len = n_addr * src->h_length;
298         
299         total_len = (n_alias + n_addr + 2) * sizeof( char * ) +
300                 total_addr_len + total_alias_len + name_len;
301         
302         if (safe_realloc( buf, total_len )) {                    
303                 tp = (char **) *buf;
304                 tbuf = *buf + (n_alias + n_addr + 2) * sizeof( char * );
305                 memcpy( res, src, sizeof( struct hostent ) );
306                 /* first the name... */
307                 memcpy( tbuf, src->h_name, name_len );
308                 res->h_name = tbuf; tbuf+=name_len;
309                 /* now the aliases */
310                 res->h_aliases = tp;
311                 tbuf = cpy_aliases( &tp, tbuf, src->h_aliases );
312                 *tp++=NULL;
313                 /* finally the addresses */
314                 res->h_addr_list = tp;
315                 tbuf = cpy_addresses( &tp, tbuf, src->h_addr_list, src->h_length );
316                 *tp++=NULL;
317                 return 0;
318         }
319         return -1;
320 }
321 #endif
322
323 #if defined( NEED_SAFE_REALLOC )
324 static char *safe_realloc( char **buf, int len )
325 {
326         char *tmpbuf;
327         tmpbuf = realloc( *buf, len );
328         if (tmpbuf) {
329                 *buf=tmpbuf;
330         } 
331         return tmpbuf;
332 }
333 #endif
334
335