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:
parent
d1d2a9b755
commit
f7c115e736
@ -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, ...);
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -193,7 +193,7 @@ void MConfig::set_directory()
|
||||
}
|
||||
#endif
|
||||
|
||||
NormalizePath(m_directory);
|
||||
normalize_path(m_directory);
|
||||
|
||||
// get directory
|
||||
char *dir = Q_strrchr(m_directory, '/');
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
};
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user