* Add con_log.c to log all console output

* Add con_passive.c to cut down on #ifdef DEDICATED in sys_main.c
* Add Sys_ErrorDialog to report ERR_FATALs to the user
  + On Windows use a MessageBox and offer to copy the console log to the
    clipboard
  + On everything else print to the terminal and save the console log as
    crashlog.txt
This commit is contained in:
Tim Angus 2007-11-30 18:32:52 +00:00
parent ccc66aadff
commit 3cde9bf0dc
10 changed files with 340 additions and 95 deletions

View file

@ -1221,6 +1221,8 @@ Q3OBJ = \
$(B)/client/sdl_input.o \
$(B)/client/sdl_snd.o \
\
$(B)/client/con_passive.o \
$(B)/client/con_log.o \
$(B)/client/sys_main.o
ifeq ($(ARCH),i386)
@ -1358,6 +1360,7 @@ Q3DOBJ = \
$(B)/ded/null_input.o \
$(B)/ded/null_snddma.o \
\
$(B)/ded/con_log.o \
$(B)/ded/sys_main.o
ifeq ($(ARCH),i386)

View file

@ -2872,7 +2872,7 @@ static void FS_CheckPak0( void )
if(!fs_gamedirvar->string[0]
|| !Q_stricmp( fs_gamedirvar->string, BASEGAME )
|| !Q_stricmp( fs_gamedirvar->string, "missionpack" ))
Com_Error(ERR_FATAL, "\n*** you need to install Quake III Arena in order to play ***");
Com_Error(ERR_FATAL, "You need to install Quake III Arena in order to play");
}
}

129
code/sys/con_log.c Normal file
View file

@ -0,0 +1,129 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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 2 of the License,
or (at your option) any later version.
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "sys_local.h"
#define MAX_LOG 32768
static char consoleLog[ MAX_LOG ];
static unsigned int write = 0;
static unsigned int read = 0;
/*
==================
CON_LogSize
==================
*/
unsigned int CON_LogSize( void )
{
if( read <= write )
return write - read;
else
return write + MAX_LOG - read;
}
/*
==================
CON_LogFree
==================
*/
static unsigned int CON_LogFree( void )
{
return MAX_LOG - CON_LogSize( ) - 1;
}
/*
==================
CON_LogWrite
==================
*/
unsigned int CON_LogWrite( const char *in )
{
unsigned int length = strlen( in );
unsigned int firstChunk;
unsigned int secondChunk;
while( CON_LogFree( ) < length && CON_LogSize( ) > 0 )
{
// Free enough space
while( consoleLog[ read ] != '\n' && CON_LogSize( ) > 1 )
read = ( read + 1 ) % MAX_LOG;
// Skip past the '\n'
read = ( read + 1 ) % MAX_LOG;
}
if( CON_LogFree( ) < length )
return 0;
if( write + length > MAX_LOG )
{
firstChunk = MAX_LOG - write;
secondChunk = length - firstChunk;
}
else
{
firstChunk = length;
secondChunk = 0;
}
Com_Memcpy( consoleLog + write, in, firstChunk );
Com_Memcpy( consoleLog, in + firstChunk, secondChunk );
write = ( write + length ) % MAX_LOG;
return length;
}
/*
==================
CON_LogRead
==================
*/
unsigned int CON_LogRead( char *out, unsigned int outSize )
{
unsigned int firstChunk;
unsigned int secondChunk;
if( CON_LogSize( ) < outSize )
outSize = CON_LogSize( );
if( read + outSize > MAX_LOG )
{
firstChunk = MAX_LOG - read;
secondChunk = outSize - firstChunk;
}
else
{
firstChunk = outSize;
secondChunk = 0;
}
Com_Memcpy( out, consoleLog + read, firstChunk );
Com_Memcpy( out + firstChunk, out, secondChunk );
read = ( read + outSize ) % MAX_LOG;
return outSize;
}

68
code/sys/con_passive.c Normal file
View file

@ -0,0 +1,68 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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 2 of the License,
or (at your option) any later version.
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "sys_local.h"
#include <stdio.h>
/*
==================
CON_Shutdown
==================
*/
void CON_Shutdown( void )
{
}
/*
==================
CON_Init
==================
*/
void CON_Init( void )
{
}
/*
==================
CON_Input
==================
*/
char *CON_Input( void )
{
return NULL;
}
/*
==================
CON_Print
==================
*/
void CON_Print( const char *msg )
{
if( com_ansiColor && com_ansiColor->integer )
Sys_AnsiColorPrint( msg );
else
fputs( msg, stderr );
}

