[PATCH] module stuff (BIG patch :-)

Stefan (metze) Metzmacher metze at metzemix.de
Fri Jan 10 00:15:55 GMT 2003


Hi Jelmer,

here are the things I changed from the last patch:

in Makefile.in:

DATADIR = @datadir@  jht agree:-)

module stuff:
we now have a

#define SMB_MODULE_INIT_SYMBOL_STR "smb_module_init"
#define SMB_MODULE_INIT_SYMBOL           smb_module_init

maybe we could postfix a version number? ->
         SMB_MODULE_INIT_SYMBOL smb_module_init_0_0

we now have the same syntax for the smb_register_*() functions

NTSTATUS smb_register_<subsystem>(struct <subsystem>_function_entry *func, 
int interfaceversion);

so we never have to change the parameter of the smb_register_fn's
(the subsystem can change the struct and the interfaceversion, but we'll 
allways have:
NTSTATUS smb_register_fn(void *,int); )

CHARSET stuff:

change prototype
NTSTATUS  smb_register_charset(struct charset_function *func, int 
interfaceversion)

add CHARSET_INTERFACE_VERSION

PASSDB stuff:

change prototype
NTSTATUS  smb_register_passdb(struct pdb_backend_function_entry *func, int 
interfaceversion)

a module now registeres only a struct of function pointers and no init 
function.
there's a new *_init_private_data function that provides the initialisation

we have to get rid of the 'passdb backend = ldapsam:ldap://localhost/'
syntax, (but later if abartlet is back :-)

AUTH stuff:

NTSTATUS smb_register_auth(struct auth_method_function_entry *func, int 
interfaceversion)

a module now registers a struct of function pointers...(maybe we should add 
a init_private_data() as in PASSDB too)

add AUTH_INTERFACE_VERSION

the 'auth method = module:module_param' syntax is gone :-)

VFS stuff:

change the prototype
NTSTATUS  smb_register_vfs(struct vfs_object_function_entry *func, int 
interfaceversion)

we now have conn->vfs_objects (a DLIST with all vfs_objects of the connection)

each vfs module got a global id number, with this number or it's registered 
name it can search itsself in the list. and got it's default options , 
opaque options or any other operations from other modules of the connection.

for making it easy for module writers we have:

vfs_get_deafult_ops(conn,module_id)  to get a pointer to a vfs_ops struct
vfs_get_default_op(conn,module_id,operation_type) to get a pointer to a 
specified operation function

vfs_get_default_ops_by_name(conn,module_name)
vfs_get_default_ops_by_name(conn.module_name)

vfs_get_opaque_ops(conn)
vfs_get_opaque_op(conn,operation_type)

the vfs_init() and vfs_done() function are gone...
and only the vfs_op_tuple array is registered by each module.
( if the module needs to init private data it should be done in the connect 
and disconnect functions)

(tridge: I hope your happy now)

- 'vfs options' is removed ( parametric options should be used)
- 'vfs objects = <module1_name>{[<module2_name>]}

-----------------------
here th ething witch were in the last patch:

here is a new patch for the modules stuff, parametric options and new 
smb_register_vfs():

- it adds 'modules path' and 'modules' as per share parameter
    (vfs path is now an alias for modules path)

- it add two new parameters to the smb_load_modules function

int smb_load_modules(const char **modules, connection_struct *conn, 
SMB_MODULE_TYPES types)

conn == NULL - for the global section.

SMB_MODULE_TYPES types - this is the bitmask witch module types should be 
loaded here, ( we don't need a winsdb module in smbd... also 
smb_register_winsdb() is not linked to smbd, witch would cause trouble)


now we can use 
smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPE_CHARSET) 
to load the charsets before the fork in smbd

smb_load_modules(lp_modules(SNUM(conn)),SNUM(conn),MODULE_TYPE_VFS) for 
loading the vfs modules per share..


lp_module_path is dyn_LIBDIR by default...

lib_path() for loading upcase.dat,... is replaced by data_path() witch is 
default dyn_DATADIR

for making jerry and jht happy I use :
DATADIR = @libdir@     in Makefile.in but it should be changed to
DATADIR = @datadir@

%-Macros can be in 'modules path' and 'modules'

- parametric options now all take a default value.
  char *lp_param_string() and char **lp_param_string_list() can be used as 
every othere
  lp_* function with char * or char **
  you should not try to free() the return values of this function!!!

- smb_register_vfs()
    Each SAMBA module must provide following global function:
     init_module         -- module initalization function

         NTSTATUS init_module(SMB_MODULE_TYPES types)
         {
                 if (types & MODULE_TYPE_VFS) {
                         if (smb_register_vfs("recycle", vfs_recycle_init, 
VFS_INTERFACE_VERSION)) {
                                 return NT_STATUS_OK;
                         } else {
                                 return NT_STATUS_UNSUCCESSFUL;
                         }
                 }

                 return NT_STATUS_OK;
         }

     Each VFS module must provide following global function:
     vfs_*_init          -- vfs initialization function

     vfs_*_init (e.g. vfs_recycle_init ) must return proper initialized 
vfs_op_tuple[] array
     which describes all operations this module claims to intercept. This 
function
     is called whenever module is loaded into smbd process using sys_dlopen().

     vfs_*_init must have a list (indexed by the SNUM(conn) or CNUM(conn))
     for storing the default_vfs_ops and if module wants to store private
     information for further usage.

     Prototypes:
     vfs_op_tuple *vfs_recycle_init(struct connection_struct *conn, struct 
vfs_ops *default_vfs_ops, const char *param);


'vfs path' is removed
'vfs options' is removed ( parametric options should be used)

'vfs object' move to 'vfs objects'  ( but 'vfs object' is an alias)

'vfs objects = <module1_name>{[<module2_name>]}

- vfs_audit.c is installed as audit.so
- vfs_recycle.c is installed as recycle.so
- vfs_nettalk.c is installed as nettalk.so

vfs_audit.c and vfs_recycle.c  are now per connection safe
vfs_netatalk.c should be updated to use SMB_VFS_INTERFACE_VERSION 6 later


I have tested this patch this afternoon and I have no problems...

metze
-----------------------------------------------------------------------------
Stefan "metze" Metzmacher <metze at metzemix.de>
-------------- next part --------------
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/Makefile.in HEAD-modules/source/Makefile.in
--- HEAD/source/Makefile.in	Wed Dec 18 07:34:56 2002
+++ HEAD-modules/source/Makefile.in	Wed Dec 18 08:25:01 2002
@@ -52,6 +52,8 @@ PDBLIBDIR = $(LIBDIR)/pdb
 CONFIGDIR = @configdir@
 VARDIR = @localstatedir@
 MANDIR = @mandir@
+# This is where valid.dat,upcase.dat,lowcase.dat are installed and searched by default
+DATADIR = @datadir@
 
 # The permissions to give the executables
 INSTALLPERMS = 0755
@@ -94,12 +96,11 @@ FLAGS32  = $(ISA32) $(FLAGS5)
 
 PASSWD_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" -DPRIVATE_DIR=\"$(PRIVATE_DIR)\"
 PATH_FLAGS1 = -DCONFIGFILE=\"$(CONFIGFILE)\"  -DSBINDIR=\"$(SBINDIR)\"
-PATH_FLAGS2 = $(PATH_FLAGS1) -DBINDIR=\"$(BINDIR)\" -DDRIVERFILE=\"$(DRIVERFILE)\" 
-PATH_FLAGS3 = $(PATH_FLAGS2) -DLMHOSTSFILE=\"$(LMHOSTSFILE)\" 
-PATH_FLAGS4 = $(PATH_FLAGS3) -DSWATDIR=\"$(SWATDIR)\"  -DLOCKDIR=\"$(LOCKDIR)\" -DPIDDIR=\"$(PIDDIR)\"
-PATH_FLAGS5 = $(PATH_FLAGS4) -DLIBDIR=\"$(LIBDIR)\" -DLOGFILEBASE=\"$(LOGFILEBASE)\" 
-PATH_FLAGS6 = $(PATH_FLAGS5) -DCONFIGDIR=\"$(CONFIGDIR)\"
-PATH_FLAGS = $(PATH_FLAGS6) $(PASSWD_FLAGS)
+PATH_FLAGS2 = $(PATH_FLAGS1) -DBINDIR=\"$(BINDIR)\" -DLMHOSTSFILE=\"$(LMHOSTSFILE)\"
+PATH_FLAGS3 = $(PATH_FLAGS2) -DSWATDIR=\"$(SWATDIR)\"  -DLOCKDIR=\"$(LOCKDIR)\" -DPIDDIR=\"$(PIDDIR)\"
+PATH_FLAGS4 = $(PATH_FLAGS3) -DLIBDIR=\"$(LIBDIR)\" -DLOGFILEBASE=\"$(LOGFILEBASE)\"
+PATH_FLAGS5 = $(PATH_FLAGS4) -DCONFIGDIR=\"$(CONFIGDIR)\" -DDATADIR=\"$(DATADIR)\"
+PATH_FLAGS = $(PATH_FLAGS5) $(PASSWD_FLAGS)
 
 # Note that all executable programs now provide for an optional executable suffix.
 
@@ -127,7 +128,7 @@ SCRIPTS = $(srcdir)/script/smbtar $(srcd
 
 QUOTAOBJS=@QUOTAOBJS@
 
-VFS_MODULES = bin/vfs_audit. at SHLIBEXT@ bin/vfs_recycle. at SHLIBEXT@ bin/vfs_netatalk. at SHLIBEXT@ 
+VFS_MODULES = bin/audit. at SHLIBEXT@ bin/recycle_bin. at SHLIBEXT@ bin/netatalk. at SHLIBEXT@ 
 PDB_MODULES = @MODULE_MYSQL@ @MODULE_XML@
 MODULES = bin/developer. at SHLIBEXT@ 
 
@@ -874,17 +875,17 @@ bin/xml. at SHLIBEXT@: $(XML_OBJ)
 	@$(SHLD) $(LDSHFLAGS) -o $@ $(XML_OBJ) @XML_LIBS@ \
 		@SONAMEFLAG@`basename $@`
 
-bin/vfs_audit. at SHLIBEXT@: $(VFS_AUDIT_OBJ)
+bin/audit. at SHLIBEXT@: $(VFS_AUDIT_OBJ)
 	@echo "Building plugin $@"
 	@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ) \
 		@SONAMEFLAG@`basename $@`
 
-bin/vfs_recycle. at SHLIBEXT@: $(VFS_RECYCLE_OBJ)
+bin/recycle_bin. at SHLIBEXT@: $(VFS_RECYCLE_OBJ)
 	@echo "Building plugin $@"
 	@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_RECYCLE_OBJ) \
 		@SONAMEFLAG@`basename $@`
 
-bin/vfs_netatalk. at SHLIBEXT@: $(VFS_NETATALK_OBJ)
+bin/netatalk. at SHLIBEXT@: $(VFS_NETATALK_OBJ)
 	@echo "Building plugin $@"
 	@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NETATALK_OBJ) \
 		@SONAMEFLAG@`basename $@`
@@ -923,24 +924,28 @@ install: installbin installman installsc
 # is not used
 
 installdirs:
-	@$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(PRIVATEDIR) $(DESTDIR)$(VFSLIBDIR) $(DESTDIR)$(PDBLIBDIR)
+	@$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(DATADIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(PRIVATEDIR)
 
 installservers: all installdirs
-	@$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(SBIN_PROGS)
+	@$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(DATADIR) $(DESTDIR)$(VARDIR) $(SBIN_PROGS)
 
 installbin: all installdirs
-	@$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(SBIN_PROGS)
-	@$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(BIN_PROGS)
+	@$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(DATADIR) $(DESTDIR)$(VARDIR) $(SBIN_PROGS)
+	@$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(DATADIR) $(DESTDIR)$(VARDIR) $(BIN_PROGS)
 
-installmodules: all installdirs
+installmoduledirs:
+	@$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VFSLIBDIR) $(DESTDIR)$(PDBLIBDIR)
+
+installmodules: modules installmoduledirs
 	@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(VFSLIBDIR) $(VFS_MODULES)
 	@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(PDBLIBDIR) $(PDB_MODULES)
+	@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(LIBDIR) $(MODULES)
 
 installscripts: installdirs
 	@$(SHELL) $(srcdir)/script/installscripts.sh $(INSTALLPERMS) $(DESTDIR)$(BINDIR) $(SCRIPTS)
 
 installdat: installdirs
-	@$(SHELL) $(srcdir)/script/installdat.sh $(DESTDIR)$(LIBDIR) $(srcdir)
+	@$(SHELL) $(srcdir)/script/installdat.sh $(DESTDIR)$(DATADIR) $(srcdir)
 
 installswat: installdirs
 	@$(SHELL) $(srcdir)/script/installswat.sh $(DESTDIR)$(SWATDIR) $(srcdir)
@@ -1021,6 +1026,7 @@ showlayout: 
 	@echo "  libdir:  $(LIBDIR)"
 	@echo "  vardir:  $(VARDIR)"
 	@echo "  mandir:  $(MANDIR)"
+	@echo "  datadir: $(DATADIR)"
 
 
 uninstall: uninstallman uninstallbin uninstallscripts
@@ -1029,8 +1035,8 @@ uninstallman:
 	@$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) $(man_langs)
 
 uninstallbin:
