diff options
Diffstat (limited to 'libjava/java/lang/natWin32Process.cc')
-rw-r--r-- | libjava/java/lang/natWin32Process.cc | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/libjava/java/lang/natWin32Process.cc b/libjava/java/lang/natWin32Process.cc index e69de29..38e6f91 100644 --- a/libjava/java/lang/natWin32Process.cc +++ b/libjava/java/lang/natWin32Process.cc @@ -0,0 +1,294 @@ +// natWin32Process.cc - Native side of Win32 process code. + +/* Copyright (C) 2003 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#include <stdio.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +// Conflicts with the definition in "java/lang/reflect/Modifier.h" +#undef STRICT + +#include <gcj/cni.h> +#include <jvm.h> + +#include <java/lang/ConcreteProcess.h> +#include <java/lang/IllegalThreadStateException.h> +#include <java/lang/InterruptedException.h> +#include <java/lang/NullPointerException.h> +#include <java/lang/Thread.h> +#include <java/io/File.h> +#include <java/io/FileDescriptor.h> +#include <java/io/FileInputStream.h> +#include <java/io/FileOutputStream.h> +#include <java/io/IOException.h> +#include <java/lang/OutOfMemoryError.h> + +void +java::lang::ConcreteProcess::cleanup (void) +{ + if (inputStream != NULL) + { + inputStream->close (); + inputStream = NULL; + } + + if (outputStream != NULL) + { + outputStream->close (); + outputStream = NULL; + } + + if (errorStream != NULL) + { + errorStream->close (); + errorStream = NULL; + } +} + +void +java::lang::ConcreteProcess::destroy (void) +{ + if (! hasExited ()) + { + // Kill it forcibly and assign an (arbitrary) exit code of 0. + TerminateProcess ((HANDLE) procHandle, 0); + exitCode = 0; + + cleanup (); + } +} + +jboolean +java::lang::ConcreteProcess::hasExited (void) +{ + DWORD exitStatus; + + if (GetExitCodeProcess ((HANDLE) procHandle, &exitStatus) != 0) + { + // NOTE: STILL_ACTIVE is defined as "259" by Win32 - if the + // child actually exits with this return code, we have a + // problem here. See MSDN documentation on GetExitCodeProcess( ). + + if (exitStatus == STILL_ACTIVE) + return false; + else + { + cleanup (); + exitCode = exitStatus; + return true; + } + } + else + return true; +} + +jint +java::lang::ConcreteProcess::waitFor (void) +{ + if (! hasExited ()) + { + DWORD exitStatus = 0UL; + + // FIXME: The wait should be interruptible. + WaitForSingleObject ((HANDLE) procHandle, INFINITE); + + GetExitCodeProcess ((HANDLE) procHandle, &exitStatus); + exitCode = exitStatus; + + cleanup (); + } + + return exitCode; +} + +static char * +new_string (jstring string) +{ + jsize s = _Jv_GetStringUTFLength (string); + char *buf = (char *) _Jv_Malloc (s + 1); + _Jv_GetStringUTFRegion (string, 0, s, buf); + buf[s] = '\0'; + return buf; +} + +void +java::lang::ConcreteProcess::startProcess (jstringArray progarray, + jstringArray envp, + java::io::File *dir) +{ + using namespace java::io; + + procHandle = (jint) INVALID_HANDLE_VALUE; + + // Reconstruct the command line. + jstring *elts = elements (progarray); + + int cmdLineLen = 0; + + for (int i = 0; i < progarray->length; ++i) + cmdLineLen += (_Jv_GetStringUTFLength (elts[i]) + 1); + + char *cmdLine = (char *) _Jv_Malloc (cmdLineLen + 1); + + int j = 0; + for (int i = 0; i < progarray->length; ++i) + { + jsize s = _Jv_GetStringUTFLength (elts[i]); + _Jv_GetStringUTFRegion (elts[i], 0, s, (cmdLine + j)); + + j += s; + *(cmdLine + j) = ' '; + j++; + } + *(cmdLine + j) = '\0'; + + // Get the environment, if any. + char *env = NULL; + if (envp) + { + elts = elements (envp); + + int envLen = 0; + for (int i = 0; i < envp->length; ++i) + envLen += (_Jv_GetStringUTFLength (elts[i]) + 1); + + env = (char *) _Jv_Malloc (envLen + 1); + + int j = 0; + for (int i = 0; i < envp->length; ++i) + { + jsize s = _Jv_GetStringUTFLength (elts[i]); + _Jv_GetStringUTFRegion (elts[i], 0, s, (env + j)); + + j += s; + *(env + j) = '\0'; + j++; + } + *(env + j) = '\0'; + } + + // Get the working directory path, if specified. + char *wdir = NULL; + if (dir != NULL) + wdir = new_string (dir->getPath ()); + + errorStream = NULL; + inputStream = NULL; + outputStream = NULL; + + java::lang::Throwable *exc = NULL; + + try + { + // We create anonymous pipes to communicate with the child + // on each of standard streams. + + HANDLE cldStdInRd, cldStdInWr; + HANDLE cldStdOutRd, cldStdOutWr; + HANDLE cldStdErrRd, cldStdErrWr; + + SECURITY_ATTRIBUTES sAttrs; + + // Explicitly allow the handles to the pipes to be inherited. + sAttrs.nLength = sizeof (SECURITY_ATTRIBUTES); + sAttrs.bInheritHandle = 1; + sAttrs.lpSecurityDescriptor = NULL; + + + char tmpBuff[64]; + if (CreatePipe (&cldStdInRd, &cldStdInWr, &sAttrs, 0) == 0) + { + sprintf (tmpBuff, + "Error creating stdin pipe (Win32 Error Code: %lu)", + GetLastError ()); + throw new IOException (JvNewStringLatin1 (tmpBuff)); + } + + if (CreatePipe (&cldStdOutRd, &cldStdOutWr, &sAttrs, 0) == 0) + { + sprintf (tmpBuff, + "Error creating stdout pipe (Win32 Error Code: %lu)", + GetLastError ()); + throw new IOException (JvNewStringLatin1 (tmpBuff)); + } + + if (CreatePipe (&cldStdErrRd, &cldStdErrWr, &sAttrs, 0) == 0) + { + sprintf (tmpBuff, + "Error creating stderr pipe (Win32 Error Code: %lu)", + GetLastError ()); + throw new IOException (JvNewStringLatin1 (tmpBuff)); + } + + outputStream = new FileOutputStream + (new FileDescriptor ((jint) cldStdInWr)); + inputStream = new FileInputStream + (new FileDescriptor ((jint) cldStdOutRd)); + errorStream = new FileInputStream + (new FileDescriptor ((jint) cldStdErrRd)); + + // Now create the child process. + PROCESS_INFORMATION pi; + STARTUPINFO si; + + ZeroMemory (&pi, sizeof (PROCESS_INFORMATION)); + + ZeroMemory (&si, sizeof (STARTUPINFO)); + si.cb = sizeof (STARTUPINFO); + + // Explicitly specify the handles to the standard streams. + si.dwFlags |= STARTF_USESTDHANDLES; + + si.hStdInput = cldStdInRd; + si.hStdOutput = cldStdOutWr; + si.hStdError = cldStdErrWr; + + if (CreateProcess (NULL, + cmdLine, + NULL, + NULL, + 1, + 0, + env, + wdir, + &si, + &pi) == 0) + { + sprintf (tmpBuff, + "Error creating child process (Win32 Error Code: %lu)", + GetLastError ()); + throw new IOException (JvNewStringLatin1 (tmpBuff)); + } + + procHandle = (jint ) pi.hProcess; + + // Close the wrong ends (for the parent) of the pipes. + CloseHandle (cldStdInRd); + CloseHandle (cldStdOutWr); + CloseHandle (cldStdErrWr); + + _Jv_Free (cmdLine); + if (env != NULL) + _Jv_Free (env); + if (wdir != NULL) + _Jv_Free (wdir); + } + catch (java::lang::Throwable *thrown) + { + cleanup (); + exc = thrown; + } + + if (exc != NULL) + throw exc; +} |