From 4d72acef0743f75a260b22a41f4d474f064d15e5 Mon Sep 17 00:00:00 2001 From: tma Date: Thu, 6 Sep 2007 20:31:30 +0000 Subject: * Build dedicated server binary on Windows git-svn-id: svn://svn.icculus.org/quake3/trunk@1169 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/sys/con_tty.c | 440 +++++++++++++++++++++++++++++++++++++++++++++++++ code/sys/con_win32.c | 70 ++++++++ code/sys/sys_loadlib.h | 16 +- code/sys/sys_local.h | 12 +- code/sys/sys_main.c | 28 ++-- code/sys/tty_console.c | 440 ------------------------------------------------- 6 files changed, 542 insertions(+), 464 deletions(-) create mode 100644 code/sys/con_tty.c create mode 100644 code/sys/con_win32.c delete mode 100644 code/sys/tty_console.c (limited to 'code/sys') diff --git a/code/sys/con_tty.c b/code/sys/con_tty.c new file mode 100644 index 0000000..dd37c19 --- /dev/null +++ b/code/sys/con_tty.c @@ -0,0 +1,440 @@ +/* +=========================================================================== +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 +=========================================================================== +*/ + +#include "../qcommon/q_shared.h" +#include "../qcommon/qcommon.h" + +#include +#include +#include +#include + +/* +============================================================= +tty console routines + +NOTE: if the user is editing a line when something gets printed to the early +console then it won't look good so we provide CON_Hide and CON_Show to be +called before and after a stdout or stderr output +============================================================= +*/ + +// general flag to tell about tty console mode +static qboolean ttycon_on = qfalse; +static int ttycon_hide = 0; + +// some key codes that the terminal may be using, initialised on start up +static int TTY_erase; +static int TTY_eof; + +static struct termios TTY_tc; + +static field_t TTY_con; + +// This is somewhat of aduplicate of the graphical console history +// but it's safer more modular to have our own here +#define CON_HISTORY 32 +static field_t ttyEditLines[ CON_HISTORY ]; +static int hist_current = -1, hist_count = 0; + +/* +================== +CON_FlushIn + +Flush stdin, I suspect some terminals are sending a LOT of shit +FIXME relevant? +================== +*/ +static void CON_FlushIn( void ) +{ + char key; + while (read(0, &key, 1)!=-1); +} + +/* +================== +CON_Back + +Output a backspace + +NOTE: it seems on some terminals just sending '\b' is not enough so instead we +send "\b \b" +(FIXME there may be a way to find out if '\b' alone would work though) +================== +*/ +static void CON_Back( void ) +{ + char key; + key = '\b'; + write(1, &key, 1); + key = ' '; + write(1, &key, 1); + key = '\b'; + write(1, &key, 1); +} + +/* +================== +CON_Hide + +Clear the display of the line currently edited +bring cursor back to beginning of line +================== +*/ +void CON_Hide( void ) +{ + if( ttycon_on ) + { + int i; + if (ttycon_hide) + { + ttycon_hide++; + return; + } + if (TTY_con.cursor>0) + { + for (i=0; i0); + ttycon_hide--; + if (ttycon_hide == 0) + { + write( 1, "]", 1 ); + if (TTY_con.cursor) + { + for (i=0; i= 0); + assert(hist_current >= -1); + assert(hist_current <= hist_count); + // make some room + for (i=CON_HISTORY-1; i>0; i--) + { + ttyEditLines[i] = ttyEditLines[i-1]; + } + ttyEditLines[0] = *field; + if (hist_count= 0); + assert(hist_current >= -1); + assert(hist_current <= hist_count); + hist_prev = hist_current + 1; + if (hist_prev >= hist_count) + { + return NULL; + } + hist_current++; + return &(ttyEditLines[hist_current]); +} + +/* +================== +Hist_Next +================== +*/ +field_t *Hist_Next( void ) +{ + assert(hist_count <= CON_HISTORY); + assert(hist_count >= 0); + assert(hist_current >= -1); + assert(hist_current <= hist_count); + if (hist_current >= 0) + { + hist_current--; + } + if (hist_current == -1) + { + return NULL; + } + return &(ttyEditLines[hist_current]); +} + +/* +================== +CON_Init + +Initialize the console input (tty mode if possible) +================== +*/ +void CON_Init( void ) +{ + struct termios tc; + + // If the process is backgrounded (running non interactively) + // then SIGTTIN or SIGTOU is emitted, if not caught, turns into a SIGSTP + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + + // Make stdin reads non-blocking + fcntl( 0, F_SETFL, fcntl( 0, F_GETFL, 0 ) | O_NDELAY ); + + if (isatty(STDIN_FILENO)!=1) + { + Com_Printf( "stdin is not a tty, tty console mode disabled\n"); + ttycon_on = qfalse; + return; + } + + Field_Clear(&TTY_con); + tcgetattr (0, &TTY_tc); + TTY_erase = TTY_tc.c_cc[VERASE]; + TTY_eof = TTY_tc.c_cc[VEOF]; + tc = TTY_tc; + + /* + ECHO: don't echo input characters + ICANON: enable canonical mode. This enables the special + characters EOF, EOL, EOL2, ERASE, KILL, REPRINT, + STATUS, and WERASE, and buffers by lines. + ISIG: when any of the characters INTR, QUIT, SUSP, or + DSUSP are received, generate the corresponding sig­ + nal + */ + tc.c_lflag &= ~(ECHO | ICANON); + + /* + ISTRIP strip off bit 8 + INPCK enable input parity checking + */ + tc.c_iflag &= ~(ISTRIP | INPCK); + tc.c_cc[VMIN] = 1; + tc.c_cc[VTIME] = 0; + tcsetattr (0, TCSADRAIN, &tc); + ttycon_on = qtrue; +} + +/* +================== +CON_ConsoleInput +================== +*/ +char *CON_ConsoleInput( void ) +{ + // we use this when sending back commands + static char text[256]; + int avail; + char key; + field_t *history; + + if( ttycon_on ) + { + avail = read(0, &key, 1); + if (avail != -1) + { + // we have something + // backspace? + // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere + if ((key == TTY_erase) || (key == 127) || (key == 8)) + { + if (TTY_con.cursor > 0) + { + TTY_con.cursor--; + TTY_con.buffer[TTY_con.cursor] = '\0'; + CON_Back(); + } + return NULL; + } + // check if this is a control char + if ((key) && (key) < ' ') + { + if (key == '\n') + { + // push it in history + Hist_Add(&TTY_con); + strcpy(text, TTY_con.buffer); + Field_Clear(&TTY_con); + key = '\n'; + write(1, &key, 1); + write( 1, "]", 1 ); + return text; + } + if (key == '\t') + { + CON_Hide(); + Field_AutoComplete( &TTY_con ); + CON_Show(); + return NULL; + } + avail = read(0, &key, 1); + if (avail != -1) + { + // VT 100 keys + if (key == '[' || key == 'O') + { + avail = read(0, &key, 1); + if (avail != -1) + { + switch (key) + { + case 'A': + history = Hist_Prev(); + if (history) + { + CON_Hide(); + TTY_con = *history; + CON_Show(); + } + CON_FlushIn(); + return NULL; + break; + case 'B': + history = Hist_Next(); + CON_Hide(); + if (history) + { + TTY_con = *history; + } else + { + Field_Clear(&TTY_con); + } + CON_Show(); + CON_FlushIn(); + return NULL; + break; + case 'C': + return NULL; + case 'D': + return NULL; + } + } + } + } + Com_DPrintf("droping ISCTL sequence: %d, TTY_erase: %d\n", key, TTY_erase); + CON_FlushIn(); + return NULL; + } + // push regular character + TTY_con.buffer[TTY_con.cursor] = key; + TTY_con.cursor++; + // print the current line (this is differential) + write(1, &key, 1); + } + + return NULL; + } + else + { + int len; + fd_set fdset; + struct timeval timeout; + static qboolean stdin_active; + + if (!com_dedicated || !com_dedicated->value) + return NULL; + + if (!stdin_active) + return NULL; + + FD_ZERO(&fdset); + FD_SET(0, &fdset); // stdin + timeout.tv_sec = 0; + timeout.tv_usec = 0; + if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset)) + { + return NULL; + } + + len = read (0, text, sizeof(text)); + if (len == 0) + { // eof! + stdin_active = qfalse; + return NULL; + } + + if (len < 1) + return NULL; + text[len-1] = 0; // rip off the /n and terminate + + return text; + } +} diff --git a/code/sys/con_win32.c b/code/sys/con_win32.c new file mode 100644 index 0000000..8e5718c --- /dev/null +++ b/code/sys/con_win32.c @@ -0,0 +1,70 @@ +/* +=========================================================================== +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 +=========================================================================== +*/ + +#include "../qcommon/q_shared.h" +#include "../qcommon/qcommon.h" + +/* +================== +CON_Hide +================== +*/ +void CON_Hide( void ) +{ +} + +/* +================== +CON_Show +================== +*/ +void CON_Show( void ) +{ +} + +/* +================== +CON_Shutdown +================== +*/ +void CON_Shutdown( void ) +{ +} + +/* +================== +CON_Init +================== +*/ +void CON_Init( void ) +{ +} + +/* +================== +CON_ConsoleInput +================== +*/ +char *CON_ConsoleInput( void ) +{ + return NULL; +} diff --git a/code/sys/sys_loadlib.h b/code/sys/sys_loadlib.h index 29b21c7..a7e854c 100644 --- a/code/sys/sys_loadlib.h +++ b/code/sys/sys_loadlib.h @@ -21,11 +21,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef DEDICATED +# ifdef _WIN32 +# include +# define Sys_LoadLibrary(f) (void*)LoadLibrary(f) +# define Sys_UnloadLibrary(h) FreeLibrary((HMODULE)h) +# define Sys_LoadFunction(h,fn) (void*)GetProcAddress((HMODULE)h,fn) +# define Sys_LibraryError() "unknown" +# else # include -# define Sys_LoadLibrary(f) dlopen(f,RTLD_NOW) -# define Sys_UnloadLibrary(h) dlclose(h) -# define Sys_LoadFunction(h,fn) dlsym(h,fn) -# define Sys_LibraryError() dlerror() +# define Sys_LoadLibrary(f) dlopen(f,RTLD_NOW) +# define Sys_UnloadLibrary(h) dlclose(h) +# define Sys_LoadFunction(h,fn) dlsym(h,fn) +# define Sys_LibraryError() dlerror() +#endif #else # include "SDL.h" # include "SDL_loadso.h" diff --git a/code/sys/sys_local.h b/code/sys/sys_local.h index 2ccac5c..c9a9a94 100644 --- a/code/sys/sys_local.h +++ b/code/sys/sys_local.h @@ -28,12 +28,12 @@ void IN_Init (void); void IN_Frame (void); void IN_Shutdown (void); -// TTY console -void TTY_Hide( void ); -void TTY_Show( void ); -void TTY_Shutdown( void ); -void TTY_Init( void ); -char *TTY_ConsoleInput(void); +// Console +void CON_Hide( void ); +void CON_Show( void ); +void CON_Shutdown( void ); +void CON_Init( void ); +char *CON_ConsoleInput(void); #ifdef MACOS_X char *Sys_StripAppBundle( char *pwd ); diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c index c73c2e4..7ecbd2e 100644 --- a/code/sys/sys_main.c +++ b/code/sys/sys_main.c @@ -113,7 +113,7 @@ Start the console input subsystem void Sys_ConsoleInputInit( void ) { #ifdef DEDICATED - TTY_Init( ); + CON_Init( ); #endif } @@ -127,7 +127,7 @@ Shutdown the console input subsystem void Sys_ConsoleInputShutdown( void ) { #ifdef DEDICATED - TTY_Shutdown( ); + CON_Shutdown( ); #endif } @@ -141,7 +141,7 @@ Handle new console input char *Sys_ConsoleInput(void) { #ifdef DEDICATED - return TTY_ConsoleInput( ); + return CON_ConsoleInput( ); #endif return NULL; @@ -224,7 +224,7 @@ static struct Q3ToAnsiColorTable_s { char Q3color; char *ANSIcolor; -} TTY_colorTable[ ] = +} CON_colorTable[ ] = { { COLOR_BLACK, "30" }, { COLOR_RED, "31" }, @@ -236,8 +236,8 @@ static struct Q3ToAnsiColorTable_s { COLOR_WHITE, "0" } }; -static int TTY_colorTableSize = - sizeof( TTY_colorTable ) / sizeof( TTY_colorTable[ 0 ] ); +static int CON_colorTableSize = + sizeof( CON_colorTable ) / sizeof( CON_colorTable[ 0 ] ); /* ================= @@ -276,11 +276,11 @@ static void Sys_ANSIColorify( const char *msg, char *buffer, int bufferSize ) if( i < msgLength ) { escapeCode = NULL; - for( j = 0; j < TTY_colorTableSize; j++ ) + for( j = 0; j < CON_colorTableSize; j++ ) { - if( msg[ i ] == TTY_colorTable[ j ].Q3color ) + if( msg[ i ] == CON_colorTable[ j ].Q3color ) { - escapeCode = TTY_colorTable[ j ].ANSIcolor; + escapeCode = CON_colorTable[ j ].ANSIcolor; break; } } @@ -310,7 +310,7 @@ Sys_Print void Sys_Print( const char *msg ) { #ifdef DEDICATED - TTY_Hide(); + CON_Hide(); #endif if( com_ansiColor && com_ansiColor->integer ) @@ -323,7 +323,7 @@ void Sys_Print( const char *msg ) fputs(msg, stderr); #ifdef DEDICATED - TTY_Show(); + CON_Show(); #endif } @@ -338,7 +338,7 @@ void Sys_Error( const char *error, ... ) char string[1024]; #ifdef DEDICATED - TTY_Hide(); + CON_Hide(); #endif CL_Shutdown (); @@ -366,13 +366,13 @@ void Sys_Warn( char *warning, ... ) va_end (argptr); #ifdef DEDICATED - TTY_Hide(); + CON_Hide(); #endif fprintf(stderr, "Warning: %s", string); #ifdef DEDICATED - TTY_Show(); + CON_Show(); #endif } diff --git a/code/sys/tty_console.c b/code/sys/tty_console.c deleted file mode 100644 index 34a09d1..0000000 --- a/code/sys/tty_console.c +++ /dev/null @@ -1,440 +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 -=========================================================================== -*/ - -#include "../qcommon/q_shared.h" -#include "../qcommon/qcommon.h" - -#include -#include -#include -#include - -/* -============================================================= -tty console routines - -NOTE: if the user is editing a line when something gets printed to the early -console then it won't look good so we provide TTY_Hide and TTY_Show to be -called before and after a stdout or stderr output -============================================================= -*/ - -// general flag to tell about tty console mode -static qboolean ttycon_on = qfalse; -static int ttycon_hide = 0; - -// some key codes that the terminal may be using, initialised on start up -static int TTY_erase; -static int TTY_eof; - -static struct termios TTY_tc; - -static field_t TTY_con; - -// This is somewhat of aduplicate of the graphical console history -// but it's safer more modular to have our own here -#define TTY_HISTORY 32 -static field_t ttyEditLines[ TTY_HISTORY ]; -static int hist_current = -1, hist_count = 0; - -/* -================== -TTY_FlushIn - -Flush stdin, I suspect some terminals are sending a LOT of shit -FIXME relevant? -================== -*/ -static void TTY_FlushIn( void ) -{ - char key; - while (read(0, &key, 1)!=-1); -} - -/* -================== -TTY_Back - -Output a backspace - -NOTE: it seems on some terminals just sending '\b' is not enough so instead we -send "\b \b" -(FIXME there may be a way to find out if '\b' alone would work though) -================== -*/ -static void TTY_Back( void ) -{ - char key; - key = '\b'; - write(1, &key, 1); - key = ' '; - write(1, &key, 1); - key = '\b'; - write(1, &key, 1); -} - -/* -================== -TTY_Hide - -Clear the display of the line currently edited -bring cursor back to beginning of line -================== -*/ -void TTY_Hide( void ) -{ - if( ttycon_on ) - { - int i; - if (ttycon_hide) - { - ttycon_hide++; - return; - } - if (TTY_con.cursor>0) - { - for (i=0; i0); - ttycon_hide--; - if (ttycon_hide == 0) - { - write( 1, "]", 1 ); - if (TTY_con.cursor) - { - for (i=0; i= 0); - assert(hist_current >= -1); - assert(hist_current <= hist_count); - // make some room - for (i=TTY_HISTORY-1; i>0; i--) - { - ttyEditLines[i] = ttyEditLines[i-1]; - } - ttyEditLines[0] = *field; - if (hist_count= 0); - assert(hist_current >= -1); - assert(hist_current <= hist_count); - hist_prev = hist_current + 1; - if (hist_prev >= hist_count) - { - return NULL; - } - hist_current++; - return &(ttyEditLines[hist_current]); -} - -/* -================== -Hist_Next -================== -*/ -field_t *Hist_Next( void ) -{ - assert(hist_count <= TTY_HISTORY); - assert(hist_count >= 0); - assert(hist_current >= -1); - assert(hist_current <= hist_count); - if (hist_current >= 0) - { - hist_current--; - } - if (hist_current == -1) - { - return NULL; - } - return &(ttyEditLines[hist_current]); -} - -/* -================== -TTY_Init - -Initialize the console input (tty mode if possible) -================== -*/ -void TTY_Init( void ) -{ - struct termios tc; - - // If the process is backgrounded (running non interactively) - // then SIGTTIN or SIGTOU is emitted, if not caught, turns into a SIGSTP - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - - // Make stdin reads non-blocking - fcntl( 0, F_SETFL, fcntl( 0, F_GETFL, 0 ) | O_NDELAY ); - - if (isatty(STDIN_FILENO)!=1) - { - Com_Printf( "stdin is not a tty, tty console mode disabled\n"); - ttycon_on = qfalse; - return; - } - - Field_Clear(&TTY_con); - tcgetattr (0, &TTY_tc); - TTY_erase = TTY_tc.c_cc[VERASE]; - TTY_eof = TTY_tc.c_cc[VEOF]; - tc = TTY_tc; - - /* - ECHO: don't echo input characters - ICANON: enable canonical mode. This enables the special - characters EOF, EOL, EOL2, ERASE, KILL, REPRINT, - STATUS, and WERASE, and buffers by lines. - ISIG: when any of the characters INTR, QUIT, SUSP, or - DSUSP are received, generate the corresponding sig­ - nal - */ - tc.c_lflag &= ~(ECHO | ICANON); - - /* - ISTRIP strip off bit 8 - INPCK enable input parity checking - */ - tc.c_iflag &= ~(ISTRIP | INPCK); - tc.c_cc[VMIN] = 1; - tc.c_cc[VTIME] = 0; - tcsetattr (0, TCSADRAIN, &tc); - ttycon_on = qtrue; -} - -/* -================== -TTY_ConsoleInput -================== -*/ -char *TTY_ConsoleInput( void ) -{ - // we use this when sending back commands - static char text[256]; - int avail; - char key; - field_t *history; - - if( ttycon_on ) - { - avail = read(0, &key, 1); - if (avail != -1) - { - // we have something - // backspace? - // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere - if ((key == TTY_erase) || (key == 127) || (key == 8)) - { - if (TTY_con.cursor > 0) - { - TTY_con.cursor--; - TTY_con.buffer[TTY_con.cursor] = '\0'; - TTY_Back(); - } - return NULL; - } - // check if this is a control char - if ((key) && (key) < ' ') - { - if (key == '\n') - { - // push it in history - Hist_Add(&TTY_con); - strcpy(text, TTY_con.buffer); - Field_Clear(&TTY_con); - key = '\n'; - write(1, &key, 1); - write( 1, "]", 1 ); - return text; - } - if (key == '\t') - { - TTY_Hide(); - Field_AutoComplete( &TTY_con ); - TTY_Show(); - return NULL; - } - avail = read(0, &key, 1); - if (avail != -1) - { - // VT 100 keys - if (key == '[' || key == 'O') - { - avail = read(0, &key, 1); - if (avail != -1) - { - switch (key) - { - case 'A': - history = Hist_Prev(); - if (history) - { - TTY_Hide(); - TTY_con = *history; - TTY_Show(); - } - TTY_FlushIn(); - return NULL; - break; - case 'B': - history = Hist_Next(); - TTY_Hide(); - if (history) - { - TTY_con = *history; - } else - { - Field_Clear(&TTY_con); - } - TTY_Show(); - TTY_FlushIn(); - return NULL; - break; - case 'C': - return NULL; - case 'D': - return NULL; - } - } - } - } - Com_DPrintf("droping ISCTL sequence: %d, TTY_erase: %d\n", key, TTY_erase); - TTY_FlushIn(); - return NULL; - } - // push regular character - TTY_con.buffer[TTY_con.cursor] = key; - TTY_con.cursor++; - // print the current line (this is differential) - write(1, &key, 1); - } - - return NULL; - } - else - { - int len; - fd_set fdset; - struct timeval timeout; - static qboolean stdin_active; - - if (!com_dedicated || !com_dedicated->value) - return NULL; - - if (!stdin_active) - return NULL; - - FD_ZERO(&fdset); - FD_SET(0, &fdset); // stdin - timeout.tv_sec = 0; - timeout.tv_usec = 0; - if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset)) - { - return NULL; - } - - len = read (0, text, sizeof(text)); - if (len == 0) - { // eof! - stdin_active = qfalse; - return NULL; - } - - if (len < 1) - return NULL; - text[len-1] = 0; // rip off the /n and terminate - - return text; - } -} -- cgit v1.2.3