/*
# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your suggestions, praise, or complaints to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org/
# --------------------------------------------------------------------------
# pvsPrivInputHandler.h
# - Handle privileged input connection requests - implementation
# --------------------------------------------------------------------------
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <QtDebug>
#include <QSocketNotifier>
#include "inputEvent.h"
#include "inputHandlerChains.h"
#include "pvsPrivInputSocket.h"
#include "pvsPrivInputHandler.h"
using namespace std;
class PrivInputContext : public InputEventContext
{
public:
PrivInputContext(pid_t pid, uid_t uid, gid_t gid)
: _pid(pid), _uid(uid), _gid(gid)
{
}
pid_t senderPid() const
{
return _pid;
}
uid_t senderUid() const
{
return _uid;
}
gid_t senderGid() const
{
return _gid;
}
private:
pid_t _pid;
uid_t _uid;
gid_t _gid;
};
PVSPrivInputHandler::PVSPrivInputHandler(int fd, QObject* parent) :
QObject(parent)
{
_fd = fd;
_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
_notifier->setEnabled(true);
connect(_notifier, SIGNAL(activated(int)), this, SLOT(canRead()));
_handlerChain = makePrivilegedInputEventHandlerChain();
}
PVSPrivInputHandler::~PVSPrivInputHandler()
{
delete _notifier;
}
void PVSPrivInputHandler::canRead()
{
_notifier->setEnabled(false);
// We need to retrieve the credentials of the process:
size_t siz = 8;
_messageAssembly.clear();
_messageAssembly.resize(8);
pid_t pid;
uid_t uid;
gid_t gid;
int err;
if(!pvsPrivInputRecvMessage(_fd, _messageAssembly.data(), siz, pid, uid, gid, &err))
{
switch(err)
{
case EAGAIN:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
// That's okay. Nothing to do.
break;
case 0:
// We'll survive. There was no actual error, just the library routine
// that decided it did not really want to receive that packet.
break;
default:
qWarning("Something bad just happened, and cannot handle it. Panicking.");
close(_fd);
deleteLater();
return;
}
}
else
{
if(siz != 8)
{
qWarning("Malformed PVS Input Event packet");
return;
}
QDataStream strm(&_messageAssembly, QIODevice::ReadOnly);
InputEvent evt;
strm.setByteOrder(QDataStream::BigEndian);
strm >> evt;
PrivInputContext ctx(pid, uid, gid);
_handlerChain.handle(evt, &ctx);
}
_notifier->setEnabled(true);
}