From 216049bd12861357e0bf080fe10816103c3c3bda Mon Sep 17 00:00:00 2001
From: Kurt Zeilenga <kurt@openldap.org>
Date: Fri, 5 Feb 1999 09:03:47 +0000
Subject: [PATCH] New Frontend->Backend Interface Separates per backend type
 from per backend database initialization 	and startup.  Also supports
 per type / per backend shutdown. New frontend startup/shutdown routines are
 also provided: 	slap_init() slap_startup() slap_shutdown()
 slap_destroy() New frontend->backend startup/shutdown is managed by: 
 backend_init() backend_startup() backend_shutdown backend_destroy
 backend_init() now calls bi_init() to initial all function pointers for the
 backend (excepting bi_init() which is now the only hardcoded entry point). 
 New entry points are detailed in slap.h struct backend_info.  backend_info is
 a per database type structure. Besides the new startup/shutdown entry points,
 the new interface also supports per backend type configuration options.  One
 could have:

	backend bdb2	(new Berkeley DB 2 backend)
	bdb2_home	/directory

	database bdb2
	...

	*** This code is fairly experimental ***
	*** Much cleanup and testing is still needed ***

see slap.h for details on struct backend_db and backend_info.
---
 include/ldbm.h                            |   4 +-
 libraries/libldbm/ldbm.c                  |  38 ++-
 servers/slapd/acl.c                       |   2 +-
 servers/slapd/back-ldbm/close.c           |   6 +-
 servers/slapd/back-ldbm/config.c          |  18 +-
 servers/slapd/back-ldbm/external.h        |  59 ++++
 servers/slapd/back-ldbm/init.c            |  91 ++++-
 servers/slapd/back-ldbm/proto-back-ldbm.h |   2 +
 servers/slapd/back-passwd/Makefile.in     |   4 +-
 servers/slapd/back-passwd/config.c        |  11 +-
 servers/slapd/back-passwd/external.h      |  19 ++
 servers/slapd/back-passwd/init.c          |  41 +++
 servers/slapd/back-passwd/search.c        |   1 +
 servers/slapd/back-perl/close.c           |  28 +-
 servers/slapd/back-perl/config.c          |  16 +-
 servers/slapd/back-perl/external.h        |  50 +++
 servers/slapd/back-perl/init.c            |  68 +++-
 servers/slapd/back-perl/perl_back.h       |   4 +-
 servers/slapd/back-perl/unbind.c          |   5 +-
 servers/slapd/back-shell/abandon.c        |   8 +-
 servers/slapd/back-shell/config.c         |  28 +-
 servers/slapd/back-shell/external.h       |  53 +++
 servers/slapd/back-shell/init.c           |  46 ++-
 servers/slapd/back-shell/shell.h          |  26 +-
 servers/slapd/back-shell/unbind.c         |   8 +-
 servers/slapd/backend.c                   | 394 +++++++++++++++-------
 servers/slapd/config.c                    | 141 +++++---
 servers/slapd/daemon.c                    |  12 -
 servers/slapd/init.c                      |  79 ++++-
 servers/slapd/main.c                      |  62 ++--
 servers/slapd/proto-slap.h                |  96 ++----
 servers/slapd/slap.h                      | 139 ++++++--
 servers/slapd/tools/ldbmtest.c            |   8 +-
 servers/slapd/tools/ldif2id2children.c    |  10 +-
 servers/slapd/tools/ldif2id2entry.c       |  12 +-
 servers/slapd/tools/ldif2index.c          |  11 +-
 servers/slapd/tools/ldif2ldbm.c           |  18 +-
 servers/slapd/unbind.c                    |   2 +-
 38 files changed, 1213 insertions(+), 407 deletions(-)
 create mode 100644 servers/slapd/back-ldbm/external.h
 create mode 100644 servers/slapd/back-passwd/external.h
 create mode 100644 servers/slapd/back-passwd/init.c
 create mode 100644 servers/slapd/back-perl/external.h
 create mode 100644 servers/slapd/back-shell/external.h

diff --git a/include/ldbm.h b/include/ldbm.h
index 3f55a6ffea..ffe8804d6c 100644
--- a/include/ldbm.h
+++ b/include/ldbm.h
@@ -202,7 +202,9 @@ LDAP_END_DECL
 
 LDAP_BEGIN_DECL
 
-void ldbm_initialize( void );
+int ldbm_initialize( void );
+int ldbm_shutdown( void );
+
 int	ldbm_errno( LDBM ldbm );
 LDBM	ldbm_open( char *name, int rw, int mode, int dbcachesize );
 void	ldbm_close( LDBM ldbm );
diff --git a/libraries/libldbm/ldbm.c b/libraries/libldbm/ldbm.c
index 743e9b4cd8..4ca6595350 100644
--- a/libraries/libldbm/ldbm.c
+++ b/libraries/libldbm/ldbm.c
@@ -48,6 +48,8 @@ ldbm_datum_dup( LDBM ldbm, Datum data )
 	return( dup );
 }
 
+static int ldbm_initialized = 0;
+
 #ifndef HAVE_BERKELEY_DB2
 /* Everything but DB2 is non-reentrant */
 
@@ -55,13 +57,22 @@ static ldap_pvt_thread_mutex_t ldbm_big_mutex;
 #define LDBM_LOCK	(ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
 #define LDBM_UNLOCK	(ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
 
-void ldbm_initialize( void )
+int ldbm_initialize( void )
 {
-	static int initialized = 0;
-
-	if(initialized++) return;
+	if(ldbm_initialized++) return 1;
 
 	ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
+
+	return 0;
+}
+
+int ldbm_shutdown( void )
+{
+	if( !ldbm_initialized ) return 1;
+
+	ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
+
+	return 0;
 }
 
 #else
@@ -87,14 +98,12 @@ static DB_ENV           ldbm_Env;
 #define LDBM_LOCK	((void)0)
 #define LDBM_UNLOCK	((void)0)
 
-void ldbm_initialize( void )
+int ldbm_initialize( void )
 {
-	static int initialized = 0;
-
 	int     err;
 	int     envFlags;
 
-	if(initialized++) return;
+	if(ldbm_initialized++) return 1;
 
 	memset( &ldbm_Env, 0, sizeof( ldbm_Env ));
 
@@ -115,8 +124,19 @@ void ldbm_initialize( void )
 		syslog( LOG_INFO,
 			"ldbm_initialize(): FATAL error in db_appinit() : %s\n",
 			error );
-	 	exit( 1 );
+	 	return( 1 );
 	}
+
+	return 0;
+}
+
+int ldbm_shutdown( void )
+{
+	if( !ldbm_initialized ) return 1;
+
+	db_appexit( &ldbm_Env );
+
+	return 0;
 }
 
 #endif
diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c
index 255cf89545..d6e92eb53b 100644
--- a/servers/slapd/acl.c
+++ b/servers/slapd/acl.c
@@ -356,7 +356,7 @@ acl_access_allowed(
 			string_expand(buf, sizeof(buf), b->a_group, edn, matches);
 			(void) dn_normalize_case(buf);
 
-			if (be_group(be, e, buf, odn,
+			if (backend_group(be, e, buf, odn,
 				b->a_objectclassvalue, b->a_groupattrname) == 0)
 			{
 				Debug( LDAP_DEBUG_ACL,
diff --git a/servers/slapd/back-ldbm/close.c b/servers/slapd/back-ldbm/close.c
index 310f441b5d..5cb9a75b1c 100644
--- a/servers/slapd/back-ldbm/close.c
+++ b/servers/slapd/back-ldbm/close.c
@@ -9,8 +9,8 @@
 #include "slap.h"
 #include "back-ldbm.h"
 
-void
-ldbm_back_close( Backend *be )
+int
+ldbm_back_db_close( Backend *be )
 {
 	Debug( LDAP_DEBUG_TRACE, "ldbm backend saving nextid\n", 0, 0, 0 );
 	if ( next_id_save( be ) < 0 ) {
@@ -20,4 +20,6 @@ ldbm_back_close( Backend *be )
 	Debug( LDAP_DEBUG_TRACE, "ldbm backend syncing\n", 0, 0, 0 );
 	ldbm_cache_flush_all( be );
 	Debug( LDAP_DEBUG_TRACE, "ldbm backend done syncing\n", 0, 0, 0 );
+
+	return 0;
 }
diff --git a/servers/slapd/back-ldbm/config.c b/servers/slapd/back-ldbm/config.c
index 541410ee4d..808aa4f4a7 100644
--- a/servers/slapd/back-ldbm/config.c
+++ b/servers/slapd/back-ldbm/config.c
@@ -10,8 +10,8 @@
 #include "slap.h"
 #include "back-ldbm.h"
 
-void
-ldbm_back_config(
+int
+ldbm_back_db_config(
     Backend	*be,
     char	*fname,
     int		lineno,
@@ -24,7 +24,7 @@ ldbm_back_config(
 	if ( li == NULL ) {
 		fprintf( stderr, "%s: line %d: ldbm backend info is null!\n",
 		    fname, lineno );
-		exit( 1 );
+		return( 1 );
 	}
 
 	/* directory where database files live */
@@ -33,7 +33,7 @@ ldbm_back_config(
 			fprintf( stderr,
 		"%s: line %d: missing dir in \"directory <dir>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		li->li_directory = ch_strdup( argv[1] );
 
@@ -49,7 +49,7 @@ ldbm_back_config(
 			fprintf( stderr,
 			"%s: line %d: missing mode in \"mode <mode>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		li->li_mode = strtol( argv[1], NULL, 0 );
 
@@ -59,7 +59,7 @@ ldbm_back_config(
 			fprintf( stderr,
 "%s: line %d: missing attr in \"index <attr> [pres,eq,approx,sub]\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		} else if ( argc > 3 ) {
 			fprintf( stderr,
 "%s: line %d: extra junk after \"index <attr> [pres,eq,approx,sub]\" line (ignored)\n",
@@ -73,7 +73,7 @@ ldbm_back_config(
 			fprintf( stderr,
 		"%s: line %d: missing size in \"cachesize <size>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		li->li_cache.c_maxsize = atoi( argv[1] );
 
@@ -83,7 +83,7 @@ ldbm_back_config(
 			fprintf( stderr,
 		"%s: line %d: missing size in \"dbcachesize <size>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		li->li_dbcachesize = atoi( argv[1] );
 
@@ -97,4 +97,6 @@ ldbm_back_config(
 "%s: line %d: unknown directive \"%s\" in ldbm database definition (ignored)\n",
 		    fname, lineno, argv[0] );
 	}
+
+	return 0;
 }
diff --git a/servers/slapd/back-ldbm/external.h b/servers/slapd/back-ldbm/external.h
new file mode 100644
index 0000000000..55dba8609c
--- /dev/null
+++ b/servers/slapd/back-ldbm/external.h
@@ -0,0 +1,59 @@
+#ifndef _LDBM_EXTERNAL_H
+#define _LDBM_EXTERNAL_H
+
+LDAP_BEGIN_DECL
+
+extern int	ldbm_back_initialize LDAP_P(( BackendInfo *bi ));
+extern int	ldbm_back_open LDAP_P(( BackendInfo *bi ));
+extern int	ldbm_back_close LDAP_P(( BackendInfo *bi ));
+extern int	ldbm_back_destroy LDAP_P(( BackendInfo *bi ));
+
+extern int	ldbm_back_db_init LDAP_P(( BackendDB *bd ));
+extern int	ldbm_back_db_open LDAP_P(( BackendDB *bd ));
+extern int	ldbm_back_db_close LDAP_P(( BackendDB *bd ));
+extern int	ldbm_back_db_destroy LDAP_P(( BackendDB *bd ));
+
+extern int	ldbm_back_db_config LDAP_P(( BackendDB *bd,
+	char *fname, int lineno, int argc, char **argv ));
+
+extern int ldbm_back_bind LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, int method, struct berval *cred, char** edn ));
+
+extern int	ldbm_back_unbind LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op ));
+
+extern int	ldbm_back_search LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *base, int scope, int deref, int sizelimit, int timelimit,
+	Filter *filter, char *filterstr, char **attrs, int attrsonly ));
+
+extern int	ldbm_back_compare LDAP_P((BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, Ava 	*ava ));
+
+extern int	ldbm_back_modify LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, LDAPModList *ml ));
+
+extern int	ldbm_back_modrdn LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, char*newrdn, int deleteoldrdn ));
+
+extern int	ldbm_back_add LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, Entry *e ));
+
+extern int	ldbm_back_delete LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, char *dn ));
+
+extern int	ldbm_back_abandon LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, int msgid ));
+
+extern int	ldbm_back_group LDAP_P(( BackendDB *bd,
+	Entry *target, char* gr_ndn, char* op_ndn,
+	char* objectclassValue, char* groupattrName));
+
+LDAP_END_DECL
+
+#endif /* _LDBM_EXTERNAL_H */
+
diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c
index f0ae9fb777..7f65cf8dd5 100644
--- a/servers/slapd/back-ldbm/init.c
+++ b/servers/slapd/back-ldbm/init.c
@@ -10,8 +10,71 @@
 #include "slap.h"
 #include "back-ldbm.h"
 
-void
-ldbm_back_init(
+int
+ldbm_back_initialize(
+    BackendInfo	*bi
+)
+{
+	bi->bi_open = ldbm_back_open;
+	bi->bi_config = NULL;
+	bi->bi_close = ldbm_back_close;
+	bi->bi_destroy = ldbm_back_destroy;
+
+	bi->bi_db_init = ldbm_back_db_init;
+	bi->bi_db_config = ldbm_back_db_config;
+	bi->bi_db_open = ldbm_back_db_open;
+	bi->bi_db_close = ldbm_back_db_close;
+	bi->bi_db_destroy = ldbm_back_db_destroy;
+
+	bi->bi_op_bind = ldbm_back_bind;
+	bi->bi_op_unbind = ldbm_back_unbind;
+	bi->bi_op_search = ldbm_back_search;
+	bi->bi_op_compare = ldbm_back_compare;
+	bi->bi_op_modify = ldbm_back_modify;
+	bi->bi_op_modrdn = ldbm_back_modrdn;
+	bi->bi_op_add = ldbm_back_add;
+	bi->bi_op_delete = ldbm_back_delete;
+	bi->bi_op_abandon = ldbm_back_abandon;
+
+	bi->bi_acl_group = ldbm_back_group;
+
+	return 0;
+}
+
+int
+ldbm_back_destroy(
+    BackendInfo	*bi
+)
+{
+	return 0;
+}
+
+int
+ldbm_back_open(
+    BackendInfo	*bi
+)
+{
+	int rc;
+
+	/* initialize the underlying database system */
+	rc = ldbm_initialize();
+
+	return rc;
+}
+
+int
+ldbm_back_close(
+    BackendInfo	*bi
+)
+{
+	/* initialize the underlying database system */
+	ldbm_shutdown();
+
+	return 0;
+}
+
+int
+ldbm_back_db_init(
     Backend	*be
 )
 {
@@ -19,9 +82,6 @@ ldbm_back_init(
 	char		*argv[ 4 ];
 	int		i;
 
-	/* initialize the underlying database system */
-	ldbm_initialize();
-
 	/* allocate backend-specific stuff */
 	li = (struct ldbminfo *) ch_calloc( 1, sizeof(struct ldbminfo) );
 
@@ -78,4 +138,25 @@ ldbm_back_init(
 	ldap_pvt_thread_cond_init( &li->li_dbcache_cv );
 
 	be->be_private = li;
+
+	return 0;
+}
+
+int
+ldbm_back_db_open(
+    BackendDB	*be
+)
+{
+	return 0;
+}
+
+int
+ldbm_back_db_destroy(
+    BackendDB	*be
+)
+{
+	/* should free/destroy every in be_private */
+	free( be->be_private );
+	be->be_private = NULL;
+	return 0;
 }
diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h
index 5b0ecd852f..ae7ec7f957 100644
--- a/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -3,6 +3,8 @@
 
 #include <ldap_cdefs.h>
 
+#include "external.h"
+
 LDAP_BEGIN_DECL
 
 /*
diff --git a/servers/slapd/back-passwd/Makefile.in b/servers/slapd/back-passwd/Makefile.in
index 24d620b103..11e66e089d 100644
--- a/servers/slapd/back-passwd/Makefile.in
+++ b/servers/slapd/back-passwd/Makefile.in
@@ -1,6 +1,6 @@
 XSRCS	= version.c
-SRCS	= search.c config.c
-OBJS	= search.o config.o
+SRCS	= search.c config.c init.c
+OBJS	= search.o config.o init.o
 
 LDAP_INCDIR= ../../../include       
 LDAP_LIBDIR= ../../../libraries
diff --git a/servers/slapd/back-passwd/config.c b/servers/slapd/back-passwd/config.c
index 3ed61fa9e7..7f6cb41169 100644
--- a/servers/slapd/back-passwd/config.c
+++ b/servers/slapd/back-passwd/config.c
@@ -9,10 +9,11 @@
 #include <ac/time.h>
 
 #include "slap.h"
+#include "external.h"
 
-void
-passwd_back_config(
-    Backend	*be,
+int
+passwd_back_db_config(
+    BackendDB	*be,
     char	*fname,
     int		lineno,
     int		argc,
@@ -26,7 +27,7 @@ passwd_back_config(
 			fprintf( stderr,
 		"%s: line %d: missing filename in \"file <filename>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		be->be_private = ch_strdup( argv[1] );
 #else /* HAVE_SETPWFILE */
@@ -41,4 +42,6 @@ passwd_back_config(
 "%s: line %d: unknown directive \"%s\" in passwd database definition (ignored)\n",
 		    fname, lineno, argv[0] );
 	}
+
+	return( 0 );
 }
diff --git a/servers/slapd/back-passwd/external.h b/servers/slapd/back-passwd/external.h
new file mode 100644
index 0000000000..ff34de26cf
--- /dev/null
+++ b/servers/slapd/back-passwd/external.h
@@ -0,0 +1,19 @@
+#ifndef _PASSWD_EXTERNAL_H
+#define _PASSWD_EXTERNAL_H
+
+LDAP_BEGIN_DECL
+
+extern int	passwd_back_initialize LDAP_P(( BackendInfo *bi ));
+
+extern int  passwd_back_search LDAP_P(( BackendDB *be,
+	Connection *c, Operation *o,
+	char *base, int scope, int deref, int slimit, int tlimit,
+	Filter *f, char *filterstr, char **attrs, int attrsonly));
+
+extern int passwd_back_db_config LDAP_P((BackendDB *bd,
+	char *fname, int lineno, int argc, char **argv ));
+
+LDAP_END_DECL
+
+#endif /* _PASSWD_EXTERNAL_H */
+
diff --git a/servers/slapd/back-passwd/init.c b/servers/slapd/back-passwd/init.c
new file mode 100644
index 0000000000..eea608c2fc
--- /dev/null
+++ b/servers/slapd/back-passwd/init.c
@@ -0,0 +1,41 @@
+/* init.c - initialize passwd backend */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "external.h"
+
+int
+passwd_back_initialize(
+    BackendInfo	*bi
+)
+{
+	bi->bi_open = NULL;
+	bi->bi_config = NULL;
+	bi->bi_close = NULL;
+	bi->bi_destroy = NULL;
+
+	bi->bi_db_init = NULL;
+	bi->bi_db_config = NULL;
+	bi->bi_db_open = NULL;
+	bi->bi_db_close = NULL;
+	bi->bi_db_destroy = NULL;
+
+	bi->bi_op_bind = NULL;
+	bi->bi_op_unbind = NULL;
+	bi->bi_op_search = passwd_back_search;
+	bi->bi_op_compare = NULL;
+	bi->bi_op_modify = NULL;
+	bi->bi_op_modrdn = NULL;
+	bi->bi_op_add = NULL;
+	bi->bi_op_delete = NULL;
+	bi->bi_op_abandon = NULL;
+
+	bi->bi_acl_group = NULL;
+
+	return 0;
+}
diff --git a/servers/slapd/back-passwd/search.c b/servers/slapd/back-passwd/search.c
index 8695ffa616..0852a88d1b 100644
--- a/servers/slapd/back-passwd/search.c
+++ b/servers/slapd/back-passwd/search.c
@@ -11,6 +11,7 @@
 #include <pwd.h>
 
 #include "slap.h"
+#include "external.h"
 
 static Entry	*pw2entry(Backend *be, struct passwd *pw);
 
diff --git a/servers/slapd/back-perl/close.c b/servers/slapd/back-perl/close.c
index 8e320e6b59..61c8f03e5b 100644
--- a/servers/slapd/back-perl/close.c
+++ b/servers/slapd/back-perl/close.c
@@ -27,16 +27,38 @@
  *
  **********************************************************/
 
-void
+int
 perl_back_close(
-	Backend *be
+	BackendInfo *bd
 )
 {
 	ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );	
 
 	perl_destruct(perl_interpreter);
-	perl_free(perl_interpreter);
 
 	ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );	
+
+	return 0;
+}
+
+int
+perl_back_destroy(
+	BackendInfo *bd
+)
+{
+	perl_free(perl_interpreter);
+	perl_interpreter = NULL;
+
+	ldap_pvt_thread_mutex_destroy( &perl_interpreter_mutex );	
+
+	return 0;
 }
 
+int
+perl_back_db_destroy(
+	BackendDB *be
+)
+{
+	free( be->be_private );
+	be->be_private = NULL;
+}
diff --git a/servers/slapd/back-perl/config.c b/servers/slapd/back-perl/config.c
index 1ac51024f9..c2e4298e67 100644
--- a/servers/slapd/back-perl/config.c
+++ b/servers/slapd/back-perl/config.c
@@ -27,9 +27,9 @@
  * Config
  *
  **********************************************************/
-void
-perl_back_config(
-	 Backend *be,
+int
+perl_back_db_config(
+	 BackendDB *be,
 	 char *fname,
 	 int lineno,
 	 int argc,
@@ -48,7 +48,7 @@ perl_back_config(
 			Debug( LDAP_DEBUG_ANY,
 				 "%s.pm: line %d: missing module in \"perlModule <module>\" line\n",
 				fname, lineno, 0 );
-			exit( 1 );
+			return( 1 );
 		}
 
 		strncpy(eval_str, argv[1], EVAL_BUF_SIZE );
@@ -82,7 +82,7 @@ perl_back_config(
 			fprintf( stderr,
 				"%s: line %d: missing module in \"PerlModulePath <module>\" line\n",
 				fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 
 		sprintf( eval_str, "push @INC, '%s';", argv[1] );
@@ -94,7 +94,9 @@ perl_back_config(
 		 */
 
 		fprintf( stderr,
-			"Unknown perl backeng config: %s\n", argv[0]);
-		exit( 1 );
+			"Unknown perl backend config: %s\n", argv[0]);
+		return( 1 );
 	}
+
+	return 0;
 }
diff --git a/servers/slapd/back-perl/external.h b/servers/slapd/back-perl/external.h
new file mode 100644
index 0000000000..a6dd621b09
--- /dev/null
+++ b/servers/slapd/back-perl/external.h
@@ -0,0 +1,50 @@
+#ifndef _PERL_EXTERNAL_H
+#define _PERL_EXTERNAL_H
+
+LDAP_BEGIN_DECL
+
+extern int	perl_back_initialize LDAP_P(( BackendInfo *bi ));
+extern int	perl_back_open LDAP_P(( BackendInfo *bi ));
+extern int	perl_back_close LDAP_P(( BackendInfo *bi ));
+extern int	perl_back_destroy LDAP_P(( BackendInfo *bi ));
+
+extern int	perl_back_db_init LDAP_P(( BackendDB *bd ));
+extern int	perl_back_db_destroy LDAP_P(( BackendDB *bd ));
+
+extern int	perl_back_db_config LDAP_P(( BackendDB *bd,
+	char *fname, int lineno, int argc, char **argv ));
+
+extern int perl_back_bind LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, int method, struct berval *cred, char** edn ));
+
+extern int	perl_back_unbind LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op ));
+
+extern int	perl_back_search LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *base, int scope, int deref, int sizelimit, int timelimit,
+	Filter *filter, char *filterstr, char **attrs, int attrsonly ));
+
+extern int	perl_back_compare LDAP_P((BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, Ava 	*ava ));
+
+extern int	perl_back_modify LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, LDAPModList *ml ));
+
+extern int	perl_back_modrdn LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, char*newrdn, int deleteoldrdn ));
+
+extern int	perl_back_add LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, Entry *e ));
+
+extern int	perl_back_delete LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, char *dn ));
+
+LDAP_END_DECL
+
+#endif /* _PERL_EXTERNAL_H */
+
diff --git a/servers/slapd/back-perl/init.c b/servers/slapd/back-perl/init.c
index c50785bc80..a009ec8056 100644
--- a/servers/slapd/back-perl/init.c
+++ b/servers/slapd/back-perl/init.c
@@ -33,25 +33,71 @@ ldap_pvt_thread_mutex_t	perl_interpreter_mutex;
  *
  **********************************************************/
 
