blob: 81a73d5a8a994269a3b0224d9d25896dbe8bacd0 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}
}