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