added amb1497 - log hooking
authorDavid Anderson <dvander@alliedmods.net>
Sun Mar 02 19:08:27 2008 +0000 (2008-03-02)
changeset 19140751a6430f15
parent 1913 a7416c7d48ea
child 1915 ab031366cfd1
added amb1497 - log hooking
core/Logger.cpp
core/Logger.h
core/smn_filesystem.cpp
plugins/include/logging.inc
plugins/include/sourcemod.inc
     1.1 --- a/core/Logger.cpp	Sun Mar 02 18:18:42 2008 +0000
     1.2 +++ b/core/Logger.cpp	Sun Mar 02 19:08:27 2008 +0000
     1.3 @@ -434,7 +434,7 @@
     1.4  	msg[len++] = '\n';
     1.5  	msg[len] = '\0';
     1.6  
     1.7 -	engine->LogPrint(msg);
     1.8 +	Engine_LogPrintWrapper(msg);
     1.9  }
    1.10  
    1.11  const char *Logger::GetLogFileName(LogType type) const
    1.12 @@ -505,3 +505,16 @@
    1.13  	}
    1.14  }
    1.15  
    1.16 +bool g_in_game_log_hook = false;
    1.17 +
    1.18 +void Engine_LogPrintWrapper(const char *msg)
    1.19 +{
    1.20 +	if (g_in_game_log_hook)
    1.21 +	{
    1.22 +		ENGINE_CALL(LogPrint)(msg);
    1.23 +	}
    1.24 +	else
    1.25 +	{
    1.26 +		engine->LogPrint(msg);
    1.27 +	}
    1.28 +}
     2.1 --- a/core/Logger.h	Sun Mar 02 18:18:42 2008 +0000
     2.2 +++ b/core/Logger.h	Sun Mar 02 19:08:27 2008 +0000
     2.3 @@ -98,6 +98,9 @@
     2.4  	bool m_InitialState;
     2.5  };
     2.6  
     2.7 +void Engine_LogPrintWrapper(const char *msg);
     2.8 +
     2.9 +extern bool g_in_game_log_hook;
    2.10  extern Logger g_Logger;
    2.11  
    2.12  #endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
     3.1 --- a/core/smn_filesystem.cpp	Sun Mar 02 18:18:42 2008 +0000
     3.2 +++ b/core/smn_filesystem.cpp	Sun Mar 02 19:08:27 2008 +0000
     3.3 @@ -37,22 +37,40 @@
     3.4  #include "Logger.h"
     3.5  #include "PluginSys.h"
     3.6  #include "sourcemm_api.h"
     3.7 +#include "ForwardSys.h"
     3.8 +
     3.9 +SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
    3.10  
    3.11  HandleType_t g_FileType;
    3.12  HandleType_t g_DirType;
    3.13 +IChangeableForward *g_pLogHook = NULL;
    3.14  
    3.15  class FileNatives : 
    3.16  	public SMGlobalClass,
    3.17 -	public IHandleTypeDispatch
    3.18 +	public IHandleTypeDispatch,
    3.19 +	public IPluginsListener
    3.20  {
    3.21  public:
    3.22 +	FileNatives()
    3.23 +	{
    3.24 +		m_bIsLoggingHooked = false;
    3.25 +	}
    3.26  	virtual void OnSourceModAllInitialized()
    3.27  	{
    3.28  		g_FileType = g_HandleSys.CreateType("File", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    3.29  		g_DirType = g_HandleSys.CreateType("Directory", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    3.30 +		g_pLogHook = g_Forwards.CreateForwardEx(NULL, ET_Hook, 1, NULL, Param_String);
    3.31 +		g_PluginSys.AddPluginsListener(this);
    3.32  	}
    3.33  	virtual void OnSourceModShutdown()
    3.34  	{
    3.35 +		g_PluginSys.RemovePluginsListener(this);
    3.36 +		if (m_bIsLoggingHooked)
    3.37 +		{
    3.38 +			SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
    3.39 +			m_bIsLoggingHooked = false;
    3.40 +		}
    3.41 +		g_Forwards.ReleaseForward(g_pLogHook);
    3.42  		g_HandleSys.RemoveType(g_DirType, g_pCoreIdent);
    3.43  		g_HandleSys.RemoveType(g_FileType, g_pCoreIdent);
    3.44  		g_DirType = 0;
    3.45 @@ -64,11 +82,59 @@
    3.46  		{
    3.47  			FILE *fp = (FILE *)object;
    3.48  			fclose(fp);
    3.49 -		} else if (type == g_DirType) {
    3.50 +		}
    3.51 +		else if (type == g_DirType)
    3.52 +		{
    3.53  			IDirectory *pDir = (IDirectory *)object;
    3.54  			g_LibSys.CloseDirectory(pDir);
    3.55  		}
    3.56  	}
    3.57 +	virtual void OnPluginDestroyed(IPlugin *plugin)
    3.58 +	{
    3.59 +		if (m_bIsLoggingHooked && g_pLogHook->GetFunctionCount() == 0)
    3.60 +		{
    3.61 +			SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
    3.62 +			m_bIsLoggingHooked = false;
    3.63 +		}
    3.64 +	}
    3.65 +	virtual void AddLogHook(IPluginFunction *pFunc)
    3.66 +	{
    3.67 +		if (!m_bIsLoggingHooked)
    3.68 +		{
    3.69 +			SH_ADD_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
    3.70 +			m_bIsLoggingHooked = true;
    3.71 +		}
    3.72 +
    3.73 +		g_pLogHook->AddFunction(pFunc);
    3.74 +	}
    3.75 +	virtual void RemoveLogHook(IPluginFunction *pFunc)
    3.76 +	{
    3.77 +		g_pLogHook->RemoveFunction(pFunc);
    3.78 +
    3.79 +		if (m_bIsLoggingHooked && g_pLogHook->GetFunctionCount() == 0)
    3.80 +		{
    3.81 +			SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, LogPrint, engine, this, &FileNatives::LogPrint, false);
    3.82 +			m_bIsLoggingHooked = false;
    3.83 +		}
    3.84 +	}
    3.85 +	virtual void LogPrint(const char *msg)
    3.86 +	{
    3.87 +		cell_t result;
    3.88 +
    3.89 +		result = 0;
    3.90 +
    3.91 +		g_in_game_log_hook = true;
    3.92 +		g_pLogHook->PushString(msg);
    3.93 +		g_pLogHook->Execute(&result);
    3.94 +		g_in_game_log_hook = false;
    3.95 +
    3.96 +		if (result >= Pl_Handled)
    3.97 +		{
    3.98 +			RETURN_META(MRES_SUPERCEDE);
    3.99 +		}
   3.100 +	}
   3.101 +private:
   3.102 +	bool m_bIsLoggingHooked;
   3.103  } s_FileNatives;
   3.104  
   3.105  static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
   3.106 @@ -521,7 +587,7 @@
   3.107  		buffer[len] = '\0';
   3.108  	}
   3.109  
   3.110 -	engine->LogPrint(buffer);
   3.111 +	Engine_LogPrintWrapper(buffer);
   3.112  
   3.113  	return 1;
   3.114  }
   3.115 @@ -835,6 +901,34 @@
   3.116  	return (fwrite(buffer, sizeof(char), len, pFile) == len) ? 1 : 0;
   3.117  }
   3.118  
   3.119 +static cell_t sm_AddGameLogHook(IPluginContext *pContext, const cell_t *params)
   3.120 +{
   3.121 +	IPluginFunction *pFunction;
   3.122 +
   3.123 +	if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
   3.124 +	{
   3.125 +		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
   3.126 +	}
   3.127 +
   3.128 +	s_FileNatives.AddLogHook(pFunction);
   3.129 +	
   3.130 +	return 1;
   3.131 +}
   3.132 +
   3.133 +static cell_t sm_RemoveGameLogHook(IPluginContext *pContext, const cell_t *params)
   3.134 +{
   3.135 +	IPluginFunction *pFunction;
   3.136 +
   3.137 +	if ((pFunction=pContext->GetFunctionById(params[1])) == NULL)
   3.138 +	{
   3.139 +		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
   3.140 +	}
   3.141 +
   3.142 +	s_FileNatives.RemoveLogHook(pFunction);
   3.143 +
   3.144 +	return 1;
   3.145 +}
   3.146 +
   3.147  REGISTER_NATIVES(filesystem)
   3.148  {
   3.149  	{"OpenDirectory",			sm_OpenDirectory},
   3.150 @@ -863,5 +957,7 @@
   3.151  	{"ReadFileString",			sm_ReadFileString},
   3.152  	{"WriteFile",				sm_WriteFile},
   3.153  	{"WriteFileString",			sm_WriteFileString},
   3.154 +	{"AddGameLogHook",			sm_AddGameLogHook},
   3.155 +	{"RemoveGameLogHook",		sm_RemoveGameLogHook},
   3.156  	{NULL,						NULL},
   3.157  };
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/plugins/include/logging.inc	Sun Mar 02 19:08:27 2008 +0000
     4.3 @@ -0,0 +1,153 @@
     4.4 +/**
     4.5 + * vim: set ts=4 :
     4.6 + * =============================================================================
     4.7 + * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     4.8 + * =============================================================================
     4.9 + *
    4.10 + * This file is part of the SourceMod/SourcePawn SDK.
    4.11 + *
    4.12 + * This program is free software; you can redistribute it and/or modify it under
    4.13 + * the terms of the GNU General Public License, version 3.0, as published by the
    4.14 + * Free Software Foundation.
    4.15 + * 
    4.16 + * This program is distributed in the hope that it will be useful, but WITHOUT
    4.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.18 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    4.19 + * details.
    4.20 + *
    4.21 + * You should have received a copy of the GNU General Public License along with
    4.22 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    4.23 + *
    4.24 + * As a special exception, AlliedModders LLC gives you permission to link the
    4.25 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    4.26 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    4.27 + * by the Valve Corporation.  You must obey the GNU General Public License in
    4.28 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    4.29 + * this exception to all derivative works.  AlliedModders LLC defines further
    4.30 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    4.31 + * or <http://www.sourcemod.net/license.php>.
    4.32 + *
    4.33 + * Version: $Id$
    4.34 + */
    4.35 + 
    4.36 +#if defined _sm_logging_included
    4.37 + #endinput
    4.38 +#endif
    4.39 +#define _sm_logging_included
    4.40 +
    4.41 +/**
    4.42 + * Logs a plugin message to the SourceMod logs.  The log message will be 
    4.43 + * prefixed by the plugin's logtag (filename).
    4.44 + *
    4.45 + * @param format		String format.
    4.46 + * @param ...			Format arguments.
    4.47 + * @noreturn
    4.48 + */
    4.49 +native LogMessage(const String:format[], any:...);
    4.50 +
    4.51 +/**
    4.52 + * Logs a message to the SourceMod logs without any plugin logtag.  This is 
    4.53 + * useful for re-routing messages from other plugins, for example, messages 
    4.54 + * from LogAction().
    4.55 + *
    4.56 + * @param format		String format.
    4.57 + * @param ...			Format arguments.
    4.58 + * @noreturn
    4.59 + */
    4.60 +native LogMessageEx(const String:format[], any:...);
    4.61 +
    4.62 +/**
    4.63 + * Logs a message to any file.  The log message will be in the normal 
    4.64 + * SourceMod format, with the plugin logtag prepended.
    4.65 + *
    4.66 + * @param file			File to write the log message in.
    4.67 + * @param format		String format.
    4.68 + * @param ...			Format arguments.
    4.69 + * @noreturn
    4.70 + * @error				File could not be opened/written.
    4.71 + */
    4.72 +native LogToFile(const String:file[], const String:format[], any:...);
    4.73 +
    4.74 +/**
    4.75 + * Same as LogToFile(), except no plugin logtag is prepended.
    4.76 + *
    4.77 + * @param file			File to write the log message in.
    4.78 + * @param format		String format.
    4.79 + * @param ...			Format arguments.
    4.80 + * @noreturn
    4.81 + * @error				File could not be opened/written.
    4.82 + */
    4.83 +native LogToFileEx(const String:file[], const String:format[], any:...);
    4.84 +
    4.85 +/**
    4.86 + * Logs an action from a command or event whereby interception and routing may 
    4.87 + * be important.  This is intended to be a logging version of ShowActivity().
    4.88 + *
    4.89 + * @param client		Client performing the action, 0 for server, or -1 if not 
    4.90 + *						applicable.
    4.91 + * @param target		Client being targetted, or -1 if not applicable.
    4.92 + * @param message		Message format.
    4.93 + * @param ...			Message formatting parameters.
    4.94 + * @noreturn
    4.95 + */
    4.96 +native LogAction(client, target, const String:message[], any:...);
    4.97 +
    4.98 +/**
    4.99 + * Logs a plugin error message to the SourceMod logs.
   4.100 + *
   4.101 + * @param format		String format.
   4.102 + * @param ...			Format arguments.
   4.103 + * @noreturn
   4.104 + */
   4.105 +native LogError(const String:format[], any:...);
   4.106 +
   4.107 +/**
   4.108 + * Called when an action is going to be logged.
   4.109 + *
   4.110 + * @param source		Handle to the object logging the action, or INVALID_HANDLE 
   4.111 + *						if Core is logging the action.
   4.112 + * @param ident			Type of object logging the action (plugin, ext, or core).
   4.113 + * @param client		Client the action is from; 0 for server, -1 if not applicable.
   4.114 + * @param target		Client the action is targetting, or -1 if not applicable.
   4.115 + * @param message		Message that is being logged.
   4.116 + * @return				Plugin_Continue will cause Core to defaulty log the message.
   4.117 + *						Plugin_Handled will stop Core from logging the message.
   4.118 + * 						Plugin_Stop is the same as Handled, but prevents any other 
   4.119 + *						plugins from handling the message.
   4.120 + */
   4.121 +forward Action:OnLogAction(Handle:source, 
   4.122 +						   Identity:ident,
   4.123 +						   client,
   4.124 +						   target,
   4.125 +						   const String:message[]);
   4.126 +
   4.127 +/**
   4.128 + * Called when a game log message is received.
   4.129 + *
   4.130 + * Any Log*() functions called within this callback will not recursively 
   4.131 + * pass through.  That is, they will log directly, bypassing this callback.
   4.132 + *
   4.133 + * Note that this does not capture log messages from the engine.  It only 
   4.134 + * captures log messages being sent from the game/mod itself.
   4.135 + *
   4.136 + * @param message		Message contents.
   4.137 + * @return				Plugin_Handled or Plugin_Stop will prevent the message 
   4.138 + * 						from being written to the log file.
   4.139 + */
   4.140 +functag GameLogHook Action:public(const String:message[]);
   4.141 +
   4.142 +/**
   4.143 + * Adds a game log hook.
   4.144 + *
   4.145 + * @param hook			Hook function.
   4.146 + * @noreturn
   4.147 + */
   4.148 +native AddGameLogHook(GameLogHook:hook);
   4.149 +
   4.150 +/**
   4.151 + * Removes a game log hook.
   4.152 + *
   4.153 + * @param hook			Hook function.
   4.154 + * @noreturn
   4.155 + */
   4.156 +native RemoveGameLogHook(GameLogHook:hook);
     5.1 --- a/plugins/include/sourcemod.inc	Sun Mar 02 18:18:42 2008 +0000
     5.2 +++ b/plugins/include/sourcemod.inc	Sun Mar 02 19:08:27 2008 +0000
     5.3 @@ -54,6 +54,7 @@
     5.4  #include <handles>
     5.5  #include <functions>
     5.6  #include <files>
     5.7 +#include <logging>
     5.8  #include <timers>
     5.9  #include <admin>
    5.10  #include <dbi>
    5.11 @@ -92,6 +93,10 @@
    5.12   * If any run-time error is thrown during this callback, the plugin will be marked 
    5.13   * as failed.
    5.14   *
    5.15 + * It is not necessary to close any handles or remove hooks in this function.  
    5.16 + * SourceMod guarantees that plugin shutdown automatically and correctly releases 
    5.17 + * all resources.
    5.18 + *
    5.19   * @noreturn
    5.20   */
    5.21  forward OnPluginStart();
    5.22 @@ -177,26 +182,6 @@
    5.23  forward OnAllPluginsLoaded();
    5.24  
    5.25  /**
    5.26 - * Called when an action is going to be logged.
    5.27 - *
    5.28 - * @param source		Handle to the object logging the action, or INVALID_HANDLE 
    5.29 - *						if Core is logging the action.
    5.30 - * @param ident			Type of object logging the action (plugin, ext, or core).
    5.31 - * @param client		Client the action is from; 0 for server, -1 if not applicable.
    5.32 - * @param target		Client the action is targetting, or -1 if not applicable.
    5.33 - * @param message		Message that is being logged.
    5.34 - * @return				Plugin_Continue will cause Core to defaulty log the message.
    5.35 - *						Plugin_Handled will stop Core from logging the message.
    5.36 - * 						Plugin_Stop is the same as Handled, but prevents any other 
    5.37 - *						plugins from handling the message.
    5.38 - */
    5.39 -forward Action:OnLogAction(Handle:source, 
    5.40 -						   Identity:ident,
    5.41 -						   client,
    5.42 -						   target,
    5.43 -						   const String:message[]);
    5.44 -
    5.45 -/**
    5.46   * Returns the calling plugin's Handle.
    5.47   *
    5.48   * @return				Handle of the calling plugin.
    5.49 @@ -316,72 +301,6 @@
    5.50  native ThrowError(const String:fmt[], any:...);
    5.51  
    5.52  /**
    5.53 - * Logs a plugin message to the SourceMod logs.  The log message will be 
    5.54 - * prefixed by the plugin's logtag (filename).
    5.55 - *
    5.56 - * @param format		String format.
    5.57 - * @param ...			Format arguments.
    5.58 - * @noreturn
    5.59 - */
    5.60 -native LogMessage(const String:format[], any:...);
    5.61 -
    5.62 -/**
    5.63 - * Logs a message to the SourceMod logs without any plugin logtag.  This is 
    5.64 - * useful for re-routing messages from other plugins, for example, messages 
    5.65 - * from LogAction().
    5.66 - *
    5.67 - * @param format		String format.
    5.68 - * @param ...			Format arguments.
    5.69 - * @noreturn
    5.70 - */
    5.71 -native LogMessageEx(const String:format[], any:...);
    5.72 -
    5.73 -/**
    5.74 - * Logs a message to any file.  The log message will be in the normal 
    5.75 - * SourceMod format, with the plugin logtag prepended.
    5.76 - *
    5.77 - * @param file			File to write the log message in.
    5.78 - * @param format		String format.
    5.79 - * @param ...			Format arguments.
    5.80 - * @noreturn
    5.81 - * @error				File could not be opened/written.
    5.82 - */
    5.83 -native LogToFile(const String:file[], const String:format[], any:...);
    5.84 -
    5.85 -/**
    5.86 - * Same as LogToFile(), except no plugin logtag is prepended.
    5.87 - *
    5.88 - * @param file			File to write the log message in.
    5.89 - * @param format		String format.
    5.90 - * @param ...			Format arguments.
    5.91 - * @noreturn
    5.92 - * @error				File could not be opened/written.
    5.93 - */
    5.94 -native LogToFileEx(const String:file[], const String:format[], any:...);
    5.95 -
    5.96 -/**
    5.97 - * Logs an action from a command or event whereby interception and routing may 
    5.98 - * be important.  This is intended to be a logging version of ShowActivity().
    5.99 - *
   5.100 - * @param client		Client performing the action, 0 for server, or -1 if not 
   5.101 - *						applicable.
   5.102 - * @param target		Client being targetted, or -1 if not applicable.
   5.103 - * @param message		Message format.
   5.104 - * @param ...			Message formatting parameters.
   5.105 - * @noreturn
   5.106 - */
   5.107 -native LogAction(client, target, const String:message[], any:...);
   5.108 -
   5.109 -/**
   5.110 - * Logs a plugin error message to the SourceMod logs.
   5.111 - *
   5.112 - * @param format		String format.
   5.113 - * @param ...			Format arguments.
   5.114 - * @noreturn
   5.115 - */
   5.116 -native LogError(const String:format[], any:...);
   5.117 -
   5.118 -/**
   5.119   * Gets the system time as a unix timestamp.
   5.120   *
   5.121   * @param bigStamp		Optional array to store the 64bit timestamp in.