summary refs log tree commit diff
path: root/nanoklogd.c
blob: 520da49b869c44c03a53aafc3f3e5c0b67931cc0 (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
/* nanoklogd - forward kernel messages to /dev/log.  */

/* Written by Leah Neukirchen <leah@vuxu.org>
   To the extent possible under law, the creator of this work has waived
   all copyright and related or neighboring rights to this work.  */

/* This uses /dev/log directly because glibc syslog(3) does
   forward LOG_KERN as LOG_USER.  */

#include <sys/klog.h>
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>

static const struct {
        short sun_family;
        char sun_path[9];
} log_addr = {
        AF_UNIX,
        "/dev/log"
};

int
main(int argc, char *argv[]) {
	char buf[16384];
	int f, l, start, stop;

	f = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
	if (f < 0)
		return 111;

	if (connect(f, (void *)&log_addr, sizeof log_addr) < 0)
		return 112;

	while (1) {
		l = klogctl(2, buf, sizeof buf);
		if (l < 0)
			return 113;

		for (start = 0; start < l; start = stop+1) {
			for (stop = start+1; stop < l && buf[stop] != '\n'; stop++)
				;

			while (send(f, buf+start, stop-start, 0) != stop-start) {
				switch (errno) {
				case ECONNREFUSED:
				case ECONNRESET:
				case ENOTCONN:
					/* syslogd went down, retry until up.  */
					close(f);
					sleep(1);
					f = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
					if (f < 0)
						return 111;
					connect(f, (void *)&log_addr, sizeof log_addr);
					break;
				default:
					return 114;
				}
			}
		}
	}
	return 0;
}