removed the old obsolete Plugin system (commit 1/2)

- Removed @ Autoconf/make and CMake, VC Projects will be cleaned in a additional commit.



git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16203 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
blacksirius 2012-06-01 14:21:02 +00:00
parent 442132fefe
commit b1881eafee
25 changed files with 5 additions and 3796 deletions

View File

@ -481,7 +481,6 @@ set( RUNTIME_DIRECTORIES
"doc"
"log"
"npc"
"plugins"
"readme"
"sql-files"
"tools"

View File

@ -18,13 +18,6 @@ else
MAP_SQL_DEPENDS=needs_mysql
endif
WITH_PLUGINS=@WITH_PLUGINS@
ifeq ($(WITH_PLUGINS),yes)
ALL_DEPENDS+=plugins
PLUGIN_DEPENDS=common_sql
else
PLUGIN_DEPENDS=no_plugins
endif
#####################################################################
.PHONY: sql \
@ -33,7 +26,7 @@ endif
login_sql \
char_sql \
map_sql \
tools plugins addons \
tools \
import \
clean help
@ -62,9 +55,6 @@ map_sql: $(MAP_SQL_DEPENDS)
tools:
@$(MAKE) -C src/tool
plugins addons: $(PLUGIN_DEPENDS)
@$(MAKE) -C src/plugins
import:
# 1) create conf/import folder
# 2) add missing files
@ -81,7 +71,6 @@ clean:
@$(MAKE) -C src/login $@
@$(MAKE) -C src/char $@
@$(MAKE) -C src/map $@
@$(MAKE) -C src/plugins $@
@$(MAKE) -C src/tool $@
help:
@ -94,8 +83,6 @@ help:
@echo "'char_sql' - builds char server (SQL version)"
@echo "'map_sql' - builds map server (SQL version)"
@echo "'tools' - builds all the tools in src/tools"
@echo "'plugins' - builds all the plugins in src/plugins"
@echo "'addons'"
@echo "'import' - builds conf/import folder from the template conf/import-tmpl"
@echo "'all' - builds all the above targets"
@echo "'sql' - builds sql servers (targets 'common_sql' 'login_sql' 'char_sql'"
@ -109,10 +96,6 @@ needs_mysql:
@echo "MySQL not found or disabled by the configure script"
@exit 1
no_plugins:
@echo "Plugins disabled by the configure script"
@exit 1
#####################################################################
# TODO

View File

@ -1,29 +0,0 @@
// Athena Plugins Configuration file
// Should we auto search for plugin files and load them?
// If set to 'yes' you will not need to set 'plugin:' commands
// in this conf file to load them
auto_search: no
//------Plugins List -----------
// Just a sample plugin
//plugin: sample
// GUI core plugin
//plugin: gui
// Crash and Uptime reporting for CygWin/Linux
//plugin: sig
// Crash reporting for Windows
//plugin: exchndl
// Alternative, improved crash reporting for Windows
//plugin: dbghelpplug
// Process id logging
//plugin: pid
// Console parser
//plugin: console

76
configure vendored
View File

@ -1,5 +1,5 @@
#! /bin/sh
# From configure.in Revision: 16198 .
# From configure.in Revision: 16200 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.67.
#
@ -604,7 +604,6 @@ MYSQL_CFLAGS
MYSQL_VERSION
HAVE_MYSQL
MYSQL_CONFIG_HOME
WITH_PLUGINS
AR
SET_MAKE
EGREP
@ -2125,7 +2124,7 @@ ac_config_files="$ac_config_files 3rdparty/mt19937ar/Makefile 3rdparty/libconfig
ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile"
ac_config_files="$ac_config_files src/map/Makefile src/plugins/Makefile src/tool/Makefile"
ac_config_files="$ac_config_files src/map/Makefile src/tool/Makefile"
ac_ext=c
@ -4834,76 +4833,6 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS="$OLD_CFLAGS"
#
# -shared needs position independent code; some platforms emit it
# always, others need -fPIC
#
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -fPIC for shared objects" >&5
$as_echo_n "checking whether $CC needs -fPIC for shared objects... " >&6; }
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -shared"
WITH_PLUGINS="yes"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int foo(void)
{
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$OLD_CFLAGS"
else
if test "$compiler_supports_pic" = "yes" ; then
# Verify if -shared really fails due to lack of -fPIC or something else
CFLAGS="$CFLAGS -fPIC"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int foo(void)
{
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$OLD_CFLAGS -fPIC"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, but fails for another reason" >&5
$as_echo "no, but fails for another reason" >&6; }
as_fn_error $? "compiler is unable to compile shared objects for an unhandled reason, please report this with attached config.log... stopping" "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
else
# Disable compilation of plugins (optional), so 'make all' does not fail
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, but unsupported" >&5
$as_echo "yes, but unsupported" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: compiler is unable to generate position independent code, disabled plugins (optional)" >&5
$as_echo "$as_me: compiler is unable to generate position independent code, disabled plugins (optional)" >&6;}
WITH_PLUGINS="no"
fi
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
#
# -O2 implies -fstrict-aliasing, but the code is not safe for that
#
@ -6374,7 +6303,6 @@ do
"src/char/Makefile") CONFIG_FILES="$CONFIG_FILES src/char/Makefile" ;;
"src/login/Makefile") CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;;
"src/map/Makefile") CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;;
"src/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/Makefile" ;;
"src/tool/Makefile") CONFIG_FILES="$CONFIG_FILES src/tool/Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;

View File

