2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2024-12-26 06:35:33 +03:00

Refactoring of mplugin and mlist

This commit is contained in:
asmodai 2017-05-09 18:34:55 +03:00
parent d1d2a9b755
commit f7c115e736
31 changed files with 917 additions and 1105 deletions

View File

@ -186,5 +186,4 @@ inline void UTIL_TraceLine(const Vector &vecStart, const Vector &vecEnd, IGNORE_
TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters), pentIgnore, ptr);
}
extern char *UTIL_VarArgs(char *format, ...);
extern void UTIL_LogPrintf(const char *fmt, ...);

View File

@ -197,7 +197,6 @@
<ClCompile Include="..\src\linkgame.cpp" />
<ClCompile Include="..\src\log_meta.cpp" />
<ClCompile Include="..\src\metamod_rehlds_api.cpp" />
<ClCompile Include="..\src\meta_eiface.cpp" />
<ClCompile Include="..\src\metamod.cpp" />
<ClCompile Include="..\src\mlist.cpp" />
<ClCompile Include="..\src\mplayer.cpp" />
@ -213,7 +212,6 @@
<ClCompile Include="..\src\reg_support.cpp" />
<ClCompile Include="..\src\sdk_util.cpp" />
<ClCompile Include="..\src\studioapi.cpp" />
<ClCompile Include="..\src\support_meta.cpp" />
<ClCompile Include="..\src\utils.cpp" />
</ItemGroup>
<ItemGroup>
@ -232,7 +230,6 @@
<ClInclude Include="..\src\log_meta.h" />
<ClInclude Include="..\src\metamod_rehlds_api.h" />
<ClInclude Include="..\src\meta_api.h" />
<ClInclude Include="..\src\meta_eiface.h" />
<ClInclude Include="..\src\metamod.h" />
<ClInclude Include="..\src\mlist.h" />
<ClInclude Include="..\src\mplayer.h" />
@ -245,7 +242,6 @@
<ClInclude Include="..\src\reg_support.h" />
<ClInclude Include="..\src\sdk_util.h" />
<ClInclude Include="..\src\studioapi.h" />
<ClInclude Include="..\src\support_meta.h" />
<ClInclude Include="..\src\utils.h" />
</ItemGroup>
<ItemGroup>

View File

@ -41,9 +41,6 @@
<ClCompile Include="..\src\log_meta.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\meta_eiface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\metamod.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -77,9 +74,6 @@
<ClCompile Include="..\src\studioapi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\support_meta.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -130,9 +124,6 @@
<ClInclude Include="..\src\meta_api.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\meta_eiface.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\metamod.h">
<Filter>Source Files</Filter>
</ClInclude>
@ -169,9 +160,6 @@
<ClInclude Include="..\src\studioapi.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\support_meta.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\utils.h">
<Filter>Source Files</Filter>
</ClInclude>

View File

