From e61097b8881bc7e72a5499816cb1199ea274a3ca Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Thu, 7 Oct 2010 22:54:10 +0200 Subject: Rework template meta-magic - No more implicit dependency on Boost.MPL - Better documentation for template magic - Move input handler policies to handler definitions where they belong - Separate out event descriptions from handlers --- src/input/inputEventHandler.h | 407 +++++++++++++++++++++--------------------- 1 file changed, 208 insertions(+), 199 deletions(-) (limited to 'src/input/inputEventHandler.h') diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 52e3338..5b03a90 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -22,274 +22,283 @@ #include #include #include -#include -#include -#include #include +#include "detail/policyChain.h" +#include "detail/systemTraits.h" -#define HANDLER_TYPE_DONT_CARE 0xffff -#define HANDLER_CODE_DONT_CARE 0xffff -#define HANDLER_VALUE_DONT_CARE 0xffffffff - -class InputEventContext -{ -public: - virtual pid_t getSenderPid() const = 0; - virtual uid_t getSenderUid() const = 0; - virtual gid_t getSenderGid() const = 0; -}; - -struct SpecialInputEventDescription +struct InputEventContext { - SpecialInputEventDescription(QString const& d, quint16 t, quint16 c, quint32 v = 0) - : descriptionString(d), evtType(t), evtCode(c), evtValue(v) + InputEventContext() { + hasBeenDenied = false; } - QString descriptionString; - quint16 evtType; - quint16 evtCode; - quint32 evtValue; + virtual pid_t getSenderPid() const = 0; + virtual uid_t getSenderUid() const = 0; + virtual gid_t getSenderGid() const = 0; - InputEvent toEvent() const - { - return InputEvent(evtType, evtCode, evtValue); - } + mutable bool hasBeenDenied; }; -template -class DefaultInputEventHandler { -protected: - static QString tr(char const* string) - { - return QCoreApplication::translate("InputEventHandler", string); - } - -public: - virtual bool matches(InputEvent const& evt, InputEventContext const*) { - if(Type != HANDLER_TYPE_DONT_CARE) { - if(evt.type() != Type) - return false; - } - if(Code != HANDLER_CODE_DONT_CARE) { - if(evt.code() != Code) - return false; - } - if(Value != HANDLER_VALUE_DONT_CARE) { - if(evt.value() != Value) - return false; - } - return true; - } +namespace input_policy +{ - virtual void initialize() +///////////////////////////////////////////////////////////////////////// +// Policy: +// Modifies the behaviour of an input handler class. +// +// There are several kinds of policy: +// - Security Policy (When to allow a certain action) +// - System Requirements (When to enable a certain handler) +// - Applicability (When to consider a certain handler) +// +// Policies are tied together using the detail::PolicyChain class. +///////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////// +// Security Policy: +// At the moment there are two security policies: +// 1. If the user is on a local seat, allow. If the user is privileged, +// allow. Else deny. +// 2. Allow everybody. +// Additional security policies can be added by following the example +// set by AllowLocalOrPrivileged +///////////////////////////////////////////////////////////////////////// +template +BEGIN_POLICY_CLASS(Security) +{ + bool allow(InputEventContext const* context) { + return PolicyImpl::allow(context); } +} +END_POLICY_CLASS - virtual void handle(InputEvent const& evt, InputEventContext const*) = 0; - - static void describeInto(QList& description) - { - } +struct AllowLocalOrPrivileged +{ + static bool allow(InputEventContext const*); }; -namespace policy { - -enum SecurityFlags { - SEC_FREE_FOR_ALL, - SEC_PHYSICAL_OR_PRIVILEGED +struct AllowEverybody +{ + static bool allow(InputEventContext const*); }; -bool allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx); -bool allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx); +typedef Security Unprivileged; -struct SecurityAllowAny +///////////////////////////////////////////////////////////////////////// +// System Requirements: +// At the moment, this is trivial, as PVS only runs on Linux. But, +// as porting efforts are already underway, we include the necessary +// machinery anyway. +///////////////////////////////////////////////////////////////////////// +template +BEGIN_POLICY_CLASS(Require) { - bool allow(InputEvent const& evt, InputEventContext const* ctx) - { - return true; - } + static const bool areSystemRequirementsFulfilled = + NextPolicy::areSystemRequirementsFulfilled && + detail::Matches::value; +} +END_POLICY_CLASS + +///////////////////////////////////////////////////////////////////////// +// System Requirements: +// At the moment, this is trivial, as PVS only runs on Linux. But, +// as porting efforts are already underway, we include the necessary +// machinery anyway. +///////////////////////////////////////////////////////////////////////// +enum { + HANDLER_CODE_DONT_CARE = 0xffff, + HANDLER_VALUE_DONT_CARE = 0xffffffff }; -struct SecurityAllowPhysicalOrPrivileged +struct T; + +template +BEGIN_POLICY_CLASS(Match) { - bool allow(InputEvent const& evt, InputEventContext const* ctx) + bool isApplicable(InputEvent const& evt) { - if(allowPhysicalSeat(evt, ctx)) - return true; - else if(allowPrivilegedUser(evt, ctx)) - return true; - return false; + if(evt.type() != EventType) + return NextPolicy::isApplicable(evt); + if(EventCode != HANDLER_CODE_DONT_CARE && evt.code() != EventCode) + return NextPolicy::isApplicable(evt); + if(EventValue != HANDLER_VALUE_DONT_CARE && evt.value() != EventValue) + return NextPolicy::isApplicable(evt); + return true; } }; +END_POLICY_CLASS -struct UnixLike; -struct Linux; -struct Windows; - -#if defined(__linux) -typedef boost::mpl::vector2::type Systems; -#elif defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) -typedef boost::mpl::vector1::type Systems; -#else -# error "Porting is needed!" -#endif - -struct SystemEnabled; -struct SystemDisabled; - -template -struct RequireSystem -{ - typedef typename boost::mpl::contains::type enabled_type; - static const bool enabled = enabled_type::value; -}; - -struct RequireNoSystem +namespace detail { - typedef boost::mpl::bool_::type enabled_type; - static const bool enabled = enabled_type::value; -}; -} - -template -class HandlerHelper +///////////////////////////////////////////////////////////////////////// +// Base case: If no policies are given: +///////////////////////////////////////////////////////////////////////// +struct InputEventHandlerPolicyBase { -public: - bool handle(InputEvent const& evt, InputEventContext const* context = 0) { - if(!securityPolicy.allow(evt, context)) - { - std::string evtStr = evt.toString(); - qWarning("Input Event %s has been denied by security policy", evtStr.c_str()); - return true; - } - if(delegate.matches(evt, context)) { - delegate.handle(evt, context); - return true; - } else { - return false; - } - } + // The default security policy applies + typedef AllowLocalOrPrivileged DefaultSecurityPolicyImpl; - void initialize() + bool allow(InputEventContext const* context) { - delegate.initialize(); + return DefaultSecurityPolicyImpl::allow(context); } - static void describeInto(QList& list) - { - Delegate::describeInto(list); - } + // A handler that does not specify requirements works + // everywhere + static const bool areSystemRequirementsFulfilled = true; -private: - Delegate delegate; - SecurityPolicy securityPolicy; -}; - -template -class HandlerHelper -{ -public: - bool handle(InputEvent const& evt, InputEventContext const* context = 0) { + // Generate an error when no match policy is given. + bool isApplicable(InputEvent const&) + { return false; } + // If any policy implementation needs an initialization hook: + // Don't forget to call NextPolicy::initialize() in your + // implementation! void initialize() { } - - static void describeInto(QList&) - { - } }; -template -struct Handler : public HandlerHelper -{ -}; +} +} -template -struct ApplyDefaultSecurityPolicy +///////////////////////////////////////////////////////////////////////// +// We want a nice non-generic base so we can make a list of polymorphic +// handlers. +// +// The actual handler class need to provide doHandle and can override +// allow and isApplicable. +///////////////////////////////////////////////////////////////////////// +/* interface */ class InputEventHandlerBase { - typedef HandlerType type; -}; +public: + enum HandlerStatus + { + HANDLER_MATCHED, + HANDLER_NOT_ALLOWED, + HANDLER_NOT_APPLICABLE + }; -template -struct ApplyDefaultSecurityPolicy > -{ - typedef Handler type; + virtual void initialize() = 0; + HandlerStatus handle(InputEvent const& evt, InputEventContext const* context = 0); + +protected: + virtual bool allow(InputEvent const& event, InputEventContext const* context = 0) = 0; + virtual bool isApplicable(InputEvent const& event, InputEventContext const* context = 0) = 0; + virtual void doHandle(InputEvent const& event, InputEventContext const* context = 0) = 0; }; -template -struct InputEventHandlerChainHelper +///////////////////////////////////////////////////////////////////////// +// Now that the machinery is in place, we can finally define what it +// is like to be an input event handler: +///////////////////////////////////////////////////////////////////////// +template +class InputEventHandler : public InputEventHandlerBase { -private: - typedef typename boost::mpl::next::type next_iterator_type; - typedef InputEventHandlerChainHelper next_in_chain; - - typedef typename boost::mpl::deref::type handler_entry_type; - typedef typename ApplyDefaultSecurityPolicy::type handler_type; - - handler_type _handler; - next_in_chain _next; +protected: + typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type; + policy_type policy; public: - void handle(InputEvent const& evt, InputEventContext const* context = 0) { - if(!_handler.handle(evt, context)) { - _next.handle(evt, context); - } + void initialize() + { + policy.initialize(); } - void initialize() { - _handler.initialize(); - _next.initialize(); - } + // Export this so the handler chain can decide whether to include this handler + static const bool areSystemRequirementsFulfilled = policy_type::areSystemRequirementsFulfilled; + +protected: + + typedef InputEventHandler super; - static void describeInto(QList& list) + // allow and isApplicable are actually provided by Policy. If the + // handler class wishes to override any of them, the policy implementation + // can be called by means of super. + bool allow(InputEvent const&, InputEventContext const* context = 0) { - handler_type::describeInto(list); - next_in_chain::describeInto(list); + return policy.allow(context); } - static QList describe() + bool isApplicable(InputEvent const& event, InputEventContext const* = 0) { - QList list; - describeInto(list); - return list; + return policy.isApplicable(event); } }; -template -struct InputEventHandlerChainHelper +///////////////////////////////////////////////////////////////////////// +// And we can chain input handlers together: +///////////////////////////////////////////////////////////////////////// +class InputEventHandlerChain { - void handle(InputEvent const&, InputEventContext const* context = 0) { - // do nothing - } +private: + QList handlers; + + ///////////////////////////////////////////////////////////////////////// + // We need to statically dispatch on a static member of HandlerType. + // Unfortunately, we cannot specialize member functions of a template. + // So, we need to make this a class with a static non-template member. + ///////////////////////////////////////////////////////////////////////// + template + struct ConditionallyAppend + { + static void doIt(InputEventHandlerChain* chain) + { + chain->handlers.append(new HandlerType); + } + }; - void initialize() { - // do nothing - } + template + struct ConditionallyAppend + { + static void doIt(InputEventHandlerChain*) + { + } + }; - static void describeInto(QList&) +public: + // Add an event handler to the chain. The argument is only for + // compilers which cannot handle template member functions + // correctly. + template + InputEventHandlerChain& add(HandlerType const* = 0) { - // do nothing + ConditionallyAppend::doIt(this); + return *this; } - static QList describe() + void initialize() { - return QList(); + QListIterator i(handlers); + while(i.hasNext()) + { + i.next()->initialize(); + } } -}; -template -struct InputEventHandlerChain : - public InputEventHandlerChainHelper::type, - typename boost::mpl::end::type> -{ + void handle(InputEvent const& event, InputEventContext const* context = 0) + { + QListIterator i(handlers); + while(i.hasNext()) + { + switch(i.next()->handle(event, context)) + { + case InputEventHandlerBase::HANDLER_MATCHED: + break; + case InputEventHandlerBase::HANDLER_NOT_ALLOWED: + context->hasBeenDenied = true; + case InputEventHandlerBase::HANDLER_NOT_APPLICABLE: + continue; + } + } + } }; #endif /* INPUTEVENTHANDLER_H_ */ -- cgit v1.2.3-55-g7522 From d45ad40dd76250d3f342d70159b3737be8562139 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:39:14 +0200 Subject: Code cleanup for inputEvent.h - Use Qt's fixed-width integral types instead of stdint.h, which I forgot to include anyway - CamelCase identifiers - fix underscore position on instance variables --- src/input/inputEvent.cpp | 4 +- src/input/inputEvent.h | 118 +++++++++++++++++------------------ src/input/inputEventHandler.h | 10 ++- src/input/x11FakeKeyboardHandler.cpp | 10 +-- 4 files changed, 74 insertions(+), 68 deletions(-) (limited to 'src/input/inputEventHandler.h') diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp index fa623e1..b623281 100644 --- a/src/input/inputEvent.cpp +++ b/src/input/inputEvent.cpp @@ -18,13 +18,13 @@ // We implement operators to serialize and load an event: QDataStream& operator <<(QDataStream& ostrm, InputEvent const& evt) { - ostrm << evt.type_ << evt.code_ << evt.value_; + ostrm << evt._type << evt._code << evt._value; return ostrm; } QDataStream& operator >>(QDataStream& istrm, InputEvent& evt) { - istrm >> evt.type_ >> evt.code_ >> evt.value_; + istrm >> evt._type >> evt._code >> evt._value; return istrm; } diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index 82b059c..73b7129 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -39,19 +39,19 @@ private: friend void eventToString(InputEvent const& evt, QString& str); friend bool eventFromString(QString const& str, InputEvent& evt); - uint16_t type_; - uint16_t code_; - uint32_t value_; + quint16 _type; + quint16 _code; + quint32 _value; // InputEvents are immutable. Prohibit assignment: InputEvent& operator=(InputEvent const&); // There intentionally is no implementation. public: - InputEvent(uint16_t type, uint16_t code, uint32_t value = 0) : type_(type), code_(code), value_(value) + InputEvent(quint16 type, quint16 code, quint32 value = 0) : _type(type), _code(code), _value(value) { } - InputEvent(InputEvent const& other) : type_(other.type_), code_(other.code_), value_(other.value_) + InputEvent(InputEvent const& other) : _type(other._type), _code(other._code), _value(other._value) { } @@ -59,110 +59,110 @@ public: { } - static InputEvent mouseMotion(uint16_t x, uint16_t y) + static InputEvent mouseMotion(quint16 x, quint16 y) { - return InputEvent(ET_POINTER, 0, ((uint32_t)x << 16) | y); + return InputEvent(ET_POINTER, 0, ((quint32)x << 16) | y); } - static uint16_t mouseButtonsFromQt(int b); + static quint16 mouseButtonsFromQt(int b); static InputEvent mousePressRelease(int button, int buttons); static InputEvent keyboardPress(int key, int mods); static InputEvent keyboardRelease(int key, int mods); - static const uint16_t ET_KEY = 0; - static const uint16_t ET_BUTTON = 1; - static const uint16_t ET_POINTER = 2; - static const uint16_t ET_SPECIAL = 3; + static const quint16 ET_KEY = 0; + static const quint16 ET_BUTTON = 1; + static const quint16 ET_POINTER = 2; + static const quint16 ET_SPECIAL = 3; - static const uint16_t EC_PRESS = 0; - static const uint16_t EC_RELEASE = 1; - static const uint16_t EC_REBOOT = 2; - static const uint16_t EC_SYSRQ = 3; - static const uint16_t EC_KILL_X = 4; - static const uint16_t EC_SAY_HELLO = 5; //< for debugging purposes + static const quint16 EC_PRESS = 0; + static const quint16 EC_RELEASE = 1; + static const quint16 EC_REBOOT = 2; + static const quint16 EC_SYSRQ = 3; + static const quint16 EC_KILL_X = 4; + static const quint16 EC_SAY_HELLO = 5; //< for debugging purposes - typedef uint32_t event_key; + typedef quint32 event_key; - typedef uint32_t event_key_modifiers; + typedef quint32 event_key_modifiers; - static const uint16_t EB_LEFT = 1; - static const uint16_t EB_MIDDLE = 2; - static const uint16_t EB_RIGHT = 4; + static const quint16 EB_LEFT = 1; + static const quint16 EB_MIDDLE = 2; + static const quint16 EB_RIGHT = 4; - static const uint32_t MODIFIER_MASK = + static const quint32 MODIFIER_MASK = 0x7e000000; - uint16_t type() const + quint16 type() const { - return type_; + return _type; } - uint16_t code() const + quint16 code() const { - return code_; + return _code; } - uint32_t value() const + quint32 value() const { - return value_; + return _value; } bool isKeyboard() const { - return type_ == ET_KEY; + return _type == ET_KEY; } bool isButton() const { - return type_ == ET_BUTTON; + return _type == ET_BUTTON; } bool isPointer() const { - return type_ == ET_POINTER; + return _type == ET_POINTER; } bool isSpecial() const { - return type_ == ET_SPECIAL; + return _type == ET_SPECIAL; } bool isPress() const { - return code_ == EC_PRESS; + return _code == EC_PRESS; } bool isRelease() const { - return code_ == EC_RELEASE; + return _code == EC_RELEASE; } - uint16_t pressedButton() const + quint16 pressedButton() const { - assert(type_ == ET_BUTTON); - return (value_ >> 16); + assert(_type == ET_BUTTON); + return (_value >> 16); } - uint16_t heldButtons() const + quint16 heldButtons() const { - assert(type_ == ET_BUTTON); - return (value_ & 0xffff); + assert(_type == ET_BUTTON); + return (_value & 0xffff); } - uint16_t xCoord() const + quint16 xCoord() const { - assert(type_ == ET_POINTER); - return (value_ >> 16); + assert(_type == ET_POINTER); + return (_value >> 16); } - uint16_t yCoord() const + quint16 yCoord() const { - assert(type_ == ET_POINTER); - return (value_ & 0xffff); + assert(_type == ET_POINTER); + return (_value & 0xffff); } - static QString typeToString(uint16_t type) + static QString typeToString(quint16 type) { switch(type) { @@ -179,7 +179,7 @@ public: } } - static QString codeToString(uint16_t code) + static QString codeToString(quint16 code) { switch(code) { @@ -200,17 +200,17 @@ public: QString toString() const { - return QString("%1:%2:%3").arg(typeToString(type_)).arg(codeToString(code_)).arg(value_, 16); + return QString("%1:%2:%3").arg(typeToString(_type)).arg(codeToString(_code)).arg(_value, 16); } - uint32_t qt_keysym() const + quint32 qtKeysym() const { - return value_ & ~MODIFIER_MASK; + return _value & ~MODIFIER_MASK; } - uint32_t qt_modifiers() const + quint32 qtModifiers() const { - return value_ & MODIFIER_MASK; + return _value & MODIFIER_MASK; } // We want to enable InputEvent as a translation context, so we fake the tr method: @@ -222,14 +222,14 @@ public: struct SpecialInputEventDescription { - SpecialInputEventDescription(uint16_t type, uint16_t code, uint32_t value, QString const& description_) + SpecialInputEventDescription(quint16 type, quint16 code, quint32 value, QString const& description_) : type(type), code(code), value(value), description(description_) { } - uint16_t type; - uint16_t code; - uint32_t value; + quint16 type; + quint16 code; + quint32 value; QString description; InputEvent toEvent() const diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 5b03a90..71a530b 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -176,7 +176,7 @@ struct InputEventHandlerPolicyBase // The actual handler class need to provide doHandle and can override // allow and isApplicable. ///////////////////////////////////////////////////////////////////////// -/* interface */ class InputEventHandlerBase +class InputEventHandlerBase { public: enum HandlerStatus @@ -246,9 +246,15 @@ private: // Unfortunately, we cannot specialize member functions of a template. // So, we need to make this a class with a static non-template member. ///////////////////////////////////////////////////////////////////////// - template + template struct ConditionallyAppend { + ///////////////////////////////////////////////////////////////////////// + // This method will never be instantiated for handlers that are + // not Compatible, thus generating no reference to HandlerType + // and permitting compilation to proceed without + // tedious nested preprocessor conditionals. + ///////////////////////////////////////////////////////////////////////// static void doIt(InputEventHandlerChain* chain) { chain->handlers.append(new HandlerType); diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index a136e45..4e3449a 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -772,16 +772,16 @@ void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext c Display* dpy = X11InputUtils::display(); // find out which keysym caused this event: - KeycodeLookupTable::const_iterator i = keysyms.find(evt.qt_keysym()); + KeycodeLookupTable::const_iterator i = keysyms.find(evt.qtKeysym()); if(i == keysyms.end()) { // Special cases. We don't know how to directly translate those, so we will try to emulate them. - switch(evt.qt_keysym()) + switch(evt.qtKeysym()) { case Qt::Key_Backtab: - doHandle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab)); + doHandle(InputEvent(evt.type(), evt.code(), evt.qtModifiers() | Qt::ShiftModifier | Qt::Key_Tab)); break; default: - ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qt_keysym(), 8, 16)); + ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qtKeysym(), 8, 16)); } } else { KeySym ks = (*i).second; @@ -805,7 +805,7 @@ void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext c else { // what modifier keys do we need to press? - XModifiers mods = translateModifiers(evt.qt_modifiers()); + XModifiers mods = translateModifiers(evt.qtModifiers()); // we may need to press additional modifiers to generate this keysym: if(QChar(ks, 0).isLetter()) -- cgit v1.2.3-55-g7522 From 18f16ac568d0c699fe24271c5b77f573b749092e Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:40:33 +0200 Subject: Lose the `get' method prefix on InputEventContext since it does not fit in --- src/input/inputEventHandler.h | 6 +++--- src/input/killX11Handler.cpp | 2 +- src/input/pvsCheckPrivileges.h | 6 +++--- src/input/pvsPrivInputHandler.cpp | 6 +++--- src/input/sayHelloHandler.cpp | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/input/inputEventHandler.h') diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 71a530b..735b75c 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -33,9 +33,9 @@ struct InputEventContext hasBeenDenied = false; } - virtual pid_t getSenderPid() const = 0; - virtual uid_t getSenderUid() const = 0; - virtual gid_t getSenderGid() const = 0; + virtual pid_t senderPid() const = 0; + virtual uid_t senderUid() const = 0; + virtual gid_t senderGid() const = 0; mutable bool hasBeenDenied; }; diff --git a/src/input/killX11Handler.cpp b/src/input/killX11Handler.cpp index 572656e..32e5873 100644 --- a/src/input/killX11Handler.cpp +++ b/src/input/killX11Handler.cpp @@ -33,7 +33,7 @@ void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx) if(displayDevice.isNull()) { - qWarning("Can not kill X server for %d,%d,%d: No Display Device", ctx->getSenderPid(), ctx->getSenderUid(), ctx->getSenderGid()); + qWarning("Can not kill X server for %d,%d,%d: No Display Device", ctx->senderPid(), ctx->senderUid(), ctx->senderGid()); return; } diff --git a/src/input/pvsCheckPrivileges.h b/src/input/pvsCheckPrivileges.h index 62b463c..92c68fe 100644 --- a/src/input/pvsCheckPrivileges.h +++ b/src/input/pvsCheckPrivileges.h @@ -32,9 +32,9 @@ struct CachedInputContext { if(source) { - pid = source->getSenderPid(); - uid = source->getSenderUid(); - gid = source->getSenderGid(); + pid = source->senderPid(); + uid = source->senderUid(); + gid = source->senderGid(); } else { diff --git a/src/input/pvsPrivInputHandler.cpp b/src/input/pvsPrivInputHandler.cpp index bfa60ce..84ccbae 100644 --- a/src/input/pvsPrivInputHandler.cpp +++ b/src/input/pvsPrivInputHandler.cpp @@ -35,17 +35,17 @@ public: { } - pid_t getSenderPid() const + pid_t senderPid() const { return _pid; } - uid_t getSenderUid() const + uid_t senderUid() const { return _uid; } - gid_t getSenderGid() const + gid_t senderGid() const { return _gid; } diff --git a/src/input/sayHelloHandler.cpp b/src/input/sayHelloHandler.cpp index 712963d..301709f 100644 --- a/src/input/sayHelloHandler.cpp +++ b/src/input/sayHelloHandler.cpp @@ -21,5 +21,5 @@ using namespace std; void SayHelloHandler::doHandle(InputEvent const&, InputEventContext const* ctx) { - cerr << "I'm right here! You sent this message from pid " << ctx->getSenderPid() << " as user " << ctx->getSenderUid() << " with gid " << ctx->getSenderGid() << endl; + cerr << "I'm right here! You sent this message from pid " << ctx->senderPid() << " as user " << ctx->senderUid() << " with gid " << ctx->senderGid() << endl; } -- cgit v1.2.3-55-g7522 From 2d31480bf052e3176edfbdc914ff5a29d54dc46c Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:41:48 +0200 Subject: Introduce an implicit logical AND into Require policy --- src/input/inputEventHandler.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/input/inputEventHandler.h') diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 735b75c..46e688c 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -92,12 +92,12 @@ typedef Security Unprivileged; // as porting efforts are already underway, we include the necessary // machinery anyway. ///////////////////////////////////////////////////////////////////////// -template +template BEGIN_POLICY_CLASS(Require) { static const bool areSystemRequirementsFulfilled = - NextPolicy::areSystemRequirementsFulfilled && - detail::Matches::value; + NextPolicy::areSystemRequirementsFulfilled || + detail::Matches, detail::SystemTraits>::value; } END_POLICY_CLASS -- cgit v1.2.3-55-g7522 From e659552d9b4c3889522d018e76c00adbe507d045 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:42:18 +0200 Subject: Add some comments to inputEventHandler.h --- src/input/inputEventHandler.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/input/inputEventHandler.h') diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 46e688c..3879b80 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -26,6 +26,11 @@ #include "detail/policyChain.h" #include "detail/systemTraits.h" +///////////////////////////////////////////////////////////////////////// +// InputEventContext: +// For handling access control, this specifies who sent the input event. +// This only makes sense in the privileged input handler chain. +///////////////////////////////////////////////////////////////////////// struct InputEventContext { InputEventContext() @@ -37,6 +42,7 @@ struct InputEventContext virtual uid_t senderUid() const = 0; virtual gid_t senderGid() const = 0; + // Support the generation of meaningful log messages: mutable bool hasBeenDenied; }; @@ -203,6 +209,7 @@ template class InputEventHandler : public InputEventHandlerBase { protected: + // instantiate our policy: typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type; policy_type policy; -- cgit v1.2.3-55-g7522 From f6d1c5346fc3b950fe31f7f6f920699e9835cb62 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 14:31:25 +0200 Subject: Fix bug in logical OR when chaining Require<...> Policy. --- src/input/inputEventHandler.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/input/inputEventHandler.h') diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 3879b80..11e2f4e 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -102,8 +102,10 @@ template BEGIN_POLICY_CLASS(Require) { static const bool areSystemRequirementsFulfilled = - NextPolicy::areSystemRequirementsFulfilled || - detail::Matches, detail::SystemTraits>::value; + (NextPolicy::areSystemRequirementsFulfilled + && !NextPolicy::areSystemRequirementsVacuouslyFulfilled) + || detail::Matches, detail::SystemTraits>::value; + static const bool areSystemRequirementsVacuouslyFulfilled = false; } END_POLICY_CLASS @@ -158,6 +160,9 @@ struct InputEventHandlerPolicyBase // everywhere static const bool areSystemRequirementsFulfilled = true; + // We need this to implement proper logical OR + static const bool areSystemRequirementsVacuouslyFulfilled = true; + // Generate an error when no match policy is given. bool isApplicable(InputEvent const&) { -- cgit v1.2.3-55-g7522 From 6fcd6c00510d4da9c72d1d44c769bb0d546ca9ef Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 12 Oct 2010 05:16:37 +0200 Subject: Fix InputEventHandler logic bug Entered break instead of return. --- src/input/inputEventHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/input/inputEventHandler.h') diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 11e2f4e..a2e943e 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -309,7 +309,7 @@ public: switch(i.next()->handle(event, context)) { case InputEventHandlerBase::HANDLER_MATCHED: - break; + return; case InputEventHandlerBase::HANDLER_NOT_ALLOWED: context->hasBeenDenied = true; case InputEventHandlerBase::HANDLER_NOT_APPLICABLE: -- cgit v1.2.3-55-g7522 From 7e3b963e3a0cbbf9391243e72ceb015e9015d630 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sat, 23 Oct 2010 17:49:12 +0200 Subject: Documentation fixes and code cleanup --- doc/doxconf | 10 +- src/input/detail/gen/gen_typeList.cpp | 3 + src/input/detail/typeList_autogen.h | 2 + src/input/i18n/pvsinput_ar_JO.ts | 46 +++---- src/input/i18n/pvsinput_de_DE.ts | 46 +++---- src/input/i18n/pvsinput_es_MX.ts | 46 +++---- src/input/i18n/pvsinput_fr_FR.ts | 46 +++---- src/input/i18n/pvsinput_pl_PL.ts | 46 +++---- src/input/inputEvent.cpp | 32 ++++- src/input/inputEvent.h | 245 +++++++++++++++++++++++++++------ src/input/inputEventHandler.h | 198 ++++++++++++++++++-------- src/input/inputHandlerChains.h | 15 ++ src/input/killX11Handler.h | 11 ++ src/input/logNonMatchingHandler.h | 3 + src/input/magicSysRqHandler.h | 12 +- src/input/privilegedHandlerForwarder.h | 13 ++ src/input/pvsCheckPrivileges.h | 65 +++++++-- src/input/pvsPrivInputHandler.h | 9 ++ src/input/pvsPrivInputSignalHandler.h | 17 +++ src/input/pvsPrivInputSocket.h | 38 +++++ src/input/pvsSyslog.h | 9 ++ src/input/rebootSystemHandler.h | 6 + src/input/sayHelloHandler.h | 4 + src/input/x11FakeKeyboardHandler.h | 7 + src/input/x11FakeMouseHandler.h | 6 + src/input/x11InputUtils.h | 3 + 26 files changed, 695 insertions(+), 243 deletions(-) (limited to 'src/input/inputEventHandler.h') diff --git a/doc/doxconf b/doc/doxconf index 50334c7..e3e32a6 100644 --- a/doc/doxconf +++ b/doc/doxconf @@ -564,7 +564,7 @@ WARN_LOGFILE = ./doxwarnlog # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ./pvsClient.h ./pvsClient.cpp ./pvs.h ./pvs.cpp ./pvsDaemon.h ./pvsDaemon.cpp ./src +INPUT = ../pvsClient.h ../pvsClient.cpp ../pvs.h ../pvs.cpp ../pvsDaemon.h ../pvsDaemon.cpp ../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -1210,13 +1210,13 @@ ENABLE_PREPROCESSING = YES # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. @@ -1244,7 +1244,9 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = +PREDEFINED = "DOXYGEN_RUNNING" \ + "BEGIN_POLICY_CLASS(name)=class name" \ + "END_POLICY_CLASS=;" # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/src/input/detail/gen/gen_typeList.cpp b/src/input/detail/gen/gen_typeList.cpp index e092b80..21056f9 100644 --- a/src/input/detail/gen/gen_typeList.cpp +++ b/src/input/detail/gen/gen_typeList.cpp @@ -47,6 +47,8 @@ int main(int, char**) cout << "template\n" "struct Contains { static const int index = -1; static const bool value = false; };\n"; + // specializations: + cout << "#ifndef DOXYGEN_RUNNING\n"; for(i = 0; i < NUM_MAX_ENTRIES; i++) { int j; @@ -70,6 +72,7 @@ int main(int, char**) } cout << "> >\n{ static const int index = " << i << "; static const bool value = true; };\n"; } + cout << "#endif\n"; // Empty List: cout << "typedef TypeList<"; diff --git a/src/input/detail/typeList_autogen.h b/src/input/detail/typeList_autogen.h index 0f8fdd4..79f1335 100644 --- a/src/input/detail/typeList_autogen.h +++ b/src/input/detail/typeList_autogen.h @@ -5,6 +5,7 @@ typedef TypeList struct Contains { static const int index = -1; static const bool value = false; }; +#ifndef DOXYGEN_RUNNING template struct Contains > { static const int index = 0; static const bool value = true; }; @@ -53,6 +54,7 @@ struct Contains struct Contains > { static const int index = 15; static const bool value = true; }; +#endif typedef TypeList EmptyList; #define IMPLICIT_TYPE_LIST_PARAMS(prefix) typename prefix##0 = void, typename prefix##1 = void, typename prefix##2 = void, typename prefix##3 = void, typename prefix##4 = void, typename prefix##5 = void, typename prefix##6 = void, typename prefix##7 = void, typename prefix##8 = void, typename prefix##9 = void, typename prefix##10 = void, typename prefix##11 = void, typename prefix##12 = void, typename prefix##13 = void, typename prefix##14 = void, typename prefix##15 = void #define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) typename prefix##0, typename prefix##1, typename prefix##2, typename prefix##3, typename prefix##4, typename prefix##5, typename prefix##6, typename prefix##7, typename prefix##8, typename prefix##9, typename prefix##10, typename prefix##11, typename prefix##12, typename prefix##13, typename prefix##14, typename prefix##15 diff --git a/src/input/i18n/pvsinput_ar_JO.ts b/src/input/i18n/pvsinput_ar_JO.ts index 1040142..bf25eda 100644 --- a/src/input/i18n/pvsinput_ar_JO.ts +++ b/src/input/i18n/pvsinput_ar_JO.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/i18n/pvsinput_de_DE.ts b/src/input/i18n/pvsinput_de_DE.ts index 56ebf26..002016a 100644 --- a/src/input/i18n/pvsinput_de_DE.ts +++ b/src/input/i18n/pvsinput_de_DE.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello Hallo sagen - + Reboot Neustart - + Kill X Server X-Server töten - + Reboot immediately Sofort neu starten - + Power off immediately Sofort abschalten - + Crash System Systemabsturz - + Turn off raw keyboard mode RAW-Tastatur-Modus abschalten - + Send SIGTERM to all SIGTERM an alle Prozesse senden - + Send SIGKILL to all SIGKILL an alle Prozesse senden - + Kill all on this terminal Alle Prozesse an diesem Terminal töten - + Activate OOM killer OOM-Killer aktivieren - + Make real-time tasks niceable Nice für Echtzeitprozesse ermöglichen - + Force-thaw filesystems - + Sync all mounted filesystems Alle eingebundenen Dateisysteme sync(2)en - + Remount all readonly Alle Dateisysteme nur-lesbar mounten - + Show all held locks Alle gehaltenen Sperren zeigen - + Show stack traces Stacktraces anzigen - + Dump memory info Speicherinfo anzeigen - + Dump registers and flags Register und Flags anzeigen - + Dump timers and clockevents Timer und Clockevents anzeigen - + Dump task list Taskliste anzeigen - + Dump uninterruptible tasks Ununterbrechbare Tasks anzeigen - + Dump ftrace buffer ftrace-Puffer anzeigen diff --git a/src/input/i18n/pvsinput_es_MX.ts b/src/input/i18n/pvsinput_es_MX.ts index 047c59c..d805d0e 100644 --- a/src/input/i18n/pvsinput_es_MX.ts +++ b/src/input/i18n/pvsinput_es_MX.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/i18n/pvsinput_fr_FR.ts b/src/input/i18n/pvsinput_fr_FR.ts index 8e3e417..af231ea 100644 --- a/src/input/i18n/pvsinput_fr_FR.ts +++ b/src/input/i18n/pvsinput_fr_FR.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/i18n/pvsinput_pl_PL.ts b/src/input/i18n/pvsinput_pl_PL.ts index 87527d5..11365c0 100644 --- a/src/input/i18n/pvsinput_pl_PL.ts +++ b/src/input/i18n/pvsinput_pl_PL.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp index b623281..cff1ac8 100644 --- a/src/input/inputEvent.cpp +++ b/src/input/inputEvent.cpp @@ -1,8 +1,17 @@ /* - * inputEvent.cpp - * - * Created on: 06.09.2010 - * Author: brs + # 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/ + # -------------------------------------------------------------------------- + # inputEvent.h: + # - Definition of an input event - utility routines + # -------------------------------------------------------------------------- */ #include @@ -16,18 +25,29 @@ #include // We implement operators to serialize and load an event: +/** + * Serialize an input event to a \ref QDataStream. + */ QDataStream& operator <<(QDataStream& ostrm, InputEvent const& evt) { ostrm << evt._type << evt._code << evt._value; return ostrm; } +/** + * Load an input event from a \ref QDataStream. + */ QDataStream& operator >>(QDataStream& istrm, InputEvent& evt) { istrm >> evt._type >> evt._code >> evt._value; return istrm; } +/** + * Produce a string-encodeable representation of an input event. + * This consists of a base64-encoded binary representation as + * generated by \ref{operator<<(QDataStream&, InputEvent const&)}. + */ void eventToString(InputEvent const& evt, QString& str) { QByteArray ba; @@ -38,6 +58,10 @@ void eventToString(InputEvent const& evt, QString& str) str = QString::fromAscii(ba.toBase64()); } +/** + * Decode the string representation of an input-event produced by + * \ref eventToString. + */ bool eventFromString(QString const& str, InputEvent& evt) { // TODO This does not do proper error checking. Only use from trusted sources! diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index f9d3225..afb33e5 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -21,15 +21,23 @@ #include // for translation #include -#ifndef __linux -# error "This will only run on a Linux system. Porting is required for other systems." -#endif - struct QDataStream; struct QString; struct QMouseEvent; struct QKeyEvent; +/** + * The inputEvent class represents a single input event. + * An input event is any of: + * - Pressing or releasing a keyboard key, + * - Moving the mouse pointer, + * - Pressing or releasing a mouse button, + * - Special system events like "reboot". + * + * Events are described by the \ref type(), \ref code() + * and \ref value(). Possible values for \ref type() are given by + * the \c ET_* constants, and for \ref code() by the \c EC_* constants. + */ class InputEvent { private: @@ -59,109 +67,229 @@ public: { } - static InputEvent mouseMotion(quint16 x, quint16 y) - { - return InputEvent(ET_POINTER, 0, ((quint32)x << 16) | y); - } - - static quint16 mouseButtonsFromQt(int b); + /** \name Factory Functions */ + /* @{ */ + /** + * Generates an event for a mouse button press or release. + * \param button The button that caused this event, as defined by \ref Qt::MouseButton. + * \param buttons The buttons that were pressed at the moment the event was generated, as defined by \ref Qt::MouseButtons. + * If the event is a button press, this includes the pressed button. If it is a button release, + * it does not include the pressed button. + */ static InputEvent mousePressRelease(int button, int buttons); - static InputEvent keyboardPress(int key, int mods); - static InputEvent keyboardRelease(int key, int mods); - - static const quint16 ET_KEY = 0; - static const quint16 ET_BUTTON = 1; - static const quint16 ET_POINTER = 2; - static const quint16 ET_SPECIAL = 3; - static const quint16 EC_PRESS = 0; - static const quint16 EC_RELEASE = 1; - static const quint16 EC_REBOOT = 2; - static const quint16 EC_SYSRQ = 3; - static const quint16 EC_KILL_X = 4; - static const quint16 EC_SAY_HELLO = 5; //< for debugging purposes + /** + * Generates an event for a keyboard press. + * \param key The key code that generated this event, as defined by \ref Qt::Key. + * \param mods The modificator keys that were pressed at the moment the event was generated, + * as defined by \ref Qt::KeyboardModifiers. + */ + static InputEvent keyboardPress(int key, int mods); - typedef quint32 event_key; + /** + * Generates an event for a keyboard release. + * \param key The key code that generated this event, as defined by \ref Qt::Key. + * \param mods The modificator keys that were pressed at the moment the event was generated, + * as defined by \ref Qt::KeyboardModifiers. + */ + static InputEvent keyboardRelease(int key, int mods); - typedef quint32 event_key_modifiers; + /** + * Generates an event for a mouse pointer movement. + * \param x,y X and Y coordinates of the mouse pointer. + */ + static InputEvent mouseMotion(uint16_t x, uint16_t y) + { + return InputEvent(ET_POINTER, 0, ((uint32_t)x << 16) | y); + } - static const quint16 EB_LEFT = 1; - static const quint16 EB_MIDDLE = 2; - static const quint16 EB_RIGHT = 4; + /* @} */ + + /** \name Event Types */ + /* @{ */ + static const uint16_t ET_KEY = 0; /**< The event is related to the keyboard */ + static const uint16_t ET_BUTTON = 1; /**< The event is related to a mouse button */ + static const uint16_t ET_POINTER = 2; /**< The event is related to the mouse pointer */ + static const uint16_t ET_SPECIAL = 3; /**< The event is a special system event */ + /* @} */ + + /** \name Event Codes */ + /* @{ */ + static const uint16_t EC_PRESS = 0; /**< The event is a press (keyboard or mouse button) */ + static const uint16_t EC_RELEASE = 1; /**< The event is a release (keyboard or mouse button) */ + static const uint16_t EC_REBOOT = 2; /**< The event is a request to reboot (special system event) */ + static const uint16_t EC_SYSRQ = 3; /**< The event is a request to perform a Magic-SysRq function (special system event) */ + static const uint16_t EC_KILL_X = 4; /**< The event is a request to kill the X Server (special system event) */ + static const uint16_t EC_SAY_HELLO = 5; /**< The event is a request to write a line to the log file (special system event) */ + /* @} */ + + /** \name Mouse Button Flags */ + /* @{ */ + static const uint16_t EB_LEFT = 1; /**< The left mouse button */ + static const uint16_t EB_MIDDLE = 2; /**< The middle mouse button */ + static const uint16_t EB_RIGHT = 4; /**< The right mouse button */ + /* @} */ static const quint32 MODIFIER_MASK = 0x7e000000; - quint16 type() const + /** \name Event Decoding Functions */ + /* @{ */ + + /** + * Return the event type, as defined by the \c ET_* constants. + */ + uint16_t type() const { return _type; } - quint16 code() const + /** + * Return the event code, as defined by the \c EC_* constants. + */ + uint16_t code() const { return _code; } - quint32 value() const + /** + * Return the value associated with the event. The interpretation + * differs according to event type and code: + * - If the event type is \c ET_KEY, the value specifies which + * key and modifiers were pressed. + * - If the event type is \c ET_BUTTON, the value specifies which + * buttons were pressed and which button generated the event. + * - If the event type is \c ET_POINTER, the value specifies the + * screen coordinates the mouse has moved to. + * - If the event type is \c ET_SPECIAL, the interpretation + * depends on the event code. + */ + uint32_t value() const { return _value; } + /** + * True if the event is a keyboard event. + */ bool isKeyboard() const { return _type == ET_KEY; } + /** + * True if the event is a mouse button event. + */ bool isButton() const { return _type == ET_BUTTON; } + /** + * True if the event is a mouse pointer event. + */ bool isPointer() const { return _type == ET_POINTER; } + /** + * True if the event is a special system event. + */ bool isSpecial() const { return _type == ET_SPECIAL; } + /** + * True if the event is a keyboard or mouse button press event. + */ bool isPress() const { return _code == EC_PRESS; } + /** + * True if the event is a keyboard or mouse button release event. + */ bool isRelease() const { return _code == EC_RELEASE; } - quint16 pressedButton() const + /** + * The mouse button that generated this event. + * \return one of the \c EB_* constants. + */ + uint16_t pressedButton() const { assert(_type == ET_BUTTON); return (_value >> 16); } - quint16 heldButtons() const + /** + * The mouse buttons that were pressed at the moment the + * event was generated. + * \return a bitwise or of \c EB_* constants. + */ + uint16_t heldButtons() const { assert(_type == ET_BUTTON); return (_value & 0xffff); } - quint16 xCoord() const + /** + * The X coordinate the pointer was moved to. + */ + uint16_t xCoord() const { assert(_type == ET_POINTER); return (_value >> 16); } - quint16 yCoord() const + /** + * The Y coordinate the pointer was moved to. + */ + uint16_t yCoord() const { assert(_type == ET_POINTER); return (_value & 0xffff); } + /** + * The key that generated the event, as defined by \ref Qt::Key. + */ + quint32 qtKeysym() const + { + return _value & ~MODIFIER_MASK; + } + + /** + * The modifier keys that were pressed at the moment the event was generated, + * as defined by \ref Qt::KeyboardModifiers. + */ + quint32 qtModifiers() const + { + return _value & MODIFIER_MASK; + } + /* @} */ + + + /** \name Conversion Functions */ + /* @{ */ + + /** + * Converts mouse buttons from the bit flags defined by \ref Qt::MouseButton + * to their internal representation as defined in \ref "Mouse Button Flags". + * \returns A bitwise or of \c EB_* values. + */ + static uint16_t mouseButtonsFromQt(int b); + + /** + * Converts an event type as given by the \c ET_* constants to + * a string. + */ static QString typeToString(quint16 type) { switch(type) @@ -179,6 +307,10 @@ public: } } + /** + * Converts an event code as given by the \c EC_* constants to + * a string. + */ static QString codeToString(quint16 code) { switch(code) @@ -198,20 +330,15 @@ public: } } + /** + * Convert the event to a human-readable representation. + */ QString toString() const { return QString("%1:%2:%3").arg(typeToString(_type)).arg(codeToString(_code)).arg(_value, 8, 16, QLatin1Char('0')); } - quint32 qtKeysym() const - { - return _value & ~MODIFIER_MASK; - } - - quint32 qtModifiers() const - { - return _value & MODIFIER_MASK; - } + /* @} */ // We want to enable InputEvent as a translation context, so we fake the tr method: static QString tr(const char* string) @@ -220,23 +347,51 @@ public: } }; +/** + * The SpecialInputEventDescription class provides a human-readable + * name for special system events. + * + * To use the translations of these descriptions in your program, + * you need to link to the \c libpvsinput library and + * use the \ref USE_PVSINPUT_TRANSLATIONS macro in your + * \c main function. + */ struct SpecialInputEventDescription { + /** + * Initialize an instance of the SpecialInputEventDescription class. + * This is only meant to be called from describeSpecialEvents(). + * If you need to add more special event descriptions, do so from there. + */ SpecialInputEventDescription(quint16 type, quint16 code, quint32 value, QString const& description_) : type(type), code(code), value(value), description(description_) { } + /** \name InputEvent fields + * \see InputEvent + */ + /* @{ */ quint16 type; quint16 code; quint32 value; - QString description; + /* @} */ + + QString description; /**< Human-readable description for a special input event. Can be translated via the + InputEvent::tr(char const*) method. */ + /** + * Returns an \ref InputEvent corresponding to this description. + */ InputEvent toEvent() const { return InputEvent(type, code, value); } + /** + * Returns a \ref QList of all known special system events with their human-readable + * description. + */ static QList describeSpecialEvents(); }; diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index a2e943e..783640f 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -26,11 +26,10 @@ #include "detail/policyChain.h" #include "detail/systemTraits.h" -///////////////////////////////////////////////////////////////////////// -// InputEventContext: -// For handling access control, this specifies who sent the input event. -// This only makes sense in the privileged input handler chain. -///////////////////////////////////////////////////////////////////////// +/** + * For handling access control, this specifies who sent the input event. + * This only really makes sense in the privileged input handler chain. + */ struct InputEventContext { InputEventContext() @@ -38,11 +37,11 @@ struct InputEventContext hasBeenDenied = false; } - virtual pid_t senderPid() const = 0; - virtual uid_t senderUid() const = 0; - virtual gid_t senderGid() const = 0; + virtual pid_t senderPid() const = 0; /**< PID of the sending process */ + virtual uid_t senderUid() const = 0; /**< UID of the sending process */ + virtual gid_t senderGid() const = 0; /**< GID of the sending process */ - // Support the generation of meaningful log messages: + /** Support the generation of meaningful log messages. */ mutable bool hasBeenDenied; }; @@ -61,15 +60,21 @@ namespace input_policy // Policies are tied together using the detail::PolicyChain class. ///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Security Policy: -// At the moment there are two security policies: -// 1. If the user is on a local seat, allow. If the user is privileged, -// allow. Else deny. -// 2. Allow everybody. -// Additional security policies can be added by following the example -// set by AllowLocalOrPrivileged -///////////////////////////////////////////////////////////////////////// +/** + * Security Policy. + * At the moment there are two security policies: + * -* If the user is on a local seat, allow. If the user is privileged, + * allow. Else deny. + * -* Allow everybody. + * + * Additional security policies can be added by following the example + * set by \ref AllowLocalOrPrivileged + * + * \param PolicyImpl The implementation class that security decisions + * should be delegated to. + * \see {AllowLocalOrPrivileged} + * \see {AllowEverybody} + */ template BEGIN_POLICY_CLASS(Security) { @@ -80,25 +85,43 @@ BEGIN_POLICY_CLASS(Security) } END_POLICY_CLASS +/** + * Check the default security model. + */ struct AllowLocalOrPrivileged { static bool allow(InputEventContext const*); }; +/** + * Do not restrict execution. + */ struct AllowEverybody { static bool allow(InputEventContext const*); }; +/** + * Shorthand for unrestricted execution. + */ typedef Security Unprivileged; -///////////////////////////////////////////////////////////////////////// -// System Requirements: -// At the moment, this is trivial, as PVS only runs on Linux. But, -// as porting efforts are already underway, we include the necessary -// machinery anyway. -///////////////////////////////////////////////////////////////////////// +/** + * System Requirements. + * + * At the moment, this is trivial, as PVS only runs on Linux. But, + * as porting efforts are already underway, we include the necessary + * machinery anyway. + * + * \param Trait... a list of system traits that need to be + * present in order for the handler that this policy is applied to + * to run. + */ +#ifdef DOXYGEN_RUNNING +template +#else template +#endif BEGIN_POLICY_CLASS(Require) { static const bool areSystemRequirementsFulfilled = @@ -109,19 +132,27 @@ BEGIN_POLICY_CLASS(Require) } END_POLICY_CLASS -///////////////////////////////////////////////////////////////////////// -// System Requirements: -// At the moment, this is trivial, as PVS only runs on Linux. But, -// as porting efforts are already underway, we include the necessary -// machinery anyway. -///////////////////////////////////////////////////////////////////////// +#ifndef DOXYGEN_RUNNING enum { HANDLER_CODE_DONT_CARE = 0xffff, HANDLER_VALUE_DONT_CARE = 0xffffffff }; - -struct T; - +#endif + +/** + * Event selection. + * + * This policy makes the handler it is applied to applicable if the + * template parameters \c EventType, \c EventCode and \c EventValue + * match the corresponding fields of the incoming \ref InputEvent. + * + * Can be applied multiple times, and will be combined by logical + * OR. + * + * \param EventType Match the \ref InputEvent::type() field. + * \param EventCode (optional:) Match the \ref InputEvent::code() field. + * \param EventValue (optional:) Match the \ref InputEvent::value() field. + */ template @@ -140,6 +171,7 @@ BEGIN_POLICY_CLASS(Match) }; END_POLICY_CLASS +#ifndef DOXYGEN_RUNNING namespace detail { @@ -177,46 +209,71 @@ struct InputEventHandlerPolicyBase } }; -} +} // namespace detail +#endif // DOXYGEN_RUNNING + } -///////////////////////////////////////////////////////////////////////// -// We want a nice non-generic base so we can make a list of polymorphic -// handlers. -// -// The actual handler class need to provide doHandle and can override -// allow and isApplicable. -///////////////////////////////////////////////////////////////////////// +/** + * Base class without template parameters to enable making a list of + * polymorphic event handlers. + * + * The actual handler class needs to provide \ref doHandle and can + * override \ref allow and \ref isApplicable. + * + * \note Do not derive from InputEventHandlerBase to implement + * new event handlers! Derive from InputEventHandler instead. + */ class InputEventHandlerBase { public: enum HandlerStatus { - HANDLER_MATCHED, - HANDLER_NOT_ALLOWED, - HANDLER_NOT_APPLICABLE + HANDLER_MATCHED, /**< The handler matched the input event and was executed. */ + HANDLER_NOT_ALLOWED, /**< Execution of the handler was prevented by security policy. */ + HANDLER_NOT_APPLICABLE /**< The handler did not match the input event. */ }; virtual void initialize() = 0; HandlerStatus handle(InputEvent const& evt, InputEventContext const* context = 0); protected: + /** + * Check security preconditions for the execution of this handler. + * This is normally handled by the \ref input_policy::Security policy. + */ virtual bool allow(InputEvent const& event, InputEventContext const* context = 0) = 0; + + /** + * Check if this handler can handle the incoming input event. + * This is normally handled by the \ref input_policy::Match policy. + */ virtual bool isApplicable(InputEvent const& event, InputEventContext const* context = 0) = 0; + + /** + * Actually handle the incoming event. + * It is assumed that all preconditions have been checked and the handler + * has been initialized at the point where this method is called. + */ virtual void doHandle(InputEvent const& event, InputEventContext const* context = 0) = 0; }; -///////////////////////////////////////////////////////////////////////// -// Now that the machinery is in place, we can finally define what it -// is like to be an input event handler: -///////////////////////////////////////////////////////////////////////// +/** + * Base class for input event handlers. + */ +#ifdef DOXYGEN_RUNNING +template +#else template +#endif class InputEventHandler : public InputEventHandlerBase { +#ifndef DOXYGEN_RUNNING protected: // instantiate our policy: typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type; policy_type policy; +#endif public: void initialize() @@ -224,16 +281,11 @@ public: policy.initialize(); } - // Export this so the handler chain can decide whether to include this handler + /** Export this so the handler chain can decide whether to include this handler */ static const bool areSystemRequirementsFulfilled = policy_type::areSystemRequirementsFulfilled; protected: - typedef InputEventHandler super; - - // allow and isApplicable are actually provided by Policy. If the - // handler class wishes to override any of them, the policy implementation - // can be called by means of super. bool allow(InputEvent const&, InputEventContext const* context = 0) { return policy.allow(context); @@ -245,14 +297,19 @@ protected: } }; -///////////////////////////////////////////////////////////////////////// -// And we can chain input handlers together: -///////////////////////////////////////////////////////////////////////// +/** + * Chain \ref InputEventHandler instances together. + * The chain is also responsible for the creation of instances. + * + * \see privilegedInputEventHandlerChain.cpp + * \see unprivilegedInputEventHandlerChain.cpp + */ class InputEventHandlerChain { private: QList handlers; +#ifndef DOXYGEN_RUNNING // Implementation detail ///////////////////////////////////////////////////////////////////////// // We need to statically dispatch on a static member of HandlerType. // Unfortunately, we cannot specialize member functions of a template. @@ -280,18 +337,31 @@ private: { } }; +#endif // DOXYGEN_RUNNING public: - // Add an event handler to the chain. The argument is only for - // compilers which cannot handle template member functions - // correctly. + /** + * Add an event handler to the chain. + * + * \param fake_parameter The parameter is only for + * compilers which cannot handle template member functions + * correctly. + * \return A reference to the receiver, for invocation chaining. + * + * \note Do not pass a value to this function. The function + * handles creation of an instance itself. + */ template - InputEventHandlerChain& add(HandlerType const* = 0) + InputEventHandlerChain& add(HandlerType const* fake_parameter = 0) { ConditionallyAppend::doIt(this); return *this; } + /** + * Call \ref InputEventHandlerBase::initialize() on all + * handlers in the chain. + */ void initialize() { QListIterator i(handlers); @@ -301,6 +371,12 @@ public: } } + /** + * Handle an input event. All handlers in the chain are tried + * in the order they were added, until one handler's + * implementation of InputEventHandlerBase::handle() returns + * InputEventHandlerBase::HANDLER_MATCHED. + */ void handle(InputEvent const& event, InputEventContext const* context = 0) { QListIterator i(handlers); diff --git a/src/input/inputHandlerChains.h b/src/input/inputHandlerChains.h index a91e605..773303b 100644 --- a/src/input/inputHandlerChains.h +++ b/src/input/inputHandlerChains.h @@ -19,7 +19,22 @@ #include "inputEventHandler.h" +/** \defgroup iehc {Input Event Handler Chains} */ +/* @{ */ + +/** + * Make an instance of InputEventHandlerChain that handles + * unprivileged input events, with a PrivilegedInputForwarder + * instance at the end. + */ InputEventHandlerChain makeUnprivilegedInputEventHandlerChain(); + +/** + * Make an instance of InputEventHandlerChain that handles + * privileged events. + */ InputEventHandlerChain makePrivilegedInputEventHandlerChain(); +/* @} */ + #endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/killX11Handler.h b/src/input/killX11Handler.h index 77d9fdb..6501d5d 100644 --- a/src/input/killX11Handler.h +++ b/src/input/killX11Handler.h @@ -20,11 +20,22 @@ #include #include "inputEventHandler.h" +/** + * Kills the X11 Server on Linux. + */ class KillX11Handler : public InputEventHandler< input_policy::Match, input_policy::Require > { public: + + /** + * Kills the X11 Server on Linux. + * + * The X11-Server is found by asking ConsoleKit for its controlling + * tty. The sole process that has an open file descriptor referencing it + * must be the X Server. It is then sent SIGTERM. + */ void doHandle(InputEvent const&, InputEventContext const*); }; diff --git a/src/input/logNonMatchingHandler.h b/src/input/logNonMatchingHandler.h index 3403640..ab95bce 100644 --- a/src/input/logNonMatchingHandler.h +++ b/src/input/logNonMatchingHandler.h @@ -19,6 +19,9 @@ #include "inputEventHandler.h" +/** + * Send a qWarning() for any InputEvent that does not have a matching handler. + */ class LogNonMatchingHandler : public InputEventHandler { public: diff --git a/src/input/magicSysRqHandler.h b/src/input/magicSysRqHandler.h index ba02997..5afe259 100644 --- a/src/input/magicSysRqHandler.h +++ b/src/input/magicSysRqHandler.h @@ -19,16 +19,20 @@ #include "inputEventHandler.h" +/** + * Emulate the magic SysRq-Key on Linux. + */ class MagicSysRqHandler : public InputEventHandler< input_policy::Match, input_policy::Require > { public: - void doHandle(InputEvent const& evt, InputEventContext const* ctx); -// static void describeInto(QList& list) -// { -// } + /** + * Send the least significant byte of \c evt's InputEvent::value() + * to the magic \c /proc/sysrq-trigger file. + */ + void doHandle(InputEvent const& evt, InputEventContext const* ctx); }; #endif /* MAGICSYSRQHANDLER_H_ */ diff --git a/src/input/privilegedHandlerForwarder.h b/src/input/privilegedHandlerForwarder.h index f5a6cc3..ea3326a 100644 --- a/src/input/privilegedHandlerForwarder.h +++ b/src/input/privilegedHandlerForwarder.h @@ -19,12 +19,25 @@ #include "inputEventHandler.h" +/** + * Forward the incoming InputEvent to \c pvsprivinputd. + */ class PrivilegedHandlerForwarder : public InputEventHandler< input_policy::Require, input_policy::Unprivileged> { public: + + /** + * Forward \c evt to \c pvsprivinputd, taking care that + * the security context is correctly sent. + */ void doHandle(InputEvent const& evt, InputEventContext const* = 0); + + /** + * Read the address of \c pvsprivinputd's listening socket + * from its configuration and connect to it. + */ void initialize(); private: diff --git a/src/input/pvsCheckPrivileges.h b/src/input/pvsCheckPrivileges.h index 92c68fe..37c4c04 100644 --- a/src/input/pvsCheckPrivileges.h +++ b/src/input/pvsCheckPrivileges.h @@ -26,6 +26,9 @@ #include #include "inputEventHandler.h" +/** + * Store the information in an InputEventContext as a plain old datatype. + */ struct CachedInputContext { CachedInputContext(InputEventContext const* source) @@ -69,16 +72,37 @@ uint qHash(CachedInputContext const& p); class QFileSystemWatcher; +/** + * Check user privileges and handle communications with ConsoleKit and PolicyKit. + * This is a singleton class. + */ class PVSCheckPrivileges : public QObject { Q_OBJECT public: + /** + * SessionKind distinguishes between local and remote users. + */ typedef enum { - SESSION_LOCAL, - SESSION_NONLOCAL, - SESSION_LOOKUP_FAILURE, - SESSION_UNKNOWN + SESSION_LOCAL, /**< User is local */ + SESSION_NONLOCAL, /**< User is remote */ + SESSION_LOOKUP_FAILURE, /**< Failure to look up whether the user is local or remote */ + SESSION_UNKNOWN /**< User session kind not (yet) known */ } SessionKind; + + /** + * UserPrivilege distinguishes between privileged and unprivileged users. + */ + typedef enum { + USER_PRIVILEGED, /**< User is privileged */ + USER_UNPRIVILEGED, /**< User is unprivileged */ + USER_LOOKUP_FAILURE, /**< Failure to look up whether the user is privileged or unprivileged */ + USER_UNKNOWN /**< User privilege level not (yet) known */ + } UserPrivilege; + + /** \name Conversion Functions */ + /* @{ */ + static QString toString(SessionKind k) { switch(k) @@ -91,12 +115,6 @@ public: } } - typedef enum { - USER_PRIVILEGED, - USER_UNPRIVILEGED, - USER_LOOKUP_FAILURE, - USER_UNKNOWN - } UserPrivilege; static QString toString(UserPrivilege k) { switch(k) @@ -109,13 +127,40 @@ public: } } + /* @} */ + + /** \name Singleton pattern */ + /* @{ */ + + /** Retrieve the singleton instance. */ static PVSCheckPrivileges* instance(); + + /** Delete the singleton instance. */ static void deleteInstance(); + /* @} */ + + /** \name Privilege Checks */ + /* @{ */ + + /** Check for a minimum SessionKind level. \return true if the requirement is fulfilled. */ bool require(SessionKind sessionKind, CachedInputContext const& sender); + + /** Check for a minimum UserPrivilege level. \return true if the requirement is fulfilled. */ bool require(UserPrivilege userPrivilege, CachedInputContext const& sender); + + /** Check for a minimum SessionKind and UserPrivilege level. \return true if both requirements are fulfilled. */ bool require(SessionKind sessionKind, UserPrivilege userPrivilege, CachedInputContext const& sender); + + /* @} */ + + /** \name Session Information */ + /* @{ */ + + /** Retrieve the name of the user's X session, according to ConsoleKit. */ QString getX11SessionName(CachedInputContext const& sender); + + /** Retrieve the TTY device of the user's X session, according to ConsoleKit. */ QString getX11DisplayDevice(CachedInputContext const& sender); public slots: diff --git a/src/input/pvsPrivInputHandler.h b/src/input/pvsPrivInputHandler.h index e82787b..015dfa1 100644 --- a/src/input/pvsPrivInputHandler.h +++ b/src/input/pvsPrivInputHandler.h @@ -24,10 +24,19 @@ class QSocketNotifier; +/** + * Handle socket communication with instances of the PVS Client Daemon. + * + * \note This runs in the context of a Qt main loop. It does not start + * a handler thread. + */ class PVSPrivInputHandler : public QObject { Q_OBJECT public: + /** + * Listen for InputEvents on file descriptor \c fd. + */ PVSPrivInputHandler(int fd, QObject* parent = 0); virtual ~PVSPrivInputHandler(); diff --git a/src/input/pvsPrivInputSignalHandler.h b/src/input/pvsPrivInputSignalHandler.h index cb75c86..bc549ec 100644 --- a/src/input/pvsPrivInputSignalHandler.h +++ b/src/input/pvsPrivInputSignalHandler.h @@ -19,6 +19,19 @@ #include +/** + * Handle signals. + * + * This class reads \c int values from a file descriptor and dispatches sends + * Qt signals according to the \c SIG... value the integer represents. + * The purpose of this mechanism is to integrate (asynchronous) Unix signal + * handling into the synchronous event-driven Qt main loop. The main() function + * is expected to open a socket pair and install handlers for all relevant signals + * that simply write the number of the signal to that pipe. + * + * If allowUnauthenticatedKilling() has not been called, this class only accepts + * signal numbers that are sent by the same process. + */ class PVSPrivInputSignalHandler : public QObject { Q_OBJECT @@ -28,16 +41,20 @@ public: { } + /** If \c value is \c true, allow sending signal numbers from other processes. */ void allowUnauthenticatedKilling(bool value) { _allowUnauthenticatedKilling = value; } public slots: + /** Connect this slot to a \c QSocketNotifier's \c activated(int) signal. */ void signalReceived(int sigfd); signals: + /** SIGTERM */ void terminate(); + /** SIGHUP */ void reloadConfiguration(); private: diff --git a/src/input/pvsPrivInputSocket.h b/src/input/pvsPrivInputSocket.h index 447360b..a57d730 100644 --- a/src/input/pvsPrivInputSocket.h +++ b/src/input/pvsPrivInputSocket.h @@ -24,14 +24,52 @@ class QSettings; +/** + * Load \c pvsprivinputd's configuration. This keeps a cached copy. + */ QSettings* pvsPrivInputGetSettings(); + +/** + * Update the cached configuration copy kept by pvsPrivInputGetSettings(). + */ QSettings* pvsPrivInputReopenSettings(); + +/** + * Hardcoded to \c /etc/pvsprivinputd.conf + */ QString pvsPrivInputGetSettingsPath(); + +/** + * Retrieve the path at which \c pvsprivinputd listens for datagrams from + * its configuration. + */ QString pvsPrivInputGetSocketAddress(); + +/** + * Enable the receiving of sender credentials on a \c unix(7) socket. + */ bool pvsPrivInputEnableReceiveCredentials(int sock); + +/** + * Make a \c unix(7) socket that is suitable for sending authenticated + * datagrams to \c pvsprivinputd. + */ int pvsPrivInputMakeClientSocket(); + +/** + * Make a listening \c unix(7) socket at the address specified by + * pvsPrivInputGetSocketAddress() that receives sender credentials. + */ int pvsPrivInputMakeServerSocket(); + +/** + * Send an authenticated message on a \c unix(7) socket. + */ bool pvsPrivInputSendMessage(int sock, void* buf, size_t len, int* err = 0); + +/** + * Receive an authenticated message on a \c unix(7) socket. + */ bool pvsPrivInputRecvMessage(int sock, void* buf, size_t& len, pid_t& pid, uid_t& uid, gid_t& gid, int* err = 0); #endif /* PVSPRIVINPUTSOCKET_H_ */ diff --git a/src/input/pvsSyslog.h b/src/input/pvsSyslog.h index 8c9591a..36ee2e0 100644 --- a/src/input/pvsSyslog.h +++ b/src/input/pvsSyslog.h @@ -20,6 +20,9 @@ #include #include +/** + * Listen on a socket or a pipe and redirect input lines to a child class. + */ class PVSLogRedirector : public QObject { Q_OBJECT @@ -33,6 +36,9 @@ private: QByteArray _buf; }; +/** + * Redirect log lines to a Unix syslog service. + */ class PVSSyslogRedirector : public PVSLogRedirector { public: @@ -46,6 +52,9 @@ protected: class QFile; class QTextStream; +/** + * Redirect log lines to a file. + */ class PVSLogfileRedirector : public PVSLogRedirector { public: diff --git a/src/input/rebootSystemHandler.h b/src/input/rebootSystemHandler.h index 4920452..357dcad 100644 --- a/src/input/rebootSystemHandler.h +++ b/src/input/rebootSystemHandler.h @@ -20,10 +20,16 @@ #include #include "inputEventHandler.h" +/** + * Reboot a Linux system. + */ class RebootLinuxSystemHandler : public InputEventHandler< input_policy::Require > { public: + /** + * Send SIGINT to the process with PID 1. + */ void doHandle(InputEvent const&, InputEventContext const*); }; diff --git a/src/input/sayHelloHandler.h b/src/input/sayHelloHandler.h index 00463ca..24118cf 100644 --- a/src/input/sayHelloHandler.h +++ b/src/input/sayHelloHandler.h @@ -20,6 +20,10 @@ #include #include "inputEventHandler.h" +/** + * Write a line to the log stating the PID, UID and GID of the + * PVS Client Daemon. + */ class SayHelloHandler : public InputEventHandler< input_policy::Match, input_policy::Security > diff --git a/src/input/x11FakeKeyboardHandler.h b/src/input/x11FakeKeyboardHandler.h index 6c18dce..7f2d12e 100644 --- a/src/input/x11FakeKeyboardHandler.h +++ b/src/input/x11FakeKeyboardHandler.h @@ -19,6 +19,13 @@ #include "inputEventHandler.h" +/** + * Send keyboard events via the XTest extension. + * This is unbelievably brittle in the face of non-system-standard keyboard + * mappings. Every Linux distribution seems to set up XTest handling in + * a different way. The code goes out of its way to find a usable mapping + * and use it. + */ class X11FakeKeyboardHandler : public InputEventHandler< input_policy::Match, input_policy::Match, diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h index 9d41c31..2700829 100644 --- a/src/input/x11FakeMouseHandler.h +++ b/src/input/x11FakeMouseHandler.h @@ -19,6 +19,9 @@ #include "inputEventHandler.h" +/** + * Send mouse button events via the XTest extension. + */ class X11FakeMouseButtonHandler : public InputEventHandler< input_policy::Match, input_policy::Require, @@ -28,6 +31,9 @@ public: void doHandle(InputEvent const&, InputEventContext const* = 0); }; +/** + * Send mouse pointer events via the XTest extension. + */ class X11FakeMouseMovementHandler : public InputEventHandler< input_policy::Match, input_policy::Require, diff --git a/src/input/x11InputUtils.h b/src/input/x11InputUtils.h index 9c85d09..94b3116 100644 --- a/src/input/x11InputUtils.h +++ b/src/input/x11InputUtils.h @@ -19,6 +19,9 @@ #include +/** + * Store the X11 Display. + */ struct X11InputUtils { static void setDisplay(Display*); static Display* display(); -- cgit v1.2.3-55-g7522