blob: 8848070d7fd7c05f79ac2c6ecfce57b68bb93f45 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.nativeexecution.api.pty;
import java.io.IOException;
import org.netbeans.modules.nativeexecution.ExProcessInfoProvider;
import org.netbeans.modules.nativeexecution.api.ExecutionEnvironment;
import org.netbeans.modules.nativeexecution.api.HostInfo;
import org.netbeans.modules.nativeexecution.api.HostInfo.CpuFamily;
import org.netbeans.modules.nativeexecution.api.NativeProcess;
import org.netbeans.modules.nativeexecution.api.util.ConnectionManager;
import org.netbeans.modules.nativeexecution.api.util.ConnectionManager.CancellationException;
import org.netbeans.modules.nativeexecution.api.util.HostInfoUtils;
import org.netbeans.modules.nativeexecution.api.util.Shell;
import org.netbeans.modules.nativeexecution.api.util.WindowsSupport;
import org.netbeans.modules.nativeexecution.pty.IOConnector;
import org.netbeans.modules.nativeexecution.pty.PtyAllocator;
import org.netbeans.modules.nativeexecution.pty.SttySupport;
import org.netbeans.modules.nativeexecution.support.Logger;
import org.openide.util.Exceptions;
import org.openide.windows.InputOutput;
/**
* An utility class for pty-related stuff...
*
* @author ak119685
*/
public final class PtySupport {
private static final java.util.logging.Logger log = Logger.getInstance();
private PtySupport() {
}
/**
* This method returns a Pty that is currently associated with the process
* (if any).
*
* @param process - process to get pty of
* @return Pty that is currently associated with the process or <tt>null</tt>
* if ptocess was started in non-pty mode.
*/
public static String getTTY(NativeProcess process) {
if (process instanceof ExProcessInfoProvider) {
return ((ExProcessInfoProvider) process).getTTY();
}
return null;
}
/**
* Connects process' IO streams with the specified InputOutput.
*
* @param io - <tt>InputOutput</tt> to connect process' IO with
* @param process - the process which should be connected with the io
*
* @return <tt>true</tt> if operation was successfull. <tt>false</tt> otherwise.
*/
public static boolean connect(InputOutput io, NativeProcess process) {
return IOConnector.getInstance().connect(io, process);
}
/**
* Connects process' IO streams with the specified InputOutput.
*
* @param io - <tt>InputOutput</tt> to connect process' IO with
* @param process - the process which should be connected with the io
*
* @return <tt>true</tt> if operation was successfull. <tt>false</tt> otherwise.
*/
public static boolean connect(InputOutput io, NativeProcess process, Runnable postConnectRunnabel) {
return IOConnector.getInstance().connect(io, process, postConnectRunnabel);
}
/**
* Connects pty's IO streams (master side) with the specified <tt>InputOutput</tt>.
* So that IO of the process that will do input/output to the specified pty'
* slave will go to the specified <tt>InputOutput</tt>.
*
* @param io - <tt>InputOutput</tt> to connect pty's IO with
* @param pty - the pty to connect InputOutput with
*
* @return <tt>true</tt> if operation was successfull. <tt>false</tt> otherwise.
*/
public static boolean connect(InputOutput io, Pty pty) {
return IOConnector.getInstance().connect(io, pty);
}
/**
* Allocates a new 'unconnected' pty
* @param env - environmant in which a pty should be allocated
* @return newly allocated pty or <tt>null</tt> if allocation failed
*/
public static Pty allocate(ExecutionEnvironment env) throws IOException {
if (!ConnectionManager.getInstance().isConnectedTo(env)) {
throw new IllegalStateException();
}
return PtyAllocator.getInstance().allocate(env);
}
public static void deallocate(Pty pty) throws IOException {
pty.close();
}
/**
* Disables echo in the tty (stty -echo)
* @param env - environmant in which a tty is used
* @param tty - tty name
*/
public static void disableEcho(ExecutionEnvironment exEnv, String tty) {
SttySupport.apply(exEnv, tty, "-echo"); //NOI18N
}
/**
* Sets 'erase' key of a terminal to ^H.
*
* There are some bugs in Solaris (7009510, 7045666, 7164170) that make this
* approach unreliable. So it is better not to use it.
*
* (it is recommended not to use stty utility for controlling any terminal
* other than the one in which it is running in.)
*
* There is an option in pty utility - --set-erase-key that could be used to
* achieve needed effect.
*/
@Deprecated
public static void setBackspaceAsEraseChar(ExecutionEnvironment exEnv, String tty) {
SttySupport.apply(exEnv, tty, "erase \\^H"); // NOI18N
}
public static boolean isSupportedFor(ExecutionEnvironment executionEnvironment) {
if (!HostInfoUtils.isHostInfoAvailable(executionEnvironment)) {
return false;
}
try {
HostInfo hostInfo = HostInfoUtils.getHostInfo(executionEnvironment);
switch (hostInfo.getOSFamily()) {
case WINDOWS:
// for now pty mode only supported with Cygwin
Shell shell = WindowsSupport.getInstance().getActiveShell();
if (shell == null) {
return false;
}
return shell.type == Shell.ShellType.CYGWIN;
case MACOSX:
return true;
case LINUX:
return hostInfo.getCpuFamily().equals(CpuFamily.X86)
|| hostInfo.getCpuFamily().equals(CpuFamily.SPARC)
|| (hostInfo.getCpuFamily().equals(CpuFamily.ARM) && Boolean.getBoolean("cnd.pty.arm.support"))
|| hostInfo.getCpuFamily().equals(CpuFamily.AARCH64);
case SUNOS:
return true;
case FREEBSD:
return false;
default:
return false;
}
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} catch (CancellationException ex) {
// don't report CancellationException
}
return false;
}
}