summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/sys_cocoa.m40
-rw-r--r--src/sys/sys_local.h3
-rw-r--r--src/sys/sys_main.c105
-rw-r--r--src/sys/sys_unix.c251
-rw-r--r--src/sys/sys_win32.c104
5 files changed, 389 insertions, 114 deletions
diff --git a/src/sys/sys_cocoa.m b/src/sys/sys_cocoa.m
deleted file mode 100644
index cfc754dd..00000000
--- a/src/sys/sys_cocoa.m
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-===========================================================================
-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
-===========================================================================
-*/
-
-#ifndef MACOS_X
-#error This file is for Mac OS X only. You probably should not compile it.
-#endif
-
-// Please note that this file is just some Mac-specific bits. Most of the
-// Mac OS X code is shared with other Unix platforms in sys_unix.c ...
-
-#import <Cocoa/Cocoa.h>
-
-void Cocoa_MsgBox( const char *text )
-{
- NSRunInformationalAlertPanel(@"ioquake3",
- [NSString stringWithUTF8String:text],
- @"OK", nil, nil);
-}
-
-// end of sys_cocoa.m ...
-
diff --git a/src/sys/sys_local.h b/src/sys/sys_local.h
index 6017150a..9f4de9cf 100644
--- a/src/sys/sys_local.h
+++ b/src/sys/sys_local.h
@@ -55,3 +55,6 @@ void Sys_PlatformInit( void );
void Sys_SigHandler( int signal );
void Sys_ErrorDialog( const char *error );
void Sys_AnsiColorPrint( const char *msg );
+
+int Sys_PID( void );
+qboolean Sys_PIDIsRunning( int pid );
diff --git a/src/sys/sys_main.c b/src/sys/sys_main.c
index 460e8a22..53fc57fb 100644
--- a/src/sys/sys_main.c
+++ b/src/sys/sys_main.c
@@ -128,6 +128,65 @@ char *Sys_ConsoleInput(void)
return CON_Input( );
}
+#ifdef DEDICATED
+# define PID_FILENAME PRODUCT_NAME "_server.pid"
+#else
+# define PID_FILENAME PRODUCT_NAME ".pid"
+#endif
+
+/*
+=================
+Sys_PIDFileName
+=================
+*/
+static char *Sys_PIDFileName( void )
+{
+ return va( "%s/%s", Sys_TempPath( ), PID_FILENAME );
+}
+
+/*
+=================
+Sys_WritePIDFile
+
+Return qtrue if there is an existing stale PID file
+=================
+*/
+qboolean Sys_WritePIDFile( void )
+{
+ char *pidFile = Sys_PIDFileName( );
+ FILE *f;
+ qboolean stale = qfalse;
+
+ // First, check if the pid file is already there
+ if( ( f = fopen( pidFile, "r" ) ) != NULL )
+ {
+ char pidBuffer[ 64 ] = { 0 };
+ int pid;
+
+ pid = fread( pidBuffer, sizeof( char ), sizeof( pidBuffer ) - 1, f );
+ fclose( f );
+
+ if(pid > 0)
+ {
+ pid = atoi( pidBuffer );
+ if( !Sys_PIDIsRunning( pid ) )
+ stale = qtrue;
+ }
+ else
+ stale = qtrue;
+ }
+
+ if( ( f = fopen( pidFile, "w" ) ) != NULL )
+ {
+ fprintf( f, "%d", Sys_PID( ) );
+ fclose( f );
+ }
+ else
+ Com_Printf( S_COLOR_YELLOW "Couldn't write %s.\n", pidFile );
+
+ return stale;
+}
+
/*
=================
Sys_Exit
@@ -135,7 +194,7 @@ Sys_Exit
Single exit point (regular exit or in case of error)
=================
*/
-void Sys_Exit( int ex )
+static void Sys_Exit( int exitCode )
{
CON_Shutdown( );
@@ -143,13 +202,13 @@ void Sys_Exit( int ex )
SDL_Quit( );
#endif
-#ifdef NDEBUG
- exit( ex );
-#else
- // Cause a backtrace on error exits
- assert( ex == 0 );
- exit( ex );
-#endif
+ if( exitCode < 2 )
+ {
+ // Normal exit
+ remove( Sys_PIDFileName( ) );
+ }
+
+ exit( exitCode );
}
/*
@@ -159,7 +218,6 @@ Sys_Quit
*/
void Sys_Quit( void )
{
- CL_Shutdown( );
Sys_Exit( 0 );
}
@@ -288,15 +346,14 @@ void Sys_Error( const char *error, ... )
va_list argptr;
char string[1024];
- CL_Shutdown ();
-
va_start (argptr,error);
Q_vsnprintf (string, sizeof(string), error, argptr);
va_end (argptr);
+ CL_Shutdown( string );
Sys_ErrorDialog( string );
- Sys_Exit( 1 );
+ Sys_Exit( 3 );
}
/*
@@ -451,7 +508,7 @@ void Sys_ParseArgs( int argc, char **argv )
#else
fprintf( stdout, Q3_VERSION " client (%s)\n", date );
#endif
- Sys_Exit(0);
+ Sys_Exit( 0 );
}
}
}
@@ -481,14 +538,16 @@ void Sys_SigHandler( int signal )
else
{
signalcaught = qtrue;
- fprintf( stderr, "Received signal %d, exiting...\n", signal );
#ifndef DEDICATED
- CL_Shutdown();
+ CL_Shutdown( va( "Received signal %d", signal ) );
#endif
- SV_Shutdown( "Signal caught" );
+ SV_Shutdown( va( "Received signal %d", signal ) );
}
- Sys_Exit( 0 ); // Exit with 0 to avoid recursive signals
+ if( signal == SIGTERM || signal == SIGINT )
+ Sys_Exit( 1 );
+ else
+ Sys_Exit( 2 );
}
/*
@@ -520,7 +579,10 @@ int main( int argc, char **argv )
if( SDL_VERSIONNUM( ver->major, ver->minor, ver->patch ) <
SDL_VERSIONNUM( MINSDL_MAJOR, MINSDL_MINOR, MINSDL_PATCH ) )
{
- Sys_Print( "SDL version " MINSDL_VERSION " or greater required\n" );
+ Sys_Dialog( DT_ERROR, va( "SDL version " MINSDL_VERSION " or greater is required, "
+ "but only version %d.%d.%d was found. You may be able to obtain a more recent copy "
+ "from http://www.libsdl.org/.", ver->major, ver->minor, ver->patch ), "SDL Library Too Old" );
+
Sys_Exit( 1 );
}
#endif
@@ -562,13 +624,6 @@ int main( int argc, char **argv )
while( 1 )
{
-#ifndef DEDICATED
- int appState = SDL_GetAppState( );
-
- Cvar_SetValue( "com_unfocused", !( appState & SDL_APPINPUTFOCUS ) );
- Cvar_SetValue( "com_minimized", !( appState & SDL_APPACTIVE ) );
-#endif
-
IN_Frame( );
Com_Frame( );
}
diff --git a/src/sys/sys_unix.c b/src/sys/sys_unix.c
index ccff6312..5ab0f8c7 100644
--- a/src/sys/sys_unix.c
+++ b/src/sys/sys_unix.c
@@ -69,6 +69,23 @@ char *Sys_DefaultHomePath(void)
return homePath;
}
+#ifndef MACOS_X
+/*
+================
+Sys_TempPath
+================
+*/
+const char *Sys_TempPath( void )
+{
+ const char *TMPDIR = getenv( "TMPDIR" );
+
+ if( TMPDIR == NULL || TMPDIR[ 0 ] == '\0' )
+ return "/tmp";
+ else
+ return TMPDIR;
+}
+#endif
+
/*
================
Sys_Milliseconds
@@ -76,8 +93,7 @@ Sys_Milliseconds
*/
/* base time in seconds, that's our origin
timeval:tv_sec is an int:
- assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038
- using unsigned long data type to work right with Sys_XTimeToSysTime */
+ assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038 */
unsigned long sys_timeBase = 0;
/* current time in ms, using sys_timeBase as origin
NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch
@@ -429,35 +445,6 @@ void Sys_FreeFileList( char **list )
Z_Free( list );
}
-#ifdef MACOS_X
-/*
-=================
-Sys_StripAppBundle
-
-Discovers if passed dir is suffixed with the directory structure of a Mac OS X
-.app bundle. If it is, the .app directory structure is stripped off the end and
-the result is returned. If not, dir is returned untouched.
-=================
-*/
-char *Sys_StripAppBundle( char *dir )
-{
- static char cwd[MAX_OSPATH];
-
- Q_strncpyz(cwd, dir, sizeof(cwd));
- if(strcmp(Sys_Basename(cwd), "MacOS"))
- return dir;
- Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
- if(strcmp(Sys_Basename(cwd), "Contents"))
- return dir;
- Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
- if(!strstr(Sys_Basename(cwd), ".app"))
- return dir;
- Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd));
- return cwd;
-}
-#endif // MACOS_X
-
-
/*
==================
Sys_Sleep
@@ -518,39 +505,195 @@ void Sys_ErrorDialog( const char *error )
Sys_Print( va( "%s\n", error ) );
-#if defined(MACOS_X) && !DEDICATED
- /* This function has to be in a separate file, compiled as Objective-C. */
- extern void Cocoa_MsgBox( const char *text );
- if (!com_dedicated || !com_dedicated->integer)
- Cocoa_MsgBox(error);
+#ifndef DEDICATED
+ Sys_Dialog( DT_ERROR, va( "%s. See \"%s\" for details.", error, ospath ), "Error" );
#endif
- /* make sure the write path for the crashlog exists... */
+ // Make sure the write path for the crashlog exists...
if( FS_CreatePath( ospath ) ) {
Com_Printf( "ERROR: couldn't create path '%s' for crash log.\n", ospath );
return;
}
- /* we might be crashing because we maxed out the Quake MAX_FILE_HANDLES,
- which will come through here, so we don't want to recurse forever by
- calling FS_FOpenFileWrite()...use the Unix system APIs instead. */
- f = open(ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640);
+ // We might be crashing because we maxed out the Quake MAX_FILE_HANDLES,
+ // which will come through here, so we don't want to recurse forever by
+ // calling FS_FOpenFileWrite()...use the Unix system APIs instead.
+ f = open( ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640 );
if( f == -1 )
{
Com_Printf( "ERROR: couldn't open %s\n", fileName );
return;
}
- /* We're crashing, so we don't care much if write() or close() fails. */
+ // We're crashing, so we don't care much if write() or close() fails.
while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 ) {
- if (write( f, buffer, size ) != size) {
+ if( write( f, buffer, size ) != size ) {
Com_Printf( "ERROR: couldn't fully write to %s\n", fileName );
break;
}
}
- close(f);
+ close( f );
+}
+
+#ifndef MACOS_X
+/*
+==============
+Sys_ZenityCommand
+==============
+*/
+static int Sys_ZenityCommand( dialogType_t type, const char *message, const char *title )
+{
+ const char *options = "";
+ char command[ 1024 ];
+
+ switch( type )
+ {
+ default:
+ case DT_INFO: options = "--info"; break;
+ case DT_WARNING: options = "--warning"; break;
+ case DT_ERROR: options = "--error"; break;
+ case DT_YES_NO: options = "--question --ok-label=\"Yes\" --cancel-label=\"No\""; break;
+ case DT_OK_CANCEL: options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\""; break;
+ }
+
+ Com_sprintf( command, sizeof( command ), "zenity %s --text=\"%s\" --title=\"%s\"",
+ options, message, title );
+
+ return system( command );
+}
+
+/*
+==============
+Sys_KdialogCommand
+==============
+*/
+static int Sys_KdialogCommand( dialogType_t type, const char *message, const char *title )
+{
+ const char *options = "";
+ char command[ 1024 ];
+
+ switch( type )
+ {
+ default:
+ case DT_INFO: options = "--msgbox"; break;
+ case DT_WARNING: options = "--sorry"; break;
+ case DT_ERROR: options = "--error"; break;
+ case DT_YES_NO: options = "--warningyesno"; break;
+ case DT_OK_CANCEL: options = "--warningcontinuecancel"; break;
+ }
+
+ Com_sprintf( command, sizeof( command ), "kdialog %s \"%s\" --title \"%s\"",
+ options, message, title );
+
+ return system( command );
+}
+
+/*
+==============
+Sys_XmessageCommand
+==============
+*/
+static int Sys_XmessageCommand( dialogType_t type, const char *message, const char *title )
+{
+ const char *options = "";
+ char command[ 1024 ];
+
+ switch( type )
+ {
+ default: options = "-buttons OK"; break;
+ case DT_YES_NO: options = "-buttons Yes:0,No:1"; break;
+ case DT_OK_CANCEL: options = "-buttons OK:0,Cancel:1"; break;
+ }
+
+ Com_sprintf( command, sizeof( command ), "xmessage -center %s \"%s\"",
+ options, message );
+
+ return system( command );
+}
+
+/*
+==============
+Sys_Dialog
+
+Display a *nix dialog box
+==============
+*/
+dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title )
+{
+ typedef enum
+ {
+ NONE = 0,
+ ZENITY,
+ KDIALOG,
+ XMESSAGE,
+ NUM_DIALOG_PROGRAMS
+ } dialogCommandType_t;
+ typedef int (*dialogCommandBuilder_t)( dialogType_t, const char *, const char * );
+
+ const char *session = getenv( "DESKTOP_SESSION" );
+ qboolean tried[ NUM_DIALOG_PROGRAMS ] = { qfalse };
+ dialogCommandBuilder_t commands[ NUM_DIALOG_PROGRAMS ] = { NULL };
+ dialogCommandType_t preferredCommandType = NONE;
+
+ commands[ ZENITY ] = &Sys_ZenityCommand;
+ commands[ KDIALOG ] = &Sys_KdialogCommand;
+ commands[ XMESSAGE ] = &Sys_XmessageCommand;
+
+ // This may not be the best way
+ if( !Q_stricmp( session, "gnome" ) )
+ preferredCommandType = ZENITY;
+ else if( !Q_stricmp( session, "kde" ) )
+ preferredCommandType = KDIALOG;
+
+ while( 1 )
+ {
+ int i;
+ int exitCode;
+
+ for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ )
+ {
+ if( preferredCommandType != NONE && preferredCommandType != i )
+ continue;
+
+ if( !tried[ i ] )
+ {
+ exitCode = commands[ i ]( type, message, title );
+
+ if( exitCode >= 0 )
+ {
+ switch( type )
+ {
+ case DT_YES_NO: return exitCode ? DR_NO : DR_YES;
+ case DT_OK_CANCEL: return exitCode ? DR_CANCEL : DR_OK;
+ default: return DR_OK;
+ }
+ }
+
+ tried[ i ] = qtrue;
+
+ // The preference failed, so start again in order
+ if( preferredCommandType != NONE )
+ {
+ preferredCommandType = NONE;
+ break;
+ }
+ }
+ }
+
+ for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ )
+ {
+ if( !tried[ i ] )
+ continue;
+ }
+
+ break;
+ }
+
+ Com_DPrintf( S_COLOR_YELLOW "WARNING: failed to show a dialog\n" );
+ return DR_OK;
}
+#endif
/*
==============
@@ -612,3 +755,23 @@ void Sys_SetEnv(const char *name, const char *value)
else
unsetenv(name);
}
+
+/*
+==============
+Sys_PID
+==============
+*/
+int Sys_PID( void )
+{
+ return getpid( );
+}
+
+/*
+==============
+Sys_PIDIsRunning
+==============
+*/
+qboolean Sys_PIDIsRunning( int pid )
+{
+ return kill( pid, 0 ) == 0;
+}
diff --git a/src/sys/sys_win32.c b/src/sys/sys_win32.c
index ead428eb..ad6f18eb 100644
--- a/src/sys/sys_win32.c
+++ b/src/sys/sys_win32.c
@@ -38,10 +38,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <conio.h>
#include <wincrypt.h>
#include <shlobj.h>
+#include <psapi.h>
// Used to determine where to store user-specific files
static char homePath[ MAX_OSPATH ] = { 0 };
+#ifdef __WIN64__
+void Sys_SnapVector( float *v )
+{
+ v[0] = rint(v[0]);
+ v[1] = rint(v[1]);
+ v[2] = rint(v[2]);
+}
+#endif
+
/*
================
Sys_DefaultHomePath
@@ -86,6 +96,24 @@ char *Sys_DefaultHomePath( void )
/*
================
+Sys_TempPath
+================
+*/
+const char *Sys_TempPath( void )
+{
+ static TCHAR path[ MAX_PATH ];
+ DWORD length;
+
+ length = GetTempPath( sizeof( path ), path );
+
+ if( length > sizeof( path ) || length == 0 )
+ return Sys_DefaultHomePath( );
+ else
+ return path;
+}
+
+/*
+================
Sys_Milliseconds
================
*/
@@ -317,7 +345,7 @@ void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, ch
{
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
char filename[MAX_OSPATH];
- int findhandle;
+ intptr_t findhandle;
struct _finddata_t findinfo;
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
@@ -400,7 +428,7 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter
char **listCopy;
char *list[MAX_FOUND_FILES];
struct _finddata_t findinfo;
- int findhandle;
+ intptr_t findhandle;
int flag;
int i;
@@ -545,8 +573,8 @@ 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 )
+ if( Sys_Dialog( DT_YES_NO, va( "%s. Copy console log to clipboard?", error ),
+ "Error" ) == DR_YES )
{
HGLOBAL memoryHandle;
char *clipMemory;
@@ -577,6 +605,37 @@ void Sys_ErrorDialog( const char *error )
}
}
+/*
+==============
+Sys_Dialog
+
+Display a win32 dialog box
+==============
+*/
+dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title )
+{
+ UINT uType;
+
+ switch( type )
+ {
+ default:
+ case DT_INFO: uType = MB_ICONINFORMATION|MB_OK; break;
+ case DT_WARNING: uType = MB_ICONWARNING|MB_OK; break;
+ case DT_ERROR: uType = MB_ICONERROR|MB_OK; break;
+ case DT_YES_NO: uType = MB_ICONQUESTION|MB_YESNO; break;
+ case DT_OK_CANCEL: uType = MB_ICONWARNING|MB_OKCANCEL; break;
+ }
+
+ switch( MessageBox( NULL, message, title, uType ) )
+ {
+ default:
+ case IDOK: return DR_OK;
+ case IDCANCEL: return DR_CANCEL;
+ case IDYES: return DR_YES;
+ case IDNO: return DR_NO;
+ }
+}
+
#ifndef DEDICATED
static qboolean SDL_VIDEODRIVER_externallySet = qfalse;
#endif
@@ -660,8 +719,43 @@ Sys_SetEnv
set/unset environment variables (empty value removes it)
==============
*/
-
void Sys_SetEnv(const char *name, const char *value)
{
_putenv(va("%s=%s", name, value));
}
+
+/*
+==============
+Sys_PID
+==============
+*/
+int Sys_PID( void )
+{
+ return GetCurrentProcessId( );
+}
+
+/*
+==============
+Sys_PIDIsRunning
+==============
+*/
+qboolean Sys_PIDIsRunning( int pid )
+{
+ DWORD processes[ 1024 ];
+ DWORD numBytes, numProcesses;
+ int i;
+
+ if( !EnumProcesses( processes, sizeof( processes ), &numBytes ) )
+ return qfalse; // Assume it's not running
+
+ numProcesses = numBytes / sizeof( DWORD );
+
+ // Search for the pid
+ for( i = 0; i < numProcesses; i++ )
+ {
+ if( processes[ i ] == pid )
+ return qtrue;
+ }
+
+ return qfalse;
+}