-void
-perl_back_init(
-	Backend	*be
+int
+perl_back_initialize(
+	BackendInfo	*bi
 )
 {
 	char *embedding[] = { "", "-e", "0" };
 
-	if( perl_interpreter == NULL ) {
-		perl_interpreter = perl_alloc();
-		perl_construct(perl_interpreter);
-		perl_parse(perl_interpreter, NULL, 3, embedding, (char **)NULL);
-		perl_run(perl_interpreter);
-		
-		ldap_pvt_thread_mutex_init( &perl_interpreter_mutex );
+	Debug( LDAP_DEBUG_TRACE, "perl backend open\n", 0, 0, 0 );
+
+	if( perl_interpreter != NULL ) {
+		Debug( LDAP_DEBUG_ANY, "perl backend open: already opened\n",
+			0, 0, 0 );
+		return 1;
 	}
+	
+	perl_interpreter = perl_alloc();
+	perl_construct(perl_interpreter);
+	perl_parse(perl_interpreter, NULL, 3, embedding, (char **)NULL);
+	perl_run(perl_interpreter);
+
+	bi->bi_open = perl_back_open;
+	bi->bi_config = NULL;
+	bi->bi_close = perl_back_close;
+	bi->bi_destroy = perl_back_destroy;
+
+	bi->bi_db_init = perl_back_db_init;
+	bi->bi_db_config = perl_back_db_config;
+	bi->bi_db_open = NULL;
+	bi->bi_db_close = NULL;
+	bi->bi_db_destroy = perl_back_db_destroy;
+
+	bi->bi_op_bind = perl_back_bind;
+	bi->bi_op_unbind = perl_back_unbind;
+	bi->bi_op_search = perl_back_search;
+	bi->bi_op_compare = perl_back_compare;
+	bi->bi_op_modify = perl_back_modify;
+	bi->bi_op_modrdn = perl_back_modrdn;
+	bi->bi_op_add = perl_back_add;
+	bi->bi_op_delete = perl_back_delete;
+	bi->bi_op_abandon = NULL;
+
+	bi->bi_acl_group = NULL;
+
+	return 0;
+}
+		
+int
+perl_back_open(
+	BackendInfo	*bi
+)
+{
+	ldap_pvt_thread_mutex_init( &perl_interpreter_mutex );
+	return 0;
+}
 
+int
+perl_back_db_init(
+	Backend	*be
+)
+{
 	be->be_private = (PerlBackend *) ch_malloc( sizeof(PerlBackend) );
 	memset(&be->be_private, 0, sizeof(PerlBackend));
 
-	Debug( LDAP_DEBUG_ANY, "Here in perl backend\n", 0, 0, 0 );
+	Debug( LDAP_DEBUG_TRACE, "perl backend db init\n", 0, 0, 0 );
+
+	return 0;
 }
 
diff --git a/servers/slapd/back-perl/perl_back.h b/servers/slapd/back-perl/perl_back.h
index a8adcd57a1..2f650a3c0a 100644
--- a/servers/slapd/back-perl/perl_back.h
+++ b/servers/slapd/back-perl/perl_back.h
@@ -1,8 +1,6 @@
 #ifndef PERL_BACK_H
 #define PERL_BACK_H 1
 
-#include <ldap_cdefs.h>
-
 LDAP_BEGIN_DECL
 
 /*
@@ -19,4 +17,6 @@ typedef struct perl_backend_instance {
 
 LDAP_END_DECL
 
+#include "external.h"
+
 #endif
diff --git a/servers/slapd/back-perl/unbind.c b/servers/slapd/back-perl/unbind.c
index 2c83d8573d..5ba03f29a8 100644
--- a/servers/slapd/back-perl/unbind.c
+++ b/servers/slapd/back-perl/unbind.c
@@ -27,7 +27,7 @@
  * UnBind
  *
  **********************************************************/
-void
+int
 perl_back_unbind(
 	Backend *be,
 	Connection *conn,
@@ -36,6 +36,7 @@ perl_back_unbind(
 {
 	send_ldap_result( conn, op, LDAP_NOT_SUPPORTED,
 		"", "not yet implemented" );
-	Debug( LDAP_DEBUG_ANY, "Perl UNBIND\n", 0, 0, 0 );
+	Debug( LDAP_DEBUG_TRACE, "Perl UNBIND\n", 0, 0, 0 );
+	return 0;
 }
 
diff --git a/servers/slapd/back-shell/abandon.c b/servers/slapd/back-shell/abandon.c
index dad3204984..e69bab6e4b 100644
--- a/servers/slapd/back-shell/abandon.c
+++ b/servers/slapd/back-shell/abandon.c
@@ -11,7 +11,7 @@
 #include "slap.h"
 #include "shell.h"
 
-void
+int
 shell_back_abandon(
     Backend	*be,
     Connection	*conn,
@@ -44,11 +44,11 @@ shell_back_abandon(
 			Debug( LDAP_DEBUG_ARGS, "shell could not find op %d\n",
 			    msgid, 0, 0 );
 		}
-		return;
+		return 0;
 	}
 
 	if ( forkandexec( si->si_abandon, &rfp, &wfp ) == -1 ) {
-		return;
+		return 0;
 	}
 
 	/* write out the request to the abandon process */
@@ -59,4 +59,6 @@ shell_back_abandon(
 
 	/* no result from abandon */
 	fclose( rfp );
+
+	return 0;
 }
diff --git a/servers/slapd/back-shell/config.c b/servers/slapd/back-shell/config.c
index ac411d7563..a308ba1a97 100644
--- a/servers/slapd/back-shell/config.c
+++ b/servers/slapd/back-shell/config.c
@@ -10,9 +10,9 @@
 #include "slap.h"
 #include "shell.h"
 
-void
-shell_back_config(
-    Backend	*be,
+int
+shell_back_db_config(
+    BackendDB	*be,
     char	*fname,
     int		lineno,
     int		argc,
@@ -24,7 +24,7 @@ shell_back_config(
 	if ( si == NULL ) {
 		fprintf( stderr, "%s: line %d: shell backend info is null!\n",
 		    fname, lineno );
-		exit( 1 );
+		return( 1 );
 	}
 
 	/* command + args to exec for binds */
@@ -33,7 +33,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"bind <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_bind = charray_dup( &argv[1] );
 
@@ -43,7 +43,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"unbind <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_unbind = charray_dup( &argv[1] );
 
@@ -53,7 +53,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"search <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_search = charray_dup( &argv[1] );
 
@@ -63,7 +63,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"compare <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_compare = charray_dup( &argv[1] );
 
@@ -73,7 +73,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"modify <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_modify = charray_dup( &argv[1] );
 
@@ -83,7 +83,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"modrdn <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_modrdn = charray_dup( &argv[1] );
 
@@ -93,7 +93,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"add <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_add = charray_dup( &argv[1] );
 
@@ -103,7 +103,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"delete <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_delete = charray_dup( &argv[1] );
 
@@ -113,7 +113,7 @@ shell_back_config(
 			fprintf( stderr,
 	"%s: line %d: missing executable in \"abandon <executable>\" line\n",
 			    fname, lineno );
-			exit( 1 );
+			return( 1 );
 		}
 		si->si_abandon = charray_dup( &argv[1] );
 
@@ -123,4 +123,6 @@ shell_back_config(
 "%s: line %d: unknown directive \"%s\" in shell database definition (ignored)\n",
 		    fname, lineno, argv[0] );
 	}
+
+	return 0;
 }
diff --git a/servers/slapd/back-shell/external.h b/servers/slapd/back-shell/external.h
new file mode 100644
index 0000000000..b12adc1d71
--- /dev/null
+++ b/servers/slapd/back-shell/external.h
@@ -0,0 +1,53 @@
+#ifndef _SHELL_EXTERNAL_H
+#define _SHELL_EXTERNAL_H
+
+LDAP_BEGIN_DECL
+
+extern int	shell_back_initialize LDAP_P(( BackendInfo *bi ));
+extern int	shell_back_open LDAP_P(( BackendInfo *bi ));
+extern int	shell_back_close LDAP_P(( BackendInfo *bi ));
+extern int	shell_back_destroy LDAP_P(( BackendInfo *bi ));
+
+extern int	shell_back_db_init LDAP_P(( BackendDB *bd ));
+extern int	shell_back_db_destroy LDAP_P(( BackendDB *bd ));
+
+extern int	shell_back_db_config LDAP_P(( BackendDB *bd,
+	char *fname, int lineno, int argc, char **argv ));
+
+extern int shell_back_bind LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, int method, struct berval *cred, char** edn ));
+
+extern int	shell_back_unbind LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op ));
+
+extern int	shell_back_search LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *base, int scope, int deref, int sizelimit, int timelimit,
+	Filter *filter, char *filterstr, char **attrs, int attrsonly ));
+
+extern int	shell_back_compare LDAP_P((BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, Ava 	*ava ));
+
+extern int	shell_back_modify LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, LDAPModList *ml ));
+
+extern int	shell_back_modrdn LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op,
+	char *dn, char*newrdn, int deleteoldrdn ));
+
+extern int	shell_back_add LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, Entry *e ));
+
+extern int	shell_back_delete LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, char *dn ));
+
+extern int	shell_back_abandon LDAP_P(( BackendDB *bd,
+	Connection *conn, Operation *op, int msgid ));
+
+LDAP_END_DECL
+
+#endif /* _SHELL_EXTERNAL_H */
+
diff --git a/servers/slapd/back-shell/init.c b/servers/slapd/back-shell/init.c
index 6a841c154b..01b46cc519 100644
--- a/servers/slapd/back-shell/init.c
+++ b/servers/slapd/back-shell/init.c
@@ -9,8 +9,39 @@
 #include "slap.h"
 #include "shell.h"
 
