[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: loadable module support



Kurt D. Zeilenga wrote:

> At 12:24 PM 4/12/99 -0700, Kurt D. Zeilenga wrote:
> >I can help here...  I assume -rdynamic is GNU Linker (gld) specific.

Yes, it is.

>
> Looks like glib-config lets us know how to use glib/gmodule...
>  GMODULE_CFLAGS="`glib-config --cflags gmodule`"
>  GMODULE_LIBS="`glib-config --libs gmodule`"

Yes, very convinient! Formally to be correct they would be '... --cflags
glib gmodule' and '... --libs glib gmodule'. Since gmodule depends on
glib it makes no difference currently, but that may change (?)
glib-config also set flags like -rdynamic (for GNU ld). However it does
not set the (gcc)flag-fPIC for compilation of the code in the modules,
so this still has to be set.

>
> I could easily add an option:
>         --{enable,disable}-dynamic
>
> Check for glib-config, sort out cflags/libs and -DHAVE_GMODULE=1.
>
>         Kurt

Please do :-)

I've included a basic patch against openldap release 1.2.1. For now it
is  just a proof of concept, that happens to work on my RH5.2 Linux box.
Let met give a brief explanation of the code.
In servers/slapd/config.c an option 'loadmodule' is added. When found it
simply calls load_module(cargs[1]). This function currently resides in
backend.c (where it actually does not belong, because it isn't
particularly backend related). It simply calls gmodule function
g_module_open() to load the module and returns.
Now it is up to the loaded module to register itself. This happens in
g_module_check_init(), a function that is automatically called upon the
loading of the module. Here a call is made to register_backend_module()
with the module name and a pointer to a backend initialization function
as arguments. If necessary all other kinds of initialization or
registration could be performed here as well. For example the module
could also register some authentication method it provides.
The register_backend_module() function (in backend.c) simply adds an
entry containg the module name and the function pointer to a hashtable
containing all dynamically loaded backend modules. In the new_backend
routine a call is made to set_backend2module() which tries to look up
the required backend. If this fails new_backend resorts to the if/then
stuff. Remark: IMHO the initialization inside the if/then stuff should
really belong in the specific backends. For loadable modules this even
is a must. Therefore a propose to put this in a separate function called
<backend>_set_back_functions(Backend* be) that sets the function
pointers in the Backend struct.
That all!
Oh, I almost forgot: you will want to build the modules as well :-).
First make sure the module code is compiled with the appropiate flags
(-fPIC for gcc). Then (for the password backend for example):
$ cd  servers/slapd/back-passwd
$ gcc -shared -o backpasswd.so *.o

The makefiles aren't yet changed to do this automatically. Also
somewhere (in portable.h?) SLAPD_LOADABLE_MODULES has to be defined or
else the patch isn't activated at all.
Please let me know if you have any questions, remarks or suggestions!

Regards,

Bastiaan




Index: openldap/ldap/servers/slapd/backend.c
diff -c openldap/ldap/servers/slapd/backend.c:1.1.1.1 openldap/ldap/servers/slapd/backend.c:1.2
*** openldap/ldap/servers/slapd/backend.c:1.1.1.1	Thu Apr  8 21:28:12 1999
--- openldap/ldap/servers/slapd/backend.c	Tue Apr 13 14:22:13 1999
***************
*** 12,24 ****
--- 12,88 ----
  
  #include "slap.h"
  
+ #ifdef SLAPD_LOADABLE_MODULES
+ #include <glib.h>
+ #include <gmodule.h>
+ #endif /* SLAPD_LOADABLE_MODULES */
  
+ 
  #define BACKEND_GRAB_SIZE	10
  
  int		nbackends;
  Backend		*backends;
  static int	maxbackends;
  
