diff options
Diffstat (limited to 'old/coreplugin/ssh/sshremoteprocess.cpp')
-rw-r--r-- | old/coreplugin/ssh/sshremoteprocess.cpp | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/old/coreplugin/ssh/sshremoteprocess.cpp b/old/coreplugin/ssh/sshremoteprocess.cpp new file mode 100644 index 0000000..c9566e9 --- /dev/null +++ b/old/coreplugin/ssh/sshremoteprocess.cpp @@ -0,0 +1,270 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "sshremoteprocess.h" +#include "sshremoteprocess_p.h" + +#include "sshdelayedsignal_p.h" +#include "sshincomingpacket_p.h" +#include "sshsendfacility_p.h" + +#include <botan/exceptn.h> + +namespace Core { + +const QByteArray SshRemoteProcess::AbrtSignal("ABRT"); +const QByteArray SshRemoteProcess::AlrmSignal("ALRM"); +const QByteArray SshRemoteProcess::FpeSignal("FPE"); +const QByteArray SshRemoteProcess::HupSignal("HUP"); +const QByteArray SshRemoteProcess::IllSignal("ILL"); +const QByteArray SshRemoteProcess::IntSignal("INT"); +const QByteArray SshRemoteProcess::KillSignal("KILL"); +const QByteArray SshRemoteProcess::PipeSignal("PIPE"); +const QByteArray SshRemoteProcess::QuitSignal("QUIT"); +const QByteArray SshRemoteProcess::SegvSignal("SEGV"); +const QByteArray SshRemoteProcess::TermSignal("TERM"); +const QByteArray SshRemoteProcess::Usr1Signal("USR1"); +const QByteArray SshRemoteProcess::Usr2Signal("USR2"); + +SshRemoteProcess::SshRemoteProcess(const QByteArray &command, quint32 channelId, + Internal::SshSendFacility &sendFacility) + : d(new Internal::SshRemoteProcessPrivate(command, channelId, sendFacility, this)) +{ +} + +SshRemoteProcess::~SshRemoteProcess() +{ + Q_ASSERT(d->channelState() == Internal::SshRemoteProcessPrivate::Inactive + || d->channelState() == Internal::SshRemoteProcessPrivate::CloseRequested + || d->channelState() == Internal::SshRemoteProcessPrivate::Closed); + delete d; +} + +void SshRemoteProcess::addToEnvironment(const QByteArray &var, const QByteArray &value) +{ + if (d->channelState() == Internal::SshRemoteProcessPrivate::Inactive) + d->m_env << qMakePair(var, value); // Cached locally and sent on start() +} + +void SshRemoteProcess::start() +{ + if (d->channelState() == Internal::SshRemoteProcessPrivate::Inactive) { +#ifdef CREATOR_SSH_DEBUG + qDebug("process start requested, channel id = %u", d->localChannelId()); +#endif + d->requestSessionStart(); + } +} + +void SshRemoteProcess::sendSignal(const QByteArray &signal) +{ + try { + if (isRunning()) + d->m_sendFacility.sendChannelSignalPacket(d->remoteChannel(), + signal); + } catch (Botan::Exception &e) { + d->setError(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; } + +namespace Internal { + +SshRemoteProcessPrivate::SshRemoteProcessPrivate(const QByteArray &command, + quint32 channelId, SshSendFacility &sendFacility, SshRemoteProcess *proc) + : AbstractSshChannel(channelId, sendFacility), m_procState(NotYetStarted), + m_wasRunning(false), m_exitCode(0), m_command(command), m_proc(proc) +{ +} + +void SshRemoteProcessPrivate::setProcState(ProcessState newState) +{ +#ifdef CREATOR_SSH_DEBUG + qDebug("channel: old state = %d,new state = %d", m_procState, newState); +#endif + m_procState = newState; + if (newState == StartFailed) { + createClosedSignal(SshRemoteProcess::FailedToStart); + } else if (newState == Running) { + m_wasRunning = true; + createStartedSignal(); + } +} + +void SshRemoteProcessPrivate::closeHook() +{ + if (m_wasRunning) { + if (!m_signal.isEmpty()) + createClosedSignal(SshRemoteProcess::KilledBySignal); + else + createClosedSignal(SshRemoteProcess::ExitedNormally); + } +} + +void SshRemoteProcessPrivate::handleOpenSuccessInternal() +{ + foreach (const EnvVar &envVar, m_env) { + m_sendFacility.sendEnvPacket(remoteChannel(), envVar.first, + envVar.second); + } + + m_sendFacility.sendExecPacket(remoteChannel(), m_command); + setProcState(ExecRequested); +} + +void SshRemoteProcessPrivate::handleOpenFailureInternal() +{ + setProcState(StartFailed); +} + +void SshRemoteProcessPrivate::handleChannelSuccess() +{ + if (m_procState != ExecRequested) { + throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, + "Unexpected SSH_MSG_CHANNEL_SUCCESS message."); + } + setProcState(Running); +} + +void SshRemoteProcessPrivate::handleChannelFailure() +{ + if (m_procState != ExecRequested) { + throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, + "Unexpected SSH_MSG_CHANNEL_FAILURE message."); + } + + setProcState(StartFailed); + closeChannel(); +} + +void SshRemoteProcessPrivate::handleChannelDataInternal(const QByteArray &data) +{ + createOutputAvailableSignal(data); +} + +void SshRemoteProcessPrivate::handleChannelExtendedDataInternal(quint32 type, + const QByteArray &data) +{ + if (type != SSH_EXTENDED_DATA_STDERR) + qWarning("Unknown extended data type %u", type); + else + createErrorOutputAvailableSignal(data); +} + +void SshRemoteProcessPrivate::handleChannelRequest(const SshIncomingPacket &packet) +{ + checkChannelActive(); + const QByteArray &requestType = packet.extractChannelRequestType(); + if (requestType == SshIncomingPacket::ExitStatusType) { + const SshChannelExitStatus status = packet.extractChannelExitStatus(); +#ifdef CREATOR_SSH_DEBUG + qDebug("Process exiting with exit code %d", status.exitStatus); +#endif + m_exitCode = status.exitStatus; + m_procState = Exited; + } else if (requestType == SshIncomingPacket::ExitSignalType) { + const SshChannelExitSignal &signal = packet.extractChannelExitSignal(); +#ifdef CREATOR_SSH_DEBUG + qDebug("Exit due to signal %s", signal.signal.data()); +#endif + setError(signal.error); + m_signal = signal.signal; + m_procState = Exited; + } else { + qWarning("Ignoring unknown request type '%s'", requestType.data()); + } +} + +void SshRemoteProcessPrivate::createStartedSignal() +{ + new SshRemoteProcessStartedSignal(this, QWeakPointer<SshRemoteProcess>(m_proc)); +} + +void SshRemoteProcessPrivate::emitStartedSignal() +{ + emit m_proc->started(); +} + +void SshRemoteProcessPrivate::createOutputAvailableSignal(const QByteArray &output) +{ + new SshRemoteProcessOutputAvailableSignal(this, + QWeakPointer<SshRemoteProcess>(m_proc), output); +} + +void SshRemoteProcessPrivate::emitOutputAvailableSignal(const QByteArray &output) +{ + emit m_proc->outputAvailable(output); +} + +void SshRemoteProcessPrivate::createErrorOutputAvailableSignal(const QByteArray &output) +{ + new SshRemoteProcessErrorOutputAvailableSignal(this, + QWeakPointer<SshRemoteProcess>(m_proc), output); +} + +void SshRemoteProcessPrivate::emitErrorOutputAvailableSignal(const QByteArray &output) +{ + emit m_proc->errorOutputAvailable(output); +} + +void SshRemoteProcessPrivate::createClosedSignal(int exitStatus) +{ + new SshRemoteProcessClosedSignal(this, + QWeakPointer<SshRemoteProcess>(m_proc), exitStatus); +} + +void SshRemoteProcessPrivate::emitClosedSignal(int exitStatus) +{ + emit m_proc->closed(exitStatus); +} + +} // namespace Internal +} // namespace Core |