-void
-shell_back_init(
+int
+shell_back_initialize(
+    BackendInfo	*bi
+)
+{
+	bi->bi_open = NULL;
+	bi->bi_config = NULL;
+	bi->bi_close = NULL;
+	bi->bi_destroy = NULL;
+
+	bi->bi_db_init = shell_back_db_init;
+	bi->bi_db_config = shell_back_db_config;
+	bi->bi_db_open = NULL;
+	bi->bi_db_close = NULL;
+	bi->bi_db_destroy = shell_back_db_destroy;
+
+	bi->bi_op_bind = shell_back_bind;
+	bi->bi_op_unbind = shell_back_unbind;
+	bi->bi_op_search = shell_back_search;
+	bi->bi_op_compare = shell_back_compare;
+	bi->bi_op_modify = shell_back_modify;
+	bi->bi_op_modrdn = shell_back_modrdn;
+	bi->bi_op_add = shell_back_add;
+	bi->bi_op_delete = shell_back_delete;
+	bi->bi_op_abandon = shell_back_abandon;
+
+	bi->bi_acl_group = NULL;
+
+	return 0;
+}
+
+int
+shell_back_db_init(
     Backend	*be
 )
 {
@@ -19,4 +50,15 @@ shell_back_init(
 	si = (struct shellinfo *) ch_calloc( 1, sizeof(struct shellinfo) );
 
 	be->be_private = si;
+
+	return si == NULL;
+}
+
+int
+shell_back_db_destroy(
+    Backend	*be
+)
+{
+	free( be->be_private );
+	return 0;
 }
diff --git a/servers/slapd/back-shell/shell.h b/servers/slapd/back-shell/shell.h
index 6860073c67..a17bc4da5b 100644
--- a/servers/slapd/back-shell/shell.h
+++ b/servers/slapd/back-shell/shell.h
@@ -3,7 +3,7 @@
 #ifndef SLAPD_SHELL_H
 #define SLAPD_SHELL_H
 
-#include <ldap_cdefs.h>
+#include "external.h"
 
 LDAP_BEGIN_DECL
 
@@ -19,14 +19,26 @@ struct shellinfo {
 	char	**si_abandon;	/* cmd + args to exec for abandon */
 };
 
-struct backend;
+struct backend_db;
 struct slap_conn;
 struct slap_op;
-extern pid_t forkandexec LDAP_P((char **args, FILE **rfp, FILE **wfp));
-extern void print_suffixes LDAP_P((FILE *fp, struct backend *be));
-extern int read_and_send_results LDAP_P((struct backend *be,
-	struct slap_conn *conn, struct slap_op *op,
-	FILE *fp, char **attrs, int attrsonly));
+
+extern pid_t forkandexec LDAP_P((
+	char **args,
+	FILE **rfp,
+	FILE **wfp));
+
+extern void print_suffixes LDAP_P((
+	FILE *fp,
+	struct backend_db *bd));
+
+extern int read_and_send_results LDAP_P((
+	struct backend_db *bd,
+	struct slap_conn *conn,
+	struct slap_op *op,
+	FILE *fp,
+	char **attrs,
+	int attrsonly));
 
 LDAP_END_DECL
 
diff --git a/servers/slapd/back-shell/unbind.c b/servers/slapd/back-shell/unbind.c
index 7ad4ba619b..6e8d1009c1 100644
--- a/servers/slapd/back-shell/unbind.c
+++ b/servers/slapd/back-shell/unbind.c
@@ -10,7 +10,7 @@
 #include "slap.h"
 #include "shell.h"
 
-void
+int
 shell_back_unbind(
     Backend		*be,
     Connection		*conn,
@@ -23,14 +23,14 @@ shell_back_unbind(
 	if ( si->si_unbind == NULL ) {
 		send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
 		    "unbind not implemented" );
-		return;
+		return 0;
 	}
 
 	if ( (op->o_private = (void *) forkandexec( si->si_unbind, &rfp, &wfp ))
 	    == (void *) -1 ) {
 		send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
 		    "could not fork/exec" );
-		return;
+		return 0;
 	}
 
 	/* write out the request to the unbind process */
@@ -42,4 +42,6 @@ shell_back_unbind(
 
 	/* no response to unbind */
 	fclose( rfp );
+
+	return 0;
 }
diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c
index be069201f9..e97914d0a8 100644
--- a/servers/slapd/backend.c
+++ b/servers/slapd/backend.c
@@ -12,139 +12,298 @@
 
 #include "slap.h"
 
+#ifdef SLAPD_LDBM
+#include "back-ldbm/external.h"
+#endif
+#ifdef SLAPD_PASSWD
+#include "back-passwd/external.h"
+#endif
+#ifdef SLAPD_PERL
+#include "back-perl/external.h"
+#endif
+#ifdef SLAPD_SHELL
+#include "back-shell/external.h"
+#endif
 
-#define BACKEND_GRAB_SIZE	10
+static BackendInfo binfo[] = {
+#ifdef SLAPD_LDBM
+	{"ldbm",	ldbm_back_initialize},
+#endif
+#ifdef SLAPD_PASSWD
+	{"passwd",	passwd_back_initialize},
+#endif
+#ifdef SLAPD_PERL
+	{"perl",	perl_back_initialize},
+#endif
+#ifdef SLAPD_SHELL
+	{"shell",	shell_back_initialize},
+#endif
+	{NULL}
+};
 
-int		nbackends;
-Backend		*backends;
-static int	maxbackends;
+int			nBackendInfo = 0;
+BackendInfo	*backendInfo = NULL;
 
-Backend *
-new_backend(
-    char	*type
-)
+int			nBackendDB = 0; 
+BackendDB	*backendDB = NULL;
+
+int backend_init(void)
 {
-	Backend	*be;
-	int	foundit;
-
-	if ( nbackends == maxbackends ) {
-		maxbackends += BACKEND_GRAB_SIZE;
-		backends = (Backend *) ch_realloc( (char *) backends,
-		    maxbackends * sizeof(Backend) );
-		memset( &backends[nbackends], '\0', BACKEND_GRAB_SIZE *
-		    sizeof(Backend) );
+	int rc = 0;
+
+	if((nBackendInfo != 0) || (backendInfo != NULL)) {
+		/* already initialized */
+		Debug( LDAP_DEBUG_ANY,
+			"backend_init: already initialized.\n", 0, 0, 0 );
+		return -1;
 	}
 
-	be = &backends[nbackends++];
-	be->be_sizelimit = defsize;
-	be->be_timelimit = deftime;
-	foundit = 0;
+	for( ;
+		binfo[nBackendInfo].bi_type !=  NULL;
+		nBackendInfo++ )
+	{
+		rc = binfo[nBackendInfo].bi_init(
+			&binfo[nBackendInfo] );
+
+		if(rc != 0) {
+			Debug( LDAP_DEBUG_ANY,
+				"backend_init: initialized for type \"%s\"\n",
+					binfo[nBackendInfo].bi_type, 0, 0 );
+
+			/* destroy those we've already inited */
+			for( nBackendInfo--;
+				nBackendInfo >= 0 ;
+				nBackendInfo-- )
+			{ 
+				if ( binfo[nBackendInfo].bi_destroy ) {
+					binfo[nBackendInfo].bi_destroy(
+						&binfo[nBackendInfo] );
+				}
+			}
+			return rc;
+		}
+	}
 
-#ifdef SLAPD_LDBM
-	if ( strcasecmp( type, "ldbm" ) == 0 ) {
-		be->be_bind = ldbm_back_bind;
-		be->be_unbind = ldbm_back_unbind;
-		be->be_search = ldbm_back_search;
-		be->be_compare = ldbm_back_compare;
-		be->be_modify = ldbm_back_modify;
-		be->be_modrdn = ldbm_back_modrdn;
-		be->be_add = ldbm_back_add;
-		be->be_delete = ldbm_back_delete;
-		be->be_abandon = ldbm_back_abandon;
-		be->be_config = ldbm_back_config;
-		be->be_init = ldbm_back_init;
-		be->be_close = ldbm_back_close;
-#ifdef SLAPD_ACLGROUPS
-		be->be_group = ldbm_back_group;
-#endif
-		be->be_type = "ldbm";
-		foundit = 1;
+	if ( nBackendInfo > 0) {
+		backendInfo = binfo;
+		return 0;
 	}
-#endif
 
-#ifdef SLAPD_PASSWD
-	if ( strcasecmp( type, "passwd" ) == 0 ) {
-		be->be_bind = NULL;
-		be->be_unbind = NULL;
-		be->be_search = passwd_back_search;
-		be->be_compare = NULL;
-		be->be_modify = NULL;
-		be->be_modrdn = NULL;
-		be->be_add = NULL;
-		be->be_delete = NULL;
-		be->be_abandon = NULL;
-		be->be_config = passwd_back_config;
-		be->be_init = NULL;
-		be->be_close = NULL;
-#ifdef SLAPD_ACLGROUPS
-		be->be_group = NULL;
-#endif
-		be->be_type = "passwd";
-		foundit = 1;
+	Debug( LDAP_DEBUG_ANY,
+		"backend_init: failed\n",
+		0, 0, 0 );
+
+
+	return rc;
+}
+
+int backend_startup(int n)
+{
+	int i;
+	int rc = 0;
+
+	if( ! ( nBackendDB > 0 ) ) {
+		/* no databases */
+		Debug( LDAP_DEBUG_ANY,
+			"backend_startup: %d databases to startup.\n",
+			nBackendDB, 0, 0 );
+		return 1;
 	}
-#endif
 
-#ifdef SLAPD_SHELL
-	if ( strcasecmp( type, "shell" ) == 0 ) {
-		be->be_bind = shell_back_bind;
-		be->be_unbind = shell_back_unbind;
-		be->be_search = shell_back_search;
-		be->be_compare = shell_back_compare;
-		be->be_modify = shell_back_modify;
-		be->be_modrdn = shell_back_modrdn;
-		be->be_add = shell_back_add;
-		be->be_delete = shell_back_delete;
-		be->be_abandon = shell_back_abandon;
-		be->be_config = shell_back_config;
-		be->be_init = shell_back_init;
-		be->be_close = NULL;
-#ifdef SLAPD_ACLGROUPS
-		be->be_group = NULL;
-#endif
-		be->be_type = "shell";
-		foundit = 1;
+	if(n >= 0) {
+		/* startup a specific backend database */
+		Debug( LDAP_DEBUG_TRACE,
+			"backend_startup: starting database %d\n",
+			n, 0, 0 );
+
+		if ( backendDB[n].bd_info->bi_open ) {
+			rc = backendDB[n].bd_info->bi_open(
+				backendDB[n].bd_info );
+		}
+
+		if(rc != 0) {
+			Debug( LDAP_DEBUG_TRACE,
+				"backend_startup: bi_open failed!\n",
+				0, 0, 0 );
+			return rc;
+		}
+
+		if ( backendDB[n].bd_info->bi_db_open ) {
+			rc = backendDB[n].bd_info->bi_db_open(
+				&backendDB[n] );
+		}
+
+		if(rc != 0) {
+			Debug( LDAP_DEBUG_TRACE,
+				"backend_startup: bi_db_open failed!\n",
+				0, 0, 0 );
+			return rc;
+		}
+
+		return rc;
 	}
-#endif
 
+	/* open each backend type */
+	for( i = 0; i < nBackendInfo; i++ ) {
+		if( backendInfo[i].bi_open ) {
+			rc = backendInfo[i].bi_open(
+				&backendInfo[i] );
+		}
 
-#ifdef SLAPD_PERL
-	if ( strcasecmp( type, "perl" ) == 0 ) {
-#ifdef notdef
-		be->be_abandon = perl_back_abandon;
-		be->be_bind = perl_back_bind;
-#else
-		be->be_abandon = NULL;
-		be->be_bind = NULL;
-#endif
-		be->be_unbind = perl_back_unbind;
-		be->be_search = perl_back_search;
-		be->be_compare = perl_back_compare;
-		be->be_modify = perl_back_modify;
-		be->be_modrdn = perl_back_modrdn;
-		be->be_add = perl_back_add;
-		be->be_delete = perl_back_delete;
-		be->be_config = perl_back_config;
-		be->be_init = perl_back_init;
-		be->be_close = perl_back_close;
-		be->be_type = "perl";
-		foundit = 1;
+		if(rc != 0) {
+			Debug( LDAP_DEBUG_TRACE,
+				"backend_startup: bi_open %d failed!\n",
+				i, 0, 0 );
+			return rc;
+		}
 	}
-#endif
 
+	/* open each backend database */
+	for( i = 0; i < nBackendDB; i++ ) {
+		if ( backendDB[i].bd_info->bi_db_open ) {
+			rc = backendDB[i].bd_info->bi_db_open(
+				&backendDB[i] );
+		}
+
+		if(rc != 0) {
+			Debug( LDAP_DEBUG_TRACE,
+				"backend_startup: bi_db_open %d failed!\n",
+				i, 0, 0 );
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
+int backend_shutdown(int n)
+{
+	int i;
+
+	if(n >= 0) {
+		/* shutdown a specific backend database */
+
+		if ( backendDB[n].bd_info->bi_db_close ) {
+			backendDB[n].bd_info->bi_db_close(
+				&backendDB[n] );
+		}
+
+		if( backendDB[n].bd_info->bi_close ) {
+			backendDB[n].bd_info->bi_close(
+				backendDB[n].bd_info );
+		}
+
+		return 0;
+	}
+
+	/* close each backend database */
+	for( i = 0; i < nBackendDB; i++ ) {
+		if ( backendDB[i].bd_info->bi_db_close ) {
+			backendDB[i].bd_info->bi_db_close(
+				&backendDB[i] );
+		}
+	}
+
+	/* close each backend type */
+	for( i = 0; i < nBackendInfo; i++ ) {
+		if( backendInfo[i].bi_close ) {
+			backendInfo[i].bi_close(
+				&backendInfo[i] );
+		}
+	}
+
+	return 0;
+}
+
+int backend_destroy(void)
+{
+	int i;
+
+	/* destroy each backend database */
+	for( i = 0; i < nBackendDB; i++ ) {
+		if ( backendDB[i].bd_info->bi_db_destroy ) {
+			backendDB[i].bd_info->bi_db_destroy(
+				&backendDB[i] );
+		}
+	}
 
+	/* destroy each backend type */
+	for( i = 0; i < nBackendInfo; i++ ) {
+		if( backendInfo[i].bi_close ) {
+			backendInfo[i].bi_close(
+				&backendInfo[i] );
+		}
+	}
+
+	return 0;
+}
+
+BackendInfo* backend_info(char *type)
+{
+	int i;
 
-	if ( be->be_init != NULL ) {
-		(*be->be_init)( be );
+	/* search for the backend type */
+	for( i = 0; i < nBackendInfo; i++ ) {
+		if( strcasecmp(backendInfo[i].bi_type, type) == 0 ) {
+			return &backendInfo[i];
+		}
 	}
 
-	if ( foundit == 0 ) {
+	return NULL;
+}
+
+
+BackendDB *
+backend_db_init(
+    char	*type
+)
+{
+	Backend	*be;
+	BackendInfo *bi = backend_info(type);
+	int	rc = 0;
+
+	if( bi == NULL ) {
 		fprintf( stderr, "Unrecognized database type (%s)\n", type );
-		exit( 1 );
+		return NULL;
+	}
+
+	backendDB = (BackendDB *) ch_realloc(
+			(char *) backendDB,
+		    (nBackendDB + 1) * sizeof(Backend) );
+
+	memset( &backendDB[nbackends], '\0', sizeof(Backend) );
+
+	be = &backends[nbackends++];
+
+	be->bd_info = bi;
+	be->be_sizelimit = defsize;
+	be->be_timelimit = deftime;
+
+	if(bi->bi_db_init) {
+		rc = bi->bi_db_init( be );
+	}
+
+	if(rc != 0) {
+		fprintf( stderr, "database init failed (%s)\n", type );
+		nbackends--;
+		return NULL;
 	}
 
 	return( be );
 }
 
+void
+be_db_close( void )
+{
+	int	i;
+
+	for ( i = 0; i < nbackends; i++ ) {
+		if ( backends[i].bd_info->bi_db_close != NULL ) {
+			(*backends[i].bd_info->bi_db_close)( &backends[i] );
+		}
+	}
+}
+
 Backend *
 select_backend( char * dn )
 {
@@ -270,21 +429,8 @@ be_isroot_pw( Backend *be, char *ndn, struct berval *cred )
 	return result == 0;
 }
 
-void
-be_close( void )
-{
-	int	i;
-
-	for ( i = 0; i < nbackends; i++ ) {
-		if ( backends[i].be_close != NULL ) {
-			(*backends[i].be_close)( &backends[i] );
-		}
-	}
-}
-
-
-void
-be_unbind(
+int
+backend_unbind(
 	Connection   *conn,
 	Operation    *op
 )
@@ -296,11 +442,13 @@ be_unbind(
 			(*backends[i].be_unbind)( &backends[i], conn, op );
 		}
 	}
+
+	return 0;
 }
 
 #ifdef SLAPD_ACLGROUPS
 int 
-be_group(
+backend_group(
 	Backend	*be,
 	Entry	*target,
 	char	*gr_ndn,
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index b810460680..306b6d9b83 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -29,32 +29,35 @@ char   *slapd_args_file = NULL;
 
 static char	*fp_getline(FILE *fp, int *lineno);
 static void	fp_getline_init(int *lineno);
-static void	fp_parse_line(char *line, int *argcp, char **argv);
+static int	fp_parse_line(char *line, int *argcp, char **argv);
 
 static char	*strtok_quote(char *line, char *sep);
 
-void
-read_config( char *fname, Backend **bep, FILE *pfp )
+int
+read_config( char *fname )
 {
 	FILE	*fp;
 	char	*line, *savefname;
 	int	cargc, savelineno;
 	char	*cargv[MAXARGS];
 	int	lineno, i;
-	Backend	*be;
 
-	if ( (fp = pfp) == NULL && (fp = fopen( fname, "r" )) == NULL ) {
+	static BackendInfo *bi = NULL;
+	static BackendDB	*be = NULL;
+
+	if ( (fp = fopen( fname, "r" )) == NULL ) {
 		ldap_syslog = 1;
 		Debug( LDAP_DEBUG_ANY,
 		    "could not open config file \"%s\" - absolute path?\n",
 		    fname, 0, 0 );
 		perror( fname );
-		exit( 1 );
+		return 1;
 	}
 
 	Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0 );
-	be = *bep;
+
 	fp_getline_init( &lineno );
+
 	while ( (line = fp_getline( fp, &lineno )) != NULL ) {
 		/* skip comments and blank lines */
 		if ( line[0] == '#' || line[0] == '\0' ) {
@@ -63,7 +66,9 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 
 		Debug( LDAP_DEBUG_CONFIG, "line %d (%s)\n", lineno, line, 0 );
 
-		fp_parse_line( line, &cargc, cargv );
+		if ( fp_parse_line( line, &cargc, cargv ) != 0 ) {
+			return( 1 );
+		}
 
 		if ( cargc < 1 ) {
 			Debug( LDAP_DEBUG_ANY,
@@ -72,16 +77,33 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 			continue;
 		}
 
+		if ( strcasecmp( cargv[0], "backend" ) == 0 ) {
+			if ( cargc < 2 ) {
+				Debug( LDAP_DEBUG_ANY,
+		"%s: line %d: missing type in \"backend <type>\" line\n",
+				    fname, lineno, 0 );
+				return( 1 );
+			}
+
+			if( be != NULL ) {
+				Debug( LDAP_DEBUG_ANY,
+"%s: line %d: backend line must appear before any database definition\n",
+				    fname, lineno, 0 );
+				return( 1 );
+			}
+
+			bi = backend_info( cargv[1] );
+
 		/* start of a new database definition */
-		if ( strcasecmp( cargv[0], "database" ) == 0 ) {
+		} else if ( strcasecmp( cargv[0], "database" ) == 0 ) {
 			if ( cargc < 2 ) {
 				Debug( LDAP_DEBUG_ANY,
 		"%s: line %d: missing type in \"database <type>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
-			*bep = new_backend( cargv[1] );
-			be = *bep;
+			bi = NULL;
+			be = backend_db_init( cargv[1] );
 
  		/* assign a default depth limit for alias deref */
 		be->be_maxDerefDepth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
@@ -92,7 +114,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing file name in \"pidfile <file>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 
 			slapd_pid_file = ch_strdup( cargv[1] );
@@ -103,7 +125,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing file name in \"argsfile <file>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 
 			slapd_args_file = ch_strdup( cargv[1] );
@@ -114,7 +136,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing limit in \"sizelimit <limit>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				defsize = atoi( cargv[1] );
@@ -128,7 +150,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing limit in \"timelimit <limit>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				deftime = atoi( cargv[1] );
@@ -142,7 +164,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 		    "%s: line %d: missing dn in \"suffix <dn>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			} else if ( cargc > 2 ) {
 				Debug( LDAP_DEBUG_ANY,
     "%s: line %d: extra cruft after <dn> in \"suffix %s\" line (ignored)\n",
@@ -164,12 +186,12 @@ read_config( char *fname, Backend **bep, FILE *pfp )
                                 Debug( LDAP_DEBUG_ANY,
                     "%s: line %d: missing alias and aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
                                     fname, lineno, 0 );
-                                exit( 1 );
+                                return( 1 );
                         } else if ( cargc < 3 ) {
                                 Debug( LDAP_DEBUG_ANY,
                     "%s: line %d: missing aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
                                     fname, lineno, 0 );
-                                exit( 1 );
+                                return( 1 );
                         } else if ( cargc > 3 ) {
                                 Debug( LDAP_DEBUG_ANY,
     "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
@@ -210,7 +232,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
                                Debug( LDAP_DEBUG_ANY,
                    "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
                                    fname, lineno, 0 );
-                               exit( 1 );
+                               return( 1 );
                        }
                        if ( be == NULL ) {
                                Debug( LDAP_DEBUG_ANY,
@@ -227,7 +249,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 		    "%s: line %d: missing dn in \"rootdn <dn>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				Debug( LDAP_DEBUG_ANY,
@@ -244,7 +266,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing passwd in \"rootpw <passwd>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				Debug( LDAP_DEBUG_ANY,
@@ -260,7 +282,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing on|off in \"readonly <on|off>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				Debug( LDAP_DEBUG_ANY,
@@ -280,7 +302,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 		    "%s: line %d: missing URL in \"referral <URL>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			default_referral = (char *) ch_malloc( strlen( cargv[1] )
 			    + sizeof("Referral:\n") + 1 );
@@ -302,7 +324,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
     "%s: line %d: missing on|off in \"schemacheck <on|off>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( strcasecmp( cargv[1], "on" ) == 0 ) {
 				global_schemacheck = 1;
@@ -320,7 +342,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing limit in \"defaultaccess <access>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				if ( (global_default_access =
@@ -328,7 +350,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 					Debug( LDAP_DEBUG_ANY,
 "%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
 					    fname, lineno, cargv[1] );
-					exit( 1 );
+					return( 1 );
 				}
 			} else {
 				if ( (be->be_dfltaccess =
@@ -336,7 +358,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 					Debug( LDAP_DEBUG_ANY,
 "%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
 					    fname, lineno, cargv[1] );
-					exit( 1 );
+					return( 1 );
 				}
 			}
 
@@ -346,7 +368,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 		    "%s: line %d: missing level in \"loglevel <level>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			ldap_syslog = atoi( cargv[1] );
 
@@ -356,7 +378,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing host in \"replica <host[:port]>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				Debug( LDAP_DEBUG_ANY,
@@ -384,7 +406,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 		    "%s: line %d: missing dn in \"updatedn <dn>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be == NULL ) {
 				Debug( LDAP_DEBUG_ANY,
@@ -401,7 +423,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing dn in \"replogfile <filename>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( be ) {
 				be->be_replogfile = ch_strdup( cargv[1] );
@@ -415,7 +437,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing on|off in \"lastmod <on|off>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			if ( strcasecmp( cargv[1], "on" ) == 0 ) {
 				if ( be )
@@ -435,12 +457,15 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
     "%s: line %d: missing filename in \"include <filename>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			savefname = ch_strdup( cargv[1] );
 			savelineno = lineno;
-			read_config( savefname, bep, NULL );
-			be = *bep;
+
+			if ( read_config( savefname ) != 0 ) {
+				return( 1 );
+			}
+
 			free( savefname );
 			lineno = savelineno - 1;
 
@@ -450,30 +475,47 @@ read_config( char *fname, Backend **bep, FILE *pfp )
 				Debug( LDAP_DEBUG_ANY,
 	    "%s: line %d: missing filename in \"srvtab <filename>\" line\n",
 				    fname, lineno, 0 );
-				exit( 1 );
+				return( 1 );
 			}
 			ldap_srvtab = ch_strdup( cargv[1] );
 
-		/* pass anything else to the current backend config routine */
+		/* pass anything else to the current backend info/db config routine */
 		} else {
-			if ( be == NULL ) {
-				Debug( LDAP_DEBUG_ANY,
-"%s: line %d: unknown directive \"%s\" outside database definition (ignored)\n",
-				    fname, lineno, cargv[0] );
-			} else if ( be->be_config == NULL ) {
+			if ( bi != NULL ) {
+				if (bi->bi_config == NULL) {
+					Debug( LDAP_DEBUG_ANY,
+"%s: line %d: unknown directive \"%s\" inside backend info definition (ignored)\n",
+				   		fname, lineno, cargv[0] );
+				} else {
+					if ( (*bi->bi_config)( bi, fname, lineno, cargc, cargv )
+						!= 0 )
+					{
+						return( 1 );
+					}
+				}
+			} else if ( be != NULL ) {
+				if ( be->be_config == NULL ) {
+					Debug( LDAP_DEBUG_ANY,
+"%s: line %d: unknown directive \"%s\" inside backend database definition (ignored)\n",
+				    	fname, lineno, cargv[0] );
+				} else {
+					if ( (*be->be_config)( be, fname, lineno, cargc, cargv )
+						!= 0 )
+					{
+						return( 1 );
+					}
+				}
+			} else {
 				Debug( LDAP_DEBUG_ANY,
-"%s: line %d: unknown directive \"%s\" inside database definition (ignored)\n",
+"%s: line %d: unknown directive \"%s\" outside backend info and database definitions (ignored)\n",
 				    fname, lineno, cargv[0] );
-			} else {
-				(*be->be_config)( be, fname, lineno, cargc,
-				    cargv );
 			}
 		}
 	}
 	fclose( fp );
 }
 
-static void
+static int
 fp_parse_line(
     char	*line,
     int		*argcp,
@@ -488,11 +530,12 @@ fp_parse_line(
 		if ( *argcp == MAXARGS ) {
 			Debug( LDAP_DEBUG_ANY, "Too many tokens (max %d)\n",
 			    MAXARGS, 0, 0 );
-			exit( 1 );
+			return( 1 );
 		}
 		argv[(*argcp)++] = token;
 	}
 	argv[*argcp] = NULL;
+	return 0;
 }
 
 static char *
diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c
index 8ed04295fc..aaed6b7cc4 100644
--- a/servers/slapd/daemon.c
+++ b/servers/slapd/daemon.c
@@ -390,18 +390,6 @@ slapd_daemon(
 	}
 	ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
 
-	/* let backends do whatever cleanup they need to do */
-	Debug( LDAP_DEBUG_TRACE,
-	    "slapd shutdown: closing each backends.\n",
-	    0, 0, 0 );
-	be_close();
-
-	Debug( LDAP_DEBUG_TRACE,
-	    "slapd shutdown: shutdown backends.\n",
-	    0, 0, 0 );
-	/* be_shutdown(); */
-	Debug( LDAP_DEBUG_ANY, "slapd: stopped\n", 0, 0, 0 );
-
 	return NULL;
 }
 
diff --git a/servers/slapd/init.c b/servers/slapd/init.c
index 2b6cd5a725..5f7e6a3ef8 100644
--- a/servers/slapd/init.c
+++ b/servers/slapd/init.c
@@ -61,9 +61,38 @@ ldap_pvt_thread_mutex_t	num_sent_mutex;
 ldap_pvt_thread_mutex_t	entry2str_mutex;
 ldap_pvt_thread_mutex_t	replog_mutex;
 
-void
-init( void )
+static char* slap_name;
+int slapMode = 0;
+
+int
+slap_init( int mode, char *name )
 {
+	int rc;
+
+	if( slapMode ) {
+		Debug( LDAP_DEBUG_ANY,
+	   	 "%s init: init called twice (old=%d, new=%d)\n",
+	   	 name, slapMode, mode );
+		return 1;
+	}
+
+	slapMode = mode;
+
+	if(!slapMode) {
+		Debug( LDAP_DEBUG_ANY,
+	   	 "%s init: undefined mode (%d).\n",
+	   	 name, mode, 0 );
+		return 1;
+	}
+
+	Debug( LDAP_DEBUG_TRACE,
+		"%s init: initiated %s.\n",
+		name,
+		mode == SLAP_SERVER_MODE ? "server" : "tool",
+		0 );
+
+	slap_name = name;
+	
 	(void) ldap_pvt_thread_initialize();
 
 	ldap_pvt_thread_mutex_init( &active_threads_mutex );
@@ -78,4 +107,50 @@ init( void )
 #ifdef SLAPD_CRYPT
 	ldap_pvt_thread_mutex_init( &crypt_mutex );
 #endif
+
+	rc = backend_init();
+
+	return rc;
+}
+
+int slap_startup(int dbnum)
+{
+	int rc;
+
+	Debug( LDAP_DEBUG_TRACE,
+		"%s startup: initiated.\n",
+		slap_name, 0, 0 );
+
+	rc = backend_startup(dbnum);
+
+	return rc;
+}
+
+int slap_shutdown(int dbnum)
+{
+	int rc;
+
+	Debug( LDAP_DEBUG_TRACE,
+		"%s shutdown: initiated\n",
+		slap_name, 0, 0 );
+
+	/* let backends do whatever cleanup they need to do */
+	rc = backend_shutdown(dbnum); 
+
+	return rc;
 }
+
+int slap_destroy(void)
+{
+	int rc;
+
+	Debug( LDAP_DEBUG_TRACE,
+		"%s shutdown: freeing system resources.\n",
+		slap_name, 0, 0 );
+
+	rc = backend_destroy();
+
+	/* should destory the above mutex */
+	return rc;
+}
+
diff --git a/servers/slapd/main.c b/servers/slapd/main.c
index 3a2a136c27..67de0a0fda 100644
--- a/servers/slapd/main.c
+++ b/servers/slapd/main.c
@@ -22,17 +22,14 @@
 #define DEFAULT_SYSLOG_USER  LOG_LOCAL4
 
 typedef struct _str2intDispatch {
-
-        char    *stringVal;
-        int      abbr;
-        int      intVal;
-
+	char    *stringVal;
+	int      abbr;
+	int      intVal;
 } STRDISP, *STRDISP_P;
 
 
 /* table to compute syslog-options to integer */
 static STRDISP  syslog_types[] = {
-
     { "LOCAL0",         6, LOG_LOCAL0 },
     { "LOCAL1",         6, LOG_LOCAL1 },
     { "LOCAL2",         6, LOG_LOCAL2 },
@@ -42,7 +39,6 @@ static STRDISP  syslog_types[] = {
     { "LOCAL6",         6, LOG_LOCAL6 },
     { "LOCAL7",         6, LOG_LOCAL7 },
     NULL
-
 };
 
 static int   cnvt_str2int();
@@ -65,10 +61,9 @@ main( int argc, char **argv )
 {
 	int		i;
 	int		inetd = 0;
+	int		rc = 0;
 	int		port;
 	int		udp;
-	Backend		*be = NULL;
-	FILE		*fp = NULL;
 #ifdef LOG_LOCAL4
     int     syslogUser = DEFAULT_SYSLOG_USER;
 #endif
@@ -171,28 +166,36 @@ main( int argc, char **argv )
 		serverName = ch_strdup( serverName + 1 );
 	}
 
-	if ( ! inetd ) {
-		/* pre-open config file before detach in case it is a relative path */
-		fp = fopen( configfile, "r" );
-#ifdef LDAP_DEBUG
-		lutil_detach( ldap_debug, 0 );
-#else
-		lutil_detach( 0, 0 );
-#endif
-	}
-
 #ifdef LOG_LOCAL4
 	openlog( serverName, OPENLOG_OPTIONS, syslogUser );
 #else
 	openlog( serverName, OPENLOG_OPTIONS );
 #endif
 
-	init();
-	read_config( configfile, &be, fp );
+	if ( slap_init( SLAP_SERVER_MODE, serverName ) != 0 ) {
+		rc = 1;
+		goto destroy;
+	}
+
+	if ( read_config( configfile ) != 0 ) {
+		rc = 1;
+		goto destroy;
+	}
+
+	if ( slap_startup(-1)  != 0 ) {
+		rc = 1;
+		goto shutdown;
+	}
 
 	if ( ! inetd ) {
 		int		status;
 
+#ifdef LDAP_DEBUG
+		lutil_detach( ldap_debug, 0 );
+#else
+		lutil_detach( 0, 0 );
+#endif
+
 		time( &starttime );
 
 		if ( status = ldap_pvt_thread_create( &listener_tid, 0,
@@ -200,13 +203,13 @@ main( int argc, char **argv )
 		{
 			Debug( LDAP_DEBUG_ANY,
 			    "listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
-			exit( 1 );
-		}
 
-		/* wait for the listener thread to complete */
-		ldap_pvt_thread_join( listener_tid, (void *) NULL );
+			rc = 1;
+		} else {
 
-		return 0;
+			/* wait for the listener thread to complete */
+			ldap_pvt_thread_join( listener_tid, (void *) NULL );
+		}
 
 	} else {
 		Connection		c;
@@ -288,7 +291,12 @@ main( int argc, char **argv )
 			ber_free( &ber, 1 );
 		}
 	}
-	return 1;
+
+shutdown:
+	slap_shutdown(-1);
+destroy:
+	slap_destroy();
+	return rc;
 }
 
 
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 6b38c81e92..a024b9a723 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -58,13 +58,27 @@ void ava_free LDAP_P(( Ava *ava, int freeit ));
  * backend.c
  */
 
-Backend * new_backend LDAP_P(( char *type ));
-Backend * select_backend LDAP_P(( char * dn ));
+int backend_init LDAP_P((void));
+int backend_startup LDAP_P((int dbnum));
+int backend_shutdown LDAP_P((int dbnum));
+int backend_destroy LDAP_P((void));
+
+BackendInfo * backend_info LDAP_P(( char *type ));
+BackendDB * backend_db_init LDAP_P(( char *type ));
+
+BackendDB * select_backend LDAP_P(( char * dn ));
+
 int be_issuffix LDAP_P(( Backend *be, char *suffix ));
 int be_isroot LDAP_P(( Backend *be, char *ndn ));
 int be_isroot_pw LDAP_P(( Backend *be, char *ndn, struct berval *cred ));
 char* be_root_dn LDAP_P(( Backend *be ));
-void be_close LDAP_P(( void ));
+
+extern int	backend_unbind LDAP_P((Connection *conn, Operation *op));
+
+extern int	backend_group LDAP_P((Backend *be,
+	Entry *target,
+	char *gr_ndn, char *op_ndn,
+	char *objectclassValue, char *groupattrName));
 
 /*
  * ch_malloc.c
@@ -90,7 +104,7 @@ char ** str2charray LDAP_P(( char *str, char *brkstr ));
  * config.c
  */
 
-void read_config LDAP_P(( char *fname, Backend **bep, FILE *pfp ));
+int read_config LDAP_P(( char *fname ));
 
 /*
  * connection.c
@@ -266,11 +280,13 @@ extern struct acl	*global_acl;
 extern struct objclass	*global_oc;
 extern time_t		currenttime;
 
-extern int	be_group LDAP_P((Backend *be, Entry *target,
-	char *gr_ndn, char *op_ndn,
-	char *objectclassValue, char *groupattrName));
-extern void	init LDAP_P((void));
-extern void	be_unbind LDAP_P((Connection *conn, Operation *op));
+extern int	slap_init LDAP_P((int mode, char* name));
+extern int	slap_startup LDAP_P((int dbnum));
+extern int	slap_shutdown LDAP_P((int dbnum));
+extern int	slap_destroy LDAP_P((void));
+
+extern void *	slapd_daemon LDAP_P((void *port));
+
 extern void	config_info LDAP_P((Connection *conn, Operation *op));
 extern void	do_abandon LDAP_P((Connection *conn, Operation *op));
 extern void	do_add LDAP_P((Connection *conn, Operation *op));
@@ -281,10 +297,7 @@ extern void	do_modify LDAP_P((Connection *conn, Operation *op));
 extern void	do_modrdn LDAP_P((Connection *conn, Operation *op));
 extern void	do_search LDAP_P((Connection *conn, Operation *op));
 extern void	do_unbind LDAP_P((Connection *conn, Operation *op));
-extern void *	slapd_daemon LDAP_P((void *port));
 
-extern int		nbackends;
-extern Backend		*backends;
 extern int send_search_entry LDAP_P((Backend *be, Connection *conn, Operation *op, Entry *e, char **attrs, int attrsonly));
 extern int str2result LDAP_P(( char *s, int *code, char **matched, char **info ));
 
@@ -294,64 +307,5 @@ extern int		dtblsize;
 extern time_t		starttime;
 #endif
 
-#ifdef SLAPD_LDBM
-extern int  ldbm_back_bind   LDAP_P((Backend *be,
-	Connection *c, Operation *o,
-	char *dn, int method, struct berval *cred, char** edn ));
-extern void ldbm_back_unbind LDAP_P((Backend *be, Connection *c, Operation *o ));
-extern int  ldbm_back_search LDAP_P((Backend *be, Connection *c, Operation *o, char *base, int scope, int deref, int slimit, int tlimit, Filter *f, char *filterstr, char **attrs, int attrsonly));
-extern int  ldbm_back_compare LDAP_P((Backend *be, Connection *c, Operation *o, char *dn, Ava *ava));
-extern int  ldbm_back_modify LDAP_P((Backend *be, Connection *c, Operation *o, char *dn, LDAPModList *ml));
-extern int  ldbm_back_modrdn LDAP_P((Backend *be, Connection *c, Operation *o, char *dn, char *newrdn, int deleteoldrdn ));
-extern int  ldbm_back_add    LDAP_P((Backend *be, Connection *c, Operation *o, Entry *e));
-extern int  ldbm_back_delete LDAP_P((Backend *be, Connection *c, Operation *o, char *dn));
-extern void ldbm_back_abandon LDAP_P((Backend *be, Connection *c, Operation *o, int msgid));
-extern void ldbm_back_config LDAP_P((Backend *be, char *fname, int lineno, int argc, char **argv ));
-extern void ldbm_back_init   LDAP_P((Backend *be));
-extern void ldbm_back_close  LDAP_P((Backend *be));
-extern int  ldbm_back_group  LDAP_P((Backend *be, Entry *target,
-	char *gr_ndn, char *op_ndn,
-	char *objectclassValue, char *groupattrName ));
-#endif
-
-#ifdef SLAPD_PASSWD
-extern int  passwd_back_search LDAP_P((Backend *be, Connection *c, Operation *o, char *base, int scope, int deref, int slimit, int tlimit, Filter *f, char *filterstr, char **attrs, int attrsonly));
-extern void passwd_back_config LDAP_P((Backend *be, char *fname, int lineno, int argc, char **argv ));
-#endif
-
-#ifdef SLAPD_SHELL
-extern int  shell_back_bind   LDAP_P((Backend *be,
-	Connection *c, Operation *o,
-	char *dn, int method, struct berval *cred, char** edn ));
-extern void shell_back_unbind LDAP_P((Backend *be, Connection *c, Operation *o ));
-extern int  shell_back_search LDAP_P((Backend *be, Connection *c, Operation *o, char *base, int scope, int deref, int slimit, int tlimit, Filter *f, char *filterstr, char **attrs, int attrsonly));
-extern int  shell_back_compare LDAP_P((Backend *be, Connection *c, Operation *o, char *dn, Ava *ava));
-extern int  shell_back_modify LDAP_P((Backend *be, Connection *c, Operation *o, char *dn, LDAPModList *m));
-extern int  shell_back_modrdn LDAP_P((Backend *be, Connection *c, Operation *o, char *dn, char *newrdn, int deleteoldrdn ));
-extern int  shell_back_add    LDAP_P((Backend *be, Connection *c, Operation *o, Entry *e));
-extern int  shell_back_delete LDAP_P((Backend *be, Connection *c, Operation *o, char *dn));
-extern void shell_back_abandon LDAP_P((Backend *be, Connection *c, Operation *o, int msgid));
-extern void shell_back_config LDAP_P((Backend *be, char *fname, int lineno, int argc, char **argv ));
-extern void shell_back_init   LDAP_P((Backend *be));
-#endif
-
-#ifdef SLAPD_PERL
-extern int perl_back_bind LDAP_P(( Backend *be,
-	Connection *conn, Operation *op,
-	char *dn, int method, struct berval *cred, char** edn ));
-extern void	perl_back_unbind LDAP_P(( Backend *be, Connection *conn, Operation *op ));
-extern int	perl_back_search LDAP_P(( Backend *be, Connection *conn, Operation *op, char *base, int scope, int deref, int sizelimit, int timelimit,  Filter *filter, char *filterstr, char **attrs, int attrsonly ));
-extern int	perl_back_compare LDAP_P((Backend *be, Connection *conn, Operation *op, char *dn, Ava 	*ava ));
-extern int	perl_back_modify LDAP_P(( Backend *be, Connection *conn, Operation *op, char *dn, LDAPModList *ml ));
-extern int	perl_back_modrdn LDAP_P(( Backend *be, Connection *conn, Operation *op, char *dn, char*newrdn, int deleteoldrdn ));
-extern int	perl_back_add LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e ));
-extern int	perl_back_delete LDAP_P(( Backend *be, Connection *conn, Operation *op, char *dn ));
-/* extern int	perl_back_abandon(); */
-extern void	perl_back_config LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
-extern void	perl_back_init LDAP_P(( Backend *be ));
-extern void	perl_back_close LDAP_P(( Backend *be ));
-/* extern int      perl_back_group(); */
-#endif 
-
 #endif /* _proto_slap */
 
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index a977323860..10f0135bf2 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -227,18 +227,54 @@ struct objclass {
 };
 
 /*
- * represents a "database"
+ * Backend-info
+ * represents a backend 
  */
 
-typedef struct backend Backend;
-struct backend {
+typedef struct backend_info BackendInfo;	/* per backend type */
+typedef struct backend_db BackendDB;		/* per backend database */
+
+extern int nBackendInfo;
+extern int nBackendDB;
+extern BackendInfo	*backendInfo;
+extern BackendDB	*backendDB;
+
+extern int			slapMode;	
+#define SLAP_UNDEFINED_MODE	0
+#define SLAP_SERVER_MODE	1
+#define SLAP_TOOL_MODE		2
+
+/* temporary aliases */
+typedef BackendDB Backend;
+#define nbackends nBackendDB
+#define backends backendDB
+
+struct backend_db {
+	BackendInfo	*bd_info;	/* pointer to shared backend info */
+
+	/* BackendInfo accessors */
+#define		be_config	bd_info->bi_db_config
+#define		be_type		bd_info->bi_type
+
+#define		be_bind		bd_info->bi_op_bind
+#define		be_unbind	bd_info->bi_op_unbind
+#define		be_add		bd_info->bi_op_add
+#define		be_compare	bd_info->bi_op_compare
+#define		be_delete	bd_info->bi_op_delete
+#define		be_modify	bd_info->bi_op_modify
+#define		be_modrdn	bd_info->bi_op_modrdn
+#define		be_search	bd_info->bi_op_search
+
+#define		be_group	bd_info->bi_acl_group
+
+	/* these should be renamed from be_ to bd_ */
 	char	**be_suffix;	/* the DN suffixes of data in this backend */
-        char    **be_suffixAlias;       /* the DN suffix aliases of data in this backend */
+	char    **be_suffixAlias;       /* the DN suffix aliases of data in this backend */
 	char	*be_root_dn;	/* the magic "root" dn for this db 	*/
 	char	*be_root_ndn;	/* the magic "root" normalized dn for this db	*/
 	char	*be_root_pw;	/* the magic "root" password for this db	*/
 	int	be_readonly;	/* 1 => db is in "read only" mode	   */
-        int     be_maxDerefDepth;       /* limit for depth of an alias deref  */
+	int     be_maxDerefDepth;       /* limit for depth of an alias deref  */
 	int	be_sizelimit;	/* size limit for this backend   	   */
 	int	be_timelimit;	/* time limit for this backend       	   */
 	struct acl *be_acl;	/* access control list for this backend	   */
@@ -247,49 +283,106 @@ struct backend {
 	char	*be_replogfile;	/* replication log file (in master)	   */
 	char	*be_update_ndn;	/* allowed to make changes (in replicas)   */
 	int	be_lastmod;	/* keep track of lastmodified{by,time}	   */
-	char	*be_type;	/* type of database			   */
 
 	void	*be_private;	/* anything the backend needs 		   */
+};
+
+struct backend_info {
+	char	*bi_type;	/* type of backend */
 
-	/* backend routines */
-	int	(*be_bind)   LDAP_P((Backend *be,
+	/*
+	 * per backend type routines:
+	 * bi_init: called to allocate a backend_info structure,
+	 *		called once BEFORE configuration file is read.
+	 *		bi_init() initializes this structure hence is
+	 *		called directly from be_initialize()
+	 * bi_config: called per 'backend' specific option
+	 *		all such options must before any 'database' options
+	 *		bi_config() is called only from read_config()
+	 * bi_open: called to open each database, called
+	 *		once AFTER configuration file is read but
+	 *		BEFORE any bi_db_open() calls.
+	 *		bi_open() is called from backend_startup()
+	 * bi_close: called to close each database, called
+	 *		once during shutdown after all bi_db_close calls.
+	 *		bi_close() is called from backend_shutdown()
+	 * bi_destroy: called to destroy each database, called
+	 *		once during shutdown after all bi_db_destroy calls.
+	 *		bi_destory() is called from backend_destroy()
+	 */
+	int (*bi_init)	LDAP_P((BackendInfo *bi));
+	int	(*bi_config) LDAP_P((BackendInfo *bi,
+		char *fname, int lineno, int argc, char **argv ));
+	int (*bi_open) LDAP_P((BackendInfo *bi));
+	int (*bi_close) LDAP_P((BackendInfo *bi));
+	int (*bi_destroy) LDAP_P((BackendInfo *bi));
+
+	/*
+	 * per database routines:
+	 * bi_db_init: called to initialize each database,
+	 *	called upon reading 'database <type>' 
+	 *	called only from backend_db_init()
+	 * bi_db_config: called to configure each database,
+	 *  called per database to handle per database options
+	 *	called only from read_config()
+	 * bi_db_open: called to open each database
+	 *	called once per database immediately AFTER bi_open()
+	 *	calls but before daemon startup.
+	 *  called only by backend_startup()
+	 * bi_db_close: called to close each database
+	 *	called once per database during shutdown but BEFORE
+	 *  any bi_close call.
+	 *  called only by backend_shutdown()
+	 * bi_db_destroy: called to destroy each database
+	 *  called once per database during shutdown AFTER all
+	 *  bi_close calls but before bi_destory calls.
+	 *  called only by backend_destory()
+	 */
+	int (*bi_db_init) LDAP_P((Backend *bd));
+	int	(*bi_db_config) LDAP_P((Backend *bd,
+		char *fname, int lineno, int argc, char **argv ));
+	int (*bi_db_open) LDAP_P((Backend *bd));
+	int (*bi_db_close) LDAP_P((Backend *bd));
+	int (*bi_db_destroy) LDAP_P((Backend *db));
+
+	/* LDAP Operations Handling Routines */
+	int	(*bi_op_bind)  LDAP_P(( BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		char *dn, int method, struct berval *cred, char** edn ));
-	void	(*be_unbind) LDAP_P((Backend *be,
+	int (*bi_op_unbind) LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o ));
-	int	(*be_search) LDAP_P((Backend *be,
+	int	(*bi_op_search) LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		char *base, int scope, int deref, int slimit, int tlimit,
 		Filter *f, char *filterstr, char **attrs, int attrsonly));
-	int	(*be_compare)LDAP_P((Backend *be,
+	int	(*bi_op_compare)LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		char *dn, Ava *ava));
-	int	(*be_modify) LDAP_P((Backend *be,
+	int	(*bi_op_modify) LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		char *dn, LDAPModList *m));
-	int	(*be_modrdn) LDAP_P((Backend *be,
+	int	(*bi_op_modrdn) LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		char *dn, char *newrdn, int deleteoldrdn ));
-	int	(*be_add)    LDAP_P((Backend *be,
+	int	(*bi_op_add)    LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		Entry *e));
-	int	(*be_delete) LDAP_P((Backend *be,
+	int	(*bi_op_delete) LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		char *dn));
-	/* Bug: be_abandon in unused! */
-	void	(*be_abandon)LDAP_P((Backend *be,
+	/* Bug: be_op_abandon in unused! */
+	int	(*bi_op_abandon) LDAP_P((BackendDB *bd,
 		struct slap_conn *c, struct slap_op *o,
 		int msgid));
-	void	(*be_config) LDAP_P((Backend *be,
-		char *fname, int lineno, int argc, char **argv ));
-	void	(*be_init)   LDAP_P((Backend *be));
-	void	(*be_close)  LDAP_P((Backend *be));
 
+	/* Auxilary Functions */
 #ifdef SLAPD_ACLGROUPS
-	int	(*be_group)  LDAP_P((Backend *be, Entry *e,
-		char *bdn, char *edn,
+	int	(*bi_acl_group)  LDAP_P((Backend *bd,
+		Entry *e, char *bdn, char *edn,
 		char *objectclassValue, char *groupattrName ));
 #endif
+
+	void	*bi_private;	/* anything the backend needs */
 };
 
 /*
diff --git a/servers/slapd/tools/ldbmtest.c b/servers/slapd/tools/ldbmtest.c
index afdd148ee0..5fd7119dad 100644
--- a/servers/slapd/tools/ldbmtest.c
+++ b/servers/slapd/tools/ldbmtest.c
@@ -80,8 +80,9 @@ main( int argc, char **argv )
 	 * initialize stuff and figure out which backend we're dealing with
 	 */
 
-	init();
-	read_config( tailorfile, &be, NULL );
+	slap_init(SLAP_TOOL_MODE, "ldbmtest");
+	read_config( tailorfile );
+	slap_startup(-1);
 
 	while ( 1 ) {
 		printf( "dbtest: " );
@@ -357,6 +358,9 @@ main( int argc, char **argv )
 		}
 	}
 
+	slap_shutdown(-1);
+	slap_destroy();
+
 	return( 0 );
 }
 
diff --git a/servers/slapd/tools/ldif2id2children.c b/servers/slapd/tools/ldif2id2children.c
index f15fb5ac32..484125cb90 100644
--- a/servers/slapd/tools/ldif2id2children.c
+++ b/servers/slapd/tools/ldif2id2children.c
@@ -83,8 +83,8 @@ main( int argc, char **argv )
 	 * initialize stuff and figure out which backend we're dealing with
 	 */
 
-	init();
-	read_config( tailorfile, &be, NULL );
+	slap_init(SLAP_TOOL_MODE, "ldif2id2children");
+	read_config( tailorfile );
 
 	if ( dbnum == -1 ) {
 		for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
@@ -105,6 +105,8 @@ main( int argc, char **argv )
 		fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
 		exit( 1 );
 	}
+
+	slap_startup(dbnum);
 	be = &backends[dbnum];
 
 	/* disable write sync'ing */
@@ -301,7 +303,9 @@ main( int argc, char **argv )
 			line[0] = '\0';
 		}
 	}
-	(*be->be_close)( be );
+
+	slap_shutdown(dbnum);
+	slap_destroy();
 
 	exit( 0 );
 }
diff --git a/servers/slapd/tools/ldif2id2entry.c b/servers/slapd/tools/ldif2id2entry.c
index 96ed84ffe3..25a9d9ee20 100644
--- a/servers/slapd/tools/ldif2id2entry.c
+++ b/servers/slapd/tools/ldif2id2entry.c
@@ -81,8 +81,8 @@ main( int argc, char **argv )
 	 * initialize stuff and figure out which backend we're dealing with
 	 */
 
-	init();
-	read_config( tailorfile, &be, NULL );
+	slap_init(SLAP_TOOL_MODE, "ldif2id2entry");
+	read_config( tailorfile );
 
 	if ( dbnum == -1 ) {
 		for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
@@ -103,6 +103,9 @@ main( int argc, char **argv )
 		fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
 		exit( 1 );
 	}
+
+	slap_startup(dbnum);
+
 	be = &backends[dbnum];
 
 	/* disable write sync'ing */
@@ -183,7 +186,8 @@ main( int argc, char **argv )
 			line[0] = '\0';
 		}
 	}
-	(*be->be_close)( be );
+
+	slap_shutdown(dbnum);
 
 	id++;
 	sprintf( line, "%s/NEXTID",
@@ -196,5 +200,7 @@ main( int argc, char **argv )
 		fclose( fp );
 	}
 
+	slap_destroy();
+
 	exit( 0 );
 }
diff --git a/servers/slapd/tools/ldif2index.c b/servers/slapd/tools/ldif2index.c
index 18f497f48f..6aa24891d7 100644
--- a/servers/slapd/tools/ldif2index.c
+++ b/servers/slapd/tools/ldif2index.c
@@ -77,8 +77,8 @@ main( int argc, char **argv )
 		}
 	}
 
-	init();
-	read_config( tailorfile, &be, NULL );
+	slap_init(SLAP_TOOL_MODE, ch_strdup(argv[0]));
+	read_config( tailorfile );
 
 	if ( dbnum == -1 ) {
 		for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
@@ -99,6 +99,9 @@ main( int argc, char **argv )
 		fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
 		exit( 1 );
 	}
+
+	slap_startup(dbnum);
+
 	be = &backends[dbnum];
 
 	/* disable write sync'ing */
@@ -166,7 +169,9 @@ main( int argc, char **argv )
 			lcur = 0;
 		}
 	}
-	(*be->be_close)( be );
+
+	slap_shutdown(dbnum);
+	slap_destroy();
 
 	exit( 0 );
 }
diff --git a/servers/slapd/tools/ldif2ldbm.c b/servers/slapd/tools/ldif2ldbm.c
index a3714161b9..9cbdf52b37 100644
--- a/servers/slapd/tools/ldif2ldbm.c
+++ b/servers/slapd/tools/ldif2ldbm.c
@@ -49,6 +49,7 @@ main( int argc, char **argv )
 	int      	lmax, lcur;
 	int		dbnum;
 	ID		id;
+	int		rc;
 	Backend		*be = NULL;
 	struct ldbminfo *li;
 	struct berval	bv;
@@ -103,8 +104,13 @@ main( int argc, char **argv )
 	 * initialize stuff and figure out which backend we're dealing with
 	 */
 
-	init();
-	read_config( tailorfile, &be, NULL );
+	rc = slap_init(SLAP_TOOL_MODE, "ldif2ldbm");
+	if (rc != 0 ) {
+		fprintf( stderr, "ldif2ldbm: slap_init failed!\n");
+		exit(1);
+	}
+
+	read_config( tailorfile );
 
 	if ( dbnum == -1 ) {
 		for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
@@ -125,6 +131,9 @@ main( int argc, char **argv )
 		fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
 		exit( 1 );
 	}
+
+	slap_startup(dbnum);
+
 	be = &backends[dbnum];
 
 	/* disable write sync'ing */
@@ -260,10 +269,13 @@ main( int argc, char **argv )
 			lcur = 0;
 		}
 	}
-	(*be->be_close)( be );
+
+	slap_shutdown(dbnum);
 
 	wait4kids( -1 );
 
+	slap_destroy();
+
 	exit( 0 );
 }
 
diff --git a/servers/slapd/unbind.c b/servers/slapd/unbind.c
index a4a8546812..1416393343 100644
--- a/servers/slapd/unbind.c
+++ b/servers/slapd/unbind.c
@@ -40,7 +40,7 @@ do_unbind(
 	    op->o_opid, 0, 0, 0 );
 
 	/* pass the unbind to all backends */
-	be_unbind( conn, op );
+	backend_unbind( conn, op );
 	
 	/* close the connection to the client */
 	close_connection( conn, op->o_connid, op->o_opid );
-- 
GitLab