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