Exemplo n.º 1
0
/*
=============
Com_Printf

Both client and server can use this, and it will output
to the apropriate place.

A raw string should NEVER be passed as fmt, because of "%f" type crashers.
=============
*/
void QDECL Com_Printf( const char *fmt, ... ) {
	va_list		argptr;
	char		msg[MAXPRINTMSG];

	va_start (argptr,fmt);
	vsprintf (msg,fmt,argptr);
	va_end (argptr);

	if ( rd_buffer ) {
		if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1)) {
			rd_flush(rd_buffer);
			*rd_buffer = 0;
		}
		Q_strcat(rd_buffer, rd_buffersize, msg);
		rd_flush(rd_buffer);			
		*rd_buffer = 0;
		return;
	}

	// echo to console if we're not a dedicated server
	if ( com_dedicated && !com_dedicated->integer ) {
		CL_ConsolePrint( msg );
	}

	// echo to dedicated console and early console
	Sys_Print( msg );

	// logfile
#ifndef _XBOX
	if ( com_logfile && com_logfile->integer ) {
		if ( !logfile && FS_Initialized() ) {
			struct tm *newtime;
			time_t aclock;

			time( &aclock );
			newtime = localtime( &aclock );

			logfile = FS_FOpenFileWrite( "qconsole.log" );
			Com_Printf( "logfile opened on %s\n", asctime( newtime ) );
			if ( com_logfile->integer > 1 ) {
				// force it to not buffer so we get valid
				// data even if we are crashing
				FS_ForceFlush(logfile);
			}
		}
		if ( logfile && FS_Initialized()) {
			FS_Write(msg, strlen(msg), logfile);
		}
	}
#endif

#if defined(_WIN32) && defined(_DEBUG) && !defined(_XBOX)
	if ( *msg )
	{
		OutputDebugString ( Q_CleanStr(msg) );
		OutputDebugString ("\n");
	}
#endif
}
Exemplo n.º 2
0
/*
 * Both client and server can use this, and it will output
 * to the apropriate place.
 */
