s3-module allow libreplace to provide dlopen replacement
[amitay/samba.git] / source3 / lib / module.c
index 941a6cfbe3945ffbd3d5435084719e2235eaa8a5..9cd3884c517a6403b6659b75588dd9f7665f8fe3 100644 (file)
@@ -7,7 +7,7 @@
    
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 
-#ifdef HAVE_DLOPEN
-
 /* Load a dynamic module.  Only log a level 0 error if we are not checking 
    for the existence of a module (probling). */
 
-static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe)
+static NTSTATUS do_smb_load_module(const char *module_name, bool is_probe)
 {
        void *handle;
        init_module_function *init;
@@ -38,31 +35,39 @@ static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe)
         * backwards compatibility, there might be symbols in the 
         * plugin referencing to old (removed) functions
         */
-       handle = sys_dlopen(module_name, RTLD_LAZY);
+       handle = dlopen(module_name, RTLD_LAZY);
+
+       /* This call should reset any possible non-fatal errors that 
+          occured since last call to dl* functions */
+       error = dlerror();
 
        if(!handle) {
                int level = is_probe ? 3 : 0;
-               DEBUG(level, ("Error loading module '%s': %s\n", module_name, 
-                             sys_dlerror()));
-
+               DEBUG(level, ("Error loading module '%s': %s\n", module_name, error ? error : ""));
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       init = (init_module_function *)sys_dlsym(handle, "init_module");
+       init = (init_module_function *)dlsym(handle, "init_samba_module");
 
-       /* we must check sys_dlerror() to determine if it worked, because
-           sys_dlsym() can validly return NULL */
-       error = sys_dlerror();
+       /* we must check dlerror() to determine if it worked, because
+           dlsym() can validly return NULL */
+       error = dlerror();
        if (error) {
-               DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", 
-                         module_name, error));
+               DEBUG(0, ("Error trying to resolve symbol 'init_samba_module' "
+                         "in %s: %s\n", module_name, error));
+               dlclose(handle);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       status = init();
-
        DEBUG(2, ("Module '%s' loaded\n", module_name));
 
+       status = init();
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Module '%s' initialization failed: %s\n",
+                           module_name, get_friendly_nt_error_msg(status)));
+               dlclose(handle);
+       }
+
        return status;
 }
 
@@ -71,7 +76,7 @@ NTSTATUS smb_load_module(const char *module_name)
        return do_smb_load_module(module_name, False);
 }
 