-	@$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(SBIN_PROGS)
-	@$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(BIN_PROGS)
+	@$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(DATADIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(SBIN_PROGS)
+	@$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(DATADIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(BIN_PROGS)
 
 uninstallmodules:
 	@$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(VFSLIBDIR) $(DESTDIR)$(VFS_MODULES)
@@ -1045,7 +1051,7 @@ TOPFILES=dynconfig.o dynconfig.po
 
 clean: delheaders python_clean
 	-rm -f core */*~ *~ */*.o */*.po */*.po32 */*. at SHLIBEXT@ \
-		$(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(MODULES) .headers.stamp
+		$(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) .headers.stamp
 
 # Making this target will just make sure that the prototype files
 # exist, not necessarily that they are up to date.  Since they're
@@ -1135,7 +1141,7 @@ ctags:
 	ctags `find $(srcdir) -name "*.[ch]" | grep -v /CVS/`
 
 realclean: clean delheaders
-	-rm -f config.log $(BIN_PROGS) $(MODULES) $(SBIN_PROGS) bin/.dummy script/findsmb
+	-rm -f config.log $(BIN_PROGS) $(SBIN_PROGS) bin/.dummy script/findsmb
 
 distclean: realclean
 	-rm -f include/stamp-h
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth.c HEAD-modules/source/auth/auth.c
--- HEAD/source/auth/auth.c	Thu Dec 12 20:24:26 2002
+++ HEAD-modules/source/auth/auth.c	Wed Dec 18 08:13:01 2002
@@ -1,7 +1,8 @@
 /* 
    Unix SMB/CIFS implementation.
    Password and authentication handling
-   Copyright (C) Andrew Bartlett         2001-2002
+   Copyright (C) Andrew Bartlett		2001-2002
+   Copyright (C) Stefan (metze) Metzmacher	2002
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -25,25 +26,90 @@
 
 /** List of various built-in authentication modules */
 
-const struct auth_init_function_entry builtin_auth_init_functions[] = {
-	{ "guest", auth_init_guest },
-	{ "rhosts", auth_init_rhosts },
-	{ "hostsequiv", auth_init_hostsequiv },
-	{ "sam", auth_init_sam },	
-	{ "samstrict", auth_init_samstrict },
-	{ "unix", auth_init_unix },
-	{ "smbserver", auth_init_smbserver },
-	{ "ntdomain", auth_init_ntdomain },
-	{ "trustdomain", auth_init_trustdomain },
-	{ "winbind", auth_init_winbind },
+extern struct auth_method_ops auth_guest_ops;
+extern struct auth_method_ops auth_rhosts_ops;
+extern struct auth_method_ops auth_hostsequiv_ops;
+extern struct auth_method_ops auth_sam_ops;
+extern struct auth_method_ops auth_samstrict_ops;
+extern struct auth_method_ops auth_samstrict_dc_ops;
+extern struct auth_method_ops auth_unix_ops;
+extern struct auth_method_ops auth_smbserver_ops;
+extern struct auth_method_ops auth_ntdomain_ops;
+extern struct auth_method_ops auth_trustdomain_ops;
+extern struct auth_method_ops auth_winbind_ops;
 #ifdef DEVELOPER
-	{ "name_to_ntstatus", auth_init_name_to_ntstatus },
-	{ "fixed_challenge", auth_init_fixed_challenge },
-#endif
-	{ "plugin", auth_init_plugin },
+extern struct auth_method_ops auth_name_to_ntstatus_ops;
+extern struct auth_method_ops auth_fixed_challenge_ops;
+#endif /* DEVELOPER */
+
+static struct auth_method_function_entry builtin_auth_methods[] = {
+	{ "guest", &auth_guest_ops},
+	{ "rhosts", &auth_rhosts_ops },
+	{ "hostsequiv", &auth_hostsequiv_ops },
+	{ "sam", &auth_sam_ops },	
+	{ "samstrict", &auth_samstrict_ops },
+	{ "samstrict_dc", &auth_samstrict_dc_ops },
+	{ "unix", &auth_unix_ops },
+	{ "smbserver", &auth_smbserver_ops },
+	{ "ntdomain", &auth_ntdomain_ops },
+	{ "trustdomain", &auth_trustdomain_ops },
+	{ "winbind", &auth_winbind_ops },
+#ifdef DEVELOPER
+	{ "name_to_ntstatus", &auth_name_to_ntstatus_ops },
+	{ "fixed_challenge", &auth_fixed_challenge_ops },
+#endif /* DEVELOPER */
 	{ NULL, NULL}
 };
 
+static struct auth_method_function_entry *global_auth_methods = NULL;
+
+static NTSTATUS smb_register_auth_method(struct auth_method_function_entry *func) 
+{
+	struct auth_method_function_entry *entry = global_auth_methods;
+
+	DEBUG(8,("Attempting to register auth method '%s'\n", func->name));
+
+	/* Check for duplicates */
+	while(entry) { 
+		if(strcasecmp(entry->name, func->name) == 0) { 
+			DEBUG(1,("smb_register_auth: There already is a auth method registered with the name %s!\n", func->name));
+			return NT_STATUS_OBJECT_NAME_COLLISION;
+		}
+		entry = entry->next;
+	}
+
+	DLIST_ADD(global_auth_methods, func);
+	DEBUG(10,("Successfully added auth_method '%s'\n", func->name));
+	return NT_STATUS_OK;
+}
+
+static void lazy_initialize_auth(void)
+{
+	int i;
+	static BOOL initialised = False;
+	
+	if(!initialised) {
+		initialised = True;
+
+		for(i = 0; builtin_auth_methods[i].name; i++) {
+			smb_register_auth_method(&builtin_auth_methods[i]);
+		}
+	}
+}
+
+NTSTATUS smb_register_auth(struct auth_method_function_entry *func, int version)
+{
+	/* make sure the builtin methods are loaded before any module */
+	lazy_initialize_auth();
+
+	if(version != AUTH_INTERFACE_VERSION){
+		DEBUG(0,("smb_register_auth: module '%s' has wrong the AUTH_INTERFACE_VERSION\n",func->name));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	return smb_register_auth_method(func);
+}
+
 /****************************************************************************
  Try to get a challenge out of the various authentication modules.
  Returns a const char of length 8 bytes.
@@ -53,7 +119,7 @@ static const uint8 *get_ntlm_challenge(s
 {
 	DATA_BLOB challenge = data_blob(NULL, 0);
 	char *challenge_set_by = NULL;
-	auth_methods *auth_method;
+	struct auth_methods *auth_method;
 	TALLOC_CTX *mem_ctx;
 
 	if (auth_context->challenge.length) {
@@ -62,7 +128,7 @@ static const uint8 *get_ntlm_challenge(s
 	}
 
 	for (auth_method = auth_context->auth_method_list; auth_method; auth_method = auth_method->next) {
-		if (auth_method->get_chal == NULL) {
+		if (auth_method->ops->get_chal==NULL) {
 			DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
 			continue;
 		}
@@ -79,7 +145,7 @@ static const uint8 *get_ntlm_challenge(s
 			smb_panic("talloc_init_named() failed!");
 		}
 		
-		challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx);
+		challenge = auth_method->ops->get_chal(auth_context, &auth_method->private_data, mem_ctx);
 		if (!challenge.length) {
 			DEBUG(3, ("auth_get_challenge: getting challenge from authentication method %s FAILED.\n", 
 				  auth_method->name));
@@ -135,7 +201,7 @@ static BOOL check_domain_match(const cha
 
 	if (!lp_allow_trusted_domains() &&
 	    !(strequal("", domain) || 
-	      strequal(lp_workgroup(), domain) || 
+	      is_myworkgroup(domain) || 
 	      is_myname(domain))) {
 		DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
 		return False;
@@ -179,7 +245,7 @@ static NTSTATUS check_ntlm_password(cons
 	
 	NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
 	const char *pdb_username;
-	auth_methods *auth_method;
+	struct auth_methods *auth_method;
 	TALLOC_CTX *mem_ctx;
 
 	if (!user_info || !auth_context || !server_info)
@@ -214,7 +280,12 @@ static NTSTATUS check_ntlm_password(cons
 		mem_ctx = talloc_init_named("%s authentication for user %s\\%s", auth_method->name, 
 					    user_info->domain.str, user_info->smb_name.str);
 
-		nt_status = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info);
+		if (auth_method->ops->auth == NULL) {
+			DEBUG(1,("check_ntlm_password: module '%s' have no auth function\n",auth_method->name));
+			continue;
+		}
+
+		nt_status = auth_method->ops->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info);
 		if (NT_STATUS_IS_OK(nt_status)) {
 			DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] suceeded\n", 
 				  auth_method->name, user_info->smb_name.str));
@@ -309,56 +380,84 @@ static NTSTATUS make_auth_context(struct
 }
 
 /***************************************************************************
- Make a auth_info struct for the auth subsystem
+ Make and init an auth_methods struct
 ***************************************************************************/
+static NTSTATUS make_auth_method(struct auth_context *auth_context, struct auth_methods **auth_method, struct auth_method_function_entry *entry)
+{
+	if (!auth_context) {
+		smb_panic("no auth_context supplied to make_auth_method()!\n");
+	}
+
+	if (!auth_method) {
+		smb_panic("make_auth_method: pointer to auth_method pointer is NULL!\n");
+	}
+
+	if (!entry) {
+		smb_panic("make_auth_method: pointer to entry pointer is NULL!\n");
+	}
+
+	if (!entry->ops||!entry->name) {
+		smb_panic("make_auth_method: entry->ops or entry->name pointer is NULL!\n");
+	}
+
+	if (((*auth_method) = (struct auth_methods *)talloc(auth_context->mem_ctx,sizeof(struct auth_methods)))==NULL) {
+		DEBUG(0,("make_auth_method: talloc failed\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ZERO_STRUCTP(*auth_method);
+
+	(*auth_method)->name	= entry->name;
+	(*auth_method)->ops	= entry->ops;
+ 	
+	return NT_STATUS_OK;
+}
 
 static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context, char **text_list) 
 {
-	auth_methods *list = NULL;
-	auth_methods *t = NULL;
-	auth_methods *tmp;
-	int i;
+	struct auth_methods *list = NULL;
+	struct auth_methods *tmp, *method = NULL;
+	struct auth_method_function_entry *entry;
+	int i = 0;
 	NTSTATUS nt_status;
 
 	if (!text_list) {
 		DEBUG(2,("make_auth_context_text_list: No auth method list!?\n"));
-		return NT_STATUS_UNSUCCESSFUL;
+		return NT_STATUS_INVALID_PARAMETER;
 	}
 	
-	if (!NT_STATUS_IS_OK(nt_status = make_auth_context(auth_context)))
+	if (NT_STATUS_IS_ERR(nt_status = make_auth_context(auth_context)))
 		return nt_status;
 	
-	for (;*text_list; text_list++) { 
-		DEBUG(5,("make_auth_context_text_list: Attempting to find an auth method to match %s\n",
+	lazy_initialize_auth();
+	
+	for (;*text_list; text_list++) {
+		BOOL found = False;
+		 
+		DEBUG(7,("make_auth_context_text_list: Attempting to find an auth method to match '%s'\n",
 					*text_list));
-		for (i = 0; builtin_auth_init_functions[i].name; i++) {
-			char *module_name = smb_xstrdup(*text_list);
-			char *module_params = NULL;
-			char *p;
-
-			p = strchr(module_name, ':');
-			if (p) {
-				*p = 0;
-				module_params = p+1;
-				trim_string(module_params, " ", " ");
-			}
-
-			trim_string(module_name, " ", " ");
-
-			if (strequal(builtin_auth_init_functions[i].name, module_name)) {
-				DEBUG(5,("make_auth_context_text_list: Found auth method %s (at pos %d)\n", *text_list, i));
-				if (NT_STATUS_IS_OK(builtin_auth_init_functions[i].init(*auth_context, module_params, &t))) {
-					DEBUG(5,("make_auth_context_text_list: auth method %s has a valid init\n",
-								*text_list));
-					DLIST_ADD_END(list, t, tmp);
-				} else {
-					DEBUG(0,("make_auth_context_text_list: auth method %s did not correctly init\n",
-								*text_list));
+		for (entry = global_auth_methods;entry;entry = entry->next) {
+			if (strequal(entry->name, *text_list)) {
+				found = True;
+				DEBUG(5,("make_auth_context_text_list: Found auth method '%s' (at pos %d)\n", *text_list, i));
+
+				if (NT_STATUS_IS_ERR(nt_status = make_auth_method(*auth_context,&method, entry))) {
+					DEBUG(0,("make_auth_context_text_list: make_auth_method failed for '%s'\n",*text_list));
+					return nt_status;
 				}
+
+				DLIST_ADD_END(list, method, tmp);
+				i++;
 				break;
 			}
-			SAFE_FREE(module_name);
 		}
+
+		if (!found) {
+			DEBUG(5,("make_auth_context_text_list: don't find an auth method '%s'\n",
+					*text_list));
+			return NT_STATUS_INVALID_PARAMETER;/* or logon_failure ??? */
+		}
+
 	}
 	
 	(*auth_context)->auth_method_list = list;
@@ -372,14 +471,11 @@ static NTSTATUS make_auth_context_text_l
 
 NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) 
 {
-	char **auth_method_list = NULL; 
+	char **auth_method_list = NULL;
+	const char **lp_auth_list = NULL; 
 	NTSTATUS nt_status;
 
-	if (lp_auth_methods() && !str_list_copy(&auth_method_list, lp_auth_methods())) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	if (auth_method_list == NULL) {
+	if ((lp_auth_list = lp_auth_methods())==NULL) {
 		switch (lp_security()) 
 		{
 		case SEC_DOMAIN:
@@ -416,16 +512,17 @@ NTSTATUS make_auth_context_subsystem(str
 			DEBUG(5,("Unknown auth method!\n"));
 			return NT_STATUS_UNSUCCESSFUL;
 		}
+		nt_status = make_auth_context_text_list(auth_context, auth_method_list);
+		str_list_free(&auth_method_list);
 	} else {
 		DEBUG(5,("Using specified auth order\n"));
+		nt_status = make_auth_context_text_list(auth_context, (char **)lp_auth_list);
 	}
 	
-	if (!NT_STATUS_IS_OK(nt_status = make_auth_context_text_list(auth_context, auth_method_list))) {
-		str_list_free(&auth_method_list);
-		return nt_status;
+	if (NT_STATUS_IS_ERR(nt_status)) {
+		DEBUG(0,("make_auth_context_subsystem: make_auth_context_text_list() failed\n"));
 	}
-	
-	str_list_free(&auth_method_list);
+
 	return nt_status;
 }
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_builtin.c HEAD-modules/source/auth/auth_builtin.c
--- HEAD/source/auth/auth_builtin.c	Thu Dec 12 20:24:26 2002
+++ HEAD-modules/source/auth/auth_builtin.c	Tue Dec 17 09:55:56 2002
@@ -50,15 +50,12 @@ static NTSTATUS check_guest_security(con
 
 /* Guest modules initialisation */
 
-NTSTATUS auth_init_guest(struct auth_context *auth_context, const char *options, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method))
-		return NT_STATUS_NO_MEMORY;
-
-	(*auth_method)->auth = check_guest_security;
-	(*auth_method)->name = "guest";
-	return NT_STATUS_OK;
-}
+struct auth_method_ops auth_guest_ops = {
+	check_guest_security,		/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
 
 /** 
  * Return an error based on username
@@ -101,15 +98,12 @@ static NTSTATUS check_name_to_ntstatus_s
 
 /** Module initailisation function */
 
-NTSTATUS auth_init_name_to_ntstatus(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method))
-		return NT_STATUS_NO_MEMORY;
-
-	(*auth_method)->auth = check_name_to_ntstatus_security;
-	(*auth_method)->name = "name_to_ntstatus";
-	return NT_STATUS_OK;
-}
+struct auth_method_ops auth_name_to_ntstatus_ops = {
+	check_name_to_ntstatus_security,/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
 
 /** 
  * Return a 'fixed' challenge instead of a varaible one.
@@ -150,61 +144,9 @@ static DATA_BLOB auth_get_fixed_challeng
 
 /** Module initailisation function */
 
-NTSTATUS auth_init_fixed_challenge(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method))
-		return NT_STATUS_NO_MEMORY;
-
-	(*auth_method)->auth = check_fixed_challenge_security;
-	(*auth_method)->get_chal = auth_get_fixed_challenge;
-	(*auth_method)->name = "fixed_challenge";
-	return NT_STATUS_OK;
-}
-
-/**
- * Outsorce an auth module to an external loadable .so
- *
- * Only works on systems with dlopen() etc.
- **/
-
-/* Plugin modules initialisation */
-
-NTSTATUS auth_init_plugin(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
-{
-	void * dl_handle;
-	char *plugin_param, *plugin_name, *p;
-	auth_init_function plugin_init;
-
-	if (param == NULL) {
-		DEBUG(0, ("auth_init_plugin: The plugin module needs an argument!\n"));
-		return NT_STATUS_UNSUCCESSFUL;
-	}
-
-	plugin_name = smb_xstrdup(param);
-	p = strchr(plugin_name, ':');
-	if (p) {
-		*p = 0;
-		plugin_param = p+1;
-		trim_string(plugin_param, " ", " ");
-	} else plugin_param = NULL;
-
-	trim_string(plugin_name, " ", " ");
-
-	DEBUG(5, ("auth_init_plugin: Trying to load auth plugin %s\n", plugin_name));
-	dl_handle = sys_dlopen(plugin_name, RTLD_NOW );
-	if (!dl_handle) {
-		DEBUG(0, ("auth_init_plugin: Failed to load auth plugin %s using sys_dlopen (%s)\n",
-					plugin_name, sys_dlerror()));
-		return NT_STATUS_UNSUCCESSFUL;
-	}
-    
-	plugin_init = sys_dlsym(dl_handle, "auth_init");
-	if (!plugin_init){
-		DEBUG(0, ("Failed to find function 'auth_init' using sys_dlsym in sam plugin %s (%s)\n",
-					plugin_name, sys_dlerror()));	    
-		return NT_STATUS_UNSUCCESSFUL;
-	}
-
-	DEBUG(5, ("Starting sam plugin %s with paramater %s\n", plugin_name, plugin_param?plugin_param:"(null)"));
-	return plugin_init(auth_context, plugin_param, auth_method);
-}
+struct auth_method_ops auth_fixed_challenge_ops = {
+	check_fixed_challenge_security,	/* auth */
+	auth_get_fixed_challenge,	/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_domain.c HEAD-modules/source/auth/auth_domain.c
--- HEAD/source/auth/auth_domain.c	Fri Dec 13 07:25:43 2002
+++ HEAD-modules/source/auth/auth_domain.c	Tue Dec 17 09:56:45 2002
@@ -412,9 +412,12 @@ static NTSTATUS check_ntdomain_security(
 	 * Check that the requested domain is not our own machine name.
 	 * If it is, we should never check the PDC here, we use our own local
 	 * password file.
+	 *
+	 * we interpret domain "" as our own machine name too --metze  
 	 */
 
-	if(is_myname(user_info->domain.str)) {
+	if(is_myname(user_info->domain.str)||
+		strequal("", user_info->domain.str)) {
 		DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n"));
 		return NT_STATUS_LOGON_FAILURE;
 	}
@@ -453,17 +456,12 @@ static NTSTATUS check_ntdomain_security(
 }
 
 /* module initialisation */
-NTSTATUS auth_init_ntdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	(*auth_method)->name = "ntdomain";
-	(*auth_method)->auth = check_ntdomain_security;
-	return NT_STATUS_OK;
-}
-
+struct auth_method_ops auth_ntdomain_ops = {
+	check_ntdomain_security,	/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
 
 /****************************************************************************
  Check for a valid username and password in a trusted domain
@@ -490,9 +488,12 @@ static NTSTATUS check_trustdomain_securi
 	 * Check that the requested domain is not our own machine name.
 	 * If it is, we should never check the PDC here, we use our own local
 	 * password file.
+	 *
+	 * we interpret domain "" as our own machine name too --metze
 	 */
 
-	if(is_myname(user_info->domain.str)) {
+	if(is_myname(user_info->domain.str)||
+		strequal("", user_info->domain.str)) {
 		DEBUG(3,("check_trustdomain_security: Requested domain was for this machine.\n"));
 		return NT_STATUS_LOGON_FAILURE;
 	}
@@ -502,7 +503,7 @@ static NTSTATUS check_trustdomain_securi
 	 * If it is, we should use our own local password file.
 	 */
 
-	if(strequal(lp_workgroup(), (user_info->domain.str))) {
+	if(is_myworkgroup(user_info->domain.str)) {
 		DEBUG(3,("check_trustdomain_security: Requested domain was for this domain.\n"));
 		return NT_STATUS_LOGON_FAILURE;
 	}
@@ -514,8 +515,8 @@ static NTSTATUS check_trustdomain_securi
 
 	if (!secrets_fetch_trusted_domain_password(user_info->domain.str, &trust_password, &sid, &last_change_time))
 	{
-		DEBUG(0, ("check_trustdomain_security: could not fetch trust account password for domain %s\n", user_info->domain.str));
-		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+		DEBUG(0, ("check_trustdomain_security: could not fetch trust account password for domain '%s', seems that we don't trust this domain.\n", user_info->domain.str));
+		return NT_STATUS_LOGON_FAILURE;/* we don't trust the domain */
 	}
 
 #ifdef DEBUG_PASSWORD
@@ -541,13 +542,9 @@ static NTSTATUS check_trustdomain_securi
 }
 
 /* module initialisation */
-NTSTATUS auth_init_trustdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	(*auth_method)->name = "trustdomain";
-	(*auth_method)->auth = check_trustdomain_security;
-	return NT_STATUS_OK;
-}
+struct auth_method_ops auth_trustdomain_ops = {
+	check_trustdomain_security,	/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_rhosts.c HEAD-modules/source/auth/auth_rhosts.c
--- HEAD/source/auth/auth_rhosts.c	Fri May 24 05:43:52 2002
+++ HEAD-modules/source/auth/auth_rhosts.c	Tue Dec 17 09:57:18 2002
@@ -179,16 +179,12 @@ static NTSTATUS check_hostsequiv_securit
 }
 
 /* module initialisation */
-NTSTATUS auth_init_hostsequiv(struct auth_context *auth_context, const char* param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	(*auth_method)->auth = check_hostsequiv_security;
-	return NT_STATUS_OK;
-}
-
+struct auth_method_ops auth_hostsequiv_ops = {
+	check_hostsequiv_security,	/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
 
 /****************************************************************************
  Check for a valid .rhosts/hosts.equiv entry for this user
@@ -223,12 +219,9 @@ static NTSTATUS check_rhosts_security(co
 }
 
 /* module initialisation */
-NTSTATUS auth_init_rhosts(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	(*auth_method)->auth = check_rhosts_security;
-	return NT_STATUS_OK;
-}
+struct auth_method_ops auth_rhosts_ops = {
+	check_rhosts_security,		/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_sam.c HEAD-modules/source/auth/auth_sam.c
--- HEAD/source/auth/auth_sam.c	Mon Nov 18 06:44:20 2002
+++ HEAD-modules/source/auth/auth_sam.c	Tue Dec 17 09:58:09 2002
@@ -423,17 +423,12 @@ static NTSTATUS check_sam_security(const
 }
 
 /* module initialisation */
-NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	(*auth_method)->auth = check_sam_security;	
-	(*auth_method)->name = "sam";
-	return NT_STATUS_OK;
-}
-
+struct auth_method_ops auth_sam_ops = {
+	check_sam_security,		/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
 
 /****************************************************************************
 Check SAM security (above) but with a few extra checks.
@@ -452,9 +447,12 @@ static NTSTATUS check_samstrict_security
 
 	/* If we are a domain member, we must not 
 	   attempt to check the password locally,
-	   unless it is one of our aliases. */
+	   unless it is one of our aliases 
+	   or empty */
 	
 	if (!is_myname(user_info->domain.str)) {
+		DEBUG(7,("The requested user domain is not local. [%s]\\[%s}\n",
+			user_info->domain.str,user_info->internal_username.str));
 		return NT_STATUS_NO_SUCH_USER;
 	}
 	
@@ -462,15 +460,47 @@ static NTSTATUS check_samstrict_security
 }
 
 /* module initialisation */
-NTSTATUS auth_init_samstrict(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
+struct auth_method_ops auth_samstrict_ops = {
+	check_samstrict_security,	/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
+
+/****************************************************************************
+Check SAM security (above) but with a few extra checks (if we're a DC).
+****************************************************************************/
+
+static NTSTATUS check_samstrict_dc_security(const struct auth_context *auth_context,
+					 void *my_private_data, 
+					 TALLOC_CTX *mem_ctx,
+					 const auth_usersupplied_info *user_info, 
+					 auth_serversupplied_info **server_info)
 {
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
+
+	if (!user_info || !auth_context) {
+		return NT_STATUS_LOGON_FAILURE;
 	}
 
-	(*auth_method)->auth = check_samstrict_security;
-	(*auth_method)->name = "samstrict";
-	return NT_STATUS_OK;
+	/* If we are a domain member, we must not 
+	   attempt to check the password locally,
+	   unless it is one of our aliases or our 
+	   domain if we are a logon server.*/
+	
+	if ((!is_myworkgroup(user_info->domain.str))&&
+		(!is_myname(user_info->domain.str))){
+		DEBUG(7,("The requested user domain is not local or our domain. [%s]\\[%s]\n",
+			user_info->domain.str,user_info->internal_username.str));
+		return NT_STATUS_NO_SUCH_USER;
+	}
+	
+	return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info);
 }
 
-
+/* module initialisation */
+struct auth_method_ops auth_samstrict_dc_ops = {
+	check_samstrict_dc_security,	/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_server.c HEAD-modules/source/auth/auth_server.c
--- HEAD/source/auth/auth_server.c	Wed Nov 13 19:52:30 2002
+++ HEAD-modules/source/auth/auth_server.c	Tue Dec 17 09:59:19 2002
@@ -388,15 +388,9 @@ use this machine as the password server.
 	return(nt_status);
 }
 
-NTSTATUS auth_init_smbserver(struct auth_context *auth_context, const char* param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	(*auth_method)->name = "smbserver";
-	(*auth_method)->auth = check_smbserver_security;
-	(*auth_method)->get_chal = auth_get_challenge_server;
-	(*auth_method)->send_keepalive = send_server_keepalive;
-	(*auth_method)->free_private_data = free_server_private_data;
-	return NT_STATUS_OK;
-}
+struct auth_method_ops auth_smbserver_ops = {
+	check_smbserver_security,	/* auth */
+	auth_get_challenge_server,	/* get_chal */
+	send_server_keepalive,		/* send_keepalive */
+	free_server_private_data	/* free_private_data */
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_unix.c HEAD-modules/source/auth/auth_unix.c
--- HEAD/source/auth/auth_unix.c	Sun Oct 13 12:11:25 2002
+++ HEAD-modules/source/auth/auth_unix.c	Tue Dec 17 09:59:40 2002
@@ -119,14 +119,9 @@ static NTSTATUS check_unix_security(cons
 }
 
 /* module initialisation */
-NTSTATUS auth_init_unix(struct auth_context *auth_context, const char* param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	(*auth_method)->name = "unix";
-	(*auth_method)->auth = check_unix_security;
-	return NT_STATUS_OK;
-}
-
+struct auth_method_ops auth_unix_ops = {
+	check_unix_security,		/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_util.c HEAD-modules/source/auth/auth_util.c
--- HEAD/source/auth/auth_util.c	Mon Nov 18 06:44:20 2002
+++ HEAD-modules/source/auth/auth_util.c	Mon Dec 16 09:32:00 2002
@@ -177,51 +177,30 @@ NTSTATUS make_user_info_map(auth_usersup
 	
 	DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
 	      client_domain, smb_name, wksta_name));
-	
-	if (lp_allow_trusted_domains() && *client_domain) {
 
-		/* the client could have given us a workstation name
-		   or other crap for the workgroup - we really need a
-		   way of telling if this domain name is one of our
-		   trusted domain names 
-
-		   Also don't allow "" as a domain, fixes a Win9X bug 
-		   where it doens't supply a domain for logon script
-		   'net use' commands.
-
-		   The way I do it here is by checking if the fully
-		   qualified username exists. This is rather reliant
-		   on winbind, but until we have a better method this
-		   will have to do 
-		*/
-
-		domain = client_domain;
-
-		if ((smb_name) && (*smb_name)) { /* Don't do this for guests */
-			char *user = NULL;
-			if (asprintf(&user, "%s%s%s", 
-				 client_domain, lp_winbind_separator(), 
-				 smb_name) < 0) {
-				DEBUG(0, ("make_user_info_map: asprintf() failed!\n"));
-				return NT_STATUS_NO_MEMORY;
-			}
+	domain = client_domain;
 
-			DEBUG(5, ("make_user_info_map: testing for user %s\n", user));
-			
-			if (Get_Pwnam(user) == NULL) {
-				DEBUG(5, ("make_user_info_map: test for user %s failed\n", user));
-				domain = lp_workgroup();
-				DEBUG(5, ("make_user_info_map: trusted domain %s doesn't appear to exist, using %s\n", 
-					  client_domain, domain));
-			} else {
-				DEBUG(5, ("make_user_info_map: using trusted domain %s\n", domain));
-			}
-			SAFE_FREE(user);
-		}
-	} else {
+	/* the client could have given us a workstation name
+	   or other crap for the workgroup - we really need a
+	   way of telling if this domain name is one of our
+	   trusted domain names 
+
+	   Also don't allow "" as a domain, fixes a Win9X bug 
+	   where it doens't supply a domain for logon script
+	   'net use' commands.
+
+	*/
+
+	if (strequal("", domain)){
+		/* maybe we should use our global_myname() 
+		 * or let it be "",
+		 * but it might be break the Win9X bug 
+		 * mentioned above. --metze*/
 		domain = lp_workgroup();
+		DEBUG(5, ("make_user_info_map: no domain name given for user %s, assuming it's our domain.\n", smb_name));
 	}
-	
+
+
 	return make_user_info(user_info, 
 			      smb_name, internal_username,
 			      client_domain, domain,
@@ -1098,30 +1077,6 @@ void free_server_info(auth_serversupplie
 		ZERO_STRUCT(**server_info);
 	}
 	SAFE_FREE(*server_info);
-}
-
-/***************************************************************************
- Make an auth_methods struct
-***************************************************************************/
-
-BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) 
-{
-	if (!auth_context) {
-		smb_panic("no auth_context supplied to make_auth_methods()!\n");
-	}
-
-	if (!auth_method) {
-		smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
-	}
-
-	*auth_method = talloc(auth_context->mem_ctx, sizeof(**auth_method));
-	if (!*auth_method) {
-		DEBUG(0,("make_auth_method: malloc failed!\n"));
-		return False;
-	}
-	ZERO_STRUCTP(*auth_method);
-	
-	return True;
 }
 
 /****************************************************************************
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/auth/auth_winbind.c HEAD-modules/source/auth/auth_winbind.c
--- HEAD/source/auth/auth_winbind.c	Mon Nov 18 06:44:20 2002
+++ HEAD-modules/source/auth/auth_winbind.c	Tue Dec 17 10:00:03 2002
@@ -125,13 +125,9 @@ static NTSTATUS check_winbind_security(c
 }
 
 /* module initialisation */
-NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
-{
-	if (!make_auth_methods(auth_context, auth_method)) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	(*auth_method)->name = "winbind";
-	(*auth_method)->auth = check_winbind_security;
-	return NT_STATUS_OK;
-}
+struct auth_method_ops auth_winbind_ops = {
+	check_winbind_security,		/* auth */
+	NULL,				/* get_chal */
+	NULL,				/* send_keepalive */	
+	NULL				/* free_private_data */
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/configure.in HEAD-modules/source/configure.in
--- HEAD/source/configure.in	Thu Dec  5 09:43:42 2002
+++ HEAD-modules/source/configure.in	Fri Dec  6 09:22:43 2002
@@ -17,9 +17,10 @@ AC_ARG_WITH(fhs, 
     logfilebase="\${VARDIR}/log/samba"
     privatedir="\${CONFIGDIR}/private"
     libdir="\${prefix}/lib/samba"
-    swatdir="\${DATADIR}/samba/swat",
-    configdir="\${LIBDIR}"
-    logfilebase="\${VARDIR}"
+    swatdir="${datadir}/samba/swat"
+    datadir="${datadir}/samba",
+    configdir="\$(LIBDIR)"
+    logfilebase="\$(VARDIR)"
     lockdir="\${VARDIR}/locks"
     piddir="\${VARDIR}/locks"
     privatedir="\${prefix}/private"
@@ -129,6 +130,7 @@ AC_SUBST(privatedir)
 AC_SUBST(swatdir)
 AC_SUBST(bindir)
 AC_SUBST(sbindir)
+AC_SUBST(datadir)
 
 dnl Unique-to-Samba variables we'll be playing with.
 AC_SUBST(SHELL)
@@ -630,7 +632,7 @@ test "${with_readline+set}" != "set" && 
 # test for where we get readline() from
 AC_MSG_CHECKING(whether to use readline)
 AC_ARG_WITH(readline,
-[  --with-readline[=DIR]   Look for readline include/libs in DIR (default=auto) ],
+[  --with-readline[=DIR]     Look for readline include/libs in DIR (default=auto) ],
 [  case "$with_readline" in
   yes)
     AC_MSG_RESULT(yes)
@@ -1969,7 +1971,7 @@ with_ads_support=yes
 AC_MSG_CHECKING([whether to use Active Directory])
 
 AC_ARG_WITH(ads,
-[   --with-ads  Active Directory support (default yes)],
+[  --with-ads              Active Directory support (default yes)],
 [ case "$withval" in
     no)
 	with_ads_support=no
@@ -2069,7 +2071,7 @@ with_ldap_support=yes
 AC_MSG_CHECKING([whether to use LDAP])
 
 AC_ARG_WITH(ldap,
-[   --with-ldap  LDAP support (default yes)],
+[  --with-ldap             LDAP support (default yes)],
 [ case "$withval" in
     no)
 	with_ldap_support=no
@@ -2265,7 +2267,7 @@ AC_ARG_WITH(sam,
 # check for a LDAP password database configuration backwards compatibility
 AC_MSG_CHECKING(whether to use LDAP SAM 2.2 compatible configuration)
 AC_ARG_WITH(ldapsam,
-[  --with-ldapsam           Include LDAP SAM 2.2 compatible configuration (default=no)],
+[  --with-ldapsam          Include LDAP SAM 2.2 compatible configuration (default=no)],
 [ case "$withval" in
   yes)
     AC_MSG_RESULT(yes)
@@ -2782,7 +2784,7 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_
 with_sendfile_support=yes
 AC_MSG_CHECKING(whether to check to support sendfile)
 AC_ARG_WITH(sendfile-support,
-[  --with-sendfile-support      Check for sendfile support (default=yes)],
+[  --with-sendfile-support Check for sendfile support (default=yes)],
 [ case "$withval" in
   yes)
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/dynconfig.c HEAD-modules/source/dynconfig.c
--- HEAD/source/dynconfig.c	Tue Nov  5 16:25:26 2002
+++ HEAD-modules/source/dynconfig.c	Fri Dec  6 09:22:43 2002
@@ -54,9 +54,9 @@ pstring dyn_LMHOSTSFILE = LMHOSTSFILE;
 /**
  * @brief Samba library directory.
  *
- * @sa lib_path() to get the path to a file inside the LIBDIR.
+ * @sa data_path() to get the path to a file inside the DATADIR.
  **/
-pstring dyn_LIBDIR = LIBDIR;  
+pstring dyn_DATADIR = DATADIR;  
 
 /**
  * @brief Directory holding lock files.
@@ -68,3 +68,6 @@ const pstring dyn_PIDDIR  = PIDDIR;
 
 const pstring dyn_SMB_PASSWD_FILE = SMB_PASSWD_FILE;
 const pstring dyn_PRIVATE_DIR = PRIVATE_DIR;
+
+/** default for lp_modules_path(int snum) **/
+const pstring dyn_LIBDIR = LIBDIR;
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/auth.h HEAD-modules/source/include/auth.h
--- HEAD/source/include/auth.h	Fri May 24 05:43:52 2002
+++ HEAD-modules/source/include/auth.h	Tue Dec 17 11:58:21 2002
@@ -1,9 +1,10 @@
-#ifndef _SMBAUTH_H_
-#define _SMBAUTH_H_
+#ifndef _AUTH_H_
+#define _AUTH_H_
 /* 
    Unix SMB/CIFS implementation.
    Standardised Authentication types
-   Copyright (C) Andrew Bartlett 2001
+   Copyright (C) Andrew Bartlett		2001
+   Copyright (C) Stefan (metze) Metzmacher	2002
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -20,6 +21,16 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+
+/*
+ * This next constant specifies the version number of the AUTH interface
+ * this SAMBA will load. Increment this if *ANY* changes are made to the interface. 
+ */
+
+/* AUTH_INTERFACE_VERSION 2 - make ready for smb_register_auth --metze*/
+#define AUTH_INTERFACE_VERSION 2
+
+
 /* AUTH_STR - string */
 typedef struct normal_string
 {
@@ -34,7 +45,7 @@ typedef struct unicode_string
 	uchar *unistr;
 } AUTH_UNISTR;
 
-typedef struct interactive_password
+typedef struct auth_interactive_password
 {
 	OWF_INFO          lm_owf;              /* LM OWF Password */
 	OWF_INFO          nt_owf;              /* NT OWF Password */
@@ -51,7 +62,7 @@ typedef struct auth_usersupplied_info
 	
  	DATA_BLOB lm_resp;
 	DATA_BLOB nt_resp;
-	auth_interactive_password * interactive_password;
+	struct auth_interactive_password * interactive_password;
  	DATA_BLOB plaintext_password;
 	
 	BOOL encrypted;
@@ -96,6 +107,38 @@ typedef struct auth_serversupplied_info 
 	
 } auth_serversupplied_info;
 
+struct auth_context;
+
+struct auth_method_ops
+{
+	NTSTATUS (*auth)(const struct auth_context *auth_context,
+			 void *my_private_data, 
+			 TALLOC_CTX *mem_ctx,
+			 const auth_usersupplied_info *user_info, 
+			 auth_serversupplied_info **server_info);
+
+	DATA_BLOB (*get_chal)(const struct auth_context *auth_context,
+			      void **my_private_data, 
+			      TALLOC_CTX *mem_ctx);
+
+	/* Function to send a keepalive message on the above structure */
+	void (*send_keepalive)(void **private_data);
+
+	/* Function to clean up the above arbitary structure */
+	void (*free_private_data)(void **private_data);
+
+};
+
+struct auth_methods
+{
+	struct auth_methods *prev, *next;
+	char *name; /* What name got this module */
+
+	struct auth_method_ops *ops;
+	/* Used to keep tabs on things like the cli for SMB server authentication */
+	void *private_data;
+};
+
 struct auth_context {
 	DATA_BLOB challenge; 
 
@@ -109,44 +152,16 @@ struct auth_context {
 	TALLOC_CTX *mem_ctx;
 	const uint8 *(*get_ntlm_challenge)(struct auth_context *auth_context);
 	NTSTATUS (*check_ntlm_password)(const struct auth_context *auth_context,
-					const struct auth_usersupplied_info *user_info, 
-					struct auth_serversupplied_info **server_info);
+					const auth_usersupplied_info *user_info, 
+					auth_serversupplied_info **server_info);
 	NTSTATUS (*nt_status_squash)(NTSTATUS nt_status);
 	void (*free)(struct auth_context **auth_context);
 };
 
-typedef struct auth_methods
-{
-	struct auth_methods *prev, *next;
-	char *name; /* What name got this module */
-
-	NTSTATUS (*auth)(const struct auth_context *auth_context,
-			 void *my_private_data, 
-			 TALLOC_CTX *mem_ctx,
-			 const struct auth_usersupplied_info *user_info, 
-			 auth_serversupplied_info **server_info);
-
-	DATA_BLOB (*get_chal)(const struct auth_context *auth_context,
-			      void **my_private_data, 
-			      TALLOC_CTX *mem_ctx);
-	
-	/* Used to keep tabs on things like the cli for SMB server authentication */
-	void *private_data;
-	
-	/* Function to clean up the above arbitary structure */
-	void (*free_private_data)(void **private_data);
-
-	/* Function to send a keepalive message on the above structure */
-	void (*send_keepalive)(void **private_data);
-
-} auth_methods;
-
-typedef NTSTATUS (*auth_init_function)(struct auth_context *, const char *, struct auth_methods **);
-
-struct auth_init_function_entry {
+struct auth_method_function_entry {
 	char *name;
-	/* Function to create a member of the authmethods list */
-
-	auth_init_function init;
+	struct auth_method_ops *ops;
+	struct auth_method_function_entry *prev,*next;	
 };
-#endif /* _SMBAUTH_H_ */
+
+#endif /* _AUTH_H_ */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/charset.h HEAD-modules/source/include/charset.h
--- HEAD/source/include/charset.h	Wed Nov 13 19:52:32 2002
+++ HEAD-modules/source/include/charset.h	Tue Dec 17 11:58:54 2002
@@ -38,3 +38,8 @@ struct charset_functions {
 	struct charset_functions *prev, *next;
 };
 
+/* 
+ * please increment the version if you make any changed to the interface 
+ */
+/* CHARSET_INTERFACE_VERSION 2 - change to use the CHARSET_INTERFACE_VERSION --metze*/
+#define CHARSET_INTERFACE_VERSION 2
\ No newline at end of file
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/dynconfig.h HEAD-modules/source/include/dynconfig.h
--- HEAD/source/include/dynconfig.h	Tue Nov  5 16:25:26 2002
+++ HEAD-modules/source/include/dynconfig.h	Fri Dec  6 09:22:43 2002
@@ -29,8 +29,9 @@ extern char const *dyn_SBINDIR,
 
 extern pstring dyn_CONFIGFILE;
 extern pstring dyn_LOGFILEBASE, dyn_LMHOSTSFILE;
-extern pstring dyn_LIBDIR;
+extern pstring dyn_DATADIR;
 extern const pstring dyn_LOCKDIR; 
 extern const pstring dyn_PIDDIR;
 extern const pstring dyn_SMB_PASSWD_FILE;
 extern const pstring dyn_PRIVATE_DIR;
+extern const pstring dyn_LIBDIR;
\ No newline at end of file
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/includes.h HEAD-modules/source/include/includes.h
--- HEAD/source/include/includes.h	Tue Dec 17 08:56:41 2002
+++ HEAD-modules/source/include/includes.h	Tue Dec 17 08:59:11 2002
@@ -734,6 +734,7 @@ extern int errno;
 
 #include "version.h"
 #include "smb.h"
+#include "modules.h"
 #include "smbw.h"
 #include "nameserv.h"
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/modules.h HEAD-modules/source/include/modules.h
--- HEAD/source/include/modules.h	Thu Jan  1 01:00:00 1970
+++ HEAD-modules/source/include/modules.h	Mon Dec 16 10:30:57 2002
@@ -0,0 +1,65 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  module loading system
+ 
+ *  Cpoyright (C) Stefan (metze) Metzmacher	2002
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MODULES_H
+#define _MODULES_H
+
+typedef SMB_BIG_UINT 		SMB_MODULE_TYPES;	
+
+#define MODULE_TYPE_NONE	0x0000000000000000
+#define	MODULE_TYPE_PDB		0x0000000000000001
+#define	MODULE_TYPE_VFS		0x0000000000000002
+#define	MODULE_TYPE_WINSDB	0x0000000000000004
+#define	MODULE_TYPE_SAM		0x0000000000000008
+#define	MODULE_TYPE_CHARSET	0x0000000000000010
+#define	MODULE_TYPE_AUTH	0x0000000000000020
+
+#define MODULE_TYPES_ALL	0xFFFFFFFFFFFFFFFF
+
+#ifdef WITH_SAM
+#define MODULE_TYPES_SMBD		MODULE_TYPE_CHARSET | MODULE_TYPE_PDB | MODULE_TYPE_AUTH | MODULE_TYPE_VFS | MODULE_TYPE_SAM
+#else
+#define MODULE_TYPES_SMBD		MODULE_TYPE_CHARSET | MODULE_TYPE_PDB | MODULE_TYPE_AUTH | MODULE_TYPE_VFS
+#endif /* WITH_SAM */
+
+#define MODULE_TYPES_PER_SHARE		MODULE_TYPE_VFS
+
+#define MODULE_TYPES_NMBD		MODULE_TYPE_CHARSET | MODULE_TYPE_WINSDB
+
+#define MODULE_TYPES_WINBINDD		MODULE_TYPE_NONE
+
+#define MODULE_TYPES_WREPLD		MODULE_TYPES_NMBD 
+
+#define MODULE_TYPES_NET		MODULE_TYPES_SMBD
+#define MODULE_TYPES_SMBPASSWD		MODULE_TYPES_SMBD
+#define MODULE_TYPES_SMBGROUPEDIT	MODULE_TYPES_SMBD
+#define MODULE_TYPES_PDBEDIT		MODULE_TYPES_SMBD
+#define MODULE_TYPES_VFSTEST		MODULE_TYPES_SMBD
+
+
+/* This is the FUNCTION SYMBOL witch we're searching for when we load modules */
+#define SMB_MODULE_SYMBOL_STR	"smb_module_init"
+#define SMB_MODULE_SYMBOL	smb_module_init
+
+/* Module support */
+typedef NTSTATUS (SMB_MODULE_INIT_FUNCTION) (SMB_MODULE_TYPES);
+
+#endif /* _MODULES_H */
\ No newline at end of file
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/passdb.h HEAD-modules/source/include/passdb.h
--- HEAD/source/include/passdb.h	Fri Nov 15 18:42:56 2002
+++ HEAD-modules/source/include/passdb.h	Tue Dec 17 13:32:23 2002
@@ -1,8 +1,9 @@
 /* 
    Unix SMB/CIFS implementation.
    passdb structures and parameters
-   Copyright (C) Gerald Carter 2001
-   Copyright (C) Luke Kenneth Casson Leighton 1998 - 2000
+   Copyright (C) Gerald Carter			2001
+   Copyright (C) Luke Kenneth Casson Leighton	1998 - 2000
+   Copyright (C) Stefan (metze) Metzmacher	2002
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -31,8 +32,9 @@
  * This next constant specifies the version number of the PASSDB interface
  * this SAMBA will load. Increment this if *ANY* changes are made to the interface. 
  */
-
-#define PASSDB_INTERFACE_VERSION 4
+ 
+/* PASSDB_INTERFACE_VERSION 5 - make ready for smb_register_passdb() --metze */
+#define PASSDB_INTERFACE_VERSION 5
 
 typedef struct pdb_context 
 {
@@ -87,15 +89,7 @@ typedef struct pdb_context 
 	
 } PDB_CONTEXT;
 
-typedef struct pdb_methods 
-{
-	const char *name; /* What name got this module */
-	struct pdb_context *parent;
-
-	/* Use macros from dlinklist.h on these two */
-	struct pdb_methods *next;
-	struct pdb_methods *prev;
-
+typedef struct pdb_method_ops {
 	NTSTATUS (*setsampwent)(struct pdb_methods *, BOOL update);
 	
 	void (*endsampwent)(struct pdb_methods *);
@@ -135,21 +129,36 @@ typedef struct pdb_methods 
 				       GROUP_MAP **rmap, int *num_entries,
 				       BOOL unix_only, BOOL with_priv);
 
-	void *private_data;  /* Private data of some kind */
+	NTSTATUS (*init_private_data)(TALLOC_CTX *mem_ctx,
+				  void **private_data,
+				  const char *parameter);  /* Private data of some kind 
+							* later we should remove the parameter
+							*/
 	
-	void (*free_private_data)(void **);
+	NTSTATUS (*free_private_data)(void **private_data);
+} PDB_METHOD_OPS;
 
-} PDB_METHODS;
+typedef struct pdb_methods 
+{
+	const char *name; /* What name got this module */
+	struct pdb_context *parent;
+
+	/* Use macros from dlinklist.h on these two */
+	struct pdb_methods *next;
+	struct pdb_methods *prev;
+
+	struct pdb_method_ops *ops;
 
-typedef NTSTATUS (*pdb_init_function)(struct pdb_context *, 
-			 struct pdb_methods **, 
-			 const char *);
+	void *private_data;  /* Private data of some kind */
+	
+	char *param; /* this should be removed soon */
+} PDB_METHODS;
 
-struct pdb_init_function_entry {
+struct pdb_backend_function_entry {
 	char *name;
 	/* Function to create a member of the pdb_methods list */
-	pdb_init_function init;
-	struct pdb_init_function_entry *prev, *next;
+	struct pdb_method_ops *ops;
+	struct pdb_backend_function_entry *prev, *next;
 };
 
 #endif /* _PASSDB_H */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/smb.h HEAD-modules/source/include/smb.h
--- HEAD/source/include/smb.h	Fri Dec 13 07:25:43 2002
+++ HEAD-modules/source/include/smb.h	Fri Dec 13 08:35:08 2002
@@ -430,18 +430,10 @@ typedef struct
 #include "smb_acls.h"
 #include "vfs.h"
 
-typedef struct smb_vfs_handle_struct
-{
-    void *data;
-    /* Handle on dlopen() call */
-    void *handle;
-    struct smb_vfs_handle_struct  *next, *prev;
-    
-} smb_vfs_handle_struct;
-
 typedef struct connection_struct
 {
 	struct connection_struct *next, *prev;
+	TALLOC_CTX *mem_ctx;
 	unsigned cnum; /* an index passed over the wire */
 	int service;
 	BOOL force_user;
@@ -456,8 +448,14 @@ typedef struct connection_struct
 	char *connectpath;
 	char *origpath;
 
-	struct vfs_ops vfs_ops;                   /* Filesystem operations */
-	struct smb_vfs_handle_struct *vfs_private;
+	struct vfs_ops vfs_ops;			/* Filesystem operations */
+	vfs_object_function_entry *vfs_objects;	/* DLIST of all objects for this connection 
+						 * (talloc'ed on conn->mem_ctx)
+						 */
+	struct vfs_ops *vfs_opaque_ops;		/* Opaque filesystem operations 
+						 * access them only via vfs_get_opaque_ops(conn)
+						 * (it init them)
+						 */
 
 	char *user; /* name of user who *opened* this connection */
 	uid_t uid; /* uid of user who *opened* this connection */
@@ -1714,8 +1712,5 @@ extern struct poptOption popt_common_soc
 extern struct poptOption popt_common_version[];
 extern struct poptOption popt_common_netbios_name[];
 extern struct poptOption popt_common_log_base[];
-
-/* Module support */
-typedef NTSTATUS (init_module_function) (void);
 
 #endif /* _SMB_H */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/smb_macros.h HEAD-modules/source/include/smb_macros.h
--- HEAD/source/include/smb_macros.h	Thu Dec  5 09:43:43 2002
+++ HEAD-modules/source/include/smb_macros.h	Tue Dec 10 13:37:44 2002
@@ -95,8 +95,11 @@
 #define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \
 				NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) )
 
+/* the service number for the [globals] defaults */ 
+#define GLOBAL_SECTION_SNUM	(-2)
 /* translates a connection number into a service number */
-#define SNUM(conn)         ((conn)?(conn)->service:-1)
+#define SNUM(conn)         	((conn)?(conn)->service:GLOBAL_SECTION_SNUM)
+
 
 /* access various service details */
 #define SERVICE(snum)      (lp_servicename(snum))
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/include/vfs.h HEAD-modules/source/include/vfs.h
--- HEAD/source/include/vfs.h	Wed Sep 18 09:44:22 2002
+++ HEAD-modules/source/include/vfs.h	Tue Dec 17 10:56:52 2002
@@ -45,46 +45,45 @@
 /* Changed to version 3 for POSIX acl extensions. JRA. */
 /* Changed to version 4 for cascaded VFS interface. Alexander Bokovoy. */
 /* Changed to version 5 for sendfile addition. JRA. */
-#define SMB_VFS_INTERFACE_VERSION 5
+/* Changed to version 6 for using smb_register_vfs()... metze */
+#define SMB_VFS_INTERFACE_VERSION 6
 
 
-/* Version of supported cascaded interface backward copmatibility.
-   (version 5 corresponds to SMB_VFS_INTERFACE_VERSION 5)
-   It is used in vfs_init_custom() to detect VFS modules which conform to cascaded 
-   VFS interface but implement elder version than current version of Samba uses.
-   This allows to use old modules with new VFS interface as far as combined VFS operation
-   set is coherent (will be in most cases). 
-*/
-#define SMB_VFS_INTERFACE_CASCADED 5
-
 /*
-    Each VFS module must provide following global functions:
-    vfs_init	-- initialization function
-    vfs_done	-- finalization function
-    
-    vfs_init must return proper initialized vfs_op_tuple[] array
+    Each SAMBA module must provide following global function:
+    init_module		-- module initalization function 
+
+	NTSTATUS init_module(SMB_MODULE_TYPES types) 
+	{
+		if (types & MODULE_TYPE_VFS) {
+			if (smb_register_vfs("recycle", vfs_recycle_init, VFS_INTERFACE_VERSION)) {
+				return NT_STATUS_OK;
+			} else {
+				return NT_STATUS_UNSUCCESSFUL;
+			}
+		}
+	
+		return NT_STATUS_OK;
+	}
+
+    Each VFS module must provide following global function:
+    vfs_*_init		-- vfs initialization function
+
+    vfs_*_init (e.g. vfs_recycle_init ) must return proper initialized vfs_op_tuple[] array
     which describes all operations this module claims to intercept. This function
     is called whenever module is loaded into smbd process using sys_dlopen().
-    
-    vfs_init must store somewhere vfs_handle reference if module wants to store per-instance
-    private information for further usage. vfs_handle->data should be used to
-    store such information. Do not try to change other fields in this structure
-    or results likely to be unpredictable.
-    
-    vfs_done must perform finalization of the module. In particular,
-    this function must free vfs_ops structure returned to module from smb_vfs_get_opaque_ops()
-    function if it is used (see below). This function is called whenever module 
-    is unloaded from smbd process using sys_dlclose().
-    
+
+    vfs_*_init must have a list (indexed by the SNUM(conn) or CNUM(conn))
+    for storing the default_vfs_ops and if module wants to store private 
+    information for further usage.
+
     Prototypes:
-    vfs_op_tuple *vfs_init(int *vfs_version, const struct vfs_ops *def_vfs_ops,
-			    struct smb_vfs_handle_struct *vfs_handle);
-    void	  vfs_done(connection_struct *conn);
+    vfs_op_tuple *vfs_recycle_init(struct connection_struct *conn, struct vfs_ops *default_vfs_ops, const char *param);
     
     All intercepted VFS operations must be declared as static functions inside module source
-    in order to keep smbd namespace unpolluted. See source of skel, audit, and recycle bin
+    in order to keep smbd namespace unpolluted. See source of nettalk, audit, and recycle bin
     example VFS modules for more details.
-    
+
 */
 
 /* VFS operations structure */
@@ -93,86 +92,167 @@ struct connection_struct;
 struct files_struct;
 struct security_descriptor_info;
 
-struct vfs_ops {
+#define VFS_OP(x) ((void *) x)
 
+typedef void  (*VFS_OP_PTR);
 	/* Disk operations */
     
-	int (*connect)(struct connection_struct *conn, const char *service, const char *user);
-	void (*disconnect)(struct connection_struct *conn);
-	SMB_BIG_UINT (*disk_free)(struct connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, 
+typedef	int (*VFS_OP_PTR_CONNECT)(struct connection_struct *conn, const char *service, const char *user);
+typedef	void (*VFS_OP_PTR_DISCONNECT)(struct connection_struct *conn);
+typedef	SMB_BIG_UINT (*VFS_OP_PTR_DISK_FREE)(struct connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, 
 		SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
     
 	/* Directory operations */
 
-	DIR *(*opendir)(struct connection_struct *conn, const char *fname);
-	struct dirent *(*readdir)(struct connection_struct *conn, DIR *dirp);
-	int (*mkdir)(struct connection_struct *conn, const char *path, mode_t mode);
-	int (*rmdir)(struct connection_struct *conn, const char *path);
-	int (*closedir)(struct connection_struct *conn, DIR *dir);
+typedef	DIR *(*VFS_OP_PTR_OPENDIR)(struct connection_struct *conn, const char *fname);
+typedef	struct dirent *(*VFS_OP_PTR_READDIR)(struct connection_struct *conn, DIR *dirp);
+typedef	int (*VFS_OP_PTR_MKDIR)(struct connection_struct *conn, const char *path, mode_t mode);
+typedef	int (*VFS_OP_PTR_RMDIR)(struct connection_struct *conn, const char *path);
+typedef	int (*VFS_OP_PTR_CLOSEDIR)(struct connection_struct *conn, DIR *dir);
     
 	/* File operations */
     
-	int (*open)(struct connection_struct *conn, const char *fname, int flags, mode_t mode);
-	int (*close)(struct files_struct *fsp, int fd);
-	ssize_t (*read)(struct files_struct *fsp, int fd, void *data, size_t n);
-	ssize_t (*write)(struct files_struct *fsp, int fd, const void *data, size_t n);
-	SMB_OFF_T (*lseek)(struct files_struct *fsp, int filedes, SMB_OFF_T offset, int whence);
-	ssize_t (*sendfile)(int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
-	int (*rename)(struct connection_struct *conn, const char *old, const char *new);
-	int (*fsync)(struct files_struct *fsp, int fd);
-	int (*stat)(struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf);
-	int (*fstat)(struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf);
-	int (*lstat)(struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf);
-	int (*unlink)(struct connection_struct *conn, const char *path);
-	int (*chmod)(struct connection_struct *conn, const char *path, mode_t mode);
-	int (*fchmod)(struct files_struct *fsp, int fd, mode_t mode);
-	int (*chown)(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid);
-	int (*fchown)(struct files_struct *fsp, int fd, uid_t uid, gid_t gid);
-	int (*chdir)(struct connection_struct *conn, const char *path);
-	char *(*getwd)(struct connection_struct *conn, char *buf);
-	int (*utime)(struct connection_struct *conn, const char *path, struct utimbuf *times);
-	int (*ftruncate)(struct files_struct *fsp, int fd, SMB_OFF_T offset);
-	BOOL (*lock)(struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
-	int (*symlink)(struct connection_struct *conn, const char *oldpath, const char *newpath);
-	int (*readlink)(struct connection_struct *conn, const char *path, char *buf, size_t bufsiz);
-	int (*link)(struct connection_struct *conn, const char *oldpath, const char *newpath);
-	int (*mknod)(struct connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev);
-	char *(*realpath)(struct connection_struct *conn, const char *path, char *resolved_path);
+typedef	int (*VFS_OP_PTR_OPEN)(struct connection_struct *conn, const char *fname, int flags, mode_t mode);
+typedef	int (*VFS_OP_PTR_CLOSE)(struct files_struct *fsp, int fd);
+typedef	ssize_t (*VFS_OP_PTR_READ)(struct files_struct *fsp, int fd, void *data, size_t n);
+typedef	ssize_t (*VFS_OP_PTR_WRITE)(struct files_struct *fsp, int fd, const void *data, size_t n);
+typedef	SMB_OFF_T (*VFS_OP_PTR_LSEEK)(struct files_struct *fsp, int filedes, SMB_OFF_T offset, int whence);
+typedef	ssize_t (*VFS_OP_PTR_SENDFILE)(int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
+typedef	int (*VFS_OP_PTR_RENAME)(struct connection_struct *conn, const char *old, const char *new);
+typedef	int (*VFS_OP_PTR_FSYNC)(struct files_struct *fsp, int fd);
+typedef	int (*VFS_OP_PTR_STAT)(struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf);
+typedef	int (*VFS_OP_PTR_FSTAT)(struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf);
+typedef	int (*VFS_OP_PTR_LSTAT)(struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf);
+typedef	int (*VFS_OP_PTR_UNLINK)(struct connection_struct *conn, const char *path);
+typedef	int (*VFS_OP_PTR_CHMOD)(struct connection_struct *conn, const char *path, mode_t mode);
+typedef	int (*VFS_OP_PTR_FCHMOD)(struct files_struct *fsp, int fd, mode_t mode);
+typedef	int (*VFS_OP_PTR_CHOWN)(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid);
+typedef	int (*VFS_OP_PTR_FCHOWN)(struct files_struct *fsp, int fd, uid_t uid, gid_t gid);
+typedef	int (*VFS_OP_PTR_CHDIR)(struct connection_struct *conn, const char *path);
+typedef	char *(*VFS_OP_PTR_GETWD)(struct connection_struct *conn, char *buf);
+typedef	int (*VFS_OP_PTR_UTIME)(struct connection_struct *conn, const char *path, struct utimbuf *times);
+typedef	int (*VFS_OP_PTR_FTRUNCATE)(struct files_struct *fsp, int fd, SMB_OFF_T offset);
+typedef	BOOL (*VFS_OP_PTR_LOCK)(struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
+typedef	int (*VFS_OP_PTR_SYMLINK)(struct connection_struct *conn, const char *oldpath, const char *newpath);
+typedef	int (*VFS_OP_PTR_READLINK)(struct connection_struct *conn, const char *path, char *buf, size_t bufsiz);
+typedef	int (*VFS_OP_PTR_LINK)(struct connection_struct *conn, const char *oldpath, const char *newpath);
+typedef	int (*VFS_OP_PTR_MKNOD)(struct connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev);
+typedef	char *(*VFS_OP_PTR_REALPATH)(struct connection_struct *conn, const char *path, char *resolved_path);
 
 	/* NT ACL operations. */
 
-	size_t (*fget_nt_acl)(struct files_struct *fsp, int fd, struct security_descriptor_info **ppdesc);
-	size_t (*get_nt_acl)(struct files_struct *fsp, const char *name, struct security_descriptor_info **ppdesc);
-	BOOL (*fset_nt_acl)(struct files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd);
-	BOOL (*set_nt_acl)(struct files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd);
+typedef	size_t (*VFS_OP_PTR_FGET_NT_ACL)(struct files_struct *fsp, int fd, struct security_descriptor_info **ppdesc);
+typedef	size_t (*VFS_OP_PTR_GET_NT_ACL)(struct files_struct *fsp, const char *name, struct security_descriptor_info **ppdesc);
+typedef	BOOL (*VFS_OP_PTR_FSET_NT_ACL)(struct files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd);
+typedef	BOOL (*VFS_OP_PTR_SET_NT_ACL)(struct files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd);
 
 	/* POSIX ACL operations. */
 
-	int (*chmod_acl)(struct connection_struct *conn, const char *name, mode_t mode);
-	int (*fchmod_acl)(struct files_struct *fsp, int fd, mode_t mode);
+typedef	int (*VFS_OP_PTR_CHMOD_ACL)(struct connection_struct *conn, const char *name, mode_t mode);
+typedef	int (*VFS_OP_PTR_FCHMOD_ACL)(struct files_struct *fsp, int fd, mode_t mode);
+
+typedef	int (*VFS_OP_PTR_SYS_ACL_GET_ENTRY)(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
+typedef	int (*VFS_OP_PTR_SYS_ACL_GET_TAG_TYPE)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
+typedef	int (*VFS_OP_PTR_SYS_ACL_GET_PERMSET)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p);
+typedef	void * (*VFS_OP_PTR_SYS_ACL_GET_QUALIFIER)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d);
+typedef	SMB_ACL_T (*VFS_OP_PTR_SYS_ACL_GET_FILE)(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type);
+typedef	SMB_ACL_T (*VFS_OP_PTR_SYS_ACL_GET_FD)(struct files_struct *fsp, int fd);
+typedef	int (*VFS_OP_PTR_SYS_ACL_CLEAR_PERMS)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset);
+typedef	int (*VFS_OP_PTR_SYS_ACL_ADD_PERM)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
+typedef	char * (*VFS_OP_PTR_SYS_ACL_TO_TEXT)(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen);
+typedef	SMB_ACL_T (*VFS_OP_PTR_SYS_ACL_INIT)(struct connection_struct *conn, int count);
+typedef	int (*VFS_OP_PTR_SYS_ACL_CREATE_ENTRY)(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
+typedef	int (*VFS_OP_PTR_SYS_ACL_SET_TAG_TYPE)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype);
+typedef	int (*VFS_OP_PTR_SYS_ACL_SET_QUALIFIER)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual);
+typedef	int (*VFS_OP_PTR_SYS_ACL_SET_PERMSET)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset);
+typedef	int (*VFS_OP_PTR_SYS_ACL_VALID)(struct connection_struct *conn, SMB_ACL_T theacl );
+typedef	int (*VFS_OP_PTR_SYS_ACL_SET_FILE)(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
+typedef	int (*VFS_OP_PTR_SYS_ACL_SET_FD)(struct files_struct *fsp, int fd, SMB_ACL_T theacl);
+typedef	int (*VFS_OP_PTR_SYS_ACL_DELETE_DEF_FILE)(struct connection_struct *conn, const char *path);
+typedef	int (*VFS_OP_PTR_SYS_ACL_GET_PERM)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
+typedef	int (*VFS_OP_PTR_SYS_ACL_FREE_TEXT)(struct connection_struct *conn, char *text);
+typedef	int (*VFS_OP_PTR_SYS_ACL_FREE_ACL)(struct connection_struct *conn, SMB_ACL_T posix_acl);
+typedef	int (*VFS_OP_PTR_SYS_ACL_FREE_QUALIFIER)(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype);
 
-	int (*sys_acl_get_entry)(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
-	int (*sys_acl_get_tag_type)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
-	int (*sys_acl_get_permset)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p);
-	void * (*sys_acl_get_qualifier)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d);
-	SMB_ACL_T (*sys_acl_get_file)(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type);
-	SMB_ACL_T (*sys_acl_get_fd)(struct files_struct *fsp, int fd);
-	int (*sys_acl_clear_perms)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset);
-	int (*sys_acl_add_perm)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
-	char * (*sys_acl_to_text)(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen);
-	SMB_ACL_T (*sys_acl_init)(struct connection_struct *conn, int count);
-	int (*sys_acl_create_entry)(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
-	int (*sys_acl_set_tag_type)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype);
-	int (*sys_acl_set_qualifier)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual);
-	int (*sys_acl_set_permset)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset);
-	int (*sys_acl_valid)(struct connection_struct *conn, SMB_ACL_T theacl );
-	int (*sys_acl_set_file)(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
-	int (*sys_acl_set_fd)(struct files_struct *fsp, int fd, SMB_ACL_T theacl);
-	int (*sys_acl_delete_def_file)(struct connection_struct *conn, const char *path);
-	int (*sys_acl_get_perm)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
-	int (*sys_acl_free_text)(struct connection_struct *conn, char *text);
-	int (*sys_acl_free_acl)(struct connection_struct *conn, SMB_ACL_T posix_acl);
-	int (*sys_acl_free_qualifier)(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype);
+
+struct vfs_ops {
+	/* Disk operations */
+    
+	VFS_OP_PTR_CONNECT connect;
+	VFS_OP_PTR_DISCONNECT disconnect;
+	VFS_OP_PTR_DISK_FREE disk_free;
+    
+	/* Directory operations */
+
+	VFS_OP_PTR_OPENDIR opendir;
+	VFS_OP_PTR_READDIR readdir;
+	VFS_OP_PTR_MKDIR mkdir;
+	VFS_OP_PTR_RMDIR rmdir;
+	VFS_OP_PTR_CLOSEDIR closedir;
+    
+	/* File operations */
+    
+	VFS_OP_PTR_OPEN open;
+	VFS_OP_PTR_CLOSE close;
+	VFS_OP_PTR_READ read;
+	VFS_OP_PTR_WRITE write;
+	VFS_OP_PTR_LSEEK lseek;
+	VFS_OP_PTR_SENDFILE sendfile;
+	VFS_OP_PTR_RENAME rename;
+	VFS_OP_PTR_FSYNC fsync;
+	VFS_OP_PTR_STAT stat;
+	VFS_OP_PTR_FSTAT fstat;
+	VFS_OP_PTR_LSTAT lstat;
+	VFS_OP_PTR_UNLINK unlink;
+	VFS_OP_PTR_CHMOD chmod;
+	VFS_OP_PTR_FCHMOD fchmod;
+	VFS_OP_PTR_CHOWN chown;
+	VFS_OP_PTR_FCHOWN fchown;
+	VFS_OP_PTR_CHDIR chdir;
+	VFS_OP_PTR_GETWD getwd;
+	VFS_OP_PTR_UTIME utime;
+	VFS_OP_PTR_FTRUNCATE ftruncate;
+	VFS_OP_PTR_LOCK lock;
+	VFS_OP_PTR_SYMLINK symlink;
+	VFS_OP_PTR_READLINK readlink;
+	VFS_OP_PTR_LINK link;
+	VFS_OP_PTR_MKNOD mknod;
+	VFS_OP_PTR_REALPATH realpath;
+
+	/* NT ACL operations. */
+
+	VFS_OP_PTR_FGET_NT_ACL fget_nt_acl;
+	VFS_OP_PTR_GET_NT_ACL get_nt_acl;
+	VFS_OP_PTR_FSET_NT_ACL fset_nt_acl;
+	VFS_OP_PTR_SET_NT_ACL set_nt_acl;
+
+	/* POSIX ACL operations. */
+
+	VFS_OP_PTR_CHMOD_ACL chmod_acl;
+	VFS_OP_PTR_FCHMOD_ACL fchmod_acl;
+
+	VFS_OP_PTR_SYS_ACL_GET_ENTRY sys_acl_get_entry;
+	VFS_OP_PTR_SYS_ACL_GET_TAG_TYPE sys_acl_get_tag_type;
+	VFS_OP_PTR_SYS_ACL_GET_PERMSET sys_acl_get_permset;
+	VFS_OP_PTR_SYS_ACL_GET_QUALIFIER sys_acl_get_qualifier;
+	VFS_OP_PTR_SYS_ACL_GET_FILE sys_acl_get_file;
+	VFS_OP_PTR_SYS_ACL_GET_FD sys_acl_get_fd;
+	VFS_OP_PTR_SYS_ACL_CLEAR_PERMS sys_acl_clear_perms;
+	VFS_OP_PTR_SYS_ACL_ADD_PERM sys_acl_add_perm;
+	VFS_OP_PTR_SYS_ACL_TO_TEXT sys_acl_to_text;
+	VFS_OP_PTR_SYS_ACL_INIT sys_acl_init;
+	VFS_OP_PTR_SYS_ACL_CREATE_ENTRY sys_acl_create_entry;
+	VFS_OP_PTR_SYS_ACL_SET_TAG_TYPE sys_acl_set_tag_type;
+	VFS_OP_PTR_SYS_ACL_SET_QUALIFIER sys_acl_set_qualifier;
+	VFS_OP_PTR_SYS_ACL_SET_PERMSET sys_acl_set_permset;
+	VFS_OP_PTR_SYS_ACL_VALID sys_acl_valid;
+	VFS_OP_PTR_SYS_ACL_SET_FILE sys_acl_set_file;
+	VFS_OP_PTR_SYS_ACL_SET_FD sys_acl_set_fd;
+	VFS_OP_PTR_SYS_ACL_DELETE_DEF_FILE sys_acl_delete_def_file;
+	VFS_OP_PTR_SYS_ACL_GET_PERM sys_acl_get_perm;
+	VFS_OP_PTR_SYS_ACL_FREE_TEXT sys_acl_free_text;
+	VFS_OP_PTR_SYS_ACL_FREE_ACL sys_acl_free_acl;
+	VFS_OP_PTR_SYS_ACL_FREE_QUALIFIER sys_acl_free_qualifier;
 };
 
 struct vfs_options {
@@ -321,18 +401,15 @@ typedef struct _vfs_op_tuple {
 	vfs_op_layer layer;
 } vfs_op_tuple;
 
-/*
-    Return vfs_ops filled with current opaque VFS operations. This function is designed to
-    be called from VFS module initialization function for those modules which needs 'direct' VFS
-    access (loggers or initiators of file operations other than connection asks for).
-    
-    Returned vfs_ops must be cleaned up in VFS module's finalizer function (vfs_done_<module_name>)
-    using safe_free().
-    
-    Prototype:
-    struct vfs_ops *smb_vfs_get_opaque_ops();
-    
-    This prototype will be available via include/proto.h
-*/
-
+typedef struct _vfs_object_function_entry {
+	char *name;
+	vfs_op_tuple *op_tuples;
+	int id;
+	struct vfs_ops *default_ops;	/* only access this with 
+					 * vfs_get_default_ops(conn,module_id) or
+					 * vfs_get_default_ops_by_name(conn,module_name)
+					 */
+	struct _vfs_object_function_entry *prev, *next;
+}vfs_object_function_entry;
+	
 #endif /* _VFS_H */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/intl/lang_tdb.c HEAD-modules/source/intl/lang_tdb.c
--- HEAD/source/intl/lang_tdb.c	Sat Nov 23 17:52:43 2002
+++ HEAD-modules/source/intl/lang_tdb.c	Fri Dec  6 09:22:43 2002
@@ -123,7 +123,7 @@ BOOL lang_tdb_init(const char *lang)
 	/* if no lang then we don't translate */
 	if (!lang) return True;
 
-	asprintf(&msg_path, "%s.msg", lib_path((char *)lang));
+	asprintf(&msg_path, "%s.msg", data_path((char *)lang));
 	if (stat(msg_path, &st) != 0) {
 		/* the msg file isn't available */
 		free(msg_path);
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/lib/iconv.c HEAD-modules/source/lib/iconv.c
--- HEAD/source/lib/iconv.c	Wed Nov 13 23:16:04 2002
+++ HEAD-modules/source/lib/iconv.c	Tue Dec 17 09:48:59 2002
@@ -37,26 +37,26 @@ struct charset_functions builtin_functio
 		{NULL, NULL, NULL}
 };
 
-static struct charset_functions *charsets = NULL;
+static struct charset_functions *global_charsets = NULL;
 
-BOOL smb_register_charset(struct charset_functions *funcs) 
+static NTSTATUS smb_register_charset_fn(struct charset_functions *funcs) 
 {
-	struct charset_functions *c = charsets;
+	struct charset_functions *c = global_charsets;
 
 	DEBUG(5, ("Attempting to register new charset %s\n", funcs->name));
 	/* Check whether we already have this charset... */
 	while(c) {
 		if(!strcasecmp(c->name, funcs->name)){ 
 			DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name));
-			return False;
+			return NT_STATUS_OBJECT_NAME_COLLISION;
 		}
 		c = c->next;
 	}
 
 	funcs->next = funcs->prev = NULL;
 	DEBUG(5, ("Registered charset %s\n", funcs->name));
-	DLIST_ADD(charsets, funcs);
-	return True;
+	DLIST_ADD(global_charsets, funcs);
+	return NT_STATUS_OK;
 }
 
 void lazy_initialize_iconv(void)
@@ -67,10 +67,23 @@ void lazy_initialize_iconv(void)
 	if (!initialized) {
 		initialized = True;
 		for(i = 0; builtin_functions[i].name; i++) 
-			smb_register_charset(&builtin_functions[i]);
+			smb_register_charset_fn(&builtin_functions[i]);
 	}
 }
 
+NTSTATUS smb_register_charset(struct charset_functions *funcs, int version) 
+{
+	/* make sure we load the builtin's first */
+	lazy_initialize_iconv();
+
+	if(version != CHARSET_INTERFACE_VERSION){
+		DEBUG(0,("smb_register_charset: module '%s' has wrong the CHARSET_INTERFACE_VERSION\n",funcs->name));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	return smb_register_charset_fn(funcs);
+}
+
 /* if there was an error then reset the internal state,
    this ensures that we don't have a shift state remaining for
    character sets like SJIS */
@@ -139,8 +152,8 @@ smb_iconv_t smb_iconv_open(const char *t
 	struct charset_functions *from, *to;
 	
 	lazy_initialize_iconv();
-	from = charsets;
-	to = charsets;
+	from = global_charsets;
+	to = global_charsets;
 
 	ret = (smb_iconv_t)malloc(sizeof(*ret));
 	if (!ret) {
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/lib/module.c HEAD-modules/source/lib/module.c
--- HEAD/source/lib/module.c	Wed Nov 13 19:52:32 2002
+++ HEAD-modules/source/lib/module.c	Thu Dec 12 13:12:46 2002
@@ -22,46 +22,72 @@
 #include "includes.h"
 
 #ifdef HAVE_DLOPEN
-NTSTATUS smb_load_module(const char *module_name)
+NTSTATUS smb_load_module(const char *module_name, connection_struct *conn, SMB_MODULE_TYPES types)
 {
 	void *handle;
-	init_module_function *init;
+	SMB_MODULE_INIT_FUNCTION *init;
 	NTSTATUS nt_status;
+	pstring full_module_name;
+
+	if (lp_modules_path(SNUM(conn)) && *lp_modules_path(SNUM(conn)) && *module_name!='/') {
+		pstrcpy(full_module_name,lp_modules_path(SNUM(conn)));
+		pstrcat(full_module_name,"/");
+		pstrcat(full_module_name,module_name);
+	} else {
+		pstrcpy(full_module_name,module_name);
+	}
+
+	/* substitutions  */
+	if (conn) {
+		standard_sub_conn(conn,full_module_name,sizeof(pstring));
+	} else {
+		standard_sub_snum(SNUM(conn),full_module_name,sizeof(pstring));
+	}
 
 	/* Always try to use LAZY symbol resolving; if the plugin has 
 	 * backwards compatibility, there might be symbols in the 
 	 * plugin referencing to old (removed) functions
 	 */
-	handle = sys_dlopen(module_name, RTLD_LAZY);
+	handle = sys_dlopen(full_module_name, RTLD_LAZY);
 
 	if(!handle) {
-		DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror()));
+		DEBUG(0, ("Error loading module '%s': %s\n", full_module_name, sys_dlerror()));
 		return NT_STATUS_UNSUCCESSFUL;
 	}
 
-	init = sys_dlsym(handle, "init_module");
+	init = sys_dlsym(handle, SMB_MODULE_SYMBOL_STR);
 
 	if(!init) {
-		DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", module_name, sys_dlerror()));
+		DEBUG(0, ("Error trying to resolve symbol '%s' in %s: %s\nMaybe you need to update your module.\n",
+			SMB_MODULE_SYMBOL_STR, full_module_name, sys_dlerror()));
 		return NT_STATUS_UNSUCCESSFUL;
 	}
 
-	nt_status = init();
+	nt_status = init(types);
 
-	DEBUG(2, ("Module '%s' loaded\n", module_name));
+	DEBUG(2, ("Module '%s' loaded\n", full_module_name));
 
 	return nt_status;
 }
 
 /* Load all modules in list and return number of 
  * modules that has been successfully loaded */
-int smb_load_modules(const char **modules)
+int smb_load_modules(const char **modules, connection_struct *conn, SMB_MODULE_TYPES types)
 {
 	int i;
 	int success = 0;
 
+	if (SNUM(conn) != GLOBAL_SECTION_SNUM && 
+		lp_modules(GLOBAL_SECTION_SNUM)==modules) {
+		/* don't load modules of the global section
+		 * when SNUM(conn) != GLOBAL_SECTION_SNUM  !!!
+		 */
+		DEBUG(5,("smb_load_modules: don't reload global modules on connection start\n")); 
+		return success;
+	}
+
 	for(i = 0; modules[i]; i++){
-		if(NT_STATUS_IS_OK(smb_load_module(modules[i]))) {
+		if(NT_STATUS_IS_OK(smb_load_module(modules[i],conn,types))) {
 			success++;
 		}
 	}
@@ -73,13 +99,13 @@ int smb_load_modules(const char **module
 
 #else /* HAVE_DLOPEN */
 
-NTSTATUS smb_load_module(const char *module_name)
+NTSTATUS smb_load_module(const char *module_name, connection_struct *conn, SMB_MODULE_TYPES types)
 {
 	DEBUG(0,("This samba executable has not been build with plugin support"));
 	return NT_STATUS_NOT_SUPPORTED;
 }
 
-int smb_load_modules(const char **modules)
+int smb_load_modules(const char **modules, connection_struct *conn, SMB_MODULE_TYPES types)
 {
 	DEBUG(0,("This samba executable has not been build with plugin support"));
 	return -1;
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/lib/util.c HEAD-modules/source/lib/util.c
--- HEAD/source/lib/util.c	Thu Dec 12 20:24:26 2002
+++ HEAD-modules/source/lib/util.c	Mon Dec 16 08:55:12 2002
@@ -1723,6 +1723,23 @@ BOOL is_myname_or_ipaddr(const char *s)
 }
 
 /*******************************************************************
+ Is the name specified our workgroup/domain name.
+ Returns true if it is equal, false otherwise.
+********************************************************************/
+
+BOOL is_myworkgroup(const char *s)
+{
+	BOOL ret = False;
+
+	if (strequal(s, lp_workgroup())) {
+		ret=True;
+	}
+
+	DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
+	return(ret);
+}
+
+/*******************************************************************
  Set the horrid remote_arch string based on an enum.
 ********************************************************************/
 
@@ -2164,15 +2181,15 @@ char *pid_path(const char *name)
 /**
  * @brief Returns an absolute path to a file in the Samba lib directory.
  *
- * @param name File to find, relative to LIBDIR.
+ * @param name File to find, relative to DATADIR.
  *
  * @retval Pointer to a static #pstring containing the full path.
  **/
 
-char *lib_path(const char *name)
+char *data_path(const char *name)
 {
 	static pstring fname;
-	snprintf(fname, sizeof(fname), "%s/%s", dyn_LIBDIR, name);
+	snprintf(fname, sizeof(fname), "%s/%s", dyn_DATADIR, name);
 	return fname;
 }
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/lib/util_str.c HEAD-modules/source/lib/util_str.c
--- HEAD/source/lib/util_str.c	Thu Dec 12 20:24:26 2002
+++ HEAD-modules/source/lib/util_str.c	Thu Dec 12 14:04:52 2002
@@ -1232,6 +1232,54 @@ char **str_list_make(const char *string,
 	return list;
 }
 
+char **talloc_str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
+{
+	char **list, **rlist;
+	const char *str;
+	char *s;
+	int num, lsize;
+	pstring tok;
+	
+	if (!string || !*string)
+		return NULL;
+	s = strdup(string);
+	if (!s) {
+		DEBUG(0,("str_list_make: Unable to allocate memory"));
+		return NULL;
+	}
+	if (!sep) sep = LIST_SEP;
+	
+	num = lsize = 0;
+	list = NULL;
+	
+	str = s;
+	while (next_token(&str, tok, sep, sizeof(tok))) {		
+		if (num == lsize) {
+			lsize += S_LIST_ABS;
+			rlist = (char **)talloc_realloc(mem_ctx, list, ((sizeof(char **)) * (lsize +1)));
+			if (!rlist) {
+				DEBUG(0,("str_list_make: Unable to allocate memory"));
+				SAFE_FREE(s);
+				return NULL;
+			} else
+				list = rlist;
+			memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
+		}
+		
+		list[num] = talloc_strdup(mem_ctx,tok);
+		if (!list[num]) {
+			DEBUG(0,("str_list_make: Unable to allocate memory"));
+			SAFE_FREE(s);
+			return NULL;
+		}
+	
+		num++;	
+	}
+	
+	SAFE_FREE(s);
+	return list;
+}
+
 BOOL str_list_copy(char ***dest, const char **src)
 {
 	char **list, **rlist;
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/lib/util_unistr.c HEAD-modules/source/lib/util_unistr.c
--- HEAD/source/lib/util_unistr.c	Sun Nov 10 00:34:38 2002
+++ HEAD-modules/source/lib/util_unistr.c	Fri Dec  6 09:22:43 2002
@@ -43,8 +43,8 @@ void load_case_tables(void)
 	if (initialised) return;
 	initialised = 1;
 
-	upcase_table = map_file(lib_path("upcase.dat"), 0x20000);
-	lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000);
+	upcase_table = map_file(data_path("upcase.dat"), 0x20000);
+	lowcase_table = map_file(data_path("lowcase.dat"), 0x20000);
 
 	/* we would like Samba to limp along even if these tables are
 	   not available */
@@ -108,7 +108,7 @@ void init_valid_table(void)
 	if (initialised && mapped_file) return;
 	initialised = 1;
 
-	valid_table = map_file(lib_path("valid.dat"), 0x10000);
+	valid_table = map_file(data_path("valid.dat"), 0x10000);
 	if (valid_table) {
 		mapped_file = 1;
 		return;
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/modules/developer.c HEAD-modules/source/modules/developer.c
--- HEAD/source/modules/developer.c	Wed Nov 13 20:07:34 2002
+++ HEAD-modules/source/modules/developer.c	Tue Dec 17 11:13:08 2002
@@ -21,6 +21,12 @@
 
 #include "includes.h"
 
+
+static int developer_debug_level = DBGC_VFS;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS developer_debug_level
+
 static struct {
 	char from;
 	char *to;
@@ -123,10 +129,38 @@ static size_t weird_push(void *cd, char 
 	return ir_count;
 }
 
-struct charset_functions weird_functions = {"WEIRD", weird_pull, weird_push};
+static struct charset_functions weird_functions = {"WEIRD", weird_pull, weird_push};
 
-int init_module(void)
+NTSTATUS SMB_MODULE_SYMBOL(SMB_MODULE_TYPES types)
 {
-	smb_register_charset(&weird_functions);
-	return 0;
+	static BOOL init = False;
+	static NTSTATUS nt_status = NT_STATUS_OK;
+	
+	if (init)
+		return nt_status;
+		
+	if (types & MODULE_TYPE_CHARSET) {
+		init = True;
+
+		nt_status = smb_register_charset(&weird_functions,CHARSET_INTERFACE_VERSION);
+		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_COLLISION,nt_status)) {
+			DEBUG(1,("developer: there's allready a charset registered as 'WEIRD'!\n"));
+			return nt_status;
+		} else if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0,("developer: failed to register charset 'WEIRD': %s\n",nt_errstr(nt_status)));
+			return nt_status;	
+		}
+
+		DEBUG(5,("developer: successful registered charset 'WEIRD'\n"));
+		
+		developer_debug_level = debug_add_class("developer");
+		if (developer_debug_level == -1) {
+			developer_debug_level = DBGC_ALL;
+			DEBUG(0, ("developer: Couldn't register custom debugging class!\n"));
+		} else {
+			DEBUG(10, ("developer: Debug class number of 'developer': %d\n", developer_debug_level));
+		}
+	}
+
+	return nt_status;
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/modules/mysql.c HEAD-modules/source/modules/mysql.c
--- HEAD/source/modules/mysql.c	Fri Nov 15 18:01:23 2002
+++ HEAD-modules/source/modules/mysql.c	Tue Dec 17 14:54:15 2002
@@ -25,12 +25,12 @@
 #define CONFIG_LOGON_TIME_DEFAULT			"logon_time"
 #define CONFIG_LOGOFF_TIME_DEFAULT			"logoff_time"
 #define CONFIG_KICKOFF_TIME_DEFAULT			"kickoff_time"
-#define CONFIG_PASS_LAST_SET_TIME_DEFAULT	"pass_last_set_time"
-#define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT	"pass_can_change_time"
-#define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time"
+#define CONFIG_PASS_LAST_SET_TIME_DEFAULT		"pass_last_set_time"
+#define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT		"pass_can_change_time"
+#define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT 		"pass_must_change_time"
 #define CONFIG_USERNAME_DEFAULT 			"username"
 #define CONFIG_DOMAIN_DEFAULT				"domain"
-#define CONFIG_NT_USERNAME_DEFAULT  		"nt_username"
+#define CONFIG_NT_USERNAME_DEFAULT  			"nt_username"
 #define CONFIG_FULLNAME_DEFAULT				"nt_fullname"
 #define CONFIG_HOME_DIR_DEFAULT				"home_dir"
 #define CONFIG_DIR_DRIVE_DEFAULT			"dir_drive"
@@ -40,8 +40,8 @@
 #define CONFIG_WORKSTATIONS_DEFAULT			"workstations"
 #define CONFIG_UNKNOWN_STR_DEFAULT			"unknown_str"
 #define CONFIG_MUNGED_DIAL_DEFAULT			"munged_dial"
-#define CONFIG_UID_DEFAULT					"uid"
-#define CONFIG_GID_DEFAULT					"gid"
+#define CONFIG_UID_DEFAULT				"uid"
+#define CONFIG_GID_DEFAULT				"gid"
 #define CONFIG_USER_SID_DEFAULT				"user_sid"
 #define CONFIG_GROUP_SID_DEFAULT			"group_sid"
 #define CONFIG_LM_PW_DEFAULT				"lm_pw"
@@ -53,13 +53,13 @@
 #define CONFIG_HOURS_LEN_DEFAULT			"hours_len"
 #define CONFIG_UNKNOWN_5_DEFAULT			"unknown_5"
 #define CONFIG_UNKNOWN_6_DEFAULT			"unknown_6"
-#define CONFIG_HOST_DEFAULT					"localhost"
-#define CONFIG_USER_DEFAULT					"samba"
-#define CONFIG_PASS_DEFAULT					""
-#define CONFIG_PORT_DEFAULT					"3306"
-#define CONFIG_DB_DEFAULT					"samba"
+#define CONFIG_HOST_DEFAULT				"localhost"
+#define CONFIG_USER_DEFAULT				"samba"
+#define CONFIG_PASS_DEFAULT				""
+#define CONFIG_PORT_DEFAULT				"3306"
+#define CONFIG_DB_DEFAULT				"samba"
 
-static int mysqlsam_debug_level = DBGC_ALL;
+static int mysqlsam_debug_level = DBGC_PASSDB;
 
 #undef DBGC_CLASS
 #define DBGC_CLASS mysqlsam_debug_level
@@ -147,10 +147,7 @@ static NTSTATUS pdb_mysql_string_field(s
 
 static char * config_value(pdb_mysql_data * data, char *name, char *default_value)
 {
-	if (lp_parm_string(NULL, data->location, name))
-		return lp_parm_string(NULL, data->location, name);
-
-	return default_value;
+	return lp_parm_string(GLOBAL_SECTION_SNUM, data->location, name, default_value);
 }
 
 static char * config_value_write(pdb_mysql_data * data, char *name, char *default_value) {
@@ -945,65 +942,35 @@ static NTSTATUS mysqlsam_enum_group_mapp
 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
+static NTSTATUS mysqlsam_free_private_data(void **privates)
+{
+	/* jelmer what's needed here --metze*/ 
+	return NT_STATUS_OK;
+}
 
-static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_methods ** pdb_method,
-		 const char *location)
+static NTSTATUS mysqlsam_init_private_data(TALLOC_CTX *mem_ctx, void **privates, const char *location)
 {
-	NTSTATUS nt_status;
 	struct pdb_mysql_data *data;
 
-	mysqlsam_debug_level = debug_add_class("mysqlsam");
-	if (mysqlsam_debug_level == -1) {
-		mysqlsam_debug_level = DBGC_ALL;
-		DEBUG(0,
-			  ("mysqlsam: Couldn't register custom debugging class!\n"));
-	}
-
-	if (!pdb_context) {
-		DEBUG(0, ("invalid pdb_methods specified\n"));
-		return NT_STATUS_UNSUCCESSFUL;
-	}
-
-	if (!NT_STATUS_IS_OK
-		(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
-		return nt_status;
+	if ((data = (struct pdb_mysql_data *)talloc_zero(mem_ctx, sizeof(struct pdb_mysql_data)))==NULL) {
+		DEBUG(0,("mysqlsam_init_private_data: talloc_zero() failed\n"));
+		return NT_STATUS_NO_MEMORY;
 	}
-
-	(*pdb_method)->name = "mysqlsam";
-
-	(*pdb_method)->setsampwent = mysqlsam_setsampwent;
-	(*pdb_method)->endsampwent = mysqlsam_endsampwent;
-	(*pdb_method)->getsampwent = mysqlsam_getsampwent;
-	(*pdb_method)->getsampwnam = mysqlsam_getsampwnam;
-	(*pdb_method)->getsampwsid = mysqlsam_getsampwsid;
-	(*pdb_method)->add_sam_account = mysqlsam_add_sam_account;
-	(*pdb_method)->update_sam_account = mysqlsam_update_sam_account;
-	(*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account;
-	(*pdb_method)->getgrsid = mysqlsam_getgrsid;
-	(*pdb_method)->getgrgid = mysqlsam_getgrgid;
-	(*pdb_method)->getgrnam = mysqlsam_getgrnam;
-	(*pdb_method)->add_group_mapping_entry = mysqlsam_add_group_mapping_entry;
-	(*pdb_method)->update_group_mapping_entry = mysqlsam_update_group_mapping_entry;
-	(*pdb_method)->delete_group_mapping_entry = mysqlsam_delete_group_mapping_entry;
-	(*pdb_method)->enum_group_mapping = mysqlsam_enum_group_mapping;
-
-	data = talloc(pdb_context->mem_ctx, sizeof(struct pdb_mysql_data));
-	(*pdb_method)->private_data = data;
+		
 	data->handle = NULL;
 	data->pwent = NULL;
 
 	if (!location) {
-		DEBUG(0, ("No identifier specified. See README for details\n"));
-		return NT_STATUS_INVALID_PARAMETER;
+		data->location = talloc_strdup(mem_ctx,"mysql");
+	} else {
+		data->location = talloc_strdup(mem_ctx,location);
 	}
 
-	data->location = smb_xstrdup(location);
-
 	DEBUG(1,
 		  ("Connecting to database server, host: %s, user: %s, password: %s, database: %s, port: %ld\n",
 		   config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
 		   config_value(data, "mysql user", CONFIG_USER_DEFAULT),
-		   config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
+		   "(ups!!!)"/*config_value(data, "mysql password", CONFIG_PASS_DEFAULT)*/,
 		   config_value(data, "mysql database", CONFIG_DB_DEFAULT),
 		   xatol(config_value(data, "mysql port", CONFIG_PORT_DEFAULT))));
 
@@ -1028,16 +995,66 @@ static NTSTATUS mysqlsam_init(struct pdb
 	}
 	
 	DEBUG(5, ("Connected to mysql db\n"));
-
+	(*privates) = data;
 	return NT_STATUS_OK;
 }
 
-int init_module(void);
+static struct pdb_method_ops mysqlsam_ops = {
+	mysqlsam_setsampwent,
+	mysqlsam_endsampwent,
+	mysqlsam_getsampwent,
+	mysqlsam_getsampwnam,
+	mysqlsam_getsampwsid,
+	mysqlsam_add_sam_account,
+	mysqlsam_update_sam_account,
+	mysqlsam_delete_sam_account,
+
+	mysqlsam_getgrsid,
+	mysqlsam_getgrgid,
+	mysqlsam_getgrnam,
+	mysqlsam_add_group_mapping_entry,
+	mysqlsam_update_group_mapping_entry,
+	mysqlsam_delete_group_mapping_entry,
+	mysqlsam_enum_group_mapping,
+
+	mysqlsam_init_private_data,
+	mysqlsam_free_private_data
+};
+
+static struct pdb_backend_function_entry mysqlsam_register = {
+	"mysql",
+	&mysqlsam_ops	
+};
 
-int init_module() 
+NTSTATUS SMB_MODULE_SYMBOL(SMB_MODULE_TYPES types) 
 {
-	if(smb_register_passdb("mysql", mysqlsam_init, PASSDB_INTERFACE_VERSION))
-		return 0;
-
-	return 1;
-}
+	static BOOL init = False;
+	static NTSTATUS nt_status = NT_STATUS_OK;
+	
+	if (init)
+		return nt_status;
+		
+	if (types & MODULE_TYPE_PDB) {
+		init = True;
+
+		nt_status = smb_register_passdb(&mysqlsam_register, PASSDB_INTERFACE_VERSION);
+		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_COLLISION,nt_status)) {
+			DEBUG(1,("mysqlsam: there's allready a passdb backend registered as 'mysql'!\n"));
+			return nt_status;
+		} else if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0,("mysqlsam: failed to register: %s\n",nt_errstr(nt_status)));
+			return nt_status;	
+		}
+		DEBUG(5,("mysqlsam: successful registered\n"));
+
+		mysqlsam_debug_level = debug_add_class("mysql");
+		if (mysqlsam_debug_level == -1) {
+			mysqlsam_debug_level = DBGC_PASSDB;
+			DEBUG(0, ("mysqlsam: Couldn't register custom debugging class!\n"));
+		} else {
+			DEBUG(10, ("mysqlsam: Debug class number of 'mysql': %d\n", mysqlsam_debug_level));
+		}		
+	}
+	
+	return nt_status;
+}
\ No newline at end of file
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/modules/vfs_audit.c HEAD-modules/source/modules/vfs_audit.c
--- HEAD/source/modules/vfs_audit.c	Wed Nov 13 14:10:29 2002
+++ HEAD-modules/source/modules/vfs_audit.c	Tue Dec 17 11:44:11 2002
@@ -4,6 +4,7 @@
  *
  * Copyright (C) Tim Potter, 1999-2000
  * Copyright (C) Alexander Bokovoy, 2002
+ * Copyright (C) Stefan (metze) Metzmacher
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,31 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "config.h"
-#include <stdio.h>
-#include <sys/stat.h>
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#include <syslog.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include <errno.h>
-#include <string.h>
-#include <includes.h>
-#include <vfs.h>
-
-#ifndef SYSLOG_FACILITY
-#define SYSLOG_FACILITY   LOG_USER
-#endif
-
-#ifndef SYSLOG_PRIORITY
-#define SYSLOG_PRIORITY   LOG_NOTICE
-#endif
+
+#include "includes.h"
+
 
 /* Function prototypes */
 
@@ -64,57 +43,62 @@ static int audit_fchmod_acl(struct files
 
 /* VFS operations */
 
-static struct vfs_ops default_vfs_ops;   /* For passthrough operation */
-static struct smb_vfs_handle_struct *audit_handle;
-
-static vfs_op_tuple audit_ops[] = {
+static vfs_op_tuple audit_op_tuples[] = {
     
 	/* Disk operations */
 
-	{audit_connect, 	SMB_VFS_OP_CONNECT, 	SMB_VFS_LAYER_LOGGER},
-	{audit_disconnect, 	SMB_VFS_OP_DISCONNECT, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_connect), 	SMB_VFS_OP_CONNECT, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_disconnect), 	SMB_VFS_OP_DISCONNECT, 	SMB_VFS_LAYER_LOGGER},
 
 	/* Directory operations */
 
-	{audit_opendir, 	SMB_VFS_OP_OPENDIR, 	SMB_VFS_LAYER_LOGGER},
-	{audit_mkdir, 		SMB_VFS_OP_MKDIR, 	SMB_VFS_LAYER_LOGGER},
-	{audit_rmdir, 		SMB_VFS_OP_RMDIR, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_opendir), 	SMB_VFS_OP_OPENDIR, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_mkdir), 		SMB_VFS_OP_MKDIR, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_rmdir), 		SMB_VFS_OP_RMDIR, 	SMB_VFS_LAYER_LOGGER},
 
 	/* File operations */
 
-	{audit_open, 		SMB_VFS_OP_OPEN, 	SMB_VFS_LAYER_LOGGER},
-	{audit_close, 		SMB_VFS_OP_CLOSE, 	SMB_VFS_LAYER_LOGGER},
-	{audit_rename, 		SMB_VFS_OP_RENAME, 	SMB_VFS_LAYER_LOGGER},
-	{audit_unlink, 		SMB_VFS_OP_UNLINK, 	SMB_VFS_LAYER_LOGGER},
-	{audit_chmod, 		SMB_VFS_OP_CHMOD, 	SMB_VFS_LAYER_LOGGER},
-	{audit_fchmod, 		SMB_VFS_OP_FCHMOD, 	SMB_VFS_LAYER_LOGGER},
-	{audit_chmod_acl, 	SMB_VFS_OP_CHMOD_ACL, 	SMB_VFS_LAYER_LOGGER},
-	{audit_fchmod_acl, 	SMB_VFS_OP_FCHMOD_ACL, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_open), 		SMB_VFS_OP_OPEN, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_close), 		SMB_VFS_OP_CLOSE, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_rename), 		SMB_VFS_OP_RENAME, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_unlink), 		SMB_VFS_OP_UNLINK, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_chmod), 		SMB_VFS_OP_CHMOD, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_fchmod), 		SMB_VFS_OP_FCHMOD, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_chmod_acl), 	SMB_VFS_OP_CHMOD_ACL, 	SMB_VFS_LAYER_LOGGER},
+	{VFS_OP(audit_fchmod_acl), 	SMB_VFS_OP_FCHMOD_ACL, 	SMB_VFS_LAYER_LOGGER},
 	
 	/* Finish VFS operations definition */
 	
 	{NULL, 			SMB_VFS_OP_NOOP, 	SMB_VFS_LAYER_NOOP}
 };
 
-/* VFS initialisation function.  Return vfs_op_tuple array back to SAMBA. */
+static vfs_object_function_entry audit_register = {
+	"audit",
+	audit_op_tuples,
+	(-1)
+};
 
-vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, 
-			struct smb_vfs_handle_struct *vfs_handle)
+static int audit_syslog_facility(struct connection_struct *conn)
 {
-	*vfs_version = SMB_VFS_INTERFACE_VERSION;
-	memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
-	
-	audit_handle = vfs_handle;
+	/* fix me: let this be configurable by:
+	 *	lp_param_enum(SNUM(conn),"vfs_audit","syslog facility",
+	 *		audit_enum_facility,LOG_USER); 
+	 */
+	return LOG_USER;
+}
 
-	openlog("smbd_audit", LOG_PID, SYSLOG_FACILITY);
-	syslog(SYSLOG_PRIORITY, "VFS_INIT: vfs_ops loaded\n");
-	return audit_ops;
+static int audit_syslog_priority(struct connection_struct *conn)
+{
+	/* fix me: let this be configurable by:
+	 *	lp_param_enum(SNUM(conn),"vfs_audit","syslog priority",
+	 *		audit_enum_priority,LOG_USER); 
+	 */
+	return LOG_NOTICE;
 }
 
-/* VFS finalization function. */
-void vfs_done(connection_struct *conn)
+static struct vfs_ops *audit_get_def_vfs_ops(struct connection_struct *conn)
 {
-	syslog(SYSLOG_PRIORITY, "VFS_DONE: vfs module unloaded\n");
+	return vfs_get_default_ops(conn,audit_register.id);	
 }
 
 /* Implementation of vfs_ops.  Pass everything on to the default
@@ -122,23 +106,55 @@ void vfs_done(connection_struct *conn)
 
 static int audit_connect(struct connection_struct *conn, const char *svc, const char *user)
 {
-	syslog(SYSLOG_PRIORITY, "connect to service %s by user %s\n", 
+	struct vfs_ops *default_vfs_ops;
+	int ret;
+	
+	openlog("smbd_audit", LOG_PID, audit_syslog_facility(conn));
+
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	syslog(audit_syslog_priority(conn), "connect to service %s by user %s\n", 
 	       svc, user);
 
-	return default_vfs_ops.connect(conn, svc, user);
+	ret = default_vfs_ops->connect(conn, svc, user);
+
+	return ret;
 }
 
 static void audit_disconnect(struct connection_struct *conn)
 {
-	syslog(SYSLOG_PRIORITY, "disconnected\n");
-	default_vfs_ops.disconnect(conn);
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return;
+	}
+	
+	syslog(audit_syslog_priority(conn), "disconnected\n");
+	default_vfs_ops->disconnect(conn);
+
+	return;
 }
 
 static DIR *audit_opendir(struct connection_struct *conn, const char *fname)
 {
-	DIR *result = default_vfs_ops.opendir(conn, fname);
+	DIR *result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return NULL;
+	}
+	
+	result = default_vfs_ops->opendir(conn, fname);
 
-	syslog(SYSLOG_PRIORITY, "opendir %s %s%s\n",
+	syslog(audit_syslog_priority(conn), "opendir %s %s%s\n",
 	       fname,
 	       (result == NULL) ? "failed: " : "",
 	       (result == NULL) ? strerror(errno) : "");
@@ -148,9 +164,18 @@ static DIR *audit_opendir(struct connect
 
 static int audit_mkdir(struct connection_struct *conn, const char *path, mode_t mode)
 {
-	int result = default_vfs_ops.mkdir(conn, path, mode);
-
-	syslog(SYSLOG_PRIORITY, "mkdir %s %s%s\n", 
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->mkdir(conn, path, mode);
+	
+	syslog(audit_syslog_priority(conn), "mkdir %s %s%s\n", 
 	       path,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -160,9 +185,18 @@ static int audit_mkdir(struct connection
 
 static int audit_rmdir(struct connection_struct *conn, const char *path)
 {
-	int result = default_vfs_ops.rmdir(conn, path);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->rmdir(conn, path);
 
-	syslog(SYSLOG_PRIORITY, "rmdir %s %s%s\n", 
+	syslog(audit_syslog_priority(conn), "rmdir %s %s%s\n", 
 	       path, 
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -172,9 +206,18 @@ static int audit_rmdir(struct connection
 
 static int audit_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode)
 {
-	int result = default_vfs_ops.open(conn, fname, flags, mode);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->open(conn, fname, flags, mode);
 
-	syslog(SYSLOG_PRIORITY, "open %s (fd %d) %s%s%s\n", 
+	syslog(audit_syslog_priority(conn), "open %s (fd %d) %s%s%s\n", 
 	       fname, result,
 	       ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", 
 	       (result < 0) ? "failed: " : "",
@@ -185,9 +228,18 @@ static int audit_open(struct connection_
 
 static int audit_close(struct files_struct *fsp, int fd)
 {
-	int result = default_vfs_ops.close(fsp, fd);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(fsp->conn))==NULL) {
+		syslog(audit_syslog_priority(fsp->conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(fsp->conn)),SNUM(fsp->conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->close(fsp, fd);
 
-	syslog(SYSLOG_PRIORITY, "close fd %d %s%s\n",
+	syslog(audit_syslog_priority(fsp->conn), "close fd %d %s%s\n",
 	       fd,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -197,9 +249,18 @@ static int audit_close(struct files_stru
 
 static int audit_rename(struct connection_struct *conn, const char *old, const char *new)
 {
-	int result = default_vfs_ops.rename(conn, old, new);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->rename(conn, old, new);
 
-	syslog(SYSLOG_PRIORITY, "rename %s -> %s %s%s\n",
+	syslog(audit_syslog_priority(conn), "rename %s -> %s %s%s\n",
 	       old, new,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -209,9 +270,18 @@ static int audit_rename(struct connectio
 
 static int audit_unlink(struct connection_struct *conn, const char *path)
 {
-	int result = default_vfs_ops.unlink(conn, path);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->unlink(conn, path);
 
-	syslog(SYSLOG_PRIORITY, "unlink %s %s%s\n",
+	syslog(audit_syslog_priority(conn), "unlink %s %s%s\n",
 	       path,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -221,9 +291,18 @@ static int audit_unlink(struct connectio
 
 static int audit_chmod(struct connection_struct *conn, const char *path, mode_t mode)
 {
-	int result = default_vfs_ops.chmod(conn, path, mode);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->chmod(conn, path, mode);
 
-	syslog(SYSLOG_PRIORITY, "chmod %s mode 0x%x %s%s\n",
+	syslog(audit_syslog_priority(conn), "chmod %s mode 0x%x %s%s\n",
 	       path, mode,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -233,9 +312,18 @@ static int audit_chmod(struct connection
 
 static int audit_chmod_acl(struct connection_struct *conn, const char *path, mode_t mode)
 {
-	int result = default_vfs_ops.chmod_acl(conn, path, mode);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(conn))==NULL) {
+		syslog(audit_syslog_priority(conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(conn)),SNUM(conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->chmod_acl(conn, path, mode);
 
-	syslog(SYSLOG_PRIORITY, "chmod_acl %s mode 0x%x %s%s\n",
+	syslog(audit_syslog_priority(conn), "chmod_acl %s mode 0x%x %s%s\n",
 	       path, mode,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -245,9 +333,18 @@ static int audit_chmod_acl(struct connec
 
 static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode)
 {
-	int result = default_vfs_ops.fchmod(fsp, fd, mode);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(fsp->conn))==NULL) {
+		syslog(audit_syslog_priority(fsp->conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(fsp->conn)),SNUM(fsp->conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->fchmod(fsp, fd, mode);
 
-	syslog(SYSLOG_PRIORITY, "fchmod %s mode 0x%x %s%s\n",
+	syslog(audit_syslog_priority(fsp->conn), "fchmod %s mode 0x%x %s%s\n",
 	       fsp->fsp_name, mode,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
@@ -257,12 +354,46 @@ static int audit_fchmod(struct files_str
 
 static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode)
 {
-	int result = default_vfs_ops.fchmod_acl(fsp, fd, mode);
+	int result;
+	struct vfs_ops *default_vfs_ops;
+	
+	if ((default_vfs_ops = audit_get_def_vfs_ops(fsp->conn))==NULL) {
+		syslog(audit_syslog_priority(fsp->conn),"can't get default ops for service '%s' [%d]\n",
+			lp_servicename(SNUM(fsp->conn)),SNUM(fsp->conn));
+		return (-1);
+	}
+	
+	result = default_vfs_ops->fchmod_acl(fsp, fd, mode);
 
-	syslog(SYSLOG_PRIORITY, "fchmod_acl %s mode 0x%x %s%s\n",
+	syslog(audit_syslog_priority(fsp->conn), "fchmod_acl %s mode 0x%x %s%s\n",
 	       fsp->fsp_name, mode,
 	       (result < 0) ? "failed: " : "",
 	       (result < 0) ? strerror(errno) : "");
 
 	return result;
+}
+
+NTSTATUS SMB_MODULE_SYMBOL(SMB_MODULE_TYPES types) 
+{
+	static BOOL init = False;
+	static NTSTATUS nt_status = NT_STATUS_OK;
+	
+	if (init)
+		return nt_status;
+
+	if (types & MODULE_TYPE_VFS) {
+		init = True;
+
+		nt_status = smb_register_vfs(&audit_register, SMB_VFS_INTERFACE_VERSION);
+		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_COLLISION,nt_status)) {
+			DEBUG(1,("audit: there's allready a vfs module registered as 'audit'!\n"));
+			return nt_status;
+		} else if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0,("audit: failed to register: %s\n",nt_errstr(nt_status)));
+			return nt_status;	
+		}
+		DEBUG(5,("audit: successful registered\n"));
+	}
+
+	return nt_status;
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/modules/vfs_netatalk.c HEAD-modules/source/modules/vfs_netatalk.c
--- HEAD/source/modules/vfs_netatalk.c	Wed Nov 13 14:10:29 2002
+++ HEAD-modules/source/modules/vfs_netatalk.c	Tue Dec 17 11:48:25 2002
@@ -1,7 +1,8 @@
 /* 
  * AppleTalk VFS module for Samba-3.x
  *
- * Copyright (C) Alexei Kotovich, 2002
+ * Copyright (C) Alexei Kotovich		2002
+ * Copyright (C) Stefan (metze) Metzmacher	2002
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,26 +19,21 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "config.h"
-#include <stdio.h>
-#include <sys/stat.h>
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include <errno.h>
-#include <string.h>
-#include <includes.h>
-#include <vfs.h>
 
+#include "includes.h"
+
+#ifdef APPLEDOUBLE
+#undef APPLEDOUBLE
+#endif
 #define APPLEDOUBLE	".AppleDouble"
 #define ADOUBLEMODE	0777
 
+
+static int atalk_debug_level = DBGC_VFS;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS atalk_debug_level
+
 /* atalk functions */
 
 static int atalk_build_paths(TALLOC_CTX *ctx, const char *path,
@@ -46,8 +42,12 @@ static int atalk_build_paths(TALLOC_CTX 
 
 static int atalk_unlink_file(const char *path);
 
-static struct vfs_ops default_vfs_ops;	/* For passthrough operation */
-static struct smb_vfs_handle_struct *atalk_handle;
+static vfs_object_function_entry atalk_register; 
+
+static struct vfs_ops *atalk_get_def_vfs_ops(struct connection_struct *conn)
+{
+	return vfs_get_default_ops(conn,atalk_register.id);
+}
 
 static int atalk_get_path_ptr(char *path)
 {
@@ -190,9 +190,15 @@ static void atalk_rrmdir(TALLOC_CTX *ctx
 
 DIR *atalk_opendir(struct connection_struct *conn, const char *fname)
 {
+	struct vfs_ops *default_vfs_ops;
 	DIR *ret = 0;
 	
-	ret = default_vfs_ops.opendir(conn, fname);
+	if ((default_vfs_ops = atalk_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("netatalk: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return NULL;
+	}
+
+	ret = default_vfs_ops->opendir(conn, fname);
 
 	/*
 	 * when we try to perform delete operation upon file which has fork
@@ -211,10 +217,16 @@ DIR *atalk_opendir(struct connection_str
 
 static int atalk_rmdir(struct connection_struct *conn, const char *path)
 {
+	struct vfs_ops *default_vfs_ops;
 	BOOL add = False;
-	TALLOC_CTX *ctx = 0;
+	TALLOC_CTX *ctx = NULL;
 	char *dpath;
 
+	if ((default_vfs_ops = atalk_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("netatalk: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return (-1);
+	}
+
 	if (!conn || !conn->origpath || !path) goto exit_rmdir;
 
 	/* due to there is no way to change bDeleteVetoFiles variable
@@ -234,13 +246,14 @@ static int atalk_rmdir(struct connection
 
 exit_rmdir:
 	talloc_destroy(ctx);
-	return default_vfs_ops.rmdir(conn, path);
+	return default_vfs_ops->rmdir(conn, path);
 }
 
 /* File operations */
 
 static int atalk_rename(struct connection_struct *conn, const char *old, const char *new)
 {
+	struct vfs_ops *default_vfs_ops;
 	int ret = 0;
 	char *adbl_path = 0;
 	char *orig_path = 0;
@@ -248,7 +261,12 @@ static int atalk_rename(struct connectio
 	SMB_STRUCT_STAT orig_info;
 	TALLOC_CTX *ctx;
 
-	ret = default_vfs_ops.rename(conn, old, new);
+	if ((default_vfs_ops = atalk_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("netatalk: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return (-1);
+	}
+
+	ret = default_vfs_ops->rename(conn, old, new);
 
 	if (!conn || !old) return ret;
 
@@ -273,6 +291,7 @@ exit_rename:
 
 static int atalk_unlink(struct connection_struct *conn, const char *path)
 {
+	struct vfs_ops *default_vfs_ops;
 	int ret = 0, i;
 	char *adbl_path = 0;
 	char *orig_path = 0;
@@ -280,7 +299,12 @@ static int atalk_unlink(struct connectio
 	SMB_STRUCT_STAT orig_info;
 	TALLOC_CTX *ctx;
 
-	ret = default_vfs_ops.unlink(conn, path);
+	if ((default_vfs_ops = atalk_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("netatalk: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return (-1);
+	}
+
+	ret = default_vfs_ops->unlink(conn, path);
 
 	if (!conn || !path) return ret;
 
@@ -329,6 +353,7 @@ exit_unlink:	
 
 static int atalk_chmod(struct connection_struct *conn, const char *path, mode_t mode)
 {
+	struct vfs_ops *default_vfs_ops;
 	int ret = 0;
 	char *adbl_path = 0;
 	char *orig_path = 0;
@@ -336,7 +361,12 @@ static int atalk_chmod(struct connection
 	SMB_STRUCT_STAT orig_info;
 	TALLOC_CTX *ctx;
 
-	ret = default_vfs_ops.chmod(conn, path, mode);
+	if ((default_vfs_ops = atalk_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("netatalk: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return (-1);
+	}
+
+	ret = default_vfs_ops->chmod(conn, path, mode);
 
 	if (!conn || !path) return ret;
 
@@ -361,6 +391,7 @@ exit_chmod:	
 
 static int atalk_chown(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid)
 {
+	struct vfs_ops *default_vfs_ops;
 	int ret = 0;
 	char *adbl_path = 0;
 	char *orig_path = 0;
@@ -368,7 +399,12 @@ static int atalk_chown(struct connection
 	SMB_STRUCT_STAT orig_info;
 	TALLOC_CTX *ctx;
 
-	ret = default_vfs_ops.chown(conn, path, uid, gid);
+	if ((default_vfs_ops = atalk_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("netatalk: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return (-1);
+	}
+
+	ret = default_vfs_ops->chown(conn, path, uid, gid);
 
 	if (!conn || !path) return ret;
 
@@ -391,40 +427,60 @@ exit_chown:	
 	return ret;
 }
 
-static vfs_op_tuple atalk_ops[] = {
+static vfs_op_tuple atalk_op_tuples[] = {
     
 	/* Directory operations */
 
-	{atalk_opendir, 	SMB_VFS_OP_OPENDIR, 	SMB_VFS_LAYER_TRANSPARENT},
-	{atalk_rmdir, 		SMB_VFS_OP_RMDIR, 	SMB_VFS_LAYER_TRANSPARENT},
+	{VFS_OP(atalk_opendir),	SMB_VFS_OP_OPENDIR, 	SMB_VFS_LAYER_TRANSPARENT},
+	{VFS_OP(atalk_rmdir),	SMB_VFS_OP_RMDIR, 	SMB_VFS_LAYER_TRANSPARENT},
 
 	/* File operations */
 
-	{atalk_rename, 		SMB_VFS_OP_RENAME, 	SMB_VFS_LAYER_TRANSPARENT},
-	{atalk_unlink, 		SMB_VFS_OP_UNLINK, 	SMB_VFS_LAYER_TRANSPARENT},
-	{atalk_chmod, 		SMB_VFS_OP_CHMOD, 	SMB_VFS_LAYER_TRANSPARENT},
-	{atalk_chown,		SMB_VFS_OP_CHOWN,	SMB_VFS_LAYER_TRANSPARENT},
+	{VFS_OP(atalk_rename), 		SMB_VFS_OP_RENAME, 	SMB_VFS_LAYER_TRANSPARENT},
+	{VFS_OP(atalk_unlink), 		SMB_VFS_OP_UNLINK, 	SMB_VFS_LAYER_TRANSPARENT},
+	{VFS_OP(atalk_chmod), 		SMB_VFS_OP_CHMOD, 	SMB_VFS_LAYER_TRANSPARENT},
+	{VFS_OP(atalk_chown),		SMB_VFS_OP_CHOWN,	SMB_VFS_LAYER_TRANSPARENT},
 	
 	/* Finish VFS operations definition */
 	
 	{NULL, 			SMB_VFS_OP_NOOP, 	SMB_VFS_LAYER_NOOP}
 };
 
-/* VFS initialisation function.  Return vfs_op_tuple array back to SAMBA. */
-vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,
-  struct smb_vfs_handle_struct *vfs_handle)
+static vfs_object_function_entry atalk_register = {
+	"netatalk",
+	atalk_op_tuples,
+	(-1)
+};
+
+NTSTATUS SMB_MODULE_SYMBOL(SMB_MODULE_TYPES types) 
 {
-	*vfs_version = SMB_VFS_INTERFACE_VERSION;
-	memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
+	static BOOL init = False;
+	static NTSTATUS nt_status = NT_STATUS_OK;
 	
-	atalk_handle = vfs_handle;
-
-	DEBUG(3, ("ATALK: vfs module loaded\n"));
-	return atalk_ops;
-}
+	if (init)
+		return nt_status;
+		
+	if (types & MODULE_TYPE_VFS) {
+		init = True;
+
+		nt_status = smb_register_vfs(&atalk_register, SMB_VFS_INTERFACE_VERSION);
+		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_COLLISION,nt_status)) {
+			DEBUG(1,("netatalk: there's allready a vfs module registered as 'netatalk'!\n"));
+			return nt_status;
+		} else if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0,("netatalk: failed to register: %s\n",nt_errstr(nt_status)));
+			return nt_status;	
+		}
+		DEBUG(5,("netatalk: successful registered\n"));
 
-/* VFS finalization function. */
-void vfs_done(connection_struct *conn)
-{
-	DEBUG(3, ("ATALK: vfs module unloaded\n"));
+		atalk_debug_level = debug_add_class("netatalk");
+		if (atalk_debug_level == -1) {
+			atalk_debug_level = DBGC_VFS;
+			DEBUG(0, ("netatalk: Couldn't register custom debugging class!\n"));
+		} else {
+			DEBUG(10, ("netatalk: Debug class number of 'netatalk': %d\n", atalk_debug_level));
+		}		
+	}
+	
+	return nt_status;
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/modules/vfs_recycle.c HEAD-modules/source/modules/vfs_recycle.c
--- HEAD/source/modules/vfs_recycle.c	Mon Dec  9 16:53:06 2002
+++ HEAD-modules/source/modules/vfs_recycle.c	Tue Dec 17 11:44:31 2002
@@ -6,6 +6,7 @@
  * Copyright (C) 2002, Alexander Bokovoy - cascaded VFS adoption,
  * Copyright (C) 2002, Juergen Hasch - added some options.
  * Copyright (C) 2002, Simo Sorce
+ * Copyright (C) 2002, Stefan (metze) Metzmacher
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,53 +25,21 @@
 
 #include "includes.h"
 
-#define ALLOC_CHECK(ptr, label) do { if ((ptr) == NULL) { DEBUG(0, ("recycle.bin: out of memory!\n")); errno = ENOMEM; goto label; } } while(0)
+#define ALLOC_CHECK(ptr, label) do { if ((ptr) == NULL) { DEBUG(0, ("recycle_bin: out of memory!\n")); errno = ENOMEM; goto label; } } while(0)
 
-static int vfs_recycle_debug_level = DBGC_VFS;
+static int recycle_debug_level = DBGC_VFS;
 
 #undef DBGC_CLASS
-#define DBGC_CLASS vfs_recycle_debug_level
+#define DBGC_CLASS recycle_debug_level
 
 static const char *delimiter = "|";		/* delimiter for options */
 
-/* One per connection */
-
-typedef struct recycle_bin_struct
-{
-	TALLOC_CTX *mem_ctx;
-	char	*repository;		/* name of the recycle bin directory */
-	BOOL	keep_dir_tree;		/* keep directory structure of deleted file in recycle bin */
-	BOOL	versions;		/* create versions of deleted files with identical name */
-	BOOL	touch;			/* touch access date of deleted file */
-	char	*exclude;		/* which files to exclude */
-	char	*exclude_dir;		/* which directories to exclude */
-	char	*noversions;		/* which files to exclude from versioning */
-	SMB_OFF_T maxsize;		/* maximum file size to be saved */
-} recycle_bin_struct;
-
-typedef struct recycle_bin_connections {
-	int conn;
-	recycle_bin_struct *data;
-	struct recycle_bin_connections *next;
-} recycle_bin_connections;
-
-typedef struct recycle_bin_private_data {
-	TALLOC_CTX *mem_ctx;
-	recycle_bin_connections *conns;
-} recycle_bin_private_data;
-
-struct smb_vfs_handle_struct *recycle_bin_private_handle;
-
-/* VFS operations */
-static struct vfs_ops default_vfs_ops;   /* For passthrough operation */
 
 static int recycle_connect(struct connection_struct *conn, const char *service, const char *user);
 static void recycle_disconnect(struct connection_struct *conn);
 static int recycle_unlink(connection_struct *, const char *);
 
-#define VFS_OP(x) ((void *) x)
-
-static vfs_op_tuple recycle_ops[] = {
+static vfs_op_tuple recycle_op_tuples[] = {
 
 	/* Disk operations */
 	{VFS_OP(recycle_connect),	SMB_VFS_OP_CONNECT,	SMB_VFS_LAYER_TRANSPARENT},
@@ -82,221 +51,149 @@ static vfs_op_tuple recycle_ops[] = {
 	{NULL,				SMB_VFS_OP_NOOP,	SMB_VFS_LAYER_NOOP}
 };
 
-/**
- * VFS initialisation function.
- *
- * @retval initialised vfs_op_tuple array
- **/
-vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,
-			struct smb_vfs_handle_struct *vfs_handle)
+static vfs_object_function_entry recycle_register = {
+	"recycle_bin",
+	recycle_op_tuples,
+	(-1)
+};
+
+static struct vfs_ops *recycle_get_def_vfs_ops(struct connection_struct *conn)
 {
-	TALLOC_CTX *mem_ctx = NULL;
+	return vfs_get_default_ops(conn,recycle_register.id);	
+}
 
-	DEBUG(10, ("Initializing VFS module recycle\n"));
-	*vfs_version = SMB_VFS_INTERFACE_VERSION;
-	memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
-	vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin");
-	if (vfs_recycle_debug_level == -1) {
-		vfs_recycle_debug_level = DBGC_VFS;
-		DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n"));
-	} else {
-		DEBUG(0, ("vfs_recycle: Debug class number of 'vfs_recycle': %d\n", vfs_recycle_debug_level));
-	}
+static const char *recycle_repository(struct connection_struct *conn)
+{
+	char *tmp_str = NULL;
+	
+	tmp_str = lp_parm_string(SNUM(conn), "recycle_bin", "repository",".recycle");
 
-	recycle_bin_private_handle = vfs_handle;
-	if (!(mem_ctx = talloc_init_named("recycle bin data"))) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return NULL;
-	}
+	DEBUG(10, ("recycle_bin: repository = %s\n", tmp_str));
+	
+	return tmp_str;
+}
 
-	recycle_bin_private_handle->data = talloc(mem_ctx, sizeof(recycle_bin_private_data));
-	if (recycle_bin_private_handle->data == NULL) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return NULL;
-	}
-	((recycle_bin_private_data *)(recycle_bin_private_handle->data))->mem_ctx = mem_ctx;
-	((recycle_bin_private_data *)(recycle_bin_private_handle->data))->conns = NULL;
+static BOOL recycle_keep_dir_tree(struct connection_struct *conn)
+{
+	BOOL ret;
+	
+	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "keeptree",False);
 
-	return recycle_ops;
+	DEBUG(10, ("recycle_bin: keeptree = %s\n", ret?"True":"False"));
+	
+	return ret;
 }
 
-/**
- * VFS finalization function.
- *
- **/
-void vfs_done(void)
+static BOOL recycle_versions(struct connection_struct *conn)
 {
-	recycle_bin_private_data *recdata;
-	recycle_bin_connections *recconn;
+	BOOL ret;
+	
+	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "versions",False);
 
-	DEBUG(10, ("Unloading/Cleaning VFS module recycle bin\n"));
+	DEBUG(10, ("recycle_bin: versions = %s\n", ret?"True":"False"));
+	
+	return ret;
+}
 
-	if (recycle_bin_private_handle)
-		recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
-	else {
-		DEBUG(0, ("Recycle bin not initialized!\n"));
-		return;
-	}
+static BOOL recycle_touch(struct connection_struct *conn)
+{
+	BOOL ret;
+	
+	ret = lp_parm_bool(SNUM(conn), "recycle_bin", "touch",False);
 
-	if (recdata) {
-		if (recdata->conns) {
-			recconn = recdata->conns;
-			while (recconn) {
-				talloc_destroy(recconn->data->mem_ctx);
-				recconn = recconn->next;
-			}
-		}
-		if (recdata->mem_ctx) {
-			talloc_destroy(recdata->mem_ctx);
-		}
-		recdata = NULL;
-	}
+	DEBUG(10, ("recycle_bin: touch = %s\n", ret?"True":"False"));
+	
+	return ret;
 }
 
-static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
+static const char **recycle_exclude(struct connection_struct *conn)
 {
-	TALLOC_CTX *ctx = NULL;
-	recycle_bin_struct *recbin;
-	recycle_bin_connections *recconn;
-	recycle_bin_connections *recconnbase;
-	recycle_bin_private_data *recdata;
-	char *tmp_str;
+	const char **tmp_lp;
+	
+	tmp_lp = lp_parm_string_list(SNUM(conn), "recycle_bin", "exclude",delimiter,NULL);
 
-	DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user));
+	DEBUG(10, ("recycle_bin: exclude = %s ...\n", tmp_lp?*tmp_lp:""));
+	
+	return tmp_lp;
+}
 
-	if (recycle_bin_private_handle)
-		recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
-	else {
-		DEBUG(0, ("Recycle bin not initialized!\n"));
-		return -1;
-	}
+static const char **recycle_exclude_dir(struct connection_struct *conn)
+{
+	const char **tmp_lp;
+	
+	tmp_lp = lp_parm_string_list(SNUM(conn), "recycle_bin", "exclude_dir",delimiter,NULL);
 
-	if (!(ctx = talloc_init_named("recycle bin connection"))) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return -1;
-	}
-
-	recbin = talloc(ctx, sizeof(recycle_bin_struct));
-	if (recbin == NULL) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		return -1;
-	}
-	recbin->mem_ctx = ctx;
-
-	/* Set defaults */
-	recbin->repository = talloc_strdup(recbin->mem_ctx, ".recycle");
-	ALLOC_CHECK(recbin->repository, error);
-	recbin->keep_dir_tree = False;
-	recbin->versions = False;
-	recbin->touch = False;
-	recbin->exclude = "";
-	recbin->exclude_dir = "";
-	recbin->noversions = "";
-	recbin->maxsize = 0;
-
-	/* parse configuration options */
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "repository")) != NULL) {
-		recbin->repository = talloc_sub_conn(recbin->mem_ctx, conn, tmp_str);
-		ALLOC_CHECK(recbin->repository, error);
-		trim_string(recbin->repository, "/", "/");
-		DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository));
-	}
-	
-	recbin->keep_dir_tree = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "keeptree");
-	DEBUG(5, ("recycle.bin: keeptree = %d\n", recbin->keep_dir_tree));
-	
-	recbin->versions = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "versions");
-	DEBUG(5, ("recycle.bin: versions = %d\n", recbin->versions));
-	
-	recbin->touch = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "touch");
-	DEBUG(5, ("recycle.bin: touch = %d\n", recbin->touch));
-
-	recbin->maxsize = lp_parm_ulong(SNUM(conn), "vfs_recycle_bin", "maxsize");
-	if (recbin->maxsize == 0) {
-		recbin->maxsize = -1;
-		DEBUG(5, ("recycle.bin: maxsize = -infinite-\n"));
-	} else {
-		DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize));
-	}
+	DEBUG(10, ("recycle_bin: exclude_dir = %s ...\n", tmp_lp?*tmp_lp:""));
+	
+	return tmp_lp;
+}
 
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "exclude")) != NULL) {
-		recbin->exclude = talloc_strdup(recbin->mem_ctx, tmp_str);
-		ALLOC_CHECK(recbin->exclude, error);
-		DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude));
-	}
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "exclude_dir")) != NULL) {
-		recbin->exclude_dir = talloc_strdup(recbin->mem_ctx, tmp_str);
-		ALLOC_CHECK(recbin->exclude_dir, error);
-		DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir));
-	}
-	if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "noversions")) != NULL) {
-		recbin->noversions = talloc_strdup(recbin->mem_ctx, tmp_str);
-		ALLOC_CHECK(recbin->noversions, error);
-		DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions));
-	}
-
-	recconn = talloc(recdata->mem_ctx, sizeof(recycle_bin_connections));
-	if (recconn == NULL) {
-		DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
-		goto error;
-	}
-	recconn->conn = SNUM(conn);
-	recconn->data = recbin;
-	recconn->next = NULL;
-	if (recdata->conns) {
-		recconnbase = recdata->conns;
-		while (recconnbase->next != NULL) recconnbase = recconnbase->next;
-		recconnbase->next = recconn;
-	} else {
-		recdata->conns = recconn;
+static const char **recycle_noversions(struct connection_struct *conn)
+{
+	const char **tmp_lp;
+	
+	tmp_lp = lp_parm_string_list(SNUM(conn), "recycle_bin", "noversions",delimiter,NULL);
+
+	DEBUG(10, ("recycle_bin: noversions = %s\n", tmp_lp?*tmp_lp:""));
+	
+	return tmp_lp;
+}
+
+static int recycle_maxsize(struct connection_struct *conn)
+{
+	int maxsize;
+	
+	maxsize = lp_parm_int(SNUM(conn), "recycle_bin", "maxsize",0);
+
+	DEBUG(10, ("recycle_bin: maxsize = %d\n", maxsize));
+	
+	return maxsize;
+}
+
+static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
+{
+	struct vfs_ops *default_vfs_ops;
+	int ret;
+	
+	DEBUG(10, ("recycle_bin: Connect to service %s (%d) as user %s\n", service, SNUM(conn), user));
+
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return (-1);
 	}
-	return default_vfs_ops.connect(conn, service, user);
 
-error:
-	talloc_destroy(ctx);
-	return -1;
+	ret = default_vfs_ops->connect(conn, service, user);
+
+	return ret;
 }
 
 static void recycle_disconnect(struct connection_struct *conn)
 {
-	recycle_bin_private_data *recdata;
-	recycle_bin_connections *recconn;
-
-	DEBUG(10, ("Disconnecting VFS module recycle bin\n"));
+	struct vfs_ops *default_vfs_ops;
+	
+	DEBUG(10, ("Disconnecting VFS module recycle_bin\n"));
 
-	if (recycle_bin_private_handle)
-		recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
-	else {
-		DEBUG(0, ("Recycle bin not initialized!\n"));
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
 		return;
 	}
 
-	if (recdata) {
-		if (recdata->conns) {
-			if (recdata->conns->conn == SNUM(conn)) {
-				talloc_destroy(recdata->conns->data->mem_ctx);
-				recdata->conns = recdata->conns->next;
-			} else {
-				recconn = recdata->conns;
-				while (recconn->next) {
-					if (recconn->next->conn == SNUM(conn)) {
-						talloc_destroy(recconn->next->data->mem_ctx);
-						recconn->next = recconn->next->next;
-						break;
-					}
-					recconn = recconn->next;
-				}
-			}
-		}
-	}
-	default_vfs_ops.disconnect(conn);
+	default_vfs_ops->disconnect(conn);
+
+	return;
 }
 
 static BOOL recycle_directory_exist(connection_struct *conn, const char *dname)
 {
 	SMB_STRUCT_STAT st;
+	struct vfs_ops *default_vfs_ops;
 
-	if (default_vfs_ops.stat(conn, dname, &st) == 0) {
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return False;
+	}
+
+	if (default_vfs_ops->stat(conn, dname, &st) == 0) {
 		if (S_ISDIR(st.st_mode)) {
 			return True;
 		}
@@ -308,8 +205,14 @@ static BOOL recycle_directory_exist(conn
 static BOOL recycle_file_exist(connection_struct *conn, const char *fname)
 {
 	SMB_STRUCT_STAT st;
+	struct vfs_ops *default_vfs_ops;
 
-	if (default_vfs_ops.stat(conn, fname, &st) == 0) {
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return False;
+	}
+
+	if (default_vfs_ops->stat(conn, fname, &st) == 0) {
 		if (S_ISREG(st.st_mode)) {
 			return True;
 		}
@@ -327,10 +230,18 @@ static BOOL recycle_file_exist(connectio
 static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname)
 {
 	SMB_STRUCT_STAT st;
-	if (default_vfs_ops.stat(conn, fname, &st) != 0) {
-		DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno)));
+	struct vfs_ops *default_vfs_ops;
+
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
 		return (SMB_OFF_T)0;
 	}
+
+	if (default_vfs_ops->stat(conn, fname, &st) != 0) {
+		DEBUG(0,("recycle_bin: stat for %s returned %s\n", fname, strerror(errno)));
+		return (SMB_OFF_T)0;
+	}
+
 	return(st.st_size);
 }
 
@@ -349,6 +260,12 @@ static BOOL recycle_create_dir(connectio
 	char *token;
 	char *tok_str;
 	BOOL ret = False;
+	struct vfs_ops *default_vfs_ops;
+
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return False;
+	}
 
 	mode = S_IREAD | S_IWRITE | S_IEXEC;
 
@@ -365,10 +282,10 @@ static BOOL recycle_create_dir(connectio
 	for(token = strtok(tok_str, "/"); token; token = strtok(NULL, "/")) {
 		safe_strcat(new_dir, token, len);
 		if (recycle_directory_exist(conn, new_dir))
-			DEBUG(10, ("recycle.bin: dir %s already exists\n", new_dir));
+			DEBUG(10, ("recycle_bin: dir %s already exists\n", new_dir));
 		else {
 			DEBUG(5, ("recycle.bin: creating new dir %s\n", new_dir));
-			if (default_vfs_ops.mkdir(conn, new_dir, mode) != 0) {
+			if (default_vfs_ops->mkdir(conn, new_dir, mode) != 0) {
 				DEBUG(1,("recycle.bin: mkdir failed for %s with error: %s\n", new_dir, strerror(errno)));
 				ret = False;
 				goto done;
@@ -390,30 +307,21 @@ done:
  * @param needle string to be matched exactly to haystack
  * @return True if found
  **/
-static BOOL checkparam(const char *haystack, const char *needle)
+static BOOL checkparam(const char **haystack_list, const char *needle)
 {
-	char *token;
-	char *tok_str;
-	char *tmp_str;
-	BOOL ret = False;
+	int i;
 
-	if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) {
+	if (haystack_list == NULL || strlen(*haystack_list) == 0 || needle == NULL || strlen(needle) == 0) {
 		return False;
 	}
 
-	tmp_str = strdup(haystack);
-	ALLOC_CHECK(tmp_str, done);
-	token = tok_str = tmp_str;
-
-	for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) {
-		if(strcmp(token, needle) == 0) {
-			ret = True;
-			goto done;
+	for(i=0; haystack_list[i] ; i++) {
+		if(strequal(haystack_list[i], needle)) {
+			return True;
 		}
 	}
-done:
-	SAFE_FREE(tmp_str);
-	return ret;
+
+	return False;
 }
 
 /**
@@ -422,42 +330,39 @@ done:
  * @param needle string to be matched exectly to haystack including pattern matching
  * @return True if found
  **/
-static BOOL matchparam(const char *haystack, const char *needle)
+static BOOL matchparam(const char **haystack_list, const char *needle)
 {
-	char *token;
-	char *tok_str;
-	char *tmp_str;
-	BOOL ret = False;
+	int i;
 
-	if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) {
+	if (haystack_list == NULL || strlen(*haystack_list) == 0 || needle == NULL || strlen(needle) == 0) {
 		return False;
 	}
 
-	tmp_str = strdup(haystack);
-	ALLOC_CHECK(tmp_str, done);
-	token = tok_str = tmp_str;
-
-	for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) {
-		if (!unix_wild_match(token, needle)) {
-			ret = True;
-			goto done;
+	for(i=0; haystack_list[i] ; i++) {
+		if(!unix_wild_match((char *)haystack_list[i], (char *)needle)) {
+			return True;
 		}
 	}
-done:
-	SAFE_FREE(tmp_str);
-	return ret;
+
+	return False;
 }
 
 /**
  * Touch access date
  **/
-static void recycle_touch(connection_struct *conn, const char *fname)
+static void recycle_do_touch(struct connection_struct *conn, const char *fname)
 {
 	SMB_STRUCT_STAT st;
 	struct utimbuf tb;
 	time_t currtime;
+	struct vfs_ops *default_vfs_ops;
+
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return;
+	}
 
-	if (default_vfs_ops.stat(conn, fname, &st) != 0) {
+	if (default_vfs_ops->stat(conn, fname, &st) != 0) {
 		DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno)));
 		return;
 	}
@@ -465,61 +370,53 @@ static void recycle_touch(connection_str
 	tb.actime = currtime;
 	tb.modtime = st.st_mtime;
 
-	if (default_vfs_ops.utime(conn, fname, &tb) == -1 )
-		DEBUG(0, ("recycle.bin: touching %s failed, reason = %s\n", fname, strerror(errno)));
+	if (default_vfs_ops->utime(conn, fname, &tb) == -1 ) {
+		DEBUG(0, ("recycle_bin: touching %s failed, reason = %s\n", fname, strerror(errno)));
 	}
+}
 
 /**
  * Check if file should be recycled
  **/
 static int recycle_unlink(connection_struct *conn, const char *inname)
 {
-	recycle_bin_private_data *recdata;
-	recycle_bin_connections *recconn;
-	recycle_bin_struct *recbin;
 	char *file_name = NULL;
 	char *path_name = NULL;
        	char *temp_name = NULL;
 	char *final_name = NULL;
 	char *base;
+	char *repository = NULL;
 	int i;
+	int maxsize;
 /*	SMB_BIG_UINT dfree, dsize, bsize;	*/
 	SMB_OFF_T file_size; /* space_avail;	*/
 	BOOL exist;
 	int rc = -1;
+	struct vfs_ops *default_vfs_ops;
+
+	if ((default_vfs_ops = recycle_get_def_vfs_ops(conn))==NULL) {
+		DEBUG(0,("recycle_bin: can't get default ops for service '%s' [%d]\n",lp_servicename(SNUM(conn)),SNUM(conn)));
+		return (-1);
+	}
 
 	file_name = strdup(inname);
 	ALLOC_CHECK(file_name, done);
 
-	recbin = NULL;
-	if (recycle_bin_private_handle) {
-		recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data);
-		if (recdata) {
-			if (recdata->conns) {
-				recconn = recdata->conns;
-				while (recconn && recconn->conn != SNUM(conn)) recconn = recconn->next;
-				if (recconn != NULL) {
-					recbin = recconn->data;
-				}
-			}
-		}
-	}
-	if (recbin == NULL) {
-		DEBUG(0, ("Recycle bin not initialized!\n"));
-		rc = default_vfs_ops.unlink(conn, file_name);
-		goto done;
-	}
-
-	if(!recbin->repository || *(recbin->repository) == '\0') {
-		DEBUG(3, ("Recycle path not set, purging %s...\n", file_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	repository = alloc_sub_conn(conn, (char *)recycle_repository(conn));
+	ALLOC_CHECK(repository, done);
+	/* shouldn't we allow absolute path names here? --metze */
+	trim_string(repository, "/", "/");
+	
+	if(!repository || *(repository) == '\0') {
+		DEBUG(3, ("recycle_bin: repository path not set, purging %s...\n", file_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
 	/* we don't recycle the recycle bin... */
-	if (strncmp(file_name, recbin->repository, strlen(recbin->repository)) == 0) {
-		DEBUG(3, ("File is within recycling bin, unlinking ...\n"));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	if (strncmp(file_name, repository, strlen(repository)) == 0) {
+		DEBUG(3, ("recycle_bin: File is within recycling bin, unlinking ...\n"));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
@@ -528,8 +425,8 @@ static int recycle_unlink(connection_str
 	 *   --- simo
 	 *
 	if(fsize == 0) {
-		DEBUG(3, ("File %s is empty, purging...\n", file_name));
-		rc = default_vfs_ops.unlink(conn,file_name);
+		DEBUG(3, ("recycle_bin: File %s is empty, purging...\n", file_name));
+		rc = default_vfs_ops->unlink(conn,file_name);
 		goto done;
 	}
 	 */
@@ -538,20 +435,21 @@ static int recycle_unlink(connection_str
 	 * not greater then maxsize, not the size of the single file, also it is better
 	 * to remove older files
 	 */
-	if(recbin->maxsize > 0 && file_size > recbin->maxsize) {
-		DEBUG(3, ("File %s exceeds maximum recycle size, purging... \n", file_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	maxsize = recycle_maxsize(conn);
+	if(maxsize > 0 && file_size > maxsize) {
+		DEBUG(3, ("recycle_bin: File %s exceeds maximum recycle size, purging... \n", file_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
 	/* FIXME: this is wrong: moving files with rename does not change the disk space
 	 * allocation
 	 *
-	space_avail = default_vfs_ops.disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
+	space_avail = default_vfs_ops->disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L;
 	DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size));
 	if(space_avail < file_size) {
-		DEBUG(3, ("Not enough diskspace, purging file %s\n", file_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+		DEBUG(3, ("recycle_bin: Not enough diskspace, purging file %s\n", file_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 	 */
@@ -571,13 +469,13 @@ static int recycle_unlink(connection_str
 		base++;
 	}
 
-	DEBUG(10, ("recycle.bin: fname = %s\n", file_name));	/* original filename with path */
-	DEBUG(10, ("recycle.bin: fpath = %s\n", path_name));	/* original path */
-	DEBUG(10, ("recycle.bin: base = %s\n", base));		/* filename without path */
-
-	if (matchparam(recbin->exclude, base)) {
-		DEBUG(3, ("recycle.bin: file %s is excluded \n", base));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	DEBUG(10, ("recycle_bin: fname = %s\n", file_name));	/* original filename with path */
+	DEBUG(10, ("recycle_bin: fpath = %s\n", path_name));	/* original path */
+	DEBUG(10, ("recycle_bin: base = %s\n", base));		/* filename without path */
+
+	if (matchparam(recycle_exclude(conn), base)) {
+		DEBUG(3, ("recycle_bin: file %s is excluded \n", base));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
@@ -585,30 +483,30 @@ static int recycle_unlink(connection_str
 	 * we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 .... 
 	 * 	---simo
 	 */
-	if (checkparam(recbin->exclude_dir, path_name)) {
-		DEBUG(3, ("recycle.bin: directory %s is excluded \n", path_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+	if (checkparam(recycle_exclude_dir(conn), path_name)) {
+		DEBUG(3, ("recycle_bin: directory %s is excluded \n", path_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
 	temp_name = (char *)malloc(PATH_MAX);
 	ALLOC_CHECK(temp_name, done);
-	safe_strcpy(temp_name, recbin->repository, PATH_MAX);
+	safe_strcpy(temp_name, repository, PATH_MAX);
 
 	/* see if we need to recreate the original directory structure in the recycle bin */
-	if (recbin->keep_dir_tree == True) {
+	if (recycle_keep_dir_tree(conn) == True) {
 		safe_strcat(temp_name, "/", PATH_MAX);
 		safe_strcat(temp_name, path_name, PATH_MAX);
 	}
 
 	exist = recycle_directory_exist(conn, temp_name);
 	if (exist) {
-		DEBUG(10, ("recycle.bin: Directory already exists\n"));
+		DEBUG(10, ("recycle_bin: Directory already exists\n"));
 	} else {
-		DEBUG(10, ("recycle.bin: Creating directory %s\n", temp_name));
+		DEBUG(10, ("recycle_bin: Creating directory %s\n", temp_name));
 		if (recycle_create_dir(conn, temp_name) == False) {
-			DEBUG(3, ("Could not create directory, purging %s...\n", file_name));
-			rc = default_vfs_ops.unlink(conn, file_name);
+			DEBUG(3, ("recycle_bin: Could not create directory, purging %s...\n", file_name));
+			rc = default_vfs_ops->unlink(conn, file_name);
 			goto done;
 		}
 	}
@@ -616,14 +514,14 @@ static int recycle_unlink(connection_str
 	final_name = (char *)malloc(PATH_MAX);
 	ALLOC_CHECK(final_name, done);
 	snprintf(final_name, PATH_MAX, "%s/%s", temp_name, base);
-	DEBUG(10, ("recycle.bin: recycled file name%s\n", temp_name));		/* new filename with path */
+	DEBUG(10, ("recycle_bin: recycled file name%s\n", temp_name));		/* new filename with path */
 
 	/* check if we should delete file from recycle bin */
 	if (recycle_file_exist(conn, final_name)) {
-		if (recbin->versions == False || matchparam(recbin->noversions, base) == True) {
-			DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", final_name));
-			if (default_vfs_ops.unlink(conn, final_name) != 0) {
-				DEBUG(1, ("recycle.bin: Error deleting old file: %s\n", strerror(errno)));
+		if (recycle_versions(conn) == False || matchparam(recycle_noversions(conn), base) == True) {
+			DEBUG(3, ("recycle_bin: Removing old file %s from recycle bin\n", final_name));
+			if (default_vfs_ops->unlink(conn, final_name) != 0) {
+				DEBUG(1, ("recycle_bin: Error deleting old file: %s\n", strerror(errno)));
 			}
 		}
 	}
@@ -634,22 +532,56 @@ static int recycle_unlink(connection_str
 		snprintf(final_name, PATH_MAX, "%s/Copy #%d of %s", temp_name, i++, base);
 	}
 
-	DEBUG(10, ("recycle.bin: Moving %s to %s\n", file_name, final_name));
-	rc = default_vfs_ops.rename(conn, file_name, final_name);
+	DEBUG(10, ("recycle_bin: Moving %s to %s\n", file_name, final_name));
+	rc = default_vfs_ops->rename(conn, file_name, final_name);
 	if (rc != 0) {
-		DEBUG(3, ("recycle.bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
-		rc = default_vfs_ops.unlink(conn, file_name);
+		DEBUG(3, ("recycle_bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name));
+		rc = default_vfs_ops->unlink(conn, file_name);
 		goto done;
 	}
 
 	/* touch access date of moved file */
-	if (recbin->touch == True )
-		recycle_touch(conn, final_name);
+	if (recycle_touch(conn) == True )
+		recycle_do_touch(conn, final_name);
 
 done:
 	SAFE_FREE(file_name);
 	SAFE_FREE(path_name);
 	SAFE_FREE(temp_name);
 	SAFE_FREE(final_name);
+	SAFE_FREE(repository);
 	return rc;
 }
+
+NTSTATUS SMB_MODULE_SYMBOL(SMB_MODULE_TYPES types) 
+{
+	static BOOL init = False;
+	static NTSTATUS nt_status = NT_STATUS_OK;
+	
+	if (init)
+		return nt_status;
+		
+	if (types & MODULE_TYPE_VFS) {
+		init = True;
+
+		nt_status = smb_register_vfs(&recycle_register, SMB_VFS_INTERFACE_VERSION);
+		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_COLLISION,nt_status)) {
+			DEBUG(1,("recycle_bin: there's allready a vfs module registered as 'recycle_bin'!\n"));
+			return nt_status;
+		} else if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0,("recycle_bin: failed to register: %s\n",nt_errstr(nt_status)));
+			return nt_status;	
+		}
+		DEBUG(5,("recycle_bin: successful registered\n"));
+
+		recycle_debug_level = debug_add_class("recycle_bin");
+		if (recycle_debug_level == -1) {
+			recycle_debug_level = DBGC_VFS;
+			DEBUG(0, ("recycle_bin: Couldn't register custom debugging class!\n"));
+		} else {
+			DEBUG(10, ("recycle_bin: Debug class number of 'recycle_bin': %d\n", recycle_debug_level));
+		}		
+	}
+	
+	return nt_status;
+}
\ No newline at end of file
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/modules/xml.c HEAD-modules/source/modules/xml.c
--- HEAD/source/modules/xml.c	Fri Nov 15 18:01:23 2002
+++ HEAD-modules/source/modules/xml.c	Tue Dec 17 15:09:52 2002
@@ -512,64 +512,156 @@ static NTSTATUS xmlsam_add_sam_account(s
 	return NT_STATUS_OK;
 }
 
-NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method,
-		 const char *location)
+static NTSTATUS xmlsam_getsampwnam(struct pdb_methods *methods, SAM_ACCOUNT * user,
+					 const char *sname)
 {
-	NTSTATUS nt_status;
-	pdb_xml *data;
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-	xmlsam_debug_level = debug_add_class("xmlsam");
-	if (xmlsam_debug_level == -1) {
-		xmlsam_debug_level = DBGC_ALL;
-		DEBUG(0, ("xmlsam: Couldn't register custom debugging class!\n"));
-	}
+static NTSTATUS xmlsam_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT * user,
+					 const DOM_SID * sid)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-	if (!pdb_context) {
-		DEBUG(0, ("invalid pdb_methods specified\n"));
-		return NT_STATUS_UNSUCCESSFUL;
-	}
+static NTSTATUS xmlsam_update_sam_account(struct pdb_methods *methods,
+							SAM_ACCOUNT * newpwd)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-	if (!NT_STATUS_IS_OK
-		(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
-		return nt_status;
+static NTSTATUS xmlsam_delete_sam_account(struct pdb_methods *methods,
+							SAM_ACCOUNT * pwd)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
+				 DOM_SID sid, BOOL with_priv)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
+				 gid_t gid, BOOL with_priv)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
+				 char *name, BOOL with_priv)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_add_group_mapping_entry(struct pdb_methods *methods,
+						GROUP_MAP *map)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_update_group_mapping_entry(struct pdb_methods *methods,
+						   GROUP_MAP *map)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_delete_group_mapping_entry(struct pdb_methods *methods,
+						   DOM_SID sid)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_enum_group_mapping(struct pdb_methods *methods,
+					   enum SID_NAME_USE sid_name_use,
+					   GROUP_MAP **rmap, int *num_entries,
+					   BOOL unix_only, BOOL with_priv)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS xmlsam_free_private_data(void **privates)
+{
+	/* jelmer what's needed here --metze*/ 
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS xmlsam_init_private_data(TALLOC_CTX *mem_ctx, void **privates, const char *location)
+{
+	pdb_xml *data;
+
+	if ( (data=(pdb_xml *)talloc_zero(mem_ctx, sizeof(pdb_xml))) ==NULL) {
+		DEBUG(0,("xmlsam_init_private_data: talloc_zero() failed\n"));
+		return NT_STATUS_NO_MEMORY;
 	}
 
-	(*pdb_method)->name = "xmlsam";
+	data->location = talloc_strdup(mem_ctx,(location?location:"-"));
 
-	(*pdb_method)->setsampwent = xmlsam_setsampwent;
-	(*pdb_method)->endsampwent = xmlsam_endsampwent;
-	(*pdb_method)->getsampwent = xmlsam_getsampwent;
-	(*pdb_method)->add_sam_account = xmlsam_add_sam_account;
-	(*pdb_method)->getsampwnam = NULL;
-	(*pdb_method)->getsampwsid = NULL;
-	(*pdb_method)->update_sam_account = NULL;
-	(*pdb_method)->delete_sam_account = NULL;
-	(*pdb_method)->getgrsid = NULL;
-	(*pdb_method)->getgrgid = NULL;
-	(*pdb_method)->getgrnam = NULL;
-	(*pdb_method)->add_group_mapping_entry = NULL;
-	(*pdb_method)->update_group_mapping_entry = NULL;
-	(*pdb_method)->delete_group_mapping_entry = NULL;
-	(*pdb_method)->enum_group_mapping = NULL;
-
-	data = talloc(pdb_context->mem_ctx, sizeof(pdb_xml));
-	data->location =
-		(location ? talloc_strdup(pdb_context->mem_ctx, location) : "-");
 	data->pwent = NULL;
 	data->written = 0;
-	(*pdb_method)->private_data = data;
+	(*privates) = data;
 
 	LIBXML_TEST_VERSION xmlKeepBlanksDefault(0);
 
 	return NT_STATUS_OK;
 }
 
-int init_module(void);
+static struct pdb_method_ops xmlsam_ops = {
+	xmlsam_setsampwent,
+	xmlsam_endsampwent,
+	xmlsam_getsampwent,
+	xmlsam_getsampwnam,
+	xmlsam_getsampwsid,
+	xmlsam_add_sam_account,
+	xmlsam_update_sam_account,
+	xmlsam_delete_sam_account,
+
+	xmlsam_getgrsid,
+	xmlsam_getgrgid,
+	xmlsam_getgrnam,
+	xmlsam_add_group_mapping_entry,
+	xmlsam_update_group_mapping_entry,
+	xmlsam_delete_group_mapping_entry,
+	xmlsam_enum_group_mapping,
+
+	xmlsam_init_private_data,
+	xmlsam_free_private_data
+};
+
+static struct pdb_backend_function_entry xmlsam_register = {
+	"xml",
+	&xmlsam_ops	
+};
 
-int init_module() 
+NTSTATUS SMB_MODULE_SYMBOL(SMB_MODULE_TYPES types) 
 {
-	if(smb_register_passdb("xml", xmlsam_init, PASSDB_INTERFACE_VERSION))
-		return 0;
-
-	return 1;
+	static BOOL init = False;
+	static NTSTATUS nt_status = NT_STATUS_OK;
+	
+	if (init)
+		return nt_status;
+		
+	if (types & MODULE_TYPE_PDB) {
+		init = True;
+
+		nt_status = smb_register_passdb(&xmlsam_register, PASSDB_INTERFACE_VERSION);
+		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_COLLISION,nt_status)) {
+			DEBUG(1,("xmlsam: there's allready a passdb backend registered as 'xml'!\n"));
+			return nt_status;
+		} else if (NT_STATUS_IS_ERR(nt_status)) {
+			DEBUG(0,("xmlsam: failed to register: %s\n",nt_errstr(nt_status)));
+			return nt_status;	
+		}
+		DEBUG(5,("xmlsam: successful registered\n"));
+
+		xmlsam_debug_level = debug_add_class("xml");
+		if (xmlsam_debug_level == -1) {
+			xmlsam_debug_level = DBGC_PASSDB;
+			DEBUG(0, ("xmlsam: Couldn't register custom debugging class!\n"));
+		} else {
+			DEBUG(10, ("xmlsam: Debug class number of 'xml': %d\n", xmlsam_debug_level));
+		}		
+	}
+	
+	return nt_status;
 }
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/nmbd/nmbd.c HEAD-modules/source/nmbd/nmbd.c
--- HEAD/source/nmbd/nmbd.c	Wed Nov 13 19:52:36 2002
+++ HEAD-modules/source/nmbd/nmbd.c	Tue Dec 10 16:13:57 2002
@@ -631,6 +631,9 @@ static BOOL open_sockets(BOOL isdaemon, 
   if ( !reload_nmbd_services(False) )
     return(-1);
 
+  if (lp_modules(GLOBAL_SECTION_SNUM))
+	smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPES_NMBD);
+
   if(!init_names())
     return -1;
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/nsswitch/winbindd.c HEAD-modules/source/nsswitch/winbindd.c
--- HEAD/source/nsswitch/winbindd.c	Mon Dec  2 15:46:20 2002
+++ HEAD-modules/source/nsswitch/winbindd.c	Tue Dec 10 16:14:38 2002
@@ -828,6 +828,9 @@ static void usage(void)
 		exit(1);
 	}
 
+	if (lp_modules(GLOBAL_SECTION_SNUM))
+		smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPES_WINBINDD);
+
 	/* Setup names. */
 
 	if (!init_names())
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/param/loadparm.c HEAD-modules/source/param/loadparm.c
--- HEAD/source/param/loadparm.c	Thu Dec 12 20:24:27 2002
+++ HEAD-modules/source/param/loadparm.c	Thu Dec 12 21:13:21 2002
@@ -84,8 +84,11 @@ static BOOL defaults_saved = False;
 typedef struct _param_opt_struct param_opt_struct;
 struct _param_opt_struct {
 	param_opt_struct *prev, *next;
+	TALLOC_CTX *mem_ctx;
 	char *key;
 	char *value;
+	char **list;
+	char *list_sep;
 };
 
 /* 
@@ -119,7 +122,6 @@ typedef struct
 	char *szPrivateDir;
 	char **szPassdbBackend;
 	char **szSamBackend;
-	char **szModules;
 	char *szPasswordServer;
 	char *szSocketOptions;
 	char *szRealm;
@@ -325,9 +327,9 @@ typedef struct
 	char **printer_admin;
 	char *volume;
 	char *fstype;
-	char *szVfsObjectFile;
-	char *szVfsOptions;
-	char *szVfsPath;
+	char **szVfsObjects;
+	char *szModulesPath;
+	char **szModules;
 	int iMinPrintSpace;
 	int iMaxPrintJobs;
 	int iWriteCacheSize;
@@ -445,8 +447,8 @@ static service sDefault = {
 	NULL,			/* volume */
 	NULL,			/* fstype */
 	NULL,			/* vfs object */
-	NULL,			/* vfs options */
-	NULL,			/* vfs path */
+	NULL,			/* modules path */
+	NULL,			/* modules */
 	0,			/* iMinPrintSpace */
 	1000,			/* iMaxPrintJobs */
 	0,			/* iWriteCacheSize */
@@ -535,7 +537,6 @@ static int default_server_announce;
 /* prototypes for the special type handlers */
 static BOOL handle_include(char *pszParmValue, char **ptr);
 static BOOL handle_copy(char *pszParmValue, char **ptr);
-static BOOL handle_vfs_object(char *pszParmValue, char **ptr);
 static BOOL handle_source_env(char *pszParmValue, char **ptr);
 static BOOL handle_netbios_name(char *pszParmValue, char **ptr);
 static BOOL handle_winbind_uid(char *pszParmValue, char **ptr);
@@ -809,7 +810,8 @@ static struct parm_struct parm_table[] =
 	{"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE},
 	{"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
 	{"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE},
-	{"modules", P_LIST, P_GLOBAL, &Globals.szModules, NULL, NULL, FLAG_BASIC | FLAG_GLOBAL},
+	{"modules path", P_STRING, P_LOCAL, &sDefault.szModulesPath, NULL, NULL, FLAG_BASIC | FLAG_SHARE| FLAG_GLOBAL | FLAG_ADVANCED | FLAG_DEVELOPER},
+	{"modules", P_LIST, P_LOCAL, &sDefault.szModules, NULL, NULL, FLAG_BASIC | FLAG_SHARE | FLAG_GLOBAL},
 
 	{"Logging Options", P_SEP, P_SEPARATOR},
 
@@ -1085,11 +1087,9 @@ static struct parm_struct parm_table[] =
 
 	{"VFS module options", P_SEP, P_SEPARATOR},
 	
-	{"vfs object", P_STRING, P_LOCAL, &sDefault.szVfsObjectFile, handle_vfs_object, NULL, FLAG_SHARE},
-	{"vfs options", P_STRING, P_LOCAL, &sDefault.szVfsOptions, NULL, NULL, FLAG_SHARE},
-	{"vfs path", P_STRING, P_LOCAL, &sDefault.szVfsPath, NULL, NULL, FLAG_SHARE},
-
-	
+	{"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_SHARE},
+	{"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_HIDE},
+		
 	{"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
 	{"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 
@@ -1243,6 +1243,7 @@ static void init_globals(void)
 				string_set(parm_table[i].ptr, "");
 
 		string_set(&sDefault.fstype, FSTYPE_STRING);
+		string_set(&sDefault.szModulesPath, dyn_LIBDIR);
 
 		init_printer_values();
 
@@ -1397,6 +1398,7 @@ static void init_globals(void)
 	Globals.ldap_ssl = LDAP_SSL_ON;
 	Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
 
+
 /* these parameters are set to defaults that are more appropriate
    for the increasing samba install base:
 
@@ -1581,7 +1583,6 @@ static FN_GLOBAL_STRING(lp_announce_vers
 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
 FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
 FN_GLOBAL_LIST(lp_sam_backend, &Globals.szSamBackend)
-FN_GLOBAL_LIST(lp_modules, &Globals.szModules)
 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
@@ -1736,9 +1737,9 @@ FN_LOCAL_LIST(lp_readlist, readlist)
 FN_LOCAL_LIST(lp_writelist, writelist)
 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
 FN_LOCAL_STRING(lp_fstype, fstype)
-FN_LOCAL_STRING(lp_vfsobj, szVfsObjectFile)
-FN_LOCAL_STRING(lp_vfs_options, szVfsOptions)
-FN_LOCAL_STRING(lp_vfs_path, szVfsPath)
+FN_LOCAL_LIST(lp_vfsobj, szVfsObjects)
+FN_LOCAL_STRING(lp_modules_path, szModulesPath)
+FN_LOCAL_LIST(lp_modules, szModules)
 static FN_LOCAL_STRING(lp_volume, volume)
 FN_LOCAL_STRING(lp_mangled_map, szMangledMap)
 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
@@ -1831,7 +1832,7 @@ static void init_copymap(service * pserv
 /* This is a helper function for parametrical options support. */
 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
 /* Actual parametrical functions are quite simple */
-static const char *get_parametrics(int lookup_service, const char *type, const char *option)
+static param_opt_struct *get_parametrics(int lookup_service, const char *type, const char *option)
 {
 	char* vfskey;
         param_opt_struct *data;
@@ -1845,26 +1846,25 @@ static const char *get_parametrics(int l
 	while (data) {
 		if (strcmp(data->key, vfskey) == 0) {
 			string_free(&vfskey);
-			return data->value;
+			return data;
 		}
 		data = data->next;
 	}
-
 	if (lookup_service >= 0) {
 		/* Try to fetch the same option but from globals */
 		/* but only if we are not already working with Globals */
 		data = Globals.param_opt;
 		while (data) {
-			if (strcmp(data->key, vfskey) == 0) {
-				string_free(&vfskey);
-				return data->value;
+		        if (strcmp(data->key, vfskey) == 0) {
+			        string_free(&vfskey);
+				return data;
 			}
 			data = data->next;
 		}
 	}
-
-	string_free(&vfskey);
 	
+	string_free(&vfskey);
+
 	return NULL;
 }
 
@@ -1940,87 +1940,101 @@ static int lp_enum(const char *s,const s
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
-/* Returned value is allocated in 'lp_talloc' context */
 
-char *lp_parm_string(int lookup_service, const char *type, const char *option)
+
+char *lp_parm_string(int lookup_service, const char *type, const char *option, char *def)
 {
-	const char *value = get_parametrics(lookup_service, type, option);
+	param_opt_struct *data = get_parametrics(lookup_service, type, option);
 	
-	if (value)
-		return lp_string(value);
-
-	return NULL;
+	if (data == NULL)
+		return def;
+		
+	return data->value;
 }
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
-/* Returned value is allocated in 'lp_talloc' context */
 
-char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
-			   const char *separator)
+const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
+			   const char *separator,char **def)
 {
-	const char *value = get_parametrics(lookup_service, type, option);
-	
-	if (value)
-		return str_list_make(value, separator);
+	param_opt_struct *data = get_parametrics(lookup_service, type, option);
 
-	return NULL;
+	if (data == NULL)
+		return (const char **)def;
+		
+	if ((data->list_sep == separator)||
+		(data->list_sep && separator && 
+		 strequal(data->list_sep,separator))) {
+		if (data->list==NULL) {
+			data->list = talloc_str_list_make(data->mem_ctx,data->value, separator);
+			if (separator) {
+				data->list_sep = talloc_strdup(data->mem_ctx,separator);
+			}
+		}
+	} else {
+		data->list = talloc_str_list_make(data->mem_ctx,data->value, separator);
+		if (separator) {
+			data->list_sep = talloc_strdup(data->mem_ctx,separator);
+		}	
+	}
+
+	return (const char **)data->list;
 }
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
 
-int lp_parm_int(int lookup_service, const char *type, const char *option)
+int lp_parm_int(int lookup_service, const char *type, const char *option, int def)
 {
-	const char *value = get_parametrics(lookup_service, type, option);
+	param_opt_struct *data = get_parametrics(lookup_service, type, option);
 	
-	if (value)
-		return lp_int(value);
+	if (data && data->value && *data->value)
+		return lp_int(data->value);
 
-	return (-1);
+	return def;
 }
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
 
-unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option)
+unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long def)
 {
-	const char *value = get_parametrics(lookup_service, type, option);
+	param_opt_struct *data = get_parametrics(lookup_service, type, option);
 	
-	if (value)
-		return lp_ulong(value);
+	if (data && data->value && *data->value)
+		return lp_ulong(data->value);
 
-	return (0);
+	return def;
 }
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
 
-BOOL lp_parm_bool(int lookup_service, const char *type, const char *option)
+BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL def)
 {
-	const char *value = get_parametrics(lookup_service, type, option);
+	param_opt_struct *data = get_parametrics(lookup_service, type, option);
 	
-	if (value)
-		return lp_bool(value);
+	if (data && data->value && *data->value)
+		return lp_bool(data->value);
 
-	return False;
+	return def;
 }
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
 
 int lp_parm_enum(int lookup_service, const char *type, const char *option,
-		 const struct enum_list *_enum)
+		 const struct enum_list *_enum, int def)
 {
-	const char *value = get_parametrics(lookup_service, type, option);
+	param_opt_struct *data = get_parametrics(lookup_service, type, option);
 	
-	if (value)
-		return lp_enum(value, _enum);
+	if (data && data->value && *data->value)
+		return lp_enum(data->value, _enum);
 
-	return (-1);
+	return def;
 }
 
-
 /***************************************************************************
  Initialise a service to the defaults.
 ***************************************************************************/
@@ -2062,15 +2076,14 @@ static void free_service(service *pservi
 			     		    (((char *)pservice) +
 					     PTR_DIFF(parm_table[i].ptr, &sDefault)));
 	}
-				
-	DEBUG(5,("Freeing parametrics:\n"));
+
 	data = pservice->param_opt;
+	if (data)
+		DEBUG(5,("Freeing parametrics:\n"));
 	while (data) {
-		DEBUG(5,("[%s = %s]\n", data->key, data->value));
-		string_free(&data->key);
-		string_free(&data->value);
+		DEBUGADD(5,("[%s = %s]\n", data->key, data->value));
 		pdata = data->next;
-		SAFE_FREE(data);
+		talloc_destroy(data->mem_ctx);
 		data = pdata;
 	}
 
@@ -2099,10 +2112,8 @@ static int add_a_service(const service *
 			/* They will be added during parsing again */
 			data = ServicePtrs[i]->param_opt;
 			while (data) {
-				string_free(&data->key);
-				string_free(&data->value);
 				pdata = data->next;
-				SAFE_FREE(data);
+				talloc_destroy(data->mem_ctx);
 				data = pdata;
 			}
 			ServicePtrs[i]->param_opt = NULL;
@@ -2351,7 +2362,6 @@ static void copy_service(service * pserv
 	int i;
 	BOOL bcopyall = (pcopymapDest == NULL);
 	param_opt_struct *data, *pdata, *paramo;
-	BOOL not_added;
 
 	for (i = 0; parm_table[i].label; i++)
 		if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
@@ -2408,24 +2418,33 @@ static void copy_service(service * pserv
 	
 	data = pserviceSource->param_opt;
 	while (data) {
-		not_added = True;
 		pdata = pserviceDest->param_opt;
 		/* Traverse destination */
 		while (pdata) {
-			/* If we already have same option, override it */
+			/* If we already have same option, remove it */
 			if (strcmp(pdata->key, data->key) == 0) {
-				string_free(&pdata->value);
-				pdata->value = strdup(data->value);
-				not_added = False;
+				DLIST_REMOVE(pserviceDest->param_opt,pdata);
+				talloc_destroy(pdata->mem_ctx);
 				break;
 			}
 			pdata = pdata->next;
 		}
-		if (not_added) {
-		    paramo = smb_xmalloc(sizeof(param_opt_struct));
-		    paramo->key = strdup(data->key);
-		    paramo->value = strdup(data->value);
-		    DLIST_ADD(pserviceDest->param_opt, paramo);
+		{
+			TALLOC_CTX *mem_ctx = NULL;
+			if ((mem_ctx = talloc_init_named("param options entry"))==NULL) {
+				DEBUG(0,("copy_service: talloc_init_named failed!\n"));
+				return;
+			}
+			if ((paramo=(param_opt_struct *)talloc(mem_ctx,sizeof(param_opt_struct)))==NULL) {
+				DEBUG(0,("copy_service: talloc failed!\n"));
+				return;
+			}
+			paramo->key = talloc_strdup(mem_ctx,data->key);
+			paramo->value = talloc_strdup(mem_ctx,data->value);
+			paramo->list = NULL;
+			paramo->list_sep = NULL;
+			paramo->mem_ctx = mem_ctx;
+			DLIST_ADD(pserviceDest->param_opt, paramo);
 		}
 		data = data->next;
 	}
@@ -2685,22 +2704,6 @@ static BOOL handle_source_env(char *pszP
 }
 
 /***************************************************************************
- Handle the interpretation of the vfs object parameter.
-*************************************************************************/
-
-static BOOL handle_vfs_object(char *pszParmValue, char **ptr)
-{
-	/* Set string value */
-
-	string_set(ptr, pszParmValue);
-
-	/* Do any other initialisation required for vfs.  Note that
-	   anything done here may have linking repercussions in nmbd. */
-
-	return True;
-}
-
-/***************************************************************************
  Handle the include operation.
 ***************************************************************************/
 
@@ -3031,39 +3034,51 @@ BOOL lp_do_parameter(int snum, char *psz
 	pstring vfskey;
 	char *sep;
 	param_opt_struct *paramo, *data;
-	BOOL not_added;
 
 	parmnum = map_parameter(pszParmName);
 
 	if (parmnum < 0) {
 		if ((sep=strchr(pszParmName, ':')) != NULL) {
-			*sep = 0;
+			*sep = '\0';
 			ZERO_STRUCT(vfskey);
 			pstr_sprintf(vfskey, "%s:", pszParmName);
 			slen = strlen(vfskey);
 			safe_strcat(vfskey, sep+1, sizeof(pstring));
 			trim_string(vfskey+slen, " ", " ");
-			not_added = True;
 			data = (snum < 0) ? Globals.param_opt : 
 				ServicePtrs[snum]->param_opt;
 			/* Traverse destination */
 			while (data) {
 				/* If we already have same option, override it */
 				if (strcmp(data->key, vfskey) == 0) {
-					string_free(&data->value);
-					data->value = strdup(pszParmValue);
-					not_added = False;
+					if (snum < 0){
+						DLIST_REMOVE(Globals.param_opt,data);
+					} else {
+						DLIST_REMOVE(ServicePtrs[snum]->param_opt,data);	
+					}
+					talloc_destroy(data->mem_ctx);
 					break;
 				}
 				data = data->next;
 			}
-			if (not_added) {
-				paramo = smb_xmalloc(sizeof(param_opt_struct));
-				paramo->key = strdup(vfskey);
-				paramo->value = strdup(pszParmValue);
-				if (snum < 0) {
+			{
+				TALLOC_CTX *mem_ctx = NULL;
+				if ((mem_ctx = talloc_init_named("param options entry"))==NULL) {
+					DEBUG(0,("lp_do_parameter: talloc_init_named failed!\n"));
+					return False;
+				}
+				if ((paramo=(param_opt_struct *)talloc(mem_ctx,sizeof(param_opt_struct)))==NULL) {
+					DEBUG(0,("lp_do_parameter: talloc failed!\n"));
+					return False;
+				}
+				paramo->key = talloc_strdup(mem_ctx,vfskey);
+				paramo->value = talloc_strdup(mem_ctx,pszParmValue);
+				paramo->list = NULL;
+				paramo->list_sep = NULL;
+				paramo->mem_ctx = mem_ctx;
+				if (snum < 0 ) {
 					DLIST_ADD(Globals.param_opt, paramo);
-				} else {
+				} else { 
 					DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
 				}
 			}
@@ -3830,10 +3845,8 @@ BOOL lp_load(const char *pszFname, BOOL 
 	if (Globals.param_opt != NULL) {
 		data = Globals.param_opt;
 		while (data) {
-			string_free(&data->key);
-			string_free(&data->value);
 			pdata = data->next;
-			SAFE_FREE(data);
+			talloc_destroy(data->mem_ctx);
 			data = pdata;
 		}
 		Globals.param_opt = NULL;
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/passdb/pdb_interface.c HEAD-modules/source/passdb/pdb_interface.c
--- HEAD/source/passdb/pdb_interface.c	Fri Nov 15 18:42:56 2002
+++ HEAD-modules/source/passdb/pdb_interface.c	Wed Dec 18 08:07:45 2002
@@ -3,6 +3,7 @@
    Password and authentication handling
    Copyright (C) Andrew Bartlett			2002
    Copyright (C) Jelmer Vernooij			2002
+   Copyright (C) Stefan (metze) Metzmacher		2002
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -25,26 +26,62 @@
 #define DBGC_CLASS DBGC_PASSDB
 
 /** List of various built-in passdb modules */
-const struct {
-    char *name;
-    /* Function to create a member of the pdb_methods list */
-    pdb_init_function init;
-} builtin_pdb_init_functions[] = {
-	{ "smbpasswd", pdb_init_smbpasswd },
-	{ "smbpasswd_nua", pdb_init_smbpasswd_nua },
-	{ "tdbsam", pdb_init_tdbsam },
-	{ "tdbsam_nua", pdb_init_tdbsam_nua },
-	{ "ldapsam", pdb_init_ldapsam },
-	{ "ldapsam_nua", pdb_init_ldapsam_nua },
-	{ "unixsam", pdb_init_unixsam },
-	{ "nisplussam", pdb_init_nisplussam },
+extern struct pdb_method_ops pdb_smbpasswd_ops;
+extern struct pdb_method_ops pdb_smbpasswd_nua_ops;
+#ifdef WITH_TDB_SAM
+extern struct pdb_method_ops pdb_tdbsam_ops;
+extern struct pdb_method_ops pdb_tdbsam_nua_ops;
+#endif /* WITH_TDB_SAM */
+#ifdef HAVE_LDAP
+extern struct pdb_method_ops pdb_ldapsam_ops;
+extern struct pdb_method_ops pdb_ldapsam_nua_ops;
+#endif /* HAVE_LDAP */
+extern struct pdb_method_ops pdb_unixsam_ops;
+#ifdef WITH_NISPLUS_SAM
+extern struct pdb_method_ops pdb_nisplussam_ops;
+#endif /* WITH_NISPLUS_SAM */
+
+struct pdb_backend_function_entry builtin_pdb_backend_functions[] = {
+	{ "smbpasswd", &pdb_smbpasswd_ops },
+	{ "smbpasswd_nua", &pdb_smbpasswd_nua_ops },
+#ifdef WITH_TDB_SAM
+	{ "tdbsam", &pdb_tdbsam_ops },
+	{ "tdbsam_nua", &pdb_tdbsam_nua_ops },
+#endif /* WITH_TDB_SAM */
+#ifdef HAVE_LDAP
+	{ "ldapsam", &pdb_ldapsam_ops },
+	{ "ldapsam_nua", &pdb_ldapsam_nua_ops },
+#endif /* HAVE_LDAP */
+	{ "unixsam", &pdb_unixsam_ops },
+#ifdef WITH_NISPLUS_SAM
+	{ "nisplussam", &pdb_nisplussam_ops },
+#endif /* WITH_NISPLUS_SAM */
 	{ NULL, NULL}
 };
 
-static struct pdb_init_function_entry *backends;
-static void lazy_initialize_passdb(void);
+static struct pdb_backend_function_entry *global_passdb_backends = NULL;
 
-static void lazy_initialize_passdb()
+static NTSTATUS smb_register_passdb_backend(struct pdb_backend_function_entry *func) 
+{
+	struct pdb_backend_function_entry *entry = global_passdb_backends;
+
+	DEBUG(8,("Attempting to register passdb backend %s\n", func->name));
+
+	/* Check for duplicates */
+	while(entry) { 
+		if(strcasecmp(entry->name,func->name) == 0) { 
+			DEBUG(0,("There already is a passdb backend registered with the name %s!\n", func->name));
+			return NT_STATUS_OBJECT_NAME_COLLISION;
+		}
+		entry = entry->next;
+	}
+
+	DLIST_ADD(global_passdb_backends, func);
+	DEBUG(10,("Successfully added passdb backend '%s'\n", func->name));
+	return NT_STATUS_OK;
+}
+
+static void lazy_initialize_passdb(void)
 {
 	int i;
 	static BOOL initialised = False;
@@ -52,37 +89,23 @@ static void lazy_initialize_passdb()
 	if(!initialised) {
 		initialised = True;
 
-		for(i = 0; builtin_pdb_init_functions[i].name; i++) {
-			smb_register_passdb(builtin_pdb_init_functions[i].name, builtin_pdb_init_functions[i].init, PASSDB_INTERFACE_VERSION);
+		for(i = 0; builtin_pdb_backend_functions[i].name; i++) {
+			smb_register_passdb_backend(&builtin_pdb_backend_functions[i]);
 		}
 	}
 }
 
-BOOL smb_register_passdb(char *name, pdb_init_function init, int version) 
+NTSTATUS smb_register_passdb(struct pdb_backend_function_entry *func, int version) 
 {
-	struct pdb_init_function_entry *entry = backends;
-
-	if(version != PASSDB_INTERFACE_VERSION)
-		return False;
-
-	DEBUG(5,("Attempting to register passdb backend %s\n", name));
+	/* make sure the builtin methods are loaded before any module */
+	lazy_initialize_passdb();
 
-	/* Check for duplicates */
-	while(entry) { 
-		if(strcasecmp(name, entry->name) == 0) { 
-			DEBUG(0,("There already is a passdb backend registered with the name %s!\n", name));
-			return False;
-		}
-		entry = entry->next;
+	if(version != PASSDB_INTERFACE_VERSION){
+		DEBUG(0,("smb_register_passdb: module '%s' has wrong the PASSDB_INTERFACE_VERSION\n",func->name));
+		return NT_STATUS_INVALID_PARAMETER;
 	}
 
-	entry = smb_xmalloc(sizeof(struct pdb_init_function_entry));
-	entry->name = name;
-	entry->init = init;
-
-	DLIST_ADD(backends, entry);
-	DEBUG(5,("Successfully added passdb backend '%s'\n", name));
-	return True;
+	return smb_register_passdb_backend(func);
 }
 
 static NTSTATUS context_setsampwent(struct pdb_context *context, BOOL update)
@@ -101,7 +124,7 @@ static NTSTATUS context_setsampwent(stru
 		return ret;
 	}
 
-	while (NT_STATUS_IS_ERR(ret = context->pwent_methods->setsampwent(context->pwent_methods, update))) {
+	while (NT_STATUS_IS_ERR(ret = context->pwent_methods->ops->setsampwent(context->pwent_methods, update))) {
 		context->pwent_methods = context->pwent_methods->next;
 		if (context->pwent_methods == NULL) 
 			return NT_STATUS_UNSUCCESSFUL;
@@ -116,8 +139,10 @@ static void context_endsampwent(struct p
 		return;
 	}
 
-	if (context->pwent_methods && context->pwent_methods->endsampwent)
-		context->pwent_methods->endsampwent(context->pwent_methods);
+	if (context->pwent_methods
+		&& context->pwent_methods->ops
+		&& context->pwent_methods->ops->endsampwent)
+		context->pwent_methods->ops->endsampwent(context->pwent_methods);
 
 	/* So we won't get strange data when calling getsampwent now */
 	context->pwent_methods = NULL;
@@ -132,9 +157,9 @@ static NTSTATUS context_getsampwent(stru
 		return ret;
 	}
 	/* Loop until we find something useful */
-	while (NT_STATUS_IS_ERR(ret = context->pwent_methods->getsampwent(context->pwent_methods, user))) {
+	while (NT_STATUS_IS_ERR(ret = context->pwent_methods->ops->getsampwent(context->pwent_methods, user))) {
 
-		context->pwent_methods->endsampwent(context->pwent_methods);
+		context->pwent_methods->ops->endsampwent(context->pwent_methods);
 
 		context->pwent_methods = context->pwent_methods->next;
 
@@ -142,7 +167,7 @@ static NTSTATUS context_getsampwent(stru
 		if (context->pwent_methods == NULL)
 			return ret;
 	
-		context->pwent_methods->setsampwent(context->pwent_methods, False);
+		context->pwent_methods->ops->setsampwent(context->pwent_methods, False);
 	}
 	user->methods = context->pwent_methods;
 	return ret;
@@ -159,7 +184,7 @@ static NTSTATUS context_getsampwnam(stru
 	}
 	curmethods = context->pdb_methods;
 	while (curmethods){
-		if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) {
+		if (NT_STATUS_IS_OK(ret = curmethods->ops->getsampwnam(curmethods, sam_acct, username))) {
 			sam_acct->methods = curmethods;
 			return ret;
 		}
@@ -182,7 +207,7 @@ static NTSTATUS context_getsampwsid(stru
 	curmethods = context->pdb_methods;
 
 	while (curmethods){
-		if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) {
+		if (NT_STATUS_IS_OK(ret = curmethods->ops->getsampwsid(curmethods, sam_acct, sid))) {
 			sam_acct->methods = curmethods;
 			return ret;
 		}
@@ -205,7 +230,7 @@ static NTSTATUS context_add_sam_account(
 	/* We now add a new account to the first database listed. 
 	 * Should we? */
 
-	return context->pdb_methods->add_sam_account(context->pdb_methods, sam_acct);
+	return context->pdb_methods->ops->add_sam_account(context->pdb_methods, sam_acct);
 }
 
 static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
@@ -224,7 +249,7 @@ static NTSTATUS context_update_sam_accou
 
 	/** @todo  This is where a 're-read on update' should be done */
 
-	return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct);
+	return sam_acct->methods->ops->update_sam_account(sam_acct->methods, sam_acct);
 }
 
 static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
@@ -245,7 +270,7 @@ static NTSTATUS context_delete_sam_accou
 		 * in /etc/passwd.
 		 */
 		while (pdb_selected){
-			if (NT_STATUS_IS_OK(ret = pdb_selected->delete_sam_account(pdb_selected, sam_acct))) {
+			if (NT_STATUS_IS_OK(ret = pdb_selected->ops->delete_sam_account(pdb_selected, sam_acct))) {
 				return ret;
 			}
 			pdb_selected = pdb_selected->next;
@@ -253,12 +278,12 @@ static NTSTATUS context_delete_sam_accou
 		return ret;
 	}
 
-	if (!sam_acct->methods->delete_sam_account){
+	if (!sam_acct->methods->ops->delete_sam_account){
 		DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n"));
 		return ret;
 	}
 	
-	return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);
+	return sam_acct->methods->ops->delete_sam_account(sam_acct->methods, sam_acct);
 }
 
 static NTSTATUS context_getgrsid(struct pdb_context *context,
@@ -273,7 +298,7 @@ static NTSTATUS context_getgrsid(struct 
 	}
 	curmethods = context->pdb_methods;
 	while (curmethods){
-		ret = curmethods->getgrsid(curmethods, map, sid, with_priv);
+		ret = curmethods->ops->getgrsid(curmethods, map, sid, with_priv);
 		if (NT_STATUS_IS_OK(ret)) {
 			map->methods = curmethods;
 			return ret;
@@ -296,7 +321,7 @@ static NTSTATUS context_getgrgid(struct 
 	}
 	curmethods = context->pdb_methods;
 	while (curmethods){
-		ret = curmethods->getgrgid(curmethods, map, gid, with_priv);
+		ret = curmethods->ops->getgrgid(curmethods, map, gid, with_priv);
 		if (NT_STATUS_IS_OK(ret)) {
 			map->methods = curmethods;
 			return ret;
@@ -319,7 +344,7 @@ static NTSTATUS context_getgrnam(struct 
 	}
 	curmethods = context->pdb_methods;
 	while (curmethods){
-		ret = curmethods->getgrnam(curmethods, map, name, with_priv);
+		ret = curmethods->ops->getgrnam(curmethods, map, name, with_priv);
 		if (NT_STATUS_IS_OK(ret)) {
 			map->methods = curmethods;
 			return ret;
@@ -340,7 +365,7 @@ static NTSTATUS context_add_group_mappin
 		return ret;
 	}
 
-	return context->pdb_methods->add_group_mapping_entry(context->pdb_methods,
+	return context->pdb_methods->ops->add_group_mapping_entry(context->pdb_methods,
 							     map);
 }
 
@@ -355,7 +380,7 @@ static NTSTATUS context_update_group_map
 	}
 
 	return context->
-		pdb_methods->update_group_mapping_entry(context->pdb_methods, map);
+		pdb_methods->ops->update_group_mapping_entry(context->pdb_methods, map);
 }
 
 static NTSTATUS context_delete_group_mapping_entry(struct pdb_context *context,
@@ -369,7 +394,7 @@ static NTSTATUS context_delete_group_map
 	}
 
 	return context->
-		pdb_methods->delete_group_mapping_entry(context->pdb_methods, sid);
+		pdb_methods->ops->delete_group_mapping_entry(context->pdb_methods, sid);
 }
 
 static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
@@ -384,7 +409,7 @@ static NTSTATUS context_enum_group_mappi
 		return ret;
 	}
 
-	return context->pdb_methods->enum_group_mapping(context->pdb_methods,
+	return context->pdb_methods->ops->enum_group_mapping(context->pdb_methods,
 							sid_name_use, rmap,
 							num_entries, unix_only,
 							with_priv);
@@ -400,8 +425,8 @@ static void free_pdb_context(struct pdb_
 	struct pdb_methods *pdb_selected = (*context)->pdb_methods;
 
 	while (pdb_selected){
-		if(pdb_selected->free_private_data)
-			pdb_selected->free_private_data(&(pdb_selected->private_data));
+		if(pdb_selected->ops->free_private_data)
+			pdb_selected->ops->free_private_data(&(pdb_selected->private_data));
 		pdb_selected = pdb_selected->next;
 	}
 
@@ -413,48 +438,42 @@ static void free_pdb_context(struct pdb_
   Make a pdb_methods from scratch
  *******************************************************************/
 
-static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected)
+static NTSTATUS make_pdb_method(struct pdb_context *context, 
+				struct pdb_methods **method, 
+				struct pdb_backend_function_entry *entry, 
+				const char *param)
 {
-	char *module_name = smb_xstrdup(selected);
-	char *module_location = NULL, *p;
-	struct pdb_init_function_entry *entry;
-	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+	NTSTATUS nt_status;
 
-	lazy_initialize_passdb();
+	if (!context) {
+		smb_panic("no context supplied to make_pdb_method()!\n");
+	}
 
-	entry = backends;
+	if (!method) {
+		smb_panic("make_pdb_method: pointer to method pointer is NULL!\n");
+	}
 
-	p = strchr(module_name, ':');
+	if (!entry) {
+		smb_panic("make_pdb_method: pointer to entry pointer is NULL!\n");
+	}
 
-	if (p) {
-		*p = 0;
-		module_location = p+1;
-		trim_string(module_location, " ", " ");
-	}
-
-	trim_string(module_name, " ", " ");
-
-	DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
-	while(entry) {
-		if (strequal(entry->name, module_name))
-		{
-			DEBUG(5,("Found pdb backend %s\n", module_name));
-			nt_status = entry->init(context, methods, module_location);
-			if (NT_STATUS_IS_OK(nt_status)) {
-				DEBUG(5,("pdb backend %s has a valid init\n", selected));
-			} else {
-				DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
-			}
-			SAFE_FREE(module_name);
-			return nt_status;
-			break; /* unreached */
-		}
-		entry = entry->next;
+	if (!entry->ops||!entry->name) {
+		smb_panic("make_pdb_method: entry->ops or entry->name pointer is NULL!\n");
 	}
 
-	/* No such backend found */
-	SAFE_FREE(module_name);
-	return NT_STATUS_INVALID_PARAMETER;
+	if (((*method) = (struct pdb_methods *)talloc_zero(context->mem_ctx,sizeof(struct pdb_methods)))==NULL) {
+		DEBUG(0,("make_pdb_method: talloc_zero failed\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+	
+	(*method)->parent	= context;
+	(*method)->name		= entry->name;
+	(*method)->ops		= entry->ops;
+	(*method)->param	= talloc_strdup(context->mem_ctx,param);
+	
+	nt_status = (*method)->ops->init_private_data(context->mem_ctx,&(*method)->private_data,(*method)->param);
+
+	return nt_status;
 }
 
 /******************************************************************
@@ -507,31 +526,71 @@ static NTSTATUS make_pdb_context(struct 
 /******************************************************************
   Make a pdb_context, given an array of strings
  *******************************************************************/
-
-NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **selected) 
+ 
+NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **text_list) 
 {
+	struct pdb_methods *list = NULL;
+	struct pdb_methods *tmp, *method = NULL;
+	struct pdb_backend_function_entry *entry;
 	int i = 0;
-	struct pdb_methods *curmethods, *tmpmethods;
-	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+	NTSTATUS nt_status;
 
-	if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
-		return nt_status;
+	if (!text_list) {
+		DEBUG(2,("make_pdb_context_list: No pdb backend list!?\n"));
+		return NT_STATUS_INVALID_PARAMETER;
 	}
+	
+	if (NT_STATUS_IS_ERR(nt_status = make_pdb_context(context)))
+		return nt_status;
+	
+	lazy_initialize_passdb();
+	
+	for (;*text_list; text_list++) {
+		BOOL found = False;
+		char *module_name = smb_xstrdup(*text_list);
+		char *module_param = NULL, *p;
+
+		p = strchr(module_name, ':');
+	
+		if (p) {
+			*p = 0;
+			module_param = p+1;
+			trim_string(module_param, " ", " ");
+		}
+	
+		trim_string(module_name, " ", " ");
+	
+		DEBUG(7,("make_pdb_context_list: Attempting to find an passdb backend to match '%s'\n",
+					module_name));
+		for (entry = global_passdb_backends;entry;entry = entry->next) {
+			if (strequal(entry->name, module_name)) {
+				found = True;
+				DEBUG(5,("make_pdb_context_list: Found passdb backend '%s' (at pos %d)\n", module_name, i));
+
+				if (NT_STATUS_IS_ERR(nt_status = make_pdb_method(*context,&method, entry, module_param))) {
+					DEBUG(0,("make_pdb_context_list: make_pdb_method failed for '%s'\n",module_name));
+					SAFE_FREE(module_name);
+					return nt_status;
+				}
+
+				DLIST_ADD_END(list, method, tmp);
+				i++;
+				break;
+			}
+		}
+
+		if (!found) {
+			DEBUG(5,("make_pdb_context_list: don't find an passdb backend '%s'\n",
+					module_name));
+			SAFE_FREE(module_name);
+			return NT_STATUS_INVALID_PARAMETER;/* or logon_failure ??? */
+		}
 
-	while (selected[i]){
-		/* Try to initialise pdb */
-		DEBUG(5,("Trying to load: %s\n", selected[i]));
-		if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) {
-			DEBUG(1, ("Loading %s failed!\n", selected[i]));
-			free_pdb_context(context);
-			return nt_status;
-		}
-		curmethods->parent = *context;
-		DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
-		i++;
+		SAFE_FREE(module_name);
 	}
 
-	return NT_STATUS_OK;
+	(*context)->pdb_methods = list;
+	return nt_status;
 }
 
 /******************************************************************
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/passdb/pdb_ldap.c HEAD-modules/source/passdb/pdb_ldap.c
--- HEAD/source/passdb/pdb_ldap.c	Wed Dec  4 07:18:42 2002
+++ HEAD-modules/source/passdb/pdb_ldap.c	Tue Dec 17 14:11:33 2002
@@ -1976,11 +1976,9 @@ static NTSTATUS ldapsam_enum_group_mappi
 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
-static void free_private_data(void **vp) 
+static NTSTATUS ldapsam_free_private_data(void **privates) 
 {
-	struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
-
-	ldapsam_close(*ldap_state);
+	struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)privates;
 
 	if ((*ldap_state)->bind_secret) {
 		memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
@@ -1994,38 +1992,16 @@ static void free_private_data(void **vp)
 	*ldap_state = NULL;
 
 	/* No need to free any further, as it is talloc()ed */
+	return NT_STATUS_OK;
 }
 
-NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS ldapsam_init_private_data(TALLOC_CTX *mem_ctx, void **privates, const char *location)
 {
-	NTSTATUS nt_status;
-	struct ldapsam_privates *ldap_state;
-
-	if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
-		return nt_status;
-	}
-
-	(*pdb_method)->name = "ldapsam";
-
-	(*pdb_method)->setsampwent = ldapsam_setsampwent;
-	(*pdb_method)->endsampwent = ldapsam_endsampwent;
-	(*pdb_method)->getsampwent = ldapsam_getsampwent;
-	(*pdb_method)->getsampwnam = ldapsam_getsampwnam;
-	(*pdb_method)->getsampwsid = ldapsam_getsampwsid;
-	(*pdb_method)->add_sam_account = ldapsam_add_sam_account;
-	(*pdb_method)->update_sam_account = ldapsam_update_sam_account;
-	(*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
-	(*pdb_method)->getgrsid = ldapsam_getgrsid;
-	(*pdb_method)->getgrgid = ldapsam_getgrgid;
-	(*pdb_method)->getgrnam = ldapsam_getgrnam;
-	(*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
-	(*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
-	(*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
-	(*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
+	struct ldapsam_privates *ldap_state = NULL;
 
 	/* TODO: Setup private data and free */
 
-	ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
+	ldap_state = talloc_zero(mem_ctx, sizeof(struct ldapsam_privates));
 
 	if (!ldap_state) {
 		DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
@@ -2033,7 +2009,7 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *p
 	}
 
 	if (location) {
-		ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
+		ldap_state->uri = talloc_strdup(mem_ctx, location);
 #ifdef WITH_LDAP_SAMCONFIG
 	} else {
 		int ldap_port = lp_ldap_port();
@@ -2043,7 +2019,7 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *p
 			ldap_port = 389;
 		}
 
-		ldap_state->uri = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
+		ldap_state->uri = talloc_asprintf(mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
 		if (!ldap_state->uri) {
 			return NT_STATUS_NO_MEMORY;
 		}
@@ -2053,26 +2029,46 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *p
 #endif
 	}
 
-	(*pdb_method)->private_data = ldap_state;
-
-	(*pdb_method)->free_private_data = free_private_data;
+	(*privates) = ldap_state;
 
 	return NT_STATUS_OK;
 }
 
-NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+
+struct pdb_method_ops pdb_ldapsam_ops = {
+	ldapsam_setsampwent,
+	ldapsam_endsampwent,
+	ldapsam_getsampwent,
+	ldapsam_getsampwnam,
+	ldapsam_getsampwsid,
+	ldapsam_add_sam_account,
+	ldapsam_update_sam_account,
+	ldapsam_delete_sam_account,
+
+	ldapsam_getgrsid,
+	ldapsam_getgrgid,
+	ldapsam_getgrnam,
+	ldapsam_add_group_mapping_entry,
+	ldapsam_update_group_mapping_entry,
+	ldapsam_delete_group_mapping_entry,
+	ldapsam_enum_group_mapping,
+
+	ldapsam_init_private_data,
+	ldapsam_free_private_data
+};
+
+
+static NTSTATUS ldapsam_nua_init_private_data(TALLOC_CTX *mem_ctx, void **privates, const char *location)
 {
 	NTSTATUS nt_status;
 	struct ldapsam_privates *ldap_state;
 	uint32 low_nua_uid, high_nua_uid;
 
-	if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
+	if (!NT_STATUS_IS_OK(nt_status = ldapsam_init_private_data(mem_ctx, privates, location))) {
 		return nt_status;
 	}
 
-	(*pdb_method)->name = "ldapsam_nua";
-
-	ldap_state = (*pdb_method)->private_data;
+	ldap_state = (*privates);
 	
 	ldap_state->permit_non_unix_accounts = True;
 
@@ -2088,20 +2084,32 @@ NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEX
 	return NT_STATUS_OK;
 }
 
+struct pdb_method_ops pdb_ldapsam_nua_ops = {
+	ldapsam_setsampwent,
+	ldapsam_endsampwent,
+	ldapsam_getsampwent,
+	ldapsam_getsampwnam,
+	ldapsam_getsampwsid,
+	ldapsam_add_sam_account,
+	ldapsam_update_sam_account,
+	ldapsam_delete_sam_account,
+
+	ldapsam_getgrsid,
+	ldapsam_getgrgid,
+	ldapsam_getgrnam,
+	ldapsam_add_group_mapping_entry,
+	ldapsam_update_group_mapping_entry,
+	ldapsam_delete_group_mapping_entry,
+	ldapsam_enum_group_mapping,
+
+	ldapsam_nua_init_private_data,
+	ldapsam_free_private_data
+};
 
 #else
 
-NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+void ldapsam_dummy_fn(void)
 {
-	DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
-	return NT_STATUS_UNSUCCESSFUL;
+	;
 }
-
-NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
-{
-	DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
-	return NT_STATUS_UNSUCCESSFUL;
-}
-
-
 #endif
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/passdb/pdb_nisplus.c HEAD-modules/source/passdb/pdb_nisplus.c
--- HEAD/source/passdb/pdb_nisplus.c	Fri Oct 25 07:33:02 2002
+++ HEAD-modules/source/passdb/pdb_nisplus.c	Wed Dec 18 08:09:42 2002
@@ -24,6 +24,9 @@
 
 #include "includes.h"
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_PASSDB
+
 #ifdef WITH_NISPLUS_SAM
 
 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
@@ -105,7 +108,7 @@
 #define NPF_WORKSTATIONS  20
 #define NPF_HOURS         21
 
-struct nisplus_private_info {
+struct nisplus_privates {
 	nis_result *result;
 	int enum_entry;
 	char *location;
@@ -132,8 +135,8 @@ static nis_result *nisp_get_nis_list (co
 
 static NTSTATUS nisplussam_setsampwent (struct pdb_methods *methods, BOOL update)
 {
-	struct nisplus_private_info *private =
-		(struct nisplus_private_info *) methods->private_data;
+	struct nisplus_privates *private =
+		(struct nisplus_privates *) methods->private_data;
 
 	char *sp;
 	pstring pfiletmp;
@@ -141,14 +144,14 @@ static NTSTATUS nisplussam_setsampwent (
 	if ((sp = strrchr (private->location, '/')))
 		safe_strcpy (pfiletmp, sp + 1, sizeof (pfiletmp) - 1);
 	else
-		safe_strcpy (pfiletmp, p, sizeof (pfiletmp) - 1);
+		safe_strcpy (pfiletmp, sp, sizeof (pfiletmp) - 1);
 	safe_strcat (pfiletmp, ".org_dir",
 		     sizeof (pfiletmp) - strlen (pfiletmp) - 1);
 
 	pdb_endsampwent ();	/* just in case */
-	global_nisp_ent->result = nisp_get_nis_list (pfiletmp, 0);
-	global_nisp_ent->enum_entry = 0;
-	if (global_nisp_ent->result != NULL) 
+	private->result = nisp_get_nis_list (pfiletmp, 0);
+	private->enum_entry = 0;
+	if (private->result != NULL) 
 		return NT_STATUS_UNSUCCESSFUL;
 	else
 		return NT_STATUS_OK;
@@ -160,8 +163,8 @@ static NTSTATUS nisplussam_setsampwent (
 
 static void nisplussam_endsampwent (struct pdb_methods *methods)
 {
-	struct nisplus_private_info *global_nisp_ent =
-		(struct nisplus_private_info *) methods->private_data;
+	struct nisplus_privates *global_nisp_ent =
+		(struct nisplus_privates *) methods->private_data;
 	if (global_nisp_ent->result)
 		nis_freeresult (global_nisp_ent->result);
 	global_nisp_ent->result = NULL;
@@ -176,8 +179,8 @@ static NTSTATUS nisplussam_getsampwent (
 				    SAM_ACCOUNT * user)
 {
 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-	struct nisplus_private_info *global_nisp_ent =
-		(struct nisplus_private_info *) methods->private_data;
+	struct nisplus_privates *global_nisp_ent =
+		(struct nisplus_privates *) methods->private_data;
 	int enum_entry = (int) (global_nisp_ent->enum_entry);
 	nis_result *result = global_nisp_ent->result;
 
@@ -211,8 +214,8 @@ static NTSTATUS nisplussam_getsampwnam (
 	nis_result *result = NULL;
 	pstring nisname;
 	BOOL ret;
-	struct nisplus_private_info *private =
-		(struct nisplus_private_info *) methods->private_data;
+	struct nisplus_privates *private =
+		(struct nisplus_privates *) methods->private_data;
 
 	if (!private->location || !(*private->location)) {
 		DEBUG (0, ("No SMB password file set\n"));
@@ -252,8 +255,8 @@ static NTSTATUS nisplussam_getsampwrid (
 	BOOL ret;
 	char *sp;
 	pstring pfiletmp;
-	struct nisplus_private_info *private =
-		(struct nisplus_private_info *) methods->private_data;
+	struct nisplus_privates *private =
+		(struct nisplus_privates *) methods->private_data;
 
 	if (!private->location || !(*private->location)) {
 		DEBUG (0, ("no SMB password file set\n"));
@@ -309,8 +312,8 @@ static NTSTATUS nisplussam_delete_sam_ac
 	pstring nisname;
 	nis_result *result, *delresult;
 	nis_object *obj;
-	struct nisplus_private_info *private =
-		(struct nisplus_private_info *) methods->private_data;
+	struct nisplus_privates *private =
+		(struct nisplus_privates *) methods->private_data;
 
 	if (!user) {
 		DEBUG (0, ("no SAM_ACCOUNT specified!\n"));
@@ -382,8 +385,8 @@ static NTSTATUS nisplussam_update_sam_ac
 	nis_object new_obj;
 	entry_col *ecol;
 	int ta_maxcol;
-	struct nisplus_private_info *private =
-		(struct nisplus_private_info *) methods->private_data;
+	struct nisplus_privates *private =
+		(struct nisplus_privates *) methods->private_data;
 	pstring nisname;
 
 	if (!private->location || !(*private->location)) {
@@ -405,7 +408,7 @@ static NTSTATUS nisplussam_update_sam_ac
 	     nisp_get_nis_list (nisname,
 				MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
 				EXPAND_NAME | HARD_LOOKUP))) {
-		return ne_status;
+		return nt_status;
 	}
 
 	if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ (result) <= 0) {
@@ -484,6 +487,8 @@ static NTSTATUS nisplussam_add_sam_accou
 	nis_object new_obj;
 	entry_col *ecol;
 	int ta_maxcol;
+	struct nisplus_privates *private =
+		(struct nisplus_privates *) methods->private_data;
 
 	/*
 	 * 1. find user domain.
@@ -866,7 +871,7 @@ static BOOL make_sam_from_nisp_object (S
 	pdb_set_fullname (pw_buf, full_name, PDB_SET);
 
 	pdb_set_acct_ctrl (pw_buf, pdb_decode_acct_ctrl (ENTRY_VAL (obj,
-								    NPF_ACB), PDB_SET));
+								    NPF_ACB)), PDB_SET);
 
 	get_single_attribute (obj, NPF_ACCT_DESC, acct_desc,
 			      sizeof (pstring));
@@ -1508,58 +1513,104 @@ static nis_result *nisp_get_nis_list (co
 	return result;
 }
 
-static void free_private_data(void **vp)
+static NTSTATUS nisplussam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
+				 DOM_SID sid, BOOL with_priv)
 {
-	struct nisplus_private_info **private = (struct nisplus_private_info **)vp;
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-	if ((*private)->result) {
-		nis_freeresult ((*private)->result);
-	}
+static NTSTATUS nisplussam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
+				 gid_t gid, BOOL with_priv)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-	free(*private);
+static NTSTATUS nisplussam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
+				 char *name, BOOL with_priv)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-        /* No need to free any further, as it is talloc()ed */
+static NTSTATUS nisplussam_add_group_mapping_entry(struct pdb_methods *methods,
+						GROUP_MAP *map)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * pdb_context,
-			      PDB_METHODS ** pdb_method, const char *location)
+static NTSTATUS nisplussam_update_group_mapping_entry(struct pdb_methods *methods,
+						   GROUP_MAP *map)
 {
-	NTSTATUS nt_status;
-	struct nisplus_private_info *private = malloc (sizeof (struct nisplus_private_info));
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-	ZERO_STRUCT(private);
-	p->location = talloc_strdup(pdb_context->mem_ctx, location);
+static NTSTATUS nisplussam_delete_group_mapping_entry(struct pdb_methods *methods,
+						   DOM_SID sid)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
 
-	if (!NT_STATUS_IS_OK
-	    (nt_status =
-	     make_pdb_methods (pdb_context->mem_ctx, pdb_method))) {
-		return nt_status;
+static NTSTATUS nisplussam_enum_group_mapping(struct pdb_methods *methods,
+					   enum SID_NAME_USE sid_name_use,
+					   GROUP_MAP **rmap, int *num_entries,
+					   BOOL unix_only, BOOL with_priv)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS nisplussam_free_private_data(void **vp)
+{
+	struct nisplus_privates **privates = (struct nisplus_privates **)vp;
+
+	if (privates&&(*privates)&&(*privates)->result) {
+		nis_freeresult ((*privates)->result);
 	}
 
-	(*pdb_method)->name = "nisplussam";
+        /* No need to free any further, as it is talloc()ed */
+        return NT_STATUS_OK;
+}
 
-	/* Functions your pdb module doesn't provide should be set 
-	 * to NULL */
+static NTSTATUS nisplussam_init_private_data (TALLOC_CTX *mem_ctx, void **private_data, const char *location)
+{
+	struct nisplus_privates *nisplus_state;
 
-	(*pdb_method)->setsampwent = nisplussam_setsampwent;
-	(*pdb_method)->endsampwent = nisplussam_endsampwent;
-	(*pdb_method)->getsampwent = nisplussam_getsampwent;
-	(*pdb_method)->getsampwnam = nisplussam_getsampwnam;
-	(*pdb_method)->getsampwsid = nisplussam_getsampwsid;
-	(*pdb_method)->add_sam_account = nisplussam_add_sam_account;
-	(*pdb_method)->update_sam_account = nisplussam_update_sam_account;
-	(*pdb_method)->delete_sam_account = nisplussam_delete_sam_account;
-	(*pdb_method)->free_private_data = free_private_data;
-	(*pdb_method)->private_data = private;
+	if ((nisplus_state = (struct nisplus_privates *)talloc_zero(mem_ctx, sizeof (struct nisplus_privates)))==NULL) {
+		DEBUG(0,("nisplussam_init_private_data: talloc_zero() failed\n"));
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	nisplus_state->location = talloc_strdup(mem_ctx, location);
 
+	(*private_data) = nisplus_state;
 	return NT_STATUS_OK;
 }
 
-#else
-NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * c, PDB_METHODS ** m,
-			      const char *l)
+struct pdb_method_ops pdb_nisplussam_ops = {
+	nisplussam_setsampwent,
+	nisplussam_endsampwent,
+	nisplussam_getsampwent,
+	nisplussam_getsampwnam,
+	nisplussam_getsampwsid,
+	nisplussam_add_sam_account,
+	nisplussam_update_sam_account,
+	nisplussam_delete_sam_account,
+
+	nisplussam_getgrsid,
+	nisplussam_getgrgid,
+	nisplussam_getgrnam,
+	nisplussam_add_group_mapping_entry,
+	nisplussam_update_group_mapping_entry,
+	nisplussam_delete_group_mapping_entry,
+	nisplussam_enum_group_mapping,
+
+	nisplussam_init_private_data,
+	nisplussam_free_private_data
+};
+
+#else /* WITH_NISPLUS_SAM */
+
+void nisplussam_dummy(void)
 {
-	DEBUG (0, ("nisplus sam not compiled in!\n"));
-	return NT_STATUS_UNSUCCESSFUL;
+	;
 }
+
 #endif /* WITH_NISPLUS_SAM */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/passdb/pdb_smbpasswd.c HEAD-modules/source/passdb/pdb_smbpasswd.c
--- HEAD/source/passdb/pdb_smbpasswd.c	Sun Nov 10 00:34:40 2002
+++ HEAD-modules/source/passdb/pdb_smbpasswd.c	Tue Dec 17 14:18:17 2002
@@ -1545,7 +1545,7 @@ static NTSTATUS smbpasswd_enum_group_map
 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
-static void free_private_data(void **vp) 
+static NTSTATUS smbpasswd_free_private_data(void **vp) 
 {
 	struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
 	
@@ -1553,39 +1553,17 @@ static void free_private_data(void **vp)
 	
 	*privates = NULL;
 	/* No need to free any further, as it is talloc()ed */
+	return NT_STATUS_OK;
 }
 
 
-NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS smbpasswd_init_private_data(TALLOC_CTX *mem_ctx, void **private_data, const char *location)
 {
-	NTSTATUS nt_status;
 	struct smbpasswd_privates *privates;
 
-	if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
-		return nt_status;
-	}
-
-	(*pdb_method)->name = "smbpasswd";
-
-	(*pdb_method)->setsampwent = smbpasswd_setsampwent;
-	(*pdb_method)->endsampwent = smbpasswd_endsampwent;
-	(*pdb_method)->getsampwent = smbpasswd_getsampwent;
-	(*pdb_method)->getsampwnam = smbpasswd_getsampwnam;
-	(*pdb_method)->getsampwsid = smbpasswd_getsampwsid;
-	(*pdb_method)->add_sam_account = smbpasswd_add_sam_account;
-	(*pdb_method)->update_sam_account = smbpasswd_update_sam_account;
-	(*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
-	(*pdb_method)->getgrsid = smbpasswd_getgrsid;
-	(*pdb_method)->getgrgid = smbpasswd_getgrgid;
-	(*pdb_method)->getgrnam = smbpasswd_getgrnam;
-	(*pdb_method)->add_group_mapping_entry = smbpasswd_add_group_mapping_entry;
-	(*pdb_method)->update_group_mapping_entry = smbpasswd_update_group_mapping_entry;
-	(*pdb_method)->delete_group_mapping_entry = smbpasswd_delete_group_mapping_entry;
-	(*pdb_method)->enum_group_mapping = smbpasswd_enum_group_mapping;
-
 	/* Setup private data and free function */
 
-	privates = talloc_zero(pdb_context->mem_ctx, sizeof(struct smbpasswd_privates));
+	privates = (struct smbpasswd_privates *)talloc_zero(mem_ctx, sizeof(struct smbpasswd_privates));
 
 	if (!privates) {
 		DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
@@ -1595,9 +1573,9 @@ NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT 
 	/* Store some config details */
 
 	if (location) {
-		privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, location);
+		privates->smbpasswd_file = talloc_strdup(mem_ctx, location);
 	} else {
-		privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, lp_smb_passwd_file());
+		privates->smbpasswd_file = talloc_strdup(mem_ctx, lp_smb_passwd_file());
 	}
 	
 	if (!privates->smbpasswd_file) {
@@ -1605,25 +1583,43 @@ NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT 
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	(*pdb_method)->private_data = privates;
-
-	(*pdb_method)->free_private_data = free_private_data;
+	(*private_data) = privates;
 
 	return NT_STATUS_OK;
 }
 
-NTSTATUS pdb_init_smbpasswd_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+struct pdb_method_ops pdb_smbpasswd_ops = {
+	smbpasswd_setsampwent,
+	smbpasswd_endsampwent,
+	smbpasswd_getsampwent,
+	smbpasswd_getsampwnam,
+	smbpasswd_getsampwsid,
+	smbpasswd_add_sam_account,
+	smbpasswd_update_sam_account,
+	smbpasswd_delete_sam_account,
+
+	smbpasswd_getgrsid,
+	smbpasswd_getgrgid,
+	smbpasswd_getgrnam,
+	smbpasswd_add_group_mapping_entry,
+	smbpasswd_update_group_mapping_entry,
+	smbpasswd_delete_group_mapping_entry,
+	smbpasswd_enum_group_mapping,
+
+	smbpasswd_init_private_data,
+	smbpasswd_free_private_data
+};
+
+static NTSTATUS smbpasswd_nua_init_private_data(TALLOC_CTX *mem_ctx, void **private_data, const char *location)
 {
 	NTSTATUS nt_status;
 	struct smbpasswd_privates *privates;
 
-	if (!NT_STATUS_IS_OK(nt_status = pdb_init_smbpasswd(pdb_context, pdb_method, location))) {
+	if (!NT_STATUS_IS_OK(nt_status = smbpasswd_init_private_data(mem_ctx, private_data, location))) {
 		return nt_status;
 	}
 
-	(*pdb_method)->name = "smbpasswd_nua";
-
-	privates = (*pdb_method)->private_data;
+	privates = (*private_data);
 	
 	privates->permit_non_unix_accounts = True;
 
@@ -1634,3 +1630,26 @@ NTSTATUS pdb_init_smbpasswd_nua(PDB_CONT
 
 	return NT_STATUS_OK;
 }
+
+
+struct pdb_method_ops pdb_smbpasswd_nua_ops = {
+	smbpasswd_setsampwent,
+	smbpasswd_endsampwent,
+	smbpasswd_getsampwent,
+	smbpasswd_getsampwnam,
+	smbpasswd_getsampwsid,
+	smbpasswd_add_sam_account,
+	smbpasswd_update_sam_account,
+	smbpasswd_delete_sam_account,
+
+	smbpasswd_getgrsid,
+	smbpasswd_getgrgid,
+	smbpasswd_getgrnam,
+	smbpasswd_add_group_mapping_entry,
+	smbpasswd_update_group_mapping_entry,
+	smbpasswd_delete_group_mapping_entry,
+	smbpasswd_enum_group_mapping,
+
+	smbpasswd_nua_init_private_data,
+	smbpasswd_free_private_data
+};
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/passdb/pdb_tdb.c HEAD-modules/source/passdb/pdb_tdb.c
--- HEAD/source/passdb/pdb_tdb.c	Tue Oct 22 07:35:11 2002
+++ HEAD-modules/source/passdb/pdb_tdb.c	Wed Dec 18 08:09:01 2002
@@ -24,19 +24,9 @@
 
 #include "includes.h"
 
-#if 0 /* when made a module use this */
-
-static int tdbsam_debug_level = DBGC_ALL;
-#undef DBGC_CLASS
-#define DBGC_CLASS tdbsam_debug_level
-
-#else
-
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
 
-#endif
-
 #ifdef WITH_TDB_SAM
 
 #define PDB_VERSION		"20010830"
@@ -948,52 +938,23 @@ static NTSTATUS tdbsam_enum_group_mappin
 		NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
-static void free_private_data(void **vp) 
+static NTSTATUS tdbsam_free_private_data(void **vp) 
 {
 	struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
 	close_tdb(*tdb_state);
 	*tdb_state = NULL;
 
 	/* No need to free any further, as it is talloc()ed */
+	return NT_STATUS_OK;
 }
 
 
-NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS tdbsam_init_private_data(TALLOC_CTX *mem_ctx, void **privates, const char *location)
 {
-	NTSTATUS nt_status;
 	struct tdbsam_privates *tdb_state;
 
-#if 0 /* when made a module use this */
-	tdbsam_debug_level = debug_add_class("tdbsam");
-	if(tdbsam_debug_level == -1) {
-		tdbsam_debug_level = DBGC_ALL;
-		DEBUG(0, ("tdbsam: Couldn't register custom debugging class!\n"));
-	}
-#endif
-
-	if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
-		return nt_status;
-	}
-
-	(*pdb_method)->name = "tdbsam";
-
-	(*pdb_method)->setsampwent = tdbsam_setsampwent;
-	(*pdb_method)->endsampwent = tdbsam_endsampwent;
-	(*pdb_method)->getsampwent = tdbsam_getsampwent;
-	(*pdb_method)->getsampwnam = tdbsam_getsampwnam;
-	(*pdb_method)->getsampwsid = tdbsam_getsampwsid;
-	(*pdb_method)->add_sam_account = tdbsam_add_sam_account;
-	(*pdb_method)->update_sam_account = tdbsam_update_sam_account;
-	(*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
-	(*pdb_method)->getgrsid = tdbsam_getgrsid;
-	(*pdb_method)->getgrgid = tdbsam_getgrgid;
-	(*pdb_method)->getgrnam = tdbsam_getgrnam;
-	(*pdb_method)->add_group_mapping_entry = tdbsam_add_group_mapping_entry;
-	(*pdb_method)->update_group_mapping_entry = tdbsam_update_group_mapping_entry;
-	(*pdb_method)->delete_group_mapping_entry = tdbsam_delete_group_mapping_entry;
-	(*pdb_method)->enum_group_mapping = tdbsam_enum_group_mapping;
 
-	tdb_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct tdbsam_privates));
+	tdb_state = talloc_zero(mem_ctx, sizeof(struct tdbsam_privates));
 
 	if (!tdb_state) {
 		DEBUG(0, ("talloc() failed for tdbsam private_data!\n"));
@@ -1001,37 +962,55 @@ NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pd
 	}
 
 	if (location) {
-		tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, location);
+		tdb_state->tdbsam_location = talloc_strdup(mem_ctx, location);
 	} else {
 		pstring tdbfile;
 		get_private_directory(tdbfile);
 		pstrcat(tdbfile, "/");
 		pstrcat(tdbfile, PASSDB_FILE_NAME);
-		tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile);
+		tdb_state->tdbsam_location = talloc_strdup(mem_ctx, tdbfile);
 	}
 
 	tdb_state->algorithmic_rids = True;
 
-	(*pdb_method)->private_data = tdb_state;
-
-	(*pdb_method)->free_private_data = free_private_data;
+	(*privates) = tdb_state;
 
 	return NT_STATUS_OK;
 }
 
-NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+struct pdb_method_ops pdb_tdbsam_ops = {
+	tdbsam_setsampwent,
+	tdbsam_endsampwent,
+	tdbsam_getsampwent,
+	tdbsam_getsampwnam,
+	tdbsam_getsampwsid,
+	tdbsam_add_sam_account,
+	tdbsam_update_sam_account,
+	tdbsam_delete_sam_account,
+
+	tdbsam_getgrsid,
+	tdbsam_getgrgid,
+	tdbsam_getgrnam,
+	tdbsam_add_group_mapping_entry,
+	tdbsam_update_group_mapping_entry,
+	tdbsam_delete_group_mapping_entry,
+	tdbsam_enum_group_mapping,
+
+	tdbsam_init_private_data,
+	tdbsam_free_private_data
+};
+
+static NTSTATUS tdbsam_nua_init_private_data(TALLOC_CTX *mem_ctx, void **privates, const char *location)
 {
 	NTSTATUS nt_status;
 	struct tdbsam_privates *tdb_state;
 	uint32 low_nua_uid, high_nua_uid;
 
-	if (!NT_STATUS_IS_OK(nt_status = pdb_init_tdbsam(pdb_context, pdb_method, location))) {
+	if (!NT_STATUS_IS_OK(nt_status = tdbsam_init_private_data(mem_ctx, privates, location))) {
 		return nt_status;
 	}
 
-	(*pdb_method)->name = "tdbsam_nua";
-
-	tdb_state = (*pdb_method)->private_data;
+	tdb_state = (*privates);
 
 	tdb_state->permit_non_unix_accounts = True;
 
@@ -1047,20 +1026,33 @@ NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT
 	return NT_STATUS_OK;
 }
 
+struct pdb_method_ops pdb_tdbsam_nua_ops = {
+	tdbsam_setsampwent,
+	tdbsam_endsampwent,
+	tdbsam_getsampwent,
+	tdbsam_getsampwnam,
+	tdbsam_getsampwsid,
+	tdbsam_add_sam_account,
+	tdbsam_update_sam_account,
+	tdbsam_delete_sam_account,
+
+	tdbsam_getgrsid,
+	tdbsam_getgrgid,
+	tdbsam_getgrnam,
+	tdbsam_add_group_mapping_entry,
+	tdbsam_update_group_mapping_entry,
+	tdbsam_delete_group_mapping_entry,
+	tdbsam_enum_group_mapping,
 
-#else
+	tdbsam_nua_init_private_data,
+	tdbsam_free_private_data
+};
 
-NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
-{
-	DEBUG(0, ("tdbsam not compiled in!\n"));
-	return NT_STATUS_UNSUCCESSFUL;
-}
+#else /* WITH_TDB_SAM */
 
-NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+void tdbsam_dummy(void)
 {
-	DEBUG(0, ("tdbsam_nua not compiled in!\n"));
-	return NT_STATUS_UNSUCCESSFUL;
+	;
 }
 
-
-#endif
+#endif /* WITH_TDB_SAM */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/passdb/pdb_unix.c HEAD-modules/source/passdb/pdb_unix.c
--- HEAD/source/passdb/pdb_unix.c	Tue Oct 22 07:35:11 2002
+++ HEAD-modules/source/passdb/pdb_unix.c	Tue Dec 17 13:52:10 2002
@@ -177,37 +177,34 @@ static NTSTATUS unixsam_enum_group_mappi
 	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS pdb_init_unixsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS unixsam_init_private_data(TALLOC_CTX *mem_ctx,void **privates,char *param)
 {
-	NTSTATUS nt_status;
-	
-	if (!pdb_context) {
-		DEBUG(0, ("invalid pdb_context specified\n"));
-		return NT_STATUS_UNSUCCESSFUL;
-	}
+	return NT_STATUS_OK;
+}
 
-	if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
-		return nt_status;
-	}
-	
-	(*pdb_method)->name = "unixsam";
-	
-	(*pdb_method)->setsampwent = unixsam_setsampwent;
-	(*pdb_method)->endsampwent = unixsam_endsampwent;
-	(*pdb_method)->getsampwent = unixsam_getsampwent;
-	(*pdb_method)->getsampwnam = unixsam_getsampwnam;
-	(*pdb_method)->getsampwsid = unixsam_getsampwsid;
-	(*pdb_method)->add_sam_account = unixsam_add_sam_account;
-	(*pdb_method)->update_sam_account = unixsam_update_sam_account;
-	(*pdb_method)->delete_sam_account = unixsam_delete_sam_account;
-	(*pdb_method)->getgrsid = unixsam_getgrsid;
-	(*pdb_method)->getgrgid = unixsam_getgrgid;
-	(*pdb_method)->getgrnam = unixsam_getgrnam;
-	(*pdb_method)->add_group_mapping_entry = unixsam_add_group_mapping_entry;
-	(*pdb_method)->update_group_mapping_entry = unixsam_update_group_mapping_entry;
-	(*pdb_method)->delete_group_mapping_entry = unixsam_delete_group_mapping_entry;
-	(*pdb_method)->enum_group_mapping = unixsam_enum_group_mapping;
-	
-	/* There's not very much to initialise here */
+static NTSTATUS unixsam_free_private_data(void **privates)
+{
 	return NT_STATUS_OK;
 }
+
+struct pdb_method_ops pdb_unixsam_ops = {
+	unixsam_setsampwent,
+	unixsam_endsampwent,
+	unixsam_getsampwent,
+	unixsam_getsampwnam,
+	unixsam_getsampwsid,
+	unixsam_add_sam_account,
+	unixsam_update_sam_account,
+	unixsam_delete_sam_account,
+
+	unixsam_getgrsid,
+	unixsam_getgrgid,
+	unixsam_getgrnam,
+	unixsam_add_group_mapping_entry,
+	unixsam_update_group_mapping_entry,
+	unixsam_delete_group_mapping_entry,
+	unixsam_enum_group_mapping,
+
+	unixsam_init_private_data,
+	unixsam_free_private_data
+};
\ No newline at end of file
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/sam/sam_ads.c HEAD-modules/source/sam/sam_ads.c
--- HEAD/source/sam/sam_ads.c	Wed Dec  4 07:18:43 2002
+++ HEAD-modules/source/sam/sam_ads.c	Tue Dec 10 16:52:34 2002
@@ -1328,10 +1328,10 @@ NTSTATUS sam_init_ads(SAM_METHODS *sam_m
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	sam_ads_state->ads_bind_dn = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(NULL,"sam_ads","bind as"));
-	sam_ads_state->ads_bind_pw = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(NULL,"sam_ads","bind pw"));
+	sam_ads_state->ads_bind_dn = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(GLOBAL_SECTION_SNUM,"sam_ads","bind as",""));
+	sam_ads_state->ads_bind_pw = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(GLOBAL_SECTION_SNUM,"sam_ads","bind pw",""));
 
-	sam_ads_state->bind_plaintext = strequal(lp_parm_string(NULL, "sam_ads", "plaintext bind"), "yes");
+	sam_ads_state->bind_plaintext = lp_parm_bool(GLOBAL_SECTION_SNUM, "sam_ads", "plaintext bind",True);
 
 	if (!sam_ads_state->ads_bind_dn || !sam_ads_state->ads_bind_pw) {
 		DEBUG(0, ("talloc_strdup() failed for bind dn or password\n"));
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/smbd/conn.c HEAD-modules/source/smbd/conn.c
--- HEAD/source/smbd/conn.c	Tue Aug 20 12:48:38 2002
+++ HEAD-modules/source/smbd/conn.c	Thu Dec 12 21:00:30 2002
@@ -94,6 +94,7 @@ thinking the server is still available.
 connection_struct *conn_new(void)
 {
 	connection_struct *conn;
+	TALLOC_CTX *mem_ctx = NULL;
 	int i;
 
 	i = bitmap_find(bmap, 1);
@@ -103,10 +104,16 @@ connection_struct *conn_new(void)
 		return NULL;
 	}
 
-	conn = (connection_struct *)malloc(sizeof(*conn));
+	if ((mem_ctx = talloc_init_named("connection struct"))==NULL) {
+		DEBUG(0,("talloc_init_named failed for connection struct\n"));
+		return NULL;
+	}
+
+	conn = (connection_struct *)talloc(mem_ctx,sizeof(*conn));
 	if (!conn) return NULL;
 
 	ZERO_STRUCTP(conn);
+	conn->mem_ctx = mem_ctx;
 	conn->cnum = i;
 
 	bitmap_set(bmap, i);
@@ -184,27 +191,8 @@ void conn_clear_vuid_cache(uint16 vuid)
 
 void conn_free(connection_struct *conn)
 {
- 	smb_vfs_handle_struct *handle, *thandle;
- 	void (*done_fptr)(connection_struct *the_conn);
-
-	/* Free vfs_connection_struct */
-	handle = conn->vfs_private;
-	while(handle) {
- 		/* Close dlopen() handle */
- 		done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done");
- 
- 		if (done_fptr == NULL) {
- 			DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle));
- 		} else {
- 			done_fptr(conn);
- 		}
-     		sys_dlclose(handle->handle);
-		DLIST_REMOVE(conn->vfs_private, handle);
-		thandle = handle->next;
-		SAFE_FREE(handle);
-		handle = thandle;
-	}
-
+	TALLOC_CTX *mem_ctx;
+	
 	DLIST_REMOVE(Connections, conn);
 
 	if (conn->ngroups && conn->groups) {
@@ -224,8 +212,9 @@ void conn_free(connection_struct *conn)
 	bitmap_clear(bmap, conn->cnum);
 	num_open--;
 
+	mem_ctx = conn->mem_ctx;
 	ZERO_STRUCTP(conn);
-	SAFE_FREE(conn);
+	talloc_destroy(mem_ctx);
 }
 
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/smbd/process.c HEAD-modules/source/smbd/process.c
--- HEAD/source/smbd/process.c	Thu Dec 12 20:24:27 2002
+++ HEAD-modules/source/smbd/process.c	Mon Dec 16 19:46:13 2002
@@ -1115,10 +1115,11 @@ static BOOL timeout_processing(int deadt
 	  /* send a keepalive for a password server or the like.
 	     This is attached to the auth_info created in the
 	     negprot */
-	  if (negprot_global_auth_context 
-	      && negprot_global_auth_context->challenge_set_method 
-	      && negprot_global_auth_context->challenge_set_method->send_keepalive) {
-		  negprot_global_auth_context->challenge_set_method->send_keepalive
+	  if (negprot_global_auth_context
+	      && negprot_global_auth_context->challenge_set_method
+	      && negprot_global_auth_context->challenge_set_method->ops 
+	      && negprot_global_auth_context->challenge_set_method->ops->send_keepalive) {
+		  negprot_global_auth_context->challenge_set_method->ops->send_keepalive
 			  (&negprot_global_auth_context->challenge_set_method->private_data);
 	  }
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/smbd/server.c HEAD-modules/source/smbd/server.c
--- HEAD/source/smbd/server.c	Tue Nov 26 14:11:04 2002
+++ HEAD-modules/source/smbd/server.c	Tue Dec 10 16:05:06 2002
@@ -374,8 +374,8 @@ static BOOL open_sockets_smbd(BOOL is_da
 				}
 
 				/* Load DSO's */
-				if(lp_modules()) 
-					smb_load_modules(lp_modules());
+				if (lp_modules(GLOBAL_SECTION_SNUM)) 
+					smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPES_SMBD);
 
 				return True; 
 			}
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/smbd/service.c HEAD-modules/source/smbd/service.c
--- HEAD/source/smbd/service.c	Thu Nov 21 07:34:44 2002
+++ HEAD-modules/source/smbd/service.c	Thu Dec 12 14:29:24 2002
@@ -554,7 +554,7 @@ static connection_struct *make_connectio
 		if (!can_write) {
 			if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
 				/* No access, read or write. */
-				DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
+				DEBUG(0,( "make_connection_snum: connection to %s denied due to security descriptor.\n",
 					  lp_servicename(snum)));
 				conn_free(conn);
 				*status = NT_STATUS_ACCESS_DENIED;
@@ -564,16 +564,7 @@ static connection_struct *make_connectio
 			}
 		}
 	}
-	/* Initialise VFS function pointers */
 
-	if (!smbd_vfs_init(conn)) {
-		DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
-		conn_free(conn);
-		*status = NT_STATUS_UNSUCCESSFUL;
-		return NULL;
-	}
-
-/* ROOT Activities: */	
 	/* check number of connections */
 	if (!claim_connection(conn,
 			      lp_servicename(SNUM(conn)),
@@ -583,7 +574,22 @@ static connection_struct *make_connectio
 		conn_free(conn);
 		*status = NT_STATUS_INSUFFICIENT_RESOURCES;
 		return NULL;
-	}  
+	}
+	
+	/* load per share modules */
+	if (lp_modules(SNUM(conn)))
+		smb_load_modules(lp_modules(SNUM(conn)),conn,MODULE_TYPES_PER_SHARE);
+	
+	/* Initialise VFS function pointers */
+
+	if (!smbd_vfs_init(conn)) {
+		DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
+		conn_free(conn);
+		*status = NT_STATUS_UNSUCCESSFUL;
+		return NULL;
+	}
+
+/* ROOT Activities: */	  
 
 	/* Preexecs are done here as they might make the dir we are to ChDir to below */
 	/* execute any "root preexec = " line */
@@ -729,8 +735,8 @@ connection_struct *make_connection_with_
 	 */
 	 
 	if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
-		DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
-			 conn->connectpath,strerror(errno)));
+		DEBUG(0,("make_connection_with_chdir: Can't change directory to %s for [%s] (%s)\n",
+			 conn->connectpath,lp_servicename(SNUM(conn)),strerror(errno)));
 		yield_connection(conn, lp_servicename(SNUM(conn)));
 		conn_free(conn);
 		*status = NT_STATUS_UNSUCCESSFUL;
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/smbd/vfs.c HEAD-modules/source/smbd/vfs.c
--- HEAD/source/smbd/vfs.c	Wed Dec  4 07:18:44 2002
+++ HEAD-modules/source/smbd/vfs.c	Tue Dec 17 16:27:18 2002
@@ -1,9 +1,9 @@
 /*
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    VFS initialisation and support functions
-   Copyright (C) Tim Potter 1999
-   Copyright (C) Alexander Bokovoy 2002
+   Copyright (C) Tim Potter			1999
+   Copyright (C) Alexander Bokovoy		2002
+   Copyright (C) Stefan (metze) Metzmacher	2002
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -35,11 +35,36 @@ struct vfs_syminfo {
 	void *fptr;
 };
 
-/*
-  Opaque (final) vfs operations. This is a combination of first-met opaque vfs operations
-  across all currently processed modules.  */
+static vfs_object_function_entry *smb_vfs_objects = NULL;
 
-static vfs_op_tuple vfs_opaque_ops[SMB_VFS_OP_LAST];
+NTSTATUS smb_register_vfs(vfs_object_function_entry *func, int version)
+{
+	vfs_object_function_entry *fn_entry = NULL;
+	static int global_module_id = 1; /* 0 is for vfs_default_fn_entry */
+
+	/* check if the interface version is ok */
+	if (version != SMB_VFS_INTERFACE_VERSION) {
+		DEBUG(0,("smb_register_vfs: vfs object '%s' have VFS_INTERFACE_VERSION %d, samba has VFS_INTERFACE_VERSION %d\n",
+		func->name,version,SMB_VFS_INTERFACE_VERSION));
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	/* check if a module is allready registered with this name */
+	for (fn_entry=smb_vfs_objects;fn_entry;fn_entry=fn_entry->next) {
+		if (strequal(fn_entry->name,func->name)) {
+			DEBUG(1,("smb_register_vfs: a module with name '%s' is allready registered!\n",func->name));
+			return NT_STATUS_OBJECT_NAME_COLLISION;
+		}
+	}
+
+	func->id = global_module_id++;
+
+	DLIST_ADD(smb_vfs_objects,func);
+
+	DEBUG(7,("smb_register_vfs: module '%s' registered!\n",func->name));
+
+	return NT_STATUS_OK;
+}
 
 /* Default vfs hooks.  WARNING: The order of these initialisers is
    very important.  They must be in the same order as defined in
@@ -127,80 +152,162 @@ static struct vfs_ops default_vfs_ops = 
 	vfswrap_sys_acl_free_qualifier
 };
 
+static vfs_op_tuple default_vfs_op_tuples[] = {
+
+	/* Disk operations */
+	{VFS_OP(vfswrap_dummy_connect),			SMB_VFS_OP_CONNECT,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_dummy_disconnect),		SMB_VFS_OP_DISCONNECT,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_disk_free),			SMB_VFS_OP_DISK_FREE,			SMB_VFS_LAYER_OPAQUE},
+
+	/* Directory operations */
+	{VFS_OP(vfswrap_opendir),			SMB_VFS_OP_OPENDIR,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_readdir),			SMB_VFS_OP_READDIR,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_mkdir),				SMB_VFS_OP_MKDIR,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_rmdir),				SMB_VFS_OP_RMDIR,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_closedir),			SMB_VFS_OP_CLOSEDIR,			SMB_VFS_LAYER_OPAQUE},
+
+	/* File operations */
+	{VFS_OP(vfswrap_open),				SMB_VFS_OP_OPEN,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_close),				SMB_VFS_OP_CLOSE,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_read),				SMB_VFS_OP_READ,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_write),				SMB_VFS_OP_WRITE,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_lseek),				SMB_VFS_OP_LSEEK,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sendfile),			SMB_VFS_OP_SENDFILE,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_rename),			SMB_VFS_OP_RENAME,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_fsync),				SMB_VFS_OP_FSYNC,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_stat),				SMB_VFS_OP_STAT,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_fstat),				SMB_VFS_OP_FSTAT,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_lstat),				SMB_VFS_OP_LSTAT,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_unlink),			SMB_VFS_OP_UNLINK,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_chmod),				SMB_VFS_OP_CHMOD,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_fchmod),			SMB_VFS_OP_FCHMOD,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_chown),				SMB_VFS_OP_CHOWN,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_fchown),			SMB_VFS_OP_FCHOWN,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_chdir),				SMB_VFS_OP_CHDIR,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_getwd),				SMB_VFS_OP_GETWD,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_utime),				SMB_VFS_OP_UTIME,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_ftruncate),			SMB_VFS_OP_FTRUNCATE,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_lock),				SMB_VFS_OP_LOCK,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_symlink),			SMB_VFS_OP_SYMLINK,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_readlink),			SMB_VFS_OP_READLINK,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_link),				SMB_VFS_OP_LINK,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_mknod),				SMB_VFS_OP_MKNOD,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_realpath),			SMB_VFS_OP_REALPATH,			SMB_VFS_LAYER_OPAQUE},
+
+	{VFS_OP(vfswrap_fget_nt_acl),			SMB_VFS_OP_FGET_NT_ACL,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_get_nt_acl),			SMB_VFS_OP_GET_NT_ACL,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_fset_nt_acl),			SMB_VFS_OP_FSET_NT_ACL,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_set_nt_acl),			SMB_VFS_OP_SET_NT_ACL,			SMB_VFS_LAYER_OPAQUE},
+
+	/* POSIX ACL operations. */
+#if defined(HAVE_NO_ACLS)
+	{VFS_OP(NULL),					SMB_VFS_OP_CHMOD_ACL,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(NULL),					SMB_VFS_OP_FCHMOD_ACL,			SMB_VFS_LAYER_OPAQUE},
+#else
+	{VFS_OP(vfswrap_chmod_acl),			SMB_VFS_OP_CHMOD_ACL,			SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_fchmod_acl),			SMB_VFS_OP_FCHMOD_ACL,			SMB_VFS_LAYER_OPAQUE},
+#endif
+	{VFS_OP(vfswrap_sys_acl_get_entry),		SMB_VFS_OP_SYS_ACL_GET_ENTRY,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_get_tag_type),		SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,	SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_get_permset),		SMB_VFS_OP_SYS_ACL_GET_PERMSET,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_get_qualifier),		SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,	SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_get_file),		SMB_VFS_OP_SYS_ACL_GET_FILE,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_get_fd),		SMB_VFS_OP_SYS_ACL_GET_FD,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_clear_perms),		SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_add_perm),		SMB_VFS_OP_SYS_ACL_ADD_PERM,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_to_text),		SMB_VFS_OP_SYS_ACL_TO_TEXT,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_init),			SMB_VFS_OP_SYS_ACL_INIT,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_create_entry),		SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,	SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_set_tag_type),		SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,	SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_set_qualifier),		SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,	SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_set_permset),		SMB_VFS_OP_SYS_ACL_SET_PERMSET,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_valid),			SMB_VFS_OP_SYS_ACL_VALID,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_set_file),		SMB_VFS_OP_SYS_ACL_SET_FILE,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_set_fd),		SMB_VFS_OP_SYS_ACL_SET_FD,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_delete_def_file),	SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,	SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_get_perm),		SMB_VFS_OP_SYS_ACL_GET_PERM,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_free_text),		SMB_VFS_OP_SYS_ACL_FREE_TEXT,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_free_acl),		SMB_VFS_OP_SYS_ACL_FREE_ACL,		SMB_VFS_LAYER_OPAQUE},
+	{VFS_OP(vfswrap_sys_acl_free_qualifier),	SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,	SMB_VFS_LAYER_OPAQUE},
+
+	{NULL,						SMB_VFS_OP_NOOP,		SMB_VFS_LAYER_NOOP}
+};
+
+static vfs_object_function_entry default_vfs_fn_entry = {
+	"default",		/* name */
+	default_vfs_op_tuples,	/* op_tuple */
+	0			/* id */
+};
 /****************************************************************************
   initialise default vfs hooks
 ****************************************************************************/
 
-static void vfs_init_default(connection_struct *conn)
+static BOOL vfs_init_default(connection_struct *conn)
 {
-	DEBUG(3, ("Initialising default vfs hooks\n"));
+	vfs_object_function_entry *fn_entry;
+	DEBUG(5, ("Initialising default vfs hooks\n"));
 
 	memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops));
-	conn->vfs_private = NULL;
+	
+	fn_entry = (vfs_object_function_entry *)talloc(conn->mem_ctx,sizeof(vfs_object_function_entry));
+	if (fn_entry == NULL) {
+		DEBUG(0,("vfs_init_default: talloc failed\n"));
+		return False;
+	}
+
+	ZERO_STRUCTP(fn_entry);
+
+	fn_entry->name		= default_vfs_fn_entry.name;
+	fn_entry->op_tuples  	= default_vfs_fn_entry.op_tuples;
+	fn_entry->id		= default_vfs_fn_entry.id;
+
+	DLIST_ADD(conn->vfs_objects,fn_entry);
+
+	return True;
 }
 
 /****************************************************************************
   initialise custom vfs hooks
 ****************************************************************************/
 
-BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
+BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object_name)
 {
-	int vfs_version = -1;
- 	vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *);
  	int i;
+ 	vfs_object_function_entry *vfs_object = NULL;
+ 	vfs_object_function_entry *fn_entry,*tmp_vfs_object;
 
-	DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object));
+	DEBUG(3, ("Initialising custom vfs hooks from '%s'\n", vfs_object_name));
 
-	/* Open object file */
+	for(tmp_vfs_object = smb_vfs_objects ; tmp_vfs_object; tmp_vfs_object=tmp_vfs_object->next) {
+		if (strequal(vfs_object_name,tmp_vfs_object->name)) {
+			vfs_object = tmp_vfs_object;
+			break;
+		}
+	}
 
-	if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) {
-		DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror()));
+	if (vfs_object == NULL) {
+		DEBUG(0,("vfs_init_custom: don't find a custom vfs module '%s'!\n",vfs_object_name));
 		return False;
 	}
 
-	/* Get handle on vfs_init() symbol */
 
-	init_fptr = (vfs_op_tuple *(*)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *))sys_dlsym(conn->vfs_private->handle, "vfs_init");
+ 	for(i=0; vfs_object->op_tuples[i].op != NULL; i++) {
+		/* Change current VFS disposition*/
+		DEBUG(20, ("Accepting operation type %d from module %s\n", vfs_object->op_tuples[i].type, vfs_object_name));
+		((void**)&conn->vfs_ops)[vfs_object->op_tuples[i].type] = vfs_object->op_tuples[i].op;
+	}
 
-	if (init_fptr == NULL) {
-		DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object));
+	fn_entry = (vfs_object_function_entry *)talloc_zero(conn->mem_ctx,sizeof(vfs_object_function_entry));
+	if (fn_entry == NULL) {
+		DEBUG(0,("vfs_init_default: talloc_zero() failed\n"));
 		return False;
 	}
+	
+	fn_entry->name		= vfs_object->name;
+	fn_entry->op_tuples	= vfs_object->op_tuples;
+	fn_entry->id		= vfs_object->id;
 
-	/* Initialise vfs_ops structure */
-
- 	if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) {
- 		DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object));
- 		return False;
- 	}
-  
- 	if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) {
- 		DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n",
- 			vfs_version, SMB_VFS_INTERFACE_VERSION ));
-  		return False;
-  	}
-  
- 	if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) {
- 		DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\
-Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n",
- 			vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version ));
-  		return False;
-  	}
-  
- 	for(i=0; ops[i].op != NULL; i++) {
- 	  DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
- 	  if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
- 	    /* Check whether this operation was already made opaque by different module */
- 	    if(vfs_opaque_ops[ops[i].type].op == ((void**)&default_vfs_ops)[ops[i].type]) {
- 	      /* No, it isn't overloaded yet. Overload. */
- 	      DEBUG(3, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
- 	      vfs_opaque_ops[ops[i].type] = ops[i];
- 	    }
- 	  }
- 	  /* Change current VFS disposition*/
- 	  DEBUG(3, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object));
- 	  ((void**)&conn->vfs_ops)[ops[i].type] = ops[i].op;
-	}
+	DLIST_ADD(conn->vfs_objects,fn_entry);
 
 	return True;
 }
