Line data Source code
1 : /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
2 : * 2012, 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 : LBINFO << "Executing: " << stringStream.str() << std::endl;
113 : //::exit( EXIT_SUCCESS );
114 0 : int nTries = 10;
115 0 : while( nTries-- )
116 : {
117 0 : execvp( argv[0], &argv[0] );
118 0 : LBWARN << "Error executing '" << argv[0] << "': " << sysError
119 0 : << std::endl;
120 0 : if( errno != ETXTBSY )
121 0 : break;
122 : }
123 :
124 0 : ::exit( EXIT_FAILURE );
125 0 : return true; // not reached
126 : #endif
127 : }
128 :
129 : #ifndef _WIN32
130 0 : void Launcher::_buildCommandLine( const std::string& command,
131 : std::vector<std::string>& commandLine )
132 : {
133 0 : const size_t length = command.size();
134 0 : const char* string = command.c_str();
135 0 : bool inTicks = false;
136 0 : size_t bufferPos = 0;
137 0 : std::vector<char> buffer( length + 1 );
138 :
139 0 : commandLine.clear();
140 :
141 : // tokenize command line
142 0 : for( size_t i=0; i<length; i++ )
143 : {
144 0 : const char c = string[i];
145 0 : switch( c )
146 : {
147 : case ' ':
148 0 : if( inTicks )
149 0 : buffer[bufferPos++] = c;
150 : else
151 : {
152 0 : buffer[bufferPos] = '\0';
153 0 : commandLine.push_back( &buffer[0] );
154 0 : bufferPos = 0;
155 : }
156 0 : break;
157 :
158 : case '"':
159 0 : inTicks = !inTicks;
160 0 : break;
161 :
162 : case '\\':
163 0 : i++;
164 0 : buffer[bufferPos++] = string[i];
165 0 : break;
166 :
167 : default:
168 0 : buffer[bufferPos++] = c;
169 0 : break;
170 : }
171 : }
172 :
173 0 : if( bufferPos > 0 )
174 : {
175 0 : buffer[bufferPos++] = '\0';
176 0 : commandLine.push_back( &buffer[0] );
177 0 : }
178 0 : }
179 : #endif
180 :
181 90 : }
|