View file

@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "sys_local.h"
#include <unistd.h>
#include <signal.h>
@ -101,7 +102,7 @@ Clear the display of the line currently edited
bring cursor back to beginning of line
==================
*/
void CON_Hide( void )
static void CON_Hide( void )
{
if( ttycon_on )
{
@ -131,7 +132,7 @@ Show the current line
FIXME need to position the cursor if needed?
==================
*/
void CON_Show( void )
static void CON_Show( void )
{
if( ttycon_on )
{
@ -296,10 +297,10 @@ void CON_Init( void )
/*
==================
CON_ConsoleInput
CON_Input
==================
*/
char *CON_ConsoleInput( void )
char *CON_Input( void )
{
// we use this when sending back commands
static char text[256];
@ -439,3 +440,20 @@ char *CON_ConsoleInput( void )
return text;
}
}
/*
==================
CON_Print
==================
*/
void CON_Print( const char *msg )
{
CON_Hide( );
if( com_ansiColor && com_ansiColor->integer )
Sys_AnsiColorPrint( msg );
else
fputs( msg, stderr );
CON_Show( );
}

View file

@ -130,21 +130,12 @@ static void CON_HistNext( void )
}
/*
==================
CON_Hide
==================
*/
void CON_Hide( void )
{
}
/*
==================
CON_Show
==================
*/
void CON_Show( void )
static void CON_Show( void )
{
CONSOLE_SCREEN_BUFFER_INFO binfo;
COORD writeSize = { MAX_EDIT_LINE, 1 };
@ -155,7 +146,7 @@ void CON_Show( void )
GetConsoleScreenBufferInfo( qconsole_hout, &binfo );
// if we' re in the middle of printf, don't bother writing the buffer
// if we're in the middle of printf, don't bother writing the buffer
if( binfo.dwCursorPosition.X != 0 )
return;
@ -249,10 +240,10 @@ void CON_Init( void )
/*
==================
CON_ConsoleInput
CON_Input
==================
*/
char *CON_ConsoleInput( void )
char *CON_Input( void )
{
INPUT_RECORD buff[ MAX_EDIT_LINE ];
DWORD count = 0, events = 0;
@ -353,3 +344,15 @@ char *CON_ConsoleInput( void )
return qconsole_line;
}
/*
==================
CON_Print
==================
*/
void CON_Print( const char *msg )
{
fputs( msg, stderr );
CON_Show( );
}

View file

@ -29,19 +29,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MINSDL_PATCH 7
// Input subsystem
void IN_Init (void);
void IN_Frame (void);
void IN_Shutdown (void);
void IN_Init( void );
void IN_Frame( void );
void IN_Shutdown( void );
// Console
void CON_Hide( void );
void CON_Show( void );
void CON_Shutdown( void );
void CON_Init( void );
char *CON_ConsoleInput(void);
char *CON_Input( void );
void CON_Print( const char *message );
unsigned int CON_LogSize( void );
unsigned int CON_LogWrite( const char *in );
unsigned int CON_LogRead( char *out, unsigned int outSize );
#ifdef MACOS_X
char *Sys_StripAppBundle( char *pwd );
#endif
void Sys_SigHandler( int signal );
void Sys_ErrorDialog( const char *error );
void Sys_AnsiColorPrint( const char *msg );

View file

@ -106,34 +106,6 @@ void Sys_In_Restart_f( void )
IN_Init();
}
/*
=================
Sys_ConsoleInputInit
Start the console input subsystem
=================
*/
void Sys_ConsoleInputInit( void )
{
#ifdef DEDICATED
CON_Init( );
#endif
}
/*
=================
Sys_ConsoleInputShutdown
Shutdown the console input subsystem
=================
*/
void Sys_ConsoleInputShutdown( void )
{
#ifdef DEDICATED
CON_Shutdown( );
#endif
}
/*
=================
Sys_ConsoleInput
@ -143,11 +115,7 @@ Handle new console input
*/
char *Sys_ConsoleInput(void)
{
#ifdef DEDICATED
return CON_ConsoleInput( );
#endif
return NULL;
return CON_Input( );
}
/*
@ -159,18 +127,18 @@ Single exit point (regular exit or in case of error)
*/
void Sys_Exit( int ex )
{
Sys_ConsoleInputShutdown();
CON_Shutdown( );
#ifndef DEDICATED
SDL_Quit( );
#endif
#ifdef NDEBUG
exit(ex);
exit( ex );
#else
// Cause a backtrace on error exits
assert( ex == 0 );
exit(ex);
exit( ex );
#endif
}
@ -179,10 +147,10 @@ void Sys_Exit( int ex )
Sys_Quit
=================
*/
void Sys_Quit (void)
void Sys_Quit( void )
{
CL_Shutdown ();
Sys_Exit(0);
CL_Shutdown( );
Sys_Exit( 0 );
}
/*
@ -227,7 +195,7 @@ Sys_AnsiColorPrint
Transform Q3 colour codes to ANSI escape sequences
=================
*/
static void Sys_AnsiColorPrint( const char *msg )
void Sys_AnsiColorPrint( const char *msg )
{
static char buffer[ MAXPRINTMSG ];
int length = 0;
@ -296,18 +264,8 @@ Sys_Print
*/
void Sys_Print( const char *msg )
{
#ifdef DEDICATED
CON_Hide();
#endif
if( com_ansiColor && com_ansiColor->integer )
Sys_AnsiColorPrint( msg );
else
fputs(msg, stderr);
#ifdef DEDICATED
CON_Show();
#endif
CON_LogWrite( msg );
CON_Print( msg );
}
/*
@ -320,16 +278,13 @@ void Sys_Error( const char *error, ... )
va_list argptr;
char string[1024];
#ifdef DEDICATED
CON_Hide();
#endif
CL_Shutdown ();
va_start (argptr,error);
Q_vsnprintf (string, sizeof(string), error, argptr);
va_end (argptr);
fprintf(stderr, "Sys_Error: %s\n", string);
Sys_ErrorDialog( string );
Sys_Exit( 1 );
}
@ -348,15 +303,7 @@ void Sys_Warn( char *warning, ... )
Q_vsnprintf (string, sizeof(string), warning, argptr);
va_end (argptr);
#ifdef DEDICATED
CON_Hide();
#endif
fprintf(stderr, "Warning: %s", string);
#ifdef DEDICATED
CON_Show();
#endif
CON_Print( va( "Warning: %s", string ) );
}
/*
@ -624,9 +571,9 @@ int main( int argc, char **argv )
}
Com_Init( commandLine );
NET_Init();
NET_Init( );
Sys_ConsoleInputInit();
CON_Init( );
#ifndef _WIN32
// Windows doesn't have these signals

View file

@ -19,6 +19,11 @@ along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "sys_local.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
@ -30,9 +35,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <pwd.h>
#include <libgen.h>
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
// Used to determine where to store user-specific files
static char homePath[ MAX_OSPATH ] = { 0 };
@ -476,3 +478,33 @@ void Sys_Sleep( int msec )
select((fileno(stdin) + 1), &fdset, NULL, NULL, &timeout);
}
}
/*
==============
Sys_ErrorDialog
Display an error message
==============
*/
void Sys_ErrorDialog( const char *error )
{
char buffer[ 1024 ];
unsigned int size;
fileHandle_t f;
const char *fileName = "crashlog.txt";
Sys_Print( va( "%s\n", error ) );
// Write console log to file
f = FS_FOpenFileWrite( fileName );
if( !f )
{
Com_Printf( "ERROR: couldn't open %s\n", fileName );
return;
}
while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 )
FS_Write( buffer, size, f );
FS_FCloseFile( f );
}

View file

@ -525,3 +525,43 @@ void Sys_Sleep( int msec )
WaitForSingleObject( GetStdHandle( STD_INPUT_HANDLE ), msec );
}
/*
==============
Sys_ErrorDialog
Display an error message
==============
*/
void Sys_ErrorDialog( const char *error )
{
if( MessageBox( NULL, va( "%s. Copy console log to clipboard?", error ),
NULL, MB_YESNO|MB_ICONERROR ) == IDYES )
{
HGLOBAL memoryHandle;
char *clipMemory;
memoryHandle = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, CON_LogSize( ) + 1 );
clipMemory = (char *)GlobalLock( memoryHandle );
if( clipMemory )
{
char *p = clipMemory;
char buffer[ 1024 ];
unsigned int size;
while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 )
{
Com_Memcpy( p, buffer, size );
p += size;
}
*p = '\0';
if( OpenClipboard( NULL ) && EmptyClipboard( ) )
SetClipboardData( CF_TEXT, memoryHandle );
GlobalUnlock( clipMemory );
CloseClipboard( );
}
}
}