8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "PosixPlatform.h"
27
28 #ifdef POSIX
29
30 #include "PlatformString.h"
31 #include "FilePath.h"
32 #include "Helpers.h"
33
34 #include <assert.h>
35 #include <stdbool.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <sys/sysctl.h>
39 #include <sys/file.h>
40 #include <sys/stat.h>
41 #ifdef LINUX
42 #include <sys/wait.h>
43 #endif
44 #include <errno.h>
45 #include <limits.h>
46 #include <pwd.h>
47 #include <iostream>
48 #include <algorithm>
49 #include <dlfcn.h>
50 #include <signal.h>
51
52
53 PosixPlatform::PosixPlatform(void) {
54 }
55
56 PosixPlatform::~PosixPlatform(void) {
57 }
58
59 TString PosixPlatform::GetTempDirectory() {
60 struct passwd* pw = getpwuid(getuid());
61 TString homedir(pw->pw_dir);
62 homedir += getTmpDirString();
63 if (!FilePath::DirectoryExists(homedir)) {
64 if (!FilePath::CreateDirectory(homedir, false)) {
65 homedir.clear();
66 }
67 }
68
69 return homedir;
70 }
71
97 return result;
98 }
99
100 void PosixPlatform::SetCurrentDirectory(TString Value) {
101 chdir(StringToFileSystemString(Value));
102 }
103
104 Module PosixPlatform::LoadLibrary(TString FileName) {
105 return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
106 }
107
108 void PosixPlatform::FreeLibrary(Module AModule) {
109 dlclose(AModule);
110 }
111
112 Procedure PosixPlatform::GetProcAddress(Module AModule,
113 std::string MethodName) {
114 return dlsym(AModule, PlatformString(MethodName));
115 }
116
117 std::vector<std::string> PosixPlatform::GetLibraryImports(
118 const TString FileName) {
119 std::vector<TString> result;
120 return result;
121 }
122
123 std::vector<TString> PosixPlatform::FilterOutRuntimeDependenciesForPlatform(
124 std::vector<TString> Imports) {
125 std::vector<TString> result;
126 return result;
127 }
128
129 Process* PosixPlatform::CreateProcess() {
130 return new PosixProcess();
131 }
132
133 PosixProcess::PosixProcess() : Process() {
134 FChildPID = 0;
135 FRunning = false;
136 FOutputHandle = 0;
137 FInputHandle = 0;
138 }
139
140 PosixProcess::~PosixProcess() {
141 Terminate();
142 }
143
144 void PosixProcess::Cleanup() {
145 if (FOutputHandle != 0) {
146 close(FOutputHandle);
147 FOutputHandle = 0;
148 }
149
150 if (FInputHandle != 0) {
151 close(FInputHandle);
152 FInputHandle = 0;
153 }
154
155 #ifdef MAC
156 sigaction(SIGINT, &savintr, (struct sigaction *)0);
157 sigaction(SIGQUIT, &savequit, (struct sigaction *)0);
158 sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *)0);
159 #endif //MAC
160 }
161
162 bool PosixProcess::ReadOutput() {
163 bool result = false;
164
165 if (FOutputHandle != 0 && IsRunning() == true) {
166 char buffer[4096] = {0};
167
168 ssize_t count = read(FOutputHandle, buffer, sizeof(buffer));
169
170 if (count == -1) {
171 if (errno == EINTR) {
172 // continue;
173 } else {
174 perror("read");
175 exit(1);
176 }
177 } else if (count == 0) {
178 // break;
179 } else {
180 if (buffer[count - 1] == EOF) {
181 buffer[count - 1] = '\0';
182 }
183
184 std::list<TString> output = Helpers::StringToArray(buffer);
185 FOutput.splice(FOutput.end(), output, output.begin(), output.end());
186 result = true;
187 }
188 }
216 printf("Kill error: The value of the sig argument is an invalid or unsupported signal number.");
217 } else if (errno == EPERM) {
218 printf("Kill error: The process does not have permission to send the signal to any receiving process.");
219 } else if (errno == ESRCH) {
220 printf("Kill error: No process or process group can be found corresponding to that specified by pid.");
221 }
222 #endif // DEBUG
223 if (IsRunning() == true) {
224 status = kill(FChildPID, SIGKILL);
225
226 if (status == 0) {
227 result = true;
228 }
229 }
230 }
231 }
232
233 return result;
234 }
235
236 #define PIPE_READ 0
237 #define PIPE_WRITE 1
238
239 bool PosixProcess::Execute(const TString Application,
240 const std::vector<TString> Arguments, bool AWait) {
241 bool result = false;
242
243 if (FRunning == false) {
244 FRunning = true;
245
246 int handles[2];
247
248 if (pipe(handles) == -1) {
249 return false;
250 }
251
252 struct sigaction sa;
253 sa.sa_handler = SIG_IGN;
254 sigemptyset(&sa.sa_mask);
255 sa.sa_flags = 0;
256 #ifdef MAC
257 sigemptyset(&savintr.sa_mask);
258 sigemptyset(&savequit.sa_mask);
259 sigaction(SIGINT, &sa, &savintr);
260 sigaction(SIGQUIT, &sa, &savequit);
261 sigaddset(&sa.sa_mask, SIGCHLD);
262 sigprocmask(SIG_BLOCK, &sa.sa_mask, &saveblock);
263 #endif // MAC
264 FChildPID = fork();
265
266 // PID returned by vfork is 0 for the child process and the
267 // PID of the child process for the parent.
268 if (FChildPID == -1) {
269 // Error
270 TString message = PlatformString::Format(
271 _T("Error: Unable to create process %s"),
272 Application.data());
273 throw Exception(message);
274 }
275 else if (FChildPID == 0) {
276 Cleanup();
277 TString command = Application;
278
279 for (std::vector<TString>::const_iterator iterator =
280 Arguments.begin(); iterator != Arguments.end();
281 iterator++) {
282 command += TString(_T(" ")) + *iterator;
283 }
284 #ifdef DEBUG
285 printf("%s\n", command.data());
286 #endif // DEBUG
287
288 dup2(handles[PIPE_READ], STDIN_FILENO);
289 dup2(handles[PIPE_WRITE], STDOUT_FILENO);
290
291 close(handles[PIPE_READ]);
292 close(handles[PIPE_WRITE]);
293
294 execl("/bin/sh", "sh", "-c", command.data(), (char *)0);
295
296 _exit(127);
297 } else {
298 FOutputHandle = handles[PIPE_READ];
299 FInputHandle = handles[PIPE_WRITE];
300
301 if (AWait == true) {
302 ReadOutput();
303 Wait();
304 Cleanup();
305 FRunning = false;
306 result = true;
307 }
308 else {
309 result = true;
310 }
311 }
312 }
313
314 return result;
315 }
316
317 bool PosixProcess::Wait() {
318 bool result = false;
319
320 int status = 0;
321 pid_t wpid = 0;
322
323 #ifdef LINUX
324 wpid = wait(&status);
325 #endif
326 #ifdef MAC
327 wpid = wait(&status);
328 #endif
329
330 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
331 if (errno != EINTR){
332 status = -1;
333 }
334 }
335
336 #ifdef DEBUG
337 if (WIFEXITED(status)) {
338 printf("child exited, status=%d\n", WEXITSTATUS(status));
339 } else if (WIFSIGNALED(status)) {
340 printf("child killed (signal %d)\n", WTERMSIG(status));
341 } else if (WIFSTOPPED(status)) {
342 printf("child stopped (signal %d)\n", WSTOPSIG(status));
343 #ifdef WIFCONTINUED // Not all implementations support this
344 } else if (WIFCONTINUED(status)) {
345 printf("child continued\n");
346 #endif // WIFCONTINUED
347 } else { // Non-standard case -- may never happen
348 printf("Unexpected status (0x%x)\n", status);
349 }
350 #endif // DEBUG
351
353 result = true;
354 }
355
356 return result;
357 }
358
359 TProcessID PosixProcess::GetProcessID() {
360 return FChildPID;
361 }
362
363 void PosixProcess::SetInput(TString Value) {
364 if (FInputHandle != 0) {
365 write(FInputHandle, Value.data(), Value.size());
366 }
367 }
368
369 std::list<TString> PosixProcess::GetOutput() {
370 ReadOutput();
371 return Process::GetOutput();
372 }
373
374 #endif // POSIX
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "PosixPlatform.h"
27
28 #include "PlatformString.h"
29 #include "FilePath.h"
30 #include "Helpers.h"
31
32 #include <assert.h>
33 #include <stdbool.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 #include <sys/sysctl.h>
37 #include <sys/file.h>
38 #include <sys/stat.h>
39 #include <sys/wait.h>
40 #include <errno.h>
41 #include <limits.h>
42 #include <pwd.h>
43 #include <iostream>
44 #include <algorithm>
45 #include <dlfcn.h>
46 #include <signal.h>
47
48 using namespace std;
49
50 PosixPlatform::PosixPlatform(void) {
51 }
52
53 PosixPlatform::~PosixPlatform(void) {
54 }
55
56 TString PosixPlatform::GetTempDirectory() {
57 struct passwd* pw = getpwuid(getuid());
58 TString homedir(pw->pw_dir);
59 homedir += getTmpDirString();
60 if (!FilePath::DirectoryExists(homedir)) {
61 if (!FilePath::CreateDirectory(homedir, false)) {
62 homedir.clear();
63 }
64 }
65
66 return homedir;
67 }
68
94 return result;
95 }
96
97 void PosixPlatform::SetCurrentDirectory(TString Value) {
98 chdir(StringToFileSystemString(Value));
99 }
100
101 Module PosixPlatform::LoadLibrary(TString FileName) {
102 return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
103 }
104
105 void PosixPlatform::FreeLibrary(Module AModule) {
106 dlclose(AModule);
107 }
108
109 Procedure PosixPlatform::GetProcAddress(Module AModule,
110 std::string MethodName) {
111 return dlsym(AModule, PlatformString(MethodName));
112 }
113
114 Process* PosixPlatform::CreateProcess() {
115 return new PosixProcess();
116 }
117
118 void PosixPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
119 }
120
121 void Platform::CopyString(char *Destination,
122 size_t NumberOfElements, const char *Source) {
123 strncpy(Destination, Source, NumberOfElements);
124
125 if (NumberOfElements > 0) {
126 Destination[NumberOfElements - 1] = '\0';
127 }
128 }
129
130 void Platform::CopyString(wchar_t *Destination,
131 size_t NumberOfElements, const wchar_t *Source) {
132 wcsncpy(Destination, Source, NumberOfElements);
133
134 if (NumberOfElements > 0) {
135 Destination[NumberOfElements - 1] = '\0';
136 }
137 }
138
139 // Owner must free the return value.
140
141 MultibyteString Platform::WideStringToMultibyteString(
142 const wchar_t* value) {
143 MultibyteString result;
144 size_t count = 0;
145
146 if (value == NULL) {
147 return result;
148 }
149
150 count = wcstombs(NULL, value, 0);
151 if (count > 0) {
152 result.data = new char[count + 1];
153 result.data[count] = '\0';
154 result.length = count;
155 wcstombs(result.data, value, count);
156 }
157
158 return result;
159 }
160
161 // Owner must free the return value.
162
163 WideString Platform::MultibyteStringToWideString(const char* value) {
164 WideString result;
165 size_t count = 0;
166
167 if (value == NULL) {
168 return result;
169 }
170
171 count = mbstowcs(NULL, value, 0);
172 if (count > 0) {
173 result.data = new wchar_t[count + 1];
174 result.data[count] = '\0';
175 result.length = count;
176 mbstowcs(result.data, value, count);
177 }
178
179 return result;
180 }
181
182 void PosixPlatform::InitStreamLocale(wios *stream) {
183 // Nothing to do for POSIX platforms.
184 }
185
186 PosixProcess::PosixProcess() : Process() {
187 FChildPID = 0;
188 FRunning = false;
189 FOutputHandle = 0;
190 FInputHandle = 0;
191 }
192
193 PosixProcess::~PosixProcess() {
194 Terminate();
195 }
196
197 bool PosixProcess::ReadOutput() {
198 bool result = false;
199
200 if (FOutputHandle != 0 && IsRunning() == true) {
201 char buffer[4096] = {0};
202
203 ssize_t count = read(FOutputHandle, buffer, sizeof (buffer));
204
205 if (count == -1) {
206 if (errno == EINTR) {
207 // continue;
208 } else {
209 perror("read");
210 exit(1);
211 }
212 } else if (count == 0) {
213 // break;
214 } else {
215 if (buffer[count - 1] == EOF) {
216 buffer[count - 1] = '\0';
217 }
218
219 std::list<TString> output = Helpers::StringToArray(buffer);
220 FOutput.splice(FOutput.end(), output, output.begin(), output.end());
221 result = true;
222 }
223 }
251 printf("Kill error: The value of the sig argument is an invalid or unsupported signal number.");
252 } else if (errno == EPERM) {
253 printf("Kill error: The process does not have permission to send the signal to any receiving process.");
254 } else if (errno == ESRCH) {
255 printf("Kill error: No process or process group can be found corresponding to that specified by pid.");
256 }
257 #endif // DEBUG
258 if (IsRunning() == true) {
259 status = kill(FChildPID, SIGKILL);
260
261 if (status == 0) {
262 result = true;
263 }
264 }
265 }
266 }
267
268 return result;
269 }
270
271 bool PosixProcess::Wait() {
272 bool result = false;
273
274 int status = 0;
275 pid_t wpid = 0;
276
277 wpid = wait(&status);
278 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
279 if (errno != EINTR) {
280 status = -1;
281 }
282 }
283
284 #ifdef DEBUG
285 if (WIFEXITED(status)) {
286 printf("child exited, status=%d\n", WEXITSTATUS(status));
287 } else if (WIFSIGNALED(status)) {
288 printf("child killed (signal %d)\n", WTERMSIG(status));
289 } else if (WIFSTOPPED(status)) {
290 printf("child stopped (signal %d)\n", WSTOPSIG(status));
291 #ifdef WIFCONTINUED // Not all implementations support this
292 } else if (WIFCONTINUED(status)) {
293 printf("child continued\n");
294 #endif // WIFCONTINUED
295 } else { // Non-standard case -- may never happen
296 printf("Unexpected status (0x%x)\n", status);
297 }
298 #endif // DEBUG
299
301 result = true;
302 }
303
304 return result;
305 }
306
307 TProcessID PosixProcess::GetProcessID() {
308 return FChildPID;
309 }
310
311 void PosixProcess::SetInput(TString Value) {
312 if (FInputHandle != 0) {
313 write(FInputHandle, Value.data(), Value.size());
314 }
315 }
316
317 std::list<TString> PosixProcess::GetOutput() {
318 ReadOutput();
319 return Process::GetOutput();
320 }
|