Line data Source code
1 : /* Copyright (c) 2005-2016, Stefan Eilemann <eile@equalizergraphics.com>
2 : * Daniel Nachbaur <danielnachbaur@gmail.com>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #include "launcher.h"
19 :
20 : #include "debug.h"
21 : #include "log.h"
22 : #include "os.h"
23 :
24 : #include <errno.h>
25 : #include <string.h>
26 : #include <signal.h>
27 : #include <sstream>
28 :
29 : #ifdef _WIN32
30 : # include <io.h>
31 : #else
32 : # include <unistd.h>
33 : # include <sys/wait.h>
34 : #endif
35 :
36 : namespace lunchbox
37 : {
38 :
39 0 : bool Launcher::run( const std::string& command )
40 : {
41 0 : if( command.empty( ))
42 0 : return false;
43 :
44 : #ifdef _WIN32
45 :
46 : STARTUPINFO startupInfo;
47 : ZeroMemory( &startupInfo, sizeof( STARTUPINFO ));
48 :
49 : PROCESS_INFORMATION procInfo;
50 : ZeroMemory( &procInfo, sizeof( PROCESS_INFORMATION ));
51 :
52 : const char* cmdLine = command.c_str();
53 :
54 : startupInfo.cb = sizeof( STARTUPINFO );
55 : const bool success =
56 : CreateProcess( 0, LPSTR( cmdLine ), // program, command line
57 : 0, 0, // process, thread attributes
58 : FALSE, // inherit handles
59 : 0, // creation flags
60 : 0, // environment
61 : 0, // current directory
62 : &startupInfo,
63 : &procInfo );
64 :
65 : if( !success )
66 : {
67 : LBERROR << "CreateProcess failed: " << sysError << std::endl;
68 : return false;
69 : }
70 :
71 : //WaitForInputIdle( procInfo.hProcess, 1000 );
72 : CloseHandle( procInfo.hProcess );
73 : CloseHandle( procInfo.hThread );
74 : return true;
75 : #else
76 0 : std::vector<std::string> commandLine;
77 0 : _buildCommandLine( command, commandLine );
78 :
79 : struct sigaction act;
80 0 : setZero( &act, sizeof( act ));
81 0 : act.sa_handler = SIG_DFL;
82 0 : act.sa_flags = SA_NOCLDWAIT;
83 0 : ::sigaction( SIGCHLD, &act, &act );
84 :
85 0 : const int result = fork();
86 0 : switch( result )
87 : {
88 : case 0: // child
89 0 : break;
90 :
91 : case -1: // error
92 0 : LBWARN << "Could not fork child process:" << sysError << std::endl;
93 0 : return false;
94 :
95 : default: // parent
96 0 : return true;
97 : }
98 :
99 : // child
100 0 : const size_t argc = commandLine.size();
101 0 : std::vector<char*> argv( argc + 1 );
102 0 : std::ostringstream stringStream;
103 :
104 0 : for( size_t i=0; i<argc; i++ )
105 : {
106 0 : argv[i] = (char*)commandLine[i].c_str();
107 0 : stringStream << commandLine[i] << " ";
108 : }
109 :
110 0 : argv[ argc ] = 0;
111 :
112 0 : LBDEBUG << "Executing: " << stringStream.str() << std::endl;
113 0 : int nTries = 10;
114 0 : while( nTries-- )
115 : {
116 0 : execvp( argv[0], &argv[0] );
117 0 : LBWARN << "Error executing '" << argv[0] << "': " << sysError
118 0 : << std::endl;
119 0 : if( errno != ETXTBSY )
120 0 : break;
121 : }
122 :
123 0 : ::exit( EXIT_FAILURE );
124 : return true; // not reached
125 : #endif
126 : }
127 :
128 : #ifndef _WIN32
129 0 : void Launcher::_buildCommandLine( const std::string& command,
130 : std::vector<std::string>& commandLine )
131 : {
132 0 : const size_t length = command.size();
133 0 : const char* string = command.c_str();
134 0 : bool inTicks = false;
135 0 : size_t bufferPos = 0;
136 0 : std::vector<char> buffer( length + 1 );
137 :
138 0 : commandLine.clear();
139 :
140 : // tokenize command line
141 0 : for( size_t i=0; i<length; i++ )
142 : {
143 0 : const char c = string[i];
144 0 : switch( c )
145 : {
146 : case ' ':
147 0 : if( inTicks )
148 0 : buffer[bufferPos++] = c;
149 : else
150 : {
151 0 : buffer[bufferPos] = '\0';
152 0 : commandLine.push_back( &buffer[0] );
153 0 : bufferPos = 0;
154 : }
155 0 : break;
156 :
157 : case '"':
158 0 : inTicks = !inTicks;
159 0 : break;
160 :
161 : case '\\':
162 0 : i++;
163 0 : buffer[bufferPos++] = string[i];
164 0 : break;
165 :
166 : default:
167 0 : buffer[bufferPos++] = c;
168 0 : break;
169 : }
170 : }
171 :
172 0 : if( bufferPos > 0 )
173 : {
174 0 : buffer[bufferPos++] = '\0';
175 0 : commandLine.push_back( &buffer[0] );
176 : }
177 0 : }
178 : #endif
179 :
180 72 : }
|