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:
parent
442132fefe
commit
b1881eafee
@ -481,7 +481,6 @@ set( RUNTIME_DIRECTORIES
|
||||
"doc"
|
||||
"log"
|
||||
"npc"
|
||||
"plugins"
|
||||
"readme"
|
||||
"sql-files"
|
||||
"tools"
|
||||
|
19
Makefile.in
19
Makefile.in
@ -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
|
||||
|
||||
|
@ -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
76
configure
vendored
@ -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 ;;
|
||||
|
52
configure.in
52
configure.in
@ -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.
@ -17,4 +17,3 @@ add_subdirectory( login )
|
||||
add_subdirectory( char )
|
||||
add_subdirectory( map )
|
||||
add_subdirectory( tool )
|
||||
add_subdirectory( plugins )
|
||||
|
@ -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"
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
@ -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;
|
||||
}
|
@ -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_ */
|
@ -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 )
|
@ -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
|
@ -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)
|
||||
{
|
||||
}
|
@ -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
@ -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
|
@ -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);
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
EXPORTS
|
||||
plugin_info DATA
|
||||
plugin_event_table DATA
|
||||
plugin_call_table DATA
|
||||
|
||||
pid_create
|
||||
pid_delete
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user