-/* Load all modules in list and return number of 
+/* Load all modules in list and return number of
  * modules that has been successfully loaded */
 int smb_load_modules(const char **modules)
 {
@@ -91,52 +96,43 @@ int smb_load_modules(const char **modules)
 
 NTSTATUS smb_probe_module(const char *subsystem, const char *module)
 {
-       pstring full_path;
-       
+       char *full_path = NULL;
+       TALLOC_CTX *ctx = talloc_stackframe();
+       NTSTATUS status;
+
        /* Check for absolute path */
 
-       /* if we make any 'samba multibyte string' 
-          calls here, we break 
+       /* if we make any 'samba multibyte string'
+          calls here, we break
           for loading string modules */
 
        DEBUG(5, ("Probing module '%s'\n", module));
 
-       if (module[0] == '/')
-               return do_smb_load_module(module, True);
-       
-       pstrcpy(full_path, lib_path(subsystem));
-       pstrcat(full_path, "/");
-       pstrcat(full_path, module);
-       pstrcat(full_path, ".");
-       pstrcat(full_path, shlib_ext());
+       if (module[0] == '/') {
+               status = do_smb_load_module(module, True);
+               TALLOC_FREE(ctx);
+               return status;
+       }
 
-       DEBUG(5, ("Probing module '%s': Trying to load from %s\n", module, full_path));
-       
-       return do_smb_load_module(full_path, True);
-}
+       full_path = talloc_asprintf(ctx,
+                                   "%s/%s.%s",
+                                   modules_path(ctx, subsystem),
+                                   module,
+                                   shlib_ext());
+       if (!full_path) {
+               TALLOC_FREE(ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-#else /* HAVE_DLOPEN */
+       DEBUG(5, ("Probing module '%s': Trying to load from %s\n",
+               module, full_path));
 
-NTSTATUS smb_load_module(const char *module_name)
-{
-       DEBUG(0,("This samba executable has not been built with plugin support\n"));
-       return NT_STATUS_NOT_SUPPORTED;
-}
-
-int smb_load_modules(const char **modules)
-{
-       DEBUG(0,("This samba executable has not been built with plugin support\n"));
-       return -1;
-}
+       status = do_smb_load_module(full_path, True);
 
-NTSTATUS smb_probe_module(const char *subsystem, const char *module)
-{
-       DEBUG(0,("This samba executable has not been built with plugin support, not probing\n")); 
-       return NT_STATUS_NOT_SUPPORTED;
+       TALLOC_FREE(ctx);
+       return status;
 }
 
-#endif /* HAVE_DLOPEN */
-
 void init_modules(void)
 {
        /* FIXME: This can cause undefined symbol errors :
@@ -144,159 +140,3 @@ void init_modules(void)
        if(lp_preload_modules()) 
                smb_load_modules(lp_preload_modules());
 }
-
-
-/***************************************************************************
- * This Function registers a idle event
- *
- * the registered funtions are run periodically
- * and maybe shutdown idle connections (e.g. to an LDAP server)
- ***************************************************************************/
-static smb_event_id_t smb_idle_event_id = 1;
-
-struct smb_idle_list_ent {
-       struct smb_idle_list_ent *prev,*next;
-       smb_event_id_t id;
-       smb_idle_event_fn *fn;
-       void *data;
-       time_t interval;
-       time_t lastrun;
-};
-
-static struct smb_idle_list_ent *smb_idle_event_list = NULL;
-
-smb_event_id_t smb_register_idle_event(smb_idle_event_fn *fn, void *data, time_t interval)
-{
-       struct smb_idle_list_ent *event;
-
-       if (!fn) {      
-               return SMB_EVENT_ID_INVALID;
-       }
-
-       event = (struct smb_idle_list_ent *)malloc(sizeof(struct smb_idle_list_ent));
-       if (!event) {
-               DEBUG(0,("malloc() failed!\n"));
-               return SMB_EVENT_ID_INVALID;
-       }
-       event->fn = fn;
-       event->data = data;
-       event->interval = interval;
-       event->lastrun = 0;
-       event->id = smb_idle_event_id++;
-
-       DLIST_ADD(smb_idle_event_list,event);
-
-       return event->id;
-}
-
-BOOL smb_unregister_idle_event(smb_event_id_t id)
-{
-       struct smb_idle_list_ent *event = smb_idle_event_list;
-       
-       while(event) {
-               if (event->id == id) {
-                       DLIST_REMOVE(smb_idle_event_list,event);
-                       SAFE_FREE(event);
-                       return True;
-               }
-               event = event->next;
-       }
-       
-       return False;
-}
-
-void smb_run_idle_events(time_t now)
-{
-       struct smb_idle_list_ent *event = smb_idle_event_list;
-
-       while (event) {
-               time_t interval;
-
-               if (event->interval >= SMB_IDLE_EVENT_MIN_INTERVAL) {
-                       interval = event->interval;
-               } else {
-                       interval = SMB_IDLE_EVENT_MIN_INTERVAL;
-               }
-               if (now >(event->lastrun+interval)) {
-                       event->fn(&event->data,&event->interval,now);
-                       event->lastrun = now;
-               }
-               event = event->next;
-       }
-
-       return;
-}
-
-/***************************************************************************
- * This Function registers a exit event
- *
- * the registered functions are run on exit()
- * and maybe shutdown idle connections (e.g. to an LDAP server)
- ***************************************************************************/
-
-struct smb_exit_list_ent {
-       struct smb_exit_list_ent *prev,*next;
-       smb_event_id_t id;
-       smb_exit_event_fn *fn;
-       void *data;
-};
-
-static struct smb_exit_list_ent *smb_exit_event_list = NULL;
-
-smb_event_id_t smb_register_exit_event(smb_exit_event_fn *fn, void *data)
-{
-       struct smb_exit_list_ent *event;
-       static smb_event_id_t smb_exit_event_id = 1;
-
-       if (!fn) {      
-               return SMB_EVENT_ID_INVALID;
-       }
-
-       event = (struct smb_exit_list_ent *)malloc(sizeof(struct smb_exit_list_ent));
-       if (!event) {
-               DEBUG(0,("malloc() failed!\n"));
-               return SMB_EVENT_ID_INVALID;
-       }
-       event->fn = fn;
-       event->data = data;
-       event->id = smb_exit_event_id++;
-
-       DLIST_ADD(smb_exit_event_list,event);
-
-       return event->id;
-}
-
-BOOL smb_unregister_exit_event(smb_event_id_t id)
-{
-       struct smb_exit_list_ent *event = smb_exit_event_list;
-       
-       while(event) {
-               if (event->id == id) {
-                       DLIST_REMOVE(smb_exit_event_list,event);
-                       SAFE_FREE(event);
-                       return True;
-               }
-               event = event->next;
-       }
-       
-       return False;
-}
-
-void smb_run_exit_events(void)
-{
-       struct smb_exit_list_ent *event = smb_exit_event_list;
-       struct smb_exit_list_ent *tmp = NULL;
-
-       while (event) {
-               event->fn(&event->data);
-               tmp = event;
-               event = event->next;
-               /* exit event should only run one time :-)*/
-               SAFE_FREE(tmp);
-       }
-
-       /* the list is empty now...*/
-       smb_exit_event_list = NULL;
-
-       return;
-}