diff options
Diffstat (limited to 'src/sys')
-rw-r--r-- | src/sys/sys_cocoa.m | 40 | ||||
-rw-r--r-- | src/sys/sys_local.h | 3 | ||||
-rw-r--r-- | src/sys/sys_main.c | 105 | ||||
-rw-r--r-- | src/sys/sys_unix.c | 251 | ||||
-rw-r--r-- | src/sys/sys_win32.c | 104 |
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; +} |