Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'core/org.eclipse.cdt.core.native/src/org/eclipse/cdt/utils/pty/PTY.java')
-rw-r--r--core/org.eclipse.cdt.core.native/src/org/eclipse/cdt/utils/pty/PTY.java275
1 files changed, 275 insertions, 0 deletions
diff --git a/core/org.eclipse.cdt.core.native/src/org/eclipse/cdt/utils/pty/PTY.java b/core/org.eclipse.cdt.core.native/src/org/eclipse/cdt/utils/pty/PTY.java
new file mode 100644
index 00000000000..abef9e9e54f
--- /dev/null
+++ b/core/org.eclipse.cdt.core.native/src/org/eclipse/cdt/utils/pty/PTY.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2014 QNX Software Systems 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:
+ * QNX Software Systems - Initial API and implementation
+ * Wind River Systems, Inc. - bug 248071
+ * Martin Oberhuber (Wind River) - [303083] Split out the Spawner
+ *******************************************************************************/
+package org.eclipse.cdt.utils.pty;
+
+import java.io.IOException;
+
+import org.eclipse.cdt.internal.core.natives.CNativePlugin;
+import org.eclipse.cdt.internal.core.natives.Messages;
+import org.eclipse.cdt.utils.spawner.Spawner;
+import org.eclipse.core.runtime.Platform;
+
+/**
+ * PTY - pseudo terminal support.
+ */
+public class PTY {
+
+ /**
+ * The pty modes.
+ * @since 5.6
+ */
+ public enum Mode {
+ /** This mode is for use with an Eclipse console. */
+ CONSOLE,
+ /** This mode is for use with a terminal emulator. */
+ TERMINAL
+ }
+
+ final boolean console;
+ final String slave;
+ final PTYInputStream in;
+ final PTYOutputStream out;
+
+ /**
+ * NOTE: Field is accessed by the native layer. Do not refactor!
+ */
+ int master;
+
+ private static boolean hasPTY;
+ private static boolean isWinPTY;
+ private static boolean isConsoleModeSupported;
+ private static boolean setTerminalSizeErrorAlreadyLogged;
+
+ /**
+ * The master fd is used on two streams. We need to wrap the fd
+ * so that when stream.close() is called the other stream is disabled.
+ */
+ public class MasterFD {
+
+ public int getFD() {
+ return master;
+ }
+
+ void setFD(int fd) {
+ master = fd;
+ }
+ }
+
+ /**
+ * @return whether PTY support for console mode is available on this platform
+ */
+ public static boolean isSupported() {
+ return isSupported(Mode.CONSOLE);
+ }
+
+ /**
+ * @return whether PTY support for given mode is available on this platform
+ * @since 5.6
+ */
+ public static boolean isSupported(Mode mode ) {
+ return hasPTY && (isConsoleModeSupported || mode == Mode.TERMINAL);
+ }
+
+
+ /**
+ * Create PTY for use with Eclipse console.
+ * Identical to {@link PTY#PTY(boolean) PTY(Mode.CONSOLE)}.
+ */
+ public PTY() throws IOException {
+ this(Mode.CONSOLE);
+ }
+
+ /**
+ * Create PTY for given mode.
+ *
+ * <p>
+ * The provided mode indicates whether the pseudo terminal is used with the interactive
+ * Eclipse console or a terminal emulation:
+ * <ul>
+ * <li><code>CONSOLE</code> - the terminal is configured with no echo and stderr is
+ * redirected to a pipe instead of the PTY. This mode is not supported on windows</li>
+ * <li><code>TERMINAL</code> - 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.
+ * Known platforms which support this mode are:
+ * <code>linux-x86</code>, <code>linux-x86_64</code>, <code>solaris-sparc</code>, <code>macosx</code>.
+ * </li>
+ * </ul>
+ * </p>
+ * @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);
+ }
+
+ /**
+ * Create pseudo terminal.
+ *
+ * <p>
+ * The provided flag indicates whether the pseudo terminal is used with the interactive
+ * Eclipse console:
+ * <ul>
+ * <li>If <code>true</code> the terminal is configured with no echo and stderr is
+ * redirected to a pipe instead of the PTY. This mode is not supported on windows</li>
+ * <li>If <code>false</code> 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.
+ * Known platforms which support this mode are:
+ * <code>linux-x86</code>, <code>linux-x86_64</code>, <code>solaris-sparc</code>, <code>macosx</code>.
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @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 (console && !isConsoleModeSupported) {
+ throw new IOException(Messages.Util_exception_cannotCreatePty);
+ }
+ slave= hasPTY ? openMaster(console) : null;
+
+ if (slave == null) {
+ throw new IOException(Messages.Util_exception_cannotCreatePty);
+ }
+
+ 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;
+ }
+
+ public MasterFD getMasterFD() {
+ return new MasterFD();
+ }
+
+ /**
+ * @return whether this pseudo terminal is for use with the Eclipse console.
+ *
+ * @since 5.2
+ */
+ public final boolean isConsole() {
+ return console;
+ }
+
+ public PTYOutputStream getOutputStream() {
+ return out;
+ }
+
+ public PTYInputStream getInputStream() {
+ return in;
+ }
+
+ /**
+ * Change terminal window size to given width and height.
+ * <p>
+ * This should only be used when the pseudo terminal is configured
+ * for use with a terminal emulation, i.e. when {@link #isConsole()}
+ * returns <code>false</code>.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> This method may not be supported on all platforms.
+ * Known platforms which support this method are:
+ * <code>linux-x86</code>, <code>linux-x86_64</code>, <code>solaris-sparc</code>, <code>macosx</code>.
+ * </p>
+ *
+ * @since 5.2
+ */
+ public final void setTerminalSize(int width, int height) {
+ try {
+ change_window_size(master, width, height);
+ } catch (UnsatisfiedLinkError ule) {
+ if (!setTerminalSizeErrorAlreadyLogged) {
+ setTerminalSizeErrorAlreadyLogged = true;
+ CNativePlugin.log(Messages.Util_exception_cannotSetTerminalSize, ule);
+ }
+ }
+ }
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ * @since 5.6
+ */
+ 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);
+ }
+ }
+
+}

Back to the top