summaryrefslogtreecommitdiffstats
path: root/src/input
diff options
context:
space:
mode:
authorSebastien Braun2010-10-06 15:19:44 +0200
committerSebastien Braun2010-10-07 09:30:24 +0200
commitaeeb2b034f50ad2938b1c32507f20070a26c1849 (patch)
tree54dfca1f4dff7202c012adfc26070cfc3c9a222c /src/input
parentInstall PolKit policy file (diff)
downloadpvs-aeeb2b034f50ad2938b1c32507f20070a26c1849.tar.gz
pvs-aeeb2b034f50ad2938b1c32507f20070a26c1849.tar.xz
pvs-aeeb2b034f50ad2938b1c32507f20070a26c1849.zip
Implement log targets for pvsprivinputd
Also: - add command line options and usage message. - change --no-fork to --daemon to bring it in line with the pvs daemon.
Diffstat (limited to 'src/input')
-rw-r--r--src/input/CMakeLists.txt2
-rw-r--r--src/input/pvsSyslog.cpp133
-rw-r--r--src/input/pvsSyslog.h63
-rw-r--r--src/input/pvsprivinputd.cpp116
4 files changed, 308 insertions, 6 deletions
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
index 0cf5177..a2e6fda 100644
--- a/src/input/CMakeLists.txt
+++ b/src/input/CMakeLists.txt
@@ -18,6 +18,7 @@ if(UNIX)
pvsprivinputd.cpp
pvsPrivInputHandler.cpp
pvsCheckPrivileges.cpp
+ pvsSyslog.cpp
pvsPrivInputSignalHandler.cpp
rebootSystemHandler.cpp
killX11Handler.cpp
@@ -27,6 +28,7 @@ if(UNIX)
set(pvsprivinputd_MOC_HDRS
pvsPrivInputHandler.h
pvsCheckPrivileges.h
+ pvsSyslog.h
pvsPrivInputSignalHandler.h
)
diff --git a/src/input/pvsSyslog.cpp b/src/input/pvsSyslog.cpp
new file mode 100644
index 0000000..6a9be31
--- /dev/null
+++ b/src/input/pvsSyslog.cpp
@@ -0,0 +1,133 @@
+/*
+ # 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/
+ # --------------------------------------------------------------------------
+ # pvsSyslog.cpp:
+ # - Send output to syslog or to a file - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <cerrno>
+#include <syslog.h>
+#include <QFile>
+#include <QTextStream>
+#include "pvsSyslog.h"
+
+using namespace std;
+
+#define PVS_LOG_BUFSIZ 8192
+
+void PVSLogRedirector::inputAvailableOn(int fd)
+{
+ QByteArray readbuf;
+ readbuf.resize(PVS_LOG_BUFSIZ);
+ ssize_t siz;
+ bool cont = true;
+
+ do
+ {
+ siz = recv(fd, readbuf.data(), readbuf.size(), MSG_DONTWAIT);
+ if(siz > 0)
+ {
+ _buf.append(readbuf.constData(), siz);
+
+ // Send lines:
+ int oldnpos = -1;
+ int npos = -1;
+ while((npos = _buf.indexOf('\n', oldnpos + 1)) >= 0)
+ {
+ if((oldnpos + 1) == npos)
+ {
+ oldnpos = npos;
+ continue;
+ }
+ QString line = QString::fromLocal8Bit(_buf.constData() + oldnpos + 1, npos - oldnpos - 1);
+ doRedirectInput(line);
+ oldnpos = npos;
+ }
+
+ // All complete lines have been sent. Remove sent bytes from buffer.
+ _buf.remove(0, oldnpos + 1);
+
+ // If line length is too large, send it now.
+ if(_buf.size() >= BUFSIZ)
+ {
+ QString longLine = QString::fromLocal8Bit(_buf.constData(), _buf.size());
+ doRedirectInput(longLine);
+ _buf.clear();
+ }
+ }
+ else if(siz == 0)
+ {
+ // Socket closed on other end.
+ break;
+ }
+ else if(siz < 0)
+ {
+ int err = errno;
+ switch(err)
+ {
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+ case EWOULDBLOCK:
+#endif
+ // We read all there is to read.
+ cont = false;
+ break;
+ default:
+ // Something happened.
+ // We can't inform the user via qDebug() and friends as that would loop right back to us again,
+ // so we emit a log line.
+ doRedirectInput(QString("Error in logging code: Could not read log input: %s").arg(strerror(err)));
+ cont = false;
+ }
+ }
+ }
+ while(cont);
+}
+
+PVSSyslogRedirector::PVSSyslogRedirector()
+{
+ openlog("pvsprivinputd", LOG_PID, LOG_USER);
+}
+
+PVSSyslogRedirector::~PVSSyslogRedirector()
+{
+ closelog();
+}
+
+void PVSSyslogRedirector::doRedirectInput(QString const& line)
+{
+ QByteArray bytes = line.toLocal8Bit();
+ syslog(LOG_NOTICE, "%s", bytes.data());
+}
+
+PVSLogfileRedirector::PVSLogfileRedirector(QString const& filename)
+{
+ _file = new QFile(filename, this);
+ _file->open(QIODevice::Append);
+ _stream = new QTextStream(_file);
+}
+
+PVSLogfileRedirector::~PVSLogfileRedirector()
+{
+ _stream->flush();
+ _file->close();
+ delete _stream;
+ delete _file;
+}
+
+void PVSLogfileRedirector::doRedirectInput(QString const& line)
+{
+ *_stream << line << flush;
+}
diff --git a/src/input/pvsSyslog.h b/src/input/pvsSyslog.h
new file mode 100644
index 0000000..8c9591a
--- /dev/null
+++ b/src/input/pvsSyslog.h
@@ -0,0 +1,63 @@
+/*
+ # 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/
+ # --------------------------------------------------------------------------
+ # pvsSyslog.h:
+ # - Send output to syslog or to a file - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef PVSSYSLOG_H_
+#define PVSSYSLOG_H_
+
+#include <QObject>
+#include <QString>
+
+class PVSLogRedirector : public QObject
+{
+ Q_OBJECT
+public slots:
+ void inputAvailableOn(int fd);
+
+protected:
+ virtual void doRedirectInput(QString const& line) = 0;
+
+private:
+ QByteArray _buf;
+};
+
+class PVSSyslogRedirector : public PVSLogRedirector
+{
+public:
+ PVSSyslogRedirector();
+ virtual ~PVSSyslogRedirector();
+
+protected:
+ void doRedirectInput(QString const& line);
+};
+
+class QFile;
+class QTextStream;
+
+class PVSLogfileRedirector : public PVSLogRedirector
+{
+public:
+ PVSLogfileRedirector(QString const& filename);
+ virtual ~PVSLogfileRedirector();
+
+protected:
+ void doRedirectInput(QString const& line);
+
+private:
+ QFile* _file;
+ QTextStream* _stream;
+};
+
+#endif /* PVSSYSLOG_H_ */
diff --git a/src/input/pvsprivinputd.cpp b/src/input/pvsprivinputd.cpp
index 2f19d90..e6ae155 100644
--- a/src/input/pvsprivinputd.cpp
+++ b/src/input/pvsprivinputd.cpp
@@ -22,8 +22,10 @@
#include <unistd.h>
#include <cerrno>
#include <cstdlib>
+#include <cstdio>
#include <cstring>
#include <QtDebug>
+#include <QFileInfo>
#include <QSettings>
#include <QCoreApplication>
#include <QStringList>
@@ -32,6 +34,7 @@
#include "pvsPrivInputSocket.h"
#include "pvsPrivInputHandler.h"
#include "pvsPrivInputSignalHandler.h"
+#include "pvsSyslog.h"
using namespace std;
@@ -42,6 +45,9 @@ using namespace std;
QByteArray socketPath;
int signalFds[2];
+QTextStream qout(stdout, QIODevice::WriteOnly);
+QTextStream qerr(stderr, QIODevice::WriteOnly);
+
static void unlinkSocket()
{
if(!socketPath.isNull())
@@ -55,13 +61,70 @@ static void onCaughtSignal(int signum)
pvsPrivInputSendMessage(signalFds[0], &signum, sizeof(signum), 0);
}
+static void usage()
+{
+ qout << QObject::tr(
+ "Usage: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>]\n"
+ "\n"
+ "Options:\n"
+ " --help, -h Show this message\n"
+ " --daemon, -d Run in background\n"
+ " --log=<Logger>,\n"
+ " -l<Logger> Redirect all output to <Logger>\n"
+ " valid values are:\n"
+ " - any file name\n"
+ " - `syslog' to redirect output to the system log\n"
+ " - `null' to discard output (default)\n"
+ " (without quotes)\n"
+ "\n"
+ "Signals:\n"
+ " SIGINT, SIGTERM (or press Ctrl+C when run in foreground)\n"
+ " Quit\n"
+ " SIGHUP Reload configuration and cached user data\n").arg(qApp->arguments().at(0)) << flush;
+}
+
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
app.setApplicationName("pvsprivinputd");
app.setOrganizationName("openslx");
- bool no_fork = app.arguments().contains("--no-fork", Qt::CaseInsensitive);
+ bool no_fork = true;
+ QString logTarget = "null";
+
+ foreach(QString arg, app.arguments().mid(1))
+ {
+ if(arg == "--daemon" || arg == "-d")
+ {
+ no_fork = false;
+ }
+ else if(arg.startsWith("-l"))
+ {
+ logTarget = arg.mid(2);
+ }
+ else if(arg.startsWith("--log="))
+ {
+ logTarget = arg.mid(6);
+ }
+ else if(arg == "--help" || arg == "-h")
+ {
+ usage();
+ return EXIT_SUCCESS;
+ }
+ else
+ {
+ qout << "Unexpected argument: " << arg << endl;
+ usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ if(logTarget != "null" && logTarget != "syslog")
+ {
+ logTarget = QFileInfo(logTarget).absoluteFilePath();
+ qout << "Writing log to " << logTarget << endl;
+ }
+
if(!no_fork)
{
pid_t pid;
@@ -118,6 +181,9 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE);
}
+ // Install our main object
+ PVSPrivInputHandler handler(sock);
+
// set up signal handling:
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, signalFds) < 0)
{
@@ -135,24 +201,62 @@ int main(int argc, char** argv)
signal(SIGTERM, onCaughtSignal);
signal(SIGHUP, onCaughtSignal);
+ PVSLogRedirector* logRedir = 0;
+ QSocketNotifier* logNotif = 0;
// Our setup is complete.
if(!no_fork)
{
// Reopen standard file descriptors:
freopen("/dev/null", "r", stdin);
- freopen("/dev/null", "w", stderr);
- freopen("/dev/null", "w", stdout);
- }
- // Install our main object
- PVSPrivInputHandler handler(sock);
+ if(logTarget == "null")
+ {
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+ }
+ else if(logTarget == "syslog")
+ {
+ logRedir = new PVSSyslogRedirector();
+ }
+ else
+ {
+ logRedir = new PVSLogfileRedirector(logTarget);
+ }
+
+ if(logRedir)
+ {
+ int logFds[2];
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, logFds) < 0)
+ {
+ qWarning("Could not open a socket pair: %s", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ logNotif = new QSocketNotifier(logFds[1], QSocketNotifier::Read);
+ QObject::connect(logNotif, SIGNAL(activated(int)), logRedir, SLOT(inputAvailableOn(int)));
+
+ // redirect stdout and stderr:
+ dup2(logFds[0], 1);
+ dup2(logFds[0], 2);
+ }
+ }
atexit(unlinkSocket);
+ qout << "PVS Privileged Input Daemon initialization complete. Entering main loop." << endl;
+
// and run the main loop.
int ret = app.exec();
+ if(logRedir)
+ {
+ delete logNotif;
+ delete logRedir;
+ }
PVSCheckPrivileges::deleteInstance();
+
+ qout << "PVS Privileged Input Daemon deinitialization complete. Exiting." << endl;
+
return ret;
}