2004-09-07 18:18:02 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program 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 .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2005-11-03 23:49:00 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
2004-09-07 18:18:02 +00:00
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
//well, linux or cygwin (windows with posix emulation layer), anyway...
2013-05-13 13:43:18 +00:00
# define _GNU_SOURCE
2004-09-07 18:18:02 +00:00
# include <unistd.h>
# include <signal.h>
# include <stdlib.h>
# include <limits.h>
2011-07-06 01:01:13 +00:00
# include <time.h>
2004-09-07 18:18:02 +00:00
# include <sys/time.h>
# include <sys/types.h>
# include <unistd.h>
# include <fcntl.h>
# include <stdarg.h>
# include <stdio.h>
2006-05-02 00:56:30 +00:00
# include <dlfcn.h>
2010-01-11 18:15:42 +00:00
# include <dirent.h>
2005-11-03 23:49:00 +00:00
# ifndef __CYGWIN__
2004-09-07 18:18:02 +00:00
# include <sys/ipc.h>
# include <sys/shm.h>
# endif
# include <sys/stat.h>
# include <string.h>
# include <ctype.h>
# include <sys/wait.h>
# include <sys/mman.h>
# include <errno.h>
2007-10-19 18:31:23 +00:00
# ifndef __MACOSX__
2006-04-15 03:44:10 +00:00
# include <X11/Xlib.h>
2007-10-19 18:31:23 +00:00
# endif
2007-12-30 00:09:34 +00:00
# ifdef MULTITHREAD
# include <pthread.h>
# endif
2004-09-07 18:18:02 +00:00
2013-11-21 23:06:58 +00:00
# ifdef __CYGWIN__
2013-11-21 23:02:28 +00:00
# define USE_LIBTOOL
2013-11-21 23:06:58 +00:00
# endif
2013-11-21 23:02:28 +00:00
# ifdef USE_LIBTOOL
# include <ltdl.h>
# endif
2004-09-07 18:18:02 +00:00
# include "quakedef.h"
# undef malloc
int noconinput = 0 ;
int nostdout = 0 ;
2013-03-12 23:03:46 +00:00
qboolean isPlugin ;
int sys_parentleft ;
int sys_parenttop ;
int sys_parentwidth ;
int sys_parentheight ;
long sys_parentwindow ;
2013-05-11 05:03:07 +00:00
qboolean X11_GetDesktopParameters ( int * width , int * height , int * bpp , int * refreshrate ) ;
2013-03-12 23:03:46 +00:00
2013-11-21 23:02:28 +00:00
char * basedir = " ./ " ;
2004-09-07 18:18:02 +00:00
qboolean Sys_InitTerminal ( void ) //we either have one or we don't.
{
return true ;
}
void Sys_CloseTerminal ( void )
{
}
2010-12-05 02:52:41 +00:00
void Sys_RecentServer ( char * command , char * target , char * title , char * desc )
{
}
2004-09-07 18:18:02 +00:00
2005-08-19 14:05:33 +00:00
# ifndef CLIENTONLY
2004-09-07 18:18:02 +00:00
qboolean isDedicated ;
2005-08-19 14:05:33 +00:00
# endif
2004-09-07 18:18:02 +00:00
// =======================================================================
// General routines
// =======================================================================
2011-01-29 19:53:38 +00:00
# if 1
static int ansiremap [ 8 ] = { 0 , 4 , 2 , 6 , 1 , 5 , 3 , 7 } ;
static void ApplyColour ( unsigned int chr )
{
static int oldchar = CON_WHITEMASK ;
int bg , fg ;
chr & = CON_FLAGSMASK ;
if ( oldchar = = chr )
return ;
oldchar = chr ;
printf ( " \ e[0; " ) ; // reset
if ( chr & CON_BLINKTEXT )
printf ( " 5; " ) ; // set blink
bg = ( chr & CON_BGMASK ) > > CON_BGSHIFT ;
fg = ( chr & CON_FGMASK ) > > CON_FGSHIFT ;
// don't handle intensive bit for background
// as terminals differ too much in displaying \e[1;7;3?m
bg & = 0x7 ;
if ( chr & CON_NONCLEARBG )
{
if ( fg & 0x8 ) // intensive bit set for foreground
{
printf ( " 1; " ) ; // set bold/intensity ansi flag
fg & = 0x7 ; // strip intensive bit
}
// set foreground and background colors
printf ( " 3%i;4%im " , ansiremap [ fg ] , ansiremap [ bg ] ) ;
}
else
{
switch ( fg )
{
//to get around wierd defaults (like a white background) we have these special hacks for colours 0 and 7
case COLOR_BLACK :
printf ( " 7m " ) ; // set inverse
break ;
case COLOR_GREY :
printf ( " 1;30m " ) ; // treat as dark grey
break ;
case COLOR_WHITE :
printf ( " m " ) ; // set nothing else
break ;
default :
if ( fg & 0x8 ) // intensive bit set for foreground
{
printf ( " 1; " ) ; // set bold/intensity ansi flag
fg & = 0x7 ; // strip intensive bit
}
printf ( " 3%im " , ansiremap [ fg ] ) ; // set foreground
break ;
}
}
}
# include <wchar.h>
void Sys_Printf ( char * fmt , . . . )
{
va_list argptr ;
char text [ 2048 ] ;
conchar_t ctext [ 2048 ] ;
conchar_t * c , * e ;
wchar_t w ;
if ( nostdout )
return ;
va_start ( argptr , fmt ) ;
2012-07-14 16:36:19 +00:00
vsnprintf ( text , sizeof ( text ) - 1 , fmt , argptr ) ;
2011-01-29 19:53:38 +00:00
va_end ( argptr ) ;
if ( strlen ( text ) > sizeof ( text ) )
Sys_Error ( " memory overwrite in Sys_Printf " ) ;
e = COM_ParseFunString ( CON_WHITEMASK , text , ctext , sizeof ( ctext ) , false ) ;
for ( c = ctext ; c < e ; c + + )
{
2012-10-14 10:53:50 +00:00
if ( * c & CON_HIDDEN )
continue ;
2011-01-29 19:53:38 +00:00
ApplyColour ( * c ) ;
w = * c & 0x0ffff ;
if ( w > = 0xe000 & & w < 0xe100 )
{
2012-10-14 10:53:50 +00:00
/*not all quake chars are ascii compatible, so map those control chars to safe ones so we don't mess up anyone's xterm*/
if ( ( w & 0x7f ) > 0x20 )
putc ( w & 0x7f , stdout ) ;
else if ( w & 0x80 )
{
static char tab [ 32 ] = " ---#@.@@@@ # >.. " " []0123456789.--- " ;
putc ( tab [ w & 31 ] , stdout ) ;
}
else
{
static char tab [ 32 ] = " .####.#### # >.. " " []0123456789.--- " ;
putc ( tab [ w & 31 ] , stdout ) ;
}
2011-01-29 19:53:38 +00:00
}
else
{
/*putwc doesn't like me. force it in utf8*/
if ( w > = 0x80 )
{
if ( w > 0x800 )
{
putc ( 0xe0 | ( ( w > > 12 ) & 0x0f ) , stdout ) ;
putc ( 0x80 | ( ( w > > 6 ) & 0x3f ) , stdout ) ;
}
else
putc ( 0xc0 | ( ( w > > 6 ) & 0x1f ) , stdout ) ;
putc ( 0x80 | ( w & 0x3f ) , stdout ) ;
}
else
putc ( w , stdout ) ;
}
}
ApplyColour ( CON_WHITEMASK ) ;
}
# else
2004-09-07 18:18:02 +00:00
void Sys_Printf ( char * fmt , . . . )
{
va_list argptr ;
char text [ 2048 ] ;
unsigned char * p ;
va_start ( argptr , fmt ) ;
2012-07-14 16:36:19 +00:00
vsnprintf ( text , sizeof ( text ) - 1 , fmt , argptr ) ;
2004-09-07 18:18:02 +00:00
va_end ( argptr ) ;
if ( strlen ( text ) > sizeof ( text ) )
Sys_Error ( " memory overwrite in Sys_Printf " ) ;
2005-08-01 15:08:05 +00:00
if ( nostdout )
return ;
2004-09-07 18:18:02 +00:00
for ( p = ( unsigned char * ) text ; * p ; p + + )
if ( ( * p > 128 | | * p < 32 ) & & * p ! = 10 & & * p ! = 13 & & * p ! = 9 )
printf ( " [%02x] " , * p ) ;
else
putc ( * p , stdout ) ;
}
2011-01-29 19:53:38 +00:00
# endif
2004-09-07 18:18:02 +00:00
void Sys_Quit ( void )
{
Host_Shutdown ( ) ;
2005-08-01 15:08:05 +00:00
fcntl ( 0 , F_SETFL , fcntl ( 0 , F_GETFL , 0 ) & ~ FNDELAY ) ;
2013-11-21 23:02:28 +00:00
# ifdef USE_LIBTOOL
lt_dlexit ( ) ;
# endif
2004-09-07 18:18:02 +00:00
exit ( 0 ) ;
}
void Sys_Init ( void )
{
}
2011-04-30 17:21:10 +00:00
void Sys_Shutdown ( void )
{
}
2004-09-07 18:18:02 +00:00
void Sys_Error ( const char * error , . . . )
2005-11-03 23:49:00 +00:00
{
2005-08-01 15:08:05 +00:00
va_list argptr ;
char string [ 1024 ] ;
2004-09-07 18:18:02 +00:00
// change stdin to non blocking
2005-08-01 15:08:05 +00:00
fcntl ( 0 , F_SETFL , fcntl ( 0 , F_GETFL , 0 ) & ~ FNDELAY ) ;
2005-11-03 23:49:00 +00:00
2005-08-01 15:08:05 +00:00
va_start ( argptr , error ) ;
2012-07-14 16:36:19 +00:00
vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
2005-08-01 15:08:05 +00:00
va_end ( argptr ) ;
2004-09-07 18:18:02 +00:00
fprintf ( stderr , " Error: %s \n " , string ) ;
Host_Shutdown ( ) ;
2013-11-21 23:02:28 +00:00
# ifdef USE_LIBTOOL
lt_dlexit ( ) ;
# endif
2004-09-07 18:18:02 +00:00
exit ( 1 ) ;
2005-11-03 23:49:00 +00:00
}
2004-09-07 18:18:02 +00:00
void Sys_Warn ( char * warning , . . . )
2005-11-03 23:49:00 +00:00
{
2005-08-01 15:08:05 +00:00
va_list argptr ;
char string [ 1024 ] ;
2005-11-03 23:49:00 +00:00
2005-08-01 15:08:05 +00:00
va_start ( argptr , warning ) ;
2012-07-14 16:36:19 +00:00
vsnprintf ( string , sizeof ( string ) - 1 , warning , argptr ) ;
2005-08-01 15:08:05 +00:00
va_end ( argptr ) ;
2004-09-07 18:18:02 +00:00
fprintf ( stderr , " Warning: %s " , string ) ;
2005-11-03 23:49:00 +00:00
}
2004-09-07 18:18:02 +00:00
/*
= = = = = = = = = = = =
Sys_FileTime
returns - 1 if not present
= = = = = = = = = = = =
*/
int Sys_FileTime ( char * path )
{
struct stat buf ;
2005-11-03 23:49:00 +00:00
2004-09-07 18:18:02 +00:00
if ( stat ( path , & buf ) = = - 1 )
return - 1 ;
2005-11-03 23:49:00 +00:00
2004-09-07 18:18:02 +00:00
return buf . st_mtime ;
}
void Sys_mkdir ( char * path )
{
2005-08-01 15:08:05 +00:00
mkdir ( path , 0777 ) ;
2004-09-07 18:18:02 +00:00
}
2005-08-01 15:08:05 +00:00
2004-09-07 18:18:02 +00:00
qboolean Sys_remove ( char * path )
{
return system ( va ( " rm \" %s \" " , path ) ) ;
}
2012-04-24 07:59:11 +00:00
qboolean Sys_Rename ( char * oldfname , char * newfname )
{
return ! rename ( oldfname , newfname ) ;
}
2004-09-07 18:18:02 +00:00
int Sys_FileOpenRead ( char * path , int * handle )
{
2005-08-01 15:08:05 +00:00
int h ;
struct stat fileinfo ;
2005-11-03 23:49:00 +00:00
2004-09-07 18:18:02 +00:00
h = open ( path , O_RDONLY , 0666 ) ;
* handle = h ;
if ( h = = - 1 )
return - 1 ;
2005-11-03 23:49:00 +00:00
2004-09-07 18:18:02 +00:00
if ( fstat ( h , & fileinfo ) = = - 1 )
Sys_Error ( " Error fstating %s " , path ) ;
return fileinfo . st_size ;
}
int Sys_FileOpenWrite ( char * path )
{
2005-08-01 15:08:05 +00:00
int handle ;
2004-09-07 18:18:02 +00:00
umask ( 0 ) ;
2005-11-03 23:49:00 +00:00
2005-08-01 15:08:05 +00:00
handle = open ( path , O_RDWR | O_CREAT | O_TRUNC , 0666 ) ;
2004-09-07 18:18:02 +00:00
if ( handle = = - 1 )
Sys_Error ( " Error opening %s: %s " , path , strerror ( errno ) ) ;
return handle ;
}
int Sys_FileWrite ( int handle , void * src , int count )
{
return write ( handle , src , count ) ;
}
void Sys_FileClose ( int handle )
{
close ( handle ) ;
}
void Sys_FileSeek ( int handle , int position )
{
lseek ( handle , position , SEEK_SET ) ;
}
int Sys_FileRead ( int handle , void * dest , int count )
{
2005-08-01 15:08:05 +00:00
return read ( handle , dest , count ) ;
2004-09-07 18:18:02 +00:00
}
2005-12-05 16:47:29 +00:00
int Sys_DebugLog ( char * file , char * fmt , . . . )
2004-09-07 18:18:02 +00:00
{
2005-11-03 23:49:00 +00:00
va_list argptr ;
2005-08-01 15:08:05 +00:00
static char data [ 1024 ] ;
int fd ;
2011-05-15 13:23:13 +00:00
size_t result ;
2005-11-03 23:49:00 +00:00
2005-08-01 15:08:05 +00:00
va_start ( argptr , fmt ) ;
2012-07-14 16:36:19 +00:00
vsnprintf ( data , sizeof ( data ) - 1 , fmt , argptr ) ;
2005-08-01 15:08:05 +00:00
va_end ( argptr ) ;
2004-09-07 18:18:02 +00:00
2005-08-01 15:08:05 +00:00
if ( strlen ( data ) > sizeof ( data ) )
Sys_Error ( " Sys_DebugLog's buffer was stomped \n " ) ;
2004-09-07 18:18:02 +00:00
2005-08-01 15:08:05 +00:00
// fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666);
fd = open ( file , O_WRONLY | O_CREAT | O_APPEND , 0666 ) ;
2005-12-05 16:47:29 +00:00
if ( fd )
{
2011-05-15 13:23:13 +00:00
result = write ( fd , data , strlen ( data ) ) ; // do something with result
2011-05-30 04:32:04 +00:00
if ( result ! = strlen ( data ) )
2011-06-01 13:21:54 +00:00
Con_SafePrintf ( " Sys_DebugLog() write: Filename: %s, expected %lu, result was %lu (%s) \n " , file , ( unsigned long ) strlen ( data ) , ( unsigned long ) result , strerror ( errno ) ) ;
2011-05-30 04:32:04 +00:00
2005-12-05 16:47:29 +00:00
close ( fd ) ;
return 0 ;
}
return 1 ;
2004-09-07 18:18:02 +00:00
}
2014-02-07 08:38:40 +00:00
int Sys_EnumerateFiles ( const char * gpath , const char * match , int ( * func ) ( const char * , qofs_t , void * , searchpathfuncs_t * ) , void * parm , searchpathfuncs_t * spath )
2004-09-07 18:18:02 +00:00
{
2010-01-11 18:15:42 +00:00
DIR * dir ;
2004-09-07 18:18:02 +00:00
char apath [ MAX_OSPATH ] ;
char file [ MAX_OSPATH ] ;
char truepath [ MAX_OSPATH ] ;
char * s ;
struct dirent * ent ;
2010-01-11 18:15:42 +00:00
struct stat st ;
2004-09-07 18:18:02 +00:00
//printf("path = %s\n", gpath);
//printf("match = %s\n", match);
if ( ! gpath )
gpath = " " ;
* apath = ' \0 ' ;
Q_strncpyz ( apath , match , sizeof ( apath ) ) ;
for ( s = apath + strlen ( apath ) - 1 ; s > = apath ; s - - )
{
if ( * s = = ' / ' )
{
s [ 1 ] = ' \0 ' ;
match + = s - apath + 1 ;
break ;
}
}
if ( s < apath ) //didn't find a '/'
* apath = ' \0 ' ;
2006-05-19 19:15:52 +00:00
Q_snprintfz ( truepath , sizeof ( truepath ) , " %s/%s " , gpath , apath ) ;
2004-09-07 18:18:02 +00:00
//printf("truepath = %s\n", truepath);
//printf("gamepath = %s\n", gpath);
//printf("apppath = %s\n", apath);
//printf("match = %s\n", match);
dir = opendir ( truepath ) ;
if ( ! dir )
{
2005-11-03 23:49:00 +00:00
Con_DPrintf ( " Failed to open dir %s \n " , truepath ) ;
2004-09-07 18:18:02 +00:00
return true ;
}
do
{
ent = readdir ( dir ) ;
if ( ! ent )
break ;
if ( * ent - > d_name ! = ' . ' )
2010-01-11 18:15:42 +00:00
{
2004-09-07 18:18:02 +00:00
if ( wildcmp ( match , ent - > d_name ) )
{
2010-01-11 18:15:42 +00:00
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , truepath , ent - > d_name ) ;
2004-09-07 18:18:02 +00:00
2010-01-11 18:15:42 +00:00
if ( stat ( file , & st ) = = 0 )
2004-09-07 18:18:02 +00:00
{
2010-01-11 18:15:42 +00:00
Q_snprintfz ( file , sizeof ( file ) , " %s%s%s " , apath , ent - > d_name , S_ISDIR ( st . st_mode ) ? " / " : " " ) ;
2004-09-07 18:18:02 +00:00
2013-03-31 05:00:53 +00:00
if ( ! func ( file , st . st_size , parm , spath ) )
2010-01-11 18:15:42 +00:00
{
2013-11-21 23:02:28 +00:00
Con_DPrintf ( " giving up on search after finding %s \n " , file ) ;
2010-01-11 18:15:42 +00:00
closedir ( dir ) ;
return false ;
}
2004-09-07 18:18:02 +00:00
}
2010-01-11 18:15:42 +00:00
else
printf ( " Stat failed for \" %s \" \n " , file ) ;
2004-09-07 18:18:02 +00:00
}
2010-01-11 18:15:42 +00:00
}
2004-09-07 18:18:02 +00:00
} while ( 1 ) ;
closedir ( dir ) ;
return true ;
}
2005-11-26 03:02:55 +00:00
int secbase ;
2004-09-07 18:18:02 +00:00
double Sys_DoubleTime ( void )
{
2005-08-01 15:08:05 +00:00
struct timeval tp ;
2005-11-03 23:49:00 +00:00
struct timezone tzp ;
gettimeofday ( & tp , & tzp ) ;
2004-09-07 18:18:02 +00:00
2005-08-01 15:08:05 +00:00
if ( ! secbase )
{
secbase = tp . tv_sec ;
return tp . tv_usec / 1000000.0 ;
}
2004-09-07 18:18:02 +00:00
2005-08-01 15:08:05 +00:00
return ( tp . tv_sec - secbase ) + tp . tv_usec / 1000000.0 ;
2004-09-07 18:18:02 +00:00
}
2010-07-12 22:46:37 +00:00
unsigned int Sys_Milliseconds ( void )
{
return Sys_DoubleTime ( ) * 1000 ;
}
2013-11-21 23:02:28 +00:00
# ifdef USE_LIBTOOL
void Sys_CloseLibrary ( dllhandle_t * lib )
{
lt_dlclose ( ( void * ) lib ) ;
}
dllhandle_t * Sys_LoadLibrary ( const char * name , dllfunction_t * funcs )
{
int i ;
dllhandle_t lib ;
lib = NULL ;
if ( ! lib )
lib = lt_dlopenext ( name ) ;
if ( ! lib )
{
Con_DPrintf ( " %s: %s \n " , name , lt_dlerror ( ) ) ;
return NULL ;
}
if ( funcs )
{
for ( i = 0 ; funcs [ i ] . name ; i + + )
{
* funcs [ i ] . funcptr = lt_dlsym ( lib , funcs [ i ] . name ) ;
if ( ! * funcs [ i ] . funcptr )
break ;
}
if ( funcs [ i ] . name )
{
Con_DPrintf ( " Unable to find symbol \" %s \" in \" %s \" \n " , funcs [ i ] . name , name ) ;
Sys_CloseLibrary ( ( dllhandle_t * ) lib ) ;
lib = NULL ;
}
}
return ( dllhandle_t * ) lib ;
}
void * Sys_GetAddressForName ( dllhandle_t * module , const char * exportname )
{
if ( ! module )
return NULL ;
return lt_dlsym ( module , exportname ) ;
}
# else
2008-11-09 22:29:28 +00:00
void Sys_CloseLibrary ( dllhandle_t * lib )
{
2008-11-11 12:20:46 +00:00
dlclose ( ( void * ) lib ) ;
2008-11-09 22:29:28 +00:00
}
2011-01-27 01:34:08 +00:00
2009-11-05 03:07:52 +00:00
dllhandle_t * Sys_LoadLibrary ( const char * name , dllfunction_t * funcs )
2008-11-09 22:29:28 +00:00
{
int i ;
2008-11-11 10:09:41 +00:00
dllhandle_t lib ;
2008-11-09 22:29:28 +00:00
2011-01-29 19:53:38 +00:00
lib = NULL ;
if ( ! lib )
lib = dlopen ( name , RTLD_LAZY ) ;
2014-02-07 08:38:40 +00:00
if ( ! lib & & ! strstr ( name , " .so " ) )
2011-01-29 19:53:38 +00:00
lib = dlopen ( va ( " %s.so " , name ) , RTLD_LAZY ) ;
2008-11-09 22:29:28 +00:00
if ( ! lib )
2012-10-08 01:30:41 +00:00
{
2012-10-08 05:10:14 +00:00
Con_DPrintf ( " %s \n " , dlerror ( ) ) ;
2008-11-09 22:29:28 +00:00
return NULL ;
2012-10-08 01:30:41 +00:00
}
2008-11-09 22:29:28 +00:00
2011-05-30 21:48:32 +00:00
if ( funcs )
2008-11-09 22:29:28 +00:00
{
2011-05-30 21:48:32 +00:00
for ( i = 0 ; funcs [ i ] . name ; i + + )
{
* funcs [ i ] . funcptr = dlsym ( lib , funcs [ i ] . name ) ;
if ( ! * funcs [ i ] . funcptr )
break ;
}
if ( funcs [ i ] . name )
{
2012-10-08 01:30:41 +00:00
Con_DPrintf ( " Unable to find symbol \" %s \" in \" %s \" \n " , funcs [ i ] . name , name ) ;
2011-05-30 21:48:32 +00:00
Sys_CloseLibrary ( ( dllhandle_t * ) lib ) ;
lib = NULL ;
}
2008-11-09 22:29:28 +00:00
}
return ( dllhandle_t * ) lib ;
}
2011-05-30 21:48:32 +00:00
void * Sys_GetAddressForName ( dllhandle_t * module , const char * exportname )
{
if ( ! module )
return NULL ;
return dlsym ( module , exportname ) ;
}
2013-11-21 23:02:28 +00:00
# endif
2011-05-30 21:48:32 +00:00
2013-05-13 13:43:18 +00:00
// =======================================================================
//friendly way to crash, including stack traces. should help reduce gdb use.
# ifdef __linux__ /*should probably be GNUC but whatever*/
# include <execinfo.h>
# ifdef __i386__
# include <ucontext.h>
# endif
# ifdef DEBUG
void DumpGLState ( void ) ;
# endif
static void Friendly_Crash_Handler ( int sig , siginfo_t * info , void * vcontext )
{
int fd ;
void * array [ 64 ] ;
size_t size ;
int firstframe = 0 ;
char signame [ 32 ] ;
switch ( sig )
{
case SIGILL : strcpy ( signame , " SIGILL " ) ; break ;
case SIGFPE : strcpy ( signame , " SIGFPE " ) ; break ;
case SIGBUS : strcpy ( signame , " SIGBUS " ) ; break ;
case SIGSEGV : Q_snprintfz ( signame , sizeof ( signame ) , " SIGSEGV (%p) " , info - > si_addr ) ; break ;
default : Q_snprintfz ( signame , sizeof ( signame ) , " %i " , sig ) ; break ;
}
// get void*'s for all entries on the stack
size = backtrace ( array , sizeof ( array ) / sizeof ( array [ 0 ] ) ) ;
# if defined(__i386__)
//x86 signals don't leave the stack in a clean state, so replace the signal handler with the real crash address, and hide this function
ucontext_t * uc = vcontext ;
array [ 1 ] = ( void * ) uc - > uc_mcontext . gregs [ REG_EIP ] ;
firstframe = 1 ;
# elif defined(__amd64__)
//amd64 is sane enough, but this function and the libc signal handler are on the stack, and should be ignored.
firstframe = 2 ;
# endif
// print out all the frames to stderr
fprintf ( stderr , " Error: signal %s: \n " , signame ) ;
backtrace_symbols_fd ( array + firstframe , size - firstframe , 2 ) ;
fd = open ( " crash.log " , O_WRONLY | O_CREAT | O_APPEND , S_IRUSR | S_IWUSR | S_IRGRP ) ;
if ( fd ! = - 1 )
{
time_t rawtime ;
struct tm * timeinfo ;
char buffer [ 80 ] ;
time ( & rawtime ) ;
timeinfo = localtime ( & rawtime ) ;
strftime ( buffer , sizeof ( buffer ) , " Time: %Y-%m-%d %H:%M:%S \n " , timeinfo ) ;
write ( fd , buffer , strlen ( buffer ) ) ;
Q_snprintfz ( buffer , sizeof ( buffer ) , " Binary: " __DATE__ " " __TIME__ " \n " ) ;
write ( fd , buffer , strlen ( buffer ) ) ;
Q_snprintfz ( buffer , sizeof ( buffer ) , " Ver: %i.%02i%s \n " , FTE_VER_MAJOR , FTE_VER_MINOR ,
# ifdef OFFICIAL_RELEASE
" (official) " ) ;
# else
" " ) ;
# endif
write ( fd , buffer , strlen ( buffer ) ) ;
# ifdef SVNREVISION
if ( strcmp ( STRINGIFY ( SVNREVISION ) , " - " ) )
{
Q_snprintfz ( buffer , sizeof ( buffer ) , " Revision: %s \n " , STRINGIFY ( SVNREVISION ) ) ;
write ( fd , buffer , strlen ( buffer ) ) ;
}
# endif
backtrace_symbols_fd ( array + firstframe , size - firstframe , fd ) ;
write ( fd , " \n " , 1 ) ;
close ( fd ) ;
}
# ifdef DEBUG
DumpGLState ( ) ;
# endif
exit ( 1 ) ;
}
# endif
2004-09-07 18:18:02 +00:00
// =======================================================================
// Sleeps for microseconds
// =======================================================================
static volatile int oktogo ;
void alarm_handler ( int x )
{
oktogo = 1 ;
}
char * Sys_ConsoleInput ( void )
{
2013-03-12 22:47:42 +00:00
# if 1
2005-08-01 15:08:05 +00:00
static char text [ 256 ] ;
int len ;
2004-09-07 18:18:02 +00:00
2013-03-12 22:47:42 +00:00
// if (!qrenderer)
2005-08-01 15:08:05 +00:00
{
2004-09-07 18:18:02 +00:00
len = read ( 0 , text , sizeof ( text ) ) ;
if ( len < 1 )
return NULL ;
2005-08-01 15:08:05 +00:00
2004-09-07 18:18:02 +00:00
text [ len - 1 ] = 0 ; // rip off the /n and terminate
2013-03-12 23:03:46 +00:00
//Con_Printf("console input: %s\n", text);
if ( ! strncmp ( text , " vid_recenter " , 13 ) )
{
Cmd_TokenizeString ( text , false , false ) ;
sys_parentleft = strtoul ( Cmd_Argv ( 1 ) , NULL , 0 ) ;
sys_parenttop = strtoul ( Cmd_Argv ( 2 ) , NULL , 0 ) ;
sys_parentwidth = strtoul ( Cmd_Argv ( 3 ) , NULL , 0 ) ;
sys_parentheight = strtoul ( Cmd_Argv ( 4 ) , NULL , 0 ) ;
sys_parentwindow = strtoul ( Cmd_Argv ( 5 ) , NULL , 16 ) ;
}
2004-09-07 18:18:02 +00:00
return text ;
}
# endif
return NULL ;
}
2011-05-19 13:34:07 +00:00
int main ( int c , const char * * v )
2004-09-07 18:18:02 +00:00
{
2005-08-01 15:08:05 +00:00
double time , oldtime , newtime ;
2004-09-07 18:18:02 +00:00
quakeparms_t parms ;
int j ;
2013-11-21 23:02:28 +00:00
// char cwd[1024];
char bindir [ 1024 ] ;
2004-09-07 18:18:02 +00:00
signal ( SIGFPE , SIG_IGN ) ;
2006-03-17 22:44:17 +00:00
signal ( SIGPIPE , SIG_IGN ) ;
2004-09-07 18:18:02 +00:00
memset ( & parms , 0 , sizeof ( parms ) ) ;
2013-11-21 23:02:28 +00:00
# ifdef USE_LIBTOOL
lt_dlinit ( ) ;
# endif
2010-07-11 10:53:13 +00:00
parms . argc = c ;
parms . argv = v ;
COM_InitArgv ( parms . argc , parms . argv ) ;
2004-09-07 18:18:02 +00:00
TL_InitLanguages ( ) ;
2013-05-13 13:43:18 +00:00
# ifdef __linux__
if ( ! COM_CheckParm ( " -nodumpstack " ) )
{
struct sigaction act ;
memset ( & act , 0 , sizeof ( act ) ) ;
act . sa_sigaction = Friendly_Crash_Handler ;
act . sa_flags = SA_SIGINFO | SA_RESTART ;
sigaction ( SIGILL , & act , NULL ) ;
sigaction ( SIGSEGV , & act , NULL ) ;
sigaction ( SIGBUS , & act , NULL ) ;
}
# endif
2004-09-07 18:18:02 +00:00
parms . basedir = basedir ;
2014-01-16 07:03:40 +00:00
memset ( bindir , 0 , sizeof ( bindir ) ) ; //readlink does NOT null terminate, apparently.
2013-05-04 04:02:25 +00:00
# ifdef __linux__
//attempt to figure out where the exe is located
2014-01-16 07:03:40 +00:00
if ( readlink ( " /proc/self/exe " , bindir , sizeof ( bindir ) - 1 ) > 0 )
2013-05-04 04:02:25 +00:00
{
* COM_SkipPath ( bindir ) = 0 ;
printf ( " Binary is located at \" %s \" \n " , bindir ) ;
parms . binarydir = bindir ;
}
/*#elif defined(__bsd__)
//attempt to figure out where the exe is located
2014-01-16 07:03:40 +00:00
if ( readlink ( " /proc/self/file " , bindir , sizeof ( bindir ) - 1 ) > 0 )
2013-05-04 04:02:25 +00:00
{
* COM_SkipPath ( bindir ) = 0 ;
printf ( " Binary is located at " % s " \n " , bindir ) ;
parms . binarydir = bindir ;
}
*/
# endif
2004-09-07 18:18:02 +00:00
2013-03-12 23:03:46 +00:00
isPlugin = ! ! COM_CheckParm ( " -plugin " ) ;
if ( isPlugin )
{
printf ( " status Starting up! \n " ) ;
fflush ( stdout ) ;
nostdout = true ;
}
2004-09-07 18:18:02 +00:00
noconinput = COM_CheckParm ( " -noconinput " ) ;
if ( ! noconinput )
fcntl ( 0 , F_SETFL , fcntl ( 0 , F_GETFL , 0 ) | FNDELAY ) ;
if ( COM_CheckParm ( " -nostdout " ) )
nostdout = 1 ;
2005-08-01 15:08:05 +00:00
Host_Init ( & parms ) ;
2004-09-07 18:18:02 +00:00
2005-08-01 15:08:05 +00:00
oldtime = Sys_DoubleTime ( ) ;
while ( 1 )
{
2011-07-06 01:01:13 +00:00
double sleeptime ;
2007-09-23 22:00:19 +00:00
# ifdef __MACOSX__
//wow, not even windows was this absurd.
2013-04-09 00:19:13 +00:00
# ifdef GLQUAKE
2007-09-23 22:00:19 +00:00
if ( glcocoaRunLoop ( ) )
{
oldtime = Sys_DoubleTime ( ) ;
continue ;
}
# endif
# endif
2004-09-07 18:18:02 +00:00
// find time spent rendering last frame
2005-08-01 15:08:05 +00:00
newtime = Sys_DoubleTime ( ) ;
time = newtime - oldtime ;
2004-09-07 18:18:02 +00:00
2011-07-06 01:01:13 +00:00
sleeptime = Host_Frame ( time ) ;
2004-09-07 18:18:02 +00:00
oldtime = newtime ;
2011-07-06 01:01:13 +00:00
Sys_Sleep ( sleeptime ) ;
2005-08-01 15:08:05 +00:00
}
2004-09-07 18:18:02 +00:00
}
/*
= = = = = = = = = = = = = = = =
Sys_MakeCodeWriteable
= = = = = = = = = = = = = = = =
*/
2013-06-24 09:04:00 +00:00
#if 0
void Sys_MakeCodeWriteable ( void * startptr , unsigned long length )
2004-09-07 18:18:02 +00:00
{
int r ;
2013-06-24 09:04:00 +00:00
uintptr_t addr ;
2004-09-07 18:18:02 +00:00
int psize = getpagesize ( ) ;
2013-06-24 09:04:00 +00:00
addr = ( ( uintptr_t ) startptr & ~ ( psize - 1 ) ) - psize ;
2004-09-07 18:18:02 +00:00
// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
// addr, startaddr+length, length);
r = mprotect ( ( char * ) addr , length + startaddr - addr + psize , 7 ) ;
if ( r < 0 )
Sys_Error ( " Protection change failed \n " ) ;
}
2013-06-24 09:04:00 +00:00
# endif
2004-09-07 18:18:02 +00:00
2004-09-07 19:07:37 +00:00
//fixme: some sort of taskbar/gnome panel flashing.
void Sys_ServerActivity ( void )
{
}
2006-04-15 03:31:23 +00:00
//FIXME: this is hacky. Unlike other OSes where the GUI is part of the OS, X is seperate
//from the OS. This will cause problems with framebuffer-only setups.
qboolean Sys_GetDesktopParameters ( int * width , int * height , int * bpp , int * refreshrate )
{
2007-09-22 19:28:27 +00:00
# ifdef __MACOSX__
//this about sums up the problem with this function
return false ;
# else
2013-03-12 23:04:11 +00:00
return X11_GetDesktopParameters ( width , height , bpp , refreshrate ) ;
2007-09-22 19:28:27 +00:00
2006-04-15 03:31:23 +00:00
Display * xtemp ;
int scr ;
2011-05-15 13:23:13 +00:00
2006-04-15 03:31:23 +00:00
xtemp = XOpenDisplay ( NULL ) ;
if ( ! xtemp )
return false ;
scr = DefaultScreen ( xtemp ) ;
2006-02-01 22:36:12 +00:00
2006-04-15 03:31:23 +00:00
* width = DisplayWidth ( xtemp , scr ) ;
* height = DisplayHeight ( xtemp , scr ) ;
* bpp = DefaultDepth ( xtemp , scr ) ;
* refreshrate = 0 ;
2006-02-01 22:36:12 +00:00
2006-04-15 03:31:23 +00:00
XCloseDisplay ( xtemp ) ;
return true ;
2007-09-22 19:28:27 +00:00
# endif
2006-04-15 03:31:23 +00:00
}
2006-03-11 03:12:10 +00:00
2013-03-12 22:47:42 +00:00
# ifndef GLQUAKE
2006-03-11 03:12:10 +00:00
# define SYS_CLIPBOARD_SIZE 256
static char clipboard_buffer [ SYS_CLIPBOARD_SIZE ] = { 0 } ;
char * Sys_GetClipboard ( void ) {
return clipboard_buffer ;
2006-02-01 22:36:12 +00:00
}
2006-03-11 03:12:10 +00:00
2006-02-01 22:36:12 +00:00
void Sys_CloseClipboard ( char * bf )
{
}
2006-03-11 03:12:10 +00:00
void Sys_SaveClipboard ( char * text ) {
Q_strncpyz ( clipboard_buffer , text , SYS_CLIPBOARD_SIZE ) ;
2006-02-12 23:55:40 +00:00
}
2013-03-12 22:47:42 +00:00
# endif
2007-12-30 00:09:34 +00:00
2011-07-31 11:18:49 +00:00
qboolean Sys_RandomBytes ( qbyte * string , int len )
{
qboolean res ;
int fd = open ( " /dev/urandom " , 0 ) ;
res = ( read ( fd , string , len ) = = len ) ;
close ( fd ) ;
return res ;
}