1
0
Fork 0
forked from fte/fteqw
fteqw/engine/common/log.c

654 lines
18 KiB
C
Raw Normal View History

// log.c: handles console logging functions and cvars
#include "quakedef.h"
// cvar callbacks
static void QDECL Log_Dir_Callback (struct cvar_s *var, char *oldvalue);
static void QDECL Log_Name_Callback (struct cvar_s *var, char *oldvalue);
// cvars
#define CONLOGGROUP "Console logging"
cvar_t log_enable[LOG_TYPES] = { CVARF("log_enable", "0", CVAR_NOTFROMSERVER),
CVARF("log_enable_players", "0", CVAR_NOTFROMSERVER),
CVARF("log_enable_rcon", "1", CVAR_NOTFROMSERVER)
};
cvar_t log_name[LOG_TYPES] = { CVARFC("log_name", "", CVAR_NOTFROMSERVER, Log_Name_Callback),
CVARFC("log_name_players", "players", CVAR_NOTFROMSERVER, Log_Name_Callback),
CVARFC("log_name_rcon", "rcon", CVAR_NOTFROMSERVER, Log_Name_Callback)};
cvar_t log_dir = CVARFC("log_dir", "", CVAR_NOTFROMSERVER, Log_Dir_Callback);
cvar_t log_readable = CVARFD("log_readable", "7", CVAR_NOTFROMSERVER, "Bitfield describing what to convert/strip. If 0, exact byte representation will be used.\n&1: Dequakify text.\n&2: Strip special markup.\n&4: Strip ansi control codes.");
cvar_t log_developer = CVARFD("log_developer", "0", CVAR_NOTFROMSERVER, "Enables logging of console prints when set to 1. Otherwise unimportant messages will not fill up your log files.");
cvar_t log_rotate_files = CVARF("log_rotate_files", "0", CVAR_NOTFROMSERVER);
cvar_t log_rotate_size = CVARF("log_rotate_size", "131072", CVAR_NOTFROMSERVER);
cvar_t log_timestamps = CVARF("log_timestamps", "1", CVAR_NOTFROMSERVER);
#ifdef _WIN32
cvar_t log_dosformat = CVARF("log_dosformat", "1", CVAR_NOTFROMSERVER);
#else
cvar_t log_dosformat = CVARF("log_dosformat", "0", CVAR_NOTFROMSERVER);
#endif
qboolean log_newline[LOG_TYPES];
// externals
extern char gamedirfile[];
// Log_Dir_Callback: called when a log_dir is changed
static void QDECL Log_Dir_Callback (struct cvar_s *var, char *oldvalue)
{
char *t = var->string;
char *e = t + (*t?strlen(t):0);
// sanity check for directory. // is equivelent to /../ on some systems, so make sure that can't be used either. : is for drives on windows or amiga, or alternative thingies on windows, so block thoses completely.
if (strstr(t, "..") || strstr(t, ":") || *t == '/' || *t == '\\' || *e == '/' || *e == '\\' || strstr(t, "//") || strstr(t, "\\\\"))
{
Con_Printf(CON_NOTICE "%s forced to default due to invalid characters.\n", var->name);
// recursion is avoided by assuming the default value is sane
Cvar_ForceSet(var, var->defaultstr);
}
}
// Log_Name_Callback: called when a log_name is changed
static void QDECL Log_Name_Callback (struct cvar_s *var, char *oldvalue)
{
char *t = var->string;
// sanity check for directory
if (strstr(t, "..") || strstr(t, ":") || strstr(t, "/") || strstr(t, "\\"))
{
Con_Printf(CON_NOTICE "%s forced to default due to invalid characters.\n", var->name);
// recursion is avoided by assuming the default value is sane
Cvar_ForceSet(var, var->defaultstr);
}
}
// Con_Log: log string to console log
void Log_String (logtype_t lognum, char *s)
{
vfsfile_t *fi;
char *d; // directory
char *f; // filename
char *t;
char utf8[2048];
int i;
char fbase[MAX_QPATH];
------------------------------------------------------------------------ r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines removed MAX_VISEDICTS limit. PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default. TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW. added android multitouch emulation for windows/rawinput (in_simulatemultitouch). split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature. now using utf-8 for windows consoles. qcc warnings/errors now give clickable console links for quick+easy editing. disabled menutint when the currently active item changes contrast or gamma (for OneManClan). Added support for drawfont/drawfontscale. tweaked the qcvm a little to reduce the number of pointers. .doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up. windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings. fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen. editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts. Added support for .framegroups files for psk(psa) and iqm formats. True support for ezquake's colour codes. Mutually exclusive with background colours. path command output slightly more readable. added support for digest_hex (MD4, SHA1, CRC16). skingroups now colourmap correctly. Fix terrain colour hints, and litdata from the wrong bsp. fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported). remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother. fix v *= v.x and similar opcodes. fteqcc: fixed support for áéíóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported. fteqcc: fixed '#if 1 == 3 && 4' parsing. fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable. fteqcc: copyright message now includes compile date instead. fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile. fteqccgui: the output window is now focused and scrolls down as compilation progresses. pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue. rewrote prespawn/modelist/soundlist code. server tracks progress now. ------------------------------------------------------------------------ git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
char fname[MAX_QPATH];
conchar_t cline[2048], *c;
mvd: cl_autotrack_team cvar locks autotrack to a specific team. getting the team name to match can still be problematic when it contains non-ascii chars however. qw: fix recording mid-map. q2: add support for recording demos on q2 servers. q: fix setattachment not using the correct orientations. q2: now supports splitscreen, as well as increased model and sound limits. cl: fix crosshair not appearing in splitscreen. cl: splitscreen clients now get their own colour tints (like the bf command) snd: tweak audio to be a bit more usable in splitscreen by default. cl: added con_logcenterprint cvar, for shoving a copy of centerprints onto the console. by default only appears in single player. qc: add checkbuiltin builtin. for all those #0 builtins without their own extension name. gl: fix r_dynamic -1 bug that was painfully visible in AD. mdl: validate per-frame bounds of mdl files (stuff that would crash software renderers). sv: fix -port or +sv_port commandline args to override the port correctly. win: attempt to cope with windows symlinks enumerating with the wrong filesizes. gl: fix skyboxes not appearing properly. gl: fix sprite alpha/edge issue resulting in some invisible sprites in AD. gl: fix screenshot_mega, in combination with r_projection. yay for HUGE panoramic screenshots. q2: fix replacement textures issue. qw: fix download demonum/X issue, both in client and server. qw: fix multicast dimensions not always being honoured properly. nq: fix starting angles sometimes being wrong. menusys: I'm finally uploading my menusys library, plus example mod, which I'll now be providing like csaddon is. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4997 fc73d0e0-1445-4013-8a0c-d673dee63da5
2016-01-18 05:22:07 +00:00
unsigned int u, flags;
f = NULL;
switch(lognum)
{
case LOG_CONSOLE:
f = "qconsole";
break;
case LOG_PLAYER:
f = "players";
break;
case LOG_RCON:
f = "rcon";
break;
default:
return;
}
if (!log_enable[lognum].value)
return;
// get directory/filename
if (log_dir.string[0])
d = log_dir.string;
else
d = "";//gamedirfile;
if (log_name[lognum].string[0])
f = log_name[lognum].string;
if (!f)
return;
COM_ParseFunString(CON_WHITEMASK, s, cline, sizeof(cline), !(log_readable.ival & 2));
t = utf8;
mvd: cl_autotrack_team cvar locks autotrack to a specific team. getting the team name to match can still be problematic when it contains non-ascii chars however. qw: fix recording mid-map. q2: add support for recording demos on q2 servers. q: fix setattachment not using the correct orientations. q2: now supports splitscreen, as well as increased model and sound limits. cl: fix crosshair not appearing in splitscreen. cl: splitscreen clients now get their own colour tints (like the bf command) snd: tweak audio to be a bit more usable in splitscreen by default. cl: added con_logcenterprint cvar, for shoving a copy of centerprints onto the console. by default only appears in single player. qc: add checkbuiltin builtin. for all those #0 builtins without their own extension name. gl: fix r_dynamic -1 bug that was painfully visible in AD. mdl: validate per-frame bounds of mdl files (stuff that would crash software renderers). sv: fix -port or +sv_port commandline args to override the port correctly. win: attempt to cope with windows symlinks enumerating with the wrong filesizes. gl: fix skyboxes not appearing properly. gl: fix sprite alpha/edge issue resulting in some invisible sprites in AD. gl: fix screenshot_mega, in combination with r_projection. yay for HUGE panoramic screenshots. q2: fix replacement textures issue. qw: fix download demonum/X issue, both in client and server. qw: fix multicast dimensions not always being honoured properly. nq: fix starting angles sometimes being wrong. menusys: I'm finally uploading my menusys library, plus example mod, which I'll now be providing like csaddon is. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4997 fc73d0e0-1445-4013-8a0c-d673dee63da5
2016-01-18 05:22:07 +00:00
for (c = cline; *c; )
{
mvd: cl_autotrack_team cvar locks autotrack to a specific team. getting the team name to match can still be problematic when it contains non-ascii chars however. qw: fix recording mid-map. q2: add support for recording demos on q2 servers. q: fix setattachment not using the correct orientations. q2: now supports splitscreen, as well as increased model and sound limits. cl: fix crosshair not appearing in splitscreen. cl: splitscreen clients now get their own colour tints (like the bf command) snd: tweak audio to be a bit more usable in splitscreen by default. cl: added con_logcenterprint cvar, for shoving a copy of centerprints onto the console. by default only appears in single player. qc: add checkbuiltin builtin. for all those #0 builtins without their own extension name. gl: fix r_dynamic -1 bug that was painfully visible in AD. mdl: validate per-frame bounds of mdl files (stuff that would crash software renderers). sv: fix -port or +sv_port commandline args to override the port correctly. win: attempt to cope with windows symlinks enumerating with the wrong filesizes. gl: fix skyboxes not appearing properly. gl: fix sprite alpha/edge issue resulting in some invisible sprites in AD. gl: fix screenshot_mega, in combination with r_projection. yay for HUGE panoramic screenshots. q2: fix replacement textures issue. qw: fix download demonum/X issue, both in client and server. qw: fix multicast dimensions not always being honoured properly. nq: fix starting angles sometimes being wrong. menusys: I'm finally uploading my menusys library, plus example mod, which I'll now be providing like csaddon is. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4997 fc73d0e0-1445-4013-8a0c-d673dee63da5
2016-01-18 05:22:07 +00:00
c = Font_Decode(c, &flags, &u);
if ((flags & CON_HIDDEN) && (log_readable.ival & 2))
continue;
if (log_readable.ival&1)
mvd: cl_autotrack_team cvar locks autotrack to a specific team. getting the team name to match can still be problematic when it contains non-ascii chars however. qw: fix recording mid-map. q2: add support for recording demos on q2 servers. q: fix setattachment not using the correct orientations. q2: now supports splitscreen, as well as increased model and sound limits. cl: fix crosshair not appearing in splitscreen. cl: splitscreen clients now get their own colour tints (like the bf command) snd: tweak audio to be a bit more usable in splitscreen by default. cl: added con_logcenterprint cvar, for shoving a copy of centerprints onto the console. by default only appears in single player. qc: add checkbuiltin builtin. for all those #0 builtins without their own extension name. gl: fix r_dynamic -1 bug that was painfully visible in AD. mdl: validate per-frame bounds of mdl files (stuff that would crash software renderers). sv: fix -port or +sv_port commandline args to override the port correctly. win: attempt to cope with windows symlinks enumerating with the wrong filesizes. gl: fix skyboxes not appearing properly. gl: fix sprite alpha/edge issue resulting in some invisible sprites in AD. gl: fix screenshot_mega, in combination with r_projection. yay for HUGE panoramic screenshots. q2: fix replacement textures issue. qw: fix download demonum/X issue, both in client and server. qw: fix multicast dimensions not always being honoured properly. nq: fix starting angles sometimes being wrong. menusys: I'm finally uploading my menusys library, plus example mod, which I'll now be providing like csaddon is. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4997 fc73d0e0-1445-4013-8a0c-d673dee63da5
2016-01-18 05:22:07 +00:00
u = COM_DeQuake(u);
//at the start of a new line, we might want a timestamp (so timestamps are correct for the first char of the line, instead of the preceeding \n)
if (log_newline[lognum])
{
if (log_timestamps.ival)
{
time_t unixtime = time(NULL);
int bufferspace = utf8+sizeof(utf8)-1-t;
if (bufferspace > 0)
{
strftime(t, bufferspace, "%Y-%m-%d %H:%M:%S ", localtime(&unixtime));
t += strlen(t);
}
}
log_newline[lognum] = false;
}
//make sure control codes are stripped. no exploiting xterm bugs please.
if ((log_readable.ival & 4) && ((u < 32 && u != '\t' && u != '\n') || u == 127 || (u >= 128 && u < 128+32))) //\r is stripped too
u = '?';
//if dos format logs, we insert a \r before every \n (also flag next char as the start of a new line)
if (u == '\n')
{
log_newline[lognum] = true;
if (log_dosformat.ival)
t += utf8_encode(t, '\r', utf8+sizeof(utf8)-1-t);
}
t += utf8_encode(t, u, utf8+sizeof(utf8)-1-t);
}
*t = 0;
if (*d)
Q_snprintfz(fbase, sizeof(fname)-4, "%s/%s", d, f);
else
Q_snprintfz(fbase, sizeof(fname)-4, "%s", f);
Q_snprintfz(fname, sizeof(fname), "%s.log", fbase);
// file rotation
if (log_rotate_size.value >= 4096 && log_rotate_files.value >= 1)
{
int x;
vfsfile_t *fi;
// check file size, use x as temp
if ((fi = FS_OpenVFS(fname, "rb", FS_GAMEONLY)))
{
x = VFS_GETLEN(fi);
VFS_CLOSE(fi);
x += strlen(utf8); // add string size to file size to never go over
}
else
x = 0;
if (x > (int)log_rotate_size.value)
{
char newf[MAX_QPATH];
char oldf[MAX_QPATH];
i = log_rotate_files.value;
// unlink file at the top of the chain
Q_snprintfz(oldf, sizeof(oldf), "%s.%i.log", fbase, i);
FS_Remove(oldf, FS_GAMEONLY);
// rename files through chain
for (x = i-1; x > 0; x--)
{
strcpy(newf, oldf);
Q_snprintfz(oldf, sizeof(oldf), "%s.%i.log", fbase, x);
// check if file exists, otherwise skip
if ((fi = FS_OpenVFS(oldf, "rb", FS_GAMEONLY)))
VFS_CLOSE(fi);
else
continue; // skip nonexistant files
if (!FS_Rename(oldf, newf, FS_GAMEONLY))
{
// rename failed, disable log and bug out
Cvar_ForceSet(&log_enable[lognum], "0");
Con_Printf("Unable to rotate log files. Logging disabled.\n");
return;
}
}
// TODO: option to compress file somewhere in here?
// rename our base file, which had better exist...
if (!FS_Rename(fname, oldf, FS_GAMEONLY))
{
// rename failed, disable log and bug out
Cvar_ForceSet(&log_enable[lognum], "0");
Con_Printf("Unable to rename base log file. Logging disabled.\n");
return;
}
}
}
FS_CreatePath(fname, FS_GAMEONLY);
if ((fi = FS_OpenVFS(fname, "ab", FS_GAMEONLY)))
{
VFS_WRITE(fi, utf8, strlen(utf8));
VFS_CLOSE(fi);
}
else
{
// write failed, bug out
Cvar_ForceSet(&log_enable[lognum], "0");
Con_Printf("Unable to write to log file. Logging disabled.\n");
return;
}
}
void Con_Log (char *s)
{
Log_String(LOG_CONSOLE, s);
}
#ifndef CLIENTONLY
//still to add stuff at:
//connects
//disconnects
//kicked
void SV_LogPlayer(client_t *cl, char *msg)
{
char line[2048];
char remote_adr[MAX_ADR_SIZE];
char realip_adr[MAX_ADR_SIZE];
if (cl->protocol == SCP_BAD)
return; //don't log botclients
snprintf(line, sizeof(line),
"%s\\%s\\%i\\%s\\%s\\%i\\guid\\%s%s\n",
msg, cl->name, cl->userid,
NET_BaseAdrToString(remote_adr, sizeof(remote_adr), &cl->netchan.remote_address), (cl->realip_status > 0 ? NET_BaseAdrToString(realip_adr, sizeof(realip_adr), &cl->realip) : "??"),
cl->netchan.remote_address.port, cl->guid, cl->userinfo);
Log_String(LOG_PLAYER, line);
}
#endif
void Log_Logfile_f (void)
{
extern char gamedirfile[];
if (log_enable[LOG_CONSOLE].value)
{
Cvar_SetValue(&log_enable[LOG_CONSOLE], 0);
Con_Printf("Logging disabled.\n");
}
else
{
char *d, *f;
d = gamedirfile;
if (log_dir.string[0])
d = log_dir.string;
f = "qconsole";
if (log_name[LOG_CONSOLE].string[0])
f = log_name[LOG_CONSOLE].string;
Con_Printf("%s", va("Logging to %s/%s.log.\n", d, f));
Cvar_SetValue(&log_enable[LOG_CONSOLE], 1);
}
}
/*
void SV_Fraglogfile_f (void)
{
char name[MAX_QPATH];
int i;
if (sv_fraglogfile)
{
Con_TPrintf ("Frag file logging off.\n");
VFS_CLOSE (sv_fraglogfile);
sv_fraglogfile = NULL;
return;
}
// find an unused name
for (i=0 ; i<1000 ; i++)
{
sprintf (name, "frag_%i.log", i);
sv_fraglogfile = FS_OpenVFS(name, "rb", FS_GAME);
if (!sv_fraglogfile)
{ // can't read it, so create this one
sv_fraglogfile = FS_OpenVFS (name, "wb", FS_GAME);
if (!sv_fraglogfile)
i=1000; // give error
break;
}
VFS_CLOSE (sv_fraglogfile);
}
if (i==1000)
{
Con_TPrintf ("Can't open any logfiles.\n");
sv_fraglogfile = NULL;
return;
}
Con_TPrintf ("Logging frags to %s.\n", name);
}
*/
/*for fuck sake, why can people still not write simple files. proquake is writing binary files as text ones. this function is to try to deal with that fuckup*/
static size_t IPLog_Read_Fucked(qbyte *file, size_t *offset, size_t totalsize, qbyte *out, size_t outsize)
{
size_t read = 0;
while (outsize-- > 0 && *offset < totalsize)
{
if (file[*offset] == '\r' && *offset+1 < totalsize && file[*offset+1] == '\n')
{
out[read] = '\n';
*offset += 2;
read += 1;
}
else
{
out[read] = file[*offset];
*offset += 1;
read += 1;
}
}
return read;
}
/*need to make sure any 13 bytes followed by 10s don't bug out when read back in *sigh* */
static size_t IPLog_Write_Fucked(vfsfile_t *file, qbyte *out, size_t outsize)
{
qbyte tmp[64];
size_t write = 0;
size_t block = 0;
while (outsize-- > 0)
{
if (block >= sizeof(tmp)-4)
{
VFS_WRITE(file, tmp, block);
write += block;
block = 0;
}
if (*out == '\n')
tmp[block++] = '\r';
tmp[block++] = *out++;
}
if (block)
{
VFS_WRITE(file, tmp, block);
write += block;
}
return write;
}
qboolean IPLog_Merge_File(const char *fname)
{
char ip[MAX_ADR_SIZE];
char name[256];
char line[1024];
vfsfile_t *f;
if (!*fname)
fname = "iplog.txt";
f = FS_OpenVFS(fname, "rb", FS_PUBBASEGAMEONLY);
if (!f)
f = FS_OpenVFS(fname, "rb", FS_GAME);
if (!f)
return false;
if (!Q_strcasecmp(COM_FileExtension(fname, name, sizeof(name)), "dat"))
{ //we don't write this format because of it being limited to ipv4, as well as player name lengths
size_t l = VFS_GETLEN(f), offset = 0;
qbyte *ffs = malloc(l+1);
VFS_READ(f, ffs, l);
ffs[l] = 0;
while (IPLog_Read_Fucked(ffs, &offset, l, line, 20) == 20)
{ //yes, these addresses are weird.
Q_snprintfz(ip, sizeof(ip), "%i.%i.%i.xxx", (qbyte)line[2], (qbyte)line[1], (qbyte)line[0]);
memcpy(name, line+4, 20-4);
name[20-4] = 0;
IPLog_Add(ip, name);
}
free(ffs);
}
else
{
while (VFS_GETS(f, line, sizeof(line)-1))
{
//whether the name contains quotes or what is an awkward one.
//we always write quotes (including string markup to avoid issues)
//dp doesn't, and our parser is lazy, so its possible we'll get gibberish that way
if (COM_ParseOut(COM_ParseOut(line, ip, sizeof(ip)), name, sizeof(name)))
IPLog_Add(ip, name);
}
}
VFS_CLOSE(f);
return true;
}
struct iplog_entry
{
netadr_t adr;
netadr_t mask;
char name[1];
} **iplog_entries;
size_t iplog_num, iplog_max;
void IPLog_Add(const char *ipstr, const char *name)
{
size_t i;
netadr_t a, m;
while (*ipstr == ' ' || *ipstr == '\t')
ipstr++;
if (*ipstr != '[' && *ipstr < '0' && *ipstr > '9')
return;
if (*ipstr == '[')
ipstr++;
//some names are dodgy.
if (!*name
//|| !Q_strcasecmp(name, /*nq default*/"player") || !Q_strcasecmp(name, /*qw default*/"unnamed")
|| !strcmp(name, /*nq fallback*/"unconnected") || !strncmp(name, "BOT:", 4))
return;
memset(&a, 0, sizeof(a));
memset(&m, 0, sizeof(m));
if (!NET_StringToAdrMasked(ipstr, false, &a, &m))
return;
//might be x.y.z.w:port
//might be x.y.z.FUCKED
//might be x.y.z.0/24
//might be [::]:port
//might be [::]/bits
//or other ways to express an ip address
//FIXME: ignore private addresses?
//check for dupes
for (i = 0; i < iplog_num; i++)
{
if (!memcmp(&a, &iplog_entries[i]->adr, sizeof(netadr_t)) && !memcmp(&m, &iplog_entries[i]->mask, sizeof(netadr_t)) && !Q_strcasecmp(name, iplog_entries[i]->name))
return;
}
//looks like its new...
if (iplog_num == iplog_max)
Z_ReallocElements((void**)&iplog_entries, &iplog_max, iplog_max+64, sizeof(*iplog_entries));
iplog_entries[iplog_num] = BZ_Malloc(sizeof(struct iplog_entry) + strlen(name));
iplog_entries[iplog_num]->adr = a;
iplog_entries[iplog_num]->mask = m;
strcpy(iplog_entries[iplog_num]->name, name);
iplog_num++;
}
static void IPLog_Identify(netadr_t *adr, netadr_t *mask, char *fmt, ...)
{
va_list argptr;
qboolean found = false;
char line[256];
size_t i;
va_start(argptr, fmt);
vsnprintf(line, sizeof(line), fmt, argptr);
va_end(argptr);
Con_Printf("%s: ", line);
for (i = 0; i < iplog_num; i++)
{
if (NET_CompareAdrMasked(adr, &iplog_entries[i]->adr, mask?mask:&iplog_entries[i]->mask))
{
if (found)
Con_Printf(", ");
found=true;
Con_Printf("%s", iplog_entries[i]->name);
}
}
if (!found)
Con_Printf("<no matches>");
Con_Printf("\n");
}
#include "cl_ignore.h"
static void IPLog_Identify_f(void)
{
const char *nameorip = Cmd_Argv(1);
netadr_t adr, mask;
char clean[256];
char *endofnum;
strtoul(nameorip, &endofnum, 10);
if (*endofnum && NET_StringToAdrMasked (nameorip, false, &adr, &mask))
{ //if not a single number, try to parse as an ip
//treading carefully here, to avoid dns name lookups weirding everything out.
IPLog_Identify(&adr, &mask, "Identity of %s", NET_AdrToStringMasked(clean, sizeof(clean), &adr, &mask));
}
#ifndef CLIENTONLY
else if (sv.active)
{ //if server is active, walk players to see if there's a name match to get their address and guess an address mask
client_t *cl;
int clnum = -1;
while((cl = SV_GetClientForString(nameorip, &clnum)))
{
if (cl->realip_status)
{
IPLog_Identify(&cl->realip, NULL, "Identity of %s (real) [%s]", cl->name, NET_AdrToString(clean, sizeof(clean), &cl->realip));
IPLog_Identify(&cl->netchan.remote_address, NULL, "Identity of %s (proxy) [%s]", cl->name, NET_AdrToString(clean, sizeof(clean), &cl->realip));
}
else
IPLog_Identify(&cl->netchan.remote_address, NULL, "Identity of %s [%s]", cl->name, NET_AdrToString(clean, sizeof(clean), &cl->realip));
}
}
#endif
#ifndef SERVERONLY
else if (cls.state >= ca_connected)
{ //else if client is active, walk players to see if there's a name match, to get their address+mask if known via nq hacks
int slot;
netadr_t adr;
if ((slot = Player_StringtoSlot(nameorip)) < 0)
Con_Printf("%s: no player with userid %s\n", Cmd_Argv(0), nameorip);
else if (!*cl.players[slot].ip)
Con_Printf("%s: ip address of %s is not known\n", Cmd_Argv(0), cl.players[slot].name);
else
{
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places. nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients). nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes! added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever). misc fixes (server crash, a couple of other less important ones). external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3. identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt) vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt). qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages. qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference). qcc: cleaned up optional vs __out ordering issues. qccgui: shift+f3 searches backwards git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
if (NET_StringToAdrMasked(cl.players[slot].ip, false, &adr, &mask))
IPLog_Identify(&adr, &mask, "Identity of %s [%s]", cl.players[slot].name, cl.players[slot].ip);
else
Con_Printf("ip address of %s not known, cannot identify\n", cl.players[slot].name);
}
}
#endif
else
Con_Printf("%s: not connected, nor raw address\n", Cmd_Argv(0));
}
static qboolean IPLog_Dump(const char *fname)
{
size_t i;
vfsfile_t *f;
qbyte line[20];
if (!*fname)
fname = "iplog.txt";
f = FS_OpenVFS(fname, "wb", FS_PUBBASEGAMEONLY);
if (!f)
return false;
if (!Q_strcasecmp(COM_FileExtension(fname, line, sizeof(line)), "dat"))
{
for (i = 0; i < iplog_num; i++)
{
//this shitty format supports only ipv4.
if (iplog_entries[i]->adr.type != NA_IP)
continue;
line[0] = iplog_entries[i]->adr.address.ip[2];
line[1] = iplog_entries[i]->adr.address.ip[1];
line[2] = iplog_entries[i]->adr.address.ip[0];
line[3] = 0;
strncpy(line+4, iplog_entries[i]->name, sizeof(line)-4);
IPLog_Write_Fucked(f, line, sizeof(line)); //convert \n to \r\n, to avoid fucking up any formatting with binary data (inside the address part, so *.13.10.* won't corrupt the file)
}
}
else
{
VFS_PRINTF(f, "//generated by "FULLENGINENAME"\n");
for (i = 0; i < iplog_num; i++)
{
char ip[512];
char buf[1024];
char buf2[1024];
VFS_PRINTF(f, log_dosformat.value?"%s %s\r\n":"%s %s\n", COM_QuotedString(NET_AdrToStringMasked(ip, sizeof(ip), &iplog_entries[i]->adr, &iplog_entries[i]->mask), buf2, sizeof(buf2), false), COM_QuotedString(iplog_entries[i]->name, buf, sizeof(buf), false));
}
}
VFS_CLOSE(f);
return true;
}
static void IPLog_Dump_f(void)
{
char native[MAX_OSPATH];
const char *fname = Cmd_Argv(1);
if (FS_NativePath(fname, FS_GAMEONLY, native, sizeof(native)))
Q_strncpyz(native, fname, sizeof(native));
IPLog_Merge_File(fname); //merge from the existing file, so that we're hopefully more robust if multiple processes are poking the same file.
if (!IPLog_Dump(fname))
Con_Printf("unable to write %s\n", fname);
else
{
Con_Printf("wrote %s\n", native);
}
}
static void IPLog_Merge_f(void)
{
const char *fname = Cmd_Argv(1);
if (!IPLog_Merge_File(fname))
Con_Printf("unable to read %s\n", fname);
}
void Log_ShutDown(void)
{
IPLog_Dump("iplog.txt");
// IPLog_Dump("iplog.dat");
while(iplog_num > 0)
{
iplog_num--;
BZ_Free(iplog_entries[iplog_num]);
}
BZ_Free(iplog_entries);
iplog_entries = NULL;
iplog_max = iplog_num = 0;
}
void Log_Init(void)
{
int i;
// register cvars
for (i = 0; i < LOG_TYPES; i++)
{
Cvar_Register (&log_enable[i], CONLOGGROUP);
Cvar_Register (&log_name[i], CONLOGGROUP);
log_newline[i] = true;
}
Cvar_Register (&log_dir, CONLOGGROUP);
Cvar_Register (&log_readable, CONLOGGROUP);
Cvar_Register (&log_developer, CONLOGGROUP);
Cvar_Register (&log_rotate_size, CONLOGGROUP);
Cvar_Register (&log_rotate_files, CONLOGGROUP);
Cvar_Register (&log_dosformat, CONLOGGROUP);
Cvar_Register (&log_timestamps, CONLOGGROUP);
Cmd_AddCommand("logfile", Log_Logfile_f);
Cmd_AddCommand("identify", IPLog_Identify_f);
Cmd_AddCommand("ipmerge", IPLog_Merge_f);
Cmd_AddCommand("ipdump", IPLog_Dump_f);
// cmd line options, debug options
#ifdef CRAZYDEBUGGING
Cvar_ForceSet(&log_enable[LOG_CONSOLE], "1");
TRACE(("dbg: Con_Init: log_enable forced\n"));
#endif
if (COM_CheckParm("-condebug"))
Cvar_ForceSet(&log_enable[LOG_CONSOLE], "1");
}