]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/plugin.c
However, SLAPI_PLUGIN_VERSION is treated as an opaque type
[openldap] / servers / slapd / slapi / plugin.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2002-2005 The OpenLDAP Foundation.
5  * Portions Copyright 1997,2002-2003 IBM Corporation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by IBM Corporation for use in
18  * IBM products and subsequently ported to OpenLDAP Software by
19  * Steve Omrani.  Additional significant contributors include:
20  *    Luke Howard
21  */
22
23 #include "portable.h"
24 #include <ldap_pvt_thread.h>
25 #include <slap.h>
26 #include <slapi.h>
27 #include <lutil.h>
28
29 /*
30  * Note: if ltdl.h is not available, slapi should not be compiled
31  */
32 #include <ltdl.h>
33
34 static int slapi_int_load_plugin( Slapi_PBlock *, const char *, const char *, int, 
35         SLAPI_FUNC *, lt_dlhandle * );
36
37 /* pointer to link list of extended objects */
38 static ExtendedOp *pGExtendedOps = NULL;
39
40 /*********************************************************************
41  * Function Name:      plugin_pblock_new
42  *
43  * Description:        This routine creates a new Slapi_PBlock structure,
44  *                     loads in the plugin module and executes the init
45  *                     function provided by the module.
46  *
47  * Input:              type - type of the plugin, such as SASL, database, etc.
48  *                     path - the loadpath to load the module in
49  *                     initfunc - name of the plugin function to execute first
50  *                     argc - number of arguements
51  *                     argv[] - an array of char pointers point to
52  *                              the arguments passed in via
53  *                              the configuration file.
54  *
55  * Output:             
56  *
57  * Return Values:      a pointer to a newly created Slapi_PBlock structrue or
58  *                     NULL - function failed 
59  *
60  * Messages:           None
61  *********************************************************************/
62
63 static Slapi_PBlock *
64 plugin_pblock_new(
65         int type, 
66         int argc, 
67         char *argv[] ) 
68 {
69         Slapi_PBlock    *pPlugin = NULL; 
70         Slapi_PluginDesc *pPluginDesc = NULL;
71         lt_dlhandle     hdLoadHandle;
72         int             rc;
73         char **av2 = NULL, **ppPluginArgv;
74         char *path = argv[2];
75         char *initfunc = argv[3];
76
77         pPlugin = slapi_pblock_new();
78         if ( pPlugin == NULL ) {
79                 rc = LDAP_NO_MEMORY;
80                 goto done;
81         }
82
83         slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)&type );
84         slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)&argc );
85
86         av2 = ldap_charray_dup( argv );
87         if ( av2 == NULL ) {
88                 rc = LDAP_NO_MEMORY;
89                 goto done;
90         }
91
92         if ( argc > 0 ) {
93                 ppPluginArgv = &av2[4];
94         } else {
95                 ppPluginArgv = NULL;
96         }
97
98         slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv );
99         slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 );
100
101         rc = slapi_int_load_plugin( pPlugin, path, initfunc, 1, NULL, &hdLoadHandle );
102         if ( rc != 0 ) {
103                 goto done;
104         }
105
106         if ( slapi_pblock_get( pPlugin, SLAPI_PLUGIN_DESCRIPTION, (void **)&pPluginDesc ) == 0 &&
107              pPluginDesc != NULL ) {
108                 slapi_log_error(SLAPI_LOG_TRACE, "plugin_pblock_new",
109                                 "Registered plugin %s %s [%s] (%s)\n",
110                                 pPluginDesc->spd_id,
111                                 pPluginDesc->spd_version,
112                                 pPluginDesc->spd_vendor,
113                                 pPluginDesc->spd_description);
114         }
115
116 done:
117         if ( rc != 0 && pPlugin != NULL ) {
118                 slapi_pblock_destroy( pPlugin );
119                 pPlugin = NULL;
120                 if ( av2 != NULL ) {
121                         ldap_charray_free( av2 );
122                 }
123         }
124
125         return pPlugin;
126
127
128 /*********************************************************************
129  * Function Name:      slapi_int_register_plugin
130  *
131  * Description:        insert the slapi_pblock structure to the end of the plugin
132  *                     list 
133  *
134  * Input:              a pointer to a plugin slapi_pblock structure to be added to 
135  *                     the list
136  *
137  * Output:             none
138  *
139  * Return Values:      LDAP_SUCCESS - successfully inserted.
140  *                     LDAP_LOCAL_ERROR.
141  *
142  * Messages:           None
143  *********************************************************************/
144 int 
145 slapi_int_register_plugin(
146         Backend *be, 
147         Slapi_PBlock *pPB )
148
149         Slapi_PBlock *pTmpPB;
150         Slapi_PBlock *pSavePB;
151         int    rc = LDAP_SUCCESS;
152
153         assert( be != NULL );
154
155         pTmpPB = SLAPI_BACKEND_PBLOCK( be );
156         if ( pTmpPB == NULL ) {
157                 SLAPI_BACKEND_PBLOCK( be ) = pPB;
158         } else {
159                 while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) {
160                         pSavePB = pTmpPB;
161                         rc = slapi_pblock_get( pTmpPB, SLAPI_IBM_PBLOCK, &pTmpPB );
162                 }
163
164                 if ( rc == LDAP_SUCCESS ) { 
165                         rc = slapi_pblock_set( pSavePB, SLAPI_IBM_PBLOCK, (void *)pPB ); 
166                 }
167         }
168      
169         return ( rc != LDAP_SUCCESS ) ? LDAP_OTHER : LDAP_SUCCESS;
170 }
171        
172 /*********************************************************************
173  * Function Name:      slapi_int_get_plugins
174  *
175  * Description:        get the desired type of function pointers defined 
176  *                     in all the plugins 
177  *
178  * Input:              the type of the functions to get, such as pre-operation,etc.
179  *
180  * Output:             none
181  *
182  * Return Values:      this routine returns a pointer to an array of function
183  *                     pointers containing backend-specific plugin functions
184  *                     followed by global plugin functions
185  *
186  * Messages:           None
187  *********************************************************************/
188 int 
189 slapi_int_get_plugins(
190         Backend *be,            
191         int functype, 
192         SLAPI_FUNC **ppFuncPtrs )
193 {
194  
195         Slapi_PBlock    *pCurrentPB; 
196         SLAPI_FUNC      FuncPtr;
197         SLAPI_FUNC      *pTmpFuncPtr;
198         int             numPB = 0;
199         int             rc = LDAP_SUCCESS;
200
201         assert( ppFuncPtrs != NULL );
202
203         if ( be == NULL ) {
204                 goto done;
205         }
206
207         pCurrentPB = SLAPI_BACKEND_PBLOCK( be );
208
209         while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
210                 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
211                 if ( rc == LDAP_SUCCESS ) {
212                         if ( FuncPtr != NULL )  {
213                                 numPB++;
214                         }
215                         rc = slapi_pblock_get( pCurrentPB,
216                                 SLAPI_IBM_PBLOCK, &pCurrentPB );
217                 }
218         }
219
220         if ( numPB == 0 ) {
221                 *ppFuncPtrs = NULL;
222                 rc = LDAP_SUCCESS;
223                 goto done;
224         }
225
226         /*
227          * Now, build the function pointer array of backend-specific
228          * plugins followed by global plugins.
229          */
230         *ppFuncPtrs = pTmpFuncPtr = 
231                 (SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) ); 
232         if ( ppFuncPtrs == NULL ) {
233                 rc = LDAP_NO_MEMORY;
234                 goto done;
235         }
236
237         pCurrentPB = SLAPI_BACKEND_PBLOCK( be );
238
239         while ( pCurrentPB != NULL && rc == LDAP_SUCCESS )  {
240                 rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
241                 if ( rc == LDAP_SUCCESS ) {
242                         if ( FuncPtr != NULL )  {
243                                 *pTmpFuncPtr = FuncPtr;
244                                 pTmpFuncPtr++;
245                         } 
246                         rc = slapi_pblock_get( pCurrentPB,
247                                         SLAPI_IBM_PBLOCK, &pCurrentPB );
248                 }
249         }
250
251         *pTmpFuncPtr = NULL;
252
253
254 done:
255         if ( rc != LDAP_SUCCESS && *ppFuncPtrs != NULL ) {
256                 ch_free( *ppFuncPtrs );
257                 *ppFuncPtrs = NULL;
258         }
259
260         return rc;
261 }
262
263 /*********************************************************************
264  * Function Name:      createExtendedOp
265  *
266  * Description: Creates an extended operation structure and
267  *              initializes the fields
268  *
269  * Return value: A newly allocated structure or NULL
270  ********************************************************************/
271 ExtendedOp *
272 createExtendedOp()
273 {
274         ExtendedOp *ret;
275
276         ret = (ExtendedOp *)ch_malloc(sizeof(ExtendedOp));
277         if ( ret != NULL ) {
278                 ret->ext_oid.bv_val = NULL;
279                 ret->ext_oid.bv_len = 0;
280                 ret->ext_func = NULL;
281                 ret->ext_be = NULL;
282                 ret->ext_next = NULL;
283         }
284
285         return ret;
286 }
287
288
289 /*********************************************************************
290  * Function Name:      slapi_int_unregister_extop
291  *
292  * Description:        This routine removes the ExtendedOp structures 
293  *                                         asscoiated with a particular extended operation 
294  *                                         plugin.
295  *
296  * Input:              pBE - pointer to a backend structure
297  *                     opList - pointer to a linked list of extended
298  *                              operation structures
299  *                     pPB - pointer to a slapi parameter block
300  *
301  * Output:
302  *
303  * Return Value:       none
304  *
305  * Messages:           None
306  *********************************************************************/
307 void
308 slapi_int_unregister_extop(
309         Backend *pBE, 
310         ExtendedOp **opList, 
311         Slapi_PBlock *pPB )
312 {
313         ExtendedOp      *pTmpExtOp, *backExtOp;
314         char            **pTmpOIDs;
315         int             i;
316
317 #if 0
318         assert( pBE != NULL); /* unused */
319 #endif /* 0 */
320         assert( opList != NULL );
321         assert( pPB != NULL );
322
323         if ( *opList == NULL ) {
324                 return;
325         }
326
327         slapi_pblock_get( pPB, SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
328         if ( pTmpOIDs == NULL ) {
329                 return;
330         }
331
332         for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
333                 backExtOp = NULL;
334                 pTmpExtOp = *opList;
335                 for ( ; pTmpExtOp != NULL; pTmpExtOp = pTmpExtOp->ext_next) {
336                         int     rc;
337                         rc = strcasecmp( pTmpExtOp->ext_oid.bv_val,
338                                         pTmpOIDs[ i ] );
339                         if ( rc == 0 ) {
340                                 if ( backExtOp == NULL ) {
341                                         *opList = pTmpExtOp->ext_next;
342                                 } else {
343                                         backExtOp->ext_next
344                                                 = pTmpExtOp->ext_next;
345                                 }
346
347                                 ch_free( pTmpExtOp );
348                                 break;
349                         }
350                         backExtOp = pTmpExtOp;
351                 }
352         }
353 }
354
355
356 /*********************************************************************
357  * Function Name:      slapi_int_register_extop
358  *
359  * Description:        This routine creates a new ExtendedOp structure, loads
360  *                     in the extended op module and put the extended op function address
361  *                     in the structure. The function will not be executed in
362  *                     this routine.
363  *
364  * Input:              pBE - pointer to a backend structure
365  *                     opList - pointer to a linked list of extended
366  *                              operation structures
367  *                     pPB - pointer to a slapi parameter block
368  *
369  * Output:
370  *
371  * Return Value:       an LDAP return code
372  *
373  * Messages:           None
374  *********************************************************************/
375 int 
376 slapi_int_register_extop(
377         Backend *pBE,   
378         ExtendedOp **opList, 
379         Slapi_PBlock *pPB )
380 {
381         ExtendedOp      *pTmpExtOp = NULL;
382         SLAPI_FUNC      tmpFunc;
383         char            **pTmpOIDs;
384         int             rc = LDAP_OTHER;
385         int             i;
386
387         if ( (*opList) == NULL ) { 
388                 *opList = createExtendedOp();
389                 if ( (*opList) == NULL ) {
390                         rc = LDAP_NO_MEMORY;
391                         goto error_return;
392                 }
393                 pTmpExtOp = *opList;
394                 
395         } else {                        /* Find the end of the list */
396                 for ( pTmpExtOp = *opList; pTmpExtOp->ext_next != NULL;
397                                 pTmpExtOp = pTmpExtOp->ext_next )
398                         ; /* EMPTY */
399                 pTmpExtOp->ext_next = createExtendedOp();
400                 if ( pTmpExtOp->ext_next == NULL ) {
401                         rc = LDAP_NO_MEMORY;
402                         goto error_return;
403                 }
404                 pTmpExtOp = pTmpExtOp->ext_next;
405         }
406
407         rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
408         if ( rc != 0 ) {
409                 rc = LDAP_OTHER;
410                 goto error_return;
411         }
412
413         rc = slapi_pblock_get(pPB,SLAPI_PLUGIN_EXT_OP_FN, &tmpFunc);
414         if ( rc != 0 ) {
415                 rc = LDAP_OTHER;
416                 goto error_return;
417         }
418
419         if ( (pTmpOIDs == NULL) || (tmpFunc == NULL) ) {
420                 rc = LDAP_OTHER;
421                 goto error_return;
422         }
423
424         for ( i = 0; pTmpOIDs[i] != NULL; i++ ) {
425                 pTmpExtOp->ext_oid.bv_val = pTmpOIDs[i];
426                 pTmpExtOp->ext_oid.bv_len = strlen( pTmpOIDs[i] );
427                 pTmpExtOp->ext_func = tmpFunc;
428                 pTmpExtOp->ext_be = pBE;
429                 if ( pTmpOIDs[i + 1] != NULL ) {
430                         pTmpExtOp->ext_next = createExtendedOp();
431                         if ( pTmpExtOp->ext_next == NULL ) {
432                                 rc = LDAP_NO_MEMORY;
433                                 break;
434                         }
435                         pTmpExtOp = pTmpExtOp->ext_next;
436                 }
437         }
438
439 error_return:
440         return rc;
441 }
442
443 /*********************************************************************
444  * Function Name:      slapi_int_get_extop_plugin
445  *
446  * Description:        This routine gets the function address for a given function
447  *                     name.
448  *
449  * Input:
450  *                     funcName - name of the extended op function, ie. an OID.
451  *
452  * Output:             pFuncAddr - the function address of the requested function name.
453  *
454  * Return Values:      a pointer to a newly created ExtendOp structrue or
455  *                     NULL - function failed
456  *
457  * Messages:           None
458  *********************************************************************/
459 int 
460 slapi_int_get_extop_plugin(
461         struct berval *reqoid,          
462         SLAPI_FUNC *pFuncAddr ) 
463 {
464         ExtendedOp      *pTmpExtOp;
465
466         assert( reqoid != NULL );
467         assert( pFuncAddr != NULL );
468
469         *pFuncAddr = NULL;
470
471         if ( pGExtendedOps == NULL ) {
472                 return LDAP_OTHER;
473         }
474
475         pTmpExtOp = pGExtendedOps;
476         while ( pTmpExtOp != NULL ) {
477                 int     rc;
478                 
479                 rc = strcasecmp( reqoid->bv_val, pTmpExtOp->ext_oid.bv_val );
480                 if ( rc == 0 ) {
481                         *pFuncAddr = pTmpExtOp->ext_func;
482                         break;
483                 }
484                 pTmpExtOp = pTmpExtOp->ext_next;
485         }
486
487         return ( *pFuncAddr == NULL ? 1 : 0 );
488 }
489
490 /***************************************************************************
491  * This function is similar to slapi_int_get_extop_plugin above. except it returns one OID
492  * per call. It is called from root_dse_info (root_dse.c).
493  * The function is a modified version of get_supported_extop (file extended.c).
494  ***************************************************************************/
495 struct berval *
496 slapi_int_get_supported_extop( int index )
497 {
498         ExtendedOp      *ext;
499
500         for ( ext = pGExtendedOps ; ext != NULL && --index >= 0;
501                         ext = ext->ext_next) {
502                 ; /* empty */
503         }
504
505         if ( ext == NULL ) {
506                 return NULL;
507         }
508
509         return &ext->ext_oid ;
510 }
511
512 /*********************************************************************
513  * Function Name:      slapi_int_load_plugin
514  *
515  * Description:        This routine loads the specified DLL, gets and executes the init function
516  *                     if requested.
517  *
518  * Input:
519  *                     pPlugin - a pointer to a Slapi_PBlock struct which will be passed to
520  *                               the DLL init function.
521  *                     path - path name of the DLL to be load.
522  *                     initfunc - either the DLL initialization function or an OID of the
523  *                                loaded extended operation.
524  *                     doInit - if it is TRUE, execute the init function, otherwise, save the
525  *                              function address but not execute it.
526  *
527  * Output:             pInitFunc - the function address of the loaded function. This param
528  *                                 should be not be null if doInit is FALSE.
529  *                     pLdHandle - handle returned by lt_dlopen()
530  *
531  * Return Values:      LDAP_SUCCESS, LDAP_LOCAL_ERROR
532  *
533  * Messages:           None
534  *********************************************************************/
535
536 static int 
537 slapi_int_load_plugin(
538         Slapi_PBlock    *pPlugin,
539         const char      *path,
540         const char      *initfunc, 
541         int             doInit,
542         SLAPI_FUNC      *pInitFunc,
543         lt_dlhandle     *pLdHandle ) 
544 {
545         int             rc = LDAP_SUCCESS;
546         SLAPI_FUNC      fpInitFunc = NULL;
547
548         assert( pLdHandle != NULL );
549
550         if ( lt_dlinit() ) {
551                 return LDAP_LOCAL_ERROR;
552         }
553
554         /* load in the module */
555         *pLdHandle = lt_dlopen( path );
556         if ( *pLdHandle == NULL ) {
557                 return LDAP_LOCAL_ERROR;
558         }
559
560         fpInitFunc = (SLAPI_FUNC)lt_dlsym( *pLdHandle, initfunc );
561         if ( fpInitFunc == NULL ) {
562                 lt_dlclose( *pLdHandle );
563                 return LDAP_LOCAL_ERROR;
564         }
565
566         if ( doInit ) {
567                 rc = ( *fpInitFunc )( pPlugin );
568                 if ( rc != LDAP_SUCCESS ) {
569                         lt_dlclose( *pLdHandle );
570                 }
571
572         } else {
573                 *pInitFunc = fpInitFunc;
574         }
575
576         return rc;
577 }
578
579 /*
580  * Special support for computed attribute plugins
581  */
582 int 
583 slapi_int_call_plugins(
584         Backend         *be,    
585         int             funcType, 
586         Slapi_PBlock    *pPB )
587 {
588
589         int rc = 0;
590         SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL; 
591
592         if ( pPB == NULL ) {
593                 return 1;
594         }
595
596         rc = slapi_int_get_plugins( be, funcType, &tmpPlugin );
597         if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
598                 /* Nothing to do, front-end should ignore. */
599                 return 1;
600         }
601
602         for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) {
603                 /*
604                  * FIXME: we should provide here a sort of sandbox,
605                  * to protect from plugin faults; e.g. trap signals
606                  * and longjump here, marking the plugin as unsafe for
607                  * later executions ...
608                  */
609                 rc = (*pGetPlugin)(pPB);
610
611                 /*
612                  * Only non-postoperation plugins abort processing on
613                  * failure (confirmed with SLAPI specification).
614                  */
615                 if ( !SLAPI_PLUGIN_IS_POST_FN( funcType ) && rc != 0 ) {
616                         /*
617                          * Plugins generally return negative error codes
618                          * to indicate failure, although in the case of
619                          * bind plugins they may return SLAPI_BIND_xxx
620                          */
621                         break;
622                 }
623         }
624
625         slapi_ch_free( (void **)&tmpPlugin );
626
627         return rc;
628 }
629
630 int
631 slapi_int_read_config(
632         Backend         *be,            
633         const char      *fname, 
634         int             lineno, 
635         int             argc, 
636         char            **argv )
637 {
638         int             iType = -1;
639         int             numPluginArgc = 0;
640
641         if ( argc < 4 ) {
642                 fprintf( stderr,
643                         "%s: line %d: missing arguments "
644                         "in \"plugin <plugin_type> <lib_path> "
645                         "<init_function> [<arguments>]\" line\n",
646                         fname, lineno );
647                 return 1;
648         }
649
650         /* automatically instantiate overlay if necessary */
651         if ( !overlay_is_inst( be, SLAPI_OVERLAY_NAME ) ) {
652                 if ( overlay_config( be, SLAPI_OVERLAY_NAME ) != 0 ) {
653                         fprintf( stderr, "Failed to instantiate SLAPI overlay\n");
654                         return -1;
655                 }
656         }
657         
658         if ( strcasecmp( argv[1], "preoperation" ) == 0 ) {
659                 iType = SLAPI_PLUGIN_PREOPERATION;
660         } else if ( strcasecmp( argv[1], "postoperation" ) == 0 ) {
661                 iType = SLAPI_PLUGIN_POSTOPERATION;
662         } else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
663                 iType = SLAPI_PLUGIN_EXTENDEDOP;
664         } else if ( strcasecmp( argv[1], "object" ) == 0 ) {
665                 iType = SLAPI_PLUGIN_OBJECT;
666         } else {
667                 fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
668                                 fname, lineno, argv[1] );
669                 return 1;
670         }
671         
672         numPluginArgc = argc - 4;
673
674         if ( iType == SLAPI_PLUGIN_PREOPERATION ||
675                         iType == SLAPI_PLUGIN_EXTENDEDOP ||
676                         iType == SLAPI_PLUGIN_POSTOPERATION ||
677                         iType == SLAPI_PLUGIN_OBJECT ) {
678                 int rc;
679                 Slapi_PBlock *pPlugin;
680
681                 pPlugin = plugin_pblock_new( iType, numPluginArgc, argv );
682                 if (pPlugin == NULL) {
683                         return 1;
684                 }
685
686                 if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
687                         rc = slapi_int_register_extop(be, &pGExtendedOps, pPlugin);
688                         if ( rc != LDAP_SUCCESS ) {
689                                 slapi_pblock_destroy( pPlugin );
690                                 return 1;
691                         }
692                 }
693
694                 rc = slapi_int_register_plugin( be, pPlugin );
695                 if ( rc != LDAP_SUCCESS ) {
696                         if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
697                                 slapi_int_unregister_extop( be, &pGExtendedOps, pPlugin );
698                         }
699                         slapi_pblock_destroy( pPlugin );
700                         return 1;
701                 }
702         }
703
704         return 0;
705 }
706
707 void
708 slapi_int_plugin_unparse(
709         Backend *be,
710         BerVarray *out
711 )
712 {
713         Slapi_PBlock *pp;
714         int i, j;
715         char **argv, ibuf[32], *ptr;
716         struct berval idx, bv;
717
718         *out = NULL;
719         idx.bv_val = ibuf;
720         i = 0;
721
722         for ( pp = SLAPI_BACKEND_PBLOCK( be );
723               pp != NULL;
724               slapi_pblock_get( pp, SLAPI_IBM_PBLOCK, &pp ) )
725         {
726                 slapi_pblock_get( pp, SLAPI_X_CONFIG_ARGV, &argv );
727                 if ( argv == NULL ) /* could be dynamic plugin */
728                         continue;
729                 idx.bv_len = sprintf( idx.bv_val, "{%d}", i );
730                 bv.bv_len = idx.bv_len;
731                 for (j=1; argv[j]; j++) {
732                         bv.bv_len += strlen(argv[j]);
733                         if ( j ) bv.bv_len++;
734                 }
735                 bv.bv_val = ch_malloc( bv.bv_len + 1 );
736                 ptr = lutil_strcopy( bv.bv_val, ibuf );
737                 for (j=1; argv[j]; j++) {
738                         if ( j ) *ptr++ = ' ';
739                         ptr = lutil_strcopy( ptr, argv[j] );
740                 }
741                 ber_bvarray_add( out, &bv );
742         }
743 }
744
745 int
746 slapi_int_initialize(void)
747 {
748         if ( ldap_pvt_thread_mutex_init( &slapi_hn_mutex ) ) {
749                 return -1;
750         }
751         
752         if ( ldap_pvt_thread_mutex_init( &slapi_time_mutex ) ) {
753                 return -1;
754         }
755
756         if ( ldap_pvt_thread_mutex_init( &slapi_printmessage_mutex ) ) {
757                 return -1;
758         }
759
760         slapi_log_file = ch_strdup( LDAP_RUNDIR LDAP_DIRSEP "errors" );
761         if ( slapi_log_file == NULL ) {
762                 return -1;
763         }
764
765         if ( slapi_int_init_object_extensions() != 0 ) {
766                 return -1;
767         }
768
769         return slapi_int_overlay_init();
770 }