void
Com_Printf(char *fmt, ...)
{
	va_list argptr;
	char msg[MAXPRINTMSG];

	va_start(argptr, fmt);
	vsnprintf(msg, MAXPRINTMSG, fmt, argptr);
	va_end(argptr);

	if (rd_target)
	{
		if ((strlen(msg) + strlen(rd_buffer)) > (rd_buffersize - 1))
		{
			rd_flush(rd_target, rd_buffer);
			*rd_buffer = 0;
		}

		strcat(rd_buffer, msg);
		return;
	}

#ifndef DEDICATED_ONLY
	Con_Print(msg);
#endif

	/* also echo to debugging console */
	Sys_ConsoleOutput(msg);

	/* logfile */
	if (logfile_active && logfile_active->value)
	{
		char name[MAX_QPATH];

		if (!logfile)
		{
			Com_sprintf(name, sizeof(name), "%s/qconsole.log", FS_Gamedir());

			if (logfile_active->value > 2)
			{
				logfile = fopen(name, "a");
			}

			else
			{
				logfile = fopen(name, "w");
			}
		}

		if (logfile)
		{
			fprintf(logfile, "%s", msg);
		}

		if (logfile_active->value > 1)
		{
			fflush(logfile);  /* force it to save every time */
		}
	}
}
Exemplo n.º 3
0
void Com_EndRedirect (void)
{
	rd_flush(rd_target, rd_buffer);

	rd_target = 0;
	rd_buffer = NULL;
	rd_buffersize = 0;
	rd_flush = NULL;
}
Exemplo n.º 4
0
void Com_EndRedirect( void ) {
	if ( rd_flush ) {
		rd_flush( rd_buffer );
	}

	rd_buffer = NULL;
	rd_buffersize = 0;
	rd_flush = NULL;
}
Exemplo n.º 5
0
/*
=============
Com_Printf

Both client and server can use this, and it will output
to the apropriate place.
=============
*/
void Com_Printf (char *fmt, ...)
{
	va_list		argptr;
	char		msg[MAXPRINTMSG];
	static qboolean printstamp = true; // jittimestamp

	va_start(argptr, fmt);
	_vsnprintf(msg, sizeof(msg), fmt, argptr); // jitsecurity -- prevent buffer overruns
	va_end(argptr);
	NULLTERMINATE(msg); // jitsecurity -- make sure string is null terminated.

	if (rd_target)
	{
		if ((strlen(msg) + strlen(rd_buffer)) > (rd_buffersize - 1))
		{
			rd_flush(rd_target, rd_buffer);
			*rd_buffer = 0;
		}

		strcat(rd_buffer, msg);
		return;
	}

	Con_Print(msg);

	// ===
	// jittimestamp
	if (printstamp && timestamp_console && timestamp_console->value)
	{	// don't tag timestamps on if it's not a new line
		time_t now;
		char timestamp[256];
		struct tm *nowtime;
		static int lastday = -1;

		time(&now);
		nowtime = localtime(&now);
		
		if (nowtime->tm_mday != lastday)
		{
			Com_sprintf(timestamp, sizeof(timestamp), "[********] Date: %04d-%02d-%02d\n",
				nowtime->tm_year + 1900, nowtime->tm_mon + 1, nowtime->tm_mday);
			Sys_ConsoleOutput(timestamp);
			ConsoleLogfile(timestamp);
			lastday = nowtime->tm_mday;
		}

		strftime(timestamp, sizeof(timestamp), "[%H:%M:%S] ", nowtime);
		Sys_ConsoleOutput(timestamp);
		ConsoleLogfile(timestamp);
	}
	
	Sys_ConsoleOutput(msg);
	printstamp = (strchr(msg, '\n') != NULL); // so we only print timestamps after a newline.
	ConsoleLogfile(msg);
	// jittimestamp
	// ===
}
Exemplo n.º 6
0
/*
==================
idCommonLocal::EndRedirect
==================
*/
void idCommonLocal::EndRedirect() {
	if ( rd_flush && rd_buffer[ 0 ] ) {
		rd_flush( rd_buffer );
	}

	rd_buffer = NULL;
	rd_buffersize = 0;
	rd_flush = NULL;
}
__cdecl void Com_PrintMessage( int dumbIWvar, char *msg, msgtype_t type) {

	//secures calls to Com_PrintMessage from recursion while redirect printing
	static qboolean lock = qfalse;

	if(dumbIWvar == 6) return;

	int msglen = strlen(msg);

	if(type != MSG_NORDPRINT && !lock)
	{
	
		Sys_EnterCriticalSection(CRIT_REDIRECTPRINT);

		if ( !lock) {

			lock = qtrue;
			Com_PrintRedirect(msg, msglen);
			lock = qfalse;

			if ( rd_buffer ) {
				if(!rd_flush){
					Sys_LeaveCriticalSection(CRIT_REDIRECTPRINT);
					return;
				}
				if ((msglen + strlen(rd_buffer)) > (rd_buffersize - 1)) {

					lock = qtrue;
					rd_flush(rd_buffer, qfalse);
					lock = qfalse;

					*rd_buffer = 0;
				}
				Q_strcat(rd_buffer, rd_buffersize, msg);
				// TTimo nooo .. that would defeat the purpose
				//rd_flush(rd_buffer);
				//*rd_buffer = 0;
				Sys_LeaveCriticalSection(CRIT_REDIRECTPRINT);
				return;
			}
		}
		
		Sys_LeaveCriticalSection(CRIT_REDIRECTPRINT);
	
	}

	
	// echo to dedicated console and early console
	Sys_Print( msg );

	// logfile
	Com_PrintLogfile( msg );

}
Exemplo n.º 8
0
void Com_EndRedirect( void )
{
	rd_flush( rd_target, rd_buffer, rd_extra );

	rd_target = 0;
	rd_buffer = NULL;
	rd_buffersize = 0;
	rd_flush = NULL;
	rd_extra = NULL;

	QMutex_Unlock( com_print_mutex );
}
Exemplo n.º 9
0
void QDECL Com_PrintfAlways( const char *fmt, ... ) {
	va_list		argptr;
	char		msg[MAXPRINTMSG];

	va_start (argptr,fmt);
	vsprintf (msg,fmt,argptr);
	va_end (argptr);

#ifndef _XBOX
	if ( rd_buffer ) {
		if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1)) {
			rd_flush(rd_buffer);
			*rd_buffer = 0;
		}
		strcat (rd_buffer, msg);
		return;
	}
#endif

	CL_ConsolePrint( msg );

	// echo to dedicated console and early console
#ifndef FINAL_BUILD
	Sys_Print( msg );

#ifdef OUTPUT_TO_BUILD_WINDOW
	OutputDebugString(msg);
