From 3bf8ec2dabe1b67c18dc325a35dd9ff59dfce618 Mon Sep 17 00:00:00 2001 From: Thilo Schulz Date: Thu, 10 Mar 2011 01:01:27 +0000 Subject: [PATCH] (#4925) - com_pipefile to create a named pipe for sending commands from other processes, patch by Chris Schwarz --- README | 4 ++++ code/qcommon/common.c | 36 ++++++++++++++++++++++++++++++++++ code/qcommon/files.c | 44 ++++++++++++++++++++++++++++++++++++++++++ code/qcommon/qcommon.h | 2 ++ code/sys/sys_unix.c | 25 ++++++++++++++++++++++++ code/sys/sys_win32.c | 11 +++++++++++ 6 files changed, 122 insertions(+) diff --git a/README b/README index 190b7f25..64867684 100644 --- a/README +++ b/README @@ -158,6 +158,10 @@ New cvars com_maxfpsMinimized - Maximum frames per second when minimized com_busyWait - Will use a busy loop to wait for rendering next frame when set to non-zero value + com_pipefile - Specify filename to create a named pipe + through which other processes can control + the server while it is running. + Nonfunctional on Windows. in_joystickNo - select which joystick to use in_availableJoysticks - list of available Joysticks diff --git a/code/qcommon/common.c b/code/qcommon/common.c index ff0b2a8a..498614fc 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -50,6 +50,7 @@ jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame FILE *debuglogfile; +static fileHandle_t pipefile; static fileHandle_t logfile; fileHandle_t com_journalFile; // events are written here fileHandle_t com_journalDataFile; // config files are written here @@ -66,6 +67,7 @@ cvar_t *com_timedemo; cvar_t *com_sv_running; cvar_t *com_cl_running; cvar_t *com_logfile; // 1 = buffer log, 2 = flush after each print +cvar_t *com_pipefile; cvar_t *com_showtrace; cvar_t *com_version; cvar_t *com_blood; @@ -2768,9 +2770,36 @@ void Com_Init( char *commandLine ) { Com_Printf ("Altivec support is %s\n", com_altivec->integer ? "enabled" : "disabled"); #endif + com_pipefile = Cvar_Get( "com_pipefile", "", CVAR_ARCHIVE|CVAR_LATCH ); + if( com_pipefile->string[0] ) + { + pipefile = FS_FCreateOpenPipeFile( com_pipefile->string ); + } + Com_Printf ("--- Common Initialization Complete ---\n"); } +/* +=============== +Com_ReadFromPipe + +Read whatever is in com_pipefile, if anything, and execute it +=============== +*/ +void Com_ReadFromPipe( void ) +{ + char buffer[MAX_STRING_CHARS] = {""}; + qboolean read; + + if( !pipefile ) + return; + + read = FS_Read( buffer, sizeof( buffer ), pipefile ); + if( read ) + Cbuf_ExecuteText( EXEC_APPEND, buffer ); +} + + //================================================================== void Com_WriteConfigToFile( const char *filename ) { @@ -3097,6 +3126,8 @@ void Com_Frame( void ) { c_pointcontents = 0; } + Com_ReadFromPipe( ); + com_frameNumber++; } @@ -3116,6 +3147,11 @@ void Com_Shutdown (void) { com_journalFile = 0; } + if( pipefile ) { + FS_FCloseFile( pipefile ); + FS_HomeRemove( com_pipefile->string ); + } + } //------------------------------------------------------------------------ diff --git a/code/qcommon/files.c b/code/qcommon/files.c index 7faea751..3256b449 100644 --- a/code/qcommon/files.c +++ b/code/qcommon/files.c @@ -905,6 +905,50 @@ fileHandle_t FS_FOpenFileAppend( const char *filename ) { return f; } +/* +=========== +FS_FCreateOpenPipeFile + +=========== +*/ +fileHandle_t FS_FCreateOpenPipeFile( const char *filename ) { + char *ospath; + FILE *fifo; + fileHandle_t f; + + if ( !fs_searchpaths ) { + Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" ); + } + + f = FS_HandleForFile(); + fsh[f].zipFile = qfalse; + + Q_strncpyz( fsh[f].name, filename, sizeof( fsh[f].name ) ); + + // don't let sound stutter + S_ClearSoundBuffer(); + + ospath = FS_BuildOSPath( fs_homepath->string, fs_gamedir, filename ); + + if ( fs_debug->integer ) { + Com_Printf( "FS_FCreateOpenPipeFile: %s\n", ospath ); + } + + FS_CheckFilenameIsNotExecutable( ospath, __func__ ); + + fifo = Sys_Mkfifo( ospath ); + if( fifo ) { + fsh[f].handleFiles.file.o = fifo; + fsh[f].handleSync = qfalse; + } + else + { + f = 0; + } + + return f; +} + /* =========== FS_FilenameCompare diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 17f997ab..e45dbb5e 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -626,6 +626,7 @@ int FS_GetModList( char *listbuf, int bufsize ); fileHandle_t FS_FOpenFileWrite( const char *qpath ); fileHandle_t FS_FOpenFileAppend( const char *filename ); +fileHandle_t FS_FCreateOpenPipeFile( const char *filename ); // will properly create any needed paths and deal with seperater character issues fileHandle_t FS_SV_FOpenFileWrite( const char *filename ); @@ -1094,6 +1095,7 @@ qboolean Sys_IsLANAddress (netadr_t adr); void Sys_ShowIP(void); qboolean Sys_Mkdir( const char *path ); +FILE *Sys_Mkfifo( const char *ospath ); char *Sys_Cwd( void ); void Sys_SetDefaultInstallPath(const char *path); char *Sys_DefaultInstallPath(void); diff --git a/code/sys/sys_unix.c b/code/sys/sys_unix.c index c1bdcab1..af9d59a2 100644 --- a/code/sys/sys_unix.c +++ b/code/sys/sys_unix.c @@ -247,6 +247,31 @@ qboolean Sys_Mkdir( const char *path ) return qtrue; } +/* +================== +Sys_Mkfifo +================== +*/ +FILE *Sys_Mkfifo( const char *ospath ) +{ + FILE *fifo; + int result; + int fn; + + result = mkfifo( ospath, 0600 ); + if( result != 0 ) + return NULL; + + fifo = fopen( ospath, "w+" ); + if( fifo ) + { + fn = fileno( fifo ); + fcntl( fn, F_SETFL, O_NONBLOCK ); + } + + return fifo; +} + /* ================== Sys_Cwd diff --git a/code/sys/sys_win32.c b/code/sys/sys_win32.c index c0568e7a..db3399c7 100644 --- a/code/sys/sys_win32.c +++ b/code/sys/sys_win32.c @@ -320,6 +320,17 @@ qboolean Sys_Mkdir( const char *path ) return qtrue; } +/* +================== +Sys_Mkfifo +Noop on windows because named pipes do not function the same way +================== +*/ +FILE *Sys_Mkfifo( const char *ospath ) +{ + return NULL; +} + /* ============== Sys_Cwd