summaryrefslogblamecommitdiffstats
path: root/src/input/pvsSyslog.cpp
blob: 6a9be31dfeb2b3ba160c073f0841b03f03ec6106 (plain) (tree)




































































































































                                                                                                                                   
/*
 # 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;
}