diff --git a/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/pty.dll b/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/pty.dll
new file mode 100644
index 00000000000..65946aaee7a
Binary files /dev/null and b/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/pty.dll differ
diff --git a/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/winpty-agent.exe b/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/winpty-agent.exe
new file mode 100644
index 00000000000..021e086947f
Binary files /dev/null and b/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/winpty-agent.exe differ
diff --git a/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/winpty.dll b/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/winpty.dll
new file mode 100644
index 00000000000..b4672786d70
Binary files /dev/null and b/core/org.eclipse.cdt.core.win32.x86/os/win32/x86/winpty.dll differ
diff --git a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/pty.dll b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/pty.dll
new file mode 100644
index 00000000000..e0ad8c13bd3
Binary files /dev/null and b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/pty.dll differ
diff --git a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/winpty-agent.exe b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/winpty-agent.exe
new file mode 100644
index 00000000000..0dc90fd36dc
Binary files /dev/null and b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/winpty-agent.exe differ
diff --git a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/winpty.dll b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/winpty.dll
new file mode 100644
index 00000000000..cda66d0dd59
Binary files /dev/null and b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/winpty.dll differ
diff --git a/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTY.h b/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTY.h
new file mode 100644
index 00000000000..5c80c5793c8
--- /dev/null
+++ b/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTY.h
@@ -0,0 +1,45 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class org_eclipse_cdt_utils_pty_PTY */
+
+#ifndef _Included_org_eclipse_cdt_utils_pty_PTY
+#define _Included_org_eclipse_cdt_utils_pty_PTY
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTY
+ * Method: openMaster
+ * Signature: (Z)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_eclipse_cdt_utils_pty_PTY_openMaster
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTY
+ * Method: change_window_size
+ * Signature: (III)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTY_change_1window_1size
+ (JNIEnv *, jobject, jint, jint, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTY
+ * Method: exec2
+ * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[ILjava/lang/String;IZ)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTY_exec2
+ (JNIEnv *, jobject, jobjectArray, jobjectArray, jstring, jintArray, jstring, jint, jboolean);
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTY
+ * Method: waitFor
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTY_waitFor
+ (JNIEnv *, jobject, jint, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTYInputStream.h b/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTYInputStream.h
new file mode 100644
index 00000000000..86cd5bdd240
--- /dev/null
+++ b/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTYInputStream.h
@@ -0,0 +1,31 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class org_eclipse_cdt_utils_pty_PTYInputStream */
+
+#ifndef _Included_org_eclipse_cdt_utils_pty_PTYInputStream
+#define _Included_org_eclipse_cdt_utils_pty_PTYInputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_eclipse_cdt_utils_pty_PTYInputStream_MAX_SKIP_BUFFER_SIZE
+#define org_eclipse_cdt_utils_pty_PTYInputStream_MAX_SKIP_BUFFER_SIZE 2048L
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYInputStream
+ * Method: read0
+ * Signature: (I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYInputStream_read0
+ (JNIEnv *, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYInputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYInputStream_close0
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTYOutputStream.h b/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTYOutputStream.h
new file mode 100644
index 00000000000..108ef248d8c
--- /dev/null
+++ b/core/org.eclipse.cdt.core.win32/library/pty/jni/include/PTYOutputStream.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class org_eclipse_cdt_utils_pty_PTYOutputStream */
+
+#ifndef _Included_org_eclipse_cdt_utils_pty_PTYOutputStream
+#define _Included_org_eclipse_cdt_utils_pty_PTYOutputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYOutputStream
+ * Method: write0
+ * Signature: (I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYOutputStream_write0
+ (JNIEnv *, jobject, jint, jbyteArray, jint);
+
+/*
+ * Class: org_eclipse_cdt_utils_pty_PTYOutputStream
+ * Method: close0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_pty_PTYOutputStream_close0
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/org.eclipse.cdt.core.win32/library/pty/jni/src/dllmain.cpp b/core/org.eclipse.cdt.core.win32/library/pty/jni/src/dllmain.cpp
new file mode 100644
index 00000000000..c19f2ebbdcc
--- /dev/null
+++ b/core/org.eclipse.cdt.core.win32/library/pty/jni/src/dllmain.cpp
@@ -0,0 +1,71 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+#include
+#include
+#include
+
+#pragma comment(lib, "delayimp")
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+static HMODULE getCurrentModule()
+{
+ HMODULE module;
+ if (!GetModuleHandleEx(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCTSTR)getCurrentModule,
+ &module)) {
+ assert(false);
+ }
+ return module;
+}
+
+HMODULE PTYExplicitLoadLibrary( LPCSTR pszModuleName )
+{
+ if( lstrcmpiA( pszModuleName, "winpty.dll" ) == 0 )
+ {
+ CHAR szPath[MAX_PATH] = "";
+ //_hdllInstance is the HMODULE of *this* module
+ DWORD cchPath = GetModuleFileNameA(getCurrentModule(), szPath, MAX_PATH );
+ while( cchPath > 0 )
+ {
+ switch( szPath[cchPath - 1] )
+ {
+ case '\\':
+ case '/':
+ case ':':
+ break;
+ default:
+ --cchPath;
+ continue;
+ }
+ break; //stop searching; found path separator
+ }
+ lstrcpynA( szPath + cchPath, pszModuleName, MAX_PATH - cchPath );
+ return LoadLibraryA( szPath ); //call with full path to dependent DLL
+ }
+ return NULL;
+}
+
+FARPROC WINAPI PTYDliNotifyHook( unsigned dliNotify, PDelayLoadInfo pdli )
+{
+ if( dliNotify == dliNotePreLoadLibrary )
+ return (FARPROC)PTYExplicitLoadLibrary( pdli->szDll );
+ return NULL;
+}
+
+extern "C" PfnDliHook __pfnDliNotifyHook2 = PTYDliNotifyHook;
diff --git a/core/org.eclipse.cdt.core.win32/library/pty/jni/src/pty.cpp b/core/org.eclipse.cdt.core.win32/library/pty/jni/src/pty.cpp
new file mode 100644
index 00000000000..d1b5f42c163
--- /dev/null
+++ b/core/org.eclipse.cdt.core.win32/library/pty/jni/src/pty.cpp
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Wind River Systems, Inc. and others. All rights reserved.
+ * This program and the accompanying materials are made available under the terms
+ * of the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+#include "PTY.h"
+#include "PTYInputStream.h"
+#include "PTYOutputStream.h"
+#include "winpty.h"
+
+#include
+#include
+#include
+ * @param mode the desired mode of operation
+ * @throws IOException if the PTY could not be created
+ * @since 5.6
+ */
+ public PTY(Mode mode) throws IOException {
+ this(mode == Mode.CONSOLE);
}
/**
@@ -63,7 +120,7 @@ public class PTY {
* Eclipse console:
*
*
If true the terminal is configured with no echo and stderr is
- * redirected to a pipe instead of the PTY.
+ * redirected to a pipe instead of the PTY. This mode is not supported on windows
*
If false the terminal is configured with echo and stderr is
* connected to the PTY. This mode is best suited for use with a proper terminal emulation.
* Note that this mode might not be supported on all platforms.
@@ -75,14 +132,16 @@ public class PTY {
*
* @param console whether terminal is used with Eclipse console
* @throws IOException if the PTY could not be created
+ * @deprecated Use {@link #PTY(Mode)} instead
* @since 5.2
*/
+ @Deprecated
public PTY(boolean console) throws IOException {
this.console = console;
-
- if (hasPTY) {
- slave= openMaster(console);
+ if (console && !isConsoleModeSupported) {
+ throw new IOException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$
}
+ slave= hasPTY ? openMaster(console) : null;
if (slave == null) {
throw new IOException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$
@@ -91,7 +150,20 @@ public class PTY {
in = new PTYInputStream(new MasterFD());
out = new PTYOutputStream(new MasterFD());
}
-
+
+ /**
+ * Test whether the slave name can be used as a tty device by external processes (e.g. gdb).
+ * If the slave name is not valid an IOException is thrown.
+ * @throws IOException if the slave name is not valid
+ * @since 5.6
+ */
+ public void validateSlaveName() throws IOException {
+ // on windows the slave name is just an internal identifier
+ // and does not represent a real device
+ if (isWinPTY)
+ throw new IOException("Slave name is not valid"); //$NON-NLS-1$
+ }
+
public String getSlaveName() {
return slave;
}
@@ -144,27 +216,58 @@ public class PTY {
}
/**
- * @return whether PTY support is available on this platform
+ * @noreference This method is not intended to be referenced by clients.
+ * @since 5.6
*/
- public static boolean isSupported() {
- return hasPTY;
+ public int exec_pty(Spawner spawner, String[] cmdarray, String[] envp, String dir, int[] chan) throws IOException {
+ if (isWinPTY) {
+ return exec2(cmdarray, envp, dir, chan, slave, master, console);
+ } else {
+ return spawner.exec2(cmdarray, envp, dir, chan, slave, master, console);
+ }
+ }
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ * @since 5.6
+ */
+ public int waitFor(Spawner spawner, int pid) {
+ if (isWinPTY) {
+ return waitFor(master, pid);
+ } else {
+ return spawner.waitFor(pid);
+ }
}
native String openMaster(boolean console);
native int change_window_size(int fdm, int width, int height);
+ /**
+ * Native method when executing with a terminal emulation (winpty only).
+ */
+ native int exec2(String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD, boolean console) throws IOException;
+
+ /**
+ * Native method to wait for process to terminate (winpty only).
+ */
+ native int waitFor(int masterFD, int processID);
+
static {
try {
System.loadLibrary("pty"); //$NON-NLS-1$
hasPTY = true;
+ isWinPTY = Platform.OS_WIN32.equals(Platform.getOS());
+ // on windows console mode is not supported except for experimental use
+ // to enable it, set system property org.eclipse.cdt.core.winpty_console_mode=true
+ isConsoleModeSupported = !isWinPTY || Boolean.getBoolean("org.eclipse.cdt.core.winpty_console_mode"); //$NON-NLS-1$
} catch (SecurityException e) {
// Comment out it worries the users too much
//CCorePlugin.log(e);
} catch (UnsatisfiedLinkError e) {
// Comment out it worries the users too much
//CCorePlugin.log(e);
- }
+ }
}
}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java
index ad07b7ead4c..c8f66f41118 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java
@@ -348,7 +348,7 @@ public class Spawner extends Process {
}
}
- private void exec_pty(String[] cmdarray, String[] envp, String dirpath, PTY pty) throws IOException {
+ private void exec_pty(String[] cmdarray, String[] envp, String dirpath, final PTY pty) throws IOException {
String command = cmdarray[0];
SecurityManager s = System.getSecurityManager();
if (s != null)
@@ -356,17 +356,15 @@ public class Spawner extends Process {
if (envp == null)
envp = new String[0];
- final String slaveName = pty.getSlaveName();
- final int masterFD = pty.getMasterFD().getFD();
- final boolean console = pty.isConsole();
- //int fdm = pty.get
Reaper reaper = new Reaper(cmdarray, envp, dirpath) {
- /* (non-Javadoc)
- * @see org.eclipse.cdt.utils.spawner.Spawner.Reaper#execute(java.lang.String[], java.lang.String[], java.lang.String, int[])
- */
@Override
int execute(String[] cmd, String[] env, String dir, int[] channels) throws IOException {
- return exec2(cmd, env, dir, channels, slaveName, masterFD, console);
+ return pty.exec_pty(Spawner.this, cmd, env, dir, channels);
+ }
+
+ @Override
+ protected int waitFor(int pid) {
+ return pty.waitFor(Spawner.this, pid);
}
};
reaper.setDaemon(true);
@@ -432,18 +430,20 @@ public class Spawner extends Process {
/**
* Native method when executing with a terminal emulation.
+ * @noreference This method is not intended to be referenced by clients.
*/
- native int exec2( String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD, boolean console) throws IOException;
+ public native int exec2( String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD, boolean console) throws IOException;
/**
* Native method to drop a signal on the process with pid.
*/
public native int raise(int processID, int sig);
- /*
+ /**
* Native method to wait(3) for process to terminate.
+ * @noreference This method is not intended to be referenced by clients.
*/
- native int waitFor(int processID);
+ public native int waitFor(int processID);
static {
try {
@@ -477,6 +477,10 @@ public class Spawner extends Process {
return exec0(cmdarray, envp, dir, channels);
}
+ int waitFor(int pid) {
+ return Spawner.this.waitFor(pid);
+ }
+
@Override
public void run() {
try {
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java
index a15d872cac6..78247d42394 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java
@@ -45,6 +45,9 @@ class SpawnerInputStream extends InputStream {
*/
@Override
public int read(byte[] buf, int off, int len) throws IOException {
+ if (fd == -1) {
+ return -1;
+ }
if (buf == null) {
throw new NullPointerException();
} else if (
@@ -85,6 +88,9 @@ class SpawnerInputStream extends InputStream {
@Override
public int available() throws IOException {
+ if (fd == -1) {
+ return 0;
+ }
try {
return available0(fd);
}
diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java
index a9cbffc7dc7..490faa9760e 100644
--- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java
+++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java
@@ -160,6 +160,7 @@ public class MIPlugin extends Plugin {
try {
PTY pseudo = new PTY();
+ pseudo.validateSlaveName();
pty = new MITTYAdapter(pseudo);
} catch (IOException e) {
// Should we not print/log this ?
@@ -436,6 +437,7 @@ public class MIPlugin extends Plugin {
if (usePty) {
try {
PTY pseudo = new PTY();
+ pseudo.validateSlaveName();
pty = new MITTYAdapter(pseudo);
} catch (IOException e) {
// Should we not print/log this ?
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java
index b0c63d0ab41..ffa1d165f6a 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java
@@ -507,6 +507,7 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
// These types always use a PTY
try {
fPty = new PTY();
+ fPty.validateSlaveName();
// Tell GDB to use this PTY
fGdb.queueCommand(
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java
index e88e9b6b3ca..436d32262e4 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java
@@ -270,6 +270,7 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence {
// and requires a pty for it.
try {
fPty = new PTY();
+ fPty.validateSlaveName();
// Tell GDB to use this PTY
fCommandControl.queueCommand(