1.1 --- a/core/Logger.cpp Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,520 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include <time.h>
1.36 -#include "sourcemod.h"
1.37 -#include "sourcemm_api.h"
1.38 -#include "sm_stringutil.h"
1.39 -#include "Logger.h"
1.40 -#include "systems/LibrarySys.h"
1.41 -#include "TimerSys.h"
1.42 -#include "sm_version.h"
1.43 -
1.44 -Logger g_Logger;
1.45 -
1.46 -/**
1.47 - * :TODO: This should be creating the log folder if it doesn't exist
1.48 - */
1.49 -
1.50 -ConfigResult Logger::OnSourceModConfigChanged(const char *key,
1.51 - const char *value,
1.52 - ConfigSource source,
1.53 - char *error,
1.54 - size_t maxlength)
1.55 -{
1.56 - if (strcasecmp(key, "Logging") == 0)
1.57 - {
1.58 - bool state;
1.59 -
1.60 - if (strcasecmp(value, "on") == 0)
1.61 - {
1.62 - state = true;
1.63 - } else if (strcasecmp(value, "off") == 0) {
1.64 - state = false;
1.65 - } else {
1.66 - UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
1.67 - return ConfigResult_Reject;
1.68 - }
1.69 -
1.70 - if (source == ConfigSource_Console)
1.71 - {
1.72 - state ? EnableLogging() : DisableLogging();
1.73 - } else {
1.74 - m_InitialState = state;
1.75 - }
1.76 -
1.77 - return ConfigResult_Accept;
1.78 - } else if (strcasecmp(key, "LogMode") == 0) {
1.79 - if (strcasecmp(value, "daily") == 0)
1.80 - {
1.81 - m_Mode = LoggingMode_Daily;
1.82 - } else if (strcasecmp(value, "map") == 0) {
1.83 - m_Mode = LoggingMode_PerMap;
1.84 - } else if (strcasecmp(value, "game") == 0) {
1.85 - m_Mode = LoggingMode_Game;
1.86 - } else {
1.87 - UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]");
1.88 - return ConfigResult_Reject;
1.89 - }
1.90 -
1.91 - return ConfigResult_Accept;
1.92 - }
1.93 -
1.94 - return ConfigResult_Ignore;
1.95 -}
1.96 -
1.97 -void Logger::OnSourceModStartup(bool late)
1.98 -{
1.99 - InitLogger(m_Mode);
1.100 -}
1.101 -
1.102 -void Logger::OnSourceModAllShutdown()
1.103 -{
1.104 - CloseLogger();
1.105 -}
1.106 -
1.107 -void Logger::OnSourceModLevelChange(const char *mapName)
1.108 -{
1.109 - MapChange(mapName);
1.110 -}
1.111 -
1.112 -void Logger::_NewMapFile()
1.113 -{
1.114 - if (!m_Active)
1.115 - {
1.116 - return;
1.117 - }
1.118 -
1.119 - /* Append "Log file closed" to previous log file */
1.120 - _CloseFile();
1.121 -
1.122 - char _filename[256];
1.123 - int i = 0;
1.124 -
1.125 - time_t t;
1.126 - GetAdjustedTime(&t);
1.127 - tm *curtime = localtime(&t);
1.128 -
1.129 - while (true)
1.130 - {
1.131 - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
1.132 - FILE *fp = fopen(_filename, "r");
1.133 - if (!fp)
1.134 - {
1.135 - break;
1.136 - }
1.137 - fclose(fp);
1.138 - i++;
1.139 - }
1.140 - m_NrmFileName.assign(_filename);
1.141 -
1.142 - FILE *fp = fopen(m_NrmFileName.c_str(), "w");
1.143 - if (!fp)
1.144 - {
1.145 - char error[255];
1.146 - g_LibSys.GetPlatformError(error, sizeof(error));
1.147 - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
1.148 - LogFatal("[SM] Platform returned error: \"%s\"", error);
1.149 - LogFatal("[SM] Logging has been disabled.");
1.150 - m_Active = false;
1.151 - return;
1.152 - } else {
1.153 - char date[32];
1.154 - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
1.155 - 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, SVN_FULL_VERSION);
1.156 - fclose(fp);
1.157 - }
1.158 -}
1.159 -
1.160 -void Logger::_CloseFile()
1.161 -{
1.162 - if (!m_Active)
1.163 - {
1.164 - return;
1.165 - }
1.166 -
1.167 - FILE *fp = NULL;
1.168 - if (!m_NrmFileName.empty())
1.169 - {
1.170 - fp = fopen(m_NrmFileName.c_str(), "r+");
1.171 - if (fp)
1.172 - {
1.173 - fseek(fp, 0, SEEK_END);
1.174 - LogMessage("Log file closed.");
1.175 - fclose(fp);
1.176 - }
1.177 - m_NrmFileName.clear();
1.178 - }
1.179 -
1.180 - if (!m_ErrMapStart)
1.181 - {
1.182 - return;
1.183 - }
1.184 - fp = fopen(m_ErrFileName.c_str(), "r+");
1.185 - if (fp)
1.186 - {
1.187 - fseek(fp, 0, SEEK_END);
1.188 - LogError("Error log file session closed.");
1.189 - fclose(fp);
1.190 - }
1.191 - m_ErrFileName.clear();
1.192 -}
1.193 -
1.194 -void Logger::InitLogger(LoggingMode mode)
1.195 -{
1.196 - m_Mode = mode;
1.197 - m_Active = m_InitialState;
1.198 -
1.199 - time_t t;
1.200 - GetAdjustedTime(&t);
1.201 - tm *curtime = localtime(&t);
1.202 - m_CurDay = curtime->tm_mday;
1.203 -
1.204 - char _filename[256];
1.205 - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
1.206 - m_ErrFileName.assign(_filename);
1.207 -
1.208 - switch (m_Mode)
1.209 - {
1.210 - case LoggingMode_PerMap:
1.211 - {
1.212 - if (!m_Active)
1.213 - {
1.214 - m_DelayedStart = true;
1.215 - }
1.216 - break;
1.217 - }
1.218 - case LoggingMode_Daily:
1.219 - {
1.220 - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
1.221 - m_NrmFileName.assign(_filename);
1.222 - m_DailyPrintHdr = true;
1.223 - break;
1.224 - }
1.225 - default:
1.226 - {
1.227 - /* do nothing... */
1.228 - break;
1.229 - }
1.230 - }
1.231 -}
1.232 -
1.233 -void Logger::CloseLogger()
1.234 -{
1.235 - _CloseFile();
1.236 -}
1.237 -
1.238 -void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
1.239 -{
1.240 - if (!m_Active)
1.241 - {
1.242 - return;
1.243 - }
1.244 -
1.245 - va_list ap;
1.246 - va_start(ap, msg);
1.247 - LogToOpenFileEx(fp, msg, ap);
1.248 - va_end(ap);
1.249 -}
1.250 -
1.251 -void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
1.252 -{
1.253 - if (!m_Active)
1.254 - {
1.255 - return;
1.256 - }
1.257 -
1.258 - char buffer[3072];
1.259 - UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
1.260 -
1.261 - char date[32];
1.262 - time_t t;
1.263 - GetAdjustedTime(&t);
1.264 - tm *curtime = localtime(&t);
1.265 - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
1.266 -
1.267 - fprintf(fp, "L %s: %s\n", date, buffer);
1.268 - g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
1.269 -}
1.270 -
1.271 -void Logger::LogMessage(const char *vafmt, ...)
1.272 -{
1.273 - if (!m_Active)
1.274 - {
1.275 - return;
1.276 - }
1.277 -
1.278 - if (m_Mode == LoggingMode_Game)
1.279 - {
1.280 - va_list ap;
1.281 - va_start(ap, vafmt);
1.282 - _PrintToGameLog(vafmt, ap);
1.283 - va_end(ap);
1.284 - return;
1.285 - }
1.286 -
1.287 - if (m_DelayedStart)
1.288 - {
1.289 - m_DelayedStart = false;
1.290 - _NewMapFile();
1.291 - }
1.292 -
1.293 - time_t t;
1.294 - GetAdjustedTime(&t);
1.295 - tm *curtime = localtime(&t);
1.296 -
1.297 - FILE *fp = NULL;
1.298 - if (m_Mode == LoggingMode_PerMap)
1.299 - {
1.300 - fp = fopen(m_NrmFileName.c_str(), "a+");
1.301 - if (!fp)
1.302 - {
1.303 - _NewMapFile();
1.304 - fp = fopen(m_NrmFileName.c_str(), "a+");
1.305 - if (!fp)
1.306 - {
1.307 - goto print_error;
1.308 - }
1.309 - }
1.310 - } else {
1.311 - if (m_CurDay != curtime->tm_mday)
1.312 - {
1.313 - char _filename[256];
1.314 - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
1.315 - m_NrmFileName.assign(_filename);
1.316 - m_CurDay = curtime->tm_mday;
1.317 - m_DailyPrintHdr = true;
1.318 - }
1.319 - fp = fopen(m_NrmFileName.c_str(), "a+");
1.320 - }
1.321 -
1.322 - if (fp)
1.323 - {
1.324 - if (m_DailyPrintHdr)
1.325 - {
1.326 - char date[32];
1.327 - m_DailyPrintHdr = false;
1.328 - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
1.329 - 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, SVN_FULL_VERSION);
1.330 - }
1.331 - va_list ap;
1.332 - va_start(ap, vafmt);
1.333 - LogToOpenFileEx(fp, vafmt, ap);
1.334 - va_end(ap);
1.335 - fclose(fp);
1.336 - } else {
1.337 - goto print_error;
1.338 - }
1.339 -
1.340 - return;
1.341 -print_error:
1.342 - char error[255];
1.343 - g_LibSys.GetPlatformError(error, sizeof(error));
1.344 - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
1.345 - LogFatal("[SM] Platform returned error: \"%s\"", error);
1.346 - LogFatal("[SM] Logging has been disabled.");
1.347 - m_Active = false;
1.348 -}
1.349 -
1.350 -void Logger::LogError(const char *vafmt, ...)
1.351 -{
1.352 - if (!m_Active)
1.353 - {
1.354 - return;
1.355 - }
1.356 -
1.357 - time_t t;
1.358 - GetAdjustedTime(&t);
1.359 - tm *curtime = localtime(&t);
1.360 -
1.361 - if (curtime->tm_mday != m_CurDay)
1.362 - {
1.363 - char _filename[256];
1.364 - g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
1.365 - m_ErrFileName.assign(_filename);
1.366 - m_CurDay = curtime->tm_mday;
1.367 - m_ErrMapStart = false;
1.368 - }
1.369 -
1.370 - FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
1.371 - if (fp)
1.372 - {
1.373 - if (!m_ErrMapStart)
1.374 - {
1.375 - char date[32];
1.376 - strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
1.377 - fprintf(fp, "L %s: SourceMod error session started\n", date);
1.378 - 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);
1.379 - m_ErrMapStart = true;
1.380 - }
1.381 - va_list ap;
1.382 - va_start(ap, vafmt);
1.383 - LogToOpenFileEx(fp, vafmt, ap);
1.384 - va_end(ap);
1.385 - fclose(fp);
1.386 - }
1.387 - else
1.388 - {
1.389 - char error[255];
1.390 - g_LibSys.GetPlatformError(error, sizeof(error));
1.391 - LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
1.392 - LogFatal("[SM] Platform returned error: \"%s\"", error);
1.393 - LogFatal("[SM] Logging has been disabled.");
1.394 - m_Active = false;
1.395 - return;
1.396 - }
1.397 -}
1.398 -
1.399 -void Logger::MapChange(const char *mapname)
1.400 -{
1.401 - m_CurMapName.assign(mapname);
1.402 -
1.403 - switch (m_Mode)
1.404 - {
1.405 - case LoggingMode_Daily:
1.406 - {
1.407 - LogMessage("-------- Mapchange to %s --------", mapname);
1.408 - break;
1.409 - }
1.410 - case LoggingMode_PerMap:
1.411 - {
1.412 - _NewMapFile();
1.413 - break;
1.414 - }
1.415 - default:
1.416 - {
1.417 - /* Do nothing... */
1.418 - break;
1.419 - }
1.420 - }
1.421 -
1.422 - if (m_ErrMapStart)
1.423 - {
1.424 - LogError("Error log file session closed.");
1.425 - }
1.426 - m_ErrMapStart = false;
1.427 -}
1.428 -
1.429 -void Logger::_PrintToGameLog(const char *fmt, va_list ap)
1.430 -{
1.431 - char msg[3072];
1.432 - size_t len;
1.433 -
1.434 - len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
1.435 - len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
1.436 -
1.437 - msg[len++] = '\n';
1.438 - msg[len] = '\0';
1.439 -
1.440 - Engine_LogPrintWrapper(msg);
1.441 -}
1.442 -
1.443 -const char *Logger::GetLogFileName(LogType type) const
1.444 -{
1.445 - switch (type)
1.446 - {
1.447 - case LogType_Normal:
1.448 - {
1.449 - return m_NrmFileName.c_str();
1.450 - }
1.451 - case LogType_Error:
1.452 - {
1.453 - return m_ErrFileName.c_str();
1.454 - }
1.455 - default:
1.456 - {
1.457 - return "";
1.458 - }
1.459 - }
1.460 -}
1.461 -
1.462 -LoggingMode Logger::GetLoggingMode() const
1.463 -{
1.464 - return m_Mode;
1.465 -}
1.466 -
1.467 -void Logger::EnableLogging()
1.468 -{
1.469 - if (m_Active)
1.470 - {
1.471 - return;
1.472 - }
1.473 - m_Active = true;
1.474 - LogMessage("[SM] Logging enabled manually by user.");
1.475 -}
1.476 -
1.477 -void Logger::DisableLogging()
1.478 -{
1.479 - if (!m_Active)
1.480 - {
1.481 - return;
1.482 - }
1.483 - LogMessage("[SM] Logging disabled manually by user.");
1.484 - m_Active = false;
1.485 -}
1.486 -
1.487 -void Logger::LogFatal(const char *msg, ...)
1.488 -{
1.489 - /* :TODO: make this print all pretty-like
1.490 - * In fact, the pretty log printing function should be abstracted.
1.491 - * It's already implemented twice which is bad.
1.492 - */
1.493 -
1.494 - va_list ap;
1.495 - char path[PLATFORM_MAX_PATH];
1.496 -
1.497 - g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
1.498 -
1.499 - FILE *fp = fopen(path, "at");
1.500 - if (fp)
1.501 - {
1.502 - m_Active = true;
1.503 - va_start(ap, msg);
1.504 - LogToOpenFileEx(fp, msg, ap);
1.505 - va_end(ap);
1.506 - m_Active = false;
1.507 - fclose(fp);
1.508 - }
1.509 -}
1.510 -
1.511 -bool g_in_game_log_hook = false;
1.512 -
1.513 -void Engine_LogPrintWrapper(const char *msg)
1.514 -{
1.515 - if (g_in_game_log_hook)
1.516 - {
1.517 - ENGINE_CALL(LogPrint)(msg);
1.518 - }
1.519 - else
1.520 - {
1.521 - engine->LogPrint(msg);
1.522 - }
1.523 -}