-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogwatch.c
More file actions
127 lines (106 loc) · 3.08 KB
/
logwatch.c
File metadata and controls
127 lines (106 loc) · 3.08 KB
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
#define _GNU_SOURCE
#include <stdio.h>
#include <err.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <regex.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <systemd/sd-journal.h>
#define LOGWATCH_CONF "/etc/logwatch.conf"
// Handle SIGINT and SIGTERM requests
static int request_exit = 0;
void sigint(int signum)
{
request_exit = 1;
}
void logwatch(const char *pattern, const char *action)
{
sd_journal *journal;
regex_t regex;
int ret;
if(pattern) {
if(regcomp(®ex, pattern, 0))
errx(EXIT_FAILURE, "Invalid expression %s\n", pattern);
}
ret = sd_journal_open_namespace(&journal, NULL, 0);
sd_journal_seek_tail(journal);
while(!request_exit) {
if((ret = sd_journal_next(journal)) < 0)
errx(EXIT_FAILURE, "sd_journal_next");
if(ret == 0) {
sd_journal_wait(journal, (uint64_t) -1);
continue;
}
if(pattern) {
const void *message;
size_t length;
char *strmessage;
if((ret = sd_journal_get_data(journal, "MESSAGE", &message, &length)) < 0) {
errx(EXIT_FAILURE, "sd_journal_get_data");
continue;
}
strmessage = strndup(message, length);
if(regexec(®ex, strmessage, 0, NULL, 0) == REG_NOMATCH) {
free(strmessage);
continue;
}
free(strmessage);
}
// Need to retrieve data from systemd before the fork
const void *data;
size_t length;
sd_journal_restart_data(journal);
char *envp[256];
int i = 0;
while(sd_journal_enumerate_data(journal, &data, &length) > 0) {
asprintf(&envp[i++], "%.*s", (int) length, (const char *)data);
}
envp[i] = 0;
int pid;
if((pid = fork()) == 0) {
execle(action, action, NULL, envp);
exit(EXIT_FAILURE);
}
// Deallocate memory
for(i = 0; envp[i]; i++) free(envp[i]);
waitpid(pid, &ret, 0);
}
if(pattern) regfree(®ex);
sd_journal_close(journal);
exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
signal(SIGINT, sigint);
signal(SIGTERM, sigint);
char *line = malloc(BUFSIZ);
size_t len = BUFSIZ;
ssize_t nread;
char pattern[BUFSIZ];
char action[BUFSIZ];
FILE *fd;
int ret;
if((fd = fopen(LOGWATCH_CONF, "r")) == NULL)
err(EXIT_FAILURE, "open(\"%s\")", LOGWATCH_CONF);
while((nread = getline(&line, &len, fd)) != -1) {
ret = sscanf(line, "%s %s", pattern, action);
if(ret != 2) continue;
if(pattern[0] == '#') continue;
if(fork() == 0) {
free(line);
fclose(fd);
sprintf(argv[0], "%-32s", "logwatch [systemd]");
logwatch(pattern, action);
}
}
free(line);
fclose(fd);
sprintf(argv[0], "%-32s", "logwatch [master]");
daemon(1, 1);
while(!request_exit) pause();
exit(EXIT_SUCCESS);
}