Replace size_t vars with unsigned int
[nagios-reports-module.git] / showlog.c
blob6f8d8710f78fb9caa2de116373fa19d033321466
1 #define _GNU_SOURCE 1
2 #include <sys/types.h>
3 #include <signal.h>
5 #include "logging.h"
6 #include "hash.h"
7 #include "lparse.h"
8 #include "logutils.h"
10 #define MAX_NVECS 16
11 #define HASH_TABLE_SIZE 128
13 static int ignore_process_events;
15 static time_t first_time, last_time; /* first and last timestamp to show */
16 static time_t ltime; /* the timestamp from the current log-line */
18 static inline void print_strvec(char **v, int n)
20 int i;
22 for (i = 0; i < n; i++)
23 printf("v[%2d]: %s\n", i, v[i]);
26 static hash_table *interesting_hosts, *interesting_services;
27 static int host_is_interesting(const char *host)
29 if (interesting_hosts)
30 return !!hash_find(interesting_hosts, host);
32 return 1;
35 static int service_is_interesting(const char *host, const char *service)
37 /* fall back to just checking if host is interesting */
38 if (!service || !interesting_services)
39 return host_is_interesting(host);
41 return !!hash_find2(interesting_services, host, service);
44 static int parse_line(char *line, uint len)
46 char *ptr, *colon;
47 int nvecs = 0;
48 struct string_code *sc;
49 static time_t last_ltime = 0;
51 line_no++;
53 /* ignore empty lines. whitespace is trimmed in the cfg_* api */
54 if (!len)
55 return 0;
57 /* skip obviously bogus lines */
58 if (len < 12 || *line != '[') {
59 warn("line %d; len too short, or line doesn't start with '[' (%s)", line_no, line);
60 return -1;
63 ltime = strtoul(line + 1, &ptr, 10);
64 if (line + 1 == ptr) {
65 crash("Failed to parse log timestamp from '%s'. I can't handle malformed logdata", line);
66 return -1;
69 /* only print lines in the interesting interval */
70 if ((first_time && ltime < first_time) || (last_time && ltime > last_time))
71 return 0;
73 /* more heuristics should go below, but we remain lazy for now */
74 puts(line);
75 return 0;
77 if (ltime < last_ltime) {
78 ltime = last_ltime;
80 else
81 last_ltime = ltime;
83 while (*ptr == ']' || *ptr == ' ')
84 ptr++;
86 if (!is_interesting(ptr))
87 return 0;
89 if (!(colon = strchr(ptr, ':'))) {
90 /* stupid heuristic, but might be good for something,
91 * somewhere, sometime. if nothing else, it should suppress
92 * annoying output */
93 if (is_start_event(ptr) || is_stop_event(ptr))
94 return 0;
96 handle_unknown_event(line);
97 return -1;
100 if (!(sc = get_event_type(ptr, colon - ptr))) {
101 handle_unknown_event(line);
102 return -1;
105 if (sc->code == IGNORE_LINE)
106 return 0;
108 *colon = 0;
109 ptr = colon + 1;
110 while (*ptr == ' ')
111 ptr++;
113 if (sc->nvecs) {
114 int i;
116 nvecs = vectorize_string(ptr, sc->nvecs);
118 if (nvecs != sc->nvecs) {
119 /* broken line */
120 warn("Line %d in %s seems to not have all the fields it should",
121 line_no, cur_file->path);
122 return -1;
125 for (i = 0; i < sc->nvecs; i++) {
126 if (!strv[i]) {
127 /* this should never happen */
128 warn("Line %d in %s seems to be broken, or we failed to parse it into a vector",
129 line_no, cur_file->path);
130 return -1;
135 switch (sc->code) {
136 char *semi_colon;
138 case NEBTYPE_EXTERNALCOMMAND_END:
139 semi_colon = strchr(ptr, ';');
140 if (!semi_colon)
141 return 0;
142 if (!(sc = get_command_type(ptr, semi_colon - ptr))) {
143 return 0;
146 nvecs = vectorize_string(semi_colon + 1, sc->nvecs);
147 if (nvecs != sc->nvecs) {
148 warn("nvecs discrepancy: %d vs %d (%s)\n", nvecs, sc->nvecs, ptr);
150 break;
152 case NEBTYPE_HOSTCHECK_PROCESSED:
153 case NEBTYPE_SERVICECHECK_PROCESSED:
154 puts(line);
156 case NEBTYPE_DOWNTIME_LOAD + CONCERNS_HOST:
157 case NEBTYPE_DOWNTIME_LOAD + CONCERNS_SERVICE:
158 break;
160 case IGNORE_LINE:
161 return 0;
164 return 0;
168 * hashes one line from an "interesting"-file. We use (void *)1
169 * to mark this as "present in hash-table" as we have no real
170 * data to lookup but still want hash_find{,2} to return non-NULL
171 * when it finds a match
173 static int hash_one_line(char *line, uint len)
175 char *p;
177 p = strchr(line, ';');
178 if (p) {
179 *p++ = 0;
180 if (!interesting_services)
181 interesting_services = hash_init(16384);
182 hash_add2(interesting_services, line, p, (void *)1);
184 else {
185 if (!interesting_hosts)
186 interesting_hosts = hash_init(16384);
188 hash_add(interesting_hosts, line, (void *)1);
191 return 0;
194 static int hash_interesting(const char *path)
196 struct stat st;
198 if (stat(path, &st) < 0)
199 crash("failed to stat %s: %s", path, strerror(errno));
201 lparse_path(path, st.st_size, hash_one_line);
203 return 0;
206 extern const char *__progname;
207 int main(int argc, char **argv)
209 int i;
210 struct naglog_file *nfile;
212 strv = calloc(sizeof(char *), MAX_NVECS);
213 nfile = calloc(sizeof(*nfile), argc - 1);
214 if (!strv || !nfile)
215 crash("Failed to alloc initial structs");
218 for (num_nfile = 0,i = 1; i < argc; i++) {
219 char *opt, *arg = argv[i];
220 struct naglog_file *nf;
221 int eq_opt = 0;
223 if ((opt = strchr(arg, '='))) {
224 *opt++ = '\0';
225 eq_opt = 1;
227 else if (i < argc - 1) {
228 opt = argv[i + 1];
231 if (!prefixcmp(arg, "--ignore-process-events")) {
232 ignore_process_events = 1;
233 continue;
235 if (!prefixcmp(arg, "--debug") || !prefixcmp(arg, "-d")) {
236 debug_level++;
237 continue;
239 if (!prefixcmp(arg, "--service")) {
240 continue;
242 if (!prefixcmp(arg, "--host")) {
243 continue;
245 if (!prefixcmp(arg, "--interesting") || !prefixcmp(arg, "-i")) {
246 if (!opt || !*opt)
247 crash("%s requires a filename as argument", arg);
248 hash_interesting(opt);
249 if (opt && !eq_opt)
250 i++;
251 continue;
253 if (!prefixcmp(arg, "--first") || !prefixcmp(arg, "--last")) {
254 time_t when;
256 if (!opt || !*opt)
257 crash("%s requires a timestamp as argument", arg);
258 when = strtoul(opt, NULL, 0);
259 if (opt && !eq_opt)
260 i++;
261 if (!prefixcmp(arg, "--first"))
262 first_time = when;
263 else
264 last_time = when;
265 continue;
268 /* non-argument, so treat as file */
269 nf = &nfile[num_nfile++];
270 nf->path = arg;
271 first_log_time(nf);
274 if (!num_nfile)
275 crash("Usage: %s [--ignore-process-events] [--interesting <file>] logfiles\n",
276 __progname);
278 qsort(nfile, num_nfile, sizeof(*nfile), nfile_cmp);
280 for (i = 0; i < num_nfile; i++) {
281 struct naglog_file *nf = &nfile[i];
282 if (last_time && nf->first > last_time) {
283 debug("ignoring %s\n", nf->path);
284 continue;
286 if (first_time && i < num_nfile - 1 && nfile[i + 1].first < first_time) {
287 debug("ignoring %s\n", nf->path);
288 continue;
291 cur_file = nf;
292 debug("importing from %s (%lu : %u)\n", nf->path, nf->first, nf->cmp);
293 line_no = 0;
294 lparse_path(nf->path, nf->size, parse_line);
297 if (warnings && debug_level)
298 fprintf(stderr, "Total warnings: %d\n", warnings);
300 print_unhandled_events();
302 return 0;