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