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