2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2012-06-29 07:23:13 +02:00
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
#include "qnxdevice.h"
|
2019-02-20 19:13:28 +01:00
|
|
|
|
|
|
|
|
#include "qnxconstants.h"
|
2022-07-21 09:19:41 +02:00
|
|
|
#include "qnxdeployqtlibrariesdialog.h"
|
2013-05-30 13:53:28 +02:00
|
|
|
#include "qnxdevicetester.h"
|
2013-09-27 16:55:38 +02:00
|
|
|
#include "qnxdeviceprocesslist.h"
|
2013-09-16 15:30:30 +02:00
|
|
|
#include "qnxdeviceprocesssignaloperation.h"
|
2019-02-20 19:13:28 +01:00
|
|
|
#include "qnxdevicewizard.h"
|
2022-07-11 14:22:42 +02:00
|
|
|
#include "qnxtr.h"
|
2012-06-29 07:23:13 +02:00
|
|
|
|
2022-02-14 18:37:56 +01:00
|
|
|
#include <remotelinux/sshprocessinterface.h>
|
|
|
|
|
|
2016-04-19 16:43:30 +02:00
|
|
|
#include <utils/port.h>
|
2013-10-21 14:54:49 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2022-05-02 19:59:40 +02:00
|
|
|
#include <utils/qtcprocess.h>
|
2013-04-29 15:45:00 +02:00
|
|
|
|
2020-06-19 13:46:26 +02:00
|
|
|
#include <QRegularExpression>
|
2013-04-29 15:45:00 +02:00
|
|
|
|
2014-11-27 17:46:45 +01:00
|
|
|
using namespace ProjectExplorer;
|
2022-02-14 18:37:56 +01:00
|
|
|
using namespace RemoteLinux;
|
2014-11-27 17:46:45 +01:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2022-07-21 09:19:41 +02:00
|
|
|
namespace Qnx::Internal {
|
2012-06-29 07:23:13 +02:00
|
|
|
|
2022-02-14 18:37:56 +01:00
|
|
|
class QnxProcessImpl final : public SshProcessInterface
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
QnxProcessImpl(const LinuxDevice *linuxDevice);
|
|
|
|
|
~QnxProcessImpl() { killIfRunning(); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QString fullCommandLine(const CommandLine &commandLine) const final;
|
2022-11-14 15:23:01 +01:00
|
|
|
void handleSendControlSignal(Utils::ControlSignal controlSignal) final;
|
2022-02-14 18:37:56 +01:00
|
|
|
|
|
|
|
|
const QString m_pidFile;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static std::atomic_int s_pidFileCounter = 1;
|
|
|
|
|
|
|
|
|
|
QnxProcessImpl::QnxProcessImpl(const LinuxDevice *linuxDevice)
|
|
|
|
|
: SshProcessInterface(linuxDevice)
|
|
|
|
|
, m_pidFile(QString::fromLatin1("/var/run/qtc.%1.pid").arg(s_pidFileCounter.fetch_add(1)))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString QnxProcessImpl::fullCommandLine(const CommandLine &commandLine) const
|
|
|
|
|
{
|
|
|
|
|
QStringList args = ProcessArgs::splitArgs(commandLine.arguments());
|
|
|
|
|
args.prepend(commandLine.executable().toString());
|
|
|
|
|
const QString cmd = ProcessArgs::createUnixArgs(args).toString();
|
|
|
|
|
|
|
|
|
|
QString fullCommandLine =
|
|
|
|
|
"test -f /etc/profile && . /etc/profile ; "
|
|
|
|
|
"test -f $HOME/profile && . $HOME/profile ; ";
|
|
|
|
|
|
|
|
|
|
if (!m_setup.m_workingDirectory.isEmpty())
|
|
|
|
|
fullCommandLine += QString::fromLatin1("cd %1 ; ").arg(
|
|
|
|
|
ProcessArgs::quoteArg(m_setup.m_workingDirectory.toString()));
|
|
|
|
|
|
2022-05-09 15:02:23 +02:00
|
|
|
const Environment env = m_setup.m_environment;
|
2022-02-14 18:37:56 +01:00
|
|
|
for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
|
|
|
|
|
fullCommandLine += QString::fromLatin1("%1='%2' ")
|
|
|
|
|
.arg(env.key(it)).arg(env.expandedValueForKey(env.key(it)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fullCommandLine += QString::fromLatin1("%1 & echo $! > %2").arg(cmd).arg(m_pidFile);
|
|
|
|
|
|
|
|
|
|
return fullCommandLine;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-14 15:23:01 +01:00
|
|
|
void QnxProcessImpl::handleSendControlSignal(Utils::ControlSignal controlSignal)
|
2022-02-14 18:37:56 +01:00
|
|
|
{
|
2022-04-29 13:18:42 +02:00
|
|
|
QTC_ASSERT(controlSignal != ControlSignal::KickOff, return);
|
|
|
|
|
const QString args = QString::fromLatin1("-%1 `cat %2`")
|
|
|
|
|
.arg(controlSignalToInt(controlSignal)).arg(m_pidFile);
|
|
|
|
|
CommandLine command = { "kill", args, CommandLine::Raw };
|
|
|
|
|
// Note: This blocking call takes up to 2 ms for local remote.
|
|
|
|
|
runInShell(command);
|
2022-02-14 18:37:56 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-21 14:54:49 +02:00
|
|
|
const char QnxVersionKey[] = "QnxVersion";
|
2014-11-27 17:46:45 +01:00
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
QnxDevice::QnxDevice()
|
2019-01-11 14:50:08 +01:00
|
|
|
{
|
2022-07-11 14:22:42 +02:00
|
|
|
setDisplayType(Tr::tr("QNX"));
|
|
|
|
|
setDefaultDisplayName(Tr::tr("QNX Device"));
|
2019-08-16 10:17:45 +02:00
|
|
|
setOsType(OsTypeOtherUnix);
|
|
|
|
|
|
2022-07-11 14:22:42 +02:00
|
|
|
addDeviceAction({Tr::tr("Deploy Qt libraries..."), [](const IDevice::Ptr &device, QWidget *parent) {
|
2019-01-11 14:50:08 +01:00
|
|
|
QnxDeployQtLibrariesDialog dialog(device, parent);
|
|
|
|
|
dialog.exec();
|
|
|
|
|
}});
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
int QnxDevice::qnxVersion() const
|
2013-10-21 14:54:49 +02:00
|
|
|
{
|
|
|
|
|
if (m_versionNumber == 0)
|
|
|
|
|
updateVersionNumber();
|
|
|
|
|
|
|
|
|
|
return m_versionNumber;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
void QnxDevice::updateVersionNumber() const
|
2013-10-21 14:54:49 +02:00
|
|
|
{
|
2022-05-02 19:59:40 +02:00
|
|
|
QtcProcess versionNumberProcess;
|
2013-10-21 14:54:49 +02:00
|
|
|
|
2022-05-10 15:33:33 +02:00
|
|
|
versionNumberProcess.setCommand({filePath("uname"), {"-r"}});
|
2022-05-02 19:59:40 +02:00
|
|
|
versionNumberProcess.runBlocking(EventLoopMode::On);
|
2013-10-21 14:54:49 +02:00
|
|
|
|
|
|
|
|
QByteArray output = versionNumberProcess.readAllStandardOutput();
|
|
|
|
|
QString versionMessage = QString::fromLatin1(output);
|
2020-06-19 13:46:26 +02:00
|
|
|
const QRegularExpression versionNumberRegExp("(\\d+)\\.(\\d+)\\.(\\d+)");
|
|
|
|
|
const QRegularExpressionMatch match = versionNumberRegExp.match(versionMessage);
|
|
|
|
|
if (match.hasMatch()) {
|
|
|
|
|
int major = match.captured(1).toInt();
|
|
|
|
|
int minor = match.captured(2).toInt();
|
|
|
|
|
int patch = match.captured(3).toInt();
|
2013-10-21 14:54:49 +02:00
|
|
|
m_versionNumber = (major << 16)|(minor<<8)|(patch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
void QnxDevice::fromMap(const QVariantMap &map)
|
2013-10-21 14:54:49 +02:00
|
|
|
{
|
|
|
|
|
m_versionNumber = map.value(QLatin1String(QnxVersionKey), 0).toInt();
|
2022-02-14 18:37:56 +01:00
|
|
|
LinuxDevice::fromMap(map);
|
2013-10-21 14:54:49 +02:00
|
|
|
}
|
|
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
QVariantMap QnxDevice::toMap() const
|
2013-10-21 14:54:49 +02:00
|
|
|
{
|
2022-02-14 18:37:56 +01:00
|
|
|
QVariantMap map(LinuxDevice::toMap());
|
2013-10-21 14:54:49 +02:00
|
|
|
map.insert(QLatin1String(QnxVersionKey), m_versionNumber);
|
|
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-10 12:53:27 +02:00
|
|
|
PortsGatheringMethod QnxDevice::portsGatheringMethod() const
|
2012-08-01 16:26:27 +02:00
|
|
|
{
|
2022-05-10 12:53:27 +02:00
|
|
|
return {
|
|
|
|
|
// TODO: The command is probably needlessly complicated because the parsing method
|
|
|
|
|
// used to be fixed. These two can now be matched to each other.
|
|
|
|
|
[this](QAbstractSocket::NetworkLayerProtocol protocol) -> CommandLine {
|
|
|
|
|
Q_UNUSED(protocol)
|
|
|
|
|
return {filePath("netstat"), {"-na"}};
|
|
|
|
|
},
|
|
|
|
|
|
2022-05-12 08:42:51 +02:00
|
|
|
&Port::parseFromNetstatOutput
|
2022-05-10 12:53:27 +02:00
|
|
|
};
|
2012-08-01 16:26:27 +02:00
|
|
|
}
|
2013-04-29 15:45:00 +02:00
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
DeviceProcessList *QnxDevice::createProcessListModel(QObject *parent) const
|
2013-04-29 15:45:00 +02:00
|
|
|
{
|
|
|
|
|
return new QnxDeviceProcessList(sharedFromThis(), parent);
|
|
|
|
|
}
|
2013-05-30 13:53:28 +02:00
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
DeviceTester *QnxDevice::createDeviceTester() const
|
2013-05-30 13:53:28 +02:00
|
|
|
{
|
|
|
|
|
return new QnxDeviceTester;
|
|
|
|
|
}
|
2013-09-16 15:30:30 +02:00
|
|
|
|
2022-02-14 18:37:56 +01:00
|
|
|
Utils::ProcessInterface *QnxDevice::createProcessInterface() const
|
|
|
|
|
{
|
|
|
|
|
return new QnxProcessImpl(this);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-19 08:56:05 +02:00
|
|
|
DeviceProcessSignalOperation::Ptr QnxDevice::signalOperation() const
|
2013-09-16 15:30:30 +02:00
|
|
|
{
|
2022-05-03 16:30:25 +02:00
|
|
|
return DeviceProcessSignalOperation::Ptr(new QnxDeviceProcessSignalOperation(sharedFromThis()));
|
2013-09-16 15:30:30 +02:00
|
|
|
}
|
2014-11-27 17:46:45 +01:00
|
|
|
|
2019-02-20 19:13:28 +01:00
|
|
|
// Factory
|
|
|
|
|
|
2022-01-26 09:05:35 +01:00
|
|
|
QnxDeviceFactory::QnxDeviceFactory() : IDeviceFactory(Constants::QNX_QNX_OS_TYPE)
|
2019-02-20 19:13:28 +01:00
|
|
|
{
|
2022-07-11 14:22:42 +02:00
|
|
|
setDisplayName(Tr::tr("QNX Device"));
|
2019-02-20 19:13:28 +01:00
|
|
|
setCombinedIcon(":/qnx/images/qnxdevicesmall.png",
|
|
|
|
|
":/qnx/images/qnxdevice.png");
|
|
|
|
|
setConstructionFunction(&QnxDevice::create);
|
2022-01-26 09:05:35 +01:00
|
|
|
setCreator([] {
|
|
|
|
|
QnxDeviceWizard wizard;
|
|
|
|
|
if (wizard.exec() != QDialog::Accepted)
|
|
|
|
|
return IDevice::Ptr();
|
|
|
|
|
return wizard.device();
|
|
|
|
|
});
|
2019-02-20 19:13:28 +01:00
|
|
|
}
|
|
|
|
|
|
2022-07-21 09:19:41 +02:00
|
|
|
} // Qnx::Internal
|