summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt7
-rw-r--r--conf-tmpl/Changelog.txt2
-rw-r--r--conf-tmpl/plugin_athena.conf5
-rw-r--r--src/char/char.c46
-rw-r--r--src/char_sql/char.c46
-rw-r--r--src/common/core.c4
-rw-r--r--src/common/core.h1
-rw-r--r--src/common/plugin.h59
-rw-r--r--src/common/plugins.c358
-rw-r--r--src/common/plugins.h33
-rw-r--r--src/common/socket.c20
-rw-r--r--src/login/login.c15
-rw-r--r--src/login_sql/login.c44
-rw-r--r--src/map/map.c44
-rw-r--r--src/plugins/console.c226
-rw-r--r--vcproj-8/plugin.def4
16 files changed, 640 insertions, 274 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 54da5ccc4..0137b69e6 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -3,6 +3,13 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
+2007/01/08
+ * Added a precompiler error when the shutdown defines are not found.
+ * Added parse_console to the plugin API.
+ * Added plugin for parsing the console. (working with cygwin)
+ * Copied the parse_console code form login txt to login sql and char.
+ * Added propper plugin version compatibility tests.
+ * Better output when a plugin fails to load. [FlavioJS]
2007/01/07
* Fixed the sleep timers not being removed when the an npc was being
unloaded and when reloading scripts. [FlavioJS]
diff --git a/conf-tmpl/Changelog.txt b/conf-tmpl/Changelog.txt
index d9910db55..fc194dca4 100644
--- a/conf-tmpl/Changelog.txt
+++ b/conf-tmpl/Changelog.txt
@@ -1,5 +1,7 @@
Date Added
+2007/01/08
+ * Added the console plugin to plugin_athena.conf commented out. [FlavioJS]
2007/01/05
* Updated noicewall mapflags (to allow them in cities), thanks to Au{R}oN
2007/01/03
diff --git a/conf-tmpl/plugin_athena.conf b/conf-tmpl/plugin_athena.conf
index c4b889da8..306fddf71 100644
--- a/conf-tmpl/plugin_athena.conf
+++ b/conf-tmpl/plugin_athena.conf
@@ -26,4 +26,7 @@ plugin: upnp
//plugin: pid
// Built-in webserver
-//plugin: httpd \ No newline at end of file
+//plugin: httpd
+
+// Console parser
+//plugin: console
diff --git a/src/char/char.c b/src/char/char.c
index 262adb86f..a7a199f12 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -3856,27 +3856,33 @@ int parse_char(int fd) {
}
// Console Command Parser [Wizputer]
-int parse_console(char *buf) {
- char *type,*command;
-
- type = (char *)aCalloc(64,1);
- command = (char *)aCalloc(64,1);
-
-// memset(type,0,64);
-// memset(command,0,64);
-
- ShowStatus("Console: %s\n",buf);
-
- if ( sscanf(buf, "%[^:]:%[^\n]", type , command ) < 2 )
- sscanf(buf,"%[^\n]",type);
-
- ShowDebug("Type of command: %s || Command: %s \n",type,command);
-
- if(buf) aFree(buf);
- if(type) aFree(type);
- if(command) aFree(command);
+int parse_console(char* buf)
+{
+ char command[256];
+
+ memset(command, 0, sizeof(command));
+
+ sscanf(buf, "%[^\n]", command);
+
+ //login_log("Console command :%s" RETCODE, command);
+
+ if( strcmpi("shutdown", command) == 0 ||
+ strcmpi("exit", command) == 0 ||
+ strcmpi("quit", command) == 0 ||
+ strcmpi("end", command) == 0 )
+ runflag = 0;
+ else if( strcmpi("alive", command) == 0 ||
+ strcmpi("status", command) == 0 )
+ ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
+ else if( strcmpi("help", command) == 0 ){
+ printf(CL_BOLD"Help of commands:"CL_RESET"\n");
+ printf(" To shutdown the server:\n");
+ printf(" 'shutdown|exit|qui|end'\n");
+ printf(" To know if server is alive:\n");
+ printf(" 'alive|status'\n");
+ }
- return 0;
+ return 0;
}
// 全てのMAPサーバーにデータ送信(送信したmap鯖の数を返す)
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index 4851fbaca..2cf237317 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -3648,27 +3648,33 @@ int parse_char(int fd) {
}
// Console Command Parser [Wizputer]
-int parse_console(char *buf) {
- char *type,*command;
-
- type = (char *)aMalloc(64);
- command = (char *)aMalloc(64);
-
- memset(type,0,64);
- memset(command,0,64);
-
- ShowNotice("Console: %s\n",buf);
-
- if ( sscanf(buf, "%[^:]:%[^\n]", type , command ) < 2 )
- sscanf(buf,"%[^\n]",type);
-
- ShowNotice("Type of command: %s || Command: %s \n",type,command);
-
- if(buf) aFree(buf);
- if(type) aFree(type);
- if(command) aFree(command);
+int parse_console(char* buf)
+{
+ char command[256];
+
+ memset(command, 0, sizeof(command));
+
+ sscanf(buf, "%[^\n]", command);
+
+ //login_log("Console command :%s" RETCODE, command);
+
+ if( strcmpi("shutdown", command) == 0 ||
+ strcmpi("exit", command) == 0 ||
+ strcmpi("quit", command) == 0 ||
+ strcmpi("end", command) == 0 )
+ runflag = 0;
+ else if( strcmpi("alive", command) == 0 ||
+ strcmpi("status", command) == 0 )
+ ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
+ else if( strcmpi("help", command) == 0 ){
+ printf(CL_BOLD"Help of commands:"CL_RESET"\n");
+ printf(" To shutdown the server:\n");
+ printf(" 'shutdown|exit|qui|end'\n");
+ printf(" To know if server is alive:\n");
+ printf(" 'alive|status'\n");
+ }
- return 0;
+ return 0;
}
// MAP send all
diff --git a/src/common/core.c b/src/common/core.c
index e8fd48923..b5db552e6 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -259,7 +259,7 @@ int main (int argc, char **argv)
do_init(argc,argv);
graph_init();
- plugin_event_trigger("Athena_Init");
+ plugin_event_trigger(EVENT_ATHENA_INIT);
{// Main runtime cycle
int next;
@@ -272,7 +272,7 @@ int main (int argc, char **argv)
}
}
- plugin_event_trigger("Athena_Final");
+ plugin_event_trigger(EVENT_ATHENA_FINAL);
graph_final();
do_final();
diff --git a/src/common/core.h b/src/common/core.h
index fffd44028..06ce86448 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -13,6 +13,7 @@ extern int runflag;
extern char *SERVER_NAME;
extern char SERVER_TYPE;
+extern int parse_console(char* buf);
extern const char *get_svn_revision(void);
extern int do_init(int,char**);
extern void set_server_type(void);
diff --git a/src/common/plugin.h b/src/common/plugin.h
index 402636b1d..f30a15e5e 100644
--- a/src/common/plugin.h
+++ b/src/common/plugin.h
@@ -4,23 +4,44 @@
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
+#include "cbasetypes.h"
+
////// Plugin functions ///////////////
-#define PLUGIN_VERSION "1.02"
+// 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* name;
char type;
- char *version;
- char *req_version;
- char *description;
+ char* version;
+ char* req_version;
+ char* description;
} Plugin_Info;
typedef struct _Plugin_Event_Table {
- char *func_name;
- char *event_name;
+ 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
@@ -31,10 +52,32 @@ typedef struct _Plugin_Event_Table {
#define IMPORT_SYMBOL(s,n) (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[]
-void **plugin_call_table;
+void** plugin_call_table;
#endif // _PLUGIN_H_
diff --git a/src/common/plugins.c b/src/common/plugins.c
index 3dcddcb3d..4d3849330 100644
--- a/src/common/plugins.c
+++ b/src/common/plugins.c
@@ -1,14 +1,6 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-#include "plugin.h"
#include "plugins.h"
#include "../common/mmo.h"
#include "../common/core.h"
@@ -19,99 +11,109 @@
#include "../common/version.h"
#include "../common/showmsg.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
//////////////////////////////////////////////
typedef struct _Plugin_Event {
- void (*func)(void);
- struct _Plugin_Event *next;
+ struct _Plugin_Event* next;
+ Plugin_Event_Func* func;
} Plugin_Event;
typedef struct _Plugin_Event_List {
- char *name;
- struct _Plugin_Event_List *next;
- struct _Plugin_Event *events;
+ struct _Plugin_Event_List* next;
+ char* name;
+ struct _Plugin_Event* events;
} Plugin_Event_List;
-static int auto_search = 1;
+static int auto_search = 0;
static int load_priority = 0;
-Plugin_Event_List *event_head = NULL;
-Plugin *plugin_head = NULL;
+Plugin_Event_List* event_head = NULL;
+Plugin* plugin_head = NULL;
-Plugin_Info default_info = { "Unknown", PLUGIN_ALL, "0", PLUGIN_VERSION, "Unknown" };
+static Plugin_Info default_info = { "Unknown", PLUGIN_ALL, "0", PLUGIN_VERSION, "Unknown" };
static size_t call_table_size = 0;
static size_t max_call_table = 0;
////// Plugin Events Functions //////////////////
-int register_plugin_func (char *name)
+int register_plugin_func(char* name)
{
- Plugin_Event_List *evl;
- if (name) {
- evl = (Plugin_Event_List *) aMalloc(sizeof(Plugin_Event_List));
- evl->name = (char *) aMalloc (strlen(name) + 1);
-
+ Plugin_Event_List* evl;
+ if( name ){
+ //ShowDebug("register_plugin_func(%s)\n", name);
+ CREATE(evl, Plugin_Event_List, 1);
evl->next = event_head;
- strcpy(evl->name, name);
+ evl->name = aStrdup(name);
evl->events = NULL;
event_head = evl;
}
return 0;
}
-Plugin_Event_List *search_plugin_func (char *name)
+static Plugin_Event_List* search_plugin_func(char* name)
{
- Plugin_Event_List *evl = event_head;
- while (evl) {
- if (strcmpi(evl->name, name) == 0)
+ 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 (void (*func)(void), char* name)
+int register_plugin_event(Plugin_Event_Func* func, char* name)
{
- Plugin_Event_List *evl = search_plugin_func(name);
- if (!evl) {
- // register event if it doesn't exist already
+ 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);
- // relocate the new event list
+ // get the new event list
evl = search_plugin_func(name);
}
- if (evl) {
- Plugin_Event *ev;
+ if( evl ){
+ Plugin_Event* ev;
- ev = (Plugin_Event *) aMalloc(sizeof(Plugin_Event));
+ CREATE(ev, Plugin_Event, 1);
ev->func = func;
ev->next = NULL;
- if (evl->events == NULL)
+ // insert event at the end of the linked list
+ if( evl->events == NULL )
evl->events = ev;
else {
- Plugin_Event *ev2 = evl->events;
- while (ev2) {
- if (ev2->next == NULL) {
- ev2->next = ev;
+ Plugin_Event* last_ev = evl->events;
+ while( last_ev ){
+ if( last_ev->next == NULL ){
+ last_ev->next = ev;
break;
}
- ev2 = ev2->next;
+ last_ev = last_ev->next;
}
}
}
return 0;
}
-int plugin_event_trigger (char *name)
+int plugin_event_trigger(char* name)
{
int c = 0;
- Plugin_Event_List *evl = search_plugin_func(name);
- if (evl) {
- Plugin_Event *ev = evl->events;
- while (ev) {
+ 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++;
+ ++c;
}
}
return c;
@@ -119,27 +121,27 @@ int plugin_event_trigger (char *name)
////// Plugins Call Table Functions /////////
-int export_symbol (void *var, int offset)
+int export_symbol(void* var, size_t offset)
{
- //printf ("0x%x\n", var);
-
+ ShowDebug("export_symbol(0x%x,%d)\n", var,offset);
+
// add to the end of the list
- if (offset < 0)
+ if( offset < 0 )
offset = call_table_size;
-
- // realloc if not large enough
- if ((size_t)offset >= max_call_table) {
+
+ if( offset >= max_call_table )
+ {// realloc if not large enough
max_call_table = 1 + offset;
- plugin_call_table = (void**)aRealloc(plugin_call_table, max_call_table*sizeof(void*));
-
+ 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 ((size_t)offset >= call_table_size)
+ if( offset >= call_table_size )
call_table_size = offset+1;
-
+
// put the pointer at the selected place
plugin_call_table[offset] = var;
return 0;
@@ -147,106 +149,139 @@ int export_symbol (void *var, int offset)
////// Plugins Core /////////////////////////
-Plugin *plugin_open (const char *filename)
+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(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;
+ Plugin* plugin;
+ Plugin_Info* info;
+ Plugin_Event_Table* events;
+ void** procs;
int init_flag = 1;
- //printf ("loading %s\n", filename);
+ //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) {
- //printf ("not loaded (duplicate) : %s\n", filename);
+ 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;
}
- plugin = (Plugin *)aCalloc(1, sizeof(Plugin));
+ CREATE(plugin, Plugin, 1);
plugin->state = -1; // not loaded
plugin->dll = DLL_OPEN(filename);
- if (!plugin->dll) {
- //printf ("not loaded (invalid file) : %s\n", 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
- DLL_SYM (info, plugin->dll, "plugin_info");
+ DLL_SYM(info, 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 && load_priority == 0) ||
- (info && ((atof(info->req_version) < atof(PLUGIN_VERSION)) || // plugin is based on older code
- (info->type != PLUGIN_ALL && info->type != PLUGIN_CORE && info->type != SERVER_TYPE) || // plugin is not for this server
- (info->type == PLUGIN_CORE && SERVER_TYPE != PLUGIN_LOGIN && SERVER_TYPE != PLUGIN_CHAR && SERVER_TYPE != PLUGIN_MAP))))
- {
- //printf ("not loaded (incompatible) : %s\n", filename);
+ 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) ? info : &default_info;
- plugin->filename = (char *) aMalloc (strlen(filename) + 1);
- strcpy(plugin->filename, filename);
+ plugin->info = ( info != NULL ? info : &default_info );
+ plugin->filename = aStrdup(filename);
// Initialise plugin call table (For exporting procedures)
- DLL_SYM (procs, plugin->dll, "plugin_call_table");
- if (procs) *procs = plugin_call_table;
-
+ DLL_SYM(procs, plugin->dll, "plugin_call_table");
+ if( procs )
+ *procs = plugin_call_table;
+ //else ShowDebug("plugin_open: plugin_call_table not found\n");
+
// Register plugin events
- DLL_SYM (events, plugin->dll, "plugin_event_table");
- if (events) {
+ DLL_SYM(events, plugin->dll, "plugin_event_table");
+ if( events ){
int i = 0;
- while (events[i].func_name) {
- if (strcmpi(events[i].event_name, "Plugin_Test") == 0) {
- int (*test_func)(void);
- DLL_SYM (test_func, plugin->dll, events[i].func_name);
- if (test_func && test_func() == 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;
+ DLL_SYM(test_func, 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
- //printf ("disabled (failed test) : %s\n", filename);
+ //ShowDebug("plugin_open: disabled (failed test) : %s\n", filename);
init_flag = 0;
}
} else {
- void (*func)(void);
- DLL_SYM (func, plugin->dll, events[i].func_name);
- if (func) register_plugin_event (func, events[i].event_name);
+ Plugin_Event_Func* func;
+ DLL_SYM(func, plugin->dll, events[i].func_name);
+ if (func)
+ register_plugin_event(func, events[i].event_name);
}
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);
+ ShowStatus("Done loading plugin '"CL_WHITE"%s"CL_RESET"'\n", (info) ? plugin->info->name : filename);
return plugin;
}
-void plugin_load (const char *filename)
+void plugin_load(const char* filename)
{
plugin_open(filename);
}
-void plugin_unload (Plugin *plugin)
+void plugin_unload(Plugin* plugin)
{
- if (plugin == NULL)
+ if( plugin == NULL )
return;
- if (plugin->filename) aFree(plugin->filename);
- if (plugin->dll) DLL_CLOSE(plugin->dll);
+ if( plugin->filename )
+ aFree(plugin->filename);
+ if( plugin->dll )
+ DLL_CLOSE(plugin->dll);
aFree(plugin);
}
-#ifdef _WIN32
+#ifdef WIN32
char *DLL_ERROR(void)
{
static char dllbuf[80];
@@ -258,107 +293,114 @@ char *DLL_ERROR(void)
////// Initialize/Finalize ////////////////////
-int plugins_config_read(const char *cfgName)
+static int plugins_config_read(const char *cfgName)
{
char line[1024], w1[1024], w2[1024];
FILE *fp;
fp = fopen(cfgName, "r");
- if (fp == NULL) {
+ if( fp == NULL ){
ShowError("File not found: %s\n", cfgName);
return 1;
}
- while (fgets(line, 1020, fp)) {
- if(line[0] == '/' && line[1] == '/')
+ while( fgets(line, 1020, fp) ){
+ if( line[0] == '/' && line[1] == '/' )
continue;
- if (sscanf(line,"%[^:]: %[^\r\n]", w1, w2) != 2)
+ if( sscanf(line,"%[^:]: %[^\r\n]",w1,w2) != 2 )
continue;
- if (strcmpi(w1, "auto_search") == 0) {
- if(strcmpi(w2, "yes")==0)
+ if( strcmpi(w1,"auto_search") == 0 ){
+ if( strcmpi(w2,"yes") == 0 )
auto_search = 1;
- else if(strcmpi(w2, "no")==0)
+ else if( strcmpi(w2,"no") == 0 )
auto_search = 0;
- else auto_search = atoi(w2);
- } else if (strcmpi(w1, "plugin") == 0) {
+ else
+ auto_search = atoi(w2);
+ } else if( strcmpi(w1,"plugin") == 0 ){
char filename[128];
- sprintf (filename, "plugins/%s%s", w2, DLL_EXT);
+ sprintf(filename, "plugins/%s%s", w2, DLL_EXT);
plugin_load(filename);
- } else if (strcmpi(w1, "import") == 0)
+ } else if( strcmpi(w1,"import") == 0 )
plugins_config_read(w2);
}
fclose(fp);
return 0;
}
-void plugins_init (void)
+void plugins_init(void)
{
- char *PLUGIN_CONF_FILENAME = "conf/plugin_athena.conf";
- register_plugin_func("Plugin_Init");
- register_plugin_func("Plugin_Final");
- register_plugin_func("Athena_Init");
- register_plugin_func("Athena_Final");
+ 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 (func_parse_table, 18);
- export_symbol (RFIFOSKIP, 17);
- export_symbol (WFIFOSET, 16);
- export_symbol (delete_session, 15);
- export_symbol (session, 14);
- export_symbol (&fd_max, 13);
- export_symbol (addr_, 12);
+ export_symbol(func_parse_table, SYMBOL_FUNC_PARSE_TABLE);
+ export_symbol(RFIFOSKIP, SYMBOL_RFIFOSKIP);
+ export_symbol(WFIFOSET, SYMBOL_WFIFOSET);
+ export_symbol(delete_session, 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, 11);
- export_symbol (delete_timer, 10);
- export_symbol (add_timer_func_list, 9);
- export_symbol (add_timer_interval, 8);
- export_symbol (add_timer, 7);
- export_symbol ((void *)get_svn_revision, 6);
- export_symbol (gettick, 5);
+ 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 (&runflag, 4);
- export_symbol (arg_v, 3);
- export_symbol (&arg_c, 2);
- export_symbol (SERVER_NAME, 1);
- export_symbol (&SERVER_TYPE, 0);
+ 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);
+ plugins_config_read(PLUGIN_CONF_FILENAME);
load_priority = 0;
- if (auto_search)
+ if( auto_search )
findfile("plugins", DLL_EXT, plugin_load);
- plugin_event_trigger("Plugin_Init");
+ plugin_event_trigger(EVENT_PLUGIN_INIT);
return;
}
-void plugins_final (void)
+void plugins_final(void)
{
- Plugin *plugin = plugin_head, *plugin2;
- Plugin_Event_List *evl = event_head, *evl2;
- Plugin_Event *ev, *ev2;
-
- plugin_event_trigger("Plugin_Final");
-
- while (plugin) {
- plugin2 = plugin->next;
+ 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 = plugin2;
+ plugin = next_plugin;
}
- while (evl) {
+ while( evl ){
ev = evl->events;
- while (ev) {
- ev2 = ev->next;
+ while( ev ){
+ next_ev = ev->next;
aFree(ev);
- ev = ev2;
+ ev = next_ev;
}
- evl2 = evl->next;
+ next_evl = evl->next;
aFree(evl->name);
aFree(evl);
- evl = evl2;
+ evl = next_evl;
}
aFree(plugin_call_table);
diff --git a/src/common/plugins.h b/src/common/plugins.h
index 34fd18a64..9cb4b94b4 100644
--- a/src/common/plugins.h
+++ b/src/common/plugins.h
@@ -4,17 +4,20 @@
#ifndef _PLUGINS_H_
#define _PLUGINS_H_
+#include "../common/plugin.h"
+
////// Dynamic Link Library functions ///////////////
-#ifdef _WIN32
+#ifdef WIN32
#include <windows.h>
#define DLL_OPEN(x) LoadLibrary(x)
#define DLL_SYM(x,y,z) (FARPROC)(x) = GetProcAddress(y,z)
#define DLL_CLOSE(x) FreeLibrary(x)
+ char *DLL_ERROR(void);
+
#define DLL_EXT ".dll"
#define DLL HINSTANCE
- char *DLL_ERROR(void);
#else
@@ -31,6 +34,8 @@
#endif
#define DLL void *
+ #include <string.h> // size_t
+
#endif
////// Plugin Definitions ///////////////////
@@ -38,24 +43,24 @@
typedef struct _Plugin {
DLL dll;
char state;
- char *filename;
- struct _Plugin_Info *info;
- struct _Plugin *next;
+ char* filename;
+ struct _Plugin_Info* info;
+ struct _Plugin* next;
} Plugin;
/////////////////////////////////////////////
-int register_plugin_func (char *);
-int register_plugin_event (void (*)(void), char *);
-int plugin_event_trigger (char *);
+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 *, int);
+int export_symbol(void* var, size_t offset);
#define EXPORT_SYMBOL(s) export_symbol((s), -1);
-Plugin *plugin_open (const char *);
-void plugin_load (const char *);
-void plugin_unload (Plugin *);
-void plugins_init (void);
-void plugins_final (void);
+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_
diff --git a/src/common/socket.c b/src/common/socket.c
index 04793094c..3d445d286 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -57,10 +57,14 @@
#include "../common/showmsg.h"
/// shutdown() constants
-#if defined(SD_RECEIVE) && !defined(SHUT_RD)
-#define SHUT_RD SD_RECEIVE
-#define SHUT_WR SD_SEND
-#define SHUT_RDWR SD_BOTH
+#ifndef SHUT_RD
+#ifdef SD_RECEIVE
+ #define SHUT_RD SD_RECEIVE
+ #define SHUT_WR SD_SEND
+ #define SHUT_RDWR SD_BOTH
+#else
+ #error "Unknown socket constants, please report this to a developer"
+#endif
#endif
fd_set readfds;
@@ -423,12 +427,12 @@ void func_parse_check (struct socket_data *sd)
}
// Console Input [Wizputer]
-int start_console(void) {
-
+int start_console(void)
+{
//Until a better plan is came up with... can't be using session[0] anymore! [Skotlex]
ShowNotice("The console is currently nonfunctional.\n");
return 0;
-
+
FD_SET(0,&readfds);
if (!session[0]) { // dummy socket already uses fd 0
@@ -1197,7 +1201,7 @@ int socket_getips(uint32 *ips, int max)
void socket_init(void)
{
char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf";
-
+
#ifdef WIN32
{// Start up windows networking
WSADATA wsaData;
diff --git a/src/login/login.c b/src/login/login.c
index 3c38c738c..84d6afd0f 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -3466,24 +3466,25 @@ int parse_login(int fd) {
//-----------------------
// Console Command Parser [Wizputer]
//-----------------------
-int parse_console(char *buf) {
+int parse_console(char *buf)
+{
char command[256];
- memset(command,0,sizeof(command));
+ memset(command, 0, sizeof(command));
sscanf(buf, "%[^\n]", command);
login_log("Console command :%s" RETCODE, command);
- if(strcmpi("shutdown", command) == 0 ||
+ if( strcmpi("shutdown", command) == 0 ||
strcmpi("exit", command) == 0 ||
strcmpi("quit", command) == 0 ||
- strcmpi("end", command) == 0)
+ strcmpi("end", command) == 0 )
runflag = 0;
- else if(strcmpi("alive", command) == 0 ||
- strcmpi("status", command) == 0)
+ else if( strcmpi("alive", command) == 0 ||
+ strcmpi("status", command) == 0 )
ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
- else if(strcmpi("help", command) == 0) {
+ else if( strcmpi("help", command) == 0 ){
printf(CL_BOLD"Help of commands:"CL_RESET"\n");
printf(" To shutdown the server:\n");
printf(" 'shutdown|exit|qui|end'\n");
diff --git a/src/login_sql/login.c b/src/login_sql/login.c
index 350fe4e1b..b1e85a4c3 100644
--- a/src/login_sql/login.c
+++ b/src/login_sql/login.c
@@ -1951,25 +1951,31 @@ int parse_login(int fd) {
}
// Console Command Parser [Wizputer]
-int parse_console(char *buf) {
- char *type,*command;
-
- type = (char *)aMalloc(64);
- command = (char *)aMalloc(64);
-
- memset(type,0,64);
- memset(command,0,64);
-
- ShowInfo("Console: %s\n",buf);
-
- if ( sscanf(buf, "%[^:]:%[^\n]", type , command ) < 2 )
- sscanf(buf,"%[^\n]",type);
-
- ShowInfo("Type of command: %s || Command: %s \n",type,command);
-
- if(buf) aFree(buf);
- if(type) aFree(type);
- if(command) aFree(command);
+int parse_console(char* buf)
+{
+ char command[256];
+
+ memset(command, 0, sizeof(command));
+
+ sscanf(buf, "%[^\n]", command);
+
+ login_log("Console command :%s" RETCODE, command);
+
+ if( strcmpi("shutdown", command) == 0 ||
+ strcmpi("exit", command) == 0 ||
+ strcmpi("quit", command) == 0 ||
+ strcmpi("end", command) == 0 )
+ runflag = 0;
+ else if( strcmpi("alive", command) == 0 ||
+ strcmpi("status", command) == 0 )
+ ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
+ else if( strcmpi("help", command) == 0 ){
+ printf(CL_BOLD"Help of commands:"CL_RESET"\n");
+ printf(" To shutdown the server:\n");
+ printf(" 'shutdown|exit|qui|end'\n");
+ printf(" To know if server is alive:\n");
+ printf(" 'alive|status'\n");
+ }
return 0;
}
diff --git a/src/map/map.c b/src/map/map.c
index f17b05e02..6d1bb490d 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3247,44 +3247,54 @@ static int char_ip_set = 0;
* Console Command Parser [Wizputer]
*------------------------------------------
*/
-int parse_console(char *buf) {
- char type[64],command[64],map[64];
- int x = 0, y = 0;
- int m, n;
+int parse_console(char* buf)
+{
+ char type[64];
+ char command[64];
+ char map[64];
+ int x = 0;
+ int y = 0;
+ int m;
+ int n;
struct map_session_data sd;
memset(&sd, 0, sizeof(struct map_session_data));
- strcpy( sd.status.name , "console");
+ strcpy(sd.status.name, "console");
- if ( ( n = sscanf(buf, "%[^:]:%[^:]:%99s %d %d[^\n]", type , command , map , &x , &y )) < 5 )
- if ( ( n = sscanf(buf, "%[^:]:%[^\n]", type , command )) < 2 )
+ if( (n=sscanf(buf, "%[^:]:%[^:]:%99s %d %d[^\n]",type,command,map,&x,&y)) < 5 )
+ if( (n=sscanf(buf, "%[^:]:%[^\n]",type,command)) < 2 )
n = sscanf(buf,"%[^\n]",type);
- if ( n == 5 ) {
+ if( n == 5 ) {
m = map_mapname2mapid(map);
- if ( m < 0 ) {
+ if( m < 0 ){
ShowWarning("Console: Unknown map\n");
return 0;
}
sd.bl.m = m;
map_search_freecell(&sd.bl, m, &sd.bl.x, &sd.bl.y, -1, -1, 0);
- if (x > 0)
+ if( x > 0 )
sd.bl.x = x;
-
- if (y > 0)
+ if( y > 0 )
sd.bl.y = y;
+ } else {
+ map[0] = '\0';
+ if( n < 2 ) command[0] = '\0';
+ if( n < 1 ) type[0] = '\0';
}
- ShowInfo("Type of command: %s || Command: %s || Map: %s Coords: %d %d\n",type,command,map,x,y);
+ ShowInfo("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y);
- if ( strcmpi("admin",type) == 0 && n == 5 ) {
+ if( n == 5 && strcmpi("admin",type) == 0 ){
if( is_atcommand_sub(sd.fd,&sd,command,99) == AtCommand_None )
printf("Console: not atcommand\n");
- } else if ( strcmpi("server",type) == 0 && n == 2 ) {
- if ( strcmpi("shutdown", command) == 0 || strcmpi("exit",command) == 0 || strcmpi("quit",command) == 0 ) {
+ } else if( n == 2 && strcmpi("server",type) == 0 ){
+ if( strcmpi("shutdown",command) == 0 ||
+ strcmpi("exit",command) == 0 ||
+ strcmpi("quit",command) == 0 ){
runflag = 0;
}
- } else if ( strcmpi("help",type) == 0 ) {
+ } else if( strcmpi("help",type) == 0 ){
ShowNotice("To use GM commands:\n");
printf("admin:<gm command>:<map of \"gm\"> <x> <y>\n");
printf("You can use any GM command that doesn't require the GM.\n");
diff --git a/src/plugins/console.c b/src/plugins/console.c
new file mode 100644
index 000000000..41ef434e9
--- /dev/null
+++ b/src/plugins/console.c
@@ -0,0 +1,226 @@
+// 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
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <poll.h>
+ #include <string.h>
+#endif
+#include <stdio.h> // stdin, fgets
+
+#ifdef WIN32
+
+#define THREAD_FUNC_START(name) DWORD WINAPI thread_ ## name(LPVOID lpParameter) { (void)lpParameter; {
+#define THREAD_FUNC_END(name) } ExitThread(0); return 0; }
+#define THREAD_EXECUTE(name,errvar) \
+ do{ \
+ int _fail_ = (CreateThread(NULL,0,thread_ ## name,NULL,0,NULL) == NULL); \
+ if( errvar ) \
+ *errvar = _fail_; \
+ }while(0)
+#define sleep Sleep
+
+#define pipe_create(p) ( CreatePipe(&p[PIPE_READ], &p[PIPE_WRITE], NULL, 1) != 0 )
+#define pipe_read(p,data,len) do{ DWORD _b_; ReadFile(p[PIPE_READ], data, len, &_b_, NULL); }while(0)
+#define pipe_write(p,data,len) do{ DWORD _b_; WriteFile(p[PIPE_WRITE], data, len, &_b_, NULL); }while(0)
+#define pipe_close(p,side) CloseHandle(p[side])
+typedef HANDLE PIPE[2];
+
+#else
+
+#define THREAD_FUNC_START(name) void thread_ ## name(void) {
+#define THREAD_FUNC_END(name) _exit(0); }
+#define THREAD_EXECUTE(name,errvar) \
+ do{ \
+ int pid = fork(); \
+ if( pid == 0 ){ \
+ thread_ ## name(); \
+ } \
+ if( errvar ) \
+ *errvar = (pid == -1); \
+ }while(0)
+
+#define pipe_create(p) pipe(p)
+#define pipe_read(p,data,len) read(p[PIPE_READ], data, len)
+#define pipe_write(p,data,len) write(p[PIPE_WRITE], data, len)
+#define pipe_close(p,side) close(p[side])
+typedef int PIPE[2];
+
+#endif
+
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+#define INPUT_BUFSIZE 4096
+
+////// 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_start", EVENT_ATHENA_INIT },
+ { "console_stop", EVENT_ATHENA_FINAL },
+ { NULL, NULL }
+};
+
+///// Variables /////
+
+typedef int TimerFunc(int tid, unsigned int tick, int id, int data);
+int (*add_timer_func_list)(TimerFunc func, char* name);
+int (*add_timer_interval)(unsigned int tick, TimerFunc* func, int id, int data, int interval);
+int (*delete_timer)(int tid, TimerFunc* func);
+unsigned int (*gettick)(void);
+int (*parse_console)(char* buf);
+
+int tid;
+PIPE data;
+PIPE next;
+
+//////// Plugin functions //////////
+
+static int pipe_hasdata(PIPE p)
+{
+#ifdef WIN32
+ return ( WaitForSingleObject(p[PIPE_READ],0) == WAIT_OBJECT_0 );
+#else
+ struct pollfd fds;
+ fds.fd = p[PIPE_READ];
+ fds.events = POLLRDNORM;
+ return ( poll(&fds,1,0) > 0 );
+#endif
+}
+
+int console_parsebuf(int tid, unsigned int tick, int id, int data_)
+{
+ //printf("console_parsebuf\n");
+ //delete_timer(tid, console_parsebuf);
+ if( pipe_hasdata(data) ){
+ char buf[INPUT_BUFSIZE];
+ size_t len;
+ //printf("console_parsebuf pipe_hasdata\n");
+ // receive string
+ pipe_read(data, &len, sizeof(size_t));
+ pipe_read(data, &buf, len);
+ buf[len] = '\0';
+ //printf("console_parsebuf buf='%s'\n", buf);
+ // parse it
+ parse_console(buf);
+ //printf("console_parsebuf writing next\n");
+ // send next state
+ buf[0] = 'R';
+ pipe_write(next, &buf, 1);
+ //printf("console_parsebuf done with next\n");
+ }
+ return 0;
+}
+
+THREAD_FUNC_START(readinput)
+ char buf[INPUT_BUFSIZE];
+ char state = 'R';
+ size_t len;
+
+ //printf("thread_readinput START\n");
+ pipe_close(data, PIPE_READ);
+ pipe_close(next, PIPE_WRITE);
+ buf[sizeof(buf)-1] = '\0';
+ for( ; state != 'X'; )
+ {
+ //printf("thread_readinput getting data\n");
+ buf[0] = '\0';
+ fgets(buf, sizeof(buf)-1, stdin);
+ len = strlen(buf);
+ //printf("thread_readinput buf='%s'\n", buf);
+ // send string
+ pipe_write(data, &len, sizeof(size_t));
+ pipe_write(data, buf, len);
+ // receive next state
+ pipe_read(next, &state, sizeof(char));
+ }
+ pipe_close(data, PIPE_WRITE);
+ pipe_close(next, PIPE_READ);
+ //printf("thread_readinput STOP (%d)\n", state);
+THREAD_FUNC_END(readinput)
+
+void console_start(void)
+{
+ int error = 0;
+ //printf("console_start\n");
+ if( pipe_create(data) ){
+ //printf("console_start data pipe failed\n");
+ return;
+ }
+ if( pipe_create(next) ){
+ //printf("console_start next pipe failed\n");
+ pipe_close(data, PIPE_READ);
+ pipe_close(data, PIPE_WRITE);
+ return;
+ }
+ THREAD_EXECUTE(readinput, &error);
+ if( error ){
+ //printf("console_start thread start error\n");
+ pipe_close(data, PIPE_READ);
+ pipe_close(next, PIPE_WRITE);
+ } else {
+ //printf("console_start thread started\n");
+ //parse_console("help");
+ add_timer_func_list(console_parsebuf,"console_parsebuf");
+ tid = add_timer_interval(gettick(),console_parsebuf,0,0,1); // run once every cycle
+ }
+ pipe_close(data, PIPE_WRITE);
+ pipe_close(next, PIPE_READ);
+}
+
+void console_stop(void)
+{
+ char c = 'X';
+ //printf("console_stop\n");
+ if( tid != -1 ){
+ delete_timer(tid, console_parsebuf);
+ pipe_write(next, &c, sizeof(char));
+ }
+ return;
+}
+
+void console_init(void)
+{
+ //printf("console_init\n");
+ // 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);
+
+ return;
+}
+
+void console_final(void)
+{
+ //printf("console_final\n");
+ return;
+}
diff --git a/vcproj-8/plugin.def b/vcproj-8/plugin.def
new file mode 100644
index 000000000..6117bedc6
--- /dev/null
+++ b/vcproj-8/plugin.def
@@ -0,0 +1,4 @@
+EXPORTS
+ plugin_info DATA
+ plugin_event_table DATA
+ plugin_call_table DATA