#endif
#endif

#ifndef _XBOX
	// logfile
	if ( com_logfile && com_logfile->integer ) {
		if ( !logfile ) {
			logfile = FS_FOpenFileWrite( "qconsole.log" );
			if ( com_logfile->integer > 1 ) {
				// force it to not buffer so we get valid
				// data even if we are crashing
				FS_ForceFlush(logfile);
			}
		}
		if ( logfile ) {
			FS_Write(msg, strlen(msg), logfile);
		}
	}
#endif
}
Exemplo n.º 10
0
void Capture() {
	//TODO: follow console filtering rules
	if(addresses.size()){
		for(i = 0; i < addresses.size(); i++){
			const char* toSend = va("%i %s", channel, msg);
			Sys_SendPacket(strlen(toSend), toSend, addresses[i]);
		}
	}
	if (rd_buffer)
	{
		if ( ( strlen( msg ) + strlen( rd_buffer ) ) > ( rd_buffersize - 1 ) ) {
			rd_flush( rd_buffer );
			*rd_buffer = 0;
		}
		strncat( rd_buffer, msg, rd_buffersize );
	}
}
Exemplo n.º 11
0
/*
=============
Com_Printf

Both client and server can use this, and it will output
to the apropriate place.

A raw string should NEVER be passed as fmt, because of "%f" type crashers.
=============
*/
void QDECL Com_Printf( const char *fmt, ... ) {
	va_list		argptr;
	char		msg[MAXPRINTMSG];

	va_start (argptr,fmt);
	Q_vsnprintf (msg, sizeof(msg), fmt, argptr);
	va_end (argptr);

	if ( rd_buffer ) {
		if ((strlen (msg) + strlen(rd_buffer)) > (unsigned)(rd_buffersize - 1)) {
			rd_flush(rd_buffer);
			*rd_buffer = 0;
		}
		Q_strcat (rd_buffer, strlen(rd_buffer), msg);
		return;
	}

	CL_ConsolePrint( msg );

	// Strip out color codes because these aren't needed in the log/viewlog or in the output window --eez
	Q_StripColor( msg );

	// echo to dedicated console and early console
	Sys_Print( msg );


#ifdef OUTPUT_TO_BUILD_WINDOW
	OutputDebugString(msg);
#endif

	// logfile
	if ( com_logfile && com_logfile->integer ) {
		if ( !logfile ) {
			logfile = FS_FOpenFileWrite( "qconsole.log" );
			if ( com_logfile->integer > 1 ) {
				// force it to not buffer so we get valid
				// data even if we are crashing
				FS_ForceFlush(logfile);
			}
		}
		if ( logfile ) {
			FS_Write(msg, strlen(msg), logfile);
		}
	}
}
Exemplo n.º 12
0
/*
=============
Com_Printf

Both client and server can use this, and it will output
to the apropriate place.

A raw string should NEVER be passed as fmt, because of "%f" type crashers.
=============
*/
void QDECL Com_Printf( const char *fmt, ... ) {
	va_list		argptr;
	char		msg[MAXPRINTMSG];

	va_start (argptr,fmt);
	vsprintf (msg,fmt,argptr);
	va_end (argptr);

	if ( rd_buffer ) {
		if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1)) {
			rd_flush(rd_buffer);
			*rd_buffer = 0;
		}
		strcat (rd_buffer, msg);
		return;
	}

	CL_ConsolePrint( msg );

	// echo to dedicated console and early console
	Sys_Print( msg );

	// logfile
	if ( com_logfile && com_logfile->integer ) {
		if ( !logfile ) {
			logfile = FS_FOpenFileWrite( "qconsole.log" );
			if ( com_logfile->integer > 1 ) {
				// force it to not buffer so we get valid
				// data even if we are crashing
				FS_ForceFlush(logfile);
			}
		}
		if ( logfile ) {
			FS_Write(msg, strlen(msg), logfile);
		}
	}
}
Exemplo n.º 13
0
/*
=============
Com_Printf

Both client and server can use this, and it will output
to the apropriate place.

A raw string should NEVER be passed as fmt, because of "%f" type crashers.
=============
*/
void QDECL Com_Printf( const char *fmt, ... ) {
	va_list		argptr;
	char		msg[MAXPRINTMSG];
	static qboolean opening_qconsole = qfalse;

	va_start (argptr,fmt);
	Q_vsnprintf (msg, sizeof(msg), fmt, argptr);
	va_end (argptr);

	if ( rd_buffer ) {
		if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1)) {
			rd_flush(rd_buffer);
			*rd_buffer = 0;
		}
		Q_strcat(rd_buffer, rd_buffersize, msg);
    // TTimo nooo .. that would defeat the purpose
		//rd_flush(rd_buffer);			
		//*rd_buffer = 0;
		return;
	}

	// echo to console if we're not a dedicated server
	if ( com_dedicated && !com_dedicated->integer ) {
		CL_ConsolePrint( msg );
	}

	// echo to dedicated console and early console
	Sys_Print( msg );

	// logfile
	if ( com_logfile && com_logfile->integer ) {
    // TTimo: only open the qconsole.log if the filesystem is in an initialized state
    //   also, avoid recursing in the qconsole.log opening (i.e. if fs_debug is on)
		if ( !logfile && FS_Initialized() && !opening_qconsole ) {
			struct tm *newtime;
			time_t aclock;

			opening_qconsole = qtrue;

			time( &aclock );
			newtime = localtime( &aclock );

			logfile = FS_FOpenFileWrite( "qconsole.log" );

			if ( logfile ) {
				Com_Printf( "logfile opened on %s\n", asctime( newtime ) );
				if ( com_logfile->integer > 1 ) {
					// force it to not buffer so we get valid
					// data even if we are crashing
					FS_ForceFlush(logfile);
				}
			}
			else {
				Com_Printf( "Opening qconsole.log failed!\n" );
				Cvar_SetValue( "logfile", 0 );
			}
		}
		opening_qconsole = qfalse;
		if ( logfile && FS_Initialized()) {
			FS_Write(msg, strlen(msg), logfile);
		}
	}


