| /******************************************************************************* |
| * Copyright (c) 2002, 2010 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 |
| *******************************************************************************/ |
| package org.eclipse.cdt.utils.pty; |
| |
| import java.io.IOException; |
| |
| import org.eclipse.cdt.core.CCorePlugin; |
| |
| /** |
| * PTY - pseudo terminal support. |
| */ |
| public class PTY { |
| static final String LIBRARY_NAME = "gpty"; //$NON-NLS-1$ |
| |
| final boolean console; |
| String slave; |
| PTYInputStream in; |
| PTYOutputStream out; |
| /** |
| * NOTE: Field is accessed by the native layer. Do not refactor! |
| */ |
| int master; |
| |
| private static boolean hasPTY; |
| 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; |
| } |
| } |
| |
| /** |
| * Create PTY for use with Eclipse console. Identical to {@link PTY#PTY(boolean) PTY(true)}. |
| */ |
| public PTY() throws IOException { |
| this(true); |
| } |
| |
| /** |
| * 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.</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 |
| * @since 5.2 |
| */ |
| public PTY(boolean console) throws IOException { |
| this.console = console; |
| |
| if (hasPTY) { |
| slave = openMaster(console); |
| } |
| |
| if (slave == null) { |
| throw new IOException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$ |
| } |
| |
| in = new PTYInputStream(new MasterFD()); |
| out = new PTYOutputStream(new MasterFD()); |
| } |
| |
| 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; |
| CCorePlugin.log( |
| CCorePlugin.getResourceString("Util.exception.cannotSetTerminalSize"), ule); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| /** |
| * @return whether PTY support is available on this platform |
| */ |
| public static boolean isSupported() { |
| return hasPTY; |
| } |
| |
| native String openMaster(boolean console); |
| |
| native int change_window_size(int fdm, int width, int height); |
| |
| static { |
| try { |
| System.loadLibrary(LIBRARY_NAME); |
| hasPTY = true; |
| } 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); |
| } |
| } |
| |
| } |