/*
 * POP3Lite - 3lite POP3 Daemon
 * Copyright (C) 2000, 2001 Gergely Nagy <8@free.bsd.hu>
 *
 * This file is part of POP3Lite.
 *
 * POP3Lite 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.
 *
 * POP3LIte 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "main.h"

#include <pop3lite.h>
#include <ltdl.h>
#include <glib.h>
#include <stdio.h>

#include <syslog.h>

#include "module.h"
#include "builtin-modules.h"

static const char rcsid[]="$Id: module.c,v 1.6 2001/01/12 15:59:00 algernon Exp $";

#ifdef WITH_MODULE_SUPPORT
static void load_module ( P3LControl *control, char *name );
static void free_module ( P3LControl *control, char *name );

/**
 * load_module: load one module
 * @control: the struct to pass to the init function
 * @fn: the module's filename
 *
 * Load a dynamic module and initialise it.
 *
 * Returns: nothing,
 **/

static void
load_module ( P3LControl *control, char *name )
{
	lt_dlhandle handle;
	p3l_module_hook modinit;
	int res;

#ifdef DEBUG
	control->system->log ( control, LOG_DEBUG, "%s:%d: loading module: %s",
			       __FILE__, __LINE__, name );
#endif

	handle = lt_dlopenext ( name );

	if ( handle == NULL )
		handle = lt_dlopen ( g_strdup_printf ( "%s.a", name ) );
	if ( handle == NULL )
	{
		control->system->log ( control, LOG_WARNING, "Loading %s failed: %s",
				       name, lt_dlerror () );
		return;
	}

	/*
	 * Try to get the module_init function
	 */

	modinit = (p3l_module_hook) lt_dlsym ( handle, "module_init" );

	/*
	 * If we got it, execute it!
	 */

	if ( modinit != NULL )
	{
		res = (*modinit) ( control );
		if ( res == 0 )
			g_hash_table_insert ( control->modules, g_strdup ( name ),
					      (gpointer) handle );
		else
			lt_dlclose ( handle );
	}
	else
		control->system->log ( control, LOG_WARNING, "Loading %s failed: %s",
				       name, lt_dlerror () );

}

/**
 * free_module: free one module
 * @control: the usual control struct
 * @name: module name to free
 *
 * Removes a specified module from the list of loaded
 * modules. Of course, unloads it too.
 *
 * Returns: nothing
 **/

static void
free_module ( P3LControl *control, char *name )
{
	lt_dlhandle handle;
	p3l_module_hook moddone;

#ifdef DEBUG
	control->system->log ( control, LOG_DEBUG, "%s:%d: freeing module %s",
			       __FILE__, __LINE__, name );
#endif

	if ( name == NULL )
		return;

	handle = g_hash_table_lookup ( control->modules, name );

	if ( handle == NULL )
		return;

	moddone = (p3l_module_hook) lt_dlsym ( handle, "module_done" );

	if ( moddone != NULL )
		(*moddone) ( control );

	lt_dlclose ( handle );
}
#endif /* WITH_MODULE_SUPPORT */

/**
 * load_modules: load all the selected modules
 * @control: the main control field
 *
 * Load all the selected modules (module_list).
 *
 * Returns: nothing.
 **/

void
load_modules ( P3LControl *control )
{
#ifdef WITH_MODULE_SUPPORT
	unsigned long i;
	GList *module_list;
	GList *module_dirs;
#endif /* WITH_MODULE_SUPPORT */

	/*
	 * Load builtin modules
	 */

	load_builtin_modules ( control );

#ifdef WITH_MODULE_SUPPORT
	/*
	 * Rertieve our options
	 */
	module_list = P3L_GET_OPTION ( "MODULE_LIST" );
	module_dirs = P3L_GET_OPTION ( "MODULE_DIRS" );

	if ( module_dirs == NULL )
		module_dirs = g_list_append ( module_dirs, MODULEDIR );

	/*
	 * This is here because dlpreopen requires this
	 */
	LTDL_SET_PRELOADED_SYMBOLS();

	/*
	 * Initialize the LTDL library
	 */
	lt_dlinit ();

	/*
	 * Add search directories
	 */

	for ( i = 0; i < g_list_length ( module_dirs ); i++ )
		lt_dladdsearchdir ( g_list_nth_data ( module_dirs, i ) );

	/*
	 * One-by-one, load them all
	 */

	for ( i = 0; i < g_list_length ( module_list ); i++ )
		load_module ( control, g_list_nth_data ( module_list, i ) );

#endif /* WITH_MODULE_SUPPORT */
}

/**
 * free_modules: free the memory occupied by the modules
 * @control: struct to pass to the destructor
 *
 * Frees the memory occupied by the modules
 *
 * Returns: nothing
 **/

void
free_modules ( P3LControl *control )
{
#ifdef WITH_MODULE_SUPPORT
	unsigned long i;
	GList *module_list;

	module_list = P3L_GET_OPTION ( "MODULE_LIST" );

	if ( g_list_length ( module_list ) == 0 )
		return;

	for ( i = g_list_length ( module_list ) - 1; i > 0; i-- )
		free_module ( control, g_list_nth_data ( module_list, i ) );

	lt_dlexit ();
#endif /* WITH_MODULE_SUPPORT */

	free_builtin_modules ( control );
}


syntax highlighted by Code2HTML, v. 0.9.1