@@ -211,71 +318,302 @@ Proceeding in compatibility mode, new op
 
 BOOL smbd_vfs_init(connection_struct *conn)
 {
-	char **vfs_objects, *vfsobj, *vfs_module, *vfs_path;
-	int nobj, i;
-	struct smb_vfs_handle_struct *handle;
-	
+	const char **vfs_objects;
+	int i;
+
 	/* Normal share - initialise with disk access functions */
-	vfs_init_default(conn);
+	if (!vfs_init_default(conn)) {
+		return False;
+	};
 
-	/* Override VFS functions if 'vfs object' was specified*/
-	if (*lp_vfsobj(SNUM(conn))) {
-		vfsobj = NULL;
-		for(i=0; i<SMB_VFS_OP_LAST; i++) {
-		  vfs_opaque_ops[i].op = ((void**)&default_vfs_ops)[i];
-		  vfs_opaque_ops[i].type = i;
-		  vfs_opaque_ops[i].layer = SMB_VFS_LAYER_OPAQUE;
-		}
-		if (string_set(&vfsobj, lp_vfsobj(SNUM(conn)))) {
-			/* Parse passed modules specification to array of modules */
-			set_first_token(vfsobj);
-			/* We are using default separators: ' \t\r\n' */
-			vfs_objects = toktocliplist(&nobj, NULL);
-			if (vfs_objects) {
-				vfs_path = lp_vfs_path(SNUM(conn));
-				conn->vfs_private = NULL;
-				for(i=nobj-1; i>=0; i--) {
-					handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct));
-					/* Loadable object file */
-					handle->handle = NULL;
-					DLIST_ADD(conn->vfs_private, handle)
-					vfs_module = NULL;
-					if (vfs_path) {
-						asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[i]);
-					} else {
-						asprintf(&vfs_module, "%s", vfs_objects[i]);
-					}
-					if (!vfs_init_custom(conn, vfs_module)) {
-						DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module));
-						string_free(&vfsobj);
-						SAFE_FREE(vfs_module);
-						return False;
-					}
-					SAFE_FREE(vfs_module);
-				}
+	/* Override VFS functions if 'vfs objects' was specified*/
+	if (((vfs_objects=lp_vfsobj(SNUM(conn)))!=NULL)&&
+		(*vfs_objects!=NULL)) {
+		for (i=(-1);vfs_objects[i+1]!=NULL;i++) {
+			/* count the objects */
+		}
+		for ( ; i>=0; i--) {
+			if (!vfs_init_custom(conn, vfs_objects[i])) {
+				DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for '%s'\n", vfs_objects[i]));
+				return False;
 			}
-			string_free(&vfsobj);
-			return True;
 		}
 	}
