mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 01:36:01 +02:00
Bug 465212 - SSH should support command shell service
Added JSchCommandShellService which creates a ChannelShell through JSch in order to open a remote terminal. Change-Id: Ib7ddeb3f9c964ab32130baf99a8d70d36605c3d8 Signed-off-by: Matthew Bastien <mbastien@qnx.com>
This commit is contained in:
parent
6ee3aff83b
commit
efeb6fc7bb
6 changed files with 104 additions and 12 deletions
|
@ -164,7 +164,7 @@ public class RemoteServicesManager implements IRemoteServicesManager {
|
||||||
List<IRemoteConnectionType> connTypes = new ArrayList<IRemoteConnectionType>();
|
List<IRemoteConnectionType> connTypes = new ArrayList<IRemoteConnectionType>();
|
||||||
for (IRemoteConnectionType connType : getAllConnectionTypes()) {
|
for (IRemoteConnectionType connType : getAllConnectionTypes()) {
|
||||||
for (Class<? extends IRemoteConnection.Service> service : services) {
|
for (Class<? extends IRemoteConnection.Service> service : services) {
|
||||||
if (!connType.hasConnectionService(service)) {
|
if (connType.hasConnectionService(service)) {
|
||||||
connTypes.add(connType);
|
connTypes.add(connType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,11 @@
|
||||||
factory="org.eclipse.remote.internal.jsch.core.JSchConnection$Factory"
|
factory="org.eclipse.remote.internal.jsch.core.JSchConnection$Factory"
|
||||||
service="org.eclipse.remote.internal.jsch.core.JSchConnection">
|
service="org.eclipse.remote.internal.jsch.core.JSchConnection">
|
||||||
</connectionService>
|
</connectionService>
|
||||||
|
<connectionService
|
||||||
|
connectionTypeId="org.eclipse.remote.JSch"
|
||||||
|
factory="org.eclipse.remote.internal.jsch.core.JSchCommandShellService$Factory"
|
||||||
|
service="org.eclipse.remote.core.IRemoteCommandShellService">
|
||||||
|
</connectionService>
|
||||||
<processService
|
<processService
|
||||||
connectionTypeId="org.eclipse.remote.JSch"
|
connectionTypeId="org.eclipse.remote.JSch"
|
||||||
factory="org.eclipse.remote.internal.jsch.core.JSchProcess$Factory"
|
factory="org.eclipse.remote.internal.jsch.core.JSchProcess$Factory"
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2015 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.remote.internal.jsch.core;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.remote.core.IRemoteCommandShellService;
|
||||||
|
import org.eclipse.remote.core.IRemoteConnection;
|
||||||
|
import org.eclipse.remote.core.IRemoteProcess;
|
||||||
|
|
||||||
|
public class JSchCommandShellService implements IRemoteCommandShellService {
|
||||||
|
private IRemoteConnection fRemoteConnection;
|
||||||
|
|
||||||
|
public JSchCommandShellService(IRemoteConnection remoteConnection) {
|
||||||
|
fRemoteConnection = remoteConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IRemoteConnection getRemoteConnection() {
|
||||||
|
return fRemoteConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IRemoteProcess getCommandShell(int flags) throws IOException {
|
||||||
|
return new JSchProcessBuilder(getRemoteConnection()).start(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory implements IRemoteConnection.Service.Factory {
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.eclipse.remote.core.IRemoteConnection.Service.Factory#getService(org.eclipse.remote.core.IRemoteConnection,
|
||||||
|
* java.lang.Class)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends IRemoteConnection.Service> T getService(IRemoteConnection connection, Class<T> service) {
|
||||||
|
if (IRemoteCommandShellService.class.equals(service)) {
|
||||||
|
return (T) new JSchCommandShellService(connection);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,7 @@ import org.eclipse.remote.internal.jsch.core.messages.Messages;
|
||||||
import com.jcraft.jsch.Channel;
|
import com.jcraft.jsch.Channel;
|
||||||
import com.jcraft.jsch.ChannelExec;
|
import com.jcraft.jsch.ChannelExec;
|
||||||
import com.jcraft.jsch.ChannelSftp;
|
import com.jcraft.jsch.ChannelSftp;
|
||||||
|
import com.jcraft.jsch.ChannelShell;
|
||||||
import com.jcraft.jsch.JSchException;
|
import com.jcraft.jsch.JSchException;
|
||||||
import com.jcraft.jsch.Session;
|
import com.jcraft.jsch.Session;
|
||||||
import com.jcraft.jsch.UIKeyboardInteractive;
|
import com.jcraft.jsch.UIKeyboardInteractive;
|
||||||
|
@ -541,6 +542,22 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a shell channel to the remote host.
|
||||||
|
*
|
||||||
|
* @return shell channel or null if the progress monitor was cancelled
|
||||||
|
*
|
||||||
|
* @throws RemoteConnectionException
|
||||||
|
* if a channel could not be opened
|
||||||
|
*/
|
||||||
|
public ChannelShell getShellChannel() throws RemoteConnectionException {
|
||||||
|
try {
|
||||||
|
return (ChannelShell) fSessions.get(0).openChannel("shell"); //$NON-NLS-1$
|
||||||
|
} catch (JSchException e) {
|
||||||
|
throw new RemoteConnectionException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getPassphrase() {
|
public String getPassphrase() {
|
||||||
return fRemoteConnection.getSecureAttribute(PASSPHRASE_ATTR);
|
return fRemoteConnection.getSecureAttribute(PASSPHRASE_ATTR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,9 @@ import org.eclipse.remote.core.IRemoteProcessSignalService;
|
||||||
import org.eclipse.remote.core.IRemoteProcessTerminalService;
|
import org.eclipse.remote.core.IRemoteProcessTerminalService;
|
||||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.Channel;
|
||||||
import com.jcraft.jsch.ChannelExec;
|
import com.jcraft.jsch.ChannelExec;
|
||||||
|
import com.jcraft.jsch.ChannelShell;
|
||||||
|
|
||||||
public class JSchProcess implements IRemoteProcessControlService, IRemoteProcessSignalService, IRemoteProcessTerminalService {
|
public class JSchProcess implements IRemoteProcessControlService, IRemoteProcessSignalService, IRemoteProcessTerminalService {
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
|
@ -32,7 +34,7 @@ public class JSchProcess implements IRemoteProcessControlService, IRemoteProcess
|
||||||
private static int WAIT_TIMEOUT = 1000;
|
private static int WAIT_TIMEOUT = 1000;
|
||||||
private static int refCount = 0;
|
private static int refCount = 0;
|
||||||
|
|
||||||
private final ChannelExec fChannel;
|
private final Channel fChannel;
|
||||||
private final IRemoteProcess fProcess;
|
private final IRemoteProcess fProcess;
|
||||||
|
|
||||||
private InputStream fProcStdout;
|
private InputStream fProcStdout;
|
||||||
|
@ -127,14 +129,14 @@ public class JSchProcess implements IRemoteProcessControlService, IRemoteProcess
|
||||||
fProcStdout = new PipedInputStream(pipedOutput);
|
fProcStdout = new PipedInputStream(pipedOutput);
|
||||||
fProcStderr = new NullInputStream();
|
fProcStderr = new NullInputStream();
|
||||||
|
|
||||||
fStderrReader = new Thread(new ProcReader(fChannel.getErrStream(), pipedOutput));
|
fStderrReader = new Thread(new ProcReader(fChannel.getExtInputStream(), pipedOutput));
|
||||||
fStdoutReader = new Thread(new ProcReader(fChannel.getInputStream(), pipedOutput));
|
fStdoutReader = new Thread(new ProcReader(fChannel.getInputStream(), pipedOutput));
|
||||||
|
|
||||||
fStderrReader.start();
|
fStderrReader.start();
|
||||||
fStdoutReader.start();
|
fStdoutReader.start();
|
||||||
} else {
|
} else {
|
||||||
fProcStdout = fChannel.getInputStream();
|
fProcStdout = fChannel.getInputStream();
|
||||||
fProcStderr = fChannel.getErrStream();
|
fProcStderr = fChannel.getExtInputStream();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Activator.log(e);
|
Activator.log(e);
|
||||||
|
@ -237,7 +239,11 @@ public class JSchProcess implements IRemoteProcessControlService, IRemoteProcess
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setTerminalSize(int cols, int rows, int width, int height) {
|
public void setTerminalSize(int cols, int rows, int width, int height) {
|
||||||
fChannel.setPtySize(cols, rows, width, height);
|
if (fChannel instanceof ChannelExec) {
|
||||||
|
((ChannelExec) fChannel).setPtySize(cols, rows, width, height);
|
||||||
|
} else if (fChannel instanceof ChannelShell) {
|
||||||
|
((ChannelShell) fChannel).setPtySize(cols, rows, width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -32,7 +32,9 @@ import org.eclipse.remote.internal.core.RemoteDebugOptions;
|
||||||
import org.eclipse.remote.internal.core.RemoteProcess;
|
import org.eclipse.remote.internal.core.RemoteProcess;
|
||||||
import org.eclipse.remote.internal.jsch.core.messages.Messages;
|
import org.eclipse.remote.internal.jsch.core.messages.Messages;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.Channel;
|
||||||
import com.jcraft.jsch.ChannelExec;
|
import com.jcraft.jsch.ChannelExec;
|
||||||
|
import com.jcraft.jsch.ChannelShell;
|
||||||
import com.jcraft.jsch.JSchException;
|
import com.jcraft.jsch.JSchException;
|
||||||
|
|
||||||
public class JSchProcessBuilder extends AbstractRemoteProcessBuilder {
|
public class JSchProcessBuilder extends AbstractRemoteProcessBuilder {
|
||||||
|
@ -41,7 +43,7 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder {
|
||||||
private final Map<String, String> fRemoteEnv = new HashMap<String, String>();
|
private final Map<String, String> fRemoteEnv = new HashMap<String, String>();
|
||||||
private final Set<Character> charSet = new HashSet<Character>();
|
private final Set<Character> charSet = new HashSet<Character>();
|
||||||
|
|
||||||
private ChannelExec fChannel;
|
private Channel fChannel;
|
||||||
private Map<String, String> fNewRemoteEnv;
|
private Map<String, String> fNewRemoteEnv;
|
||||||
private boolean fPreamble = true;
|
private boolean fPreamble = true;
|
||||||
|
|
||||||
|
@ -64,6 +66,10 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder {
|
||||||
this(connection, Arrays.asList(command));
|
this(connection, Arrays.asList(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSchProcessBuilder(IRemoteConnection connection) {
|
||||||
|
this(connection, "shell"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IFileStore directory() {
|
public IFileStore directory() {
|
||||||
IFileStore dir = super.directory();
|
IFileStore dir = super.directory();
|
||||||
|
@ -155,13 +161,19 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fChannel = fConnection.getExecChannel();
|
if (cmdArgs.size() == 1 && cmdArgs.get(0).equals("shell")) { //$NON-NLS-1$
|
||||||
String command = buildCommand(remoteCmd, env, clearEnv);
|
fChannel = fConnection.getShellChannel();
|
||||||
fChannel.setCommand(command);
|
((ChannelShell) fChannel).setPty((flags & ALLOCATE_PTY) == ALLOCATE_PTY);
|
||||||
fChannel.setPty((flags & ALLOCATE_PTY) == ALLOCATE_PTY);
|
RemoteDebugOptions.trace(RemoteDebugOptions.DEBUG_REMOTE_COMMANDS, "executing command: shell"); //$NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
fChannel = fConnection.getExecChannel();
|
||||||
|
String command = buildCommand(remoteCmd, env, clearEnv);
|
||||||
|
((ChannelExec) fChannel).setCommand(command);
|
||||||
|
((ChannelExec) fChannel).setPty((flags & ALLOCATE_PTY) == ALLOCATE_PTY);
|
||||||
|
RemoteDebugOptions.trace(RemoteDebugOptions.DEBUG_REMOTE_COMMANDS, "executing command: " + command); //$NON-NLS-1$
|
||||||
|
}
|
||||||
fChannel.setXForwarding((flags & FORWARD_X11) == FORWARD_X11);
|
fChannel.setXForwarding((flags & FORWARD_X11) == FORWARD_X11);
|
||||||
fChannel.connect();
|
fChannel.connect();
|
||||||
RemoteDebugOptions.trace(RemoteDebugOptions.DEBUG_REMOTE_COMMANDS, "executing command: " + command); //$NON-NLS-1$
|
|
||||||
return new RemoteProcess(getRemoteConnection(), this);
|
return new RemoteProcess(getRemoteConnection(), this);
|
||||||
} catch (RemoteConnectionException e) {
|
} catch (RemoteConnectionException e) {
|
||||||
throw new IOException(e.getMessage());
|
throw new IOException(e.getMessage());
|
||||||
|
@ -170,7 +182,7 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelExec getChannel() {
|
public Channel getChannel() {
|
||||||
return fChannel;
|
return fChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue