]> git.sur5r.net Git - openldap/blob - libraries/liblber/options.c
allow to unregister (and free) memory handling functions
[openldap] / libraries / liblber / options.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2005 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 #include "portable.h"
17
18 #include <ac/stdlib.h>
19 #include <ac/string.h>
20 #include <ac/stdarg.h>
21 #include "lber-int.h"
22
23 char ber_pvt_opt_on;    /* used to get a non-NULL address for *_OPT_ON */
24
25 struct lber_options ber_int_options = {
26         LBER_UNINITIALIZED, 0, 0, 0 };
27
28 int
29 ber_get_option(
30         void    *item,
31         int             option,
32         void    *outvalue)
33 {
34         const BerElement *ber;
35         const Sockbuf *sb;
36
37         ber_int_options.lbo_valid = LBER_INITIALIZED;
38
39         if(outvalue == NULL) {
40                 /* no place to get to */
41                 ber_errno = LBER_ERROR_PARAM;
42                 return LBER_OPT_ERROR;
43         }
44
45         if(item == NULL) {
46                 switch ( option ) {
47                 case LBER_OPT_BER_DEBUG:
48                         * (int *) outvalue = ber_int_debug;
49                         return LBER_OPT_SUCCESS;
50
51                 case LBER_OPT_MEMORY_INUSE:
52                         /* The memory inuse is a global variable on kernal implementations.
53                          * This means that memory debug is shared by all LDAP processes
54                          * so for this variable to have much meaning, only one LDAP process
55                          * should be running and memory inuse should be initialized to zero
56                          * using the lber_set_option() function during startup.
57                          * The counter is not accurate for multithreaded ldap applications.
58                          */
59 #ifdef LDAP_MEMORY_DEBUG
60                         * (int *) outvalue = ber_int_options.lbo_meminuse;
61                         return LBER_OPT_SUCCESS;
62 #else
63                         return LBER_OPT_ERROR;
64 #endif
65                 case LBER_OPT_LOG_PRINT_FILE:
66                         *((FILE**)outvalue) = (FILE*)ber_pvt_err_file;
67                         return LBER_OPT_SUCCESS;
68                 }
69
70                 ber_errno = LBER_ERROR_PARAM;
71                 return LBER_OPT_ERROR;
72         }
73
74         ber = item;
75         sb = item;
76
77         switch(option) {
78         case LBER_OPT_BER_OPTIONS:
79                 assert( LBER_VALID( ber ) );
80                 * (int *) outvalue = ber->ber_options;
81                 return LBER_OPT_SUCCESS;
82
83         case LBER_OPT_BER_DEBUG:
84                 assert( LBER_VALID( ber ) );
85                 * (int *) outvalue = ber->ber_debug;
86                 return LBER_OPT_SUCCESS;
87
88         case LBER_OPT_BER_REMAINING_BYTES:
89                 assert( LBER_VALID( ber ) );
90                 *((ber_len_t *) outvalue) = ber_pvt_ber_remaining(ber);
91                 return LBER_OPT_SUCCESS;
92
93         case LBER_OPT_BER_TOTAL_BYTES:
94                 assert( LBER_VALID( ber ) );
95                 *((ber_len_t *) outvalue) = ber_pvt_ber_total(ber);
96                 return LBER_OPT_SUCCESS;
97
98         case LBER_OPT_BER_BYTES_TO_WRITE:
99                 assert( LBER_VALID( ber ) );
100                 *((ber_len_t *) outvalue) = ber_pvt_ber_write(ber);
101                 return LBER_OPT_SUCCESS;
102
103         case LBER_OPT_BER_MEMCTX:
104                 assert( LBER_VALID( ber ) );
105                 *((void **) outvalue) = ber->ber_memctx;
106                 return LBER_OPT_SUCCESS;
107         
108         default:
109                 /* bad param */
110                 ber_errno = LBER_ERROR_PARAM;
111                 break;
112         }
113
114         return LBER_OPT_ERROR;
115 }
116
117 int
118 ber_set_option(
119         void    *item,
120         int             option,
121         LDAP_CONST void *invalue)
122 {
123         BerElement *ber;
124         Sockbuf *sb;
125
126         if( (ber_int_options.lbo_valid == LBER_UNINITIALIZED)
127                 && ( ber_int_memory_fns == NULL )
128                 && ( option == LBER_OPT_MEMORY_FNS )
129                 && ( invalue != NULL ) )
130         {
131                 const BerMemoryFunctions *f =
132                         (const BerMemoryFunctions *) invalue;
133                 /* make sure all functions are provided */
134                 if(!( f->bmf_malloc && f->bmf_calloc
135                         && f->bmf_realloc && f->bmf_free ))
136                 {
137                         ber_errno = LBER_ERROR_PARAM;
138                         return LBER_OPT_ERROR;
139                 }
140
141                 ber_int_memory_fns = (BerMemoryFunctions *)
142                         (*(f->bmf_malloc))(sizeof(BerMemoryFunctions), NULL);
143
144                 if ( ber_int_memory_fns == NULL ) {
145                         ber_errno = LBER_ERROR_MEMORY;
146                         return LBER_OPT_ERROR;
147                 }
148
149                 AC_MEMCPY(ber_int_memory_fns, f, sizeof(BerMemoryFunctions));
150
151                 ber_int_options.lbo_valid = LBER_INITIALIZED;
152                 return LBER_OPT_SUCCESS;
153         }
154
155         if ( option == LBER_OPT_MEMORY_FNS ) {
156                 if ( ber_int_options.lbo_valid != LBER_INITIALIZED ) {
157                         return LBER_OPT_ERROR;
158                 }
159
160                 if ( invalue != NULL ) {
161                         return LBER_OPT_ERROR;
162                 }
163
164                 if ( ber_int_memory_fns == NULL ) {     
165                         return LBER_OPT_ERROR;
166                 }
167                         
168                 ber_int_memory_fns->bmf_free( ber_int_memory_fns, NULL );
169                 ber_int_memory_fns = NULL;
170                 ber_int_options.lbo_valid = LBER_UNINITIALIZED;
171                 return LBER_OPT_SUCCESS;
172         }
173
174         ber_int_options.lbo_valid = LBER_INITIALIZED;
175
176         if(invalue == NULL) {
177                 /* no place to set from */
178                 ber_errno = LBER_ERROR_PARAM;
179                 return LBER_OPT_ERROR;
180         }
181
182         if(item == NULL) {
183                 switch ( option ) {
184                 case LBER_OPT_BER_DEBUG:
185                         ber_int_debug = * (const int *) invalue;
186                         return LBER_OPT_SUCCESS;
187
188                 case LBER_OPT_LOG_PRINT_FN:
189                         ber_pvt_log_print = (BER_LOG_PRINT_FN) invalue;
190                         return LBER_OPT_SUCCESS;
191
192                 case LBER_OPT_LOG_PRINT_FILE:
193                         ber_pvt_err_file = (void *) invalue;
194                         return LBER_OPT_SUCCESS;
195
196                 case LBER_OPT_MEMORY_INUSE:
197                         /* The memory inuse is a global variable on kernal implementations.
198                          * This means that memory debug is shared by all LDAP processes
199                          * so for this variable to have much meaning, only one LDAP process
200                          * should be running and memory inuse should be initialized to zero
201                          * using the lber_set_option() function during startup.
202                          * The counter is not accurate for multithreaded applications.
203                          */
204 #ifdef LDAP_MEMORY_DEBUG
205                         ber_int_options.lbo_meminuse = * (int *) invalue;
206                         return LBER_OPT_SUCCESS;
207 #else
208                         return LBER_OPT_ERROR;
209 #endif
210                 case LBER_OPT_LOG_PROC:
211                         ber_int_log_proc = (BER_LOG_FN)invalue;
212                         return LBER_OPT_SUCCESS;
213                 }
214
215                 ber_errno = LBER_ERROR_PARAM;
216                 return LBER_OPT_ERROR;
217         }
218
219         ber = item;
220         sb = item;
221
222         switch(option) {
223         case LBER_OPT_BER_OPTIONS:
224                 assert( LBER_VALID( ber ) );
225                 ber->ber_options = * (const int *) invalue;
226                 return LBER_OPT_SUCCESS;
227
228         case LBER_OPT_BER_DEBUG:
229                 assert( LBER_VALID( ber ) );
230                 ber->ber_debug = * (const int *) invalue;
231                 return LBER_OPT_SUCCESS;
232
233         case LBER_OPT_BER_REMAINING_BYTES:
234                 assert( LBER_VALID( ber ) );
235                 ber->ber_end = &ber->ber_ptr[* (const ber_len_t *) invalue];
236                 return LBER_OPT_SUCCESS;
237
238         case LBER_OPT_BER_TOTAL_BYTES:
239                 assert( LBER_VALID( ber ) );
240                 ber->ber_end = &ber->ber_buf[* (const ber_len_t *) invalue];
241                 return LBER_OPT_SUCCESS;
242
243         case LBER_OPT_BER_BYTES_TO_WRITE:
244                 assert( LBER_VALID( ber ) );
245                 ber->ber_ptr = &ber->ber_buf[* (const ber_len_t *) invalue];
246                 return LBER_OPT_SUCCESS;
247
248         case LBER_OPT_BER_MEMCTX:
249                 assert( LBER_VALID( ber ) );
250                 ber->ber_memctx = *(void **)invalue;
251                 return LBER_OPT_SUCCESS;
252
253         default:
254                 /* bad param */
255                 ber_errno = LBER_ERROR_PARAM;
256                 break;
257         }
258
259         return LBER_OPT_ERROR;
260 }