00001 #ifndef __PROCESS_ABSTRACTION_CPP__
00002 #define __PROCESS_ABSTRACTION_CPP__
00003
00004 #include <system/process_abstraction.h>
00005 #include <utilities/exception.h>
00006 #include <utilities/nwindows.h>
00007 #include <utilities/string_utilities.h>
00008
00009 #if defined( CYGWIN_PLATFORM ) || defined( NIX_PLATFORM )
00010 #include <unistd.h>
00011 #include <signal.h>
00012 #include <sys/wait.h>
00013 #include <sys/types.h>
00014 #endif
00015
00016 #include <iostream>
00017
00018 namespace nitro
00019 {
00020
00021 #if defined( WIN32_PLATFORM ) || defined( MINGW_PLATFORM )
00022 struct ProcessInfo{
00023 STARTUPINFO si;
00024 PROCESS_INFORMATION pi;
00025 };
00026 #endif
00027
00028 ProcessAbstraction::ProcessAbstraction( void )
00029 {
00030 try
00031 {
00032 }
00033 catch( nitro::exception e )
00034 {
00035 throw( nitro::exception( std::string( "ProcessAbstraction::ProcessAbstraction( void )::" ) + e.what() , e.code() ) );
00036 }
00037 catch( ... )
00038 {
00039 throw( nitro::exception( std::string( "ProcessAbstraction::ProcessAbstraction( void )::An error occured" ) , 0 ) );
00040 }
00041 }
00042
00043 void ProcessAbstraction::CreateProcess( const char * Command , const char * argv [] )
00044 {
00045 try
00046 {
00047 #if defined( WIN32_PLATFORM ) || defined( MINGW_PLATFORM )
00048 ProcessHandle = new ProcessInfo;
00049 ZeroMemory( &( ( ( ProcessInfo * )ProcessHandle )->si ) , sizeof( ( ( ProcessInfo * )ProcessHandle )->si ) );
00050 ( ( ProcessInfo * )ProcessHandle )->si.cb = sizeof( ( ( ProcessInfo * )ProcessHandle )->si );
00051 ZeroMemory( &( ( ( ProcessInfo * )ProcessHandle )->pi ) , sizeof( ( ( ProcessInfo * )ProcessHandle )->pi ) );
00052
00053 std::string CommandLine( Command );
00054
00055 for( std::size_t i( 0 ) ; argv && argv[ i ] ; i++ )
00056 {
00057 CommandLine += " ";
00058 CommandLine += argv[ i ];
00059 }
00060
00061 if( !CreateProcessA( NULL , ( LPSTR )CommandLine.c_str() , NULL , NULL , FALSE , 0 , NULL , NULL , &( ( ( ProcessInfo * )ProcessHandle )->si ) , &( ( ( ProcessInfo * )ProcessHandle )->pi ) ) )
00062 {
00063 throw( nitro::exception( std::string( "An error occured while process startup " ) + Command , 0 ) );
00064 }
00065 #endif
00066
00067 #if defined( NIX_PLATFORM ) || defined( CYGWIN_PLATFORM )
00068 ProcessHandle = new int;
00069
00070 *( ( int * )ProcessHandle ) = fork();
00071
00072 if( *( ( int * )ProcessHandle ) == 0 )
00073 {
00074 std::size_t ArgCounter( 0 );
00075 if( argv )
00076 {
00077 for( ; argv[ ArgCounter ] != NULL ; ArgCounter++ );
00078 }
00079
00080 DEFINE_DYNAMIC_ARRAY( const char * , Args , ArgCounter + 2 )
00081
00082 std::string FileName( FSPath::ExtractFileName( std::string( Command ) ) );
00083 Args[ 0 ] = FileName.c_str();
00084
00085 for( std::size_t i( 1 ) ; i < ArgCounter + 2 ; i++ )
00086 {
00087 if( argv )
00088 {
00089 Args[ i ] = argv[ i - 1 ];
00090 }
00091 else
00092 {
00093 Args[ i ] = NULL;
00094 }
00095 }
00096
00097 if( strchr( Command , '/' ) || strchr( Command , '\\' ) )
00098 {
00099
00100 if( execv( Command , ( char * const * )Args ) == -1 )
00101 {
00102 throw( nitro::exception( std::string( "An error occured while process startup " ) + Command , 0 ) );
00103 }
00104 }
00105 else
00106 {
00107
00108 if( execvp( Command , ( char * const * )Args ) == -1 )
00109 {
00110 throw( nitro::exception( std::string( "An error occured while process startup " ) + Command , 0 ) );
00111 }
00112 }
00113 }
00114 #endif
00115 }
00116 catch( nitro::exception e )
00117 {
00118 throw( nitro::exception( std::string( "ProcessAbstraction::CreateProcess( const char * Command , const char * argv [] )::" ) + e.what() , e.code() ) );
00119 }
00120 catch( ... )
00121 {
00122 throw( nitro::exception( std::string( "ProcessAbstraction::CreateProcess( const char * Command , const char * argv [] )::An error occured" ) , 0 ) );
00123 }
00124 }
00125
00126 void ProcessAbstraction::CreateProcess( const std::string & Command , const char * argv [] )
00127 {
00128 try
00129 {
00130 CreateProcess( Command.c_str() , argv );
00131 }
00132 catch( nitro::exception e )
00133 {
00134 throw( nitro::exception( std::string( "ProcessAbstraction::CreateProcess( const std::string & Command , const char * argv [] /* = NULL */ )::" ) + e.what() , e.code() ) );
00135 }
00136 catch( ... )
00137 {
00138 throw( nitro::exception( std::string( "ProcessAbstraction::CreateProcess( const std::string & Command , const char * argv [] /* = NULL */ )::An error occured" ) , 0 ) );
00139 }
00140 }
00141
00142 void ProcessAbstraction::Wait( void )
00143 {
00144 try
00145 {
00146 #if defined( WIN32_PLATFORM ) || defined( MINGW_PLATFORM )
00147 WaitForSingleObject( ( ( ProcessInfo * )ProcessHandle )->pi.hProcess, INFINITE );
00148
00149 CloseHandle( ( ( ProcessInfo * )ProcessHandle )->pi.hProcess );
00150 CloseHandle( ( ( ProcessInfo * )ProcessHandle )->pi.hThread );
00151 #endif
00152
00153 #if defined( NIX_PLATFORM ) || defined( CYGWIN_PLATFORM )
00154 waitpid( *( ( int * )ProcessHandle ) , NULL , WUNTRACED );
00155 #endif
00156 }
00157 catch( nitro::exception e )
00158 {
00159 throw( nitro::exception( std::string( "ProcessAbstraction::Wait( void )::" ) + e.what() , e.code() ) );
00160 }
00161 catch( ... )
00162 {
00163 throw( nitro::exception( std::string( "ProcessAbstraction::Wait( void )::An error occured" ) , 0 ) );
00164 }
00165 }
00166
00167 void ProcessAbstraction::TerminateProcess( void )
00168 {
00169 try
00170 {
00171 #if defined( WIN32_PLATFORM ) || defined( MINGW_PLATFORM )
00172 if( ::TerminateProcess( ( ( ProcessInfo * )ProcessHandle )->pi.hProcess, 0 ) == 0 )
00173 {
00174 throw( nitro::exception( "An error occured while process termination" , 1 ) );
00175 }
00176
00177 CloseHandle( ( ( ProcessInfo * )ProcessHandle )->pi.hProcess );
00178 CloseHandle( ( ( ProcessInfo * )ProcessHandle )->pi.hThread );
00179 #endif
00180
00181 #if defined( NIX_PLATFORM ) || defined( CYGWIN_PLATFORM )
00182 if( kill( *( ( int * )ProcessHandle ) , SIGKILL ) != 0 )
00183 {
00184 throw( nitro::exception( "An error occured while process termination" , 1 ) );
00185 }
00186 #endif
00187 }
00188 catch( nitro::exception e )
00189 {
00190 throw( nitro::exception( std::string( "ProcessAbstraction::Wait( void )::" ) + e.what() , e.code() ) );
00191 }
00192 catch( ... )
00193 {
00194 throw( nitro::exception( std::string( "ProcessAbstraction::Wait( void )::An error occured" ) , 0 ) );
00195 }
00196 }
00197
00198 ProcessAbstraction::~ProcessAbstraction()
00199 {
00200 try
00201 {
00202 #if defined( WIN32_PLATFORM ) || defined( MINGW_PLATFORM )
00203 delete ( ProcessInfo * )ProcessHandle;
00204 #endif
00205
00206 #if defined( NIX_PLATFORM ) || defined( CYGWIN_PLATFORM )
00207 delete ( int * )ProcessHandle;
00208 #endif
00209 }
00210 catch( ... )
00211 {
00212 }
00213 }
00214
00215 ProcessAbstraction::ProcessAbstraction( const ProcessAbstraction & )
00216 {
00217 try
00218 {
00219 }
00220 catch( nitro::exception e )
00221 {
00222 throw( nitro::exception( std::string( "ProcessAbstraction::ProcessAbstraction( const ProcessAbstraction & )::" ) + e.what() , e.code() ) );
00223 }
00224 catch( ... )
00225 {
00226 throw( nitro::exception( std::string( "ProcessAbstraction::ProcessAbstraction( const ProcessAbstraction & )::An error occured" ) , 0 ) );
00227 }
00228 }
00229
00230 ProcessAbstraction ProcessAbstraction::operator=( const ProcessAbstraction & )
00231 {
00232 try
00233 {
00234 return( *this );
00235 }
00236 catch( nitro::exception e )
00237 {
00238 throw( nitro::exception( std::string( "ProcessAbstraction::operator=( const ProcessAbstraction & )::" ) + e.what() , e.code() ) );
00239 }
00240 catch( ... )
00241 {
00242 throw( nitro::exception( std::string( "ProcessAbstraction::operator=( const ProcessAbstraction & )::An error occured" ) , 0 ) );
00243 }
00244 }
00245
00246
00247
00248
00249 BEGIN_TESTING_SECTION()
00250
00251 ENABLE_CLASS_TESTING( ProcessAbstraction )
00252
00253 CLASS_MEMBER_FUNCTION_TESTING_2( ProcessAbstraction , aliasCreateProcess , tstCreateProcess , const char * , const char ** , void , NO_RET )
00254 CLASS_MEMBER_FUNCTION_TESTING_0( ProcessAbstraction , Wait , tstWait , void , NO_RET )
00255 CLASS_MEMBER_FUNCTION_TESTING_0( ProcessAbstraction , TerminateProcess , tstTerminateProcess , void , NO_RET )
00256
00257 #if defined( ENABLE_AUTOTESTING )
00258 NITRO_EXPORTING void tstCreateProcessUtil( const char * ObjectName , const char * ModuleName , const char * FirstParameter )
00259 {
00260 const char * Args[ 2 ];
00261 Args[ 0 ] = FirstParameter;
00262 Args[ 1 ] = NULL;
00263
00264 tstCreateProcess( ObjectName , ModuleName , ( const char * * )Args );
00265 }
00266 #endif
00267
00268 END_TESTING_SECTION()
00269 }
00270
00271 #endif