2004-09-07 18:10:08 +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:42:00 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
2004-09-07 18:10:08 +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 .
*/
2006-03-17 22:44:17 +00:00
# include <signal.h>
2004-09-07 18:10:08 +00:00
# include <sys/types.h>
2006-05-02 00:56:30 +00:00
# include <dlfcn.h>
2004-09-07 18:10:08 +00:00
# include "qwsvdef.h"
2006-03-17 22:44:17 +00:00
2004-09-07 18:10:08 +00:00
# undef malloc
# ifdef NeXT
# include <libc.h>
# endif
# include <sys/stat.h>
2005-12-21 03:07:33 +00:00
# include <termios.h>
2004-09-07 18:10:08 +00:00
# include <unistd.h>
# include <sys/time.h>
# include <errno.h>
# include <fcntl.h>
2010-01-11 18:15:42 +00:00
# include <dirent.h>
2011-07-06 01:01:13 +00:00
# include <time.h>
2004-09-07 18:10:08 +00:00
2007-12-30 20:12:50 +00:00
# ifdef MULTITHREAD
# include <pthread.h>
# endif
2006-05-06 02:53:36 +00:00
// callbacks
void Sys_Linebuffer_Callback ( struct cvar_s * var , char * oldvalue ) ;
2010-07-11 12:33:58 +00:00
cvar_t sys_nostdout = CVAR ( " sys_nostdout " , " 0 " ) ;
cvar_t sys_extrasleep = CVAR ( " sys_extrasleep " , " 0 " ) ;
cvar_t sys_colorconsole = CVAR ( " sys_colorconsole " , " 0 " ) ;
cvar_t sys_linebuffer = CVARC ( " sys_linebuffer " , " 1 " , Sys_Linebuffer_Callback ) ;
2004-09-07 18:10:08 +00:00
qboolean stdin_ready ;
2005-12-21 03:07:33 +00:00
struct termios orig , changes ;
2004-09-07 18:10:08 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
REQUIRED SYS FUNCTIONS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = =
Sys_FileTime
returns - 1 if not present
= = = = = = = = = = = =
*/
int Sys_FileTime ( char * path )
{
struct stat buf ;
2005-11-03 23:42:00 +00:00
2004-09-07 18:10:08 +00:00
if ( stat ( path , & buf ) = = - 1 )
return - 1 ;
2005-11-03 23:42:00 +00:00
2004-09-07 18:10:08 +00:00
return buf . st_mtime ;
}
/*
= = = = = = = = = = = =
Sys_mkdir
= = = = = = = = = = = =
*/
void Sys_mkdir ( char * path )
{
if ( mkdir ( path , 0777 ) ! = - 1 )
return ;
2007-03-11 12:27:17 +00:00
// if (errno != EEXIST)
// Sys_Error ("mkdir %s: %s",path, strerror(errno));
2004-09-07 18:10:08 +00:00
}
qboolean Sys_remove ( char * path )
{
return system ( va ( " rm \" %s \" " , path ) ) ;
}
2005-12-05 16:47:29 +00:00
int Sys_DebugLog ( char * file , char * fmt , . . . )
2004-09-07 18:10:08 +00:00
{
va_list argptr ;
char data [ 1024 ] ;
int fd ;
2011-05-15 13:23:13 +00:00
size_t result ;
2005-11-03 23:42:00 +00:00
2004-09-07 18:10:08 +00:00
va_start ( argptr , fmt ) ;
_vsnprintf ( data , sizeof ( data ) - 1 , fmt , argptr ) ;
va_end ( argptr ) ;
if ( strlen ( data ) > = sizeof ( data ) - 1 )
Sys_Error ( " Sys_DebugLog was stomped \n " ) ;
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 the result
2011-05-30 04:32:04 +00:00
if ( result ! = strlen ( data ) )
2011-06-01 13:21:54 +00:00
Con_Printf ( " 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:10:08 +00:00
}
2007-10-02 15:17:22 +00:00
/*
= = = = = = = = = = = = = = = =
Sys_Milliseconds
= = = = = = = = = = = = = = = =
*/
unsigned int Sys_Milliseconds ( void )
{
struct timeval tp ;
struct timezone tzp ;
2007-12-03 11:38:58 +00:00
static int secbase ;
2007-10-02 15:17:22 +00:00
gettimeofday ( & tp , & tzp ) ;
if ( ! secbase )
{
secbase = tp . tv_sec ;
return tp . tv_usec / 1000 ;
}
return ( tp . tv_sec - secbase ) * 1000 + tp . tv_usec / 1000 ;
}
2004-09-07 18:10:08 +00:00
/*
= = = = = = = = = = = = = = = =
Sys_DoubleTime
= = = = = = = = = = = = = = = =
*/
double Sys_DoubleTime ( void )
{
struct timeval tp ;
struct timezone tzp ;
static int secbase ;
gettimeofday ( & tp , & tzp ) ;
2005-11-03 23:42:00 +00:00
2004-09-07 18:10:08 +00:00
if ( ! secbase )
{
secbase = tp . tv_sec ;
return tp . tv_usec / 1000000.0 ;
}
2005-11-03 23:42:00 +00:00
2004-09-07 18:10:08 +00:00
return ( tp . tv_sec - secbase ) + tp . tv_usec / 1000000.0 ;
}
/*
= = = = = = = = = = = = = = = =
Sys_Error
= = = = = = = = = = = = = = = =
*/
void Sys_Error ( const char * error , . . . )
{
va_list argptr ;
char string [ 1024 ] ;
2005-11-03 23:42:00 +00:00
2004-09-07 18:10:08 +00:00
va_start ( argptr , error ) ;
_vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
va_end ( argptr ) ;
printf ( " Fatal error: %s \n " , string ) ;
2005-11-03 23:42:00 +00:00
2005-12-21 03:07:33 +00:00
tcsetattr ( STDIN_FILENO , TCSADRAIN , & orig ) ;
2004-09-07 18:10:08 +00:00
* ( int * ) - 3 = 0 ;
exit ( 1 ) ;
}
2006-01-01 09:01:15 +00:00
int ansiremap [ 8 ] = { 0 , 4 , 2 , 6 , 1 , 5 , 3 , 7 } ;
2005-12-21 03:07:33 +00:00
void ApplyColour ( unsigned int chr )
{
2006-01-01 09:01:15 +00:00
static int oldchar = CON_WHITEMASK ;
int bg , fg ;
chr & = CON_FLAGSMASK ;
2005-12-21 03:07:33 +00:00
if ( oldchar = = chr )
return ;
oldchar = chr ;
2006-01-01 09:01:15 +00:00
printf ( " \ e[0; " ) ; // reset
if ( chr & CON_BLINKTEXT )
printf ( " 5; " ) ; // set blink
2006-04-06 08:21:17 +00:00
bg = ( chr & CON_BGMASK ) > > CON_BGSHIFT ;
fg = ( chr & CON_FGMASK ) > > CON_FGSHIFT ;
2011-05-15 13:23:13 +00:00
2006-01-01 09:01:15 +00:00
// 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
2005-12-21 03:07:33 +00:00
{
2006-01-01 09:01:15 +00:00
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 :
2006-01-29 00:47:54 +00:00
printf ( " m " ) ; // set nothing else
2006-01-01 09:01:15 +00:00
break ;
default :
if ( fg & 0x8 ) // intensive bit set for foreground
{
printf ( " 1; " ) ; // set bold/intensity ansi flag
fg & = 0x7 ; // strip intensive bit
}
2006-04-06 08:21:17 +00:00
printf ( " 3%im " , ansiremap [ fg ] ) ; // set foreground
2006-01-01 09:01:15 +00:00
break ;
}
2005-12-21 03:07:33 +00:00
}
}
# define putch(c) putc(c, stdout);
void Sys_PrintColouredChar ( unsigned int chr )
{
ApplyColour ( chr ) ;
2006-04-06 08:33:47 +00:00
chr = chr & CON_CHARMASK ;
2006-03-11 04:57:22 +00:00
if ( ( chr > 128 | | chr < 32 ) & & chr ! = 10 & & chr ! = 13 & & chr ! = 9 )
printf ( " [%02x] " , chr ) ;
else
chr & = ~ 0x80 ;
2006-04-06 08:33:47 +00:00
putch ( chr ) ;
2005-12-21 03:07:33 +00:00
}
/*
= = = = = = = = = = = = = = = =
Sys_Printf
= = = = = = = = = = = = = = = =
*/
# define MAXPRINTMSG 4096
char coninput_text [ 256 ] ;
int coninput_len ;
void Sys_Printf ( char * fmt , . . . )
{
2011-05-15 13:23:13 +00:00
va_list argptr ;
2005-12-21 03:07:33 +00:00
if ( sys_nostdout . value )
return ;
if ( 1 )
{
char msg [ MAXPRINTMSG ] ;
unsigned char * t ;
va_start ( argptr , fmt ) ;
vsnprintf ( msg , sizeof ( msg ) - 1 , fmt , argptr ) ;
va_end ( argptr ) ;
if ( ! sys_linebuffer . value )
{
int i ;
2011-05-15 13:23:13 +00:00
2005-12-21 03:07:33 +00:00
for ( i = 0 ; i < coninput_len ; i + + )
putch ( ' \b ' ) ;
putch ( ' \b ' ) ;
for ( i = 0 ; i < coninput_len ; i + + )
putch ( ' ' ) ;
putch ( ' ' ) ;
for ( i = 0 ; i < coninput_len ; i + + )
putch ( ' \b ' ) ;
putch ( ' \b ' ) ;
}
for ( t = ( unsigned char * ) msg ; * t ; t + + )
{
if ( * t > = 146 & & * t < 156 )
* t = * t - 146 + ' 0 ' ;
if ( * t > = 0x12 & & * t < = 0x1b )
* t = * t - 0x12 + ' 0 ' ;
if ( * t = = 143 )
* t = ' . ' ;
if ( * t = = 157 | | * t = = 158 | | * t = = 159 )
* t = ' - ' ;
if ( * t > = 128 )
* t - = 128 ;
if ( * t = = 16 )
* t = ' [ ' ;
if ( * t = = 17 )
* t = ' ] ' ;
if ( * t = = 0x1c )
* t = 249 ;
}
if ( sys_colorconsole . value )
{
2006-01-01 09:01:15 +00:00
int ext = CON_WHITEMASK ;
2005-12-21 03:07:33 +00:00
int extstack [ 4 ] ;
int extstackdepth = 0 ;
unsigned char * str = ( unsigned char * ) msg ;
while ( * str )
{
if ( * str = = ' ^ ' )
{
str + + ;
2006-01-01 09:01:15 +00:00
if ( * str > = ' 0 ' & & * str < = ' 9 ' )
2005-12-21 03:07:33 +00:00
{
2006-01-01 09:01:15 +00:00
ext = q3codemasks [ * str + + - ' 0 ' ] | ( ext & ~ CON_Q3MASK ) ; //change colour only.
2005-12-21 03:07:33 +00:00
continue ;
}
2006-01-11 07:23:31 +00:00
else if ( * str = = ' & ' ) // extended code
{
2006-04-06 08:42:24 +00:00
if ( isextendedcode ( str [ 1 ] ) & & isextendedcode ( str [ 2 ] ) )
2006-01-11 07:23:31 +00:00
{
str + + ; // foreground char
if ( * str = = ' - ' ) // default for FG
ext = ( COLOR_WHITE < < CON_FGSHIFT ) | ( ext & ~ CON_FGMASK ) ;
else if ( * str > = ' A ' )
ext = ( ( * str - ( ' A ' - 10 ) ) < < CON_FGSHIFT ) | ( ext & ~ CON_FGMASK ) ;
else
ext = ( ( * str - ' 0 ' ) < < CON_FGSHIFT ) | ( ext & ~ CON_FGMASK ) ;
str + + ; // background char
if ( * str = = ' - ' ) // default (clear) for BG
ext & = ~ CON_BGMASK & ~ CON_NONCLEARBG ;
else if ( * str > = ' A ' )
ext = ( ( * str - ( ' A ' - 10 ) ) < < CON_BGSHIFT ) | ( ext & ~ CON_BGMASK ) | CON_NONCLEARBG ;
else
ext = ( ( * str - ' 0 ' ) < < CON_BGSHIFT ) | ( ext & ~ CON_BGMASK ) | CON_NONCLEARBG ;
2006-04-06 20:57:46 +00:00
str + + ;
2006-01-11 07:23:31 +00:00
continue ;
}
2006-04-06 08:21:17 +00:00
Sys_PrintColouredChar ( ' ^ ' | ext ) ;
// else invalid code
2006-01-11 07:23:31 +00:00
}
2005-12-21 03:07:33 +00:00
else if ( * str = = ' a ' )
{
str + + ;
2006-01-01 09:01:15 +00:00
ext ^ = CON_2NDCHARSETTEXT ;
2005-12-21 03:07:33 +00:00
continue ;
}
else if ( * str = = ' b ' )
{
str + + ;
2006-01-01 09:01:15 +00:00
ext ^ = CON_BLINKTEXT ;
2005-12-21 03:07:33 +00:00
continue ;
}
2006-01-11 07:23:31 +00:00
else if ( * str = = ' h ' )
{
str + + ;
ext ^ = CON_HALFALPHA ;
continue ;
}
2005-12-21 03:07:33 +00:00
else if ( * str = = ' s ' ) //store on stack (it's great for names)
{
str + + ;
if ( extstackdepth < sizeof ( extstack ) / sizeof ( extstack [ 0 ] ) )
{
extstack [ extstackdepth ] = ext ;
extstackdepth + + ;
}
continue ;
}
else if ( * str = = ' r ' ) //restore from stack (it's great for names)
{
str + + ;
if ( extstackdepth )
{
extstackdepth - - ;
ext = extstack [ extstackdepth ] ;
}
continue ;
}
else if ( * str = = ' ^ ' )
{
2006-01-01 09:01:15 +00:00
Sys_PrintColouredChar ( ' ^ ' | ext ) ;
2005-12-21 03:07:33 +00:00
str + + ;
}
else
{
2006-01-01 09:01:15 +00:00
Sys_PrintColouredChar ( ' ^ ' | ext ) ;
Sys_PrintColouredChar ( ( * str + + ) | ext ) ;
2005-12-21 03:07:33 +00:00
}
continue ;
}
2006-01-01 09:01:15 +00:00
Sys_PrintColouredChar ( ( * str + + ) | ext ) ;
2005-12-21 03:07:33 +00:00
}
2006-01-01 09:01:15 +00:00
ApplyColour ( CON_WHITEMASK ) ;
2005-12-21 03:07:33 +00:00
}
else
{
for ( t = msg ; * t ; t + + )
{
* t & = 0x7f ;
if ( ( * t > 128 | | * t < 32 ) & & * t ! = 10 & & * t ! = 13 & & * t ! = 9 )
printf ( " [%02x] " , * t ) ;
else
putc ( * t , stdout ) ;
}
}
if ( ! sys_linebuffer . value )
{
if ( coninput_len )
printf ( " ]%s " , coninput_text ) ;
else
putch ( ' ] ' ) ;
}
}
else
{
va_start ( argptr , fmt ) ;
vprintf ( fmt , argptr ) ;
va_end ( argptr ) ;
}
fflush ( stdout ) ;
}
#if 0
2004-09-07 18:10:08 +00:00
/*
= = = = = = = = = = = = = = = =
Sys_Printf
= = = = = = = = = = = = = = = =
*/
void Sys_Printf ( char * fmt , . . . )
{
va_list argptr ;
static char text [ 2048 ] ;
unsigned char * p ;
va_start ( argptr , fmt ) ;
_vsnprintf ( text , sizeof ( text ) - 1 , fmt , argptr ) ;
va_end ( argptr ) ;
if ( strlen ( text ) > sizeof ( text ) )
Sys_Error ( " memory overwrite in Sys_Printf " ) ;
if ( sys_nostdout . value )
return ;
for ( p = ( unsigned char * ) text ; * p ; p + + ) {
* p & = 0x7f ;
if ( ( * p > 128 | | * p < 32 ) & & * p ! = 10 & & * p ! = 13 & & * p ! = 9 )
printf ( " [%02x] " , * p ) ;
else
putc ( * p , stdout ) ;
}
fflush ( stdout ) ;
}
2005-12-21 03:07:33 +00:00
# endif
2004-09-07 18:10:08 +00:00
/*
= = = = = = = = = = = = = = = =
Sys_Quit
= = = = = = = = = = = = = = = =
*/
void Sys_Quit ( void )
{
2005-12-21 03:07:33 +00:00
tcsetattr ( STDIN_FILENO , TCSADRAIN , & orig ) ;
2004-09-07 18:10:08 +00:00
exit ( 0 ) ; // appkit isn't running
}
static int do_stdin = 1 ;
2005-12-21 03:07:33 +00:00
# if 1
char * Sys_LineInputChar ( char * line )
{
char c ;
while ( * line )
{
c = * line + + ;
if ( c = = ' \r ' | | c = = ' \n ' )
{
coninput_text [ coninput_len ] = 0 ;
putch ( ' \n ' ) ;
putch ( ' ] ' ) ;
coninput_len = 0 ;
fflush ( stdout ) ;
return coninput_text ;
}
if ( c = = 8 )
{
if ( coninput_len )
{
putch ( c ) ;
putch ( ' ' ) ;
putch ( c ) ;
coninput_len - - ;
coninput_text [ coninput_len ] = 0 ;
}
continue ;
}
if ( c = = ' \t ' )
{
int i ;
char * s = Cmd_CompleteCommand ( coninput_text , true , true , 0 ) ;
if ( s )
{
for ( i = 0 ; i < coninput_len ; i + + )
putch ( ' \b ' ) ;
for ( i = 0 ; i < coninput_len ; i + + )
putch ( ' ' ) ;
for ( i = 0 ; i < coninput_len ; i + + )
putch ( ' \b ' ) ;
strcpy ( coninput_text , s ) ;
coninput_len = strlen ( coninput_text ) ;
printf ( " %s " , coninput_text ) ;
}
continue ;
}
putch ( c ) ;
coninput_text [ coninput_len ] = c ;
coninput_len + + ;
coninput_text [ coninput_len ] = 0 ;
if ( coninput_len = = sizeof ( coninput_text ) )
coninput_len = 0 ;
}
fflush ( stdout ) ;
return NULL ;
}
# endif
2004-09-07 18:10:08 +00:00
/*
= = = = = = = = = = = = = = = =
Sys_ConsoleInput
Checks for a complete line of text typed in at the console , then forwards
it to the host command processor
= = = = = = = = = = = = = = = =
*/
2006-05-06 02:53:36 +00:00
void Sys_Linebuffer_Callback ( struct cvar_s * var , char * oldvalue )
{
changes = orig ;
if ( var - > value )
{
changes . c_lflag | = ( ICANON | ECHO ) ;
}
else
{
changes . c_lflag & = ~ ( ICANON | ECHO ) ;
changes . c_cc [ VTIME ] = 0 ;
changes . c_cc [ VMIN ] = 1 ;
}
tcsetattr ( STDIN_FILENO , TCSADRAIN , & changes ) ;
}
2004-09-07 18:10:08 +00:00
char * Sys_ConsoleInput ( void )
{
2006-03-04 20:43:48 +00:00
static char text [ 256 ] ;
2005-12-21 03:07:33 +00:00
int len ;
2004-09-07 18:10:08 +00:00
if ( ! stdin_ready | | ! do_stdin )
return NULL ; // the select didn't say it was ready
stdin_ready = false ;
2005-12-21 03:07:33 +00:00
if ( sys_linebuffer . value = = 0 )
{
text [ 0 ] = getc ( stdin ) ;
text [ 1 ] = 0 ;
len = 1 ;
return Sys_LineInputChar ( text ) ;
}
else
{
len = read ( 0 , text , sizeof ( text ) - 1 ) ;
if ( len = = 0 ) {
// end of file
do_stdin = 0 ;
return NULL ;
}
if ( len < 1 )
return NULL ;
text [ len - 1 ] = 0 ; // rip off the /n and terminate
return text ;
2004-09-07 18:10:08 +00:00
}
}
/*
= = = = = = = = = = = = =
Sys_Init
Quake calls this so the system can register variables before host_hunklevel
is marked
= = = = = = = = = = = = =
*/
void Sys_Init ( void )
{
Cvar_Register ( & sys_nostdout , " System configuration " ) ;
Cvar_Register ( & sys_extrasleep , " System configuration " ) ;
2005-12-21 03:07:33 +00:00
Cvar_Register ( & sys_colorconsole , " System configuration " ) ;
Cvar_Register ( & sys_linebuffer , " System configuration " ) ;
2004-09-07 18:10:08 +00:00
}
2011-04-30 17:21:10 +00:00
void Sys_Shutdown ( void )
{
}
2011-06-18 17:04:47 +00:00
# ifdef __linux__ /*should probably be GNUC but whatever*/
2011-06-06 01:41:33 +00:00
# include <execinfo.h>
static void Friendly_Crash_Handler ( int sig )
{
int fd ;
void * array [ 10 ] ;
size_t size ;
// get void*'s for all entries on the stack
size = backtrace ( array , 10 ) ;
// print out all the frames to stderr
fprintf ( stderr , " Error: signal %d: \n " , sig ) ;
backtrace_symbols_fd ( array , size , 2 ) ;
fd = open ( " crash.log " , O_WRONLY | O_CREAT | O_APPEND , S_IRUSR | S_IWUSR | S_IRGRP ) ;
if ( fd ! = - 1 )
{
write ( fd , " Crash Log: \n " , 11 ) ;
size = backtrace ( array , 10 ) ;
backtrace_symbols_fd ( array , size , fd ) ;
write ( fd , " \n " , 1 ) ;
close ( fd ) ;
}
exit ( 1 ) ;
}
2011-06-18 17:04:47 +00:00
# endif
2011-06-06 01:41:33 +00:00
2004-09-07 18:10:08 +00:00
/*
= = = = = = = = = = = = =
main
= = = = = = = = = = = = =
*/
int main ( int argc , char * argv [ ] )
{
2011-06-05 23:53:33 +00:00
int maxsleep ;
2004-09-07 18:10:08 +00:00
quakeparms_t parms ;
// fd_set fdset;
// extern int net_socket;
int j ;
2006-03-17 22:44:17 +00:00
signal ( SIGPIPE , SIG_IGN ) ;
2005-12-21 03:07:33 +00:00
tcgetattr ( STDIN_FILENO , & orig ) ;
changes = orig ;
2004-09-07 18:10:08 +00:00
memset ( & parms , 0 , sizeof ( parms ) ) ;
2011-05-19 13:34:07 +00:00
COM_InitArgv ( argc , ( const char * * ) argv ) ;
2004-09-07 18:10:08 +00:00
TL_InitLanguages ( ) ;
parms . argc = com_argc ;
parms . argv = com_argv ;
2011-06-18 17:04:47 +00:00
# ifdef __linux__
2011-06-06 01:41:33 +00:00
if ( COM_CheckParm ( " -dumpstack " ) )
{
signal ( SIGILL , Friendly_Crash_Handler ) ;
2011-06-16 02:03:57 +00:00
signal ( SIGFPE , Friendly_Crash_Handler ) ;
2011-06-06 01:41:33 +00:00
signal ( SIGSEGV , Friendly_Crash_Handler ) ;
signal ( SIGBUS , Friendly_Crash_Handler ) ;
}
2011-06-18 17:04:47 +00:00
# endif
2006-03-17 22:44:17 +00:00
2004-09-07 18:10:08 +00:00
parms . memsize = 16 * 1024 * 1024 ;
j = COM_CheckParm ( " -mem " ) ;
if ( j )
parms . memsize = ( int ) ( Q_atof ( com_argv [ j + 1 ] ) * 1024 * 1024 ) ;
if ( ( parms . membase = malloc ( parms . memsize ) ) = = NULL )
2009-11-04 21:16:50 +00:00
Sys_Error ( " Can't allocate %u \n " , parms . memsize ) ;
2004-09-07 18:10:08 +00:00
parms . basedir = " . " ;
SV_Init ( & parms ) ;
// run one frame immediately for first heartbeat
2011-06-05 23:53:33 +00:00
maxsleep = SV_Frame ( ) * 1000 ;
2004-09-07 18:10:08 +00:00
//
// main loop
//
while ( 1 )
{
2005-03-10 03:55:18 +00:00
if ( do_stdin )
2011-06-05 23:53:33 +00:00
stdin_ready = NET_Sleep ( maxsleep , true ) ;
2005-03-10 03:55:18 +00:00
else
2005-11-03 23:42:00 +00:00
{
2011-06-05 23:53:33 +00:00
NET_Sleep ( maxsleep , false ) ;
2005-03-10 03:55:18 +00:00
stdin_ready = false ;
}
2004-09-07 18:10:08 +00:00
2011-06-05 23:53:33 +00:00
maxsleep = SV_Frame ( ) * 1000 ;
2005-11-03 23:42:00 +00:00
2004-09-07 18:10:08 +00:00
// extrasleep is just a way to generate a fucked up connection on purpose
if ( sys_extrasleep . value )
usleep ( sys_extrasleep . value ) ;
2005-11-03 23:42:00 +00:00
}
2004-09-07 18:10:08 +00:00
return 0 ;
}
2009-04-02 22:25:54 +00:00
int Sys_EnumerateFiles ( const char * gpath , const char * match , int ( * func ) ( const char * , int , void * ) , void * parm )
2004-09-07 18:10:08 +00:00
{
2010-01-11 18:15:42 +00:00
DIR * dir ;
2004-09-07 18:10:08 +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:10:08 +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:10:08 +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:42:00 +00:00
Con_Printf ( " Failed to open dir %s \n " , truepath ) ;
2004-09-07 18:10:08 +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:10:08 +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:10:08 +00:00
2010-01-11 18:15:42 +00:00
if ( stat ( file , & st ) = = 0 )
2004-09-07 18:10:08 +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:10:08 +00:00
2010-01-11 18:15:42 +00:00
if ( ! func ( file , st . st_size , parm ) )
{
closedir ( dir ) ;
return false ;
}
2004-09-07 18:10:08 +00:00
}
2010-01-11 18:15:42 +00:00
else
printf ( " Stat failed for \" %s \" \n " , file ) ;
2004-09-07 18:10:08 +00:00
}
2010-01-11 18:15:42 +00:00
}
2004-09-07 18:10:08 +00:00
} while ( 1 ) ;
closedir ( dir ) ;
return true ;
}
2009-03-07 05:05:54 +00:00
void Sys_CloseLibrary ( dllhandle_t * lib )
{
dlclose ( ( void * ) lib ) ;
}
2009-11-04 21:16:50 +00:00
dllhandle_t * Sys_LoadLibrary ( const char * name , dllfunction_t * funcs )
2009-03-07 05:05:54 +00:00
{
int i ;
dllhandle_t lib ;
lib = dlopen ( name , RTLD_LAZY ) ;
if ( ! lib )
return NULL ;
2011-05-30 21:48:32 +00:00
if ( funcs )
2009-03-07 05:05:54 +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 )
{
Sys_CloseLibrary ( ( dllhandle_t * ) lib ) ;
lib = NULL ;
}
2009-03-07 05:05:54 +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 ) ;
}
2009-03-07 05:05:54 +00:00
2006-05-02 00:56:30 +00:00
static void * game_library ;
void Sys_UnloadGame ( void )
2004-09-07 18:10:08 +00:00
{
2011-05-15 13:23:13 +00:00
if ( game_library )
2006-05-02 00:56:30 +00:00
{
dlclose ( game_library ) ;
game_library = 0 ;
}
2004-09-07 18:10:08 +00:00
}
2006-05-02 00:56:30 +00:00
void * Sys_GetGameAPI ( void * parms )
2004-09-07 18:10:08 +00:00
{
2006-05-02 00:56:30 +00:00
void * ( * GetGameAPI ) ( void * ) ;
char name [ MAX_OSPATH ] ;
char curpath [ MAX_OSPATH ] ;
char * searchpath ;
const char * gamename = " gamei386.so " ;
2011-05-19 13:34:07 +00:00
char * result ;
2006-05-02 00:56:30 +00:00
void * ret ;
2011-05-15 13:23:13 +00:00
result = getcwd ( curpath , sizeof ( curpath ) ) ; // do soemthing with the result
2006-05-02 00:56:30 +00:00
searchpath = 0 ;
while ( ( searchpath = COM_NextPath ( searchpath ) ) )
{
2011-07-22 15:11:35 +00:00
snprintf ( name , sizeof ( name ) , " %s/%s/%s " , curpath , searchpath , gamename ) ;
2006-05-02 00:56:30 +00:00
game_library = dlopen ( name , RTLD_LAZY ) ;
if ( game_library )
{
GetGameAPI = ( void * ) dlsym ( game_library , " GetGameAPI " ) ;
if ( GetGameAPI & & ( ret = GetGameAPI ( parms ) ) )
{
return ret ;
}
dlclose ( game_library ) ;
game_library = 0 ;
}
}
return 0 ;
2004-09-07 18:10:08 +00:00
}
void Sys_ServerActivity ( void )
{
}
2007-12-30 00:09:34 +00:00
# ifdef MULTITHREAD
/* Thread creation calls */
typedef void * ( * pfunction_t ) ( void * ) ;
2011-07-03 16:24:53 +00:00
void * Sys_CreateThread ( int ( * func ) ( void * ) , void * args , int priority , int stacksize )
2007-12-30 00:09:34 +00:00
{
2007-12-30 20:05:49 +00:00
pthread_t * thread ;
2007-12-30 00:09:34 +00:00
pthread_attr_t attr ;
2011-05-15 13:23:13 +00:00
2007-12-30 20:05:49 +00:00
thread = ( pthread_t * ) malloc ( sizeof ( pthread_t ) ) ;
if ( ! thread )
return NULL ;
2011-05-15 13:23:13 +00:00
2007-12-30 00:09:34 +00:00
pthread_attr_init ( & attr ) ;
2007-12-30 20:05:49 +00:00
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_JOINABLE ) ;
2007-12-30 00:09:34 +00:00
if ( stacksize < PTHREAD_STACK_MIN )
stacksize = PTHREAD_STACK_MIN ;
pthread_attr_setstacksize ( & attr , stacksize ) ;
2007-12-30 20:05:49 +00:00
if ( pthread_create ( thread , & attr , ( pfunction_t ) func , args ) )
{
free ( thread ) ;
thread = NULL ;
}
pthread_attr_destroy ( & attr ) ;
return ( void * ) thread ;
}
2007-12-30 00:09:34 +00:00
2007-12-30 20:05:49 +00:00
void Sys_WaitOnThread ( void * thread )
{
2011-05-15 13:23:13 +00:00
pthread_join ( ( pthread_t * ) thread , NULL ) ;
2007-12-30 20:05:49 +00:00
free ( thread ) ;
2007-12-30 00:09:34 +00:00
}
/* Mutex calls */
2008-06-01 05:42:23 +00:00
void * Sys_CreateMutex ( void )
2007-12-30 00:09:34 +00:00
{
pthread_mutex_t * mutex = ( pthread_mutex_t * ) malloc ( sizeof ( pthread_mutex_t ) ) ;
2011-05-15 13:23:13 +00:00
2007-12-30 00:09:34 +00:00
if ( mutex & & ! pthread_mutex_init ( mutex , NULL ) )
return mutex ;
return NULL ;
}
qboolean Sys_TryLockMutex ( void * mutex )
{
return ! pthread_mutex_trylock ( mutex ) ;
}
qboolean Sys_LockMutex ( void * mutex )
{
return ! pthread_mutex_lock ( mutex ) ;
}
qboolean Sys_UnlockMutex ( void * mutex )
{
return ! pthread_mutex_unlock ( mutex ) ;
}
void Sys_DestroyMutex ( void * mutex )
{
pthread_mutex_destroy ( mutex ) ;
free ( mutex ) ;
}
2008-06-01 05:42:23 +00:00
/* Conditional wait calls */
typedef struct condvar_s
{
pthread_mutex_t * mutex ;
pthread_cond_t * cond ;
} condvar_t ;
void * Sys_CreateConditional ( void )
{
condvar_t * condv ;
pthread_mutex_t * mutex ;
pthread_cond_t * cond ;
2011-05-15 13:23:13 +00:00
2008-06-01 05:42:23 +00:00
condv = ( condvar_t * ) malloc ( sizeof ( condvar_t ) ) ;
if ( ! condv )
return NULL ;
2011-05-15 13:23:13 +00:00
2008-06-01 05:42:23 +00:00
mutex = ( pthread_mutex_t * ) malloc ( sizeof ( pthread_mutex_t ) ) ;
if ( ! mutex )
return NULL ;
2011-05-15 13:23:13 +00:00
2008-06-01 05:42:23 +00:00
cond = ( pthread_cond_t * ) malloc ( sizeof ( pthread_cond_t ) ) ;
if ( ! cond )
return NULL ;
2011-05-15 13:23:13 +00:00
2008-06-01 05:42:23 +00:00
if ( ! pthread_mutex_init ( mutex , NULL ) )
{
if ( ! pthread_cond_init ( cond , NULL ) )
{
condv - > cond = cond ;
condv - > mutex = mutex ;
2011-05-15 13:23:13 +00:00
2008-06-01 05:42:23 +00:00
return ( void * ) condv ;
}
else
pthread_mutex_destroy ( mutex ) ;
}
2011-05-15 13:23:13 +00:00
2008-06-01 05:42:23 +00:00
free ( cond ) ;
free ( mutex ) ;
free ( condv ) ;
2011-05-15 13:23:13 +00:00
return NULL ;
2008-06-01 05:42:23 +00:00
}
qboolean Sys_LockConditional ( void * condv )
{
return ! pthread_mutex_lock ( ( ( condvar_t * ) condv ) - > mutex ) ;
}
qboolean Sys_UnlockConditional ( void * condv )
{
return ! pthread_mutex_unlock ( ( ( condvar_t * ) condv ) - > mutex ) ;
}
qboolean Sys_ConditionWait ( void * condv )
{
return ! pthread_cond_wait ( ( ( condvar_t * ) condv ) - > cond , ( ( condvar_t * ) condv ) - > mutex ) ;
}
qboolean Sys_ConditionSignal ( void * condv )
{
return ! pthread_cond_signal ( ( ( condvar_t * ) condv ) - > cond ) ;
}
qboolean Sys_ConditionBroadcast ( void * condv )
{
return ! pthread_cond_broadcast ( ( ( condvar_t * ) condv ) - > cond ) ;
}
void Sys_DestroyConditional ( void * condv )
{
condvar_t * cv = ( condvar_t * ) condv ;
2011-05-15 13:23:13 +00:00
2008-06-01 05:42:23 +00:00
pthread_cond_destroy ( cv - > cond ) ;
pthread_mutex_destroy ( cv - > mutex ) ;
free ( cv - > cond ) ;
free ( cv - > mutex ) ;
free ( cv ) ;
}
2011-07-06 01:01:13 +00:00
# endif
2011-07-03 16:24:53 +00:00
2011-07-06 01:01:13 +00:00
void Sys_Sleep ( double seconds )
2011-07-03 16:24:53 +00:00
{
2011-07-06 01:01:13 +00:00
struct timespec ts ;
2007-12-30 00:09:34 +00:00
2011-07-06 01:01:13 +00:00
ts . tv_sec = ( time_t ) seconds ;
seconds - = ts . tv_sec ;
ts . tv_nsec = seconds * 1000000000.0 ;
nanosleep ( & ts , NULL ) ;
}