forked from qt-creator/qt-creator
SSH: Derive SshRemoteProcess from QIODevice.
Now it looks even more like QProcess. Things like process channels are still missing. Change-Id: I3f30cd00ed4a054d02e83add9a6f4162b48f8345 Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
This commit is contained in:
@@ -42,6 +42,8 @@
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
/*!
|
||||
\class Utils::SshRemoteProcess
|
||||
|
||||
@@ -49,17 +51,10 @@
|
||||
|
||||
Objects are created via SshConnection::createRemoteProcess.
|
||||
The process is started via the start() member function.
|
||||
A closeChannel() function is provided, but rarely useful, because
|
||||
|
||||
\list
|
||||
\i a) when the process ends, the channel is closed automatically, and
|
||||
\i b) closing a channel will not necessarily kill the remote process.
|
||||
\endlist
|
||||
|
||||
Therefore, the only sensible use case for calling closeChannel() is to
|
||||
get rid of an SshRemoteProces object before the process is actually started.
|
||||
If the process needs a pseudo terminal, you can request one
|
||||
via requestTerminal() before calling start().
|
||||
Note that this class does not support QIODevice's waitFor*() functions, i.e. it has
|
||||
no synchronous mode.
|
||||
*/
|
||||
|
||||
namespace Utils {
|
||||
@@ -99,12 +94,63 @@ SshRemoteProcess::~SshRemoteProcess()
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool SshRemoteProcess::atEnd() const
|
||||
{
|
||||
return QIODevice::atEnd() && d->m_stdout.isEmpty();
|
||||
}
|
||||
|
||||
qint64 SshRemoteProcess::bytesAvailable() const
|
||||
{
|
||||
return QIODevice::bytesAvailable() + d->m_stdout.count();
|
||||
}
|
||||
|
||||
bool SshRemoteProcess::canReadLine() const
|
||||
{
|
||||
return QIODevice::canReadLine() || d->m_stdout.contains('\n'); // TODO: Not cross-platform?
|
||||
}
|
||||
|
||||
QByteArray SshRemoteProcess::readAllStandardOutput()
|
||||
{
|
||||
return readAll();
|
||||
}
|
||||
|
||||
QByteArray SshRemoteProcess::readAllStandardError()
|
||||
{
|
||||
const QByteArray data = d->m_stderr;
|
||||
d->m_stderr.clear();
|
||||
return data;
|
||||
}
|
||||
|
||||
void SshRemoteProcess::close()
|
||||
{
|
||||
d->closeChannel();
|
||||
QIODevice::close();
|
||||
}
|
||||
|
||||
qint64 SshRemoteProcess::readData(char *data, qint64 maxlen)
|
||||
{
|
||||
const qint64 bytesRead = qMin(qint64(d->m_stdout.count()), maxlen);
|
||||
memcpy(data, d->m_stdout.constData(), bytesRead);
|
||||
d->m_stdout.remove(0, bytesRead);
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
qint64 SshRemoteProcess::writeData(const char *data, qint64 len)
|
||||
{
|
||||
if (isRunning()) {
|
||||
d->sendData(QByteArray(data, len));
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SshRemoteProcess::init()
|
||||
{
|
||||
connect(d, SIGNAL(started()), this, SIGNAL(started()),
|
||||
Qt::QueuedConnection);
|
||||
connect(d, SIGNAL(readyReadStandardOutput()), this, SIGNAL(readyReadStandardOutput()),
|
||||
Qt::QueuedConnection);
|
||||
connect(d, SIGNAL(readyReadStandardOutput()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
|
||||
connect(d, SIGNAL(readyReadStandardError()), this,
|
||||
SIGNAL(readyReadStandardError()), Qt::QueuedConnection);
|
||||
connect(d, SIGNAL(closed(int)), this, SIGNAL(closed(int)), Qt::QueuedConnection);
|
||||
@@ -129,6 +175,7 @@ void SshRemoteProcess::start()
|
||||
#ifdef CREATOR_SSH_DEBUG
|
||||
qDebug("process start requested, channel id = %u", d->localChannelId());
|
||||
#endif
|
||||
QIODevice::open(QIODevice::ReadWrite);
|
||||
d->requestSessionStart();
|
||||
}
|
||||
}
|
||||
@@ -140,36 +187,19 @@ void SshRemoteProcess::sendSignal(const QByteArray &signal)
|
||||
d->m_sendFacility.sendChannelSignalPacket(d->remoteChannel(),
|
||||
signal);
|
||||
} catch (Botan::Exception &e) {
|
||||
d->setError(QString::fromAscii(e.what()));
|
||||
setErrorString(QString::fromAscii(e.what()));
|
||||
d->closeChannel();
|
||||
}
|
||||
}
|
||||
|
||||
void SshRemoteProcess::closeChannel()
|
||||
{
|
||||
d->closeChannel();
|
||||
}
|
||||
|
||||
void SshRemoteProcess::sendInput(const QByteArray &data)
|
||||
{
|
||||
if (isRunning())
|
||||
d->sendData(data);
|
||||
}
|
||||
|
||||
bool SshRemoteProcess::isRunning() const
|
||||
{
|
||||
return d->m_procState == Internal::SshRemoteProcessPrivate::Running;
|
||||
}
|
||||
|
||||
QString SshRemoteProcess::errorString() const { return d->errorString(); }
|
||||
|
||||
int SshRemoteProcess::exitCode() const { return d->m_exitCode; }
|
||||
|
||||
QByteArray SshRemoteProcess::exitSignal() const { return d->m_signal; }
|
||||
|
||||
QByteArray SshRemoteProcess::readAllStandardOutput() { return d->readAllStandardOutput(); }
|
||||
QByteArray SshRemoteProcess::readAllStandardError() { return d->readAllStandardError(); }
|
||||
|
||||
namespace Internal {
|
||||
|
||||
SshRemoteProcessPrivate::SshRemoteProcessPrivate(const QByteArray &command,
|
||||
@@ -214,20 +244,6 @@ void SshRemoteProcessPrivate::setProcState(ProcessState newState)
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray SshRemoteProcessPrivate::readAllStandardOutput()
|
||||
{
|
||||
const QByteArray data = m_stdout;
|
||||
m_stdout.clear();
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray SshRemoteProcessPrivate::readAllStandardError()
|
||||
{
|
||||
const QByteArray data = m_stderr;
|
||||
m_stderr.clear();
|
||||
return data;
|
||||
}
|
||||
|
||||
void SshRemoteProcessPrivate::closeHook()
|
||||
{
|
||||
if (m_wasRunning) {
|
||||
@@ -256,9 +272,10 @@ void SshRemoteProcessPrivate::handleOpenSuccessInternal()
|
||||
m_timeoutTimer->start(ReplyTimeout);
|
||||
}
|
||||
|
||||
void SshRemoteProcessPrivate::handleOpenFailureInternal()
|
||||
void SshRemoteProcessPrivate::handleOpenFailureInternal(const QString &reason)
|
||||
{
|
||||
setProcState(StartFailed);
|
||||
m_proc->setErrorString(reason);
|
||||
}
|
||||
|
||||
void SshRemoteProcessPrivate::handleChannelSuccess()
|
||||
@@ -313,9 +330,9 @@ void SshRemoteProcessPrivate::handleExitSignal(const SshChannelExitSignal &signa
|
||||
#ifdef CREATOR_SSH_DEBUG
|
||||
qDebug("Exit due to signal %s", signal.signal.data());
|
||||
#endif
|
||||
setError(signal.error);
|
||||
m_signal = signal.signal;
|
||||
m_procState = Exited;
|
||||
m_proc->setErrorString(tr("Process killed by signal"));
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user