241 lines
5.1 KiB
241 lines
5.1 KiB
/* |
|
sv_log.c - server logging in multiplayer |
|
Copyright (C) 2017 Uncle Mike |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
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. |
|
*/ |
|
|
|
#include "common.h" |
|
#include "server.h" |
|
|
|
void Log_Open( void ) |
|
{ |
|
time_t ltime; |
|
struct tm *today; |
|
char szFileBase[ MAX_OSPATH ]; |
|
char szTestFile[ MAX_OSPATH ]; |
|
file_t *fp = NULL; |
|
const char *temp; |
|
int i; |
|
|
|
if( !svs.log.active ) |
|
return; |
|
|
|
if( sv_log_onefile.value && svs.log.file ) |
|
return; |
|
|
|
if( !mp_logfile.value ) |
|
{ |
|
Con_Printf( "Server logging data to console.\n" ); |
|
return; |
|
} |
|
|
|
Log_Close(); |
|
|
|
// Find a new log file slot |
|
time( <ime ); |
|
today = localtime( <ime ); |
|
temp = Cvar_VariableString( "logsdir" ); |
|
|
|
if( COM_CheckString( temp ) && !Q_strchr( temp, ':' ) && !Q_strstr( temp, ".." )) |
|
Q_snprintf( szFileBase, sizeof( szFileBase ), "%s/L%02i%02i", temp, today->tm_mon + 1, today->tm_mday ); |
|
else Q_snprintf( szFileBase, sizeof( szFileBase ), "logs/L%02i%02i", today->tm_mon + 1, today->tm_mday ); |
|
|
|
for ( i = 0; i < 1000; i++ ) |
|
{ |
|
Q_snprintf( szTestFile, sizeof( szTestFile ), "%s%03i.log", szFileBase, i ); |
|
|
|
if( FS_FileExists( szTestFile, false )) |
|
continue; |
|
|
|
fp = FS_Open( szTestFile, "w", true ); |
|
if( fp ) |
|
{ |
|
Con_Printf( "Server logging data to file %s\n", szTestFile ); |
|
} |
|
else |
|
{ |
|
i = 1000; |
|
} |
|
break; |
|
} |
|
|
|
if( i == 1000 ) |
|
{ |
|
Con_Printf( "Unable to open logfiles under %s\nLogging disabled\n", szFileBase ); |
|
svs.log.active = false; |
|
return; |
|
} |
|
|
|
if( fp ) svs.log.file = fp; |
|
Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/" XASH_VERSION "/%d\")\n", |
|
szTestFile, Info_ValueForKey( SV_Serverinfo(), "*gamedir" ), PROTOCOL_VERSION, Q_buildnum() ); |
|
} |
|
|
|
void Log_Close( void ) |
|
{ |
|
if( svs.log.file ) |
|
{ |
|
Log_Printf( "Log file closed\n" ); |
|
FS_Close( svs.log.file ); |
|
} |
|
svs.log.file = NULL; |
|
} |
|
|
|
/* |
|
================== |
|
Log_Printf |
|
|
|
Prints a frag log message to the server's frag log file, console, and possible a UDP port. |
|
================== |
|
*/ |
|
void Log_Printf( const char *fmt, ... ) |
|
{ |
|
va_list argptr; |
|
static char string[1024]; |
|
char *p; |
|
time_t ltime; |
|
struct tm *today; |
|
int len; |
|
|
|
if( !svs.log.active ) |
|
return; |
|
|
|
time( <ime ); |
|
today = localtime( <ime ); |
|
|
|
len = Q_snprintf( string, sizeof( string ), "%02i/%02i/%04i - %02i:%02i:%02i: ", |
|
today->tm_mon+1, today->tm_mday, 1900 + today->tm_year, today->tm_hour, today->tm_min, today->tm_sec ); |
|
|
|
p = string + len; |
|
|
|
va_start( argptr, fmt ); |
|
Q_vsnprintf( p, sizeof( string ) - len, fmt, argptr ); |
|
va_end( argptr ); |
|
|
|
if( svs.log.net_log ) |
|
Netchan_OutOfBandPrint( NS_SERVER, svs.log.net_address, "log %s", string ); |
|
|
|
if( svs.log.active && ( svs.maxclients > 1 || sv_log_singleplayer.value != 0.0f )) |
|
{ |
|
// echo to server console |
|
if( mp_logecho.value ) |
|
Con_Printf( "%s", string ); |
|
|
|
// echo to log file |
|
if( svs.log.file && mp_logfile.value ) |
|
FS_Printf( svs.log.file, "%s", string ); |
|
} |
|
} |
|
|
|
static void Log_PrintServerCvar( const char *var_name, const char *var_value, const void *unused2, void *unused3 ) |
|
{ |
|
Log_Printf( "Server cvar \"%s\" = \"%s\"\n", var_name, var_value ); |
|
} |
|
|
|
/* |
|
================== |
|
Log_PrintServerVars |
|
|
|
================== |
|
*/ |
|
void Log_PrintServerVars( void ) |
|
{ |
|
if( !svs.log.active ) |
|
return; |
|
|
|
Log_Printf( "Server cvars start\n" ); |
|
Cvar_LookupVars( FCVAR_SERVER, NULL, NULL, (setpair_t)Log_PrintServerCvar ); |
|
Log_Printf( "Server cvars end\n" ); |
|
} |
|
|
|
/* |
|
==================== |
|
SV_SetLogAddress_f |
|
|
|
==================== |
|
*/ |
|
void SV_SetLogAddress_f( void ) |
|
{ |
|
const char *s; |
|
int port; |
|
string addr; |
|
|
|
if( Cmd_Argc() != 3 ) |
|
{ |
|
Con_Printf( "logaddress: usage\nlogaddress ip port\n" ); |
|
|
|
if( svs.log.active ) |
|
Con_Printf( "current: %s\n", NET_AdrToString( svs.log.net_address )); |
|
|
|
return; |
|
} |
|
|
|
port = Q_atoi( Cmd_Argv( 2 )); |
|
if( !port ) |
|
{ |
|
Con_Printf( "logaddress: must specify a valid port\n" ); |
|
return; |
|
} |
|
|
|
s = Cmd_Argv( 1 ); |
|
if( !COM_CheckString( s )) |
|
{ |
|
Con_Printf( "logaddress: unparseable address\n" ); |
|
return; |
|
} |
|
|
|
Q_snprintf( addr, sizeof( addr ), "%s:%i", s, port ); |
|
if( !NET_StringToAdr( addr, &svs.log.net_address )) |
|
{ |
|
Con_Printf( "logaddress: unable to resolve %s\n", addr ); |
|
return; |
|
} |
|
|
|
svs.log.net_log = true; |
|
Con_Printf( "logaddress: %s\n", NET_AdrToString( svs.log.net_address )); |
|
} |
|
|
|
/* |
|
==================== |
|
SV_ServerLog_f |
|
|
|
==================== |
|
*/ |
|
void SV_ServerLog_f( void ) |
|
{ |
|
if( Cmd_Argc() != 2 ) |
|
{ |
|
Con_Printf( S_USAGE "log < on|off >\n" ); |
|
|
|
if( svs.log.active ) |
|
Con_Printf( "currently logging\n" ); |
|
else Con_Printf( "not currently logging\n" ); |
|
return; |
|
} |
|
|
|
if( !Q_stricmp( Cmd_Argv( 1 ), "off" )) |
|
{ |
|
if( svs.log.active ) |
|
Log_Close(); |
|
} |
|
else if( !Q_stricmp( Cmd_Argv( 1 ), "on" )) |
|
{ |
|
svs.log.active = true; |
|
Log_Open(); |
|
} |
|
else |
|
{ |
|
Con_Printf( "log: unknown parameter %s\n", Cmd_Argv( 1 )); |
|
} |
|
|
|
return; |
|
}
|
|
|