Remove sys_dl*() - stubs are already provided by libreplace.
[ira/wip.git] / source3 / lib / module.c
index 4437d085f9c18df2945efef74519e430fee9576a..de136680092f87fc85863cf4b0cbc45596c5fb11 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
-NTSTATUS smb_load_module(const char *module_name)
+
+/* 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)
 {
        void *handle;
        init_module_function *init;
@@ -34,31 +37,48 @@ NTSTATUS smb_load_module(const char *module_name)
         * 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) {
-               DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror()));
+               int level = is_probe ? 3 : 0;
+               DEBUG(level, ("Error loading module '%s': %s\n", module_name, error ? error : ""));
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       init = 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;
 }
 
-/* Load all modules in list and return number of 
+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
  * modules that has been successfully loaded */
 int smb_load_modules(const char **modules)
 {
@@ -78,25 +98,41 @@ 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 */
-       if (module[0] == '/')
-               return smb_load_module(module);
-       
-       pstrcpy(full_path, lib_path(subsystem));
-       pstrcat(full_path, "/");
-       pstrcat(full_path, module);
-       pstrcat(full_path, ".");
-       pstrcat(full_path, shlib_ext());
-
-       DEBUG(5, ("Probing module %s: Trying to load from %s\n", module, full_path));
-       
-       return smb_load_module(full_path);
+
+       DEBUG(5, ("Probing module '%s'\n", module));
+
+       if (module[0] == '/') {
+               status = do_smb_load_module(module, True);
+               TALLOC_FREE(ctx);
+               return status;
+       }
+
+       full_path = talloc_asprintf(ctx,
+                       "%s/%s.%s",
+                       modules_path(subsystem),
+                       module,
+                       shlib_ext());
+       if (!full_path) {
+               TALLOC_FREE(ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       DEBUG(5, ("Probing module '%s': Trying to load from %s\n",
+               module, full_path));
+
+       status = do_smb_load_module(full_path, True);
+
+       TALLOC_FREE(ctx);
+       return status;
 }
 
 #else /* HAVE_DLOPEN */
@@ -128,182 +164,3 @@ void init_modules(void)
        if(lp_preload_modules()) 
                smb_load_modules(lp_preload_modules());
 }
-
-
-/*************************************************************************
- * This functions /path/to/foobar.so -> foobar
- ************************************************************************/
-void module_path_get_name(const char *path, pstring name)
-{
-       char *s;
-
-       /* First, make the path relative */
-       s = strrchr(path, '/');
-       if(s) pstrcpy(name, s+1);
-       else pstrcpy(name, path);
-       
-       if (dyn_SHLIBEXT && *dyn_SHLIBEXT && strlen(dyn_SHLIBEXT) < strlen(name)) {
-               int n = strlen(name) - strlen(dyn_SHLIBEXT);
-               
-               /* Remove extension if necessary */
-               if (name[n-1] == '.' && !strcmp(name+n, dyn_SHLIBEXT)) {
-                       name[n-1] = '\0';
-               }
-       }
-}
-
-
-/***************************************************************************
- * 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;
-}