#if defined(_WIN32) && defined(_DEBUG)
	if ( *msg )
	{
		OutputDebugString ( Q_CleanStr(msg) );
		OutputDebugString ("\n");
	}
#endif
}
Exemplo n.º 14
0
/*
* Com_Printf
* 
* Both client and server can use this, and it will output
* to the apropriate place.
*/
void Com_Printf( const char *format, ... )
{
	va_list	argptr;
	char msg[MAX_PRINTMSG];

	time_t timestamp;
	char timestamp_str[MAX_PRINTMSG];
	struct tm *timestampptr;
	timestamp = time( NULL );
	timestampptr = gmtime( &timestamp );
	strftime( timestamp_str, MAX_PRINTMSG, "%Y-%m-%dT%H:%M:%SZ ", timestampptr );

	va_start( argptr, format );
	Q_vsnprintfz( msg, sizeof( msg ), format, argptr );
	va_end( argptr );

	if( rd_target )
	{
		if( (int)( strlen( msg ) + strlen( rd_buffer ) ) > ( rd_buffersize - 1 ) )
		{
			rd_flush( rd_target, rd_buffer, rd_extra );
			*rd_buffer = 0;
		}
		strcat( rd_buffer, msg );
		return;
	}

	QMutex_Lock( com_print_mutex );

	Con_Print( msg );

	// also echo to debugging console
	Sys_ConsoleOutput( msg );

	// logconsole
	if( logconsole && logconsole->modified )
	{
		logconsole->modified = qfalse;

		if( log_file )
		{
			FS_FCloseFile( log_file );
			log_file = 0;
		}

		if( logconsole->string && logconsole->string[0] )
		{
			size_t name_size;
			char *name;

			name_size = strlen( logconsole->string ) + strlen( ".log" ) + 1;
			name = ( char* )Mem_TempMalloc( name_size );
			Q_strncpyz( name, logconsole->string, name_size );
			COM_DefaultExtension( name, ".log", name_size );

			if( FS_FOpenFile( name, &log_file, ( logconsole_append && logconsole_append->integer ? FS_APPEND : FS_WRITE ) ) == -1 )
			{
				log_file = 0;
				Com_Printf( "Couldn't open: %s\n", name );
			}

			Mem_TempFree( name );
		}
	}

	if( log_file )
	{
		if( logconsole_timestamp && logconsole_timestamp->integer )
			FS_Printf( log_file, "%s", timestamp_str );
		FS_Printf( log_file, "%s", msg );
		if( logconsole_flush && logconsole_flush->integer )
			FS_Flush( log_file ); // force it to save every time
	}

	QMutex_Unlock( com_print_mutex );
}
Exemplo n.º 15
0
/*
==================
idCommonLocal::VPrintf

A raw string should NEVER be passed as fmt, because of "%f" type crashes.
==================
*/
void idCommonLocal::VPrintf( const char *fmt, va_list args ) {
	static bool	logFileFailed = false;

	// if the cvar system is not initialized
	if ( !cvarSystem->IsInitialized() ) {
		return;
	}
	// optionally put a timestamp at the beginning of each print,
	// so we can see how long different init sections are taking
	int timeLength = 0;
	char msg[MAX_PRINT_MSG_SIZE];
	msg[ 0 ] = '\0';
	if ( com_timestampPrints.GetInteger() ) {
		int	t = Sys_Milliseconds();
		if ( com_timestampPrints.GetInteger() == 1 ) {
			sprintf( msg, "[%5.2f]", t * 0.001f );
		} else {
			sprintf( msg, "[%i]", t );
		}
	} 
	timeLength = strlen( msg );
	// don't overflow
	if ( idStr::vsnPrintf( msg+timeLength, MAX_PRINT_MSG_SIZE-timeLength-1, fmt, args ) < 0 ) {
		msg[sizeof(msg)-2] = '\n'; msg[sizeof(msg)-1] = '\0'; // avoid output garbling
		Sys_Printf( "idCommon::VPrintf: truncated to %d characters\n", strlen(msg)-1 );
	}

	if ( rd_buffer ) {
		if ( (int)( strlen( msg ) + strlen( rd_buffer ) ) > ( rd_buffersize - 1 ) ) {
			rd_flush( rd_buffer );
			*rd_buffer = 0;
		}
		strcat( rd_buffer, msg );
		return;
	}
#ifndef ID_RETAIL
	if ( com_printFilter.GetString() != NULL && com_printFilter.GetString()[ 0 ] != '\0' ) {
		idStrStatic< 4096 > filterBuf = com_printFilter.GetString();
		idStrStatic< 4096 > msgBuf = msg;
		filterBuf.ToLower();
		msgBuf.ToLower();
		char *sp = strtok( &filterBuf[ 0 ], ";" );
		bool p = false;
		for( ; sp != NULL ; ) {
			if ( strstr( msgBuf, sp ) != NULL ) {
				p = true;
				break;
			}
			sp = strtok( NULL, ";" );
		}
		if ( !p ) {
			return;
		}
	}
#endif
	if ( !idLib::IsMainThread() ) {
#if defined( ID_PC_WIN )
		OutputDebugString( msg );
#else
		printf( "%s", msg );
#endif // ID_PC_WIN
		return;
	}

	// echo to console buffer
	console->Print( msg );

	// remove any color codes
	idStr::RemoveColors( msg );

	// echo to dedicated console and early console
	Sys_Printf( "%s", msg );

	// print to script debugger server
	// DebuggerServerPrint( msg );

#if 0	// !@#
#if defined(_DEBUG) && defined(WIN32)
	if ( strlen( msg ) < 512 ) {
		TRACE( msg );
	}
#endif
#endif

	// logFile
	if ( com_logFile.GetInteger() && !logFileFailed && fileSystem->IsInitialized() ) {
		static bool recursing;

		if ( !logFile && !recursing ) {
			const char *fileName = com_logFileName.GetString()[0] ? com_logFileName.GetString() : "qconsole.log";

			// fileSystem->OpenFileWrite can cause recursive prints into here
			recursing = true;

			logFile = fileSystem->OpenFileWrite( fileName );
			if ( !logFile ) {
				logFileFailed = true;
				FatalError( "failed to open log file '%s'\n", fileName );
			}

			recursing = false;

			if ( com_logFile.GetInteger() > 1 ) {
				// force it to not buffer so we get valid
				// data even if we are crashing
				logFile->ForceFlush();
			}

			time_t aclock;
			time( &aclock );
			struct tm * newtime = localtime( &aclock );
			Printf( "log file '%s' opened on %s\n", fileName, asctime( newtime ) );
		}
		if ( logFile ) {
			logFile->Write( msg, strlen( msg ) );
			logFile->Flush();	// ForceFlush doesn't help a whole lot
		}
	}

	// don't trigger any updates if we are in the process of doing a fatal error
	if ( com_errorEntered != ERP_FATAL ) {
		// update the console if we are in a long-running command, like dmap
		if ( com_refreshOnPrint ) {
			const bool captureToImage = false;
			UpdateScreen( captureToImage );
		}
	}
}
Exemplo n.º 16
0
/*
 * Both client and server can use this, and it will output
 * to the apropriate place.
 */
