summaryrefslogtreecommitdiffstats
path: root/src/input/pvsSyslog.cpp
blob: 6a9be31dfeb2b3ba160c073f0841b03f03ec6106 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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;
}