/*
# 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/
# --------------------------------------------------------------------------
# killX11Handler.h
# - Kill the X11 Server - implementation
# --------------------------------------------------------------------------
*/
#include <sys/types.h>
#include <signal.h>
#include <cerrno>
#include <QDir>
#include <QFileInfo>
#include <QStringList>
#include "pvsCheckPrivileges.h"
#include "killX11Handler.h"
using namespace std;
void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx)
{
// Find out which display device is used:
QString displayDevice = PVSCheckPrivileges::instance()->getX11DisplayDevice(ctx);
QString displayDeviceAbs = QFileInfo(displayDevice).canonicalFilePath();
if(displayDevice.isNull())
{
qWarning("Can not kill X server for %d,%d,%d: No Display Device", ctx->senderPid(), ctx->senderUid(), ctx->senderGid());
return;
}
QList<pid_t> pids;
// Find all processes that have it opened:
QDir proc("/proc");
QFileInfoList entries = proc.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
foreach(QFileInfo fi, entries)
{
// We are only interested in numerical ids:
bool ok;
pid_t pid = fi.fileName().toUInt(&ok);
if(!ok)
continue;
// We have a pid. Now check open files:
QDir fds(QString("/proc/%1/fd").arg(pid));
qDebug("Searching for X server in %s", fds.absolutePath().toLocal8Bit().constData());
QFileInfoList fdfiles = fds.entryInfoList(QDir::Files);
foreach(QFileInfo fdfile, fdfiles)
{
qDebug(" Looking for terminal in %s", fdfile.absoluteFilePath().toLocal8Bit().constData());
QFileInfo fdTarget(fdfile.readLink());
if(fdTarget.canonicalFilePath() == displayDeviceAbs)
{
qDebug(" ... found");
pids << pid;
}
}
}
// If everything is well, we have exactly one pid:
if(pids.size() != 1)
{
QStringList pidStrs;
foreach(pid_t pid, pids)
{
pidStrs << QString::number(pid);
}
qWarning("Display device %s is open by multiple or zero processes (%s). We don't know which is X. Aborting.",
displayDeviceAbs.toLocal8Bit().constData(),
pidStrs.join(", ").toLocal8Bit().constData());
return;
}
// We found the PID for the X server. Now kill it.
QString exe = QFileInfo(QString("/proc/%1/exe").arg(pids[0])).readLink();
qDebug("Killing X server, PID %d, exe name %s with SIGTERM", pids[0], exe.toLocal8Bit().constData());
kill(pids[0], SIGTERM);
}