summaryrefslogtreecommitdiff
path: root/src/sys/sys_unix.c
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2011-07-24 22:01:50 +0000
committerTim Angus <tim@ngus.net>2013-01-10 22:33:36 +0000
commitc35b7fdd51b90101ec54afe83a91a9454d56af49 (patch)
treee8c8df6daf8a1c3a48995b1dc7e9d205bff085a5 /src/sys/sys_unix.c
parent0924ab7ab33596b30471bb70fc5f3f19329b0b37 (diff)
* Replace usage of system with fork/exec
Diffstat (limited to 'src/sys/sys_unix.c')
-rw-r--r--src/sys/sys_unix.c153
1 files changed, 114 insertions, 39 deletions
diff --git a/src/sys/sys_unix.c b/src/sys/sys_unix.c
index 7cc082ca..b72c91d7 100644
--- a/src/sys/sys_unix.c
+++ b/src/sys/sys_unix.c
@@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <libgen.h>
#include <fcntl.h>
#include <fenv.h>
+#include <sys/wait.h>
qboolean stdinIsATTY;
@@ -543,28 +544,106 @@ void Sys_ErrorDialog( const char *error )
}
#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
==============
*/
-static void Sys_ZenityCommand( dialogType_t type, const char *message, const char *title,
- char *command, size_t commandSize )
+static void Sys_ZenityCommand( dialogType_t type, const char *message, const char *title )
{
- const char *options = "";
+ Sys_ClearExecBuffer( );
+ Sys_AppendToExecBuffer( "zenity" );
switch( type )
{
default:
- case DT_INFO: options = "--info"; break;
- case DT_WARNING: options = "--warning"; break;
- case DT_ERROR: options = "--error"; break;
- case DT_YES_NO: options = "--question --ok-label=\"Yes\" --cancel-label=\"No\""; break;
- case DT_OK_CANCEL: options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\""; break;
+ case DT_INFO: Sys_AppendToExecBuffer( "--info" ); break;
+ case DT_WARNING: Sys_AppendToExecBuffer( "--warning" ); break;
+ case DT_ERROR: Sys_AppendToExecBuffer( "--error" ); break;
+ case DT_YES_NO:
+ 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",
- options, message, title );
+ Sys_AppendToExecBuffer( va( "--text=%s", message ) );
+ Sys_AppendToExecBuffer( va( "--title=%s", title ) );
}
/*
@@ -572,23 +651,23 @@ static void Sys_ZenityCommand( dialogType_t type, const char *message, const cha
Sys_KdialogCommand
==============
*/
-static void Sys_KdialogCommand( dialogType_t type, const char *message, const char *title,
- char *command, size_t commandSize )
+static void Sys_KdialogCommand( dialogType_t type, const char *message, const char *title )
{
- const char *options = "";
+ Sys_ClearExecBuffer( );
+ Sys_AppendToExecBuffer( "kdialog" );
switch( type )
{
default:
- case DT_INFO: options = "--msgbox"; break;
- case DT_WARNING: options = "--sorry"; break;
- case DT_ERROR: options = "--error"; break;
- case DT_YES_NO: options = "--warningyesno"; break;
- case DT_OK_CANCEL: options = "--warningcontinuecancel"; break;
+ case DT_INFO: Sys_AppendToExecBuffer( "--msgbox" ); break;
+ case DT_WARNING: Sys_AppendToExecBuffer( "--sorry" ); break;
+ case DT_ERROR: Sys_AppendToExecBuffer( "--error" ); break;
+ case DT_YES_NO: Sys_AppendToExecBuffer( "--warningyesno" ); break;
+ case DT_OK_CANCEL: Sys_AppendToExecBuffer( "--warningcontinuecancel" ); break;
}
- Com_sprintf( command, commandSize, "kdialog %s \"%s\" --title \"%s\" >/dev/null 2>/dev/null",
- options, message, title );
+ Sys_AppendToExecBuffer( message );
+ Sys_AppendToExecBuffer( va( "--title=%s", title ) );
}
/*
@@ -596,20 +675,21 @@ static void Sys_KdialogCommand( dialogType_t type, const char *message, const ch
Sys_XmessageCommand
==============
*/
-static void Sys_XmessageCommand( dialogType_t type, const char *message, const char *title,
- char *command, size_t commandSize )
+static void Sys_XmessageCommand( dialogType_t type, const char *message, const char *title )
{
- const char *options = "";
+ Sys_ClearExecBuffer( );
+ Sys_AppendToExecBuffer( "xmessage" );
+ Sys_AppendToExecBuffer( "-buttons" );
switch( type )
{
- default: options = "-buttons OK:0"; break;
- case DT_YES_NO: options = "-buttons Yes:0,No:1"; break;
- case DT_OK_CANCEL: options = "-buttons OK:0,Cancel:1"; break;
+ default: Sys_AppendToExecBuffer( "OK:0" ); break;
+ case DT_YES_NO: Sys_AppendToExecBuffer( "Yes:0,No: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",
- options, message );
+ Sys_AppendToExecBuffer( "-center" );
+ Sys_AppendToExecBuffer( message );
}
/*
@@ -629,7 +709,7 @@ dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *t
XMESSAGE,
NUM_DIALOG_PROGRAMS
} 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" );
qboolean tried[ NUM_DIALOG_PROGRAMS ] = { qfalse };
@@ -658,21 +738,16 @@ dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *t
if( !tried[ i ] )
{
int exitCode;
- int childSignal;
- int childCode;
- char command[ 1024 ];
- commands[ i ]( type, message, title, command, sizeof( command ) );
- exitCode = system( command );
- childSignal = exitCode & 127;
- childCode = exitCode >> 8;
+ commands[ i ]( type, message, title );
+ exitCode = Sys_Exec( );
- if( exitCode != -1 && childSignal == 0 && childCode != 126 && childCode != 127 )
+ if( exitCode >= 0 )
{
switch( type )
{
- case DT_YES_NO: return childCode ? DR_NO : DR_YES;
- case DT_OK_CANCEL: return childCode ? DR_CANCEL : DR_OK;
+ case DT_YES_NO: return exitCode ? DR_NO : DR_YES;
+ case DT_OK_CANCEL: return exitCode ? DR_CANCEL : DR_OK;
default: return DR_OK;
}
}