summaryrefslogtreecommitdiffstats
path: root/syslog.c
blob: 889b005767e0b0b9cfaf9935f947c2adb652865b (plain)
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
134
135
136
137
138
/* logger.c
 * Helper routines for klogd. It replaces the regular glibc syslog()
 * call. The reason is that the glibc version does not support
 * logging with the kernel facility. This file is a re-implementation
 * of the functions with only the functionality required for klogd.
 * So it can NOT be used as a general-purpose replacment.
 * Thanks to being special, this version is deemed to be considerable
 * faster than its glibc counterpart.
 * To avoid confusion, the syslog() replacement is named writeSyslog().
 * all other functions are just helpers to it.
 * RGerhards, 2007-06-14
 *
 * Copyright (C) 2007 Rainer Gerhards
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
 */
#include <stdio.h>
#include <assert.h>
#include <sys/socket.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <unistd.h>

#define PATH_LOGNAME "/dev/log"		/* be sure you know what you do if you change this! */

static struct sockaddr LoggerAddr;	/* AF_UNIX address of local logger */
static int connected;			/* have done connect */
static int fdLog = -1;			/* fd for log - -1 if closed */

/* klogOpenLog
 * opens the system log for writing. The log is opened immediately.
 * If it is already open, no action is taken)
 */
static void klogOpenlog(void)
{
	if (fdLog == -1) {
		LoggerAddr.sa_family = AF_UNIX;
		strncpy(LoggerAddr.sa_data, PATH_LOGNAME, sizeof(LoggerAddr.sa_data));
		fdLog = socket(AF_UNIX, SOCK_DGRAM, 0);
	}
	if (fdLog != -1 && !connected)
		if(connect(fdLog, &LoggerAddr, sizeof(LoggerAddr.sa_family) +
		    sizeof(PATH_LOGNAME) - 1 /* for \0 byte!*/ ) != -1)
		connected = 1;
}

/* Close the log file if it is currently open.
 */
static void klogCloselog(void)
{
	if(fdLog != -1)
		close(fdLog);
	fdLog = -1;
	connected = 0;
}

/* Write a message to the syslogd.
 * returns -1 if it fails, something else otherwise
 */
int writeSyslogV(int iPRI, const char *szFmt, va_list va)
{
	int iChars;
	int iLen;
	time_t tNow;
	int iWritten;	/* number of bytes written */
	char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */

	assert(szFmt != NULL);

	if (fdLog < 0 || !connected)
		klogOpenlog();

	/* build the message */
	time(&tNow);
	/* we can use sprintf safely below, because we know the size of the constants.
	 * By doing so, we save some cpu cycles and code complexity (for unnecessary
	 * error checking).
	 */
	iLen = sprintf(msgBuf, "<%d>%.15s kernel: ", iPRI, ctime(&tNow) + 4);

	iChars = vsnprintf(msgBuf + iLen, sizeof(msgBuf) / sizeof(char) - iLen, szFmt, va);
	if(iChars > sizeof(msgBuf) / sizeof(char) - iLen)
		iLen = sizeof(msgBuf) / sizeof(char) - 1; /* full buffer siz minus \0 byte */
	else
		iLen += iChars;

	/* output the message to the local logger */
	iWritten = write(fdLog, msgBuf, iLen);
	/* Debug aid below - uncomment to use
	printf("wrote to log(%d): '%s'\n", iWritten, msgBuf); */

	if(iWritten == -1) {
		/* retry */
		klogCloselog();
		klogOpenlog();
		iWritten = write(fdLog, msgBuf, iLen);
	}

	return(iWritten);
}

/* And now the same with variable arguments */
int writeSyslog(int iPRI, const char *szFmt, ...)
{
	int iRet;
	va_list va;

	assert(szFmt != NULL);
	va_start(va, szFmt);
	iRet = writeSyslogV(iPRI, szFmt, va);
	va_end(va);

	return(iRet);
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 * End:
 * vi:set ai:
 */