@ -8,7 +8,7 @@ AC_CONFIG_SRCDIR([src/common/cbasetypes.h])
AC_CONFIG_FILES([Makefile src/common/Makefile])
AC_CONFIG_FILES([3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile])
AC_CONFIG_FILES([src/char/Makefile src/login/Makefile])
AC_CONFIG_FILES([src/map/Makefile src/plugins/Makefile src/tool/Makefile])
AC_CONFIG_FILES([src/map/Makefile src/tool/Makefile])
AC_GNU_SOURCE
@ -444,56 +444,6 @@ AC_COMPILE_IFELSE(
CFLAGS="$OLD_CFLAGS"
#
# -shared needs position independent code; some platforms emit it
# always, others need -fPIC
#
AC_MSG_CHECKING([whether $CC needs -fPIC for shared objects])
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -shared"
WITH_PLUGINS="yes"
AC_LINK_IFELSE(
[
int foo(void)
{
return 0;
}
],
[
AC_MSG_RESULT([no])
CFLAGS="$OLD_CFLAGS"
],
[
if test "$compiler_supports_pic" = "yes" ; then
# Verify if -shared really fails due to lack of -fPIC or something else
CFLAGS="$CFLAGS -fPIC"
AC_LINK_IFELSE(
[
int foo(void)
{
return 0;
}
],
[
AC_MSG_RESULT([yes])
CFLAGS="$OLD_CFLAGS -fPIC"
],
[
AC_MSG_RESULT([no, but fails for another reason])
AC_MSG_ERROR([compiler is unable to compile shared objects for an unhandled reason, please report this with attached config.log... stopping])
]
)
else
# Disable compilation of plugins (optional), so 'make all' does not fail
AC_MSG_RESULT([yes, but unsupported])
AC_MSG_NOTICE([compiler is unable to generate position independent code, disabled plugins (optional)])
WITH_PLUGINS="no"
fi
]
)
AC_SUBST([WITH_PLUGINS])
#
# -O2 implies -fstrict-aliasing, but the code is not safe for that
#

Binary file not shown.

Binary file not shown.

View File

@ -17,4 +17,3 @@ add_subdirectory( login )
add_subdirectory( char )
add_subdirectory( map )
add_subdirectory( tool )
add_subdirectory( plugins )

View File

@ -31,7 +31,6 @@ set( COMMON_ALL_HEADERS
"${CMAKE_CURRENT_BINARY_DIR}/svnversion.h"
"${COMMON_SOURCE_DIR}/cbasetypes.h"
"${COMMON_SOURCE_DIR}/mmo.h"
"${COMMON_SOURCE_DIR}/plugin.h"
)
set( COMMON_MINI_HEADERS
@ -71,7 +70,6 @@ set( COMMON_BASE_HEADERS
"${COMMON_SOURCE_DIR}/mapindex.h"
"${COMMON_SOURCE_DIR}/md5calc.h"
"${COMMON_SOURCE_DIR}/nullpo.h"
"${COMMON_SOURCE_DIR}/plugins.h"
"${COMMON_SOURCE_DIR}/random.h"
"${COMMON_SOURCE_DIR}/showmsg.h"
"${COMMON_SOURCE_DIR}/socket.h"
@ -92,7 +90,6 @@ set( COMMON_BASE_SOURCES
"${COMMON_SOURCE_DIR}/mapindex.c"
"${COMMON_SOURCE_DIR}/md5calc.c"
"${COMMON_SOURCE_DIR}/nullpo.c"
"${COMMON_SOURCE_DIR}/plugins.c"
"${COMMON_SOURCE_DIR}/random.c"
"${COMMON_SOURCE_DIR}/showmsg.c"
"${COMMON_SOURCE_DIR}/socket.c"

View File

@ -1,5 +1,5 @@
COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/plugins.o obj_all/lock.o \
COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/lock.o \
obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \
obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \
obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \

View File

@ -9,7 +9,6 @@
#include "../common/db.h"
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/plugins.h"
#endif
#include <stdio.h>
@ -288,10 +287,8 @@ int main (int argc, char **argv)
timer_init();
socket_init();
plugins_init();
do_init(argc,argv);
plugin_event_trigger(EVENT_ATHENA_INIT);
{// Main runtime cycle
int next;
@ -301,11 +298,9 @@ int main (int argc, char **argv)
}
}
plugin_event_trigger(EVENT_ATHENA_FINAL);
do_final();
timer_final();
plugins_final();
socket_final();
db_final();
#endif

View File

@ -1,86 +0,0 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
#include "../common/cbasetypes.h"
////// Plugin functions ///////////////
// Plugin version <major version>.<minor version>
// * <major version> is increased and <minor version> reset when at least one
// export of the previous version becomes incompatible
// * <minor version> is increased if the previous version remains compatible
//
// Compatible plugins have:
// - equal major version
// - lower or equal minor version
#define PLUGIN_VERSION "1.03"
typedef struct _Plugin_Info {
char* name;
char type;
char* version;
char* req_version;
char* description;
} Plugin_Info;
typedef struct _Plugin_Event_Table {
char* func_name;
char* event_name;
} Plugin_Event_Table;
// Format of the test function
typedef int Plugin_Test_Func(void);
#define EVENT_PLUGIN_INIT "Plugin_Init" // Initialize the plugin
#define EVENT_PLUGIN_FINAL "Plugin_Final" // Finalize the plugin
#define EVENT_ATHENA_INIT "Athena_Init" // Server started
#define EVENT_ATHENA_FINAL "Athena_Final" // Server ended
// Format of event functions
typedef void Plugin_Event_Func(void);
#define EVENT_PLUGIN_TEST "Plugin_Test" // Test the plugin for compatibility
////// Plugin Export functions /////////////
#define PLUGIN_ALL 0
#define PLUGIN_LOGIN 1
#define PLUGIN_CHAR 2
#define PLUGIN_MAP 8
#define PLUGIN_CORE 16
#define IMPORT_SYMBOL(s,n) SET_FUNCPOINTER((s), plugin_call_table[n])
#define SYMBOL_SERVER_TYPE 0
#define SYMBOL_SERVER_NAME 1
#define SYMBOL_ARG_C 2
#define SYMBOL_ARG_V 3
#define SYMBOL_RUNFLAG 4
#define SYMBOL_GETTICK 5
#define SYMBOL_GET_SVN_REVISION 6
#define SYMBOL_ADD_TIMER 7
#define SYMBOL_ADD_TIMER_INTERVAL 8
#define SYMBOL_ADD_TIMER_FUNC_LIST 9
#define SYMBOL_DELETE_TIMER 10
#define SYMBOL_GET_UPTIME 11
#define SYMBOL_ADDR 12
#define SYMBOL_FD_MAX 13
#define SYMBOL_SESSION 14
#define SYMBOL_DELETE_SESSION 15
#define SYMBOL_WFIFOSET 16
#define SYMBOL_RFIFOSKIP 17
#define SYMBOL_FUNC_PARSE_TABLE 18
// 1.03
#define SYMBOL_PARSE_CONSOLE 19
////// Global Plugin variables /////////////
#define PLUGIN_INFO struct _Plugin_Info plugin_info
#define PLUGIN_EVENTS_TABLE struct _Plugin_Event_Table plugin_event_table[]
#ifndef _PLUGINS_H_
void** plugin_call_table;
#endif
#endif /* _PLUGIN_H_ */

View File

@ -1,415 +0,0 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include "../common/mmo.h"
#include "../common/core.h"
#include "../common/timer.h"
#include "../common/utils.h" // findfile()
#include "../common/socket.h"
#include "../common/malloc.h"
#include "../common/showmsg.h"
#include "plugins.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#endif
//////////////////////////////////////////////
typedef struct _Plugin_Event {
struct _Plugin_Event* next;
Plugin_Event_Func* func;
} Plugin_Event;
typedef struct _Plugin_Event_List {
struct _Plugin_Event_List* next;
char* name;
struct _Plugin_Event* events;
} Plugin_Event_List;
static int auto_search = 0;
static int load_priority = 0;
Plugin_Event_List* event_head = NULL;
Plugin* plugin_head = NULL;
static Plugin_Info default_info = { "Unknown", PLUGIN_ALL, "0", PLUGIN_VERSION, "Unknown" };
void** plugin_call_table;
static size_t call_table_size = 0;
static size_t max_call_table = 0;
////// Plugin Events Functions //////////////////
int register_plugin_func(char* name)
{
Plugin_Event_List* evl;
if( name ){
//ShowDebug("register_plugin_func(%s)\n", name);
CREATE(evl, Plugin_Event_List, 1);
evl->next = event_head;
evl->name = aStrdup(name);
evl->events = NULL;
event_head = evl;
}
return 0;
}
static Plugin_Event_List* search_plugin_func(char* name)
{
Plugin_Event_List* evl = event_head;
while( evl ){
if( strcmpi(evl->name,name) == 0 )
return evl;
evl = evl->next;
}
return NULL;
}
int register_plugin_event(Plugin_Event_Func* func, char* name)
{
Plugin_Event_List* evl = search_plugin_func(name);
//ShowDebug("register_plugin_event(0x%x, %s)\n", func, name);
if( !evl )
{// event does not exist, register
register_plugin_func(name);
// get the new event list
evl = search_plugin_func(name);
}
if( evl ){
Plugin_Event* ev;
CREATE(ev, Plugin_Event, 1);
ev->func = func;
ev->next = NULL;
// insert event at the end of the linked list
if( evl->events == NULL )
evl->events = ev;
else {
Plugin_Event* last_ev = evl->events;
while( last_ev ){
if( last_ev->next == NULL ){
last_ev->next = ev;
break;
}
last_ev = last_ev->next;
}
}
}
return 0;
}
int plugin_event_trigger(char* name)
{
int c = 0;
Plugin_Event_List* evl = search_plugin_func(name);
//ShowDebug("plugin_event_trigger(%s)\n", name);
if( evl ){
Plugin_Event* ev = evl->events;
while( ev ){
ev->func();
//ShowDebug("plugin_event_trigger: Executing function 0x%x.\n", ev->func);
ev = ev->next;
++c;
}
}
return c;
}
////// Plugins Call Table Functions /////////
int export_symbol(void* var, size_t offset)
{
//ShowDebug("export_symbol(0x%x,%d)\n", var,offset);
// add to the end of the list
if( offset < 0 )
offset = call_table_size;
if( offset >= max_call_table )
{// realloc if not large enough
max_call_table = 1 + offset;
RECREATE(plugin_call_table, void*, max_call_table);
// clear the new alloced block
memset(plugin_call_table + call_table_size, 0, (max_call_table-call_table_size)*sizeof(void*));
}
// the new table size is delimited by the new element at the end
if( offset >= call_table_size )
call_table_size = offset+1;
// put the pointer at the selected place
plugin_call_table[offset] = var;
return 0;
}
////// Plugins Core /////////////////////////
static int plugin_iscompatible(char* version)
{
int req_major = 0;
int req_minor = 0;
int major = 0;
int minor = 0;
if( version == NULL )
return 0;
sscanf(version, "%d.%d", &req_major, &req_minor);
sscanf(PLUGIN_VERSION, "%d.%d", &major, &minor);
return ( req_major == major && req_minor <= minor );
}
Plugin* plugin_open(const char* filename)
{
Plugin* plugin;
Plugin_Info* info;
Plugin_Event_Table* events;
void** procs;
int init_flag = 1;
//ShowDebug("plugin_open(%s)\n", filename);
// Check if the plugin has been loaded before
plugin = plugin_head;
while (plugin) {
// returns handle to the already loaded plugin
if( plugin->state && strcmpi(plugin->filename, filename) == 0 ){
ShowWarning("plugin_open: not loaded (duplicate) : '"CL_WHITE"%s"CL_RESET"'\n", filename);
return plugin;
}
plugin = plugin->next;
}
CREATE(plugin, Plugin, 1);
plugin->state = -1; // not loaded
plugin->dll = DLL_OPEN(filename);
if( !plugin->dll ){
ShowWarning("plugin_open: not loaded (invalid file) : '"CL_WHITE"%s"CL_RESET"'\n", filename);
plugin_unload(plugin);
return NULL;
}
// Retrieve plugin information
plugin->state = 0; // initialising
info = (Plugin_Info*)DLL_SYM(plugin->dll, "plugin_info");
// For high priority plugins (those that are explicitly loaded from the conf file)
// we'll ignore them even (could be a 3rd party dll file)
if( !info )
{// foreign plugin
//ShowDebug("plugin_open: plugin_info not found\n");
if( load_priority == 0 )
{// not requested
//ShowDebug("plugin_open: not loaded (not requested) : '"CL_WHITE"%s"CL_RESET"'\n", filename);
plugin_unload(plugin);
return NULL;
}
} else if( !plugin_iscompatible(info->req_version) )
{// incompatible version
ShowWarning("plugin_open: not loaded (incompatible version '%s' -> '%s') : '"CL_WHITE"%s"CL_RESET"'\n", info->req_version, PLUGIN_VERSION, filename);
plugin_unload(plugin);
return NULL;
} else if( (info->type != PLUGIN_ALL && info->type != PLUGIN_CORE && info->type != SERVER_TYPE) ||
(info->type == PLUGIN_CORE && SERVER_TYPE != PLUGIN_LOGIN && SERVER_TYPE != PLUGIN_CHAR && SERVER_TYPE != PLUGIN_MAP) )
{// not for this server
//ShowDebug("plugin_open: not loaded (incompatible) : '"CL_WHITE"%s"CL_RESET"'\n", filename);
plugin_unload(plugin);
return NULL;
}
plugin->info = ( info != NULL ? info : &default_info );
plugin->filename = aStrdup(filename);
// Initialise plugin call table (For exporting procedures)
procs = (void**)DLL_SYM(plugin->dll, "plugin_call_table");
if( procs )
*procs = plugin_call_table;
//else ShowDebug("plugin_open: plugin_call_table not found\n");
// Register plugin events
events = (Plugin_Event_Table*)DLL_SYM(plugin->dll, "plugin_event_table");
if( events ){
int i = 0;
//ShowDebug("plugin_open: parsing plugin_event_table\n");
while( events[i].func_name ){
if( strcmpi(events[i].event_name, EVENT_PLUGIN_TEST) == 0 ){
Plugin_Test_Func* test_func;
test_func = (Plugin_Test_Func*)DLL_SYM(plugin->dll, events[i].func_name);
//ShowDebug("plugin_open: invoking "EVENT_PLUGIN_TEST" with %s()\n", events[i].func_name);
if( test_func && test_func() == 0 ){
// plugin has failed test, disabling
//ShowDebug("plugin_open: disabled (failed test) : %s\n", filename);
init_flag = 0;
}
} else {
Plugin_Event_Func* func;
func = (Plugin_Event_Func*)DLL_SYM(plugin->dll, events[i].func_name);
if (func)
register_plugin_event(func, events[i].event_name);
else
ShowError("Failed to locate function '%s' in '%s'.\n", events[i].func_name, filename);
}
i++;
}
}
//else ShowDebug("plugin_open: plugin_event_table not found\n");
plugin->next = plugin_head;
plugin_head = plugin;
plugin->state = init_flag; // fully loaded
ShowStatus("Done loading plugin '"CL_WHITE"%s"CL_RESET"'\n", (info) ? plugin->info->name : filename);
return plugin;
}
void plugin_load(const char* filename)
{
plugin_open(filename);
}
void plugin_unload(Plugin* plugin)
{
if( plugin == NULL )
return;
if( plugin->filename )
aFree(plugin->filename);
if( plugin->dll )
DLL_CLOSE(plugin->dll);
aFree(plugin);
}
#ifdef WIN32
char *DLL_ERROR(void)
{
static char dllbuf[80];
DWORD dw = GetLastError();
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, 0, dllbuf, 80, NULL);
return dllbuf;
}
#endif
////// Initialize/Finalize ////////////////////
static int plugins_config_read(const char *cfgName)
{
char line[1024], w1[1024], w2[1024];
FILE *fp;
fp = fopen(cfgName, "r");
if( fp == NULL ){
ShowError("File not found: %s\n", cfgName);
return 1;
}
while( fgets(line, sizeof(line), fp) )
{
if( line[0] == '/' && line[1] == '/' )
continue;
if( sscanf(line,"%[^:]: %[^\r\n]",w1,w2) != 2 )
continue;
if( strcmpi(w1,"auto_search") == 0 ){
if( strcmpi(w2,"yes") == 0 )
auto_search = 1;
else if( strcmpi(w2,"no") == 0 )
auto_search = 0;
else
auto_search = atoi(w2);
} else if( strcmpi(w1,"plugin") == 0 ){
char filename[128];
sprintf(filename, "plugins/%s%s", w2, DLL_EXT);
plugin_load(filename);
} else if( strcmpi(w1,"import") == 0 )
plugins_config_read(w2);
else
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
}
fclose(fp);
return 0;
}
void plugins_init(void)
{
// Sugested functionality:
// add atcommands/script commands (Borf)
char* PLUGIN_CONF_FILENAME = "conf/plugin_athena.conf";
//ShowDebug("plugins_init()\n");
register_plugin_func(EVENT_PLUGIN_INIT);
register_plugin_func(EVENT_PLUGIN_FINAL);
register_plugin_func(EVENT_ATHENA_INIT);
register_plugin_func(EVENT_ATHENA_FINAL);
// networking
EXPORT_SYMBOL(RFIFOSKIP, SYMBOL_RFIFOSKIP);
EXPORT_SYMBOL(WFIFOSET, SYMBOL_WFIFOSET);
EXPORT_SYMBOL(do_close, SYMBOL_DELETE_SESSION);
EXPORT_SYMBOL(session, SYMBOL_SESSION);
EXPORT_SYMBOL(&fd_max, SYMBOL_FD_MAX);
EXPORT_SYMBOL(addr_, SYMBOL_ADDR);
// timers
EXPORT_SYMBOL(get_uptime, SYMBOL_GET_UPTIME);
EXPORT_SYMBOL(delete_timer, SYMBOL_DELETE_TIMER);
EXPORT_SYMBOL(add_timer_func_list, SYMBOL_ADD_TIMER_FUNC_LIST);
EXPORT_SYMBOL(add_timer_interval, SYMBOL_ADD_TIMER_INTERVAL);
EXPORT_SYMBOL(add_timer, SYMBOL_ADD_TIMER);
EXPORT_SYMBOL((void*)get_svn_revision, SYMBOL_GET_SVN_REVISION);
EXPORT_SYMBOL(gettick, SYMBOL_GETTICK);
// core
EXPORT_SYMBOL(parse_console, SYMBOL_PARSE_CONSOLE);
EXPORT_SYMBOL(&runflag, SYMBOL_RUNFLAG);
EXPORT_SYMBOL(arg_v, SYMBOL_ARG_V);
EXPORT_SYMBOL(&arg_c, SYMBOL_ARG_C);
EXPORT_SYMBOL(SERVER_NAME, SYMBOL_SERVER_NAME);
EXPORT_SYMBOL(&SERVER_TYPE, SYMBOL_SERVER_TYPE);
load_priority = 1;
plugins_config_read(PLUGIN_CONF_FILENAME);
load_priority = 0;
if( auto_search )
findfile("plugins", DLL_EXT, plugin_load);
plugin_event_trigger(EVENT_PLUGIN_INIT);
return;
}
void plugins_final(void)
{
Plugin* plugin = plugin_head;
Plugin* next_plugin;
Plugin_Event_List* evl = event_head;
Plugin_Event_List* next_evl;
Plugin_Event* ev;
Plugin_Event* next_ev;
//ShowDebug("plugins_final()\n");
plugin_event_trigger(EVENT_PLUGIN_FINAL);
while( plugin ){
next_plugin = plugin->next;
plugin_unload(plugin);
plugin = next_plugin;
}
while( evl ){
ev = evl->events;
while( ev ){
next_ev = ev->next;
aFree(ev);
ev = next_ev;
}
next_evl = evl->next;
aFree(evl->name);
aFree(evl);
evl = next_evl;
}
aFree(plugin_call_table);
return;
}

View File

@ -1,69 +0,0 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#ifndef _PLUGINS_H_
#define _PLUGINS_H_
#include "../common/cbasetypes.h"
#include "../common/plugin.h"
////// Dynamic Link Library functions ///////////////
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define DLL_OPEN(x) LoadLibraryA(x)
#define DLL_SYM(x,y) GetProcAddress(x,y)
#define DLL_CLOSE(x) FreeLibrary(x)
char *DLL_ERROR(void);
#define DLL_EXT ".dll"
#define DLL HINSTANCE
#else
#include <dlfcn.h>
#define DLL_OPEN(x) dlopen(x,RTLD_NOW)
#define DLL_SYM(x,y) dlsym(x,y)
#define DLL_CLOSE(x) dlclose(x)
#define DLL_ERROR dlerror
#ifdef CYGWIN
#define DLL_EXT ".dll"
#else
#define DLL_EXT ".so"
#endif
#define DLL void *
#include <string.h> // size_t
#endif
////// Plugin Definitions ///////////////////
typedef struct _Plugin {
DLL dll;
char state;
char* filename;
struct _Plugin_Info* info;
struct _Plugin* next;
} Plugin;
/////////////////////////////////////////////
int register_plugin_func(char* name);
int register_plugin_event(Plugin_Event_Func* func, char* name);
int plugin_event_trigger(char* name);
int export_symbol(void* var, size_t offset);
#define EXPORT_SYMBOL(s,o) export_symbol((void*)(s),(o));
#define EXPORT_SYMBOL2(s) EXPORT_SYMBOL((s), -1);
Plugin* plugin_open(const char* filename);
void plugin_load(const char* filename);
void plugin_unload(Plugin* plugin);
void plugins_init(void);
void plugins_final(void);
#endif /* _PLUGINS_H_ */

View File

@ -1,174 +0,0 @@
#
# setup
#
get_property( CAN_BUILD_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS )
if( NOT CAN_BUILD_SHARED_LIBS )
return()
endif()
#
# console
#
option( BUILD_PLUGIN_console "build console plugin" OFF )
if( BUILD_PLUGIN_console )
message( STATUS "Creating target console" )
set( CONSOLE_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/console.c"
"${CMAKE_CURRENT_SOURCE_DIR}/console.def"
)
set( LIBRARIES ${GLOBAL_LIBRARIES} )
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
set( SOURCE_FILES ${CONSOLE_SOURCES} )
source_group( console FILES ${CONSOLE_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
add_library( console SHARED ${SOURCE_FILES} )
target_link_libraries( console ${LIBRARIES} )
set_target_properties( console PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
set_target_properties( console PROPERTIES PREFIX "" )
if( INSTALL_COMPONENT_RUNTIME )
cpack_add_component( Runtime_console DESCRIPTION "console plugin" DISPLAY_NAME "console" GROUP Runtime )
install( TARGETS console
DESTINATION "plugins"
COMPONENT Runtime_console )
endif( INSTALL_COMPONENT_RUNTIME )
set( TARGET_LIST ${TARGET_LIST} console CACHE INTERNAL "" )
message( STATUS "Creating target console - done" )
endif( BUILD_PLUGIN_console )
#
# dbghelpplug
#
if( WIN32 )
find_path( HAVE_DBGHELP_H dbghelp.h )
mark_as_advanced( HAVE_DBGHELP_H )
if( HAVE_DBGHELP_H )
option( BUILD_PLUGIN_dbghelpplug "build dbghelpplug plugin" OFF )
endif()
endif()
if( NOT DEFINED BUILD_PLUGIN_dbghelpplug )
message( STATUS "Disabled dbghelpplug plugin target (requires WIN32 and HAVE_DBGHELP_H)" )
endif()
if( BUILD_PLUGIN_dbghelpplug )
message( STATUS "Creating target dbghelpplug" )
set( DBGHELPPLUG_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/dbghelpplug.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dbghelpplug.rc"
)
set( LIBRARIES ${GLOBAL_LIBRARIES} )
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
set( SOURCE_FILES ${DBGHELPPLUG_SOURCES} )
source_group( dbghelpplug FILES ${DBGHELPPLUG_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
add_library( dbghelpplug SHARED ${SOURCE_FILES} )
target_link_libraries( dbghelpplug ${LIBRARIES} )
set_target_properties( dbghelpplug PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
set_target_properties( dbghelpplug PROPERTIES PREFIX "" )
if( INSTALL_COMPONENT_RUNTIME )
cpack_add_component( Runtime_dbghelpplug DESCRIPTION "dbghelpplug plugin" DISPLAY_NAME "dbghelpplug" GROUP Runtime )
install( TARGETS dbghelpplug
DESTINATION "plugins"
COMPONENT Runtime_dbghelpplug )
endif( INSTALL_COMPONENT_RUNTIME )
set( TARGET_LIST ${TARGET_LIST} dbghelpplug CACHE INTERNAL "" )
message( STATUS "Creating target dbghelpplug - done" )
endif( BUILD_PLUGIN_dbghelpplug )
#
# pid
#
if( WIN32 OR HAVE_GETPID )
option( BUILD_PLUGIN_pid "build pid plugin" OFF )
else()
message( STATUS "Disabled pid plugin target (requires WIN32 or HAVE_GETPID)" )
endif()
if( BUILD_PLUGIN_pid )
message( STATUS "Creating target pid" )
set( PID_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/pid.c"
"${CMAKE_CURRENT_SOURCE_DIR}/pid.def"
)
set( LIBRARIES ${GLOBAL_LIBRARIES} )
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
set( SOURCE_FILES ${PID_SOURCES} )
source_group( pid FILES ${PID_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
add_library( pid SHARED ${SOURCE_FILES} )
target_link_libraries( pid ${LIBRARIES} )
set_target_properties( pid PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
set_target_properties( pid PROPERTIES PREFIX "" )
if( INSTALL_COMPONENT_RUNTIME )
cpack_add_component( Runtime_pid DESCRIPTION "pid plugin" DISPLAY_NAME "pid" GROUP Runtime )
install( TARGETS pid
DESTINATION "plugins"
COMPONENT Runtime_pid )
endif( INSTALL_COMPONENT_RUNTIME )
set( TARGET_LIST ${TARGET_LIST} pid CACHE INTERNAL "" )
message( STATUS "Creating target pid - done" )
endif( BUILD_PLUGIN_pid )
#
# sample
#
option( BUILD_PLUGIN_sample "build sample plugin" OFF )
if( BUILD_PLUGIN_sample )
message( STATUS "Creating target sample" )
set( SAMPLE_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/sample.c"
"${CMAKE_CURRENT_SOURCE_DIR}/sample.def"
)
set( LIBRARIES ${GLOBAL_LIBRARIES} )
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
set( SOURCE_FILES ${SAMPLE_SOURCES} )
source_group( sample FILES ${SAMPLE_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
add_library( sample SHARED ${SOURCE_FILES} )
target_link_libraries( sample ${LIBRARIES} )
set_target_properties( sample PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
set_target_properties( sample PROPERTIES PREFIX "" )
if( INSTALL_COMPONENT_RUNTIME )
cpack_add_component( Runtime_sample DESCRIPTION "sample plugin" DISPLAY_NAME "sample" GROUP Runtime )
install( TARGETS sample
DESTINATION "plugins"
COMPONENT Runtime_sample )
endif( INSTALL_COMPONENT_RUNTIME )
set( TARGET_LIST ${TARGET_LIST} sample CACHE INTERNAL "" )
message( STATUS "Creating target sample - done" )
endif( BUILD_PLUGIN_sample )
#
# sig
#
option( BUILD_PLUGIN_sig "build sig plugin" OFF )
if( BUILD_PLUGIN_sig )
message( STATUS "Creating target sig" )
set( SIG_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/sig.c"
)
set( LIBRARIES ${GLOBAL_LIBRARIES} )
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
set( DEFINITIONS "${GLOBAL_DEFINITIONS} -DNO_MEMMGR" )
set( SOURCE_FILES ${SIG_SOURCES} )
source_group( sig FILES ${SIG_SOURCES} )
include_directories( ${INCLUDE_DIRS} )
add_library( sig SHARED ${SOURCE_FILES} )
target_link_libraries( sig ${LIBRARIES} )
set_target_properties( sig PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
set_target_properties( sig PROPERTIES PREFIX "" )
if( INSTALL_COMPONENT_RUNTIME )
cpack_add_component( Runtime_sig DESCRIPTION "sig plugin" DISPLAY_NAME "sig" GROUP Runtime )
install( TARGETS sig
DESTINATION "plugins"
COMPONENT Runtime_sig )
endif( INSTALL_COMPONENT_RUNTIME )
set( TARGET_LIST ${TARGET_LIST} sig CACHE INTERNAL "" )
message( STATUS "Creating target sig - done" )
endif( BUILD_PLUGIN_sig )

View File

@ -1,54 +0,0 @@
COMMON_OBJ = ../common/obj_all/showmsg.o ../common/obj_all/utils.o ../common/obj_all/strlib.o \
../common/obj_all/minimalloc.o
COMMON_H = ../common/plugin.h ../common/cbasetypes.h \
../common/showmsg.h ../common/utils.h ../common/strlib.h \
../common/malloc.h
PLUGINS = sample sig pid console
@SET_MAKE@
#####################################################################
.PHONY : all $(PLUGINS) clean help
all: $(PLUGINS)
sample: sample@DLLEXT@
sig: sig@DLLEXT@
pid: pid@DLLEXT@
console: console@DLLEXT@
clean:
@echo " CLEAN plugins"
@rm -rf *.o
help:
@echo "possible targets are $(PLUGINS:%='%') 'all' 'clean' 'help'"
@echo "'sample' - sample plugin"
@echo "'sig' - signal handler plugin"
@echo "'pid' - process id plugin"
@echo "'console' - console plugin"
@echo "'all' - builds all above targets"
@echo "'clean' - cleans builds and objects"
@echo "'help' - outputs this message"
#####################################################################
%@DLLEXT@: %.c
@echo " CC $<"
@@CC@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ -shared -o ../../plugins/$@ $<
sig@DLLEXT@: sig.c $(COMMON_OBJ)
@echo " CC $<"
@@CC@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ -shared -o ../../plugins/$@ $< $(COMMON_OBJ)
# missing common object files
../common/obj_all/%.o: ../common/%.c $(COMMON_H)
@$(MAKE) -C ../common txt
../common/obj_all/mini%.o: ../common/%.c $(COMMON_H)
@$(MAKE) -C ../common txt

View File

@ -1,496 +0,0 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include "../common/plugin.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#define __USE_XOPEN
#include <sys/types.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
#endif
#include <stdio.h> // stdin, fgets
#define INPUT_BUFSIZE 4096
#define INPUT_INVALID 0
#define INPUT_READY 1
#define INPUT_WAITING 2
#define INPUT_READING 3
#define INPUT_CLOSED 4
//////////////////////////////
#ifdef WIN32
//////////////////////////////
// In windows the worker is a thread so it can access the same variables.
#define WORKER_FUNC_DECLARE(name) DWORD WINAPI worker_ ## name(LPVOID lpParameter)
#define WORKER_FUNC_START(name) DWORD WINAPI worker_ ## name(LPVOID lpParameter) { (void)lpParameter; {
#define WORKER_FUNC_END(name) } ExitThread(0); return 0; }
#define WORKER_EXECUTE(name,errvar) \
do{ \
DWORD dwThreadId; \
buf.worker = CreateThread(NULL, 0, worker_ ## name, NULL, CREATE_SUSPENDED, &dwThreadId); \
*(errvar) = ( buf.worker == NULL ); \
}while(0)
/// Buffer for asynchronous input
typedef struct _buffer {
char arr[INPUT_BUFSIZE];
size_t len;
HANDLE worker;
HANDLE state_mux; // mutex for the state
char state;
} BUFFER;
//////////////////////////////
#else
//////////////////////////////
/// In linux the worker is a process so it needs to comunicate through pipes.
#define WORKER_FUNC_DECLARE(name) void worker_ ## name(void)
#define WORKER_FUNC_START(name) void worker_ ## name(void) {
#define WORKER_FUNC_END(name) _exit(0); }
#define WORKER_EXECUTE(name,errvar) \
do{ \
int pid = fork(); \
if( pid == 0 ){ \
worker_ ## name(); \
} \
*(errvar) = (pid == -1); \
}while(0)
#define PIPE_READ 0
#define PIPE_WRITE 1
/// Buffer for asynchronous input
typedef struct _buffer {
char arr[INPUT_BUFSIZE];
size_t len;
int data_pipe[2]; // pipe to receive data
int state_pipe[2]; // pipe to send state
char state;
unsigned close_unused_flag : 1;
} BUFFER;
//////////////////////////////
#endif
//////////////////////////////
////// Plugin information ////////
PLUGIN_INFO = {
"Console", // Name
PLUGIN_ALL, // Target servers
"0.1", // Version
"1.03", // Minimum plugin engine version to run
"Console parser" // Short description
};
////// Plugin event list //////////
// Format: <plugin function>,<event name>
// All registered functions to a event gets executed
// (In descending order) when its called.
// Multiple functions can be called by multiple events too,
// So it's up to your creativity ^^
//
PLUGIN_EVENTS_TABLE = {
{ "console_init", EVENT_PLUGIN_INIT },
{ "console_final", EVENT_PLUGIN_FINAL },
{ "console_autostart", EVENT_ATHENA_INIT },
//{ "console_start", EVENT_CONSOLE_START },//## add these events to the plugins framework
//{ "console_stop", EVENT_CONSOLE_STOP },
{ "console_stop", EVENT_ATHENA_FINAL },
{ NULL, NULL }
};
///// Variables /////
// Imported functions
typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data);
int (*add_timer_func_list)(TimerFunc func, char* name);
int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval);
int (*delete_timer)(int tid, TimerFunc func);
unsigned int (*gettick)(void);
int (*parse_console)(const char* buf);
// Locals
int tid = -1; // timer id
BUFFER buf; // input buffer
WORKER_FUNC_DECLARE(getinput); // worker for the input buffer
//////// Asynchronous input functions //////////
//////////////////////////////
#ifdef WIN32
//////////////////////////////
//
// --=== Asynchronous console input ===--
//
// On windows a thread is used (both threads have access to the same data).
// The worker threads starts suspended and is resumed when data is required.
// After getting the data, the worker thread updates the state variable and
// suspends itself.
//
// A mutex is used to synchronize access to the state variable between the
// threads. Access and updates to state are probably already atomic so the
// mutex shouldn't be needed, but using it is more correct so it stays.
//
// Note: The Worker thread only starts to get input data when further data is
// requested. This is a design choise and brings no real advantage or
// disadvantage I can think of.
//
/// Returns the state of the input
char input_getstate()
{
char state;
WaitForSingleObject(buf.state_mux, INFINITE);
state = buf.state;
ReleaseMutex(buf.state_mux);
return state;
}
/// Sets the state of the input
void input_setstate(char state)
{
char oldstate;
// update state
WaitForSingleObject(buf.state_mux, INFINITE);
oldstate = buf.state;
buf.state = state;
ReleaseMutex(buf.state_mux);
if( state == INPUT_READY && oldstate == INPUT_READING )
{// data has become available
SuspendThread(buf.worker);
} else if( state == INPUT_WAITING )
{// input is waiting for data
ResumeThread(buf.worker);
//} else if( state == INPUT_READING )
//{// worker is reading data
} else if( state == INPUT_CLOSED )
{// end the input
CloseHandle(buf.state_mux);
TerminateThread(buf.worker, 0);
}
}
/// Gets the next state of the input
#define input_nextstate() input_getstate()
/// Returns if data is available from asynchronous input.
/// Requests data if none is available.
int input_hasdata(void)
{
if( input_getstate() == INPUT_READY )
{// buffer is ready
if( buf.len > 0 )
return 1; // data found ;)
// request data from the worker
input_setstate(INPUT_WAITING);
}
return 0; // no data
}
/// Initialize asynchronous input
int input_init(void)
{
int err = 0;
memset(&buf, 0, sizeof(buf));
buf.state_mux = CreateMutex(NULL, FALSE, NULL);
if( buf.state_mux == NULL )
{// failed to create state mutex
return 1;
}
buf.len = 0;
input_setstate(INPUT_READY);
WORKER_EXECUTE(getinput, &err);
if( err )
{// failed to start worker
input_setstate(INPUT_CLOSED);
}
return err;
}
/// Finalize asynchronous input
int input_final(void)
{
input_setstate(INPUT_CLOSED);
return 0;
}
//////////////////////////////
#else
//////////////////////////////
//
// --=== Asynchronous console input ===--
//
// On the other systems a process is used and pipes are used to comunicate.
// The worker process receives status updates through one of the pipes either
// requesting data or ending the worker.
// The other pipe is used by the worker to send the input data and is checked
// for data by the main thread in the timer function.
//
// Note: The Worker thread only starts to get input data when further data is
// requested. This is a design choise and brings no real advantage or
// disadvantage I can think of.
//
/// Returns the state of the input
#define input_getstate() buf.state
/// Sets the state of the input
void input_setstate(char state) {
size_t fileReadCount = 0;
if( state == INPUT_READY && input_getstate() == INPUT_READING ) {// send data from the worker to the main process
fileReadCount = write(buf.data_pipe[PIPE_WRITE], &buf.len, sizeof(buf.len));
fileReadCount = write(buf.data_pipe[PIPE_WRITE], &buf.arr, buf.len);
} else if( state == INPUT_WAITING ) {
if( buf.close_unused_flag == 0 ) {// close unused pipe sides in the main process
close(buf.data_pipe[PIPE_WRITE]);
close(buf.state_pipe[PIPE_READ]);
buf.close_unused_flag = 1;
}
// send the next state
fileReadCount = write(buf.state_pipe[PIPE_WRITE], &state, sizeof(state));
} else if( state == INPUT_READING ) {
if( buf.close_unused_flag == 0 ) {// close unused pipe sides in the worker process
close(buf.data_pipe[PIPE_READ]);
close(buf.state_pipe[PIPE_WRITE]);
buf.close_unused_flag = 1;
}
} else if( state == INPUT_CLOSED ) {// send next state to the worker and close the pipes
fileReadCount = write(buf.state_pipe[PIPE_WRITE], &state, sizeof(state));
close(buf.data_pipe[PIPE_WRITE]);
close(buf.data_pipe[PIPE_READ]);
close(buf.state_pipe[PIPE_WRITE]);
close(buf.state_pipe[PIPE_READ]);
}
buf.state = state;
}
/// Waits for the next state of the input
char input_nextstate()
{
char state = INPUT_CLOSED;
int bytes = 0;
while( bytes == 0 )
bytes = read(buf.state_pipe[PIPE_READ], &state, sizeof(state));
if( bytes == -1 )
{// error, terminate worker
input_setstate(INPUT_CLOSED);
}
return state;
}
/// Returns if data is available from asynchronous input.
/// If data is available, it's put in the local buffer.
int input_hasdata()
{
struct pollfd fds;
int hasData;
size_t fileReadCount;
if( input_getstate() == INPUT_READY ) {// start getting data
input_setstate(INPUT_WAITING);
return 0;
}
// check if data is available
fds.fd = buf.data_pipe[PIPE_READ];
fds.events = POLLRDNORM;
hasData = ( poll(&fds,1,0) > 0 );
if( hasData ) {// read the data from the pipe
fileReadCount = read(buf.data_pipe[PIPE_READ], &buf.len, sizeof(buf.len));
fileReadCount = read(buf.data_pipe[PIPE_READ], buf.arr, buf.len);
input_setstate(INPUT_READY);
}
return hasData;
}
/// Initialize asynchronous input
int input_init(void)
{
int err = 0;
memset(&buf, 0, sizeof(buf));
if( pipe(buf.data_pipe) )
{// error creating data pipe
return 1;
}
if( pipe(buf.state_pipe) )
{// error creating state pipe
close(buf.data_pipe[PIPE_READ]);
close(buf.data_pipe[PIPE_WRITE]);
return 1;
}
buf.len = 0;
input_setstate(INPUT_READY);
WORKER_EXECUTE(getinput, &err);
if( err ){
//printf("input_init failed to start worker (%d)\n", err);
input_setstate(INPUT_CLOSED);
}
return err;
}
/// Finalize asynchronous input
int input_final(void)
{
close(buf.data_pipe[PIPE_READ]);
close(buf.data_pipe[PIPE_WRITE]);
close(buf.state_pipe[PIPE_READ]);
close(buf.state_pipe[PIPE_WRITE]);
return 0;
}
//////////////////////////////
#endif
//////////////////////////////
/// Returns the input data array
#define input_getdata() buf.arr
/// Returns the input data length
#define input_getlen() buf.len
/// Clear the input data
#define input_clear() ( buf.len = 0 )
/// Worker thread/process that gets input
WORKER_FUNC_START(getinput)
while( input_nextstate() != INPUT_CLOSED )
{// get input
input_setstate(INPUT_READING);
buf.arr[0] = '\0';
if( fgets(buf.arr, INPUT_BUFSIZE, stdin) != NULL )
buf.len = strlen(buf.arr);
input_setstate(INPUT_READY);
}
WORKER_FUNC_END(getinput)
//////// Plugin console functions //////////
/// Timer function that checks if there's assynchronous input data and feeds parse_console()
/// The input reads one line at a time and line terminators are removed.
int console_getinputtimer(int tid, unsigned int tick, int id, intptr_t data)
{
char* cmd;
size_t len;
if( input_hasdata() ){
// get data (removes line terminators)
cmd = input_getdata();
len = input_getlen();
while( len > 0 && (cmd[len-1] == '\r' || cmd[len-1] == '\n') )
cmd[--len] = '\0';
// parse data
parse_console(cmd);
input_clear();
}
return 0;
}
/// Start the console
void console_start(void)
{
if( input_init() ){
return;
}
//##TODO add a 'startupcmd' config options
//parse_console("help");
add_timer_func_list(console_getinputtimer,"console_getinputtimer");
tid = add_timer_interval(gettick(),console_getinputtimer,0,0,250);//##TODO add a 'timerperiod' config option
}
void console_autostart(void)
{//##TODO add an 'autostart' config option
console_start();
}
/// Stop the console
void console_stop(void)
{
if( tid != -1 ){
delete_timer(tid, console_getinputtimer);
input_final();
}
return;
}
/// Test the console for compatibility
int console_test(void)
{// always compatible at the moment, maybe test if standard input is available?
return 1;
}
/// Initialize the console
void console_init(void)
{
// import symbols
IMPORT_SYMBOL(add_timer_interval, SYMBOL_ADD_TIMER_INTERVAL);
IMPORT_SYMBOL(add_timer_func_list, SYMBOL_ADD_TIMER_FUNC_LIST);
IMPORT_SYMBOL(delete_timer, SYMBOL_DELETE_TIMER);
IMPORT_SYMBOL(gettick, SYMBOL_GETTICK);
IMPORT_SYMBOL(parse_console, SYMBOL_PARSE_CONSOLE);
//printf("%d -> add_timer_func_list=0x%x\n", SYMBOL_ADD_TIMER_FUNC_LIST, (int)add_timer_func_list);
//printf("%d -> add_timer_interval=0x%x\n", SYMBOL_ADD_TIMER_INTERVAL, (int)add_timer_interval);
//printf("%d -> delete_timer=0x%x\n", SYMBOL_DELETE_TIMER, (int)delete_timer);
//printf("%d -> gettick=0x%x\n", SYMBOL_GETTICK, (int)gettick);
//printf("%d -> parse_console=0x%x\n", SYMBOL_PARSE_CONSOLE, (int)parse_console);
}
/// Finalize the console
void console_final(void)
{
}

View File

@ -1,13 +0,0 @@
EXPORTS
; common exports
plugin_info DATA
plugin_event_table DATA
plugin_call_table DATA
; console-specific exports
console_init
console_final
console_test
console_autostart
console_start
console_stop

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +0,0 @@
// BC++ has all the necessary preprocessor macros defined automatically
#if !defined(__BORLANDC__)
#include "winres.h"
#endif // !defined(__BORLANDC__)
#define VER_FILEVERSION 1,0,0,2
#define VER_FILEVERSION_STR "1.0.0.2\0"
#define VER_PRODUCTVERSION 1,0,0,2
#define VER_PRODUCTVERSION_STR "1.0.0.2\0"
#if defined(DEBUG) || defined(_DEBUG)
#define VER_DEBUG 0
#else
#define VER_DEBUG VS_FF_DEBUG
#endif
#define VER_COMMENTS_STR "Registers as the unhandled exception handler. Generates reports and minidumps.\0"
#define VER_COMPANYNAME_STR "eAthena\0"
#define VER_FILEDESCRIPTION_STR "Stackdump Plugin by eAthena\0"
#define VER_INTERNALNAME_STR "dbghelpplug\0"
#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 2008\0"
#define VER_ORIGINALFILENAME_STR "dbghelpplug.dll\0"
#define VER_PRODUCTNAME_STR "dbghelpplug\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS VER_DEBUG
FILEOS (VOS_NT|VOS__WINDOWS32)
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "Comments", VER_COMMENTS_STR
VALUE "CompanyName", VER_COMPANYNAME_STR
VALUE "FileDescription", VER_FILEDESCRIPTION_STR
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", VER_INTERNALNAME_STR
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
VALUE "ProductName", VER_PRODUCTNAME_STR
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END

View File

@ -1,53 +0,0 @@
#include <stdio.h>
#include <string.h>
#if !defined _WIN32 || defined MINGW
#include <unistd.h> // getpid(), unlink()
#else
#include <windows.h>
#define getpid GetCurrentProcessId
#endif
#include "../common/plugin.h"
PLUGIN_INFO = {
"ProcessId",
PLUGIN_ALL,
"1.0",
PLUGIN_VERSION,
"Logs the process ID"
};
PLUGIN_EVENTS_TABLE = {
{ "pid_create", "Plugin_Init" },
{ "pid_delete", "Plugin_Final" },
{ NULL, NULL }
};
char pid_file[256];
char *server_name;
void pid_create ()
{
FILE *fp;
int len;
IMPORT_SYMBOL(server_name, 1);
len = strlen(server_name);
strcpy(pid_file, server_name);
if(len > 4 && pid_file[len - 4] == '.') {
pid_file[len - 4] = 0;
}
strcat(pid_file, ".pid");
fp = fopen(pid_file, "w");
if (fp) {
fprintf(fp, "%d", getpid());
fclose(fp);
}
}
void pid_delete ()
{
unlink(pid_file);
}

View File

@ -1,7 +0,0 @@
EXPORTS
plugin_info DATA
plugin_event_table DATA
plugin_call_table DATA
pid_create
pid_delete

View File

@ -1,77 +0,0 @@
// Sample Athena plugin
#include <stdio.h>
#include <string.h>
#include "../common/plugin.h"
////// Plugin information ////////
//
PLUGIN_INFO = {
// change only the following area
"Test", // Plugin name
PLUGIN_ALL, // Which servers is this plugin for
"0.1", // Plugin version
PLUGIN_VERSION, // Minimum plugin engine version to run
"A sample plugin" // Short description of plugin
};
////// Plugin event list //////////
// Format: <plugin function>,<event name>
// All registered functions to a event gets executed
// (In descending order) when its called.
// Multiple functions can be called by multiple events too,
// So it's up to your creativity ^^
//
PLUGIN_EVENTS_TABLE = {
// change only the following area
{ "test_me", "Plugin_Test" }, // when the plugin is tested for compatibility
{ "do_init", "Plugin_Init" }, // when plugins are loaded
{ "do_final", "Plugin_Final" }, // when plugins are unloaded
{ "some_function", "some_event" },
{ "some_function", "another_event" },
{ NULL, NULL }
};
///// Variables /////
char *server_type;
char *server_name;
//////// Plugin functions //////////
int do_init ()
{
// import symbols from the server
IMPORT_SYMBOL(server_type, 0);
IMPORT_SYMBOL(server_name, 1);
printf ("Server type is ");
switch (*server_type) {
case PLUGIN_LOGIN: printf ("Login\n"); break;
case PLUGIN_CHAR: printf ("Char\n"); break;
case PLUGIN_MAP: printf ("Map\n"); break;
}
printf ("Filename is %s\n", server_name);
return 1;
}
int do_final ()
{
printf ("Bye world\n");
return 1;
}
int some_function ()
{
printf ("Some function\n");
return 0;
}
// return 1 if the testing passes, otherwise 0
// (where the plugin will be deactivated)
int test_me ()
{
if (1 + 1 == 2)
return 1;
return 0;
}

View File

@ -1,11 +0,0 @@
EXPORTS
; common exports
plugin_info DATA
plugin_event_table DATA
plugin_call_table DATA
; plugin-specific exports
test_me
do_init
do_final
some_function

View File

@ -1,208 +0,0 @@
// $Id: sig.c 1 2005-6-13 3:17:17 PM Celestia $
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#define __USE_GNU // required to enable strsignal on some platforms
#include <string.h>
#include <time.h>
#include "../common/plugin.h"
PLUGIN_INFO = {
"Signals",
PLUGIN_CORE,
"1.1",
PLUGIN_VERSION,
"Handles program signals"
};
PLUGIN_EVENTS_TABLE = {
{ "sig_init", "Plugin_Init" },
{ "sig_final", "Plugin_Final" },
{ NULL, NULL }
};
//////////////////////////////////////
#if defined(_WIN32) || defined(MINGW)
int sig_init()
{
printf("sig: This plugin is not supported - Enable 'exchndl' instead!\n");
return 0;
}
int sig_final() { return 0; }
#elif defined (__NETBSD__) || defined (__FREEBSD__)
int sig_init()
{
printf("sig: This plugin is not supported!\n");
return 0;
}
int sig_final() { return 0; }
#else
//////////////////////////////////////
#if !defined(CYGWIN)
#include <execinfo.h>
#endif
const char* (*getrevision)();
unsigned long (*getuptime)();
char *server_name;
int crash_flag = 0;
int sig_final ();
// by Gabuzomeu
// This is an implementation of signal() using sigaction() for portability.
// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced
// Programming in the UNIX Environment_.
//
#ifndef POSIX
#define compat_signal(signo, func) signal(signo, func)
#else
sigfunc *compat_signal(int signo, sigfunc *func)
{
struct sigaction sact, oact;
sact.sa_handler = func;
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
#ifdef SA_INTERRUPT
sact.sa_flags |= SA_INTERRUPT; /* SunOS */
#endif
if (sigaction(signo, &sact, &oact) < 0)
return (SIG_ERR);
return (oact.sa_handler);
}
#endif
/*=========================================
* Dumps the stack using glibc's backtrace
*-----------------------------------------
*/
#ifdef CYGWIN
#define FOPEN_ freopen
#ifdef __cplusplus
extern "C" void cygwin_stackdump();
#else
extern void cygwin_stackdump();
#endif
#else
#define FOPEN_(fn,m,s) fopen(fn,m)
#endif
void sig_dump(int sn)
{
FILE *fp;
char file[256];
int no = 0;
crash_flag = 1;
// search for a usable filename
do {
sprintf (file, "log/%s%04d.stackdump", server_name, ++no);
} while((fp = fopen(file,"r")) && (fclose(fp), no < 9999));
// dump the trace into the file
if ((fp = FOPEN_(file, "w", stderr)) != NULL) {
const char *revision;
#ifndef CYGWIN
void* array[20];
char **stack;
size_t size;
#endif
printf ("sig: Dumping stack to '%s'...\n", file);
if ((revision = getrevision()) != NULL)
fprintf(fp, "Version: svn%s \n", revision);
fprintf(fp, "Exception: %s \n", strsignal(sn));
fflush (fp);
#ifdef CYGWIN
cygwin_stackdump ();
#else
fprintf(fp, "Stack trace:\n");
size = backtrace (array, 20);
stack = backtrace_symbols (array, size);
for (no = 0; no < size; no++) {
fprintf(fp, "%s\n", stack[no]);
}
fprintf(fp,"End of stack trace\n");
free(stack);
#endif
printf("sig: %s Saved.\n", file);
fflush(stdout);
fclose(fp);
}
sig_final(); // Log our uptime
// Pass the signal to the system's default handler
compat_signal(sn, SIG_DFL);
raise(sn);
}
/*=========================================
* Shutting down (Program did not crash ^^)
* - Log our current up time
*-----------------------------------------
*/
int sig_final ()
{
time_t curtime;
char curtime2[24];
FILE *fp;
long seconds = 0, day = 24*60*60, hour = 60*60,
minute = 60, days = 0, hours = 0, minutes = 0;
fp = fopen("log/uptime.log","a");
if (fp) {
time(&curtime);
strftime(curtime2, 24, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
seconds = getuptime();
days = seconds/day;
seconds -= (seconds/day>0)?(seconds/day)*day:0;
hours = seconds/hour;
seconds -= (seconds/hour>0)?(seconds/hour)*hour:0;
minutes = seconds/minute;
seconds -= (seconds/minute>0)?(seconds/minute)*minute:0;
fprintf(fp, "%s: %s %s - %ld days, %ld hours, %ld minutes, %ld seconds.\n",
curtime2, server_name, (crash_flag ? "crashed" : "uptime"),
days, hours, minutes, seconds);
fclose(fp);
}
return 1;
}
/*=========================================
* Register the signal handlers
*-----------------------------------------
*/
int sig_init ()
{
void (*func)(int) = sig_dump;
#ifdef CYGWIN // test if dumper is enabled
char *buf = getenv ("CYGWIN");
if (buf && strstr(buf, "error_start") != NULL)
func = SIG_DFL;
#endif
IMPORT_SYMBOL(server_name, 1);
IMPORT_SYMBOL(getrevision, 6);
IMPORT_SYMBOL(getuptime, 11);
compat_signal(SIGSEGV, func);
compat_signal(SIGFPE, func);
compat_signal(SIGILL, func);
compat_signal(SIGBUS, func);
return 1;
}
#endif