123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /****************************************************************************
- **
- ** Copyright (C) 2013 Jarek Pelczar <jpelczar@gmail.com>
- **
- ** 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 Digia. For licensing terms and
- ** conditions see http://qt.digia.com/licensing. For further information
- ** use the contact form at http://qt.digia.com/contact-us.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file. Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Digia gives you certain additional
- ** rights. These rights are described in the Digia Qt LGPL Exception
- ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
- **
- ****************************************************************************/
- #include "tizendevice.h"
- #include "tizenconstants.h"
- #include "tizendevicetester.h"
- #include "sdbcommandexecutor.h"
- #include <QCoreApplication>
- #include <projectexplorer/devicesupport/deviceprocesslist.h>
- #include <utils/qtcassert.h>
- #include <utils/consoleprocess.h>
- #include "tizenconfigurations.h"
- using namespace ProjectExplorer;
- namespace Tizen {
- const char Delimiter0[] = "x--";
- const char Delimiter1[] = "---";
- static QString visualizeNull(QString s)
- {
- return s.replace(QLatin1Char('\0'), QLatin1String("<null>"));
- }
- class TizenDeviceProcessList : public ProjectExplorer::DeviceProcessList
- {
- Q_OBJECT
- public:
- Tizen::SdbCommandExecutor * m_executor;
- QPointer<Tizen::SdbConnector> m_connector;
- TizenDeviceProcessList(const ProjectExplorer::IDevice::ConstPtr& device, QPointer<Tizen::SdbConnector> conn, QObject * parent = 0);
- virtual ~TizenDeviceProcessList();
- virtual void doUpdate();
- virtual void doKillProcess(const ProjectExplorer::DeviceProcess &process);
- QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const
- {
- qDebug() << "Response is " << listProcessesReply;
- QList<DeviceProcess> processes;
- const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0)
- + QString::fromLatin1(Delimiter1), QString::SkipEmptyParts);
- foreach (const QString &line, lines) {
- const QStringList elements = line.split(QLatin1Char('\n'));
- if (elements.count() < 4) {
- qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO,
- elements.count(), qPrintable(visualizeNull(line)));
- continue;
- }
- bool ok;
- const int pid = elements.first().mid(6).toInt(&ok);
- if (!ok) {
- qDebug("%s: Expected number in %s. Line was '%s'.", Q_FUNC_INFO,
- qPrintable(elements.first()), qPrintable(visualizeNull(line)));
- continue;
- }
- QString command = elements.at(1);
- command.replace(QLatin1Char('\0'), QLatin1Char(' '));
- if (command.isEmpty()) {
- const QString &statString = elements.at(2);
- const int openParenPos = statString.indexOf(QLatin1Char('('));
- const int closedParenPos = statString.indexOf(QLatin1Char(')'), openParenPos);
- if (openParenPos == -1 || closedParenPos == -1)
- continue;
- command = QLatin1Char('[')
- + statString.mid(openParenPos + 1, closedParenPos - openParenPos - 1)
- + QLatin1Char(']');
- }
- DeviceProcess process;
- process.pid = pid;
- process.cmdLine = command;
- process.exe = elements.at(3);
- processes.append(process);
- }
- qSort(processes);
- return processes;
- }
- public slots:
- void handleListFinished();
- void handleKillFinished();
- void handleError();
- };
- TizenDeviceProcessList::TizenDeviceProcessList(const ProjectExplorer::IDevice::ConstPtr& device, QPointer<Tizen::SdbConnector> conn, QObject * parent) :
- ProjectExplorer::DeviceProcessList(device, parent),
- m_executor(NULL),
- m_connector(conn)
- {
- }
- TizenDeviceProcessList::~TizenDeviceProcessList()
- {
- }
- static QString listProcessesCommandLine()
- {
- return QString::fromLatin1(
- "for dir in `ls -d /proc/[0123456789]*`; do "
- "test -d $dir || continue;" // Decrease the likelihood of a race condition.
- "echo $dir;"
- "cat $dir/cmdline;echo;" // cmdline does not end in newline
- "cat $dir/stat;"
- "readlink -q $dir/exe;"
- "printf '%1''%2';"
- "done").arg(QLatin1String(Delimiter0)).arg(QLatin1String(Delimiter1));
- }
- void TizenDeviceProcessList::doUpdate()
- {
- QTC_ASSERT(!m_executor, return);
- QTC_ASSERT(!m_connector.isNull(), return);
- m_executor = new Tizen::SdbCommandExecutor(m_connector.data(), this);
- connect(m_executor, SIGNAL(finished()), SLOT(handleListFinished()));
- connect(m_executor, SIGNAL(failed()), SLOT(handleError()));
- m_executor->start(device()->id().toString(), listProcessesCommandLine());
- }
- void TizenDeviceProcessList::doKillProcess(const DeviceProcess &process)
- {
- QTC_ASSERT(!m_executor, return);
- QTC_ASSERT(!m_connector.isNull(), return);
- m_executor = new Tizen::SdbCommandExecutor(m_connector.data(), this);
- connect(m_executor, SIGNAL(finished()), SLOT(handleKillFinished()));
- connect(m_executor, SIGNAL(failed()), SLOT(handleError()));
- m_executor->start(device()->id().toString(),
- device()->processSupport()->killProcessByPidCommandLine(process.pid));
- }
- void TizenDeviceProcessList::handleListFinished()
- {
- QByteArray remoteStdout = m_executor->readAll();
- m_executor->disconnect(this);
- m_executor->deleteLater();
- m_executor = NULL;
- reportProcessListUpdated(buildProcessList(QString::fromUtf8(remoteStdout.constData(), remoteStdout.size())));
- }
- void TizenDeviceProcessList::handleKillFinished()
- {
- m_executor->disconnect(this);
- m_executor->deleteLater();
- m_executor = NULL;
- reportProcessKilled();
- }
- void TizenDeviceProcessList::handleError()
- {
- reportError(tr("Communication failure"));
- }
- QString TizenDeviceProcessSupport::killProcessByPidCommandLine(int pid) const
- {
- return QLatin1String("kill -9 ") + QString::number(pid);
- }
- QString TizenDeviceProcessSupport::killProcessByNameCommandLine(const QString &filePath) const
- {
- return QString::fromLatin1("cd /proc; for pid in `ls -d [0123456789]*`; "
- "do "
- "if [ \"`readlink /proc/$pid/exe`\" = \"%1\" ]; then "
- " kill $pid; sleep 1; kill -9 $pid; "
- "fi; "
- "done").arg(filePath);
- }
- static QString signalProcessByNameCommandLine(const QString &filePath, int signal)
- {
- return QString::fromLatin1("cd /proc; for pid in `ls -d [0123456789]*`; "
- "do "
- "if [ \"`readlink /proc/$pid/exe`\" = \"%1\" ]; then "
- " kill %2 $pid;"
- "fi; "
- "done").arg(filePath).arg(signal);
- }
- QString TizenDeviceProcessSupport::interruptProcessByNameCommandLine(const QString &filePath) const
- {
- return signalProcessByNameCommandLine(filePath, 2);
- }
- TizenDevice::DevPtr TizenDevice::create(Core::Id id, DeviceState state, const QString &name)
- {
- return DevPtr(new TizenDevice(id, state, name));
- }
- TizenPortsGatheringMethod::~TizenPortsGatheringMethod()
- {
- }
- QByteArray TizenPortsGatheringMethod::commandLine(QAbstractSocket::NetworkLayerProtocol protocol) const
- {
- QString procFilePath;
- int addressLength;
- if (protocol == QAbstractSocket::IPv4Protocol) {
- procFilePath = QLatin1String("/proc/net/tcp");
- addressLength = 8;
- } else {
- procFilePath = QLatin1String("/proc/net/tcp6");
- addressLength = 32;
- }
- return QString::fromLatin1("sed "
- "'s/.*: [[:xdigit:]]\\{%1\\}:\\([[:xdigit:]]\\{4\\}\\).*/\\1/g' %2")
- .arg(addressLength).arg(procFilePath).toUtf8();
- }
- QList<int> TizenPortsGatheringMethod::usedPorts(const QByteArray &output) const
- {
- QList<int> ports;
- QList<QByteArray> portStrings = output.split('\n');
- portStrings.removeFirst();
- foreach (const QByteArray &portString, portStrings) {
- if (portString.isEmpty())
- continue;
- bool ok;
- const int port = portString.toInt(&ok, 16);
- if (ok) {
- if (!ports.contains(port))
- ports << port;
- } else {
- qWarning("%s: Unexpected string '%s' is not a port.",
- Q_FUNC_INFO, portString.data());
- }
- }
- return ports;
- }
- TizenDevice::TizenDevice()
- {
- }
- TizenDevice::TizenDevice(Core::Id id, DeviceState state, const QString& name) :
- IDevice(Constants::TIZEN_DEVICE_TYPE, AutoDetected, Hardware, id)
- {
- setDeviceState(state);
- setDisplayName(name);
- }
- TizenDevice::~TizenDevice()
- {
- }
- QString TizenDevice::displayType() const
- {
- return tr("Tizen Device");
- }
- ProjectExplorer::IDeviceWidget * TizenDevice::createWidget()
- {
- return NULL;
- }
- QList<Core::Id> TizenDevice::actionIds() const
- {
- return QList<Core::Id>() << Constants::DEVICE_ACTION_ROOT << Constants::DEVICE_ACTION_SHELL;
- }
- QString TizenDevice::displayNameForActionId(Core::Id id) const
- {
- if(id == Constants::DEVICE_ACTION_ROOT)
- return tr("Root mode");
- if(id == Constants::DEVICE_ACTION_SHELL)
- return tr("Shell");
- return QString();
- }
- void TizenDevice::executeAction(Core::Id id, QWidget *) const
- {
- if(id == Constants::DEVICE_ACTION_SHELL) {
- QString sdbPath = TizenConfigurations::instance()->tizenConfig().m_sdbLocation.toString();
- Utils::ConsoleProcess * process = new Utils::ConsoleProcess();
- if(!process->start(sdbPath, QString(QLatin1String("-s %1 shell")).arg(this->id().toString()))) {
- delete process;
- return;
- }
- QObject::connect(process, SIGNAL(processStopped(int,QProcess::ExitStatus)), process, SLOT(deleteLater()));
- }
- }
- TizenDevice::Ptr TizenDevice::clone() const
- {
- return Ptr(new TizenDevice(*this));
- }
- ProjectExplorer::DeviceProcessSupport::Ptr TizenDevice::processSupport() const
- {
- return DeviceProcessSupport::Ptr(new TizenDeviceProcessSupport);
- }
- ProjectExplorer::DeviceProcessList * TizenDevice::createProcessListModel(QObject *parent) const
- {
- return new TizenDeviceProcessList(sharedFromThis(), m_connector, parent);
- }
- ProjectExplorer::PortsGatheringMethod::Ptr TizenDevice::portsGatheringMethod() const
- {
- return ProjectExplorer::PortsGatheringMethod::Ptr(new TizenPortsGatheringMethod);
- }
- //ProjectExplorer::DeviceTester * TizenDevice::createDeviceTester() const
- //{
- // return new TizenDeviceTester(m_connector);
- //}
- } // namespace Tizen
- #include "tizendevice.moc"
|