-/*
- * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2002-2005 The OpenLDAP Foundation.
+ * Portions Copyright 1997,2002-2003 IBM Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
*/
-/*
- * (C) Copyright IBM Corp. 1997,2002
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is
- * given to IBM Corporation. This software is provided ``as is''
- * without express or implied warranty.
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by IBM Corporation for use in
+ * IBM products and subsequently ported to OpenLDAP Software by
+ * Steve Omrani. Additional significant contributors include:
+ * Luke Howard
*/
#include "portable.h"
-#include "slapi_common.h"
#include <ldap_pvt_thread.h>
#include <slap.h>
#include <slapi.h>
+#include <lutil.h>
/*
* Note: if ltdl.h is not available, slapi should not be compiled
*/
#include <ltdl.h>
-static int loadPlugin( Slapi_PBlock *, const char *, const char *, int,
+static int slapi_int_load_plugin( Slapi_PBlock *, const char *, const char *, int,
SLAPI_FUNC *, lt_dlhandle * );
/* pointer to link list of extended objects */
static ExtendedOp *pGExtendedOps = NULL;
+/* global plugins not associated with a specific backend */
+static Slapi_PBlock *pGPlugins = NULL;
/*********************************************************************
- * Function Name: newPlugin
+ * Function Name: plugin_pblock_new
*
* Description: This routine creates a new Slapi_PBlock structure,
* loads in the plugin module and executes the init
* Messages: None
*********************************************************************/
-Slapi_PBlock *
-newPlugin(
+static Slapi_PBlock *
+plugin_pblock_new(
int type,
- const char *path,
- const char *initfunc,
int argc,
char *argv[] )
{
Slapi_PBlock *pPlugin = NULL;
+ Slapi_PluginDesc *pPluginDesc = NULL;
lt_dlhandle hdLoadHandle;
int rc;
+ char **av2 = NULL, **ppPluginArgv;
+ char *path = argv[2];
+ char *initfunc = argv[3];
pPlugin = slapi_pblock_new();
if ( pPlugin == NULL ) {
}
rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_TYPE, (void *)type );
- if ( rc != LDAP_SUCCESS ) {
+ if ( rc != 0 ) {
goto done;
}
rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGC, (void *)argc );
- if ( rc != LDAP_SUCCESS ) {
+ if ( rc != 0 ) {
goto done;
}
- rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)argv );
- if ( rc != LDAP_SUCCESS ) {
+ av2 = ldap_charray_dup( argv );
+ if ( !av2 ) {
+ rc = LDAP_NO_MEMORY;
goto done;
}
- rc = loadPlugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle );
+ if ( argc > 0 ) {
+ ppPluginArgv = &av2[4];
+ } else {
+ ppPluginArgv = NULL;
+ }
+ rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv );
+ if ( rc != 0 ) {
+ goto done;
+ }
+
+ rc = slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 );
+ if ( rc != 0 ) {
+ goto done;
+ }
+
+ rc = slapi_int_load_plugin( pPlugin, path, initfunc, TRUE, NULL, &hdLoadHandle );
+ if ( rc != 0 ) {
+ goto done;
+ }
+
+ if ( slapi_pblock_get( pPlugin, SLAPI_PLUGIN_DESCRIPTION, (void **)&pPluginDesc ) == 0 &&
+ pPluginDesc != NULL ) {
+ slapi_log_error(SLAPI_LOG_TRACE, "plugin_pblock_new",
+ "Registered plugin %s %s [%s] (%s)\n",
+ pPluginDesc->spd_id,
+ pPluginDesc->spd_version,
+ pPluginDesc->spd_vendor,
+ pPluginDesc->spd_description);
+ }
done:
- if ( rc != LDAP_SUCCESS && pPlugin != NULL ) {
+ if ( rc != 0 && pPlugin != NULL ) {
slapi_pblock_destroy( pPlugin );
pPlugin = NULL;
+ if ( av2 ) {
+ ldap_charray_free( av2 );
+ }
}
return pPlugin;
}
/*********************************************************************
- * Function Name: insertPlugin
+ * Function Name: slapi_int_register_plugin
*
* Description: insert the slapi_pblock structure to the end of the plugin
* list
* Messages: None
*********************************************************************/
int
-insertPlugin(
+slapi_int_register_plugin(
Backend *be,
Slapi_PBlock *pPB )
{
Slapi_PBlock *pSavePB;
int rc = LDAP_SUCCESS;
- pTmpPB = (Slapi_PBlock *)(be->be_pb);
-
+ pTmpPB = ( be == NULL ) ? pGPlugins : (Slapi_PBlock *)(be->be_pb);
+
if ( pTmpPB == NULL ) {
- be->be_pb = (void *)pPB;
+ if ( be != NULL )
+ be->be_pb = (void *)pPB;
+ else
+ pGPlugins = pPB;
} else {
while ( pTmpPB != NULL && rc == LDAP_SUCCESS ) {
pSavePB = pTmpPB;
}
/*********************************************************************
- * Function Name: getAllPluginFuncs
+ * Function Name: slapi_int_get_plugins
*
* Description: get the desired type of function pointers defined
* in all the plugins
* Output: none
*
* Return Values: this routine returns a pointer to an array of function
- * pointers
+ * pointers containing backend-specific plugin functions
+ * followed by global plugin functions
*
* Messages: None
*********************************************************************/
int
-getAllPluginFuncs(
+slapi_int_get_plugins(
Backend *be,
int functype,
SLAPI_FUNC **ppFuncPtrs )
int numPB = 0;
int rc = LDAP_SUCCESS;
- assert( be );
assert( ppFuncPtrs );
- pCurrentPB = (Slapi_PBlock *)(be->be_pb);
-
- if ( pCurrentPB == NULL ) {
- /*
- * LDAP_OTHER is returned if no plugins are installed
- */
- rc = LDAP_OTHER;
+ /*
+ * First, count the plugins associated with a specific
+ * backend.
+ */
+ if ( be != NULL ) {
+ pCurrentPB = (Slapi_PBlock *)be->be_pb;
+
+ while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
+ rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
+ if ( rc == LDAP_SUCCESS ) {
+ if ( FuncPtr != NULL ) {
+ numPB++;
+ }
+ rc = slapi_pblock_get( pCurrentPB,
+ SLAPI_IBM_PBLOCK, &pCurrentPB );
+ }
+ }
+ }
+
+ if ( rc != LDAP_SUCCESS ) {
goto done;
}
- while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
+ /*
+ * Then, count the global plugins.
+ */
+ pCurrentPB = pGPlugins;
+
+ while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
if ( rc == LDAP_SUCCESS ) {
if ( FuncPtr != NULL ) {
goto done;
}
+ /*
+ * Now, build the function pointer array of backend-specific
+ * plugins followed by global plugins.
+ */
*ppFuncPtrs = pTmpFuncPtr =
(SLAPI_FUNC *)ch_malloc( ( numPB + 1 ) * sizeof(SLAPI_FUNC) );
if ( ppFuncPtrs == NULL ) {
goto done;
}
- pCurrentPB = (Slapi_PBlock *)(be->be_pb);
+ if ( be != NULL ) {
+ pCurrentPB = (Slapi_PBlock *)be->be_pb;
+
+ while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
+ rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
+ if ( rc == LDAP_SUCCESS ) {
+ if ( FuncPtr != NULL ) {
+ *pTmpFuncPtr = FuncPtr;
+ pTmpFuncPtr++;
+ }
+ rc = slapi_pblock_get( pCurrentPB,
+ SLAPI_IBM_PBLOCK, &pCurrentPB );
+ }
+ }
+ }
+
+ pCurrentPB = pGPlugins;
+
while ( pCurrentPB != NULL && rc == LDAP_SUCCESS ) {
rc = slapi_pblock_get( pCurrentPB, functype, &FuncPtr );
if ( rc == LDAP_SUCCESS ) {
return rc;
}
-
+
/*********************************************************************
* Function Name: createExtendedOp
*
/*********************************************************************
- * Function Name: removeExtendedOp
+ * Function Name: slapi_int_unregister_extop
*
* Description: This routine removes the ExtendedOp structures
* asscoiated with a particular extended operation
* Messages: None
*********************************************************************/
void
-removeExtendedOp(
+slapi_int_unregister_extop(
Backend *pBE,
ExtendedOp **opList,
Slapi_PBlock *pPB )
/*********************************************************************
- * Function Name: newExtendedOp
+ * Function Name: slapi_int_register_extop
*
* Description: This routine creates a new ExtendedOp structure, loads
* in the extended op module and put the extended op function address
* Messages: None
*********************************************************************/
int
-newExtendedOp(
+slapi_int_register_extop(
Backend *pBE,
ExtendedOp **opList,
Slapi_PBlock *pPB )
}
rc = slapi_pblock_get( pPB,SLAPI_PLUGIN_EXT_OP_OIDLIST, &pTmpOIDs );
- if ( rc != LDAP_SUCCESS ) {
+ if ( rc != 0 ) {
rc = LDAP_OTHER;
goto error_return;
}
}
/*********************************************************************
- * Function Name: getPluginFunc
+ * Function Name: slapi_int_get_extop_plugin
*
* Description: This routine gets the function address for a given function
* name.
* Messages: None
*********************************************************************/
int
-getPluginFunc(
+slapi_int_get_extop_plugin(
struct berval *reqoid,
SLAPI_FUNC *pFuncAddr )
{
}
/***************************************************************************
- * This function is similar to getPluginFunc above. except it returns one OID
+ * This function is similar to slapi_int_get_extop_plugin above. except it returns one OID
* per call. It is called from root_dse_info (root_dse.c).
* The function is a modified version of get_supported_extop (file extended.c).
***************************************************************************/
struct berval *
-ns_get_supported_extop( int index )
+slapi_int_get_supported_extop( int index )
{
ExtendedOp *ext;
}
/*********************************************************************
- * Function Name: loadPlugin
+ * Function Name: slapi_int_load_plugin
*
* Description: This routine loads the specified DLL, gets and executes the init function
* if requested.
*********************************************************************/
static int
-loadPlugin(
+slapi_int_load_plugin(
Slapi_PBlock *pPlugin,
const char *path,
const char *initfunc,
return rc;
}
-
+/*
+ * Special support for computed attribute plugins
+ */
int
-doPluginFNs(
+slapi_int_call_plugins(
Backend *be,
int funcType,
Slapi_PBlock *pPB )
{
- int rc = LDAP_SUCCESS;
+ int rc = 0;
SLAPI_FUNC *pGetPlugin = NULL, *tmpPlugin = NULL;
- rc = getAllPluginFuncs(be, funcType, &tmpPlugin );
+ if ( pPB == NULL ) {
+ return 1;
+ }
+
+ rc = slapi_int_get_plugins( be, funcType, &tmpPlugin );
if ( rc != LDAP_SUCCESS || tmpPlugin == NULL ) {
- return rc;
+ /* Nothing to do, front-end should ignore. */
+ return 1;
}
for ( pGetPlugin = tmpPlugin ; *pGetPlugin != NULL; pGetPlugin++ ) {
/*
- * FIXME: operation stops at first non-success
- *
* FIXME: we should provide here a sort of sandbox,
* to protect from plugin faults; e.g. trap signals
* and longjump here, marking the plugin as unsafe for
*/
rc = (*pGetPlugin)(pPB);
- if ( rc != LDAP_SUCCESS ) {
+ /*
+ * Only non-postoperation plugins abort processing on
+ * failure (confirmed with SLAPI specification).
+ */
+ if ( !SLAPI_PLUGIN_IS_POST_FN( funcType ) && rc != 0 ) {
+ /*
+ * Plugins generally return negative error codes
+ * to indicate failure, although in the case of
+ * bind plugins they may return SLAPI_BIND_xxx
+ */
break;
}
}
- ch_free( tmpPlugin );
+ slapi_ch_free( (void **)&tmpPlugin );
return rc;
}
int
-netscape_plugin(
+slapi_int_read_config(
Backend *be,
const char *fname,
int lineno,
{
int iType = -1;
int numPluginArgc = 0;
- char **ppPluginArgv = NULL;
if ( argc < 4 ) {
fprintf( stderr,
iType = SLAPI_PLUGIN_POSTOPERATION;
} else if ( strcasecmp( argv[1], "extendedop" ) == 0 ) {
iType = SLAPI_PLUGIN_EXTENDEDOP;
+ } else if ( strcasecmp( argv[1], "object" ) == 0 ) {
+ iType = SLAPI_PLUGIN_OBJECT;
} else {
fprintf( stderr, "%s: line %d: invalid plugin type \"%s\".\n",
fname, lineno, argv[1] );
}
numPluginArgc = argc - 4;
- if ( numPluginArgc > 0 ) {
- ppPluginArgv = &argv[4];
- } else {
- ppPluginArgv = NULL;
- }
if ( iType == SLAPI_PLUGIN_PREOPERATION ||
iType == SLAPI_PLUGIN_EXTENDEDOP ||
- iType == SLAPI_PLUGIN_POSTOPERATION ) {
+ iType == SLAPI_PLUGIN_POSTOPERATION ||
+ iType == SLAPI_PLUGIN_OBJECT ) {
int rc;
Slapi_PBlock *pPlugin;
- pPlugin = newPlugin( iType, argv[2], argv[3],
- numPluginArgc, ppPluginArgv );
+ pPlugin = plugin_pblock_new( iType, numPluginArgc, argv );
if (pPlugin == NULL) {
return 1;
}
if (iType == SLAPI_PLUGIN_EXTENDEDOP) {
- rc = newExtendedOp(be, &pGExtendedOps, pPlugin);
+ rc = slapi_int_register_extop(be, &pGExtendedOps, pPlugin);
if ( rc != LDAP_SUCCESS ) {
slapi_pblock_destroy( pPlugin );
return 1;
}
}
- rc = insertPlugin( be, pPlugin );
+ rc = slapi_int_register_plugin( be, pPlugin );
if ( rc != LDAP_SUCCESS ) {
if ( iType == SLAPI_PLUGIN_EXTENDEDOP ) {
- removeExtendedOp( be, &pGExtendedOps, pPlugin );
+ slapi_int_unregister_extop( be, &pGExtendedOps, pPlugin );
}
slapi_pblock_destroy( pPlugin );
return 1;
return 0;
}
+void
+slapi_int_plugin_unparse(
+ Backend *be,
+ BerVarray *out
+)
+{
+ Slapi_PBlock *pp;
+ int i, j, rc;
+ char **argv, ibuf[32], *ptr;
+ struct berval idx, bv;
+
+ *out = NULL;
+ idx.bv_val = ibuf;
+ i = 0;
+ for ( pp=be->be_pb; pp; slapi_pblock_get( pp, SLAPI_IBM_PBLOCK, &pp ) ) {
+ slapi_pblock_get( pp, SLAPI_X_CONFIG_ARGV, &argv );
+ idx.bv_len = sprintf( idx.bv_val, "{%d}", i );
+ bv.bv_len = idx.bv_len;
+ for (j=1; argv[j]; j++) {
+ bv.bv_len += strlen(argv[j]);
+ if ( j ) bv.bv_len++;
+ }
+ bv.bv_val = ch_malloc( bv.bv_len + 1 );
+ ptr = lutil_strcopy( bv.bv_val, ibuf );
+ for (j=1; argv[j]; j++) {
+ if ( j ) *ptr++ = ' ';
+ ptr = lutil_strcopy( ptr, argv[j] );
+ }
+ ber_bvarray_add( out, &bv );
+ }
+}
+
int
-slapi_init(void)
+slapi_int_initialize(void)
{
if ( ldap_pvt_thread_mutex_init( &slapi_hn_mutex ) ) {
return -1;
return -1;
}
+ if ( slapi_int_init_object_extensions() != 0 ) {
+ return -1;
+ }
+
return 0;
}