From fb7438850279ceb54966be1db95ff9696a369b22 Mon Sep 17 00:00:00 2001 From: Greg Watson Date: Thu, 20 Aug 2015 15:44:00 -0400 Subject: Bug 475530 - Add login shell command support to JSch connections Change-Id: I7db0e9dfe14804751063b08bb8476c75a0825c96 Signed-off-by: Greg Watson --- .../remote/internal/jsch/core/JSchConnection.java | 12 +++++ .../internal/jsch/core/JSchProcessBuilder.java | 45 +++++++++++++++++- .../remote/internal/jsch/ui/messages/Messages.java | 3 ++ .../internal/jsch/ui/messages/messages.properties | 3 ++ .../jsch/ui/wizards/JSchConnectionPage.java | 54 +++++++++++++++++++--- 5 files changed, 109 insertions(+), 8 deletions(-) diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java index a23726c..dee054e 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java @@ -69,6 +69,7 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC public static final String PASSPHRASE_ATTR = "JSCH_PASSPHRASE_ATTR"; //$NON-NLS-1$ public static final String TIMEOUT_ATTR = "JSCH_TIMEOUT_ATTR"; //$NON-NLS-1$ public static final String USE_LOGIN_SHELL_ATTR = "JSCH_USE_LOGIN_SHELL_ATTR"; //$NON-NLS-1$ + public static final String LOGIN_SHELL_COMMAND_ATTR = "JSCH_LOGIN_SHELL_COMMAND_ATTR"; //$NON-NLS-1$ /** * Class to supply credentials from connection attributes without user interaction. @@ -243,6 +244,7 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC public static final int DEFAULT_TIMEOUT = 0; public static final boolean DEFAULT_IS_PASSWORD = false; public static final boolean DEFAULT_USE_LOGIN_SHELL = true; + public static final String DEFAULT_LOGIN_SHELL_COMMAND = "/bin/bash -l -c '{0}'"; //$NON-NLS-1$ public static final String EMPTY_STRING = ""; //$NON-NLS-1$ private String fWorkingDir; @@ -632,6 +634,16 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC return fProperties.get(key); } + /** + * Get the login shell command if useLoginShell is true + * + * @return login shell command + */ + public String getLoginShellCommand() { + String loginShell = fRemoteConnection.getAttribute(LOGIN_SHELL_COMMAND_ATTR); + return loginShell.isEmpty() ? DEFAULT_LOGIN_SHELL_COMMAND : loginShell; + } + /** * Gets the proxy command. For no proxy command null is returned. * diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java index f12ff5c..a2926e1 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchProcessBuilder.java @@ -218,8 +218,7 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder { } sb.append(cmd); if (fPreamble && fConnection.useLoginShell()) { - sb.insert(0, "/bin/bash -l -c '"); //$NON-NLS-1$ - sb.append("'"); //$NON-NLS-1$ + return substitute(fConnection.getLoginShellCommand(), sb.toString()); } return sb.toString(); } @@ -244,4 +243,46 @@ public class JSchProcessBuilder extends AbstractRemoteProcessBuilder { return inputString; } + private String substitute(String str, String... args) { + int length = str.length(); + StringBuffer buffer = new StringBuffer(length + (args.length * 5)); + for (int i = 0; i < length; i++) { + char c = str.charAt(i); + switch (c) { + case '{': + int index = str.indexOf('}', i); + // if we don't have a matching closing brace then... + if (index == -1) { + buffer.append(c); + break; + } + i++; + if (i >= length) { + buffer.append(c); + break; + } + // look for a substitution + int number = -1; + try { + number = Integer.parseInt(str.substring(i, index)); + } catch (NumberFormatException e) { + buffer.append(""); //$NON-NLS-1$ + i = index; + break; + } + if (number >= args.length || number < 0) { + buffer.append(""); //$NON-NLS-1$ + i = index; + break; + } + buffer.append(args[number]); + i = index; + break; + default: + buffer.append(c); + } + } + return buffer.toString(); + } + } \ No newline at end of file diff --git a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/Messages.java b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/Messages.java index 2b3420d..7f6efa0 100755 --- a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/Messages.java +++ b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/Messages.java @@ -21,6 +21,9 @@ public class Messages extends NLS { NLS.initializeMessages(BUNDLE_ID, Messages.class); } + public static String JSchConnectionPage_0; + public static String JSchConnectionPage_1; + public static String JSchConnectionPage_2; public static String JSchConnectionPage_A_connection_with_that_name_already_exists; public static String JSchConnectionPage_Edit_Connection; public static String JSchConnectionPage_Edit_properties_of_an_existing_connection; diff --git a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/messages.properties b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/messages.properties index 9f64c2e..d8aa8fa 100755 --- a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/messages.properties +++ b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/messages/messages.properties @@ -8,6 +8,9 @@ # Contributors: # IBM Corporation - initial implementation ############################################################################### +JSchConnectionPage_0=Use login shell +JSchConnectionPage_1=Login shell command +JSchConnectionPage_2=Login shell command cannot be empty JSchConnectionPage_A_connection_with_that_name_already_exists=A connection with that name already exists JSchConnectionPage_Edit_Connection=Edit Connection JSchConnectionPage_Edit_properties_of_an_existing_connection=Edit properties of an existing connection diff --git a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/wizards/JSchConnectionPage.java b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/wizards/JSchConnectionPage.java index c44c5af..a9874cb 100755 --- a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/wizards/JSchConnectionPage.java +++ b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/wizards/JSchConnectionPage.java @@ -65,12 +65,14 @@ public class JSchConnectionPage extends WizardPage { private Text fConnectionName; private Button fPasswordButton; private Button fPublicKeyButton; + private Button fUseLoginShellButton; private Text fHostText; private Text fUserText; private Text fPasswordText; private Text fPassphraseText; private Text fPortText; private Text fTimeoutText; + private Text fLoginShellText; private String fInitialName = "Remote Host"; //$NON-NLS-1$ private Set fInvalidConnectionNames; @@ -145,6 +147,29 @@ public class JSchConnectionPage extends WizardPage { fTimeoutText.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); setTextFieldWidthInChars(fTimeoutText, 5); + fUseLoginShellButton = new Button(settingsComp, SWT.CHECK); + fUseLoginShellButton.setText(Messages.JSchConnectionPage_0); + fUseLoginShellButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); + fUseLoginShellButton.addSelectionListener(new SelectionAdapter() { + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetSelected(SelectionEvent e) { + validateFields(); + updateEnablement(); + } + }); + Label loginShellLabel = new Label(settingsComp, SWT.NONE); + loginShellLabel.setText(Messages.JSchConnectionPage_1); + fLoginShellText = new Text(settingsComp, SWT.BORDER | SWT.SINGLE); + fLoginShellText.setText(JSchConnection.DEFAULT_LOGIN_SHELL_COMMAND); + fLoginShellText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + fUseLoginShellButton.setSelection(JSchConnection.DEFAULT_USE_LOGIN_SHELL); + Group proxyComp = new Group(advancedComp, SWT.NONE); proxyComp.setText(Messages.JSchConnectionPage_Proxy); proxyComp.setLayout(new GridLayout(1, false)); @@ -226,7 +251,8 @@ public class JSchConnectionPage extends WizardPage { fPasswordButton.setSelection(JSchConnection.DEFAULT_IS_PASSWORD); fPublicKeyButton.setSelection(!JSchConnection.DEFAULT_IS_PASSWORD); - controls.setTabList(new Control[] { fHostText, fUserText, fPublicKeyButton, fPassphraseText, fPasswordButton, fPasswordText }); + controls.setTabList( + new Control[] { fHostText, fUserText, fPublicKeyButton, fPassphraseText, fPasswordButton, fPasswordText }); } @Override @@ -358,6 +384,12 @@ public class JSchConnectionPage extends WizardPage { fPublicKeyButton.setSelection(!isPwd); fPasswordText.setText(fConnection.getSecureAttribute(JSchConnection.PASSWORD_ATTR)); fPassphraseText.setText(fConnection.getSecureAttribute(JSchConnection.PASSPHRASE_ATTR)); + String useLoginShellStr = fConnection.getAttribute(JSchConnection.USE_LOGIN_SHELL_ATTR); + boolean useLoginShell = useLoginShellStr.isEmpty() ? JSchConnection.DEFAULT_USE_LOGIN_SHELL + : Boolean.parseBoolean(useLoginShellStr); + fUseLoginShellButton.setSelection(useLoginShell); + String loginShellStr = fConnection.getAttribute(JSchConnection.LOGIN_SHELL_COMMAND_ATTR); + fLoginShellText.setText(loginShellStr.isEmpty() ? JSchConnection.DEFAULT_LOGIN_SHELL_COMMAND : loginShellStr); fProxyCommandText.setText(fConnection.getAttribute(JSchConnection.PROXYCOMMAND_ATTR)); JSchConnection proxyConn = fConnection.getService(JSchConnection.class).getProxyConnection(); if (proxyConn == null) { @@ -396,6 +428,14 @@ public class JSchConnectionPage extends WizardPage { if (passphrase != null) { fPassphraseText.setText(passphrase); } + String useLoginShell = fInitialAttributes.get(JSchConnection.USE_LOGIN_SHELL_ATTR); + if (useLoginShell != null) { + fUseLoginShellButton.setSelection(Boolean.parseBoolean(useLoginShell)); + } + String loginShell = fInitialAttributes.get(JSchConnection.LOGIN_SHELL_COMMAND_ATTR); + if (loginShell != null) { + fLoginShellText.setText(loginShell); + } fProxyConnectionWidget.setConnection(manager.getLocalConnectionType().getConnections().get(0)); } } @@ -408,6 +448,7 @@ public class JSchConnectionPage extends WizardPage { fPassphraseText.addModifyListener(fDataModifyListener); fPortText.addModifyListener(fDataModifyListener); fTimeoutText.addModifyListener(fDataModifyListener); + fLoginShellText.addModifyListener(fDataModifyListener); fProxyCommandText.addModifyListener(fDataModifyListener); fProxyConnectionWidget.addSelectionListener(new SelectionAdapter() { @Override @@ -484,6 +525,8 @@ public class JSchConnectionPage extends WizardPage { fConnection.setAttribute(JSchConnection.TIMEOUT_ATTR, fTimeoutText.getText().trim()); fConnection.setAttribute(JSchConnection.PORT_ATTR, fPortText.getText().trim()); fConnection.setAttribute(JSchConnection.PROXYCOMMAND_ATTR, fProxyCommandText.getText().trim()); + fConnection.setAttribute(JSchConnection.USE_LOGIN_SHELL_ATTR, Boolean.toString(fUseLoginShellButton.getSelection())); + fConnection.setAttribute(JSchConnection.LOGIN_SHELL_COMMAND_ATTR, fLoginShellText.getText().trim()); IRemoteConnection proxyConnection = fProxyConnectionWidget.getConnection(); IRemoteServicesManager manager = Activator.getService(IRemoteServicesManager.class); String proxyConnectionName = ""; //$NON-NLS-1$ @@ -498,6 +541,7 @@ public class JSchConnectionPage extends WizardPage { boolean isPasswordAuth = fPasswordButton.getSelection(); fPasswordText.setEnabled(isPasswordAuth); fPassphraseText.setEnabled(!isPasswordAuth); + fLoginShellText.setEnabled(fUseLoginShellButton.getSelection()); } private String validateAdvanced() { @@ -511,9 +555,6 @@ public class JSchConnectionPage extends WizardPage { } catch (NumberFormatException ne) { return Messages.JSchNewConnectionPage_Timeout_is_not_valid; } - // if (fCipherCombo.getSelectionIndex() == -1) { - // return "Invalid cipher type"; - // } return null; } @@ -527,8 +568,9 @@ public class JSchConnectionPage extends WizardPage { message = Messages.JSchNewConnectionPage_Host_name_cannot_be_empty; } else if (fUserText.getText().trim().length() == 0) { message = Messages.JSchNewConnectionPage_User_name_cannot_be_empty; - } - if (message == null && fProxyConnectionWidget.getConnection() == null) { + } else if (fUseLoginShellButton.getSelection() && fLoginShellText.getText().trim().length() == 0) { + message = Messages.JSchConnectionPage_2; + } else if (fProxyConnectionWidget.getConnection() == null) { message = Messages.JSchConnectionPage_selectProxyConnection; } if (message == null) { -- cgit v1.2.3