diff options
Diffstat (limited to 'source/lib/module.c')
-rw-r--r-- | source/lib/module.c | 244 |
1 files changed, 52 insertions, 192 deletions
diff --git a/source/lib/module.c b/source/lib/module.c index 2abe918ef44..15f92db59e0 100644 --- a/source/lib/module.c +++ b/source/lib/module.c @@ -3,7 +3,6 @@ module loading system Copyright (C) Jelmer Vernooij 2002-2003 - Copyright (C) Stefan (metze) Metzmacher 2003 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,15 +23,31 @@ #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) +/* Load module (or directory with modules) recursively. + * Includes running the init_module() function */ +NTSTATUS smb_load_module(const char *module_name) { void *handle; - init_module_function *init; + init_module_function init; NTSTATUS status; const char *error; + struct stat st; + DIR *dir; + struct dirent *dirent; + + stat(module_name, &st); + + /* If the argument is a directory, recursively load all files / + * directories in it */ + + /* How about symlinks pointing to themselves - wouldn't we rather + * want to use wildcards here? */ + if(S_ISDIR(st.st_mode)) { + dir = opendir(module_name); + while ((dirent = readdir(dir))) { + smb_load_module(dirent->d_name); + } + } /* Always try to use LAZY symbol resolving; if the plugin has * backwards compatibility, there might be symbols in the @@ -41,20 +56,17 @@ static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe) handle = sys_dlopen(module_name, RTLD_LAZY); if(!handle) { - int level = is_probe ? 3 : 0; - error = sys_dlerror(); - DEBUG(level, ("Error loading module '%s': %s\n", module_name, error ? error : "")); + DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); return NT_STATUS_UNSUCCESSFUL; } - init = (init_module_function *)sys_dlsym(handle, "init_module"); + init = (init_module_function)sys_dlsym(handle, "init_module"); /* we must check sys_dlerror() to determine if it worked, because sys_dlsym() can validly return NULL */ error = sys_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_module' in %s: %s\n", module_name, error)); return NT_STATUS_UNSUCCESSFUL; } @@ -65,11 +77,6 @@ static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe) return status; } -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) @@ -88,32 +95,6 @@ int smb_load_modules(const char **modules) return success; } -NTSTATUS smb_probe_module(const char *subsystem, const char *module) -{ - pstring full_path; - - /* Check for absolute path */ - - /* 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()); - - DEBUG(5, ("Probing module '%s': Trying to load from %s\n", module, full_path)); - - return do_smb_load_module(full_path, True); -} - #else /* HAVE_DLOPEN */ NTSTATUS smb_load_module(const char *module_name) @@ -128,177 +109,56 @@ int smb_load_modules(const char **modules) return -1; } -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; -} - #endif /* HAVE_DLOPEN */ void init_modules(void) { - /* FIXME: This can cause undefined symbol errors : - * smb_register_vfs() isn't available in nmbd, for example */ 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; +struct subsystem { + char *name; + register_backend_function callback; + struct subsystem *prev, *next; }; -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; -} +static struct subsystem *subsystems = NULL; -void smb_run_idle_events(time_t now) +NTSTATUS register_subsystem(const char *name, register_backend_function callback) { - struct smb_idle_list_ent *event = smb_idle_event_list; - - while (event) { - struct smb_idle_list_ent *next = event->next; - time_t interval; - - if (event->interval <= 0) { - interval = SMB_IDLE_EVENT_DEFAULT_INTERVAL; - } else if (event->interval >= SMB_IDLE_EVENT_MIN_INTERVAL) { - interval = event->interval; - } else { - interval = SMB_IDLE_EVENT_MIN_INTERVAL; + struct subsystem *s; + struct subsystem *t = subsystems; + + while(t) { + if(!strcmp(name, t->name)) { + /* its already registered! */ + DEBUG(0,("SUBSYSTEM '%s' for type already registered\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; } - if (now >(event->lastrun+interval)) { - event->lastrun = now; - event->fn(&event->data,&event->interval,now); - } - event = next; + t = t->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; - } + s = smb_xmalloc(sizeof(struct subsystem)); - 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++; + s->name = smb_xstrdup(name); + s->callback = callback; + s->prev = s->next = NULL; - DLIST_ADD(smb_exit_event_list,event); + DLIST_ADD(subsystems, s); - return event->id; + return NT_STATUS_OK; } -BOOL smb_unregister_exit_event(smb_event_id_t id) +NTSTATUS register_backend(const char *subsystem, void *args) { - 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; -} + /* Find the specified subsystem */ + struct subsystem *s = subsystems; -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); + while(s) { + if(!strcmp(subsystem, s->name)) return s->callback(args); + s = s->next; } - /* the list is empty now...*/ - smb_exit_event_list = NULL; - - return; + return NT_STATUS_NOT_IMPLEMENTED; } |