2002-10-30 14:52:36 +03:00
/*
Unix SMB / CIFS implementation .
module loading system
2003-05-06 06:34:59 +04:00
Copyright ( C ) Jelmer Vernooij 2002 - 2003
Copyright ( C ) Stefan ( metze ) Metzmacher 2003
2002-10-30 14:52:36 +03:00
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 0213 9 , USA .
*/
# include "includes.h"
# ifdef HAVE_DLOPEN
2003-09-04 06:02:26 +04:00
/* 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 )
2002-10-30 14:52:36 +03:00
{
void * handle ;
init_module_function * init ;
2003-04-28 21:48:48 +04:00
NTSTATUS status ;
2003-01-18 00:23:14 +03:00
const char * error ;
2002-10-30 14:52:36 +03:00
/* 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
*/
2002-10-30 20:50:36 +03:00
handle = sys_dlopen ( module_name , RTLD_LAZY ) ;
2002-10-30 14:52:36 +03:00
if ( ! handle ) {
2003-09-15 04:19:25 +04:00
int level = is_probe ? 3 : 0 ;
2003-11-20 01:57:56 +03:00
error = sys_dlerror ( ) ;
DEBUG ( level , ( " Error loading module '%s': %s \n " , module_name , error ? error : " " ) ) ;
2003-04-28 21:48:48 +04:00
return NT_STATUS_UNSUCCESSFUL ;
2002-10-30 14:52:36 +03:00
}
2003-08-15 08:42:05 +04:00
init = ( init_module_function * ) sys_dlsym ( handle , " init_module " ) ;
2002-10-30 14:52:36 +03:00
2003-01-18 00:23:14 +03:00
/* we must check sys_dlerror() to determine if it worked, because
sys_dlsym ( ) can validly return NULL */
error = sys_dlerror ( ) ;
if ( error ) {
2003-09-04 06:02:26 +04:00
DEBUG ( 0 , ( " Error trying to resolve symbol 'init_module' in %s: %s \n " ,
module_name , error ) ) ;
2003-04-28 21:48:48 +04:00
return NT_STATUS_UNSUCCESSFUL ;
2002-10-30 14:52:36 +03:00
}
2003-04-15 02:23:02 +04:00
status = init ( ) ;
2002-10-30 14:52:36 +03:00
DEBUG ( 2 , ( " Module '%s' loaded \n " , module_name ) ) ;
2003-04-15 02:23:02 +04:00
return status ;
}
2003-09-04 06:02:26 +04:00
NTSTATUS smb_load_module ( const char * module_name )
{
return do_smb_load_module ( module_name , False ) ;
}
2003-04-15 02:23:02 +04:00
/* Load all modules in list and return number of
* modules that has been successfully loaded */
int smb_load_modules ( const char * * modules )
{
int i ;
int success = 0 ;
for ( i = 0 ; modules [ i ] ; i + + ) {
2003-04-28 21:48:48 +04:00
if ( NT_STATUS_IS_OK ( smb_load_module ( modules [ i ] ) ) ) {
2003-04-15 02:23:02 +04:00
success + + ;
}
}
DEBUG ( 2 , ( " %d modules successfully loaded \n " , success ) ) ;
return success ;
}
2003-04-28 21:48:48 +04:00
NTSTATUS smb_probe_module ( const char * subsystem , const char * module )
2003-04-15 02:23:02 +04:00
{
pstring full_path ;
/* Check for absolute path */
2003-05-03 08:34:13 +04:00
/* if we make any 'samba multibyte string'
calls here , we break
for loading string modules */
2003-09-04 06:02:26 +04:00
DEBUG ( 5 , ( " Probing module '%s' \n " , module ) ) ;
2003-05-03 08:34:13 +04:00
if ( module [ 0 ] = = ' / ' )
2003-09-04 06:02:26 +04:00
return do_smb_load_module ( module , True ) ;
2003-04-15 02:23:02 +04:00
pstrcpy ( full_path , lib_path ( subsystem ) ) ;
pstrcat ( full_path , " / " ) ;
pstrcat ( full_path , module ) ;
pstrcat ( full_path , " . " ) ;
pstrcat ( full_path , shlib_ext ( ) ) ;
2003-09-04 06:02:26 +04:00
DEBUG ( 5 , ( " Probing module '%s': Trying to load from %s \n " , module , full_path ) ) ;
2003-04-15 02:23:02 +04:00
2003-09-04 06:02:26 +04:00
return do_smb_load_module ( full_path , True ) ;
2002-10-30 14:52:36 +03:00
}
# else /* HAVE_DLOPEN */
2003-04-28 21:48:48 +04:00
NTSTATUS smb_load_module ( const char * module_name )
2003-04-15 02:23:02 +04:00
{
2003-05-03 08:34:13 +04:00
DEBUG ( 0 , ( " This samba executable has not been built with plugin support \n " ) ) ;
2003-04-28 21:48:48 +04:00
return NT_STATUS_NOT_SUPPORTED ;
2003-04-15 02:23:02 +04:00
}
int smb_load_modules ( const char * * modules )
{
2003-05-03 08:34:13 +04:00
DEBUG ( 0 , ( " This samba executable has not been built with plugin support \n " ) ) ;
2003-04-28 21:48:48 +04:00
return - 1 ;
2003-04-15 02:23:02 +04:00
}
2003-04-28 21:48:48 +04:00
NTSTATUS smb_probe_module ( const char * subsystem , const char * module )
2002-10-30 14:52:36 +03:00
{
2003-05-03 08:34:13 +04:00
DEBUG ( 0 , ( " This samba executable has not been built with plugin support, not probing \n " ) ) ;
2003-04-28 21:48:48 +04:00
return NT_STATUS_NOT_SUPPORTED ;
2002-10-30 14:52:36 +03:00
}
# endif /* HAVE_DLOPEN */
2003-04-15 02:23:02 +04:00
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 ( ) ) ;
}
2003-05-06 06:34:59 +04:00
/***************************************************************************
* This Function registers a idle event
*
* the registered funtions are run periodically
* and maybe shutdown idle connections ( e . g . to an LDAP server )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-05-29 18:40:55 +04:00
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 )
2003-05-06 06:34:59 +04:00
{
2003-05-29 18:40:55 +04:00
struct smb_idle_list_ent * event ;
if ( ! fn ) {
return SMB_EVENT_ID_INVALID ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
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 + + ;
2003-05-06 06:34:59 +04:00
2003-05-29 18:40:55 +04:00
DLIST_ADD ( smb_idle_event_list , event ) ;
2003-05-06 06:34:59 +04:00
2003-05-29 18:40:55 +04:00
return event - > id ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
BOOL smb_unregister_idle_event ( smb_event_id_t id )
2003-05-06 06:34:59 +04:00
{
2003-05-29 18:40:55 +04:00
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 ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
return False ;
2003-05-06 06:34:59 +04:00
}
void smb_run_idle_events ( time_t now )
{
2003-05-29 18:40:55 +04:00
struct smb_idle_list_ent * event = smb_idle_event_list ;
2003-05-06 06:34:59 +04:00
2003-05-29 18:40:55 +04:00
while ( event ) {
2003-09-18 03:36:55 +04:00
struct smb_idle_list_ent * next = event - > next ;
2003-05-06 06:34:59 +04:00
time_t interval ;
2003-09-18 03:36:55 +04:00
if ( event - > interval < = 0 ) {
interval = SMB_IDLE_EVENT_DEFAULT_INTERVAL ;
} else if ( event - > interval > = SMB_IDLE_EVENT_MIN_INTERVAL ) {
2003-05-29 18:40:55 +04:00
interval = event - > interval ;
} else {
interval = SMB_IDLE_EVENT_MIN_INTERVAL ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
if ( now > ( event - > lastrun + interval ) ) {
event - > lastrun = now ;
2003-09-18 03:36:55 +04:00
event - > fn ( & event - > data , & event - > interval , now ) ;
2003-05-29 18:40:55 +04:00
}
2003-09-18 03:36:55 +04:00
event = next ;
2003-05-06 06:34:59 +04:00
}
return ;
}
/***************************************************************************
* This Function registers a exit event
*
2003-05-29 18:40:55 +04:00
* the registered functions are run on exit ( )
2003-05-06 06:34:59 +04:00
* and maybe shutdown idle connections ( e . g . to an LDAP server )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-05-29 18:40:55 +04:00
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 )
2003-05-06 06:34:59 +04:00
{
2003-05-29 18:40:55 +04:00
struct smb_exit_list_ent * event ;
static smb_event_id_t smb_exit_event_id = 1 ;
if ( ! fn ) {
return SMB_EVENT_ID_INVALID ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
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 + + ;
2003-05-06 06:34:59 +04:00
2003-05-29 18:40:55 +04:00
DLIST_ADD ( smb_exit_event_list , event ) ;
return event - > id ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
BOOL smb_unregister_exit_event ( smb_event_id_t id )
2003-05-06 06:34:59 +04:00
{
2003-05-29 18:40:55 +04:00
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 ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
return False ;
2003-05-06 06:34:59 +04:00
}
void smb_run_exit_events ( void )
{
2003-05-29 18:40:55 +04:00
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 ) ;
2003-05-06 06:34:59 +04:00
}
2003-05-29 18:40:55 +04:00
/* the list is empty now...*/
2003-05-06 06:34:59 +04:00
smb_exit_event_list = NULL ;
return ;
}