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