+ #ifdef SLAPD_LOADABLE_MODULES
+ GHashTable* backend_modules = NULL;
+ 
+ int 
+ load_module(
+ 	    const char* file_name
+ ) 
+ {
+    GModule* module = NULL;
+ 
+    if (!g_module_supported()) {
+       Debug(LDAP_DEBUG_ANY, "loadable modules not supported on this plaform\n", 0, 0, 0);
+       return FALSE;
+    }
+ 
+    if ((module = g_module_open(file_name, G_MODULE_BIND_LAZY)) == NULL) {
+       Debug(LDAP_DEBUG_ANY, "failed to load module %s: %s\n", file_name, g_module_error(), 0);
+       return FALSE;
+    }
+ 
+    Debug(LDAP_DEBUG_CONFIG, "loaded module %s\n", file_name, 0, 0);
+    
+    return TRUE;
+ }
+ 
+ gint string_compare_for_hashtable(gconstpointer a, gconstpointer b) {
+    return (strcmp((const char*)a, (const char*)b) == 0) ? TRUE : FALSE;
+ }
+ 
+ void register_backend_module(const char* name, void (*init_function)(Backend * be)) {
+    if (backend_modules == NULL) {
+       backend_modules = g_hash_table_new(g_str_hash, string_compare_for_hashtable);
+       if (backend_modules == NULL) {
+ 	 Debug(LDAP_DEBUG_ANY, "failed to alloc backend hashtable\n", 0, 0, 0);
+ 	 return;
+ 	 /* or exit right away? */
+       }
+    }
+ 
+    g_hash_table_insert(backend_modules, name, init_function);
+    Debug(LDAP_DEBUG_CONFIG, "registered backend module %s\n", name, 0, 0);
+ }
+ 
+ gboolean set_backend2module(Backend* be, const char* type) {
+    void (*init_function)(Backend *be);
+ 
+    if (backend_modules == NULL)
+       return FALSE;
+ 
+    if ((init_function = g_hash_table_lookup(backend_modules, type)) != NULL) {
+       init_function(be);
+       return TRUE;
+    } else {
+       return FALSE;
+    }
+ }
+ 
+ #endif /* SLAPD_LOADABLE_MODULES */
+ 
  Backend *
  new_backend(
      char	*type
***************
*** 40,45 ****
--- 104,115 ----
  	be->be_timelimit = deftime;
  	foundit = 0;
  
+ #ifdef SLAPD_LOADABLE_MODULES
+ 	if (set_backend2module(be, type)) {
+ 	   foundit = 1;
+ 	} else {
+ #endif /* SLAPD_LOADABLE_MODULES */
+ 
  #ifdef SLAPD_LDBM
  	if ( strcasecmp( type, "ldbm" ) == 0 ) {
  		be->be_bind = ldbm_back_bind;
***************
*** 105,110 ****
--- 175,184 ----
  		foundit = 1;
  	}
  #endif
+ 
+ #ifdef SLAPD_LOADABLE_MODULES
+         }
+ #endif /* SLAPD_LOADABLE_MODULES */
  
  	if ( be->be_init != NULL ) {
  		(*be->be_init)( be );
Index: openldap/ldap/servers/slapd/config.c
diff -c openldap/ldap/servers/slapd/config.c:1.1.1.1 openldap/ldap/servers/slapd/config.c:1.2
*** openldap/ldap/servers/slapd/config.c:1.1.1.1	Thu Apr  8 21:28:12 1999
--- openldap/ldap/servers/slapd/config.c	Tue Apr 13 14:22:13 1999
***************
*** 454,459 ****
--- 454,476 ----
  			}
  			ldap_srvtab = ch_strdup( cargv[1] );
  
+ #ifdef SLAPD_LOADABLE_MODULES
+ 		} else if (strcasecmp( cargv[0], "loadmodule") == 0 ) {
+ 		   if ( cargc < 2 ) {
+ 		      Debug( LDAP_DEBUG_ANY,
+ 			     "%s: line %d: missing filename in \"loadmodule <filename>\" line\n",
+ 			     fname, lineno, 0 );
+ 		      exit( 1 );
+ 		   }
+ 		   if (!load_module(cargv[1])) {
+ 		      Debug( LDAP_DEBUG_ANY,
+ 			     "%s: line %d: failed to load module %s\n",
+ 			     fname, lineno, cargv[1]);
+ 		      exit( 1 );
+ 		   }
+ 
+ #endif /*SLAPD_LOADABLE_MODULES*/
+ 
  		/* pass anything else to the current backend config routine */
  		} else {
  			if ( be == NULL ) {
Index: openldap/ldap/servers/slapd/back-ldbm/init.c
diff -c openldap/ldap/servers/slapd/back-ldbm/init.c:1.1.1.1 openldap/ldap/servers/slapd/back-ldbm/init.c:1.3
*** openldap/ldap/servers/slapd/back-ldbm/init.c:1.1.1.1	Thu Apr  8 21:28:12 1999
--- openldap/ldap/servers/slapd/back-ldbm/init.c	Tue Apr 13 14:36:29 1999
***************
*** 10,15 ****
--- 10,48 ----
  #include "slap.h"
  #include "back-ldbm.h"
  
+ #ifdef SLAPD_LOADABLE_MODULES
+ #include <gmodule.h>
+ 
+ void shell_set_back_functions(Backend* be);
+ 
+ const gchar* g_module_check_init(GModule* module) {
+    register_backend_module("ldbm", ldbm_set_back_functions);
+    return NULL;
+ }
+ 
+ #endif /* SLAPD_LOADABLE_MODULES */
+ 
+ void ldbm_set_back_functions(Backend* be) {
+    be->be_bind = ldbm_back_bind;
+    be->be_unbind = ldbm_back_unbind;
+    be->be_search = ldbm_back_search;
+    be->be_compare = ldbm_back_compare;
+    be->be_modify = ldbm_back_modify;
+    be->be_modrdn = ldbm_back_modrdn;
+    be->be_add = ldbm_back_add;
+    be->be_delete = ldbm_back_delete;
+    be->be_abandon = ldbm_back_abandon;
+    be->be_config = ldbm_back_config;
+    be->be_init = ldbm_back_init;
+    be->be_close = ldbm_back_close;
+ #ifdef SLAPD_ACLGROUPS
+    be->be_group = ldbm_back_group;
+ #endif
+    be->be_type = "ldbm";
+    foundit = 1;
+ }
+ 
+ 
  void
  ldbm_back_init(
      Backend	*be
Index: openldap/ldap/servers/slapd/back-passwd/config.c
diff -c openldap/ldap/servers/slapd/back-passwd/config.c:1.1.1.1 openldap/ldap/servers/slapd/back-passwd/config.c:1.2
*** openldap/ldap/servers/slapd/back-passwd/config.c:1.1.1.1	Thu Apr  8 21:28:12 1999
--- openldap/ldap/servers/slapd/back-passwd/config.c	Tue Apr 13 14:22:13 1999
***************
*** 10,15 ****
--- 10,46 ----
  
  #include "slap.h"
  
+ #ifdef SLAPD_LOADABLE_MODULES
+ #include <gmodule.h>
+ 
+ void passwd_set_back_functions(Backend* be);
+ 
+ const gchar* g_module_check_init(GModule* module) {
+    register_backend_module("passwd", passwd_set_back_functions);
+    return NULL;
+ }
+ 
+ #endif /* SLAPD_LOADABLE_MODULES */
+ 
+ void passwd_set_back_functions(Backend* be) {
+    be->be_bind = NULL;
+    be->be_unbind = NULL;
+    be->be_search = passwd_back_search;
+    be->be_compare = NULL;
+    be->be_modify = NULL;
+    be->be_modrdn = NULL;
+    be->be_add = NULL;
+    be->be_delete = NULL;
+    be->be_abandon = NULL;
+    be->be_config = passwd_back_config;
+    be->be_init = NULL;
+    be->be_close = NULL;
+ #ifdef SLAPD_ACLGROUPS
+    be->be_group = NULL;
+ #endif
+    be->be_type = "passwd";
+ }
+ 
  void
  passwd_back_config(
      Backend	*be,
***************
*** 42,44 ****
--- 73,82 ----
  		    fname, lineno, argv[0] );
  	}
  }
+ 
+ 
+ 
+ 
+ 
+ 
+ 
Index: openldap/ldap/servers/slapd/back-shell/init.c
diff -c openldap/ldap/servers/slapd/back-shell/init.c:1.1.1.1 openldap/ldap/servers/slapd/back-shell/init.c:1.2
*** openldap/ldap/servers/slapd/back-shell/init.c:1.1.1.1	Thu Apr  8 21:28:12 1999
--- openldap/ldap/servers/slapd/back-shell/init.c	Tue Apr 13 14:22:14 1999
***************
*** 9,14 ****
--- 9,45 ----
  #include "slap.h"
  #include "shell.h"
  
+ #ifdef SLAPD_LOADABLE_MODULES
+ #include <gmodule.h>
+ 
+ void shell_set_back_functions(Backend* be);
+ 
+ const gchar* g_module_check_init(GModule* module) {
+    register_backend_module("shell", shell_set_back_functions);
+    return NULL;
+ }
+ 
+ #endif /* SLAPD_LOADABLE_MODULES */
+ 
+ void shell_set_back_functions(Backend* be) {
+    be->be_bind = shell_back_bind;
+    be->be_unbind = shell_back_unbind;
+    be->be_search = shell_back_search;
+    be->be_compare = shell_back_compare;
+    be->be_modify = shell_back_modify;
+    be->be_modrdn = shell_back_modrdn;
+    be->be_add = shell_back_add;
+    be->be_delete = shell_back_delete;
+    be->be_abandon = shell_back_abandon;
+    be->be_config = shell_back_config;
+    be->be_init = shell_back_init;
+    be->be_close = NULL;
+ #ifdef SLAPD_ACLGROUPS
+    be->be_group = NULL;
+ #endif
+    be->be_type = "shell";
+ }
+ 
  void
  shell_back_init(
      Backend	*be
***************
*** 20,22 ****
--- 51,54 ----
  
  	be->be_private = si;
  }
+ 
begin:          vcard
fn:             Bastiaan Bakker
n:              Bakker;Bastiaan
org:            LifeLine Networks BV
email;internet: Bastiaan.Bakker@lifeline.nl
x-mozilla-cpt:  ;0
x-mozilla-html: TRUE
version:        2.1
end:            vcard