Merge pull request #133 from alliedmodders/logger-logic

Move Logger and core natives from core to logic (r=dvander).
This commit is contained in:
Nicholas Hastings
2014-08-20 06:43:31 -04:00
31 changed files with 832 additions and 751 deletions
+2
View File
@@ -66,6 +66,8 @@ binary.sources += [
'sm_trie.cpp',
'smn_console.cpp',
'ProfileTools.cpp',
'Logger.cpp',
'smn_core.cpp',
]
if builder.target_platform == 'windows':
binary.sources += ['thread/WinThreads.cpp']
+2 -2
View File
@@ -198,11 +198,11 @@ private:
if (!m_bFileNameLogged)
{
smcore.LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
logger->LogError("[SM] Parse error(s) detected in file \"%s\":", m_File);
m_bFileNameLogged = true;
}
smcore.LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer);
logger->LogError("[SM] (Line %d): %s", states ? states->line : 0, buffer);
}
private:
bool m_bFileNameLogged;
+3 -3
View File
@@ -89,11 +89,11 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
ke::AutoLock lock(&m_ConfigLock);
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
{
smcore.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
if (err != SMCError_Custom)
{
const char *txt = textparsers->GetSMCErrorString(err);
smcore.LogError("[SM] Line %d: %s", states.line, txt);
logger->LogError("[SM] Line %d: %s", states.line, txt);
}
}
}
@@ -541,7 +541,7 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
{
if (!s_OneTimeThreaderErrorMsg)
{
smcore.LogError("[SM] Unable to create db threader (error unknown)");
logger->LogError("[SM] Unable to create db threader (error unknown)");
s_OneTimeThreaderErrorMsg = true;
}
m_Worker = NULL;
+20 -19
View File
@@ -32,6 +32,7 @@
#include <IPluginSys.h>
#include <stdarg.h>
#include "DebugReporter.h"
#include "Logger.h"
DebugReport g_DbgReporter;
@@ -49,7 +50,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
va_end(ap);
smcore.Log("[SM] %s", buffer);
g_Logger.LogMessage("[SM] %s", buffer);
}
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
@@ -71,12 +72,12 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
if (error)
{
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
} else {
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
}
smcore.LogError("[SM] %s", buffer);
g_Logger.LogError("[SM] %s", buffer);
if (func_idx != -1)
{
@@ -86,7 +87,7 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
sp_public_t *function;
if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
{
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
}
}
}
@@ -106,18 +107,18 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
if (error)
{
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
} else {
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
}
smcore.LogError("[SM] %s", buffer);
g_Logger.LogError("[SM] %s", buffer);
IPluginDebugInfo *pDebug;
if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL)
{
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
_GetPluginIndex(pContext));
return;
}
@@ -125,9 +126,9 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
const char *name;
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
{
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
} else {
smcore.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
}
}
@@ -139,7 +140,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
if (n_err != SP_ERROR_NATIVE)
{
smcore.LogError("[SM] Plugin encountered error %d: %s",
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
n_err,
error->GetErrorString());
}
@@ -149,26 +150,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
const char *custerr;
if ((custerr=error->GetCustomErrorString()) != NULL)
{
smcore.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
} else {
smcore.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
}
}
if (!error->DebugInfoAvailable())
{
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
_GetPluginIndex(ctx));
return;
}
CallStackInfo stk_info;
int i = 0;
smcore.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
while (error->GetTraceInfo(&stk_info))
{
smcore.LogError("[SM] [%d] Line %d, %s::%s()",
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
i++,
stk_info.line,
stk_info.filename,
+1 -1
View File
@@ -606,7 +606,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
{
if (bErrorOnMissing || libsys->IsPathFile(p->GetPath()))
{
smcore.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
logger->LogError("[SM] Unable to load extension \"%s\": %s", path, error);
}
p->SetError(error);
+14 -14
View File
@@ -301,8 +301,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
if (error[0] != '\0')
{
m_IgnoreLevel = 1;
smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
smcore.LogError("[SM] %s", error);
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
logger->LogError("[SM] %s", error);
} else {
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
}
@@ -335,8 +335,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
{
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0)
{
smcore.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
smcore.LogError("[SM] Unrecognized platform \"%s\"", name);
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
}
m_IgnoreLevel = 1;
}
@@ -435,7 +435,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
}
else
{
smcore.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
}
} else if (strcmp(key, "signature") == 0) {
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
@@ -503,7 +503,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
&& (!m_Offsets.retrieve(m_offset)))
{
smcore.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
logger->LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
m_Class,
m_Prop,
m_CurFile,
@@ -556,7 +556,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
void *final_addr = NULL;
if (addrInBase == NULL)
{
smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
s_TempSig.library,
m_CurFile);
}
@@ -570,7 +570,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (VirtualQuery(addrInBase, &mem, sizeof(mem)))
final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]);
else
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
#elif defined PLATFORM_POSIX
Dl_info info;
/* GNU only: returns 0 on error, inconsistent! >:[ */
@@ -585,12 +585,12 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
final_addr = dlsym(handle, &s_TempSig.sig[1]);
dlclose(handle);
} else {
smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
s_TempSig.library,
m_File);
}
} else {
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
s_TempSig.library,
m_File);
}
@@ -827,8 +827,8 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
{
const char *msg = textparsers->GetSMCErrorString(err);
smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path);
logger->LogError("[SM] Error %d on line %d, col %d: %s",
err,
state.line,
state.col,
@@ -915,8 +915,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
{
const char *msg = textparsers->GetSMCErrorString(err);
smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
logger->LogError("[SM] Error %d on line %d, col %d: %s",
err,
state.line,
state.col,
+2 -2
View File
@@ -957,8 +957,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
}
#define HANDLE_LOG_VERY_BAD(message, ...) \
smcore.LogFatal(message, ##__VA_ARGS__); \
smcore.LogError(message, ##__VA_ARGS__);
logger->LogFatal(message, ##__VA_ARGS__); \
logger->LogError(message, ##__VA_ARGS__);
bool HandleSystem::TryAndFreeSomeHandles()
{
+551
View File
@@ -0,0 +1,551 @@
/**
* vim: set ts=4 sw=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <time.h>
#include <cstdarg>
#include "Logger.h"
#include <sourcemod_version.h>
#include <ISourceMod.h>
Logger g_Logger;
/**
* :TODO: This should be creating the log folder if it doesn't exist
*/
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{
if (strcasecmp(key, "Logging") == 0)
{
bool state;
if (strcasecmp(value, "on") == 0)
{
state = true;
} else if (strcasecmp(value, "off") == 0) {
state = false;
} else {
smcore.Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
return ConfigResult_Reject;
}
if (source == ConfigSource_Console)
{
state ? EnableLogging() : DisableLogging();
} else {
m_InitialState = state;
}
return ConfigResult_Accept;
} else if (strcasecmp(key, "LogMode") == 0) {
if (strcasecmp(value, "daily") == 0)
{
m_Mode = LoggingMode_Daily;
} else if (strcasecmp(value, "map") == 0) {
m_Mode = LoggingMode_PerMap;
} else if (strcasecmp(value, "game") == 0) {
m_Mode = LoggingMode_Game;
} else {
smcore.Format(error, maxlength, "Invalid value: must be [daily|map|game]");
return ConfigResult_Reject;
}
return ConfigResult_Accept;
}
return ConfigResult_Ignore;
}
void Logger::OnSourceModStartup(bool late)
{
InitLogger(m_Mode);
}
void Logger::OnSourceModAllShutdown()
{
CloseLogger();
}
void Logger::OnSourceModLevelChange(const char *mapName)
{
MapChange(mapName);
}
void Logger::_NewMapFile()
{
if (!m_Active)
{
return;
}
/* Append "Log file closed" to previous log file */
_CloseFile();
char _filename[256];
int i = 0;
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
while (true)
{
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
FILE *fp = fopen(_filename, "r");
if (!fp)
{
break;
}
fclose(fp);
i++;
}
m_NrmFileName.assign(_filename);
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
if (!fp)
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return;
} else {
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
fclose(fp);
}
}
void Logger::_CloseFile()
{
if (!m_Active)
{
return;
}
FILE *fp = NULL;
if (!m_NrmFileName.empty())
{
fp = fopen(m_NrmFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogMessage("Log file closed.");
fclose(fp);
}
m_NrmFileName.clear();
}
if (!m_ErrMapStart)
{
return;
}
fp = fopen(m_ErrFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogError("Error log file session closed.");
fclose(fp);
}
m_ErrFileName.clear();
}
void Logger::InitLogger(LoggingMode mode)
{
m_Mode = mode;
m_Active = m_InitialState;
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
m_NrmCurDay = curtime->tm_mday;
m_ErrCurDay = curtime->tm_mday;
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrFileName.assign(_filename);
switch (m_Mode)
{
case LoggingMode_PerMap:
{
if (!m_Active)
{
m_DelayedStart = true;
}
break;
}
case LoggingMode_Daily:
{
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_NrmFileName.assign(_filename);
m_DailyPrintHdr = true;
break;
}
default:
{
/* do nothing... */
break;
}
}
}
void Logger::CloseLogger()
{
_CloseFile();
}
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
{
if (!m_Active)
{
return;
}
va_list ap;
va_start(ap, msg);
LogToOpenFileEx(fp, msg, ap);
va_end(ap);
}
void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
{
if (!m_Active)
{
return;
}
va_list ap;
va_start(ap, msg);
LogToFileOnlyEx(fp, msg, ap);
va_end(ap);
}
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
{
if (!m_Active)
{
return;
}
static ConVar *sv_logecho = smcore.FindConVar("sv_logecho");
char buffer[3072];
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer);
if (!sv_logecho || smcore.GetCvarBool(sv_logecho))
{
static char conBuffer[4096];
smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
smcore.ConPrint(conBuffer);
}
}
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
{
if (!m_Active)
{
return;
}
char buffer[3072];
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer);
fflush(fp);
}
void Logger::LogMessage(const char *vafmt, ...)
{
va_list ap;
va_start(ap, vafmt);
LogMessageEx(vafmt, ap);
va_end(ap);
}
void Logger::LogMessageEx(const char *vafmt, va_list ap)
{
if (!m_Active)
{
return;
}
if (m_Mode == LoggingMode_Game)
{
_PrintToGameLog(vafmt, ap);
return;
}
if (m_DelayedStart)
{
m_DelayedStart = false;
_NewMapFile();
}
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
FILE *fp = NULL;
if (m_Mode == LoggingMode_PerMap)
{
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
_NewMapFile();
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
goto print_error;
}
}
} else {
if (m_NrmCurDay != curtime->tm_mday)
{
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_NrmFileName.assign(_filename);
m_NrmCurDay = curtime->tm_mday;
m_DailyPrintHdr = true;
}
fp = fopen(m_NrmFileName.c_str(), "a+");
}
if (fp)
{
if (m_DailyPrintHdr)
{
char date[32];
m_DailyPrintHdr = false;
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
} else {
goto print_error;
}
return;
print_error:
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
}
void Logger::LogError(const char *vafmt, ...)
{
va_list ap;
va_start(ap, vafmt);
LogErrorEx(vafmt, ap);
va_end(ap);
}
void Logger::LogErrorEx(const char *vafmt, va_list ap)
{
if (!m_Active)
{
return;
}
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
if (curtime->tm_mday != m_ErrCurDay)
{
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrFileName.assign(_filename);
m_ErrCurDay = curtime->tm_mday;
m_ErrMapStart = false;
}
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
if (fp)
{
if (!m_ErrMapStart)
{
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod error session started\n", date);
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrMapStart = true;
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
}
else
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return;
}
}
void Logger::MapChange(const char *mapname)
{
m_CurMapName.assign(mapname);
switch (m_Mode)
{
case LoggingMode_Daily:
{
LogMessage("-------- Mapchange to %s --------", mapname);
break;
}
case LoggingMode_PerMap:
{
_NewMapFile();
break;
}
default:
{
/* Do nothing... */
break;
}
}
if (m_ErrMapStart)
{
LogError("Error log file session closed.");
}
m_ErrMapStart = false;
}
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
{
char msg[3072];
size_t len;
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
msg[len++] = '\n';
msg[len] = '\0';
smcore.LogToGame(msg);
}
const char *Logger::GetLogFileName(LogType type) const
{
switch (type)
{
case LogType_Normal:
{
return m_NrmFileName.c_str();
}
case LogType_Error:
{
return m_ErrFileName.c_str();
}
default:
{
return "";
}
}
}
LoggingMode Logger::GetLoggingMode() const
{
return m_Mode;
}
void Logger::EnableLogging()
{
if (m_Active)
{
return;
}
m_Active = true;
LogMessage("[SM] Logging enabled manually by user.");
}
void Logger::DisableLogging()
{
if (!m_Active)
{
return;
}
LogMessage("[SM] Logging disabled manually by user.");
m_Active = false;
}
void Logger::LogFatal(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
LogFatalEx(msg, ap);
va_end(ap);
}
void Logger::LogFatalEx(const char *msg, va_list ap)
{
/* :TODO: make this print all pretty-like
* In fact, the pretty log printing function should be abstracted.
* It's already implemented twice which is bad.
*/
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
FILE *fp = fopen(path, "at");
if (fp)
{
m_Active = true;
LogToOpenFileEx(fp, msg, ap);
m_Active = false;
fclose(fp);
}
}
+111
View File
@@ -0,0 +1,111 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_CLOGGER_H_
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
#include <stdio.h>
#include <sh_string.h>
#include "common_logic.h"
using namespace SourceHook;
enum LogType
{
LogType_Normal,
LogType_Error
};
enum LoggingMode
{
LoggingMode_Daily,
LoggingMode_PerMap,
LoggingMode_Game
};
class Logger : public SMGlobalClass, public ILogger
{
public:
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
m_InitialState(true)
{
}
public: //SMGlobalClass
ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength);
void OnSourceModStartup(bool late);
void OnSourceModAllShutdown();
void OnSourceModLevelChange(const char *mapName);
public:
void InitLogger(LoggingMode mode);
void CloseLogger();
void EnableLogging();
void DisableLogging();
void LogMessage(const char *msg, ...);
void LogMessageEx(const char *msg, va_list ap);
void LogError(const char *msg, ...);
void LogErrorEx(const char *msg, va_list ap);
void LogFatal(const char *msg, ...);
void LogFatalEx(const char *msg, va_list ap);
void LogToOpenFile(FILE *fp, const char *msg, ...);
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
/* This version does not print to console, and is thus thread-safe */
void LogToFileOnly(FILE *fp, const char *msg, ...);
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
void MapChange(const char *mapname);
const char *GetLogFileName(LogType type) const;
LoggingMode GetLoggingMode() const;
private:
void _CloseFile();
void _NewMapFile();
void _PrintToGameLog(const char *fmt, va_list ap);
private:
String m_NrmFileName;
String m_ErrFileName;
String m_CurMapName;
LoggingMode m_Mode;
int m_NrmCurDay;
int m_ErrCurDay;
bool m_ErrMapStart;
bool m_Active;
bool m_DelayedStart;
bool m_DailyPrintHdr;
bool m_InitialState;
};
extern Logger g_Logger;
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
+7 -6
View File
@@ -42,6 +42,7 @@
#include "GameConfigs.h"
#include "common_logic.h"
#include "Translator.h"
#include "Logger.h"
CPluginManager g_PluginSys;
HandleType_t g_PluginType = 0;
@@ -844,8 +845,8 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
{
char error[256];
libsys->GetPlatformError(error, sizeof(error));
smcore.LogError("[SM] Failure reading from plugins path: %s", localpath);
smcore.LogError("[SM] Platform returned error: %s", error);
g_Logger.LogError("[SM] Failure reading from plugins path: %s", localpath);
g_Logger.LogError("[SM] Platform returned error: %s", error);
return;
}
@@ -990,9 +991,9 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de
} else {
if (bulletinUrl[0] != '\0')
{
smcore.Log("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
} else {
smcore.Log("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
}
}
}
@@ -1094,7 +1095,7 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure)
{
smcore.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
pl->SetErrorState(
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
"%s",
@@ -1136,7 +1137,7 @@ void CPluginManager::LoadAll_SecondPass()
error[0] = '\0';
if (!RunSecondPass(pPlugin, error, sizeof(error)))
{
smcore.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
g_Logger.LogError("[SM] Unable to load plugin \"%s\": %s", pPlugin->GetFilename(), error);
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
}
}
+13 -13
View File
@@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...)
if (!m_FileLogged)
{
smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
logger->LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
m_FileLogged = true;
}
smcore.LogError("[SM] %s", buffer);
logger->LogError("[SM] %s", buffer);
}
void CPhraseFile::ReparseFile()
@@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str();
}
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
}
const char *code;
@@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str();
}
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
code,
m_File.c_str());
smcore.LogError("[SM] Error (line %d, column %d): %s",
logger->LogError("[SM] Error (line %d, column %d): %s",
states.line,
states.col,
msg);
@@ -831,13 +831,13 @@ void Translator::RebuildLanguageDatabase()
str_err = m_CustomError.c_str();
}
smcore.LogError("[SM] Failed to parse language header file: \"%s\"", path);
smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
logger->LogError("[SM] Failed to parse language header file: \"%s\"", path);
logger->LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
}
if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang))
{
smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
logger->LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
@@ -845,7 +845,7 @@ void Translator::RebuildLanguageDatabase()
if (!m_Languages.size())
{
smcore.LogError("[SM] Fatal error, no languages found! Translation will not work.");
logger->LogError("[SM] Fatal error, no languages found! Translation will not work.");
}
for (size_t i=0; i<m_Files.size(); i++)
@@ -872,7 +872,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
if (!m_InLanguageSection)
{
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
logger->LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
}
return SMCResult_Continue;
@@ -1025,11 +1025,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned
{
if (fail_phrase != NULL)
{
smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase);
logger->LogError("[SM] Could not find core phrase: %s", fail_phrase);
}
else
{
smcore.LogError("[SM] Unknown fatal error while translating a core phrase.");
logger->LogError("[SM] Unknown fatal error while translating a core phrase.");
}
return false;
+4
View File
@@ -50,6 +50,7 @@
#include "ForwardSys.h"
#include "AdminCache.h"
#include "ProfileTools.h"
#include "Logger.h"
sm_core_t smcore;
IHandleSys *handlesys = &g_HandleSys;
@@ -72,6 +73,8 @@ ISourcePawnEngine *g_pSourcePawn;
ISourcePawnEngine2 *g_pSourcePawn2;
CNativeOwner g_CoreNatives;
IScriptManager *scripts = &g_PluginSys;
IExtensionSys *extsys = &g_Extensions;
ILogger *logger = &g_Logger;
static void AddCorePhraseFile(const char *filename)
{
@@ -140,6 +143,7 @@ static sm_logic_t logic =
&g_Forwards,
&g_Admins,
NULL,
&g_Logger,
-1.0f
};
+2
View File
@@ -53,6 +53,8 @@ extern IPlayerManager *playerhelpers;
extern IAdminSystem *adminsys;
extern IGameHelpers *gamehelpers;
extern IScriptManager *scripts;
extern IExtensionSys *extsys;
extern ILogger *logger;
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
+12 -6
View File
@@ -52,7 +52,7 @@ using namespace SourceHook;
* Add 1 to the RHS of this expression to bump the intercom file
* This is to prevent mismatching core/logic binaries
*/
#define SM_LOGIC_MAGIC (0x0F47C0DE - 28)
#define SM_LOGIC_MAGIC (0x0F47C0DE - 29)
#if defined SM_LOGIC
class IVEngineServer
@@ -214,6 +214,14 @@ public:
virtual void CallOnCoreMapEnd() = 0;
};
class ILogger
{
public:
virtual void LogMessage(const char *msg, ...) = 0;
virtual void LogError(const char *msg, ...) = 0;
virtual void LogFatal(const char *msg, ...) = 0;
};
class AutoPluginList
{
public:
@@ -274,13 +282,10 @@ struct sm_core_t
ConVar * (*FindConVar)(const char*);
unsigned int (*strncopy)(char*, const char*, size_t);
char * (*TrimWhitespace)(char *, size_t &);
void (*LogError)(const char*, ...);
void (*LogFatal)(const char*, ...);
void (*Log)(const char*, ...);
void (*LogToFile)(FILE *fp, const char*, ...);
void (*LogToGame)(const char *message);
void (*ConPrint)(const char *message);
const char * (*GetCvarString)(ConVar*);
bool (*GetCvarBool)(ConVar*);
size_t (*Format)(char*, size_t, const char*, ...);
size_t (*FormatArgs)(char*, size_t, const char*,va_list ap);
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
@@ -326,7 +331,7 @@ struct sm_logic_t
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
IGameConfig * (*GetCoreGameConfig)();
bool (*OnLogPrint)(const char *msg); // true to supercede
bool (*OnLogPrint)(const char *msg); // true to supersede
IDebugListener *debugger;
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
void (*AddNatives)(sp_nativeinfo_t *natives);
@@ -340,6 +345,7 @@ struct sm_logic_t
IForwardManager *forwardsys;
IAdminSystem *adminsys;
IdentityToken_t *core_ident;
ILogger *logger;
float sentinel;
};
+777
View File
@@ -0,0 +1,777 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include "common_logic.h"
#include "Logger.h"
#include <ISourceMod.h>
#include <ITranslator.h>
#include <sourcehook.h>
#include <sh_memory.h>
#if defined PLATFORM_WINDOWS
#include <windows.h>
#elif defined PLATFORM_POSIX
#include <limits.h>
#include <unistd.h>
#include <sys/times.h>
#endif
HandleType_t g_PlIter;
IForward *g_OnLogAction = NULL;
static ConVar *sm_datetime_format = NULL;
class CoreNativeHelpers :
public SMGlobalClass,
public IHandleTypeDispatch
{
public:
void OnSourceModAllInitialized()
{
HandleAccess hacc;
handlesys->InitAccessDefaults(NULL, &hacc);
hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
g_PlIter = handlesys->CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL);
g_OnLogAction = forwardsys->CreateForward("OnLogAction",
ET_Hook,
5,
NULL,
Param_Cell,
Param_Cell,
Param_Cell,
Param_Cell,
Param_String);
sm_datetime_format = smcore.FindConVar("sm_datetime_format");
}
void OnHandleDestroy(HandleType_t type, void *object)
{
IPluginIterator *iter = (IPluginIterator *)object;
iter->Release();
}
void OnSourceModShutdown()
{
forwardsys->ReleaseForward(g_OnLogAction);
handlesys->RemoveType(g_PlIter, g_pCoreIdent);
}
} g_CoreNativeHelpers;
void LogAction(Handle_t hndl, int type, int client, int target, const char *message)
{
if (g_OnLogAction->GetFunctionCount())
{
cell_t result = 0;
g_OnLogAction->PushCell(hndl);
g_OnLogAction->PushCell(type);
g_OnLogAction->PushCell(client);
g_OnLogAction->PushCell(target);
g_OnLogAction->PushString(message);
g_OnLogAction->Execute(&result);
if (result >= (ResultType)Pl_Handled)
{
return;
}
}
const char *logtag = "SM";
if (type == 2)
{
HandleError err;
IPlugin *pPlugin = scripts->FindPluginByHandle(hndl, &err);
if (pPlugin)
{
logtag = pPlugin->GetFilename();
}
}
g_Logger.LogMessage("[%s] %s", logtag, message);
}
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
{
char buffer[512];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (pContext->GetLastNativeError() == SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
}
return 0;
}
static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
{
time_t t = g_pSM->GetAdjustedTime();
cell_t *addr;
pContext->LocalToPhysAddr(params[1], &addr);
*(time_t *)addr = t;
return static_cast<cell_t>(t);
}
#if defined SUBPLATFORM_SECURECRT
void _ignore_invalid_parameter(
const wchar_t * expression,
const wchar_t * function,
const wchar_t * file,
unsigned int line,
uintptr_t pReserved
)
{
/* Wow we don't care, thanks Microsoft. */
}
#endif
static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
{
char *format, *buffer;
pContext->LocalToString(params[1], &buffer);
pContext->LocalToStringNULL(params[3], &format);
if (format == NULL)
{
format = const_cast<char *>(smcore.GetCvarString(sm_datetime_format));
}
#if defined SUBPLATFORM_SECURECRT
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
#endif
time_t t = (params[4] == -1) ? g_pSM->GetAdjustedTime() : (time_t)params[4];
size_t written = strftime(buffer, params[2], format, localtime(&t));
#if defined SUBPLATFORM_SECURECRT
_set_invalid_parameter_handler(handler);
#endif
if (params[2] && format[0] != '\0' && !written)
{
pContext->ThrowNativeError("Invalid time format or buffer too small");
return 0;
}
return 1;
}
static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params)
{
IPluginIterator *iter = scripts->GetPluginIterator();
Handle_t hndl = handlesys->CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE)
{
iter->Release();
}
return hndl;
}
static cell_t MorePlugins(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleError err;
IPluginIterator *pIter;
HandleSecurity sec;
sec.pIdentity = g_pCoreIdent;
sec.pOwner = pContext->GetIdentity();
if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
{
return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
}
return pIter->MorePlugins() ? 1 : 0;
}
static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleError err;
IPluginIterator *pIter;
HandleSecurity sec;
sec.pIdentity = g_pCoreIdent;
sec.pOwner = pContext->GetIdentity();
if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
{
return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
}
IPlugin *pPlugin = pIter->GetPlugin();
if (!pPlugin)
{
return BAD_HANDLE;
}
pIter->NextPlugin();
return pPlugin->GetMyHandle();
}
IPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
{
if (hndl == BAD_HANDLE)
{
return scripts->FindPluginByContext(pContext->GetContext());
} else {
HandleError err;
IPlugin *pPlugin = scripts->FindPluginByHandle(hndl, &err);
if (!pPlugin)
{
pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
}
return pPlugin;
}
}
static cell_t GetPluginStatus(IPluginContext *pContext, const cell_t *params)
{
IPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
if (!pPlugin)
{
return 0;
}
return pPlugin->GetStatus();
}
static cell_t GetPluginFilename(IPluginContext *pContext, const cell_t *params)
{
IPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
if (!pPlugin)
{
return 0;
}
pContext->StringToLocalUTF8(params[2], params[3], pPlugin->GetFilename(), NULL);
return 1;
}
static cell_t IsPluginDebugging(IPluginContext *pContext, const cell_t *params)
{
IPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
if (!pPlugin)
{
return 0;
}
return pPlugin->IsDebugging() ? 1 : 0;
}
/* Local to plugins only */
enum PluginInfo
{
PlInfo_Name, /**< Plugin name */
PlInfo_Author, /**< Plugin author */
PlInfo_Description, /**< Plugin description */
PlInfo_Version, /**< Plugin verison */
PlInfo_URL, /**< Plugin URL */
};
static cell_t GetPluginInfo(IPluginContext *pContext, const cell_t *params)
{
IPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
if (!pPlugin)
{
return 0;
}
const sm_plugininfo_t *info = pPlugin->GetPublicInfo();
if (!info)
{
return 0;
}
const char *str = NULL;
switch ((PluginInfo)params[2])
{
case PlInfo_Name:
{
str = info->name;
break;
}
case PlInfo_Author:
{
str = info->author;
break;
}
case PlInfo_Description:
{
str = info->description;
break;
}
case PlInfo_Version:
{
str = info->version;
break;
}
case PlInfo_URL:
{
str = info->url;
break;
}
}
if (!str || str[0] == '\0')
{
return 0;
}
pContext->StringToLocalUTF8(params[3], params[4], str, NULL);
return 1;
}
static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
{
char *str;
SMPlugin *pPlugin;
pContext->LocalToString(params[1], &str);
pPlugin = scripts->FindPluginByContext(pContext->GetContext());
if (params[0] == 1)
{
pPlugin->SetErrorState(Plugin_Error, "%s", str);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", str);
}
else
{
char buffer[2048];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
pPlugin->SetErrorState(Plugin_Error, "%s", str);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "Formatting error (%s)", str);
}
else
{
pPlugin->SetErrorState(Plugin_Error, "%s", buffer);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
}
}
return 0;
}
static cell_t GetSysTickCount(IPluginContext *pContext, const cell_t *params)
{
#if defined PLATFORM_WINDOWS
return (cell_t)GetTickCount();
#elif defined PLATFORM_POSIX
tms tm;
clock_t ticks = times(&tm);
long ticks_per_sec = sysconf(_SC_CLK_TCK);
double fticks = (double)ticks / (double)ticks_per_sec;
fticks *= 1000.0f;
if (fticks > INT_MAX)
{
double r = (int)(fticks / INT_MAX) * (double)INT_MAX;
fticks -= r;
}
return (cell_t)fticks;
#endif
}
static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params)
{
SMPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext());
char *cfg, *folder;
pContext->LocalToString(params[2], &cfg);
pContext->LocalToString(params[3], &folder);
if (cfg[0] == '\0')
{
static char temp_str[255];
static char temp_file[PLATFORM_MAX_PATH];
char *ptr;
libsys->GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
if ((ptr = strstr(temp_str, ".smx")) != NULL)
{
*ptr = '\0';
}
/* We have the raw filename! */
g_pSM->Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
cfg = temp_file;
}
plugin->AddConfig(params[1] ? true : false, cfg, folder);
return 1;
}
static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *params)
{
char *name;
uint32_t idx;
sp_native_t *native;
pContext->LocalToString(params[1], &name);
if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE)
{
/* Oops! This HAS to silently fail! */
return 0;
}
pContext->GetNativeByIndex(idx, &native);
native->flags |= SP_NTVFLAG_OPTIONAL;
return 1;
}
static cell_t RegPluginLibrary(IPluginContext *pContext, const cell_t *params)
{
char *name;
SMPlugin *pl = scripts->FindPluginByContext(pContext->GetContext());
pContext->LocalToString(params[1], &name);
pl->AddLibrary(name);
return 1;
}
static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params)
{
char *str;
pContext->LocalToString(params[1], &str);
if (strcmp(str, "__CanTestFeatures__") == 0)
{
return 1;
}
if (scripts->LibraryExists(str))
{
return 1;
}
if (extsys->LibraryExists(str))
{
return 1;
}
return 0;
}
static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
{
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
LogAction(pPlugin->GetMyHandle(), 2, params[1], params[2], buffer);
return 1;
}
static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
{
char *file;
pContext->LocalToString(params[1], &file);
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
FILE *fp = fopen(path, "at");
if (!fp)
{
return pContext->ThrowNativeError("Could not open file \"%s\"", path);
}
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
fclose(fp);
return 0;
}
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
g_Logger.LogToOpenFile(fp, "[%s] %s", pPlugin->GetFilename(), buffer);
fclose(fp);
return 1;
}
static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
{
char *file;
pContext->LocalToString(params[1], &file);
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
FILE *fp = fopen(path, "at");
if (!fp)
{
return pContext->ThrowNativeError("Could not open file \"%s\"", path);
}
char buffer[2048];
g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
fclose(fp);
return 0;
}
g_Logger.LogToOpenFile(fp, "%s", buffer);
fclose(fp);
return 1;
}
static cell_t GetExtensionFileStatus(IPluginContext *pContext, const cell_t *params)
{
char *str;
pContext->LocalToString(params[1], &str);
IExtension *pExtension = extsys->FindExtensionByFile(str);
if (!pExtension)
{
return -2;
}
if (!pExtension->IsLoaded())
{
return -1;
}
char *error;
pContext->LocalToString(params[2], &error);
if (!pExtension->IsRunning(error, params[3]))
{
return 0;
}
return 1;
}
static cell_t FindPluginByNumber(IPluginContext *pContext, const cell_t *params)
{
IPlugin *pPlugin = scripts->FindPluginByOrder(params[1]);
if (pPlugin == NULL)
{
return BAD_HANDLE;
}
return pPlugin->GetMyHandle();
}
static cell_t VerifyCoreVersion(IPluginContext *pContext, const cell_t *params)
{
return 4;
}
static cell_t GetFeatureStatus(IPluginContext *pContext, const cell_t *params)
{
FeatureType type = (FeatureType)params[1];
char *name;
pContext->LocalToString(params[2], &name);
return sharesys->TestFeature(pContext->GetRuntime(), type, name);
}
static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params)
{
FeatureType type = (FeatureType)params[1];
char *name;
pContext->LocalToString(params[2], &name);
if (sharesys->TestFeature(pContext->GetRuntime(), type, name) != FeatureStatus_Available)
{
char buffer[255];
char *msg = buffer;
char default_message[255];
SMPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 3);
if (pContext->GetLastNativeError() != SP_ERROR_NONE || buffer[0] == '\0')
{
g_pSM->Format(default_message, sizeof(default_message), "Feature \"%s\" not available", name);
msg = default_message;
}
pPlugin->SetErrorState(Plugin_Error, "%s", msg);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", msg);
}
return 1;
}
enum NumberType
{
NumberType_Int8,
NumberType_Int16,
NumberType_Int32
};
//memory addresses below 0x10000 are automatically considered invalid for dereferencing
#define VALID_MINIMUM_MEMORY_ADDRESS 0x10000
static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
{
void *addr = reinterpret_cast<void*>(params[1]);
if (addr == NULL)
{
return pContext->ThrowNativeError("Address cannot be null");
}
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
}
NumberType size = static_cast<NumberType>(params[2]);
switch(size)
{
case NumberType_Int8:
return *reinterpret_cast<uint8_t*>(addr);
case NumberType_Int16:
return *reinterpret_cast<uint16_t*>(addr);
case NumberType_Int32:
return *reinterpret_cast<uint32_t*>(addr);
default:
return pContext->ThrowNativeError("Invalid number types %d", size);
}
}
static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
{
void *addr = reinterpret_cast<void*>(params[1]);
if (addr == NULL)
{
return pContext->ThrowNativeError("Address cannot be null");
}
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
}
cell_t data = params[2];
NumberType size = static_cast<NumberType>(params[3]);
switch(size)
{
case NumberType_Int8:
SourceHook::SetMemAccess(addr, sizeof(uint8_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
*reinterpret_cast<uint8_t*>(addr) = data;
break;
case NumberType_Int16:
SourceHook::SetMemAccess(addr, sizeof(uint16_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
*reinterpret_cast<uint16_t*>(addr) = data;
break;
case NumberType_Int32:
SourceHook::SetMemAccess(addr, sizeof(uint32_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
*reinterpret_cast<uint32_t*>(addr) = data;
break;
default:
return pContext->ThrowNativeError("Invalid number types %d", size);
}
return 0;
}
REGISTER_NATIVES(coreNatives)
{
{"ThrowError", ThrowError},
{"GetTime", GetTime},
{"FormatTime", FormatTime},
{"GetPluginIterator", GetPluginIterator},
{"MorePlugins", MorePlugins},
{"ReadPlugin", ReadPlugin},
{"GetPluginStatus", GetPluginStatus},
{"GetPluginFilename", GetPluginFilename},
{"IsPluginDebugging", IsPluginDebugging},
{"GetPluginInfo", GetPluginInfo},
{"SetFailState", SetFailState},
{"GetSysTickCount", GetSysTickCount},
{"AutoExecConfig", AutoExecConfig},
{"MarkNativeAsOptional", MarkNativeAsOptional},
{"RegPluginLibrary", RegPluginLibrary},
{"LibraryExists", LibraryExists},
{"LogAction", sm_LogAction},
{"LogToFile", LogToFile},
{"LogToFileEx", LogToFileEx},
{"GetExtensionFileStatus", GetExtensionFileStatus},
{"FindPluginByNumber", FindPluginByNumber},
{"VerifyCoreVersion", VerifyCoreVersion},
{"GetFeatureStatus", GetFeatureStatus},
{"RequireFeature", RequireFeature},
{"LoadFromAddress", LoadFromAddress},
{"StoreToAddress", StoreToAddress},
{NULL, NULL},
};
+5 -4
View File
@@ -38,6 +38,7 @@
#include <ISourceMod.h>
#include <ITranslator.h>
#include "common_logic.h"
#include "Logger.h"
#if defined PLATFORM_WINDOWS
#include <io.h>
@@ -637,7 +638,7 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
}
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
smcore.Log("[%s] %s", pPlugin->GetFilename(), buffer);
g_Logger.LogMessage("[%s] %s", pPlugin->GetFilename(), buffer);
return 1;
}
@@ -655,7 +656,7 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
}
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
smcore.LogError("[%s] %s", pPlugin->GetFilename(), buffer);
g_Logger.LogError("[%s] %s", pPlugin->GetFilename(), buffer);
return 1;
}
@@ -708,7 +709,7 @@ static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params)
}
IPlugin *pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
smcore.LogToFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer);
g_Logger.LogToOpenFile(pFile, "[%s] %s", pPlugin->GetFilename(), buffer);
return 1;
}
@@ -738,7 +739,7 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
return 0;
}
smcore.LogToFile(pFile, "%s", buffer);
g_Logger.LogToOpenFile(pFile, "%s", buffer);
return 1;
}
+2 -2
View File
@@ -202,8 +202,8 @@ public:
{
errmsg = "Unknown error";
}
smcore.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
smcore.LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg);
logger->LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
logger->LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg);
}
else
{
+1 -1
View File
@@ -120,7 +120,7 @@ public: //ICommandTargetProcessor
Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
AutoHandleCloner ahc(hndl, sec);
if (ahc.getClone() == BAD_HANDLE) {
smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
logger->LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
delete array;
return false;
}