+
 	return True;
 }
 
-/*******************************************************************
- Create vfs_ops reflecting current vfs_opaque_ops
-*******************************************************************/
+struct vfs_ops *vfs_get_ops(struct connection_struct *conn)
+{
+	return &conn->vfs_ops;
+}
 
-struct vfs_ops *smb_vfs_get_opaque_ops(void)
+void *vfs_get_op(struct connection_struct *conn, int type)
 {
-  int i;
-  struct vfs_ops *ops;
+	if (type <= SMB_VFS_OP_NOOP || type > SMB_VFS_OP_LAST) {
+		DEBUG(0,("vfs_get_op: wrong oparartion type #%d\n",type));
+		return VFS_OP(NULL);
+	}
 
-  ops = smb_xmalloc(sizeof(struct vfs_ops));
+	if (((void**)&conn->vfs_ops)[type]==NULL) {
+		DEBUG(0,("vfs_get_op: Warning: oparation #%d is not available\n",type));
+	}
 
-  for(i=0; i<SMB_VFS_OP_LAST; i++) {
-    ((void**)ops)[i] = vfs_opaque_ops[i].op;
-  }
-  return ops;
+	return ((void**)&conn->vfs_ops)[type];
+}
+
+struct _vfs_object_function_entry *vfs_object_find_in_conn(struct connection_struct *conn,int module_id)
+{
+ 	vfs_object_function_entry *vfs_object = NULL;
+ 	vfs_object_function_entry *tmp_vfs_object;
+ 
+	for(tmp_vfs_object = conn->vfs_objects ; tmp_vfs_object; tmp_vfs_object=tmp_vfs_object->next) {
+		if (module_id == tmp_vfs_object->id) {
+			vfs_object = tmp_vfs_object;
+			break;
+		}
+	}
+
+	if (vfs_object == NULL) {
+		DEBUG(0,("vfs_object_find_in_conn: didn't find module %d\n",module_id));
+	}
+
+	return vfs_object;
+}
+
+struct vfs_ops *vfs_get_default_ops(struct connection_struct *conn, int module_id)
+{
+ 	struct vfs_ops *tmp_ops = NULL;
+ 	int i,type;
+ 	vfs_object_function_entry *vfs_object = NULL;
+ 	vfs_object_function_entry *tmp_vfs_object;
+
+	if (module_id<0) {
+		DEBUG(0,("vfs_get_default_ops: invalid module_id %d",module_id));
+		return NULL;
+	}
+
+	if (conn->vfs_objects == NULL) {
+		DEBUG(0,("vfs_get_default_ops: no oparations specified for connection %d\n",SNUM(conn)));
+		return NULL;
+	}
+
+	if ((vfs_object=vfs_object_find_in_conn(conn,module_id))==NULL) {
+		DEBUG(0,("vfs_get_default_ops: Can't find default_ops for module (id = %d)\n",module_id));
+		return NULL;
+	}
+
+	if (vfs_object->default_ops !=NULL) {
+		return vfs_object->default_ops;
+	}
+
+	if ((tmp_ops = (struct vfs_ops *)talloc(conn->mem_ctx,sizeof(struct vfs_ops)))==NULL) {
+		DEBUG(0,("vfs_get_default_ops: talloc() failed\n"));
+		return NULL;
+	}
+
+	for(type=0; type<SMB_VFS_OP_LAST; type++) {
+		((void**)tmp_ops)[type] = NULL;
+		
+		for(tmp_vfs_object = vfs_object->next ; tmp_vfs_object; tmp_vfs_object=tmp_vfs_object->next) {
+			for(i=0; tmp_vfs_object->op_tuples[i].op != NULL; i++) {
+				if (tmp_vfs_object->op_tuples[i].type == type 
+					&& tmp_vfs_object->op_tuples[i].op != NULL) {
+					DEBUG(20, ("vfs_get_default_ops: '%s' using op type #%d from module '%s'\n",
+						vfs_object->name, type, tmp_vfs_object->name));
+					((void**)tmp_ops)[type] = tmp_vfs_object->op_tuples[i].op;
+					goto out;
+				}
+			}
+		}
+out:
+		
+		if (((void**)tmp_ops)[type] == NULL) {
+			DEBUG(1,("vfs_get_default_ops: Warning: no default op #%d found\n",type));
+		}
+	}
+
+	vfs_object->default_ops = tmp_ops;
+
+	return tmp_ops;
+}
+
+void *vfs_get_default_op(struct connection_struct *conn, int module_id, int type)
+{
+	struct vfs_ops *tmp_ops = NULL;
+ 	
+	if (module_id<0) {
+		DEBUG(0,("vfs_get_default_op: invalid module_id %d",module_id));
+		return VFS_OP(NULL);
+	}
+
+	if (type <= SMB_VFS_OP_NOOP || type > SMB_VFS_OP_LAST) {
+		DEBUG(0,("vfs_get_default_op: wrong oparartion type #%d\n",type));
+		return VFS_OP(NULL);
+	}
+
+	if (conn->vfs_objects == NULL) {
+		DEBUG(0,("vfs_get_default_op: no oparations specified for connection %d\n",SNUM(conn)));
+		return VFS_OP(NULL);
+	}
+
+	if ((tmp_ops = vfs_get_default_ops(conn,module_id)) == NULL) {
+		DEBUG(0,("vfs_get_default_op: type: #%d vfs_get_default_ops() failed\n",type));
+		return NULL;
+	}
+
+	return ((void**)&tmp_ops)[type];
+}
+
+int vfs_object_id_by_name(const char *module_name)
+{
+	int module_id = (-1);
+ 	vfs_object_function_entry *tmp_vfs_object;
+ 
+ 	if (!module_name) {
+ 		DEBUG(0,("vfs_object_id_by_name: no name given\n"));
+ 		return module_id;
+ 	}
+
+	for(tmp_vfs_object = smb_vfs_objects ; tmp_vfs_object; tmp_vfs_object=tmp_vfs_object->next) {
+		if (strequal(module_name,tmp_vfs_object->name)) {
+			module_id = tmp_vfs_object->id;
+			break;
+		}
+	}
+	
+	if (module_id == (-1)) {
+		DEBUG(0,("vfs_object_id_by_name: object '%s' not found\n",module_name));
+	}
+
+	return module_id;
+}
+
+const char *vfs_object_name_by_id(int module_id)
+{
+	char *module_name = NULL;
+ 	vfs_object_function_entry *tmp_vfs_object;
+ 
+ 	if (module_id<0) {
+		DEBUG(0,("vfs_get_default_ops: invalid module_id %d",module_id));
+ 		return module_name;
+ 	}
+
+	for(tmp_vfs_object = smb_vfs_objects ; tmp_vfs_object; tmp_vfs_object=tmp_vfs_object->next) {
+		if (module_id == tmp_vfs_object->id) {
+			module_name = tmp_vfs_object->name;
+			break;
+		}
+	}
+	
+	if (module_name == NULL) {
+		DEBUG(0,("vfs_object_name_by_id: object '%d' not found\n",module_id));
+	}
+
+	return module_name;
+}
+
+struct vfs_ops *vfs_get_default_ops_by_name(struct connection_struct *conn, const char *module_name)
+{
+ 	if (!module_name) {
+		DEBUG(0,("vfs_get_default_ops_by_name: no module_name given\n"));
+		return NULL;
+	}
+
+	if (conn->vfs_objects == NULL) {
+		DEBUG(0,("vfs_get_default_ops_by_name: no oparations specified for connection %d\n",SNUM(conn)));
+		return NULL;
+	}
+
+	return vfs_get_default_ops(conn,vfs_object_id_by_name(module_name));
+}
+
+void *vfs_get_default_op_by_name(struct connection_struct *conn, const char *module_name, int type)
+{
+	if (!module_name) {
+		DEBUG(0,("vfs_get_default_ops_by_name: no module_name given\n"));
+		return VFS_OP(NULL);
+	}
+
+	if (type <= SMB_VFS_OP_NOOP || type > SMB_VFS_OP_LAST) {
+		DEBUG(0,("vfs_get_default_op: wrong oparartion type #%d\n",type));
+		return VFS_OP(NULL);
+	}
+
+	if (conn->vfs_objects == NULL) {
+		DEBUG(0,("vfs_get_default_ops_by_name: no oparations specified for connection %d\n",SNUM(conn)));
+		return VFS_OP(NULL);
+	}
+
+	return vfs_get_default_op(conn,vfs_object_id_by_name(module_name),type);
+}
+
+struct vfs_ops *vfs_get_opaque_ops(struct connection_struct *conn)
+{
+ 	struct vfs_ops *tmp_ops = NULL;
+ 	int i,type;
+ 	vfs_object_function_entry *tmp_vfs_object;
+
+	if (conn->vfs_objects == NULL) {
+		DEBUG(0,("vfs_get_opaque_ops: no oparations specified for connection %d\n",SNUM(conn)));
+		return NULL;
+	}
+
+	if (conn->vfs_opaque_ops !=NULL) {
+		return conn->vfs_opaque_ops;
+	}
+
+	if ((tmp_ops = (struct vfs_ops *)talloc(conn->mem_ctx,sizeof(struct vfs_ops)))==NULL) {
+		DEBUG(0,("vfs_get_opaque_ops: tmalloc() failed\n"));
+		return NULL;
+	}
+
+	for(type=0; type<SMB_VFS_OP_LAST; type++) {
+		((void**)tmp_ops)[type] = NULL;
+		
+		for(tmp_vfs_object = conn->vfs_objects ; tmp_vfs_object; tmp_vfs_object=tmp_vfs_object->next) {
+			for(i=0; tmp_vfs_object->op_tuples[i].op != NULL; i++) {
+				if (tmp_vfs_object->op_tuples[i].type == type 
+					&& tmp_vfs_object->op_tuples[i].layer == SMB_VFS_LAYER_OPAQUE) {
+					DEBUG(20, ("vfs_get_opaque_ops: Accepting operation type #%d \n",
+						tmp_vfs_object->op_tuples[i].type));
+					((void**)tmp_ops)[type] = tmp_vfs_object->op_tuples[i].op;
+					goto out;
+				}
+			}
+		}
+		
+out:
+		if (((void**)tmp_ops)[type] == NULL) {
+			DEBUG(1,("vfs_get_opaque_ops: Warning: no default op #%d found\n",type));
+		}
+	}
+
+	conn->vfs_opaque_ops = tmp_ops;
+
+	return tmp_ops;
+}
+
+void *vfs_get_opaque_op(struct connection_struct *conn, int type)
+{
+	struct vfs_ops *tmp_ops = NULL;
+ 	
+	if (type <= SMB_VFS_OP_NOOP || type > SMB_VFS_OP_LAST) {
+		DEBUG(0,("vfs_get_opaque_op: wrong oparartion type #%d\n",type));
+		return VFS_OP(NULL);
+	}
+
+	if (conn->vfs_objects == NULL) {
+		DEBUG(0,("vfs_get_opaque_op: no oparations specified for connection %d\n",SNUM(conn)));
+		return NULL;
+	}
+
+	if ((tmp_ops = vfs_get_opaque_ops(conn)) == NULL) {
+		DEBUG(0,("vfs_get_opaque_op: type: #%d vfs_get_opaque_ops() failed\n",type));
+		return NULL;
+	}
+
+	return ((void**)tmp_ops)[type];
 }
 
 /*******************************************************************
@@ -472,7 +810,7 @@ int vfs_allocate_file_space(files_struct
 
 	len -= st.st_size;
 	len /= 1024; /* Len is now number of 1k blocks needed. */
