You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/cervisia/cvsservice/sshagent.cpp

238 lines
6.1 KiB

/*
* Copyright (c) 2003 Christian Loose <christian.loose@hamburg.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "sshagent.h"
#include <tqregexp.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <kprocess.h>
#include <stdlib.h>
// initialize static member variables
bool SshAgent::m_isRunning = false;
bool SshAgent::m_isOurAgent = false;
TQString SshAgent::m_authSock = TQString();
TQString SshAgent::m_pid = TQString();
SshAgent::SshAgent(TQObject* parent, const char* name)
: TQObject(parent, name)
{
}
SshAgent::~SshAgent()
{
}
bool SshAgent::querySshAgent()
{
kdDebug(8051) << "SshAgent::querySshAgent(): ENTER" << endl;
if( m_isRunning )
return true;
// Did the user already start a ssh-agent process?
char* pid;
if( (pid = ::getenv("SSH_AGENT_PID")) != 0 )
{
kdDebug(8051) << "SshAgent::querySshAgent(): ssh-agent already exists"
<< endl;
m_pid = TQString::fromLocal8Bit(pid);
char* sock = ::getenv("SSH_AUTH_SOCK");
if( sock )
m_authSock = TQString::fromLocal8Bit(sock);
m_isOurAgent = false;
m_isRunning = true;
}
// We have to start a new ssh-agent process
else
{
kdDebug(8051) << "SshAgent::querySshAgent(): start ssh-agent" << endl;
m_isOurAgent = true;
m_isRunning = startSshAgent();
}
return m_isRunning;
}
bool SshAgent::addSshIdentities()
{
kdDebug(8051) << "SshAgent::addSshIdentities(): ENTER" << endl;
if( !m_isRunning || !m_isOurAgent )
return false;
// add identities to ssh-agent
KProcess proc;
proc.setEnvironment("SSH_AGENT_PID", m_pid);
proc.setEnvironment("SSH_AUTH_SOCK", m_authSock);
proc.setEnvironment("SSH_ASKPASS", "cvsaskpass");
proc << "ssh-add";
connect(&proc, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)),
TQT_SLOT(slotReceivedStdout(KProcess*, char*, int)));
connect(&proc, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)),
TQT_SLOT(slotReceivedStderr(KProcess*, char*, int)));
proc.start(KProcess::DontCare, KProcess::AllOutput);
// wait for process to finish
// TODO CL use timeout?
proc.wait();
kdDebug(8051) << "SshAgent::slotProcessExited(): added identities" << endl;
return (proc.normalExit() && proc.exitStatus() == 0);
}
void SshAgent::killSshAgent()
{
kdDebug(8051) << "SshAgent::killSshAgent(): ENTER" << endl;
if( !m_isRunning || !m_isOurAgent )
return;
KProcess proc;
proc << "kill" << m_pid;
proc.start(KProcess::DontCare, KProcess::NoCommunication);
kdDebug(8051) << "SshAgent::killSshAgent(): killed pid = " << m_pid << endl;
}
void SshAgent::slotProcessExited(KProcess*)
{
kdDebug(8051) << "SshAgent::slotProcessExited(): ENTER" << endl;
TQRegExp cshPidRx("setenv SSH_AGENT_PID (\\d*);");
TQRegExp cshSockRx("setenv SSH_AUTH_SOCK (.*);");
TQRegExp bashPidRx("SSH_AGENT_PID=(\\d*).*");
TQRegExp bashSockRx("SSH_AUTH_SOCK=(.*\\.\\d*);.*");
TQStringList::Iterator it = m_outputLines.begin();
TQStringList::Iterator end = m_outputLines.end();
for( ; it != end; ++it )
{
if( m_pid.isEmpty() )
{
int pos = cshPidRx.search(*it);
if( pos > -1 )
{
m_pid = cshPidRx.cap(1);
continue;
}
pos = bashPidRx.search(*it);
if( pos > -1 )
{
m_pid = bashPidRx.cap(1);
continue;
}
}
if( m_authSock.isEmpty() )
{
int pos = cshSockRx.search(*it);
if( pos > -1 )
{
m_authSock = cshSockRx.cap(1);
continue;
}
pos = bashSockRx.search(*it);
if( pos > -1 )
{
m_authSock = bashSockRx.cap(1);
continue;
}
}
}
kdDebug(8051) << "SshAgent::slotProcessExited(): pid = " << m_pid
<< ", socket = " << m_authSock << endl;
}
void SshAgent::slotReceivedStdout(KProcess* proc, char* buffer, int buflen)
{
Q_UNUSED(proc);
TQString output = TQString::fromLocal8Bit(buffer, buflen);
m_outputLines += TQStringList::split("\n", output);
kdDebug(8051) << "SshAgent::slotReceivedStdout(): output = " << output << endl;
}
void SshAgent::slotReceivedStderr(KProcess* proc, char* buffer, int buflen)
{
Q_UNUSED(proc);
TQString output = TQString::fromLocal8Bit(buffer, buflen);
m_outputLines += TQStringList::split("\n", output);
kdDebug(8051) << "SshAgent::slotReceivedStderr(): output = " << output << endl;
}
bool SshAgent::startSshAgent()
{
kdDebug(8051) << "SshAgent::startSshAgent(): ENTER" << endl;
KProcess proc;
proc << "ssh-agent";
connect(&proc, TQT_SIGNAL(processExited(KProcess*)),
TQT_SLOT(slotProcessExited(KProcess*)));
connect(&proc, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)),
TQT_SLOT(slotReceivedStdout(KProcess*, char*, int)));
connect(&proc, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)),
TQT_SLOT(slotReceivedStderr(KProcess*, char*, int)) );
proc.start(KProcess::NotifyOnExit, KProcess::All);
// wait for process to finish
// TODO CL use timeout?
proc.wait();
return (proc.normalExit() && proc.exitStatus() == 0);
}
#include "sshagent.moc"