showlog: Don't show INITIAL/CURRENT state for uninteresting objects
[nagios-reports-module.git] / showlog.c
blobfaa4e0f491314fed571840706a411079867eb71c
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"
13 #define MAX_NVECS 16
14 #define HASH_TABLE_SIZE 128
16 static time_t first_time, last_time; /* first and last timestamp to show */
17 static time_t ltime; /* the timestamp from the current log-line */
18 static uint severity;
19 static const char *image_url = "/ninja/application/views/themes/default/icons/16x16";
20 static int reverse_parse_files;
21 static uint skip, limit;
23 #define EVT_PROCESS (1 << 0)
24 #define EVT_NOTIFY (1 << 1)
25 #define EVT_ALERT (1 << 2)
26 #define EVT_COMMAND (1 << 3)
27 #define EVT_STATE (1 << 4)
28 #define EVT_FLAPPING (1 << 5)
29 #define EVT_DOWNTIME (1 << 6)
30 #define EVT_LROTATE (1 << 7)
31 #define EVT_EHANDLER (1 << 8)
32 #define EVT_START (1 << 9)
33 #define EVT_STOP (1 << 10)
35 #define EVT_HOST (1 << 20)
36 #define EVT_SERVICE (1 << 21)
37 #define EVT_INITIAL (1 << 22)
39 #define EVENT_MASK (0xffffffff & (~(EVT_HOST | EVT_SERVICE)))
40 static int event_filter = EVENT_MASK;
41 static int host_state_filter = -1;
42 static int service_state_filter = -1;
43 static int statetype_filter = (1 << HARD_STATE) | (1 << SOFT_STATE);
45 #define add_event(string, eventcode) add_code(0, string, eventcode)
46 static struct string_code event_codes[] = {
47 add_event("Error", EVT_PROCESS),
48 add_event("Warning", EVT_PROCESS),
49 add_event("HOST NOTIFICATION", EVT_NOTIFY | EVT_SERVICE),
50 add_event("HOST FLAPPING ALERT", EVT_FLAPPING | EVT_HOST),
51 add_event("SERVICE NOTIFICATION", EVT_NOTIFY | EVT_SERVICE),
52 add_event("SERVICE FLAPPING ALERT", EVT_FLAPPING | EVT_SERVICE),
53 add_event("LOG ROTATION", EVT_LROTATE),
54 add_event("HOST EVENT HANDLER", EVT_EHANDLER | EVT_HOST),
55 add_event("SERVICE EVENT HANDLER", EVT_EHANDLER | EVT_SERVICE),
56 add_event("LOG VERSION", EVT_PROCESS),
57 add_event("EXTERNAL COMMAND", EVT_COMMAND),
59 add_code(5, "HOST ALERT", EVT_ALERT | EVT_HOST),
60 add_code(5, "INITIAL HOST STATE", EVT_STATE | EVT_HOST | EVT_INITIAL),
61 add_code(5, "CURRENT HOST STATE", EVT_STATE | EVT_HOST | EVT_INITIAL),
62 add_code(6, "SERVICE ALERT", EVT_ALERT | EVT_SERVICE),
63 add_code(6, "INITIAL SERVICE STATE", EVT_STATE | EVT_SERVICE | EVT_INITIAL),
64 add_code(6, "CURRENT SERVICE STATE", EVT_STATE | EVT_SERVICE | EVT_INITIAL),
65 add_code(3, "HOST DOWNTIME ALERT", EVT_DOWNTIME | EVT_HOST),
66 add_code(4, "SERVICE DOWNTIME ALERT", EVT_DOWNTIME | EVT_SERVICE),
67 { 0, NULL, 0, 0 },
70 static void print_time_iso8601(struct tm *t)
72 printf("[%d-%02d-%02d %02d:%02d:%02d] ",
73 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
74 t->tm_hour, t->tm_min, t->tm_sec);
77 static void print_time_div_iso8601(struct tm *t)
79 printf("%d-%02d-%02d %02d:00 ",
80 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour);
83 static void print_time_raw(struct tm *t)
85 printf("[%lu] ", ltime);
88 static struct {
89 char *name;
90 void (*func)(struct tm *);
91 void (*func_div)(struct tm *);
92 } time_format_selections[] = {
93 { "iso8601", print_time_iso8601, print_time_div_iso8601 },
94 { "raw", print_time_raw, NULL },
95 { NULL },
97 static void (*print_time)(struct tm *) = print_time_iso8601;
98 static void (*print_time_div)(struct tm *) = print_time_div_iso8601;
100 static void parse_time_format(const char *selection)
102 int i;
104 if (selection) for (i = 0; time_format_selections[i].name; i++) {
105 if (strcasecmp(selection, time_format_selections[i].name))
106 continue;
107 print_time = time_format_selections[i].func;
108 print_time_div = time_format_selections[i].func_div;
109 return;
112 crash("Illegal timeformat selection: '%s'\n", selection);
115 static inline void pre_print_mangle_line(struct tm *t, char *line, uint len)
117 uint i;
119 for (i = 0; i < len; i++) {
120 if (!line[i])
121 line[i] = ';';
124 gmtime_r(&ltime, t);
125 if (!t->tm_isdst)
126 t->tm_hour++;
130 static void print_line_ascii(int type, struct tm *t, char *line, uint len)
132 print_time(t);
133 puts(line);
137 static void print_line_ansi(int type, struct tm *t, char *line, uint len)
139 const char *color = NULL;
141 switch (type & ~EVT_INITIAL) {
142 case EVT_ALERT | EVT_HOST:
143 case EVT_STATE | EVT_HOST:
144 if (severity == HOST_UP)
145 color = CLR_GREEN;
146 else
147 color = CLR_RED;
148 break;
150 case EVT_ALERT | EVT_SERVICE:
151 case EVT_STATE | EVT_SERVICE:
152 switch (severity) {
153 case SERVICE_OK: color = CLR_GREEN; break;
154 case SERVICE_WARNING: color = CLR_YELLOW; break;
155 case SERVICE_CRITICAL: color = CLR_RED; break;
156 case SERVICE_UNKNOWN: color = CLR_BROWN; break;
158 break;
160 case EVT_DOWNTIME | EVT_HOST:
161 case EVT_DOWNTIME | EVT_SERVICE:
162 color = CLR_BLUE;
163 break;
165 case EVT_FLAPPING | EVT_HOST:
166 case EVT_FLAPPING | EVT_SERVICE:
167 color = CLR_CYAN;
168 break;
170 case EVT_PROCESS:
171 color = CLR_MAGENTA;
172 break;
174 case EVT_LROTATE:
175 color = CLR_BOLD;
176 break;
178 case EVT_COMMAND:
179 color = CLR_BRIGHT_MAGENTA;
180 break;
182 case EVT_START: case EVT_STOP:
183 color = CLR_BRIGHT_BLUE;
184 break;
187 if (color) {
188 printf("%s", color);
189 print_time(t);
190 printf("%s%s\n", line, CLR_RESET);
191 } else {
192 print_time(t);
193 puts(line);
198 static void print_time_break(struct tm *t)
200 struct tm h;
202 memcpy(&h, t, sizeof(h));
203 h.tm_min = h.tm_sec = 0;
204 if (reverse_parse_files) {
205 /* using mktime and gmtime_r again here means we never
206 * have to worry about changing date, month or year in
207 * case we overshoot by one */
208 time_t when = mktime(&h) + 3600;
209 gmtime_r(&when, &h);
212 printf("<h2>");
213 print_time_div(&h);
214 puts("</h2>");
218 static void print_line_html(int type, struct tm *t, char *line, uint len)
220 const char *image = NULL;
221 static time_t last_time_break = 0;
223 switch (type) {
224 case EVT_ALERT | EVT_HOST:
225 case EVT_STATE | EVT_HOST:
226 if (severity == HOST_UP)
227 image = "shield-ok.png";
228 else
229 image = "shield-critical.png";
230 break;
232 case EVT_ALERT | EVT_SERVICE:
233 case EVT_STATE | EVT_SERVICE:
234 switch (severity) {
235 case SERVICE_OK: image = "shield-ok.png"; break;
236 case SERVICE_WARNING: image = "shield-warning.png"; break;
237 case SERVICE_CRITICAL: image = "shield-critical.png"; break;
238 case SERVICE_UNKNOWN: image = "shield-unknown.png"; break;
240 break;
242 case EVT_DOWNTIME | EVT_HOST:
243 case EVT_DOWNTIME | EVT_SERVICE:
244 image = "scheduled-downtime.png";
245 break;
247 case EVT_FLAPPING | EVT_HOST:
248 case EVT_FLAPPING | EVT_SERVICE:
249 image = "flapping.gif";
250 break;
252 case EVT_COMMAND:
253 image = "command.png";
254 break;
256 case EVT_LROTATE:
257 image = "logrotate.png";
258 break;
260 case EVT_EHANDLER | EVT_HOST:
261 image = "hostevent.gif";
262 break;
264 case EVT_EHANDLER | EVT_SERVICE:
265 image = "serviceevent.gif";
266 break;
268 case EVT_START:
269 image = "start.png";
270 break;
272 case EVT_STOP:
273 image = "stop.png";
274 break;
277 if (!image)
278 image = "shield-info.png";
280 if (last_time_break != ltime / 3600) {
281 print_time_break(t);
282 last_time_break = ltime / 3600;
285 printf("<img src=\"%s/%s\" alt=\"%s\" /> ", image_url, image, image);
286 print_time(t);
287 printf("%s<br />\n", line);
291 static void (*real_print_line)(int type, struct tm *, char *, uint) = print_line_ascii;
292 static void print_line(int type, char *line, uint len)
294 struct tm t;
296 /* are we still skipping? If so, return early */
297 if (skip) {
298 skip--;
299 return;
302 pre_print_mangle_line(&t, line, len);
303 real_print_line(type, &t, line, len);
305 /* if we've printed all the lines we should, just exit */
306 if (limit) {
307 if (!--limit)
308 exit(0);
313 static int parse_line(char *orig_line, uint len)
315 char *ptr, *colon, *line;
316 int nvecs = 0;
317 struct string_code *sc;
319 line_no++;
321 /* ignore empty lines */
322 if (!len)
323 return 0;
325 /* skip obviously bogus lines */
326 if (len < 12 || *orig_line != '[') {
327 warn("line %d; len too short, or line doesn't start with '[' (%s)",
328 line_no, orig_line);
329 return -1;
332 ltime = strtoul(orig_line + 1, &ptr, 10);
333 if (orig_line + 1 == ptr) {
334 crash("Failed to parse log timestamp from '%s'. I can't handle malformed logdata",
335 orig_line);
336 return -1;
339 /* only print lines in the interesting interval */
340 if (ltime < first_time || ltime > last_time)
341 return 0;
343 while (*ptr == ']' || *ptr == ' ')
344 ptr++;
346 line = ptr;
347 len -= line - orig_line;
349 if (!is_interesting(ptr))
350 return 0;
352 if (!(colon = strchr(ptr, ':'))) {
353 /* stupid heuristic, but might be good for something,
354 * somewhere, sometime. if nothing else, it should suppress
355 * annoying output */
356 if (!(event_filter & EVT_PROCESS))
357 return 0;
359 if (is_start_event(ptr)) {
360 print_line(EVT_START, line, len);
361 } else if (is_stop_event(ptr)) {
362 print_line(EVT_STOP, line, len);
365 return 0;
368 if (!(sc = get_event_type(ptr, colon - ptr))) {
369 return 0;
372 if (sc->code == IGNORE_LINE)
373 return 0;
374 if ((sc->code & event_filter) != sc->code)
375 return 0;
377 ptr = colon + 1;
378 while (*ptr == ' ')
379 ptr++;
381 if (sc->nvecs) {
382 int i;
384 nvecs = vectorize_string(ptr, sc->nvecs);
386 if (nvecs != sc->nvecs) {
387 /* broken line */
388 warn("Line %d in %s seems to not have all the fields it should",
389 line_no, cur_file->path);
390 return -1;
393 for (i = 0; i < sc->nvecs; i++) {
394 if (!strv[i]) {
395 /* this should never happen */
396 warn("Line %d in %s seems to be broken, or we failed to parse it into a vector",
397 line_no, cur_file->path);
398 return -1;
403 switch (sc->code & ~EVT_INITIAL) {
404 case EVT_ALERT | EVT_HOST:
405 case EVT_STATE | EVT_HOST:
406 if (!(statetype_filter & (1 << soft_hard(strv[2]))))
407 return 0;
408 if (!(host_state_filter & (1 << parse_host_state(strv[1]))))
409 return 0;
410 if (!auth_host_ok(strv[0]))
411 return 0;
412 if (!is_interesting_host(strv[0]))
413 return 0;
415 severity = parse_host_state(strv[1]);
416 break;
418 case EVT_ALERT | EVT_SERVICE:
419 case EVT_STATE | EVT_SERVICE:
420 if (!(statetype_filter & (1 << soft_hard(strv[3]))))
421 return 0;
422 if (!(service_state_filter & (1 << parse_service_state(strv[2]))))
423 return 0;
424 if (!auth_service_ok(strv[0], strv[1]))
425 return 0;
426 if (!is_interesting_service(strv[0], strv[1]))
427 return 0;
429 severity = parse_service_state(strv[2]);
430 break;
432 case EVT_FLAPPING | EVT_HOST:
433 case EVT_DOWNTIME | EVT_HOST:
434 if (!auth_host_ok(strv[0]))
435 return 0;
436 if (!is_interesting_host(strv[0]))
437 return 0;
438 break;
440 case EVT_FLAPPING | EVT_SERVICE:
441 case EVT_DOWNTIME | EVT_SERVICE:
442 if (!auth_service_ok(strv[0], strv[1]))
443 return 0;
444 if (!is_interesting_service(strv[0], strv[1]))
445 return 0;
446 break;
448 case EVT_NOTIFY | EVT_HOST:
449 if (!auth_host_ok(strv[1]))
450 return 0;
451 if (!is_interesting_host(strv[1]))
452 return 0;
454 case EVT_NOTIFY | EVT_SERVICE:
455 if (!auth_service_ok(strv[1], strv[2]))
456 return 0;
457 if (!is_interesting_service(strv[1], strv[2]))
458 return 0;
461 print_line(sc->code, line, len);
462 return 0;
466 * hashes one line from an "interesting"-file. We use (void *)1
467 * to mark this as "present in hash-table" as we have no real
468 * data to lookup but still want hash_find{,2} to return non-NULL
469 * when it finds a match
471 static int hash_one_line(char *line, uint len)
473 return add_interesting_object(line);
476 static int hash_interesting(const char *path)
478 struct stat st;
480 if (stat(path, &st) < 0)
481 crash("failed to stat %s: %s", path, strerror(errno));
483 lparse_path(path, st.st_size, hash_one_line);
485 return 0;
488 static void parse_host_state_filter(char *p)
490 host_state_filter = 0;
491 for (; *p; p++) {
492 switch (*p) {
493 case 'a': case '*':
494 host_state_filter = -1;
495 break;
496 case 'u':
497 host_state_filter |= 1 << HOST_UNREACHABLE;
498 break;
499 case 'd':
500 host_state_filter |= 1 << HOST_DOWN;
501 break;
502 case 'r':
503 host_state_filter |= 1 << HOST_UP;
504 break;
509 static void parse_service_state_filter(char *p)
511 service_state_filter = 0;
512 for (; *p; p++) {
513 switch (*p) {
514 case 'a': case '*':
515 service_state_filter = -1;
516 break;
517 case 'r':
518 service_state_filter |= 1 << SERVICE_OK;
519 break;
520 case 'w':
521 service_state_filter |= 1 << SERVICE_WARNING;
522 break;
523 case 'c':
524 service_state_filter |= 1 << SERVICE_CRITICAL;
525 break;
526 case 'u':
527 service_state_filter |= 1 << SERVICE_UNKNOWN;
532 extern const char *__progname;
533 static void usage(const char *fmt, ...)
535 int i;
537 if (fmt && *fmt) {
538 va_list ap;
540 va_start(ap, fmt);
541 vprintf(fmt, ap);
542 va_end(ap);
545 printf("usage: %s [options] [logfiles]\n\n", __progname);
546 printf(" <logfiles> refers to all the nagios logfiles you want to search through\n");
547 printf(" If --nagios-cfg is given or can be inferred no logfiles need to be supplied\n");
548 printf("Options:\n");
549 printf(" --reverse parse (and print) logs in reverse\n");
550 printf(" --help this cruft\n");
551 printf(" --debug print debugging information\n");
552 printf(" --html print html output\n");
553 printf(" --ansi force-colorize the output\n");
554 printf(" --ascii don't colorize the output\n"),
555 printf(" --user=<username> show only logs this user can see\n");
556 printf(" --cgi-cfg=</path/to/cgi.cfg> path to cgi.cfg\n");
557 printf(" --nagios-cfg=</path/to/nagios.cfg> path to nagios.cfg\n");
558 printf(" --object-cache=</path/to/objects.cache> path to objects.cache\n");
559 printf(" --image-url=<image url> url to images. Implies --html\n");
560 printf(" --hide-flapping hide flapping messages\n");
561 printf(" --hide-downtime hide downtime messages\n");
562 printf(" --hide-process hide process messages\n");
563 printf(" --hide-command hide external command messages\n");
564 printf(" --hide-notifications hide notification messages\n");
565 printf(" --hide-logrotation hide log rotation messages\n");
566 printf(" --hide-initial hide INITIAL and CURRENT states\n");
567 printf(" --skip=<integer> number of filtered in messages to skip\n");
568 printf(" --limit=<integer> max number of messages to print\n");
569 printf(" --host=<host_name> show log entries for the named host\n");
570 printf(" --service=<hostname;servicedescription> show log entries for the named service\n");
571 printf(" --first=<timestamp> first log-entry to show\n");
572 printf(" --last=<timestamp> last log-entry to show\n");
573 printf(" --state-type=[hard|soft] state-types to show. default is all\n");
574 printf(" --host-states=[*ardu] host-states to show. can be mixed\n");
575 printf(" 'a' and '*' shows 'all'\n");
576 printf(" 'r' shows 'recovery'\n");
577 printf(" 'd' shows 'down'\n");
578 printf(" 'u' shows 'unreachable'\n");
579 printf(" --service-states=[*arwcu] service-states to show. can be mixed\n");
580 printf(" 'a' and '*' shows 'all'\n");
581 printf(" 'r' shows 'recovery'\n");
582 printf(" 'w' shows 'warning'\n");
583 printf(" 'c' shows 'critical'\n");
584 printf(" 'u' shows 'unknown'\n");
585 printf(" --time-format=[");
586 for (i = 0; time_format_selections[i].name; i++) {
587 printf("%s", time_format_selections[i].name);
588 if (time_format_selections[i + 1].name)
589 printf("|");
591 printf("] set timeformat for log-entries\n");
593 putchar('\n');
595 if (fmt && *fmt)
596 exit(1);
598 exit(0);
601 int main(int argc, char **argv)
603 int i;
604 const char *nagios_cfg = NULL, *cgi_cfg = NULL, *object_cache = NULL;
606 strv = calloc(sizeof(char *), MAX_NVECS);
607 if (!strv)
608 crash("Failed to alloc initial structs");
610 if (isatty(fileno(stdout))) {
611 real_print_line = print_line_ansi;
612 event_filter &= ~(EVT_LROTATE | EVT_PROCESS);
615 for (i = 1; i < argc; i++) {
616 char *opt, *arg = argv[i];
617 int arg_len, eq_opt = 0;
619 if ((opt = strchr(arg, '='))) {
620 *opt++ = '\0';
621 eq_opt = 1;
623 else if (i < argc - 1) {
624 opt = argv[i + 1];
627 if (!strcmp(arg, "--reverse")) {
628 reverse_parse_files = 1;
629 continue;
631 if (!strcmp(arg, "--html")) {
632 real_print_line = print_line_html;
633 continue;
635 if (!strcmp(arg, "--ansi")) {
636 real_print_line = print_line_ansi;
637 continue;
639 if (!strcmp(arg, "--ascii")) {
640 real_print_line = print_line_ascii;
641 continue;
643 if (!strcmp(arg, "--debug") || !strcmp(arg, "-d")) {
644 debug_level++;
645 continue;
647 if (!strcmp(arg, "--help")) {
648 usage(NULL);
649 continue;
651 if (!prefixcmp(arg, "--hide-flapping")) {
652 event_filter &= ~EVT_FLAPPING;
653 continue;
655 if (!prefixcmp(arg, "--hide-downtime")) {
656 event_filter &= ~EVT_DOWNTIME;
657 continue;
659 if (!prefixcmp(arg, "--hide-process")) {
660 event_filter &= ~EVT_PROCESS;
661 continue;
663 if (!prefixcmp(arg, "--hide-command")) {
664 event_filter &= ~EVT_COMMAND;
665 continue;
667 if (!prefixcmp(arg, "--hide-notification")) {
668 event_filter &= ~EVT_NOTIFY;
669 continue;
671 if (!prefixcmp(arg, "--hide-logrotat")) {
672 event_filter &= ~EVT_LROTATE;
673 continue;
675 if (!prefixcmp(arg, "--hide-initial")) {
676 event_filter &= ~EVT_INITIAL;
677 continue;
680 if (!prefixcmp(arg, "--")) {
681 if (!opt)
682 usage("Option '%s' requires an argument\n", arg);
683 if (!eq_opt)
684 i++;
687 /* options parsed below require arguments */
688 if (!strcmp(arg, "--user")) {
689 auth_set_user(opt);
690 continue;
692 if (!prefixcmp(arg, "--object-cache")) {
693 object_cache = opt;
694 continue;
696 if (!strcmp(arg, "--nagios-cfg")) {
697 nagios_cfg = opt;
698 continue;
700 if (!strcmp(arg, "--cgi-cfg")) {
701 cgi_cfg = opt;
702 continue;
704 if (!strcmp(arg, "--skip")) {
705 skip = strtoul(opt, NULL, 0);
706 continue;
708 if (!strcmp(arg, "--limit")) {
709 limit = strtoul(opt, NULL, 0);
710 continue;
712 if (!strcmp(arg, "--host")) {
713 event_filter |= EVT_HOST;
714 add_interesting_object(opt);
715 continue;
717 if (!strcmp(arg, "--service")) {
718 event_filter |= EVT_SERVICE;
719 add_interesting_object(opt);
720 continue;
722 if (!strcmp(arg, "--image-url")) {
723 real_print_line = print_line_html;
724 image_url = opt;
725 continue;
727 if (!strcmp(arg, "--interesting") || !strcmp(arg, "-i")) {
728 if (!opt || !*opt)
729 usage("%s requires a filename as argument", arg);
730 hash_interesting(opt);
731 continue;
733 if (!strcmp(arg, "--first") || !strcmp(arg, "--last")) {
734 time_t when;
736 if (!opt || !*opt)
737 crash("%s requires a timestamp as argument", arg);
738 when = strtoul(opt, NULL, 0);
739 if (opt && !eq_opt)
740 i++;
741 if (!strcmp(arg, "--first"))
742 first_time = when;
743 else
744 last_time = when;
745 continue;
747 if (!strcmp(arg, "--state-type")) {
748 if (!strcasecmp(opt, "hard"))
749 statetype_filter = (1 << HARD_STATE);
750 if (!strcasecmp(opt, "soft"))
751 statetype_filter = (1 << SOFT_STATE);
752 continue;
754 if (!strcmp(arg, "--host-states")) {
755 event_filter |= EVT_HOST;
756 parse_host_state_filter(opt);
757 continue;
759 if (!strcmp(arg, "--service-states")) {
760 event_filter |= EVT_SERVICE;
761 parse_service_state_filter(opt);
762 continue;
764 if (!strcmp(arg, "--time-format")) {
765 parse_time_format(opt);
766 continue;
769 /* non-argument, so treat as config- or log-file */
770 arg_len = strlen(arg);
771 if (arg_len > 7 && !strcmp(&arg[arg_len - 7], "cgi.cfg")) {
772 cgi_cfg = arg;
773 } else if (!strcmp(&arg[strlen(arg) - 10], "nagios.cfg")) {
774 nagios_cfg = arg;
775 } else {
776 add_naglog_path(arg);
780 if (debug_level)
781 print_interesting_objects();
783 /* fallback for op5 systems */
784 if (auth_get_user() || (!nagios_cfg && !num_nfile)) {
785 struct cfg_comp *conf;
787 conf = cfg_parse_file(cgi_cfg ? cgi_cfg : "/opt/monitor/etc/cgi.cfg");
788 if (conf) {
789 int i;
790 for (i = 0; i < conf->vars; i++) {
791 struct cfg_var *v = conf->vlist[i];
792 if (!nagios_cfg && !strcmp(v->key, "main_config_file")) {
793 nagios_cfg = strdup(v->value);
795 if (!prefixcmp(v->key, "authorized_for_")) {
796 auth_parse_permission(v->key, v->value);
799 cfg_destroy_compound(conf);
800 } else {
801 if (cgi_cfg) {
802 crash("Failed to parse cgi.cfg file '%s'\n", cgi_cfg);
804 if (auth_get_user()) {
805 crash("--user given, but no suitable cgi.cfg file found\n");
810 if (!nagios_cfg && !num_nfile) {
811 nagios_cfg = "/opt/monitor/etc/nagios.cfg";
813 if (nagios_cfg) {
814 struct cfg_comp *conf;
816 conf = cfg_parse_file(nagios_cfg);
817 if (!conf)
818 usage("Failed to parse nagios' main config file '%s'\n", nagios_cfg);
819 for (i = 0; i < conf->vars; i++) {
820 struct cfg_var *v = conf->vlist[i];
821 if (!strcmp(v->key, "log_file")) {
822 add_naglog_path(v->value);
824 if (!strcmp(v->key, "log_archive_path")) {
825 add_naglog_path(v->value);
827 if (!object_cache && !strcmp(v->key, "object_cache_file")) {
828 object_cache = v->value;
833 if (!num_nfile)
834 usage(NULL);
836 if (auth_get_user() && object_cache) {
837 auth_init(object_cache);
840 /* make sure first_time and last_time are set */
841 last_time = last_time ? last_time : time(NULL);
842 first_time = first_time ? first_time : 1;
844 /* flip them if the user made an error (common when reverse-importing) */
845 if (last_time < first_time) {
846 int temp = last_time;
847 last_time = first_time;
848 first_time = temp;
851 if (reverse_parse_files)
852 qsort(nfile, num_nfile, sizeof(*nfile), nfile_rev_cmp);
853 else
854 qsort(nfile, num_nfile, sizeof(*nfile), nfile_cmp);
856 for (i = 0; i < num_nfile; i++) {
857 struct naglog_file *nf = &nfile[i];
858 time_t last; /* last possible timestamp in current file */
860 if (reverse_parse_files)
861 last = i ? nfile[i - 1].first : time(NULL);
862 else
863 last = i + 1 < num_nfile ? nfile[i + 1].first : time(NULL);
865 if (first_time > last || last_time < nf->first) {
866 continue;
869 cur_file = nf;
870 debug("importing from %s (%lu : %u)\n", nf->path, nf->first, nf->cmp);
871 line_no = 0;
872 lparse_path_real(reverse_parse_files, nf->path, nf->size, parse_line);
875 if (warnings && debug_level)
876 fprintf(stderr, "Total warnings: %d\n", warnings);
878 print_unhandled_events();
880 return 0;