aboutsummaryrefslogtreecommitdiffstats
path: root/code/unix/unix_shared.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/unix/unix_shared.c')
-rwxr-xr-xcode/unix/unix_shared.c870
1 files changed, 435 insertions, 435 deletions
diff --git a/code/unix/unix_shared.c b/code/unix/unix_shared.c
index af67760..742cffe 100755
--- a/code/unix/unix_shared.c
+++ b/code/unix/unix_shared.c
@@ -1,435 +1,435 @@
-/*
-===========================================================================
-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 Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <pwd.h>
-
-#include "../game/q_shared.h"
-#include "../qcommon/qcommon.h"
-
-//=============================================================================
-
-// Used to determine CD Path
-static char cdPath[MAX_OSPATH];
-
-// Used to determine local installation path
-static char installPath[MAX_OSPATH];
-
-// Used to determine where to store user-specific files
-static char homePath[MAX_OSPATH];
-
-/*
-================
-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 */
-unsigned long sys_timeBase = 0;
-/* current time in ms, using sys_timeBase as origin
- NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch
- 0x7fffffff ms - ~24 days
- although timeval:tv_usec is an int, I'm not sure wether it is actually used as an unsigned int
- (which would affect the wrap period) */
-int curtime;
-int Sys_Milliseconds (void)
-{
- struct timeval tp;
-
- gettimeofday(&tp, NULL);
-
- if (!sys_timeBase)
- {
- sys_timeBase = tp.tv_sec;
- return tp.tv_usec/1000;
- }
-
- curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
-
- return curtime;
-}
-
-#if defined(__linux__) && !defined(DEDICATED)
-/*
-================
-Sys_XTimeToSysTime
-sub-frame timing of events returned by X
-X uses the Time typedef - unsigned long
-disable with in_subframe 0
-
- sys_timeBase*1000 is the number of ms since the Epoch of our origin
- xtime is in ms and uses the Epoch as origin
- Time data type is an unsigned long: 0xffffffff ms - ~49 days period
- I didn't find much info in the XWindow documentation about the wrapping
- we clamp sys_timeBase*1000 to unsigned long, that gives us the current origin for xtime
- the computation will still work if xtime wraps (at ~49 days period since the Epoch) after we set sys_timeBase
-
-================
-*/
-extern cvar_t *in_subframe;
-int Sys_XTimeToSysTime (unsigned long xtime)
-{
- int ret, time, test;
-
- if (!in_subframe->value)
- {
- // if you don't want to do any event times corrections
- return Sys_Milliseconds();
- }
-
- // test the wrap issue
-#if 0
- // reference values for test: sys_timeBase 0x3dc7b5e9 xtime 0x541ea451 (read these from a test run)
- // xtime will wrap in 0xabe15bae ms >~ 0x2c0056 s (33 days from Nov 5 2002 -> 8 Dec)
- // NOTE: date -d '1970-01-01 UTC 1039384002 seconds' +%c
- // use sys_timeBase 0x3dc7b5e9+0x2c0056 = 0x3df3b63f
- // after around 5s, xtime would have wrapped around
- // we get 7132, the formula handles the wrap safely
- unsigned long xtime_aux,base_aux;
- int test;
-// Com_Printf("sys_timeBase: %p\n", sys_timeBase);
-// Com_Printf("xtime: %p\n", xtime);
- xtime_aux = 500; // 500 ms after wrap
- base_aux = 0x3df3b63f; // the base a few seconds before wrap
- test = xtime_aux - (unsigned long)(base_aux*1000);
- Com_Printf("xtime wrap test: %d\n", test);
-#endif
-
- // some X servers (like suse 8.1's) report weird event times
- // if the game is loading, resolving DNS, etc. we are also getting old events
- // so we only deal with subframe corrections that look 'normal'
- ret = xtime - (unsigned long)(sys_timeBase*1000);
- time = Sys_Milliseconds();
- test = time - ret;
- //printf("delta: %d\n", test);
- if (test < 0 || test > 30) // in normal conditions I've never seen this go above
- {
- return time;
- }
-
- return ret;
-}
-#endif
-
-//#if 0 // bk001215 - see snapvector.nasm for replacement
-#if (defined __APPLE__) // rcg010206 - using this for PPC builds...
-long fastftol( float f ) { // bk001213 - from win32/win_shared.c
- //static int tmp;
- // __asm fld f
- //__asm fistp tmp
- //__asm mov eax, tmp
- return (long)f;
-}
-
-void Sys_SnapVector( float *v ) { // bk001213 - see win32/win_shared.c
- // bk001213 - old linux
- v[0] = rint(v[0]);
- v[1] = rint(v[1]);
- v[2] = rint(v[2]);
-}
-#endif
-
-
-void Sys_Mkdir( const char *path )
-{
- mkdir (path, 0777);
-}
-
-char *strlwr (char *s) {
- if ( s==NULL ) { // bk001204 - paranoia
- assert(0);
- return s;
- }
- while (*s) {
- *s = tolower(*s);
- s++;
- }
- return s; // bk001204 - duh
-}
-
-//============================================
-
-#define MAX_FOUND_FILES 0x1000
-
-// bk001129 - new in 1.26
-void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) {
- char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
- char filename[MAX_OSPATH];
- DIR *fdir;
- struct dirent *d;
- struct stat st;
-
- if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
- return;
- }
-
- if (strlen(subdirs)) {
- Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs );
- }
- else {
- Com_sprintf( search, sizeof(search), "%s", basedir );
- }
-
- if ((fdir = opendir(search)) == NULL) {
- return;
- }
-
- while ((d = readdir(fdir)) != NULL) {
- Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
- if (stat(filename, &st) == -1)
- continue;
-
- if (st.st_mode & S_IFDIR) {
- if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) {
- if (strlen(subdirs)) {
- Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
- }
- else {
- Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
- }
- Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
- }
- }
- if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
- break;
- }
- Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name );
- if (!Com_FilterPath( filter, filename, qfalse ))
- continue;
- list[ *numfiles ] = CopyString( filename );
- (*numfiles)++;
- }
-
- closedir(fdir);
-}
-
-// bk001129 - in 1.17 this used to be
-// char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs )
-char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs )
-{
- struct dirent *d;
- // char *p; // bk001204 - unused
- DIR *fdir;
- qboolean dironly = wantsubs;
- char search[MAX_OSPATH];
- int nfiles;
- char **listCopy;
- char *list[MAX_FOUND_FILES];
- //int flag; // bk001204 - unused
- int i;
- struct stat st;
-
- int extLen;
-
- if (filter) {
-
- nfiles = 0;
- Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
-
- list[ nfiles ] = 0;
- *numfiles = nfiles;
-
- if (!nfiles)
- return NULL;
-
- listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
- for ( i = 0 ; i < nfiles ; i++ ) {
- listCopy[i] = list[i];
- }
- listCopy[i] = NULL;
-
- return listCopy;
- }
-
- if ( !extension)
- extension = "";
-
- if ( extension[0] == '/' && extension[1] == 0 ) {
- extension = "";
- dironly = qtrue;
- }
-
- extLen = strlen( extension );
-
- // search
- nfiles = 0;
-
- if ((fdir = opendir(directory)) == NULL) {
- *numfiles = 0;
- return NULL;
- }
-
- while ((d = readdir(fdir)) != NULL) {
- Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
- if (stat(search, &st) == -1)
- continue;
- if ((dironly && !(st.st_mode & S_IFDIR)) ||
- (!dironly && (st.st_mode & S_IFDIR)))
- continue;
-
- if (*extension) {
- if ( strlen( d->d_name ) < strlen( extension ) ||
- Q_stricmp(
- d->d_name + strlen( d->d_name ) - strlen( extension ),
- extension ) ) {
- continue; // didn't match
- }
- }
-
- if ( nfiles == MAX_FOUND_FILES - 1 )
- break;
- list[ nfiles ] = CopyString( d->d_name );
- nfiles++;
- }
-
- list[ nfiles ] = 0;
-
- closedir(fdir);
-
- // return a copy of the list
- *numfiles = nfiles;
-
- if ( !nfiles ) {
- return NULL;
- }
-
- listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
- for ( i = 0 ; i < nfiles ; i++ ) {
- listCopy[i] = list[i];
- }
- listCopy[i] = NULL;
-
- return listCopy;
-}
-
-void Sys_FreeFileList( char **list ) {
- int i;
-
- if ( !list ) {
- return;
- }
-
- for ( i = 0 ; list[i] ; i++ ) {
- Z_Free( list[i] );
- }
-
- Z_Free( list );
-}
-
-char *Sys_Cwd( void )
-{
- static char cwd[MAX_OSPATH];
-
- getcwd( cwd, sizeof( cwd ) - 1 );
- cwd[MAX_OSPATH-1] = 0;
-
- return cwd;
-}
-
-void Sys_SetDefaultCDPath(const char *path)
-{
- Q_strncpyz(cdPath, path, sizeof(cdPath));
-}
-
-char *Sys_DefaultCDPath(void)
-{
- return cdPath;
-}
-
-void Sys_SetDefaultInstallPath(const char *path)
-{
- Q_strncpyz(installPath, path, sizeof(installPath));
-}
-
-char *Sys_DefaultInstallPath(void)
-{
- if (*installPath)
- return installPath;
- else
- return Sys_Cwd();
-}
-
-void Sys_SetDefaultHomePath(const char *path)
-{
- Q_strncpyz(homePath, path, sizeof(homePath));
-}
-
-char *Sys_DefaultHomePath(void)
-{
- char *p;
-
- if (*homePath)
- return homePath;
-
- if ((p = getenv("HOME")) != NULL) {
- Q_strncpyz(homePath, p, sizeof(homePath));
-#ifdef MACOS_X
- Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/Quake3");
-#else
- Q_strcat(homePath, sizeof(homePath), "/.q3a");
-#endif
- if (mkdir(homePath, 0777)) {
- if (errno != EEXIST)
- Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", homePath, strerror(errno), errno);
- }
- return homePath;
- }
- return ""; // assume current dir
-}
-
-//============================================
-
-int Sys_GetProcessorId( void )
-{
- return CPUID_GENERIC;
-}
-
-void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
-{
-}
-
-char *Sys_GetCurrentUser( void )
-{
- struct passwd *p;
-
- if ( (p = getpwuid( getuid() )) == NULL ) {
- return "player";
- }
- return p->pw_name;
-}
-
-#if defined(__linux__)
-// TTimo
-// sysconf() in libc, POSIX.1 compliant
-unsigned int Sys_ProcessorCount()
-{
- return sysconf(_SC_NPROCESSORS_ONLN);
-}
-#endif
+/*
+===========================================================================
+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 Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <pwd.h>
+
+#include "../game/q_shared.h"
+#include "../qcommon/qcommon.h"
+
+//=============================================================================
+
+// Used to determine CD Path
+static char cdPath[MAX_OSPATH];
+
+// Used to determine local installation path
+static char installPath[MAX_OSPATH];
+
+// Used to determine where to store user-specific files
+static char homePath[MAX_OSPATH];
+
+/*
+================
+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 */
+unsigned long sys_timeBase = 0;
+/* current time in ms, using sys_timeBase as origin
+ NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch
+ 0x7fffffff ms - ~24 days
+ although timeval:tv_usec is an int, I'm not sure wether it is actually used as an unsigned int
+ (which would affect the wrap period) */
+int curtime;
+int Sys_Milliseconds (void)
+{
+ struct timeval tp;
+
+ gettimeofday(&tp, NULL);
+
+ if (!sys_timeBase)
+ {
+ sys_timeBase = tp.tv_sec;
+ return tp.tv_usec/1000;
+ }
+
+ curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
+
+ return curtime;
+}
+
+#if defined(__linux__) && !defined(DEDICATED)
+/*
+================
+Sys_XTimeToSysTime
+sub-frame timing of events returned by X
+X uses the Time typedef - unsigned long
+disable with in_subframe 0
+
+ sys_timeBase*1000 is the number of ms since the Epoch of our origin
+ xtime is in ms and uses the Epoch as origin
+ Time data type is an unsigned long: 0xffffffff ms - ~49 days period
+ I didn't find much info in the XWindow documentation about the wrapping
+ we clamp sys_timeBase*1000 to unsigned long, that gives us the current origin for xtime
+ the computation will still work if xtime wraps (at ~49 days period since the Epoch) after we set sys_timeBase
+
+================
+*/
+extern cvar_t *in_subframe;
+int Sys_XTimeToSysTime (unsigned long xtime)
+{
+ int ret, time, test;
+
+ if (!in_subframe->value)
+ {
+ // if you don't want to do any event times corrections
+ return Sys_Milliseconds();
+ }
+
+ // test the wrap issue
+#if 0
+ // reference values for test: sys_timeBase 0x3dc7b5e9 xtime 0x541ea451 (read these from a test run)
+ // xtime will wrap in 0xabe15bae ms >~ 0x2c0056 s (33 days from Nov 5 2002 -> 8 Dec)
+ // NOTE: date -d '1970-01-01 UTC 1039384002 seconds' +%c
+ // use sys_timeBase 0x3dc7b5e9+0x2c0056 = 0x3df3b63f
+ // after around 5s, xtime would have wrapped around
+ // we get 7132, the formula handles the wrap safely
+ unsigned long xtime_aux,base_aux;
+ int test;
+// Com_Printf("sys_timeBase: %p\n", sys_timeBase);
+// Com_Printf("xtime: %p\n", xtime);
+ xtime_aux = 500; // 500 ms after wrap
+ base_aux = 0x3df3b63f; // the base a few seconds before wrap
+ test = xtime_aux - (unsigned long)(base_aux*1000);
+ Com_Printf("xtime wrap test: %d\n", test);
+#endif
+
+ // some X servers (like suse 8.1's) report weird event times
+ // if the game is loading, resolving DNS, etc. we are also getting old events
+ // so we only deal with subframe corrections that look 'normal'
+ ret = xtime - (unsigned long)(sys_timeBase*1000);
+ time = Sys_Milliseconds();
+ test = time - ret;
+ //printf("delta: %d\n", test);
+ if (test < 0 || test > 30) // in normal conditions I've never seen this go above
+ {
+ return time;
+ }
+
+ return ret;
+}
+#endif
+
+//#if 0 // bk001215 - see snapvector.nasm for replacement
+#if (defined __APPLE__) // rcg010206 - using this for PPC builds...
+long fastftol( float f ) { // bk001213 - from win32/win_shared.c
+ //static int tmp;
+ // __asm fld f
+ //__asm fistp tmp
+ //__asm mov eax, tmp
+ return (long)f;
+}
+
+void Sys_SnapVector( float *v ) { // bk001213 - see win32/win_shared.c
+ // bk001213 - old linux
+ v[0] = rint(v[0]);
+ v[1] = rint(v[1]);
+ v[2] = rint(v[2]);
+}
+#endif
+
+
+void Sys_Mkdir( const char *path )
+{
+ mkdir (path, 0777);
+}
+
+char *strlwr (char *s) {
+ if ( s==NULL ) { // bk001204 - paranoia
+ assert(0);
+ return s;
+ }
+ while (*s) {
+ *s = tolower(*s);
+ s++;
+ }
+ return s; // bk001204 - duh
+}
+
+//============================================
+
+#define MAX_FOUND_FILES 0x1000
+
+// bk001129 - new in 1.26
+void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) {
+ char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
+ char filename[MAX_OSPATH];
+ DIR *fdir;
+ struct dirent *d;
+ struct stat st;
+
+ if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
+ return;
+ }
+
+ if (strlen(subdirs)) {
+ Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs );
+ }
+ else {
+ Com_sprintf( search, sizeof(search), "%s", basedir );
+ }
+
+ if ((fdir = opendir(search)) == NULL) {
+ return;
+ }
+
+ while ((d = readdir(fdir)) != NULL) {
+ Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
+ if (stat(filename, &st) == -1)
+ continue;
+
+ if (st.st_mode & S_IFDIR) {
+ if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) {
+ if (strlen(subdirs)) {
+ Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
+ }
+ else {
+ Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
+ }
+ Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
+ }
+ }
+ if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
+ break;
+ }
+ Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name );
+ if (!Com_FilterPath( filter, filename, qfalse ))
+ continue;
+ list[ *numfiles ] = CopyString( filename );
+ (*numfiles)++;
+ }
+
+ closedir(fdir);
+}
+
+// bk001129 - in 1.17 this used to be
+// char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs )
+char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs )
+{
+ struct dirent *d;
+ // char *p; // bk001204 - unused
+ DIR *fdir;
+ qboolean dironly = wantsubs;
+ char search[MAX_OSPATH];
+ int nfiles;
+ char **listCopy;
+ char *list[MAX_FOUND_FILES];
+ //int flag; // bk001204 - unused
+ int i;
+ struct stat st;
+
+ int extLen;
+
+ if (filter) {
+
+ nfiles = 0;
+ Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
+
+ list[ nfiles ] = 0;
+ *numfiles = nfiles;
+
+ if (!nfiles)
+ return NULL;
+
+ listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
+ for ( i = 0 ; i < nfiles ; i++ ) {
+ listCopy[i] = list[i];
+ }
+ listCopy[i] = NULL;
+
+ return listCopy;
+ }
+
+ if ( !extension)
+ extension = "";
+
+ if ( extension[0] == '/' && extension[1] == 0 ) {
+ extension = "";
+ dironly = qtrue;
+ }
+
+ extLen = strlen( extension );
+
+ // search
+ nfiles = 0;
+
+ if ((fdir = opendir(directory)) == NULL) {
+ *numfiles = 0;
+ return NULL;
+ }
+
+ while ((d = readdir(fdir)) != NULL) {
+ Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
+ if (stat(search, &st) == -1)
+ continue;
+ if ((dironly && !(st.st_mode & S_IFDIR)) ||
+ (!dironly && (st.st_mode & S_IFDIR)))
+ continue;
+
+ if (*extension) {
+ if ( strlen( d->d_name ) < strlen( extension ) ||
+ Q_stricmp(
+ d->d_name + strlen( d->d_name ) - strlen( extension ),
+ extension ) ) {
+ continue; // didn't match
+ }
+ }
+
+ if ( nfiles == MAX_FOUND_FILES - 1 )
+ break;
+ list[ nfiles ] = CopyString( d->d_name );
+ nfiles++;
+ }
+
+ list[ nfiles ] = 0;
+
+ closedir(fdir);
+
+ // return a copy of the list
+ *numfiles = nfiles;
+
+ if ( !nfiles ) {
+ return NULL;
+ }
+
+ listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
+ for ( i = 0 ; i < nfiles ; i++ ) {
+ listCopy[i] = list[i];
+ }
+ listCopy[i] = NULL;
+
+ return listCopy;
+}
+
+void Sys_FreeFileList( char **list ) {
+ int i;
+
+ if ( !list ) {
+ return;
+ }
+
+ for ( i = 0 ; list[i] ; i++ ) {
+ Z_Free( list[i] );
+ }
+
+ Z_Free( list );
+}
+
+char *Sys_Cwd( void )
+{
+ static char cwd[MAX_OSPATH];
+
+ getcwd( cwd, sizeof( cwd ) - 1 );
+ cwd[MAX_OSPATH-1] = 0;
+
+ return cwd;
+}
+
+void Sys_SetDefaultCDPath(const char *path)
+{
+ Q_strncpyz(cdPath, path, sizeof(cdPath));
+}
+
+char *Sys_DefaultCDPath(void)
+{
+ return cdPath;
+}
+
+void Sys_SetDefaultInstallPath(const char *path)
+{
+ Q_strncpyz(installPath, path, sizeof(installPath));
+}
+
+char *Sys_DefaultInstallPath(void)
+{
+ if (*installPath)
+ return installPath;
+ else
+ return Sys_Cwd();
+}
+
+void Sys_SetDefaultHomePath(const char *path)
+{
+ Q_strncpyz(homePath, path, sizeof(homePath));
+}
+
+char *Sys_DefaultHomePath(void)
+{
+ char *p;
+
+ if (*homePath)
+ return homePath;
+
+ if ((p = getenv("HOME")) != NULL) {
+ Q_strncpyz(homePath, p, sizeof(homePath));
+#ifdef MACOS_X
+ Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/Quake3");
+#else
+ Q_strcat(homePath, sizeof(homePath), "/.q3a");
+#endif
+ if (mkdir(homePath, 0777)) {
+ if (errno != EEXIST)
+ Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", homePath, strerror(errno), errno);
+ }
+ return homePath;
+ }
+ return ""; // assume current dir
+}
+
+//============================================
+
+int Sys_GetProcessorId( void )
+{
+ return CPUID_GENERIC;
+}
+
+void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
+{
+}
+
+char *Sys_GetCurrentUser( void )
+{
+ struct passwd *p;
+
+ if ( (p = getpwuid( getuid() )) == NULL ) {
+ return "player";
+ }
+ return p->pw_name;
+}
+
+#if defined(__linux__)
+// TTimo
+// sysconf() in libc, POSIX.1 compliant
+unsigned int Sys_ProcessorCount()
+{
+ return sysconf(_SC_NPROCESSORS_ONLN);
+}
+#endif