* Replace usage of system with fork/exec

This commit is contained in:
Tim Angus 2011-07-24 22:01:50 +00:00
parent 1972bf97db
commit 22552c7bab

View file

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <libgen.h> #include <libgen.h>
#include <fcntl.h> #include <fcntl.h>
#include <fenv.h> #include <fenv.h>
#include <sys/wait.h>
qboolean stdinIsATTY; qboolean stdinIsATTY;
@ -550,28 +551,106 @@ void Sys_ErrorDialog( const char *error )
} }
#ifndef MACOS_X #ifndef MACOS_X
static char execBuffer[ 1024 ];
static char *execBufferPointer;
static char *execArgv[ 16 ];
static int execArgc;
/*
==============
Sys_ClearExecBuffer
==============
*/
static void Sys_ClearExecBuffer( void )
{
execBufferPointer = execBuffer;
Com_Memset( execArgv, 0, sizeof( execArgv ) );
execArgc = 0;
}
/*
==============
Sys_AppendToExecBuffer
==============
*/
static void Sys_AppendToExecBuffer( const char *text )
{
size_t size = sizeof( execBuffer ) - ( execBufferPointer - execBuffer );
int length = strlen( text ) + 1;
if( length > size || execArgc >= ARRAY_LEN( execArgv ) )
return;
Q_strncpyz( execBufferPointer, text, size );
execArgv[ execArgc++ ] = execBufferPointer;
execBufferPointer += length;
}
/*
==============
Sys_Exec
==============
*/
static int Sys_Exec( void )
{
pid_t pid = fork( );
if( pid < 0 )
return -1;
if( pid )
{
// Parent
int exitCode;
wait( &exitCode );
return WEXITSTATUS( exitCode );
}
else
{
// Child
execvp( execArgv[ 0 ], execArgv );
// Failed to execute
exit( -1 );
return -1;
}
}
/* /*
============== ==============
Sys_ZenityCommand Sys_ZenityCommand
============== ==============
*/ */
static void Sys_ZenityCommand( dialogType_t type, const char *message, const char *title, static void Sys_ZenityCommand( dialogType_t type, const char *message, const char *title )
char *command, size_t commandSize )
{ {
const char *options = ""; Sys_ClearExecBuffer( );
Sys_AppendToExecBuffer( "zenity" );
switch( type ) switch( type )
{ {
default: default:
case DT_INFO: options = "--info"; break; case DT_INFO: Sys_AppendToExecBuffer( "--info" ); break;
case DT_WARNING: options = "--warning"; break; case DT_WARNING: Sys_AppendToExecBuffer( "--warning" ); break;
case DT_ERROR: options = "--error"; break; case DT_ERROR: Sys_AppendToExecBuffer( "--error" ); break;
case DT_YES_NO: options = "--question --ok-label=\"Yes\" --cancel-label=\"No\""; break; case DT_YES_NO:
case DT_OK_CANCEL: options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\""; break; Sys_AppendToExecBuffer( "--question" );
Sys_AppendToExecBuffer( "--ok-label=Yes" );
Sys_AppendToExecBuffer( "--cancel-label=No" );
break;
case DT_OK_CANCEL:
Sys_AppendToExecBuffer( "--question" );
Sys_AppendToExecBuffer( "--ok-label=OK" );
Sys_AppendToExecBuffer( "--cancel-label=Cancel" );
break;
} }
Com_sprintf( command, commandSize, "zenity %s --text=\"%s\" --title=\"%s\" >/dev/null 2>/dev/null", Sys_AppendToExecBuffer( va( "--text=%s", message ) );
options, message, title ); Sys_AppendToExecBuffer( va( "--title=%s", title ) );
} }
/* /*
@ -579,23 +658,23 @@ static void Sys_ZenityCommand( dialogType_t type, const char *message, const cha
Sys_KdialogCommand Sys_KdialogCommand
============== ==============
*/ */
static void Sys_KdialogCommand( dialogType_t type, const char *message, const char *title, static void Sys_KdialogCommand( dialogType_t type, const char *message, const char *title )
char *command, size_t commandSize )
{ {
const char *options = ""; Sys_ClearExecBuffer( );
Sys_AppendToExecBuffer( "kdialog" );
switch( type ) switch( type )
{ {
default: default:
case DT_INFO: options = "--msgbox"; break; case DT_INFO: Sys_AppendToExecBuffer( "--msgbox" ); break;
case DT_WARNING: options = "--sorry"; break; case DT_WARNING: Sys_AppendToExecBuffer( "--sorry" ); break;
case DT_ERROR: options = "--error"; break; case DT_ERROR: Sys_AppendToExecBuffer( "--error" ); break;
case DT_YES_NO: options = "--warningyesno"; break; case DT_YES_NO: Sys_AppendToExecBuffer( "--warningyesno" ); break;
case DT_OK_CANCEL: options = "--warningcontinuecancel"; break; case DT_OK_CANCEL: Sys_AppendToExecBuffer( "--warningcontinuecancel" ); break;
} }
Com_sprintf( command, commandSize, "kdialog %s \"%s\" --title \"%s\" >/dev/null 2>/dev/null", Sys_AppendToExecBuffer( message );
options, message, title ); Sys_AppendToExecBuffer( va( "--title=%s", title ) );
} }
/* /*
@ -603,20 +682,21 @@ static void Sys_KdialogCommand( dialogType_t type, const char *message, const ch
Sys_XmessageCommand Sys_XmessageCommand
============== ==============
*/ */
static void Sys_XmessageCommand( dialogType_t type, const char *message, const char *title, static void Sys_XmessageCommand( dialogType_t type, const char *message, const char *title )
char *command, size_t commandSize )
{ {
const char *options = ""; Sys_ClearExecBuffer( );
Sys_AppendToExecBuffer( "xmessage" );
Sys_AppendToExecBuffer( "-buttons" );
switch( type ) switch( type )
{ {
default: options = "-buttons OK:0"; break; default: Sys_AppendToExecBuffer( "OK:0" ); break;
case DT_YES_NO: options = "-buttons Yes:0,No:1"; break; case DT_YES_NO: Sys_AppendToExecBuffer( "Yes:0,No:1" ); break;
case DT_OK_CANCEL: options = "-buttons OK:0,Cancel:1"; break; case DT_OK_CANCEL: Sys_AppendToExecBuffer( "OK:0,Cancel:1" ); break;
} }
Com_sprintf( command, commandSize, "xmessage -center %s \"%s\" >/dev/null 2>/dev/null", Sys_AppendToExecBuffer( "-center" );
options, message ); Sys_AppendToExecBuffer( message );
} }
/* /*
@ -636,7 +716,7 @@ dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *t
XMESSAGE, XMESSAGE,
NUM_DIALOG_PROGRAMS NUM_DIALOG_PROGRAMS
} dialogCommandType_t; } dialogCommandType_t;
typedef void (*dialogCommandBuilder_t)( dialogType_t, const char *, const char *, char *, size_t ); typedef void (*dialogCommandBuilder_t)( dialogType_t, const char *, const char * );
const char *session = getenv( "DESKTOP_SESSION" ); const char *session = getenv( "DESKTOP_SESSION" );
qboolean tried[ NUM_DIALOG_PROGRAMS ] = { qfalse }; qboolean tried[ NUM_DIALOG_PROGRAMS ] = { qfalse };
@ -665,21 +745,16 @@ dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *t
if( !tried[ i ] ) if( !tried[ i ] )
{ {
int exitCode; int exitCode;
int childSignal;
int childCode;
char command[ 1024 ];
commands[ i ]( type, message, title, command, sizeof( command ) ); commands[ i ]( type, message, title );
exitCode = system( command ); exitCode = Sys_Exec( );
childSignal = exitCode & 127;
childCode = exitCode >> 8;
if( exitCode != -1 && childSignal == 0 && childCode != 126 && childCode != 127 ) if( exitCode >= 0 )
{ {
switch( type ) switch( type )
{ {
case DT_YES_NO: return childCode ? DR_NO : DR_YES; case DT_YES_NO: return exitCode ? DR_NO : DR_YES;
case DT_OK_CANCEL: return childCode ? DR_CANCEL : DR_OK; case DT_OK_CANCEL: return exitCode ? DR_CANCEL : DR_OK;
default: return DR_OK; default: return DR_OK;
} }
} }