diff --git a/src/libs/ssh/sshprocess.cpp b/src/libs/ssh/sshprocess.cpp index 9e29f0b88d3..4b1304d37f6 100644 --- a/src/libs/ssh/sshprocess.cpp +++ b/src/libs/ssh/sshprocess.cpp @@ -40,8 +40,13 @@ namespace Internal { SshProcess::SshProcess() { Utils::Environment env = Utils::Environment::systemEnvironment(); - if (SshSettings::askpassFilePath().exists()) + if (SshSettings::askpassFilePath().exists()) { env.set("SSH_ASKPASS", SshSettings::askpassFilePath().toUserOutput()); + + // OpenSSH only uses the askpass program if DISPLAY is set, regardless of the platform. + if (!env.hasKey("DISPLAY")) + env.set("DISPLAY", ":0"); + } setProcessEnvironment(env.toProcessEnvironment()); } diff --git a/src/libs/ssh/sshsettings.cpp b/src/libs/ssh/sshsettings.cpp index 25505b0fc2d..0a0cb0dedc1 100644 --- a/src/libs/ssh/sshsettings.cpp +++ b/src/libs/ssh/sshsettings.cpp @@ -113,12 +113,23 @@ int SshSettings::connectionSharingTimeout() return sshSettings->connectionSharingTimeOutInMinutes; } -static FileName filePathValue(const FileName &value, const QString &defaultFileName) +static FileName filePathValue(const FileName &value, const QStringList &candidateFileNames) { - return !value.isEmpty() - ? value - : Environment::systemEnvironment().searchInPath(defaultFileName, - sshSettings->searchPathRetriever()); + if (!value.isEmpty()) + return value; + const QList additionalSearchPaths = sshSettings->searchPathRetriever(); + for (const QString &candidate : candidateFileNames) { + const FileName filePath = Environment::systemEnvironment() + .searchInPath(candidate, additionalSearchPaths); + if (!filePath.isEmpty()) + return filePath; + } + return FileName(); +} + +static FileName filePathValue(const FileName &value, const QString &candidateFileName) +{ + return filePathValue(value, QStringList(candidateFileName)); } void SshSettings::setSshFilePath(const FileName &ssh) { sshSettings->sshFilePath = ssh; } @@ -138,7 +149,7 @@ FileName SshSettings::askpassFilePath() candidate = sshSettings->askpassFilePath; if (candidate.isEmpty()) candidate = FileName::fromString(Environment::systemEnvironment().value("SSH_ASKPASS")); - return filePathValue(candidate, "ssh-askpass"); + return filePathValue(candidate, QStringList{"qtc-askpass", "ssh-askpass"}); } void SshSettings::setKeygenFilePath(const FileName &keygen) diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index d303f6f620e..0caa97f68c1 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -1723,8 +1723,10 @@ void ProjectExplorerPlugin::extensionsInitialized() DeviceManager::instance()->addDevice(IDevice::Ptr(new DesktopDevice)); QSsh::SshSettings::loadSettings(Core::ICore::settings()); - if (Utils::HostOsInfo::isWindowsHost()) { - const auto searchPathRetriever = [] { + const auto searchPathRetriever = [] { + Utils::FileNameList searchPaths; + searchPaths << Utils::FileName::fromString(Core::ICore::libexecPath()); + if (Utils::HostOsInfo::isWindowsHost()) { const QString gitBinary = Core::ICore::settings()->value("Git/BinaryPath", "git") .toString(); const QStringList rawGitSearchPaths = Core::ICore::settings()->value("Git/Path") @@ -1733,15 +1735,14 @@ void ProjectExplorerPlugin::extensionsInitialized() [](const QString &rawPath) { return Utils::FileName::fromString(rawPath); }); const Utils::FileName fullGitPath = Utils::Environment::systemEnvironment() .searchInPath(gitBinary, gitSearchPaths); - if (fullGitPath.isEmpty()) - return Utils::FileNameList(); - return Utils::FileNameList{ - fullGitPath.parentDir(), - fullGitPath.parentDir().parentDir() + "/usr/bin" - }; - }; - QSsh::SshSettings::setExtraSearchPathRetriever(searchPathRetriever); - } + if (!fullGitPath.isEmpty()) { + searchPaths << fullGitPath.parentDir() + << fullGitPath.parentDir().parentDir() + "/usr/bin"; + } + } + return searchPaths; + }; + QSsh::SshSettings::setExtraSearchPathRetriever(searchPathRetriever); // delay restoring kits until UI is shown for improved perceived startup performance QTimer::singleShot(0, this, &ProjectExplorerPlugin::restoreKits); diff --git a/src/tools/qtc-askpass/qtc-askpass-main.cpp b/src/tools/qtc-askpass/qtc-askpass-main.cpp new file mode 100644 index 00000000000..3e527bc3ad8 --- /dev/null +++ b/src/tools/qtc-askpass/qtc-askpass-main.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + QTimer::singleShot(0, [] { + QInputDialog dlg; + const QStringList appArgs = qApp->arguments(); + QString labelText = QCoreApplication::translate("qtc-askpass", + "Password required for SSH login."); + if (appArgs.count() > 1) + labelText.append('\n').append(appArgs.at(1)); + dlg.setLabelText(labelText); + dlg.setTextEchoMode(QLineEdit::Password); + if (dlg.exec() == QDialog::Accepted) + std::cout << qPrintable(dlg.textValue()) << std::endl; + }); + return app.exec(); +} diff --git a/src/tools/qtc-askpass/qtc-askpass.pro b/src/tools/qtc-askpass/qtc-askpass.pro new file mode 100644 index 00000000000..e0d61eba183 --- /dev/null +++ b/src/tools/qtc-askpass/qtc-askpass.pro @@ -0,0 +1,5 @@ +include(../../qtcreatortool.pri) + +TARGET = qtc-askpass + +SOURCES = qtc-askpass-main.cpp diff --git a/src/tools/qtc-askpass/qtc-askpass.qbs b/src/tools/qtc-askpass/qtc-askpass.qbs new file mode 100644 index 00000000000..c8e61e741a6 --- /dev/null +++ b/src/tools/qtc-askpass/qtc-askpass.qbs @@ -0,0 +1,9 @@ +import qbs + +QtcTool { + name: "qtc-askpass" + Depends { name: "Qt.widgets" } + files: [ + "qtc-askpass-main.cpp", + ] +} diff --git a/src/tools/tools.pro b/src/tools/tools.pro index e90c7f68e0b..558e8eb9ee4 100644 --- a/src/tools/tools.pro +++ b/src/tools/tools.pro @@ -6,7 +6,8 @@ SUBDIRS = qtpromaker \ ../plugins/cpaster/frontend \ valgrindfake \ 3rdparty \ - buildoutputparser + buildoutputparser \ + qtc-askpass isEmpty(QTC_SKIP_SDKTOOL): SUBDIRS += sdktool diff --git a/src/tools/tools.qbs b/src/tools/tools.qbs index cf07eb8c13c..6a30971da3d 100644 --- a/src/tools/tools.qbs +++ b/src/tools/tools.qbs @@ -12,6 +12,7 @@ Project { "qml2puppet/qml2puppet.qbs", "qtcdebugger/qtcdebugger.qbs", "qtcreatorcrashhandler/qtcreatorcrashhandler.qbs", + "qtc-askpass/qtc-askpass.qbs", "qtpromaker/qtpromaker.qbs", "sdktool/sdktool.qbs", "valgrindfake/valgrindfake.qbs",