void
Com_VPrintf(int print_level, const char *fmt, va_list argptr)
{
	if((print_level == PRINT_DEVELOPER) && (!developer || !developer->value))
	{
		return; /* don't confuse non-developers with techie stuff... */
	}
	else
	{
		int i;
		char msg[MAXPRINTMSG];
		int msgLen = vsnprintf(msg, MAXPRINTMSG, fmt, argptr);
		if(msgLen >= MAXPRINTMSG)  msgLen = MAXPRINTMSG-1;
		if (rd_target)
		{
			if ((msgLen + strlen(rd_buffer)) > (rd_buffersize - 1))
			{
				rd_flush(rd_target, rd_buffer);
				*rd_buffer = 0;
			}

			strcat(rd_buffer, msg);
			return;
		}

	#ifndef DEDICATED_ONLY
		Con_Print(msg);
	#endif

		// remove unprintable characters
		for(i=0; i<msgLen; ++i)
		{
			char c = msg[i];
			if(c < ' ' && (c < '\t' || c > '\r'))
			{
				switch(c)
				{
					// no idea if the following two are ever sent here, but in conchars.pcx they look like this
					// so do the replacements.. won't hurt I guess..
					case 0x10:
						msg[i] = '[';
						break;
					case 0x11:
						msg[i] = ']';
						break;
					// horizontal line chars
					case 0x1D:
					case 0x1F:
						msg[i] = '-';
						break;
					case 0x1E:
						msg[i] = '=';
						break;
					default: // just replace all other unprintable chars with space, should be good enough
						msg[i] = ' ';
				}
			}
		}

		/* also echo to debugging console */
		Sys_ConsoleOutput(msg);

		/* logfile */
		if (logfile_active && logfile_active->value)
		{
			char name[MAX_OSPATH];

			if (!logfile)
			{
				Com_sprintf(name, sizeof(name), "%s/qconsole.log", FS_Gamedir());

				if (logfile_active->value > 2)
				{
					logfile = fopen(name, "a");
				}

				else
				{
					logfile = fopen(name, "w");
				}
			}

			if (logfile)
			{
				fprintf(logfile, "%s", msg);
			}

			if (logfile_active->value > 1)
			{
				fflush(logfile);  /* force it to save every time */
			}
		}
	}
}
Exemplo n.º 17
0
/*
=============
Com_Printf

Both client and server can use this, and it will output
to the apropriate place.
=============
*/
void Com_Printf (const char *fmt, ...)
{
	va_list		argptr;
	char		msg[MAXPRINTMSG], *s, *text;

	va_start (argptr,fmt);
	vsnprintf(msg, MAXPRINTMSG, fmt, argptr);
	va_end (argptr);

	if (rd_target)
	{
		if ((strlen (msg) + strlen(rd_buffer)) > (rd_buffersize - 1)) {
			rd_flush(rd_target, rd_buffer);
			*rd_buffer = 0;
		}
		strcat (rd_buffer, msg);
		return;
	}

	Con_Print (msg);

	text = msg;
	//Remove color triggers
	switch (msg[0]) {
	case 1:
	case 2:
		text++;
	default:
		for (s = text; *s; s++)
			*s &= 127;
		break;
	case COLOR_ONE:
		text++;
		if (Q_IsColorString(text))
			text += 2;

		for (s = text; *s; s++)
			*s &= 127;
		break;
	case COLOR_ENABLE:
		text++;
		for (s = text; *s;) {
			if(Q_IsColorString(s)) {
				memmove( s, s + 2, MAXPRINTMSG - 2 - (s - msg));
				continue;
			}
			*s++ &= 127;
		}
		break;
	}

	// also echo to debugging console
	Sys_ConsoleOutput (text);

	// logfile
	if (logfile_active->integer) {
		if (!logfile) {
			logfile = fopen(va("%s/qconsole.log", FS_Gamedir()), (logfile_active->integer > 2) ? "a" : "w");
		}
		if (logfile) {
			fprintf(logfile, "%s", text);
			if (logfile_active->integer > 1)
				fflush(logfile);		// force it to save every time
		}
	}
}