state: Make sure we duplicate the keys used for hashing
[nagios-reports-module.git] / showlog.c
blob2f1e6f8abffcd3e28935f5b33a6f3f26dda298f5
1 #define _GNU_SOURCE 1
2 #include <sys/types.h>
3 #include <signal.h>
4 #include <stdarg.h>
6 #include "logging.h"
7 #include "hash.h"
8 #include "lparse.h"
9 #include "logutils.h"
10 #include "cfgfile.h"
11 #include "auth.h"
12 #include "state.h"
14 #define MAX_NVECS 16
15 #define HASH_TABLE_SIZE 128
17 static time_t first_time, last_time; /* first and last timestamp to show */
18 static time_t ltime; /* the timestamp from the current log-line */
19 static uint severity;
20 static const char *image_url = "/ninja/application/views/themes/default/icons/16x16";
21 static int reverse_parse_files;
22 static uint skip, limit;
23 static int hide_state_dupes; /* if set, we hide duplicate state messages */
25 #define EVT_PROCESS (1 << 0)
26 #define EVT_NOTIFY (1 << 1)
27 #define EVT_ALERT (1 << 2)
28 #define EVT_COMMAND (1 << 3)
29 #define EVT_STATE (1 << 4)
30 #define EVT_FLAPPING (1 << 5)
31 #define EVT_DOWNTIME (1 << 6)
32 #define EVT_LROTATE (1 << 7)
33 #define EVT_EHANDLER (1 << 8)
34 #define EVT_START (1 << 9)
35 #define EVT_STOP (1 << 10)
37 #define EVT_HOST (1 << 20)
38 #define EVT_SERVICE (1 << 21)
39 #define EVT_INITIAL (1 << 22)
41 #define EVENT_MASK (0xffffffff & (~(EVT_HOST | EVT_SERVICE)))
42 static int event_filter = EVENT_MASK;
43 static int host_state_filter = -1;
44 static int service_state_filter = -1;
45 static int statetype_filter = (1 << HARD_STATE) | (1 << SOFT_STATE);
47 #define add_event(string, eventcode) add_code(0, string, eventcode)
48 static struct string_code event_codes[] = {
49 add_event("Error", EVT_PROCESS),
50 add_event("Warning", EVT_PROCESS),
51 add_event("HOST NOTIFICATION", EVT_NOTIFY | EVT_SERVICE),
52 add_event("HOST FLAPPING ALERT", EVT_FLAPPING | EVT_HOST),
53 add_event("SERVICE NOTIFICATION", EVT_NOTIFY | EVT_SERVICE),
54 add_event("SERVICE FLAPPING ALERT", EVT_FLAPPING | EVT_SERVICE),
55 add_event("LOG ROTATION", EVT_LROTATE),
56 add_event("HOST EVENT HANDLER", EVT_EHANDLER | EVT_HOST),
57 add_event("SERVICE EVENT HANDLER", EVT_EHANDLER | EVT_SERVICE),
58 add_event("LOG VERSION", EVT_PROCESS),
59 add_event("EXTERNAL COMMAND", EVT_COMMAND),
61 add_code(5, "HOST ALERT", EVT_ALERT | EVT_HOST),
62 add_code(5, "INITIAL HOST STATE", EVT_STATE | EVT_HOST | EVT_INITIAL),
63 add_code(5, "CURRENT HOST STATE", EVT_STATE | EVT_HOST | EVT_INITIAL),
64 add_code(6, "SERVICE ALERT", EVT_ALERT | EVT_SERVICE),
65 add_code(6, "INITIAL SERVICE STATE", EVT_STATE | EVT_SERVICE | EVT_INITIAL),
66 add_code(6, "CURRENT SERVICE STATE", EVT_STATE | EVT_SERVICE | EVT_INITIAL),
67 add_code(3, "HOST DOWNTIME ALERT", EVT_DOWNTIME | EVT_HOST),
68 add_code(4, "SERVICE DOWNTIME ALERT", EVT_DOWNTIME | EVT_SERVICE),
69 { 0, NULL, 0, 0 },
72 static void print_time_iso8601(struct tm *t)
74 printf("[%d-%02d-%02d %02d:%02d:%02d] ",
75 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
76 t->tm_hour, t->tm_min, t->tm_sec);
79 static void print_time_div_iso8601(struct tm *t)
81 printf("%d-%02d-%02d %02d:00 ",
82 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour);
85 static void print_time_raw(struct tm *t)
87 printf("[%lu] ", ltime);
90 static struct {
91 char *name;
92 void (*func)(struct tm *);
93 void (*func_div)(struct tm *);
94 } time_format_selections[] = {
95 { "iso8601", print_time_iso8601, print_time_div_iso8601 },
96 { "raw", print_time_raw, NULL },
97 { NULL },
99 static void (*print_time)(struct tm *) = print_time_iso8601;
100 static void (*print_time_div)(struct tm *) = print_time_div_iso8601;
102 static void parse_time_format(const char *selection)
104 int i;
106 if (selection) for (i = 0; time_format_selections[i].name; i++) {
107 if (strcasecmp(selection, time_format_selections[i].name))
108 continue;
109 print_time = time_format_selections[i].func;
110 print_time_div = time_format_selections[i].func_div;
111 return;
114 crash("Illegal timeformat selection: '%s'\n", selection);
117 static inline void pre_print_mangle_line(struct tm *t, char *line, uint len)
119 uint i;
121 for (i = 0; i < len; i++) {
122 if (!line[i])
123 line[i] = ';';
126 gmtime_r(&ltime, t);
127 if (!t->tm_isdst)
128 t->tm_hour++;
132 static void print_line_ascii(int type, struct tm *t, char *line, uint len)
134 print_time(t);
135 puts(line);
139 static void print_line_ansi(int type, struct tm *t, char *line, uint len)
141 const char *color = NULL;
143 switch (type & ~EVT_INITIAL) {
144 case EVT_ALERT | EVT_HOST:
145 case EVT_STATE | EVT_HOST:
146 if (severity == HOST_UP)
147 color = CLR_GREEN;
148 else
149 color = CLR_RED;
150 break;
152 case EVT_ALERT | EVT_SERVICE:
153 case EVT_STATE | EVT_SERVICE:
154 switch (severity) {
155 case SERVICE_OK: color = CLR_GREEN; break;
156 case SERVICE_WARNING: color = CLR_YELLOW; break;
157 case SERVICE_CRITICAL: color = CLR_RED; break;
158 case SERVICE_UNKNOWN: color = CLR_BROWN; break;
160 break;
162 case EVT_DOWNTIME | EVT_HOST:
163 case EVT_DOWNTIME | EVT_SERVICE:
164 color = CLR_BLUE;
165 break;
167 case EVT_FLAPPING | EVT_HOST:
168 case EVT_FLAPPING | EVT_SERVICE:
169 color = CLR_CYAN;
170 break;
172 case EVT_PROCESS:
173 color = CLR_MAGENTA;
174 break;
176 case EVT_LROTATE:
177 color = CLR_BOLD;
178 break;
180 case EVT_COMMAND:
181 color = CLR_BRIGHT_MAGENTA;
182 break;
184 case EVT_START: case EVT_STOP:
185 color = CLR_BRIGHT_BLUE;
186 break;
189 if (color) {
190 printf("%s", color);
191 print_time(t);
192 printf("%s%s\n", line, CLR_RESET);
193 } else {
194 print_time(t);
195 puts(line);
200 static void print_time_break(struct tm *t)
202 struct tm h;
204 memcpy(&h, t, sizeof(h));
205 h.tm_min = h.tm_sec = 0;
206 if (reverse_parse_files) {
207 /* using mktime and gmtime_r again here means we never
208 * have to worry about changing date, month or year in
209 * case we overshoot by one */
210 time_t when = mktime(&h) + 3600;
211 gmtime_r(&when, &h);
214 printf("<h2>");
215 print_time_div(&h);
216 puts("</h2>");
220 static void print_line_html(int type, struct tm *t, char *line, uint len)
222 const char *image = NULL;
223 static time_t last_time_break = 0;
225 switch (type) {
226 case EVT_ALERT | EVT_HOST:
227 case EVT_STATE | EVT_HOST:
228 if (severity == HOST_UP)
229 image = "shield-ok.png";
230 else
231 image = "shield-critical.png";
232 break;
234 case EVT_ALERT | EVT_SERVICE:
235 case EVT_STATE | EVT_SERVICE:
236 switch (severity) {
237 case SERVICE_OK: image = "shield-ok.png"; break;
238 case SERVICE_WARNING: image = "shield-warning.png"; break;
239 case SERVICE_CRITICAL: image = "shield-critical.png"; break;
240 case SERVICE_UNKNOWN: image = "shield-unknown.png"; break;
242 break;
244 case EVT_DOWNTIME | EVT_HOST:
245 case EVT_DOWNTIME | EVT_SERVICE:
246 image = "scheduled-downtime.png";
247 break;
249 case EVT_FLAPPING | EVT_HOST:
250 case EVT_FLAPPING | EVT_SERVICE:
251 image = "flapping.gif";
252 break;
254 case EVT_COMMAND:
255 image = "command.png";
256 break;
258 case EVT_LROTATE:
259 image = "logrotate.png";
260 break;
262 case EVT_EHANDLER | EVT_HOST:
263 image = "hostevent.gif";
264 break;
266 case EVT_EHANDLER | EVT_SERVICE:
267 image = "serviceevent.gif";
268 break;
270 case EVT_START:
271 image = "start.png";
272 break;
274 case EVT_STOP:
275 image = "stop.png";
276 break;
279 if (!image)
280 image = "shield-info.png";
282 if (last_time_break != ltime / 3600) {
283 print_time_break(t);
284 last_time_break = ltime / 3600;
287 printf("<img src=\"%s/%s\" alt=\"%s\" /> ", image_url, image, image);
288 print_time(t);
289 printf("%s<br />\n", line);
293 static void (*real_print_line)(int type, struct tm *, char *, uint) = print_line_ascii;
294 static void print_line(int type, char *line, uint len)
296 struct tm t;
298 /* are we still skipping? If so, return early */
299 if (skip) {
300 skip--;
301 return;
304 pre_print_mangle_line(&t, line, len);
305 real_print_line(type, &t, line, len);
307 /* if we've printed all the lines we should, just exit */
308 if (limit) {
309 if (!--limit)
310 exit(0);
315 static int parse_line(char *orig_line, uint len)
317 char *ptr, *colon, *line;
318 int nvecs = 0;
319 struct string_code *sc;
320 int hard;
322 line_no++;
324 /* ignore empty lines */
325 if (!len)
326 return 0;
328 /* skip obviously bogus lines */
329 if (len < 12 || *orig_line != '[') {
330 warn("line %d; len too short, or line doesn't start with '[' (%s)",
331 line_no, orig_line);
332 return -1;
335 ltime = strtoul(orig_line + 1, &ptr, 10);
336 if (orig_line + 1 == ptr) {
337 crash("Failed to parse log timestamp from '%s'. I can't handle malformed logdata",
338 orig_line);
339 return -1;
342 /* only print lines in the interesting interval */
343 if (ltime < first_time || ltime > last_time)
344 return 0;
346 while (*ptr == ']' || *ptr == ' ')
347 ptr++;
349 line = ptr;
350 len -= line - orig_line;
352 if (!is_interesting(ptr))
353 return 0;
355 if (!(colon = strchr(ptr, ':'))) {
356 /* stupid heuristic, but might be good for something,
357 * somewhere, sometime. if nothing else, it should suppress
358 * annoying output */
359 if (!(event_filter & EVT_PROCESS))
360 return 0;
362 if (is_start_event(ptr)) {
363 print_line(EVT_START, line, len);
364 } else if (is_stop_event(ptr)) {
365 print_line(EVT_STOP, line, len);
368 return 0;
371 if (!(sc = get_event_type(ptr, colon - ptr))) {
372 return 0;
375 if (sc->code == IGNORE_LINE)
376 return 0;
377 if ((sc->code & event_filter) != sc->code)
378 return 0;
380 ptr = colon + 1;
381 while (*ptr == ' ')
382 ptr++;
384 if (sc->nvecs) {
385 int i;
387 nvecs = vectorize_string(ptr, sc->nvecs);
389 if (nvecs != sc->nvecs) {
390 /* broken line */
391 warn("Line %d in %s seems to not have all the fields it should",
392 line_no, cur_file->path);
393 return -1;
396 for (i = 0; i < sc->nvecs; i++) {
397 if (!strv[i]) {
398 /* this should never happen */
399 warn("Line %d in %s seems to be broken, or we failed to parse it into a vector",
400 line_no, cur_file->path);
401 return -1;
406 switch (sc->code & ~EVT_INITIAL) {
407 case EVT_ALERT | EVT_HOST:
408 case EVT_STATE | EVT_HOST:
409 hard = soft_hard(strv[2]);
410 if (!(statetype_filter & (1 << hard)))
411 return 0;
412 severity = parse_host_state(strv[1]);
413 if (!(host_state_filter & (1 << severity)))
414 return 0;
415 if (!auth_host_ok(strv[0]))
416 return 0;
417 if (!is_interesting_host(strv[0]))
418 return 0;
419 if (hide_state_dupes && !host_has_new_state(strv[0], severity, hard))
420 return 0;
422 break;
424 case EVT_ALERT | EVT_SERVICE:
425 case EVT_STATE | EVT_SERVICE:
426 hard = soft_hard(strv[3]);
427 if (!(statetype_filter & (1 << hard)))
428 return 0;
429 severity = parse_service_state(strv[2]);
430 if (!(service_state_filter & (1 << severity)))
431 return 0;
432 if (!auth_service_ok(strv[0], strv[1]))
433 return 0;
434 if (!is_interesting_service(strv[0], strv[1]))
435 return 0;
436 if (hide_state_dupes && !service_has_new_state(strv[0], strv[1], severity, hard))
437 return 0;
439 break;
441 case EVT_FLAPPING | EVT_HOST:
442 case EVT_DOWNTIME | EVT_HOST:
443 if (!auth_host_ok(strv[0]))
444 return 0;
445 if (!is_interesting_host(strv[0]))
446 return 0;
447 break;
449 case EVT_FLAPPING | EVT_SERVICE:
450 case EVT_DOWNTIME | EVT_SERVICE:
451 if (!auth_service_ok(strv[0], strv[1]))
452 return 0;
453 if (!is_interesting_service(strv[0], strv[1]))
454 return 0;
455 break;
457 case EVT_NOTIFY | EVT_HOST:
458 if (!auth_host_ok(strv[1]))
459 return 0;
460 if (!is_interesting_host(strv[1]))
461 return 0;
463 case EVT_NOTIFY | EVT_SERVICE:
464 if (!auth_service_ok(strv[1], strv[2]))
465 return 0;
466 if (!is_interesting_service(strv[1], strv[2]))
467 return 0;
470 print_line(sc->code, line, len);
471 return 0;
475 * hashes one line from an "interesting"-file. We use (void *)1
476 * to mark this as "present in hash-table" as we have no real
477 * data to lookup but still want hash_find{,2} to return non-NULL
478 * when it finds a match
480 static int hash_one_line(char *line, uint len)
482 return add_interesting_object(line);
485 static int hash_interesting(const char *path)
487 struct stat st;
489 if (stat(path, &st) < 0)
490 crash("failed to stat %s: %s", path, strerror(errno));
492 lparse_path(path, st.st_size, hash_one_line);
494 return 0;
497 static void parse_host_state_filter(char *p)
499 host_state_filter = 0;
500 for (; *p; p++) {
501 switch (*p) {
502 case 'a': case '*':
503 host_state_filter = -1;
504 break;
505 case 'u':
506 host_state_filter |= 1 << HOST_UNREACHABLE;
507 break;
508 case 'd':
509 host_state_filter |= 1 << HOST_DOWN;
510 break;
511 case 'r':
512 host_state_filter |= 1 << HOST_UP;
513 break;
518 static void parse_service_state_filter(char *p)
520 service_state_filter = 0;
521 for (; *p; p++) {
522 switch (*p) {
523 case 'a': case '*':
524 service_state_filter = -1;
525 break;
526 case 'r':
527 service_state_filter |= 1 << SERVICE_OK;
528 break;
529 case 'w':
530 service_state_filter |= 1 << SERVICE_WARNING;
531 break;
532 case 'c':
533 service_state_filter |= 1 << SERVICE_CRITICAL;
534 break;
535 case 'u':
536 service_state_filter |= 1 << SERVICE_UNKNOWN;
541 extern const char *__progname;
542 static void usage(const char *fmt, ...)
544 int i;
546 if (fmt && *fmt) {
547 va_list ap;
549 va_start(ap, fmt);
550 vprintf(fmt, ap);
551 va_end(ap);
554 printf("usage: %s [options] [logfiles]\n\n", __progname);
555 printf(" <logfiles> refers to all the nagios logfiles you want to search through\n");
556 printf(" If --nagios-cfg is given or can be inferred no logfiles need to be supplied\n");
557 printf("Options:\n");
558 printf(" --reverse parse (and print) logs in reverse\n");
559 printf(" --help this cruft\n");
560 printf(" --debug print debugging information\n");
561 printf(" --html print html output\n");
562 printf(" --ansi force-colorize the output\n");
563 printf(" --ascii don't colorize the output\n"),
564 printf(" --user=<username> show only logs this user can see\n");
565 printf(" --cgi-cfg=</path/to/cgi.cfg> path to cgi.cfg\n");
566 printf(" --nagios-cfg=</path/to/nagios.cfg> path to nagios.cfg\n");
567 printf(" --object-cache=</path/to/objects.cache> path to objects.cache\n");
568 printf(" --image-url=<image url> url to images. Implies --html\n");
569 printf(" --hide-state-dupes hide duplicate status messages\n");
570 printf(" --hide-flapping hide flapping messages\n");
571 printf(" --hide-downtime hide downtime messages\n");
572 printf(" --hide-process hide process messages\n");
573 printf(" --hide-command hide external command messages\n");
574 printf(" --hide-notifications hide notification messages\n");
575 printf(" --hide-logrotation hide log rotation messages\n");
576 printf(" --hide-initial hide INITIAL and CURRENT states\n");
577 printf(" --skip=<integer> number of filtered in messages to skip\n");
578 printf(" --limit=<integer> max number of messages to print\n");
579 printf(" --host=<host_name> show log entries for the named host\n");
580 printf(" --service=<hostname;servicedescription> show log entries for the named service\n");
581 printf(" --first=<timestamp> first log-entry to show\n");
582 printf(" --last=<timestamp> last log-entry to show\n");
583 printf(" --state-type=[hard|soft] state-types to show. default is all\n");
584 printf(" --host-states=[*ardu] host-states to show. can be mixed\n");
585 printf(" 'a' and '*' shows 'all'\n");
586 printf(" 'r' shows 'recovery'\n");
587 printf(" 'd' shows 'down'\n");
588 printf(" 'u' shows 'unreachable'\n");
589 printf(" --service-states=[*arwcu] service-states to show. can be mixed\n");
590 printf(" 'a' and '*' shows 'all'\n");
591 printf(" 'r' shows 'recovery'\n");
592 printf(" 'w' shows 'warning'\n");
593 printf(" 'c' shows 'critical'\n");
594 printf(" 'u' shows 'unknown'\n");
595 printf(" --time-format=[");
596 for (i = 0; time_format_selections[i].name; i++) {
597 printf("%s", time_format_selections[i].name);
598 if (time_format_selections[i + 1].name)
599 printf("|");
601 printf("] set timeformat for log-entries\n");
603 putchar('\n');
605 if (fmt && *fmt)
606 exit(1);
608 exit(0);
611 int main(int argc, char **argv)
613 int i;
614 const char *nagios_cfg = NULL, *cgi_cfg = NULL, *object_cache = NULL;
616 strv = calloc(sizeof(char *), MAX_NVECS);
617 if (!strv)
618 crash("Failed to alloc initial structs");
620 if (isatty(fileno(stdout))) {
621 real_print_line = print_line_ansi;
622 event_filter &= ~(EVT_LROTATE | EVT_PROCESS);
625 for (i = 1; i < argc; i++) {
626 char *opt, *arg = argv[i];
627 int arg_len, eq_opt = 0;
629 if ((opt = strchr(arg, '='))) {
630 *opt++ = '\0';
631 eq_opt = 1;
633 else if (i < argc - 1) {
634 opt = argv[i + 1];
637 if (!strcmp(arg, "--reverse")) {
638 reverse_parse_files = 1;
639 continue;
641 if (!strcmp(arg, "--html")) {
642 real_print_line = print_line_html;
643 continue;
645 if (!strcmp(arg, "--ansi")) {
646 real_print_line = print_line_ansi;
647 continue;
649 if (!strcmp(arg, "--ascii")) {
650 real_print_line = print_line_ascii;
651 continue;
653 if (!strcmp(arg, "--debug") || !strcmp(arg, "-d")) {
654 debug_level++;
655 continue;
657 if (!strcmp(arg, "--help")) {
658 usage(NULL);
659 continue;
661 if (!prefixcmp(arg, "--hide-state-dupes")) {
662 hide_state_dupes = 1;
663 continue;
665 if (!prefixcmp(arg, "--hide-flapping")) {
666 event_filter &= ~EVT_FLAPPING;
667 continue;
669 if (!prefixcmp(arg, "--hide-downtime")) {
670 event_filter &= ~EVT_DOWNTIME;
671 continue;
673 if (!prefixcmp(arg, "--hide-process")) {
674 event_filter &= ~EVT_PROCESS;
675 continue;
677 if (!prefixcmp(arg, "--hide-command")) {
678 event_filter &= ~EVT_COMMAND;
679 continue;
681 if (!prefixcmp(arg, "--hide-notification")) {
682 event_filter &= ~EVT_NOTIFY;
683 continue;
685 if (!prefixcmp(arg, "--hide-logrotat")) {
686 event_filter &= ~EVT_LROTATE;
687 continue;
689 if (!prefixcmp(arg, "--hide-initial")) {
690 event_filter &= ~EVT_INITIAL;
691 continue;
694 if (!prefixcmp(arg, "--")) {
695 if (!opt)
696 usage("Option '%s' requires an argument\n", arg);
697 if (!eq_opt)
698 i++;
701 /* options parsed below require arguments */
702 if (!strcmp(arg, "--user")) {
703 auth_set_user(opt);
704 continue;
706 if (!prefixcmp(arg, "--object-cache")) {
707 object_cache = opt;
708 continue;
710 if (!strcmp(arg, "--nagios-cfg")) {
711 nagios_cfg = opt;
712 continue;
714 if (!strcmp(arg, "--cgi-cfg")) {
715 cgi_cfg = opt;
716 continue;
718 if (!strcmp(arg, "--skip")) {
719 skip = strtoul(opt, NULL, 0);
720 continue;
722 if (!strcmp(arg, "--limit")) {
723 limit = strtoul(opt, NULL, 0);
724 continue;
726 if (!strcmp(arg, "--host")) {
727 event_filter |= EVT_HOST;
728 add_interesting_object(opt);
729 continue;
731 if (!strcmp(arg, "--service")) {
732 event_filter |= EVT_SERVICE;
733 add_interesting_object(opt);
734 continue;
736 if (!strcmp(arg, "--image-url")) {
737 real_print_line = print_line_html;
738 image_url = opt;
739 continue;
741 if (!strcmp(arg, "--interesting") || !strcmp(arg, "-i")) {
742 if (!opt || !*opt)
743 usage("%s requires a filename as argument", arg);
744 hash_interesting(opt);
745 continue;
747 if (!strcmp(arg, "--first") || !strcmp(arg, "--last")) {
748 time_t when;
750 if (!opt || !*opt)
751 crash("%s requires a timestamp as argument", arg);
752 when = strtoul(opt, NULL, 0);
753 if (opt && !eq_opt)
754 i++;
755 if (!strcmp(arg, "--first"))
756 first_time = when;
757 else
758 last_time = when;
759 continue;
761 if (!strcmp(arg, "--state-type")) {
762 if (!strcasecmp(opt, "hard"))
763 statetype_filter = (1 << HARD_STATE);
764 if (!strcasecmp(opt, "soft"))
765 statetype_filter = (1 << SOFT_STATE);
766 continue;
768 if (!strcmp(arg, "--host-states")) {
769 event_filter |= EVT_HOST;
770 parse_host_state_filter(opt);
771 continue;
773 if (!strcmp(arg, "--service-states")) {
774 event_filter |= EVT_SERVICE;
775 parse_service_state_filter(opt);
776 continue;
778 if (!strcmp(arg, "--time-format")) {
779 parse_time_format(opt);
780 continue;
783 /* non-argument, so treat as config- or log-file */
784 arg_len = strlen(arg);
785 if (arg_len > 7 && !strcmp(&arg[arg_len - 7], "cgi.cfg")) {
786 cgi_cfg = arg;
787 } else if (!strcmp(&arg[strlen(arg) - 10], "nagios.cfg")) {
788 nagios_cfg = arg;
789 } else {
790 add_naglog_path(arg);
794 if (debug_level)
795 print_interesting_objects();
797 /* fallback for op5 systems */
798 if (auth_get_user() || (!nagios_cfg && !num_nfile)) {
799 struct cfg_comp *conf;
801 conf = cfg_parse_file(cgi_cfg ? cgi_cfg : "/opt/monitor/etc/cgi.cfg");
802 if (conf) {
803 int i;
804 for (i = 0; i < conf->vars; i++) {
805 struct cfg_var *v = conf->vlist[i];
806 if (!nagios_cfg && !strcmp(v->key, "main_config_file")) {
807 nagios_cfg = strdup(v->value);
809 if (!prefixcmp(v->key, "authorized_for_")) {
810 auth_parse_permission(v->key, v->value);
813 cfg_destroy_compound(conf);
814 } else {
815 if (cgi_cfg) {
816 crash("Failed to parse cgi.cfg file '%s'\n", cgi_cfg);
818 if (auth_get_user()) {
819 crash("--user given, but no suitable cgi.cfg file found\n");
824 if (!nagios_cfg && !num_nfile) {
825 nagios_cfg = "/opt/monitor/etc/nagios.cfg";
827 if (nagios_cfg) {
828 struct cfg_comp *conf;
830 conf = cfg_parse_file(nagios_cfg);
831 if (!conf)
832 usage("Failed to parse nagios' main config file '%s'\n", nagios_cfg);
833 for (i = 0; i < conf->vars; i++) {
834 struct cfg_var *v = conf->vlist[i];
835 if (!strcmp(v->key, "log_file")) {
836 add_naglog_path(v->value);
838 if (!strcmp(v->key, "log_archive_path")) {
839 add_naglog_path(v->value);
841 if (!object_cache && !strcmp(v->key, "object_cache_file")) {
842 object_cache = v->value;
847 if (!num_nfile)
848 usage(NULL);
850 if (auth_get_user() && object_cache) {
851 auth_init(object_cache);
854 if (hide_state_dupes)
855 state_init();
857 /* make sure first_time and last_time are set */
858 last_time = last_time ? last_time : time(NULL);
859 first_time = first_time ? first_time : 1;
861 /* flip them if the user made an error (common when reverse-importing) */
862 if (last_time < first_time) {
863 int temp = last_time;
864 last_time = first_time;
865 first_time = temp;
868 if (reverse_parse_files)
869 qsort(nfile, num_nfile, sizeof(*nfile), nfile_rev_cmp);
870 else
871 qsort(nfile, num_nfile, sizeof(*nfile), nfile_cmp);
873 for (i = 0; i < num_nfile; i++) {
874 struct naglog_file *nf = &nfile[i];
875 time_t last; /* last possible timestamp in current file */
877 if (reverse_parse_files)
878 last = i ? nfile[i - 1].first : time(NULL);
879 else
880 last = i + 1 < num_nfile ? nfile[i + 1].first : time(NULL);
882 if (first_time > last || last_time < nf->first) {
883 continue;
886 cur_file = nf;
887 debug("importing from %s (%lu : %u)\n", nf->path, nf->first, nf->cmp);
888 line_no = 0;
889 lparse_path_real(reverse_parse_files, nf->path, nf->size, parse_line);
892 if (warnings && debug_level)
893 fprintf(stderr, "Total warnings: %d\n", warnings);
895 print_unhandled_events();
897 return 0;