-	space_avail = conn->vfs_ops.disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize);
+	space_avail = vfs_ops->disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize);
 
 	DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n",
 			fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail ));
@@ -560,72 +898,6 @@ char *vfs_readdirname(connection_struct 
 	return(dname);
 }
 
-/* VFS options not quite working yet */
-
-#if 0
-
-/***************************************************************************
-  handle the interpretation of the vfs option parameter
- *************************************************************************/
-static BOOL handle_vfs_option(char *pszParmValue, char **ptr)
-{
-    struct vfs_options *new_option, **options = (struct vfs_options **)ptr;
-    int i;
-
-    /* Create new vfs option */
-
-    new_option = (struct vfs_options *)malloc(sizeof(*new_option));
-    if (new_option == NULL) {
-	return False;
-    }
-
-    ZERO_STRUCTP(new_option);
-
-    /* Get name and value */
-
-    new_option->name = strtok(pszParmValue, "=");
-
-    if (new_option->name == NULL) {
-	return False;
-    }
-
-    while(isspace(*new_option->name)) {
-	new_option->name++;
-    }
-
-    for (i = strlen(new_option->name); i > 0; i--) {
-	if (!isspace(new_option->name[i - 1])) break;
-    }
-
-    new_option->name[i] = '\0';
-    new_option->name = strdup(new_option->name);
-
-    new_option->value = strtok(NULL, "=");
-
-    if (new_option->value != NULL) {
-
-	while(isspace(*new_option->value)) {
-	    new_option->value++;
-	}
-	
-	for (i = strlen(new_option->value); i > 0; i--) {
-	    if (!isspace(new_option->value[i - 1])) break;
-	}
-	
-	new_option->value[i] = '\0';
-	new_option->value = strdup(new_option->value);
-    }
-
-    /* Add to list */
-
-    DLIST_ADD(*options, new_option);
-
-    return True;
-}
-
-#endif
-
-
 /*******************************************************************
  A wrapper for vfs_chdir().
 ********************************************************************/
