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