@ -128,7 +128,7 @@ void CForwardCallbackJIT::naked_main()
for (int i = 0, hookid = 0; i < m_jitdata->plugins_count; i++) {
auto plug = &m_jitdata->plugins[i];
if (plug->m_status < PL_RUNNING) // allow only running and paused
if (plug->status() < PL_RUNNING) // allow only running and paused
continue;
size_t fn_table = *(size_t *)(size_t(plug) + m_jitdata->table_offset);
@ -141,7 +141,7 @@ void CForwardCallbackJIT::naked_main()
// check status and handler set
mov(ecx, dword_ptr[fn_table + m_jitdata->pfn_offset]);
cmp(byte_ptr[size_t(&plug->m_status)], PL_RUNNING);
cmp(byte_ptr[plug->status_ptr()], PL_RUNNING);
jecxz(go_next_plugin);
jnz(go_next_plugin);
@ -209,7 +209,7 @@ void CForwardCallbackJIT::naked_main()
for (int i = 0, hookid = 0; i < m_jitdata->plugins_count; i++) {
auto plug = &m_jitdata->plugins[i];
if (plug->m_status < PL_RUNNING) // allow only running and paused
if (plug->status() < PL_RUNNING) // allow only running and paused
continue;
size_t fn_table = *(size_t *)(size_t(plug) + m_jitdata->post_table_offset);
@ -222,7 +222,7 @@ void CForwardCallbackJIT::naked_main()
// check status and handler set
mov(ecx, dword_ptr[fn_table + m_jitdata->pfn_offset]);
cmp(byte_ptr[size_t(&plug->m_status)], PL_RUNNING);
cmp(byte_ptr[plug->status_ptr()], PL_RUNNING);
jecxz(go_next_plugin);
jnz(go_next_plugin);

View File

@ -335,7 +335,7 @@ void cmd_doplug(PLUG_CMD pcmd)
// Otherwise, print error and exit.
if (pcmd == PC_REQUIRE)
{
if (findp && findp->m_status >= PL_RUNNING && unique)
if (findp && findp->status() >= PL_RUNNING && unique)
{
META_DEBUG(3, "Required plugin '%s' found loaded and running.", arg);
return;
@ -375,69 +375,69 @@ void cmd_doplug(PLUG_CMD pcmd)
{
case PC_PAUSE:
if (findp->pause())
META_CONS("Paused plugin '%s'", findp->m_desc);
META_CONS("Paused plugin '%s'", findp->description());
else
META_CONS("Pause failed for plugin '%s'", findp->m_desc);
META_CONS("Pause failed for plugin '%s'", findp->description());
break;
case PC_UNPAUSE:
if (findp->unpause())
META_CONS("Unpaused plugin '%s'", findp->m_desc);
META_CONS("Unpaused plugin '%s'", findp->description());
else
META_CONS("Unpause failed for plugin '%s'", findp->m_desc);
META_CONS("Unpause failed for plugin '%s'", findp->description());
break;
case PC_UNLOAD:
{
findp->m_action = PA_UNLOAD;
if (findp->unload(PT_ANYTIME, PNL_COMMAND, PNL_COMMAND))
findp->set_action(PA_UNLOAD);
if (findp->unload(PT_ANYTIME, PNL_COMMAND))
{
META_CONS("Unloaded plugin '%s'", findp->m_desc);
META_CONS("Unloaded plugin '%s'", findp->description());
g_plugins->show();
}
else if (false /*meta_errno == ME_DELAYED*/) // TODO
META_CONS("Unload delayed for plugin '%s'", findp->m_desc);
META_CONS("Unload delayed for plugin '%s'", findp->description());
else
META_CONS("Unload failed for plugin '%s'", findp->m_desc);
META_CONS("Unload failed for plugin '%s'", findp->description());
break;
}
case PC_FORCE_UNLOAD:
{
findp->m_action = PA_UNLOAD;
if (findp->unload(PT_ANYTIME, PNL_CMD_FORCED, PNL_CMD_FORCED))
findp->set_action(PA_UNLOAD);
if (findp->unload(PT_ANYTIME, PNL_CMD_FORCED))
{
META_CONS("Forced unload plugin '%s'", findp->m_desc);
META_CONS("Forced unload plugin '%s'", findp->description());
g_plugins->show();
}
else
META_CONS("Forced unload failed for plugin '%s'", findp->m_desc);
META_CONS("Forced unload failed for plugin '%s'", findp->description());
break;
}
case PC_RELOAD:
{
findp->m_action = PA_RELOAD;
findp->set_action(PA_RELOAD);
if (findp->reload(PT_ANYTIME, PNL_COMMAND))
META_CONS("Reloaded plugin '%s'", findp->m_desc);
META_CONS("Reloaded plugin '%s'", findp->description());
else if (0/*meta_errno == ME_DELAYED*/) // TODO
META_CONS("Reload delayed for plugin '%s'", findp->m_desc);
META_CONS("Reload delayed for plugin '%s'", findp->description());
else if (0/*meta_errno == ME_NOTALLOWED*/)
META_CONS("Reload not allowed for plugin '%s' now, only allowed %s", findp->m_desc, findp->str_loadable(SL_ALLOWED));
META_CONS("Reload not allowed for plugin '%s' now, only allowed %s", findp->description(), findp->str_loadable(SL_ALLOWED));
else
META_CONS("Reload failed for plugin '%s'", findp->m_desc);
META_CONS("Reload failed for plugin '%s'", findp->description());
break;
}
case PC_RETRY:
if (findp->retry(PT_ANYTIME, PNL_COMMAND))
META_CONS("Retry succeeded for plugin '%s'", findp->m_desc);
META_CONS("Retry succeeded for plugin '%s'", findp->description());
else
META_CONS("Retry failed for plugin '%s'", findp->m_desc);
META_CONS("Retry failed for plugin '%s'", findp->description());
break;
case PC_CLEAR:
if (!findp->clear())
{
META_CONS("Clear failed for plugin '%s'", findp->m_desc);
META_CONS("Clear failed for plugin '%s'", findp->description());
return;
}
META_CONS("Cleared failed plugin '%s' from list", findp->m_desc);
META_CONS("Cleared failed plugin '%s' from list", findp->description());
g_plugins->show();
break;
case PC_INFO:

View File

@ -193,7 +193,7 @@ void MConfig::set_directory()
}
#endif
NormalizePath(m_directory);
normalize_path(m_directory);
// get directory
char *dir = Q_strrchr(m_directory, '/');

View File

@ -3,8 +3,8 @@
#define CDATA_ENG_H(x, p, h) CDATA_ENTRY(enginefuncs_t, x, p, size_t(h))
#define CDATA_ENG(x) CDATA_ENTRY(enginefuncs_t, x, P_PRE, 0u)
meta_enginefuncs_t g_meta_engfuncs; // static trampolines to dynamic callbacks (for gamedll)
meta_enginefuncs_t g_meta_engfuncs_jit; // dynamic jit callbacks
enginefuncs_t g_meta_engfuncs; // static trampolines to dynamic callbacks (for gamedll)
enginefuncs_t g_meta_engfuncs_jit; // dynamic jit callbacks
void MM_PRE_HOOK mm_QueryClientCvarValue(const edict_t* pEdict, const char* cvarName)
{

View File

@ -12,8 +12,7 @@ typedef int (*GET_ENGINE_FUNCTIONS_FN)(enginefuncs_s *pengfuncsFromEngine, int *
// Protect against other projects which use this include file but use the
// normal enginefuncs_t type for their meta_engfuncs.
#ifdef METAMOD_CORE
#include "meta_eiface.h" // meta_enginefuncs_t
extern meta_enginefuncs_t g_meta_engfuncs;
extern enginefuncs_t g_meta_engfuncs;
void compile_engine_callbacks();
#else

View File

@ -10,14 +10,6 @@
// "hack" our way around that by using a flag METAMOD_CORE which is set
// when compiling Metamod proper.
#ifdef METAMOD_CORE
#include "meta_eiface.h" // HL_enginefuncs_t
// Use a #define to bend the enginefuncs_t type to our HL_enginefuncs_t
// type instead as we now use that for the global object g_engfuncs.
#define enginefuncs_t HL_enginefuncs_t
#endif
#include <enginecallback.h> // ALERT, etc
#ifdef METAMOD_CORE

View File

@ -116,7 +116,7 @@ bool setup_gamedll(gamedll_t *gamedll)
// If the path is relative, the gamedll file will be missing and
// it might be found in the cache file.
if (!IsAbsolutePath(gamedll->pathname))
if (!is_abs_path(gamedll->pathname))
{
char szInstallPath[MAX_PATH];
Q_snprintf(szInstallPath, sizeof(szInstallPath), "%s/%s", gamedll->gamedir, gamedll->pathname);

View File

@ -34,7 +34,7 @@ void _fini()
#endif
//! Holds engine functionality callbacks
HL_enginefuncs_t g_engfuncs;
enginefuncs_t g_engfuncs;
globalvars_t* gpGlobals;
engine_t g_engine;
@ -49,7 +49,8 @@ void WINAPI GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, globalvars_t *pG
g_engine.funcs = &g_engfuncs;
g_engine.globals = pGlobals;
g_engfuncs.initialise_interface(pengfuncsFromEngine);
g_engfuncs = *pengfuncsFromEngine;
flush_ALERT_buffer();
// NOTE! Have to call logging function _after_ initialising g_engfuncs, so
// that g_engfuncs.pfnAlertMessage() can be resolved properly, heh. :)
META_DEV("called: GiveFnptrsToDll");

View File

@ -1,20 +0,0 @@
#include "precompiled.h"
void meta_new_dll_functions_t::set_from(NEW_DLL_FUNCTIONS* _pFuncs)
{
Q_memcpy(this, _pFuncs, sizeof(NEW_DLL_FUNCTIONS));
}
void meta_enginefuncs_t::set_from(enginefuncs_t* _pFuncs)
{
Q_memcpy(this, _pFuncs, sizeof(enginefuncs_t));
}
void HL_enginefuncs_t::initialise_interface(enginefuncs_t* _pFuncs)
{
set_from(_pFuncs);
// Now the pfnAlertMessage is available and we trust it to be a valid
// pointer, so flush the message buffer.
flush_ALERT_buffer();
}

View File

@ -1,45 +0,0 @@
#pragma once
// We use our own versions of the engine/dll interface structs. We add a
// few dummy entries to the end and set them to 0. That way we are
// protected from updates to the HL SDK adding new functions which would
// cause a) the game dll copying arbitrary values from us and b) the game
// dll overwriting our memory when using an old Metamod with a new game
// dll.
// meta_new_dll_functions_t
struct meta_new_dll_functions_t: public NEW_DLL_FUNCTIONS
{
// Fill this object with pointers copied from a NEW_DLL_FUNCTIONS struct.
void set_from(NEW_DLL_FUNCTIONS* pFuncs);
};
// meta_enginefuncs_t
struct meta_enginefuncs_t : public enginefuncs_t
{
// Fill this object with pointers copied from an enginefuncs_t struct.
void set_from(enginefuncs_t* pFuncs);
};
// This is a specialisation of the meta_enginefuncs_t struct which is only
// used for the initial copy of the engine functions, i.e. those we get
// passed from the HL engine right at the beginning.
// Since there is only one master copy of engine functions this could be
// implemented as a singleton. This is left as an option for later.
struct HL_enginefuncs_t: public meta_enginefuncs_t
{
HL_enginefuncs_t() {};
// Fill this object with pointers copied from an enginefuncs_t struct
// and fixup the interface.
// For this class this happens in the GiveFptrsToDll() function
// with the pointers passed from the HL engine.
void initialise_interface(enginefuncs_t* pFuncs);
private:
// Moving copy_to() and set_from() to the private space.
void set_from(enginefuncs_t* pFuncs)
{
meta_enginefuncs_t::set_from(pFuncs);
}
};

View File

@ -20,7 +20,7 @@ gamedll_t g_GameDLL;
ALIGN16
meta_globals_t g_metaGlobals;
meta_enginefuncs_t g_plugin_engfuncs;
enginefuncs_t g_plugin_engfuncs;
MPluginList *g_plugins;
MRegCmdList *g_regCmds;
@ -84,7 +84,7 @@ void metamod_startup()
{
META_LOG("Configfile specified via localinfo: %s", cp);
if (FileExistsInGameDir(cp))
if (is_file_exists_in_gamedir(cp))
{
Q_strncpy(configFile, cp, sizeof configFile - 1);
configFile[sizeof configFile - 1] = '\0';
@ -93,7 +93,7 @@ void metamod_startup()
META_ERROR("Empty/missing config.ini file: %s; falling back to %s", cp, configFile);
}
if (!FileExistsInGameDir(configFile))
if (!is_file_exists_in_gamedir(configFile))
{
Q_strncpy(configFile, g_config->directory(), sizeof configFile - 1);
configFile[sizeof configFile - 1] = '\0';
@ -105,14 +105,14 @@ void metamod_startup()
}
Q_strcat(configFile, "/" CONFIG_INI);
if (!FileExistsInGameDir(configFile))
if (!is_file_exists_in_gamedir(configFile))
{
META_DEBUG(2, "No config.ini file found: %s", CONFIG_INI);
}
}
// Load config file
if (FileExistsInGameDir(configFile))
if (is_file_exists_in_gamedir(configFile))
g_config->load(configFile);
// Now, override config options with localinfo commandline options.
@ -163,7 +163,7 @@ void metamod_startup()
// Copy, and store pointer in g_engine struct. Yes, we could just store
// the actual engine_t struct in g_engine, but then it wouldn't be a
// pointer to match the other g_engfuncs.
g_plugin_engfuncs.set_from(g_engine.funcs);
g_plugin_engfuncs = *g_engine.funcs;
g_engine.pl_funcs = &g_plugin_engfuncs;
// substitute our special versions of various commands
g_engine.pl_funcs->pfnAddServerCommand = meta_AddServerCommand;
@ -197,7 +197,7 @@ void metamod_startup()
// In fact, we need gamedir even earlier, so moved up above.
// Load plugins file
if (!FileExistsInGameDir(pluginFile))
if (!is_file_exists_in_gamedir(pluginFile))
{
Q_strncpy(pluginFile, g_config->directory(), sizeof pluginFile - 1);
pluginFile[sizeof pluginFile - 1] = '\0';
@ -209,7 +209,7 @@ void metamod_startup()
}
Q_strcat(pluginFile, "/" PLUGINS_INI);
if (!FileExistsInGameDir(pluginFile))
if (!is_file_exists_in_gamedir(pluginFile))
{
META_DEBUG(2, "No plugins.ini file found: %s", PLUGINS_INI);
}
@ -243,7 +243,7 @@ void metamod_startup()
execFile[sizeof execFile - 1] = '\0';
}
if (FileExistsInGameDir(execFile))
if (is_file_exists_in_gamedir(execFile))
{
if (execFile[0] == '/')
META_ERROR("Cannot exec absolute pathnames: %s", execFile);
@ -268,7 +268,7 @@ bool meta_init_gamedll()
Q_memset(&g_GameDLL, 0, sizeof g_GameDLL);
GET_GAME_DIR(gamedir);
NormalizePath(gamedir);
normalize_path(gamedir);
// As of 1.1.1.1, the engine routine GET_GAME_DIR no longer returns a
// full-pathname, but rather just the path specified as the argument to
@ -280,7 +280,7 @@ bool meta_init_gamedll()
// Note: the code has always assumed the server op wouldn't do:
// hlds -game other/firearms
//
if (IsAbsolutePath(gamedir))
if (is_abs_path(gamedir))
{
// Old style; GET_GAME_DIR returned full pathname. Copy this into
// our gamedir, and truncate to get the game name.

View File

@ -6,7 +6,6 @@
#include "conf_meta.h" // MConfig
#include "osdep.h" // NAME_MAX, etc
#include "mplayer.h" // MPlayerList
#include "meta_eiface.h" // HL_enginefuncs_t, meta_enginefuncs_t
#include "engine_t.h" // engine_t, Engine
#define PLUGINS_INI "plugins.ini" // file that lists plugins to load at startup
@ -32,11 +31,11 @@ struct gamedll_t
extern gamedll_t g_GameDLL;
// SDK variables for storing engine funcs and globals.
extern HL_enginefuncs_t g_engfuncs;
extern enginefuncs_t g_engfuncs;
extern globalvars_t *gpGlobals;
// Our modified version of the engine funcs, to give to plugins.
extern meta_enginefuncs_t g_plugin_engfuncs;
extern enginefuncs_t g_plugin_engfuncs;
// g_config structure.
extern MConfig *g_config;

View File

@ -11,7 +11,7 @@ MPluginList::MPluginList(const char* ifile) : m_max_loaded_count(0)
Q_memset(m_plist, 0, sizeof m_plist);
for (int i = 0; i < MAX_PLUGINS; i++)
{
m_plist[i].m_index = i + 1; // 1-based
new(m_plist + i) MPlugin(i + 1); // 1-based
}
m_max_loaded_count = 0;
@ -67,7 +67,6 @@ MPlugin *MPluginList::find(plid_t id)
{
if (m_plist[i].m_status < PL_VALID)
continue;
if (m_plist[i].m_info == id)
return &m_plist[i];
}
@ -131,10 +130,10 @@ MPlugin *MPluginList::find_match(const char *prefix, bool& unique)
if (plug->m_status < PL_VALID)
continue;
if (plug->m_info && !Q_strnicmp(plug->m_info->name, prefix, len)
if (plug->info() && !Q_strnicmp(plug->info()->name, prefix, len)
|| !Q_strnicmp(plug->m_desc, prefix, len)
|| !Q_strnicmp(plug->m_file, prefix, len)
|| plug->m_info && !Q_strnicmp(plug->m_info->logtag, prefix, len))
|| plug->info() && !Q_strnicmp(plug->info()->logtag, prefix, len))
{
if (pfound) {
unique = false;
@ -182,7 +181,7 @@ MPlugin* MPluginList::plugin_addload(plid_t plid, const char* fname, PLUG_LOADTI
return nullptr;
}
if (pl_temp.resolve() != true) {
if (!pl_temp.resolve()) {
META_DEBUG(1, "Couldn't resolve given path into a file: %s", pl_temp.m_file);
return nullptr;
}
@ -215,7 +214,6 @@ MPlugin* MPluginList::plugin_addload(plid_t plid, const char* fname, PLUG_LOADTI
return nullptr;
}
meta_rebuild_callbacks();
META_DEBUG(1, "Loaded plugin '%s' successfully", pl_added->m_desc);
return pl_added;
@ -263,7 +261,7 @@ MPlugin* MPluginList::add(MPlugin* padd)
// copy pathname
Q_strncpy(iplug->m_pathname, padd->m_pathname, sizeof iplug->m_pathname - 1);
iplug->m_pathname[sizeof iplug->m_pathname - 1] = '\0';
NormalizePath(iplug->m_pathname);
normalize_path(iplug->m_pathname);
iplug->m_source = padd->m_source;
iplug->m_status = padd->m_status;
@ -272,15 +270,13 @@ MPlugin* MPluginList::add(MPlugin* padd)
return iplug;
}
// Read plugins.ini at server startup.
bool MPluginList::ini_startup()
{
char line[MAX_STRBUF_LEN];
int n, ln;
MPlugin *pmatch;
if (!FileExistsInGameDir(m_inifile))
if (!is_file_exists_in_gamedir(m_inifile))
{
META_ERROR("ini: Metamod plugins file empty or missing: %s", m_inifile);
return false;
@ -307,9 +303,7 @@ bool MPluginList::ini_startup()
// Parse directly into next entry in array
if (!m_plist[n].ini_parseline(line))
{
continue;
}
// Check for a duplicate - an existing entry with this pathname.
if (find(m_plist[n].m_pathname))
@ -321,18 +315,13 @@ bool MPluginList::ini_startup()
// Check for a matching platform with different platform specifics
// level.
if (nullptr != (pmatch = find_match(&m_plist[n])))
auto pmatch = find_match(&m_plist[n]);
if (pmatch)
{
if (pmatch->m_pfspecific >= m_plist[n].m_pfspecific)
{
META_DEBUG(1, "ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)", ln, m_inifile, pmatch->m_pfspecific, m_plist[n].m_pfspecific);
continue;
}
META_DEBUG(1, "ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d", ln, pmatch->m_pfspecific, m_plist[n].m_pfspecific);
int _index = pmatch->m_index;
META_DEBUG(1, "ini: Plugin in line %d overrides existing plugin", ln);
int index = pmatch->m_index;
Q_memset(pmatch, 0, sizeof(MPlugin));
pmatch->m_index = _index;
pmatch->m_index = index;
}
m_plist[n].m_action = PA_LOAD;
META_LOG("ini: Read plugin config for: %s", m_plist[n].m_desc);
@ -340,12 +329,10 @@ bool MPluginList::ini_startup()
m_max_loaded_count = n; // mark end of list
}
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins to load", m_inifile, n);
fclose(fp);
if (!n)
{
META_ERROR("ini: Warning; no plugins found to load?");
}
META_LOG("ini: Warning; no plugins found to load?");
return true;
}
@ -355,8 +342,6 @@ bool MPluginList::ini_refresh()
{
char line[MAX_STRBUF_LEN];
int n, ln;
MPlugin pl_temp;
MPlugin *pl_found, *pl_added;
FILE* fp = fopen(m_inifile, "r");
if (!fp)
@ -377,7 +362,7 @@ bool MPluginList::ini_refresh()
*cp = '\0';
// Parse into a temp plugin
Q_memset(&pl_temp, 0, sizeof pl_temp);
MPlugin pl_temp = {};
if (!pl_temp.ini_parseline(line))
{
META_ERROR("ini: Skipping malformed line %d of %s",ln, m_inifile);
@ -385,32 +370,30 @@ bool MPluginList::ini_refresh()
}
// Try to find plugin with this pathname in the current list of
// plugins.
if (!(pl_found = find(pl_temp.m_pathname)))
auto pl_found = find(pl_temp.m_pathname);
if (!pl_found)
{
// Check for a matching platform with higher platform specifics
// level.
if (nullptr != (pl_found = find_match(&pl_temp)))
pl_found = find_match(&pl_temp);
if (pl_found)
{
if (pl_found->m_pfspecific >= pl_temp.m_pfspecific)
if (pl_found->m_action == PA_LOAD)
{
META_DEBUG(1, "ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)", ln, m_inifile, pl_found->m_pfspecific, pl_temp.m_pfspecific);
continue;
}
if (PA_LOAD == pl_found->m_action)
{
META_DEBUG(1, "ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d", ln, pl_found->m_pfspecific, pl_temp.m_pfspecific);
META_DEBUG(1, "ini: Plugin in line %d overrides loading of plugin", ln);
int _index = pl_found->m_index;
Q_memset(pl_found, 0, sizeof(MPlugin));
pl_found->m_index = _index;
}
else
{
META_DEBUG(1, "ini: Plugin in line %d should override existing plugin with lower platform specific level %d, ours %d. Unable to comply.", ln, pl_found->m_pfspecific, pl_temp.m_pfspecific);
META_DEBUG(1, "ini: Plugin in line %d should override existing plugin. Unable to comply.", ln);
continue;
}
}
// new plugin; add to list
if ((pl_added = add(&pl_temp)))
auto pl_added = add(&pl_temp);
if (pl_added)
{
// try to load this plugin at the next opportunity
pl_added->m_action = PA_LOAD;
@ -447,22 +430,17 @@ bool MPluginList::ini_refresh()
}
if (pl_found)
{
META_LOG("ini: Read plugin config for: %s", pl_found->m_desc);
}
else
{
META_LOG("ini: Read plugin config for: %s", pl_temp.m_desc);
}
n++;
}
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins", m_inifile, n);
fclose(fp);
if (!n)
{
META_ERROR("ini: Warning; no plugins found to load?");
}
return true;
}
@ -471,9 +449,7 @@ bool MPluginList::ini_refresh()
bool MPluginList::cmd_addload(const char* args)
{
MPlugin pl_temp = {};
MPlugin *pl_found, *pl_added;
if (pl_temp.cmd_parseline(args) != true)
if (!pl_temp.cmd_parseline(args))
{
META_CONS("Couldn't parse 'meta load' arguments: %s", args);
return false;
@ -481,7 +457,7 @@ bool MPluginList::cmd_addload(const char* args)
// resolve given path into a file; accepts various "shortcut"
// pathnames.
if (pl_temp.resolve() != true)
if (!pl_temp.resolve())
{
// Couldn't find a matching file on disk
META_CONS("Couldn't resolve given path into a file: %s", pl_temp.m_file);
@ -490,14 +466,16 @@ bool MPluginList::cmd_addload(const char* args)
// Try to find plugin with this pathname in the current list of
// plugins.
if ((pl_found = find(pl_temp.m_pathname)))
auto pl_found = find(pl_temp.m_pathname);
if (pl_found)
{
// Already in list
META_CONS("Plugin '%s' already in current list; file=%s desc='%s'", pl_temp.m_file, pl_found->m_file, pl_found->m_desc);
return false;
}
// new plugin; add to list
if (!(pl_added = add(&pl_temp)))
auto pl_added = add(&pl_temp);
if (!pl_added)
{
META_CONS("Couldn't add plugin '%s' to list; see log", pl_temp.m_desc);
return false;
@ -513,14 +491,13 @@ bool MPluginList::cmd_addload(const char* args)
else
META_CONS("Couldn't load plugin '%s'; see log", pl_added->m_desc);
show(0);
show();
return false;
}
META_CONS("Loaded plugin '%s' successfully", pl_added->m_desc);
show();
meta_rebuild_callbacks();
show(0);
return true;
}
@ -540,16 +517,15 @@ bool MPluginList::load()
if (m_plist[i].m_status < PL_VALID)
continue;
if (m_plist[i].load(PT_STARTUP) == true)
if (m_plist[i].load(PT_STARTUP))
n++;
else
// all plugins should be loadable at startup...
META_ERROR("dll: Failed to load plugin '%s'", m_plist[i].m_file);
}
meta_rebuild_callbacks();
META_LOG("dll: Finished loading %d plugins", n);
meta_rebuild_callbacks();
return true;
}
@ -598,7 +574,7 @@ bool MPluginList::refresh(PLUG_LOADTIME now)
{
META_DEBUG(1, "Unloading plugin '%s'", iplug->m_desc);
iplug->m_action = PA_UNLOAD;
if (iplug->unload(now, PNL_INI_DELETED, PNL_INI_DELETED))
if (iplug->unload(now, PNL_INI_DELETED))
nunloaded++;
/*else if (meta_errno == ME_DELAYED) TODO
ndelayed++;*/
@ -630,9 +606,8 @@ bool MPluginList::refresh(PLUG_LOADTIME now)
ndone++;
}
meta_rebuild_callbacks();
META_LOG("dll: Finished updating %d plugins; kept %d, loaded %d, unloaded %d, reloaded %d, delayed %d", ndone, nkept, nloaded, nunloaded, nreloaded, ndelayed);
meta_rebuild_callbacks();
return true;
}
@ -688,9 +663,9 @@ void MPluginList::show(int source_index)
Q_strncpy(file, pl->m_file, sizeof file - 1);
file[sizeof file - 1] = '\0';
if (pl->m_info && pl->m_info->version)
if (pl->info() && pl->info()->version)
{
Q_strncpy(vers, pl->m_info->version, sizeof vers - 1);
Q_strncpy(vers, pl->info()->version, sizeof vers - 1);
vers[sizeof vers - 1] = '\0';
}
else
@ -724,16 +699,16 @@ void MPluginList::show_client(edict_t *pEntity)
for (int i = 0; i < m_max_loaded_count; i++)
{
auto pl = &m_plist[i];
if (pl->m_status != PL_RUNNING || !pl->m_info)
if (pl->m_status != PL_RUNNING || !pl->info())
continue;
n++;
META_CLIENT(pEntity, " [%3d] %s, v%s, %s, by %s, see %s", n,
pl->m_info->name ? pl->m_info->name : "<unknown>",
pl->m_info->version ? pl->m_info->version : "<?>",
pl->m_info->date ? pl->m_info->date : "<../../..>",
pl->m_info->author ? pl->m_info->author : "<unknown>",
pl->m_info->url ? pl->m_info->url : "<unknown>");
pl->info()->name ? pl->info()->name : "<unknown>",
pl->info()->version ? pl->info()->version : "<?>",
pl->info()->date ? pl->info()->date : "<../../..>",
pl->info()->author ? pl->info()->author : "<unknown>",
pl->info()->url ? pl->info()->url : "<unknown>");
}
META_CLIENT(pEntity, "%d plugins", n);

View File

@ -12,7 +12,8 @@
#define WIDTH_MAX_PLUGINS 2
// A list of plugins.
class MPluginList {
class MPluginList
{
public:
MPluginList(const char *ifile);

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,12 @@
#pragma once
#include "api_info.h"
#include "support_meta.h"
#include "utils.h"
// Flags to indicate current "load" state of plugin.
// NOTE: order is important, as greater/less comparisons are made.
enum PLUG_STATUS : uint8
{
PL_EMPTY = 0, // empty slot
PL_EMPTY, // empty slot
PL_VALID, // has valid info in it
PL_BADFILE, // nonexistent file (open failed), or not a valid plugin file (query failed)
PL_OPENED, // dlopened and queried
@ -19,7 +18,7 @@ enum PLUG_STATUS : uint8
// Action to take for plugin at next opportunity.
enum PLUG_ACTION : uint8
{
PA_NULL = 0,
PA_NULL,
PA_NONE, // no action needed right now
PA_KEEP, // keep, after ini refresh
PA_LOAD, // load (dlopen, query) and try to attach
@ -31,7 +30,7 @@ enum PLUG_ACTION : uint8
// Flags to indicate from where the plugin was loaded.
enum PLOAD_SOURCE : uint8
{
PS_INI = 0, // was loaded from the plugins.ini
PS_INI, // was loaded from the plugins.ini
PS_CMD, // was loaded via a server command
PS_PLUGIN, // was loaded by other plugin
};
@ -48,68 +47,50 @@ enum STR_LOADTIME : uint8
// Flags for how to format description of status.
enum STR_STATUS : uint8
{
ST_SIMPLE = 0, // single word
ST_SIMPLE, // single word
ST_SHOW, // for "show" output, 4 chars
};
// Flags for how to format description of action.
enum STR_ACTION : uint8
{
SA_SIMPLE = 0, // single word
SA_SIMPLE, // single word
SA_SHOW, // for "show" output, 4 chars
};
// Flags for how to format description of source.
enum STR_SOURCE : uint8
{
SO_SIMPLE = 0, // two words
SO_SIMPLE, // two words
SO_SHOW, // for "list" output, 3 chars
};
enum STR_PLATFORM : uint8
{
SP_WINDOWS,
SP_LINUX
};
// An individual plugin.
class MPlugin {
class MPlugin
{
public:
PLUG_STATUS m_status; // current status of plugin (loaded, etc)
PLUG_ACTION m_action; // what to do with plugin (load, unload, etc)
PLOAD_SOURCE m_source; // source of the request to load the plugin
int m_index; // 1-based
plugin_info_t *m_info; // information plugin provides about itself
CSysModule m_sys_module;
time_t m_time_loaded; // when plugin was loaded
int m_source_plugin_index; // who loaded this plugin
int m_unloader_index;
bool m_is_unloader; // fix to prevent other plugins unload active unloader.
MPlugin();
MPlugin(int index);
DLL_FUNCTIONS *m_dllapi_table;
DLL_FUNCTIONS *m_dllapi_post_table;
NEW_DLL_FUNCTIONS *m_newapi_table;
NEW_DLL_FUNCTIONS *m_newapi_post_table;
enginefuncs_t *m_engine_table;
enginefuncs_t *m_engine_post_table;
gamedll_funcs_t m_gamedll_funcs;
mutil_funcs_t m_mutil_funcs;
char m_filename[PATH_MAX]; // ie "dlls/mm_test_i386.so", from inifile
char *m_file; // ie "mm_test_i386.so", ptr from filename
char m_desc[MAX_DESC_LEN]; // ie "Test metamod plugin", from inifile
char m_pathname[PATH_MAX]; // UNIQUE, ie "/home/willday/half-life/cstrike/dlls/mm_test_i386.so", built with GameDLL.gamedir
int m_pfspecific; // level of specific platform affinity, used during load time
bool ini_parseline(char *line); // parse line from inifile
bool cmd_parseline(const char *line); // parse from console command
bool ini_parseline(char *line); // parse line from .ini file
bool cmd_parseline(const char *line); // parse from console command
bool plugin_parseline(const char *fname, int loader_index); // parse from plugin
bool check_input();
bool check_input(); // check filename, path, status
bool resolve(); // find a matching file on disk
char *resolve_dirs(char *path) const;
char *resolve_prefix(char *path) const;
char *resolve_suffix(char *path) const;
bool resolve(); // find a matching file on disk
char *resolve_dirs(const char *path, char *tempbuf, size_t bufsize) const; // try resolve filename in different dirs
char *resolve_suffix(const char *path, char *tempbuf, size_t bufsize) const; // try resolve given filename with different suffixes
bool platform_match(MPlugin* plugin) const;
bool platform_match(MPlugin* plugin) const; // check if a given plugin is the same but possibly for a different platform
bool load(PLUG_LOADTIME now);
bool unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, PL_UNLOAD_REASON real_reason);
bool load(PLUG_LOADTIME now); // load parsed plugin
bool unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
bool reload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
bool pause();
bool unpause();
@ -120,36 +101,66 @@ public:
bool newer_file() const; // check for newer file on disk
const char *str_status(STR_STATUS fmt) const;
const char *str_action(STR_ACTION fmt) const;
const char *str_source(STR_SOURCE fmt) const;
const char *str_reason(PL_UNLOAD_REASON preason, PL_UNLOAD_REASON preal_reason) const;
const char *str_status(STR_STATUS fmt = ST_SIMPLE) const;
const char *str_action(STR_ACTION fmt = SA_SIMPLE) const;
const char *str_source(STR_SOURCE fmt = SO_SIMPLE) const;
const char *str_reason(PL_UNLOAD_REASON reason) const;
static const char *str_loadtime(PLUG_LOADTIME pallow, STR_LOADTIME fmt);
const char *str_status() { return str_status(ST_SIMPLE); };
const char *str_action() { return str_action(SA_SIMPLE); };
const char *str_source() { return str_source(SO_SIMPLE); };
const char* str_loadable() const;
const char* str_unloadable() const;
const char* str_loadable(STR_LOADTIME fmt) const;
const char* str_unloadable(STR_LOADTIME fmt) const;
const char *str_loadable() {
if (m_info) return str_loadtime(m_info->loadable, SL_SIMPLE);
else return " -";
};
const char *str_unloadable() {
if (m_info) return str_loadtime(m_info->unloadable, SL_SIMPLE);
else return " -";
};
const char *str_loadable(STR_LOADTIME fmt) {
if (m_info) return str_loadtime(m_info->loadable, fmt);
else return " -";
};
const char *str_unloadable(STR_LOADTIME fmt) {
if (m_info) return str_loadtime(m_info->unloadable, fmt);
else return " -";
};
PLUG_STATUS status() const;
PLUG_ACTION action() const;
const char* description() const;
plugin_info_t* info() const;
int index() const;
int source_index() const;
const char* file() const;
const char* filename() const;
const char* pathname() const;
const CSysModule& sys_module() const;
size_t status_ptr();
void set_action(PLUG_ACTION action);
private:
bool query();
bool attach(PLUG_LOADTIME now);
bool detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
bool query(); // check exports, call init, getfnptrs and query
bool attach(PLUG_LOADTIME now); // call attach
bool detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason); // call detach
PLUG_STATUS m_status; // current status of plugin (loaded, etc)
PLUG_ACTION m_action; // what to do with plugin (load, unload, etc)
PLOAD_SOURCE m_source; // source of the request to load the plugin
STR_PLATFORM m_platform; // plugin platform
int m_index; // 1-based
plugin_info_t *m_info; // information plugin provides about itself
CSysModule m_sys_module; // system module
time_t m_time_loaded; // when plugin was loaded
int m_source_plugin_index; // who loaded this plugin
int m_unloader_index; // index of unloader plugin
bool m_is_unloader; // fix to prevent other plugins unload active unloader.
public:
// pointers to tables inside plugins
DLL_FUNCTIONS *m_dllapi_table;
DLL_FUNCTIONS *m_dllapi_post_table;
NEW_DLL_FUNCTIONS *m_newapi_table;
NEW_DLL_FUNCTIONS *m_newapi_post_table;
enginefuncs_t *m_engine_table;
enginefuncs_t *m_engine_post_table;
private:
gamedll_funcs_t m_gamedll_funcs;
mutil_funcs_t m_mutil_funcs;
char m_filename[PATH_MAX]; // ie "dlls/mm_test_i386.so", from inifile
char *m_file; // ie "mm_test_i386.so", ptr from filename
char m_desc[MAX_DESC_LEN]; // ie "Test metamod plugin", from inifile
char m_pathname[PATH_MAX]; // UNIQUE, ie "/home/willday/half-life/cstrike/dlls/mm_test_i386.so", built with GameDLL.gamedir
static const char *s_rPrintLoadTime[][4];
friend class MPluginList;
};

View File

@ -1,6 +1,6 @@
#include "precompiled.h"
MRegCmd::MRegCmd(char* cmd_name, REG_CMD_FN cmd_handler, MPlugin* cmd_plugin) : m_pfunction(cmd_handler), m_plugid(cmd_plugin->m_index), m_status(RG_VALID)
MRegCmd::MRegCmd(char* cmd_name, REG_CMD_FN cmd_handler, MPlugin* cmd_plugin) : m_pfunction(cmd_handler), m_plugid(cmd_plugin->index()), m_status(RG_VALID)
{
m_name = Q_strdup(cmd_name);
}
@ -112,7 +112,7 @@ void MRegCmdList::show() const
{
auto iplug = g_plugins->find(reg->m_plugid);
Q_strncpy(bplug, iplug ? iplug->m_desc : "(unknown)", sizeof bplug - 1);
Q_strncpy(bplug, iplug ? iplug->description() : "(unknown)", sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
}
else
@ -149,7 +149,7 @@ void MRegCmdList::show(int plugin_id) const
META_CONS("%d commands", total_count);
}
MRegCvar::MRegCvar(cvar_t* cv_ptr, MPlugin* cv_plugin) : m_cvar(cv_ptr), m_plugid(cv_plugin ? cv_plugin->m_index : 0), m_status(RG_VALID)
MRegCvar::MRegCvar(cvar_t* cv_ptr, MPlugin* cv_plugin) : m_cvar(cv_ptr), m_plugid(cv_plugin ? cv_plugin->index() : 0), m_status(RG_VALID)
{
m_cvar = new cvar_t;
m_cvar->name = Q_strdup(cv_ptr->name);
@ -228,7 +228,7 @@ void MRegCvarList::show() const
if (reg->m_status == RG_VALID)
{
auto plug = g_plugins->find(reg->m_plugid);
Q_strncpy(bplug, plug ? plug->m_desc : "(unknown)", sizeof bplug - 1);
Q_strncpy(bplug, plug ? plug->description() : "(unknown)", sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
}
else

View File

@ -252,7 +252,7 @@ const char* EXT_FUNC mutil_GetPluginPath(plid_t plid)
return nullptr;
}
Q_strncpy(buf, plug->m_pathname, sizeof buf - 1);
Q_strncpy(buf, plug->pathname(), sizeof buf - 1);
buf[sizeof buf - 1] = '\0';
return buf;
}
@ -301,7 +301,6 @@ int EXT_FUNC mutil_LoadMetaPlugin(plid_t plid, const char* fname, PLUG_LOADTIME
}
auto pl_loaded = g_plugins->plugin_addload(plid, fname, now);
if (!pl_loaded)
{
if (plugin_handle)
@ -309,13 +308,13 @@ int EXT_FUNC mutil_LoadMetaPlugin(plid_t plid, const char* fname, PLUG_LOADTIME
return 1; // TODO: WTF
}
else
{
if (plugin_handle)
*plugin_handle = (void *)pl_loaded->m_sys_module.gethandle();
return 0;
}
meta_rebuild_callbacks();
if (plugin_handle)
*plugin_handle = (void *)pl_loaded->sys_module().gethandle();
return 0;
}
int EXT_FUNC mutil_UnloadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
@ -339,8 +338,10 @@ int EXT_FUNC mutil_UnloadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIM
if (!findp || !unique)
return 1;
if (findp->plugin_unload(plid, now, reason))
if (findp->plugin_unload(plid, now, reason)) {
meta_rebuild_callbacks();
return 0;
}
return 1;
}
@ -357,8 +358,10 @@ int EXT_FUNC mutil_UnloadMetaPluginByHandle(plid_t plid, void *plugin_handle, PL
if (!findp)
return 1;
if (findp->plugin_unload(plid, now, reason))
if (findp->plugin_unload(plid, now, reason)) {
meta_rebuild_callbacks();
return 0;
}
return 1;
}

View File

@ -7,12 +7,14 @@ CSysModule::CSysModule() : m_handle(0), m_base(0), m_size(0)
#ifdef _WIN32
module_handle_t CSysModule::load(const char* filepath)
{
m_handle = LoadLibrary(filepath);
if (!m_handle) {
m_handle = LoadLibrary(filepath);
MODULEINFO module_info;
if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof module_info)) {
m_base = (uintptr_t)module_info.lpBaseOfDll;
m_size = module_info.SizeOfImage;
MODULEINFO module_info;
if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof module_info)) {
m_base = (uintptr_t)module_info.lpBaseOfDll;
m_size = module_info.SizeOfImage;
}
}
return m_handle;
@ -20,7 +22,7 @@ module_handle_t CSysModule::load(const char* filepath)
bool CSysModule::unload()
{
bool ret = false;
bool ret = true;
if (m_handle) {
ret = FreeLibrary(m_handle) != ERROR;
@ -34,7 +36,7 @@ bool CSysModule::unload()
void* CSysModule::getsym(const char* name) const
{
return GetProcAddress(m_handle, name);
return m_handle ? GetProcAddress(m_handle, name) : nullptr;
}
#else
static ElfW(Addr) dlsize(void* base)
@ -59,35 +61,38 @@ static ElfW(Addr) dlsize(void* base)
module_handle_t CSysModule::load(const char* filepath)
{
m_handle = dlopen(filepath, RTLD_NOW);
if (!m_handle) {
m_handle = dlopen(filepath, RTLD_NOW);
char buf[1024], dummy[1024], path[260];
sprintf(buf, "/proc/%i/maps", getpid());
char buf[1024], dummy[1024], path[260];
sprintf(buf, "/proc/%i/maps", getpid());
FILE* fp = fopen(buf, "r");
FILE* fp = fopen(buf, "r");
while (fgets(buf, sizeof buf, fp)) {
uintptr_t start, end;
while (fgets(buf, sizeof buf, fp)) {
uintptr_t start, end;
int args = sscanf(buf, "%x-%x %128s %128s %128s %128s %255s", &start, &end, dummy, dummy, dummy, dummy, path);
if (args != 7) {
continue;
int args = sscanf(buf, "%x-%x %128s %128s %128s %128s %255s", &start, &end, dummy, dummy, dummy, dummy, path);
if (args != 7) {
continue;
}
if (!Q_stricmp(path, filepath)) {
m_base = start;
m_size = end - start;
break;
}
}
if (!Q_stricmp(path, filepath)) {
m_base = start;
m_size = end - start;
break;
}
fclose(fp);
}
fclose(fp);
return m_handle;
}
bool CSysModule::unload()
{
bool ret = false;
bool ret = true;
if (m_handle) {
ret = dlclose(m_handle) != 0;
@ -101,7 +106,7 @@ bool CSysModule::unload()
void* CSysModule::getsym(const char* name) const
{
return dlsym(m_handle, name);
return m_handle ? dlsym(m_handle, name) : nullptr;
}
#endif
@ -130,7 +135,7 @@ const char* CSysModule::getloaderror()
// http://msdn.microsoft.com/library/en-us/debug/errors_0sdh.asp
// except without FORMAT_MESSAGE_ALLOCATE_BUFFER, since we use a local
// static buffer.
const char *str_GetLastError()
static const char *str_GetLastError()
{
static char buf[MAX_STRBUF_LEN];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, MAX_STRBUF_LEN - 1, nullptr);

View File

@ -4,7 +4,7 @@
// NOTE: order is crucial, as greater/less comparisons are made.
enum PLUG_LOADTIME
{
PT_NEVER = 0,
PT_NEVER,
PT_STARTUP, // should only be loaded/unloaded at initial hlds execution
PT_CHANGELEVEL, // can be loaded/unloaded between maps
PT_ANYTIME, // can be loaded/unloaded at any time
@ -14,7 +14,7 @@ enum PLUG_LOADTIME
// Flags to indicate why the plugin is being unloaded.
enum PL_UNLOAD_REASON
{
PNL_NULL = 0,
PNL_NULL,
PNL_INI_DELETED, // was deleted from plugins.ini
PNL_FILE_NEWER, // file on disk is newer than last load
PNL_COMMAND, // requested by server/console command

View File

@ -31,11 +31,9 @@
#include "metamod.h"
#include "log_meta.h"
#include "conf_meta.h"
#include "support_meta.h"
#include "dllapi.h"
#include "engine_api.h"
#include "game_support.h"
#include "meta_eiface.h"
#include "mreg.h"
#include "meta_api.h"
#include "mutil.h"

View File

@ -30,7 +30,7 @@ void EXT_FUNC meta_AddServerCommand(char *cmd_name, void (*function)())
{
MPlugin *plug = g_plugins->find_memloc(function);
META_DEBUG(4, "called: meta_AddServerCommand; cmd_name=%s, function=%d, plugin=%s", cmd_name, function, plug ? plug->m_file : "unknown");
META_DEBUG(4, "called: meta_AddServerCommand; cmd_name=%s, function=%d, plugin=%s", cmd_name, function, plug ? plug->file() : "unknown");
if (!plug) {
META_ERROR("Failed to find memloc for regcmd '%s'", cmd_name);

View File

@ -1,6 +1,6 @@
#include "precompiled.h"
char *UTIL_VarArgs(char *format, ...)
char *UTIL_VarArgs(const char *format, ...)
{
va_list argptr;
static char string[1024];

View File

@ -13,4 +13,5 @@
#include "enginecallbacks.h"
#include <util.h>
char *UTIL_VarArgs(const char *format, ...);
void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage);

View File

@ -1,91 +0,0 @@
#include "precompiled.h"
void __declspec(noreturn) do_exit(int exitval)
{
//Allahu Akbar!!
*((int *)nullptr) = 0;
}
// Checks for a non-empty file, relative to the gamedir if necessary.
// Formerly used LOAD_FILE_FOR_ME, which provided a simple way to check for
// a file under the gamedir, but which would _also_ look in the sibling
// "valve" directory, thus sometimes finding files that weren't desired.
// Also, formerly named just "valid_file".
//
// Special-case-recognize "/dev/null" as a valid file.
bool FileExistsInGameDir(const char *path)
{
struct stat st;
char buf[PATH_MAX];
if (!path)
return false;
if (!Q_strcmp(path, "/dev/null"))
return true;
if (IsAbsolutePath(path))
{
Q_strncpy(buf, path, sizeof buf);
buf[sizeof buf - 1] = '\0';
}
else
snprintf(buf, sizeof buf, "%s/%s", g_GameDLL.gamedir, path);
int ret = stat(buf, &st);
if (ret != 0)
{
META_DEBUG(5, "Unable to stat '%s': %s", buf, strerror(errno));
return false;
}
int reg = S_ISREG(st.st_mode);
if (!reg)
{
META_DEBUG(5, "Not a regular file: %s", buf);
return false;
}
if (!st.st_size)
{
META_DEBUG(5, "Empty file: %s", buf);
return false;
}
if (ret == 0 && reg)
return true;
return false;
}
// Turns path into a full path:
// - if not absolute, prepends gamedir
// - calls realpath() to collapse ".." and such
// - calls NormalizePath() to fix backslashes, etc
//
// Much like realpath, buffer pointed to by fullpath is assumed to be
// able to store a string of PATH_MAX length.
char* full_gamedir_path(const char* path, char* fullpath)
{
char buf[PATH_MAX];
// Build pathname from filename, plus gamedir if relative path.
if (IsAbsolutePath(path))
{
Q_strncpy(buf, path, sizeof buf - 1);
buf[sizeof buf - 1] = '\0';
}
else snprintf(buf, sizeof buf, "%s/%s", g_GameDLL.gamedir, path);
// Remove relative path components, if possible.
if (!realpath(buf, fullpath))
{
META_DEBUG(4, "Unable to get realpath for '%s': %s", buf, str_os_error());
Q_strncpy(fullpath, path, sizeof fullpath - 1);
fullpath[sizeof fullpath - 1] = '\0';
}
// Replace backslashes, etc.
NormalizePath(fullpath);
return fullpath;
}

View File

@ -1,23 +0,0 @@
#pragma once
#include <sys/types.h> // stat
#include <sys/stat.h> // stat
#include "osdep.h" // _stricmp, S_ISREG,
void __declspec(noreturn) do_exit(int exitval);
bool FileExistsInGameDir(const char *path);
char *full_gamedir_path(const char *path, char *fullpath);
// Turn a variable/function name into the corresponding string, optionally
// stripping off the leading "len" characters. Useful for things like
// turning 'pfnClientCommand' into "ClientCommand" so we don't have to
// specify strings used for all the debugging/log messages.
#define STRINGIZE(name, len) #name+len
// Max description length for plugins.ini and other places.
#define MAX_DESC_LEN 256
// For various character string buffers.
#define MAX_STRBUF_LEN 1024

View File

@ -1,5 +1,13 @@
#include "precompiled.h"
const char* g_platform_postfixes[4] =
{
"_i386.so",
"_i486.so",
"_i586.so",
"_i686.so",
};
bool is_yes(const char* str)
{
return !Q_strcmp(str, "true") || !Q_strcmp(str, "yes") || !Q_strcmp(str, "1");
@ -119,7 +127,7 @@ char *trimbuf(char *str)
return str;
}
void NormalizePath(char *path)
void normalize_path(char *path)
{
#ifdef _WIN32
for (char* cp = path; *cp; cp++)
@ -133,7 +141,7 @@ void NormalizePath(char *path)
#endif
}
bool IsAbsolutePath(const char *path)
bool is_abs_path(const char *path)
{
if (path[0] == '/') return true;
#ifdef _WIN32
@ -143,6 +151,23 @@ bool IsAbsolutePath(const char *path)
return false;
}
bool is_valid_path(const char *path)
{
struct stat st;
return !stat(path, &st) && S_ISREG(st.st_mode);
}
bool is_platform_postfix(const char* pf)
{
if (pf) {
for (size_t i = 0; i < arraysize(g_platform_postfixes); i++) {
if (!Q_strcmp(pf, g_platform_postfixes[i]))
return true;
}
}
return false;
}
#ifdef _WIN32
char *realpath(const char *file_name, char *resolved_name)
{
@ -162,10 +187,94 @@ char *realpath(const char *file_name, char *resolved_name)
}
FindClose(handle);
NormalizePath(resolved_name);
normalize_path(resolved_name);
return resolved_name;
}
return nullptr;
}
#endif // _WIN32
void __declspec(noreturn) do_exit(int exitval)
{
//Allahu Akbar!!
*((int *)nullptr) = 0;
}
// Checks for a non-empty file, relative to the gamedir if necessary.
// Formerly used LOAD_FILE_FOR_ME, which provided a simple way to check for
// a file under the gamedir, but which would _also_ look in the sibling
// "valve" directory, thus sometimes finding files that weren't desired.
// Also, formerly named just "valid_file".
//
// Special-case-recognize "/dev/null" as a valid file.
bool is_file_exists_in_gamedir(const char *path)
{
char buf[PATH_MAX];
if (!path)
return false;
if (!Q_strcmp(path, "/dev/null"))
return true;
if (is_abs_path(path)) {
Q_strncpy(buf, path, sizeof buf);
buf[sizeof buf - 1] = '\0';
}
else
snprintf(buf, sizeof buf, "%s/%s", g_GameDLL.gamedir, path);
struct stat st;
int ret = stat(buf, &st);
if (ret != 0) {
META_DEBUG(5, "Unable to stat '%s': %s", buf, strerror(errno));
return false;
}
int reg = S_ISREG(st.st_mode);
if (!reg) {
META_DEBUG(5, "Not a regular file: %s", buf);
return false;
}
if (!st.st_size) {
META_DEBUG(5, "Empty file: %s", buf);
return false;
}
if (ret == 0 && reg)
return true;
return false;
}
// Turns path into a full path:
// - if not absolute, prepends gamedir
// - calls realpath() to collapse ".." and such
// - calls NormalizePath() to fix backslashes, etc
//
// Much like realpath, buffer pointed to by fullpath is assumed to be
// able to store a string of PATH_MAX length.
char* full_gamedir_path(const char* path, char* fullpath)
{
char buf[PATH_MAX];
// Build pathname from filename, plus gamedir if relative path.
if (is_abs_path(path)) {
Q_strncpy(buf, path, sizeof buf - 1);
buf[sizeof buf - 1] = '\0';
}
else snprintf(buf, sizeof buf, "%s/%s", g_GameDLL.gamedir, path);
// Remove relative path components, if possible.
if (!realpath(buf, fullpath)) {
META_DEBUG(4, "Unable to get realpath for '%s': %s", buf, str_os_error());
Q_strncpy(fullpath, path, sizeof fullpath - 1);
fullpath[sizeof fullpath - 1] = '\0';
}
// Replace backslashes, etc.
normalize_path(fullpath);
return fullpath;
}

View File

@ -1,5 +1,17 @@
#pragma once
// Turn a variable/function name into the corresponding string, optionally
// stripping off the leading "len" characters. Useful for things like
// turning 'pfnClientCommand' into "ClientCommand" so we don't have to
// specify strings used for all the debugging/log messages.
#define STRINGIZE(name, len) #name+len
// Max description length for plugins.ini and other places.
#define MAX_DESC_LEN 256
// For various character string buffers.
#define MAX_STRBUF_LEN 1024
template <typename T, size_t N>
char(&ArraySizeHelper(T(&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
@ -54,5 +66,14 @@ char *realpath(const char *file_name, char *resolved_name);
#endif // _WIN32
char* trimbuf(char *str);
void NormalizePath(char *path);
bool IsAbsolutePath(const char *path);
void normalize_path(char *path);
bool is_abs_path(const char *path);
bool is_valid_path(const char *path);
bool is_platform_postfix(const char *pf);
void __declspec(noreturn) do_exit(int exitval);
bool is_file_exists_in_gamedir(const char *path);
char *full_gamedir_path(const char *path, char *fullpath);
extern const char* g_platform_postfixes[4];