@@ -641,7 +913,7 @@ int vfs_ChDir(connection_struct *conn, c
 	if (*path == '/' && strcsequal(LastDir,path))
 		return(0);
 
-	DEBUG(3,("vfs_ChDir to %s\n",path));
+	DEBUG(4,("vfs_ChDir to %s\n",path));
 
 	res = vfs_chdir(conn,path);
 	if (!res)
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/torture/cmd_vfs.c HEAD-modules/source/torture/cmd_vfs.c
--- HEAD/source/torture/cmd_vfs.c	Sat Nov 23 17:52:50 2002
+++ HEAD-modules/source/torture/cmd_vfs.c	Wed Dec 11 16:14:15 2002
@@ -2,8 +2,9 @@
    Unix SMB/CIFS implementation.
    VFS module functions
 
-   Copyright (C) Simo Sorce 2002
-   Copyright (C) Eric Lorimer 2002
+   Copyright (C) Simo Sorce			2002
+   Copyright (C) Eric Lorimer			2002
+   Copyright (C) Stefan (metze) Metzmacher	2002
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -27,32 +28,40 @@ static char *null_string = "";
 
 static NTSTATUS cmd_load_module(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
 {
-	struct smb_vfs_handle_struct *handle;
-	char *path = lp_vfs_path(0);
-	char name[PATH_MAX];
-	
-	if (argc != 2) {
-		printf("Usage: load <module path>\n");
+	if (argc < 2) {
+		printf("Usage: load <module path> {[<module path>]}\n");
 		return NT_STATUS_OK;
 	}
 
-	if (path != NULL && *path != '\0') {
-		snprintf(name, PATH_MAX, "%s/%s", path, argv[1]);
-	} else {
-		snprintf(name, PATH_MAX, "%s", argv[1]);
-	}
-	vfs->conn->vfs_private = NULL;
-	handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct));
-	handle->handle = NULL;
-	DLIST_ADD(vfs->conn->vfs_private, handle)
-	if (!vfs_init_custom(vfs->conn, name)) {
-		DEBUG(0, ("load: error=-1 (vfs_init_custom failed for %s)\n", argv[1]));
+	if (!smb_load_modules((const char **)&argv[1],vfs->conn, MODULE_TYPES_PER_SHARE)) {
+		DEBUG(0, ("load: error=-1 (smb_load_modules) failed for %s ...)\n", argv[1]));
 		return NT_STATUS_UNSUCCESSFUL;
 	}
 	printf("load: ok\n");
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS cmd_load_objects(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
+{
+	int i;
+
+	if (argc < 2) {
+		printf("Usage: objects <vfs object name> {[<vfs object name>]}\n");
+		return NT_STATUS_OK;
+	}
+
+	for (i = argc -1; i>0;i--) {
+				
+		if (!vfs_init_custom(vfs->conn,argv[i])) {
+			DEBUG(0,("objects: vfs_init_custom failed for '%s' with parameter '%s'\n",argv[i]));
+			return NT_STATUS_UNSUCCESSFUL;
+		}
+	}
+
+	printf("objects: ok\n");
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
 {
 	char c;
@@ -1011,7 +1020,8 @@ struct cmd_set vfs_commands[] = {
 
 	{ "VFS Commands" },
 
-	{ "load", cmd_load_module, "Load a module", "load <module.so>" },
+	{ "load", cmd_load_module, "Load modulea", "load <module.so> {[</path/to/module2.so>]}" },
+	{ "objects", cmd_load_objects, "Specify vfs objects", "objects <module>[:<parameter>] {[<module2>[:<parameter2>]]}" },
 	{ "populate", cmd_populate, "Populate a data buffer", "populate <char> <size>" },
 	{ "showdata", cmd_show_data, "Show data currently in data buffer", "show_data [<offset> <len>]"},
 	{ "connect",   cmd_connect,   "VFS connect()",    "connect" },
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/torture/vfstest.c HEAD-modules/source/torture/vfstest.c
--- HEAD/source/torture/vfstest.c	Thu Sep  5 11:40:32 2002
+++ HEAD-modules/source/torture/vfstest.c	Tue Dec 10 16:13:19 2002
@@ -527,6 +527,9 @@ int main(int argc, char *argv[])
 
 	/* TODO: check output */
 	reload_services(False);
+	
+	if (lp_modules(GLOBAL_SECTION_SNUM))
+		smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPES_VFSTEST);
 
 	/* the following functions are part of the Samba debugging
 	   facilities.  See lib/debug.c */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/utils/net.c HEAD-modules/source/utils/net.c
--- HEAD/source/utils/net.c	Wed Nov 13 19:52:41 2002
+++ HEAD-modules/source/utils/net.c	Tue Dec 10 16:15:12 2002
@@ -608,7 +608,10 @@ static struct functable net_func[] = {
 	if (!opt_target_workgroup) {
 		opt_target_workgroup = strdup(lp_workgroup());
 	}
-	
+
+	if (lp_modules(GLOBAL_SECTION_SNUM))
+		smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL, MODULE_TYPES_NET);
+
 	if (!init_names())
 		exit(1);
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/utils/pdbedit.c HEAD-modules/source/utils/pdbedit.c
--- HEAD/source/utils/pdbedit.c	Wed Nov 13 19:52:42 2002
+++ HEAD-modules/source/utils/pdbedit.c	Tue Dec 10 16:15:39 2002
@@ -503,8 +503,8 @@ int main (int argc, char **argv)
 		exit(1);
 	}
 
-	if(lp_modules())
-		smb_load_modules(lp_modules());
+	if (lp_modules(GLOBAL_SECTION_SNUM))
+		smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPES_PDBEDIT);
 	
 	if (!init_names())
 		exit(1);
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/utils/smbgroupedit.c HEAD-modules/source/utils/smbgroupedit.c
--- HEAD/source/utils/smbgroupedit.c	Wed Nov 13 19:52:42 2002
+++ HEAD-modules/source/utils/smbgroupedit.c	Tue Dec 10 16:16:18 2002
@@ -279,6 +279,9 @@ int main (int argc, char **argv)
 		exit(1);
 	}
 
+	if (lp_modules(GLOBAL_SECTION_SNUM))
+		smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPES_SMBGROUPEDIT);
+
 	if (!init_names())
 		exit(1);
 	
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/utils/smbpasswd.c HEAD-modules/source/utils/smbpasswd.c
--- HEAD/source/utils/smbpasswd.c	Fri Dec 13 07:25:46 2002
+++ HEAD-modules/source/utils/smbpasswd.c	Fri Dec 13 07:29:48 2002
@@ -582,6 +582,9 @@ int main(int argc, char **argv)
 
 	setup_logging("smbpasswd", True);
 	
+	if (lp_modules(GLOBAL_SECTION_SNUM))
+		smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL,MODULE_TYPES_SMBPASSWD);
+	
 	/*
 	 * Set the machine NETBIOS name if not already
 	 * set from the config file. 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure HEAD/source/wrepld/server.c HEAD-modules/source/wrepld/server.c
--- HEAD/source/wrepld/server.c	Wed Nov 13 19:52:43 2002
+++ HEAD-modules/source/wrepld/server.c	Tue Dec 10 16:21:11 2002
@@ -661,6 +661,9 @@ static void process(void)
 	if (!reload_services(False))
 		return(-1);	
 
+	if (lp_modules(GLOBAL_SECTION_SNUM))
+		smb_load_modules(lp_modules(GLOBAL_SECTION_SNUM),NULL, MODULE_TYPES_WREPLD);
+
 	if (!init_names())
 		return -1;
 	


More information about the samba-technical mailing list