1 /***********************************************************************
2  *
3  * HISTORY.C - Nagios History CGI
4  *
5  *
6  * This CGI program will display the history for the specified host.
7  * If no host is specified, the history for all hosts will be displayed.
8  *
9  * License:
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  ***********************************************************************/
24 
25 #include "../include/config.h"
26 #include "../include/common.h"
27 #include "../include/objects.h"
28 
29 #include "../include/getcgi.h"
30 #include "../include/cgiutils.h"
31 #include "../include/cgiauth.h"
32 
33 #define DISPLAY_HOSTS			0
34 #define DISPLAY_SERVICES		1
35 
36 #define SERVICE_HISTORY			0
37 #define HOST_HISTORY			1
38 #define SERVICE_FLAPPING_HISTORY        2
39 #define HOST_FLAPPING_HISTORY           3
40 #define SERVICE_DOWNTIME_HISTORY        4
41 #define HOST_DOWNTIME_HISTORY           5
42 
43 #define STATE_ALL			0
44 #define STATE_SOFT			1
45 #define STATE_HARD			2
46 
47 void get_history(void);
48 
49 void document_header(int);
50 void document_footer(void);
51 int process_cgivars(void);
52 
53 extern char main_config_file[MAX_FILENAME_LENGTH];
54 extern char url_html_path[MAX_FILENAME_LENGTH];
55 extern char url_images_path[MAX_FILENAME_LENGTH];
56 extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
57 
58 extern int enable_splunk_integration;
59 
60 authdata current_authdata;
61 
62 char log_file_to_use[MAX_FILENAME_LENGTH];
63 int log_archive = 0;
64 
65 int show_all_hosts = TRUE;
66 char *host_name = "all";
67 char *svc_description = "";
68 int display_type = DISPLAY_HOSTS;
69 int use_lifo = TRUE;
70 
71 int history_options = HISTORY_ALL;
72 int state_options = STATE_ALL;
73 
74 int embedded = FALSE;
75 int display_header = TRUE;
76 int display_frills = TRUE;
77 int display_timebreaks = TRUE;
78 int display_system_messages = TRUE;
79 int display_flapping_alerts = TRUE;
80 int display_downtime_alerts = TRUE;
81 
82 
main(void)83 int main(void) {
84 	char temp_buffer[MAX_INPUT_BUFFER];
85 	char temp_buffer2[MAX_INPUT_BUFFER];
86 
87 	/* get the variables passed to us */
88 	process_cgivars();
89 
90 	/* reset internal CGI variables */
91 	reset_cgi_vars();
92 
93 	cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0);
94 
95 	document_header(TRUE);
96 
97 	/* get authentication information */
98 	get_authentication_information(&current_authdata);
99 
100 	/* determine what log file we should be using */
101 	get_log_archive_to_use(log_archive, log_file_to_use, (int)sizeof(log_file_to_use));
102 
103 	if(display_header == TRUE) {
104 
105 		/* begin top table */
106 		printf("<table border=0 width=100%%>\n");
107 		printf("<tr>\n");
108 
109 		/* left column of the first row */
110 		printf("<td align=left valign=top width=33%%>\n");
111 
112 		if(display_type == DISPLAY_SERVICES)
113 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service Alert History");
114 		else if(show_all_hosts == TRUE)
115 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Alert History");
116 		else
117 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host Alert History");
118 		temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
119 		display_info_table(temp_buffer, FALSE, &current_authdata);
120 
121 		printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
122 		printf("<TR><TD CLASS='linkBox'>\n");
123 		if(display_type == DISPLAY_HOSTS) {
124 			printf("<A HREF='%s?host=%s'>View Status Detail For %s</A><BR />\n", STATUS_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "All Hosts" : "This Host");
125 			printf("<A HREF='%s?host=%s'>View Notifications For %s</A><BR />\n", NOTIFICATIONS_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "All Hosts" : "This Host");
126 #ifdef USE_TRENDS
127 			if(show_all_hosts == FALSE)
128 				printf("<A HREF='%s?host=%s'>View Trends For This Host</A>\n", TRENDS_CGI, url_encode(host_name));
129 #endif
130 			}
131 		else {
132 			printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
133 			printf("service=%s'>View Notifications For This Service</A><BR />\n", url_encode(svc_description));
134 #ifdef USE_TRENDS
135 			printf("<A HREF='%s?host=%s&", TRENDS_CGI, url_encode(host_name));
136 			printf("service=%s'>View Trends For This Service</A><BR />\n", url_encode(svc_description));
137 #endif
138 			printf("<A HREF='%s?host=%s'>View History For This Host</A>\n", HISTORY_CGI, url_encode(host_name));
139 			}
140 		printf("</TD></TR>\n");
141 		printf("</TABLE>\n");
142 
143 		printf("</td>\n");
144 
145 
146 		/* middle column of top row */
147 		printf("<td align=center valign=top width=33%%>\n");
148 
149 		printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
150 		if(display_type == DISPLAY_SERVICES)
151 			printf("Service '%s' On Host '%s'", svc_description, host_name);
152 		else if(show_all_hosts == TRUE)
153 			printf("All Hosts and Services");
154 		else
155 			printf("Host '%s'", host_name);
156 		printf("</DIV>\n");
157 		printf("<BR />\n");
158 
159 		snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s?%shost=%s&type=%d&statetype=%d&", HISTORY_CGI, (use_lifo == FALSE) ? "oldestfirst&" : "", url_encode(host_name), history_options, state_options);
160 		temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
161 		if(display_type == DISPLAY_SERVICES) {
162 			snprintf(temp_buffer2, sizeof(temp_buffer2) - 1, "service=%s&", url_encode(svc_description));
163 			temp_buffer2[sizeof(temp_buffer2) - 1] = '\x0';
164 			strncat(temp_buffer, temp_buffer2, sizeof(temp_buffer) - strlen(temp_buffer) - 1);
165 			temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
166 			}
167 		display_nav_table(temp_buffer, log_archive);
168 
169 		printf("</td>\n");
170 
171 
172 		/* right hand column of top row */
173 		printf("<td align=right valign=top width=33%%>\n");
174 
175 		printf("<form method=\"GET\" action=\"%s\">\n", HISTORY_CGI);
176 		printf("<table border=0 CLASS='optBox'>\n");
177 		printf("<input type='hidden' name='host' value='%s'>\n", (show_all_hosts == TRUE) ? "all" : escape_string(host_name));
178 		if(display_type == DISPLAY_SERVICES)
179 			printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
180 		printf("<input type='hidden' name='archive' value='%d'>\n", log_archive);
181 
182 		printf("<tr>\n");
183 		printf("<td align=left CLASS='optBoxItem'>State type options:</td>\n");
184 		printf("</tr>\n");
185 
186 		printf("<tr>\n");
187 		printf("<td align=left CLASS='optBoxItem'><select name='statetype'>\n");
188 		printf("<option value=%d %s>All state types</option>\n", STATE_ALL, (state_options == STATE_ALL) ? "selected" : "");
189 		printf("<option value=%d %s>Soft states</option>\n", STATE_SOFT, (state_options == STATE_SOFT) ? "selected" : "");
190 		printf("<option value=%d %s>Hard states</option>\n", STATE_HARD, (state_options == STATE_HARD) ? "selected" : "");
191 		printf("</select></td>\n");
192 		printf("</tr>\n");
193 
194 		printf("<tr>\n");
195 		printf("<td align=left CLASS='optBoxItem'>History detail level for ");
196 		if(display_type == DISPLAY_HOSTS)
197 			printf("%s host%s", (show_all_hosts == TRUE) ? "all" : "this", (show_all_hosts == TRUE) ? "s" : "");
198 		else
199 			printf("service");
200 		printf(":</td>\n");
201 		printf("</tr>\n")
202 		;
203 		printf("<tr>\n");
204 		printf("<td align=left CLASS='optBoxItem'><select name='type'>\n");
205 		if(display_type == DISPLAY_HOSTS)
206 			printf("<option value=%d %s>All alerts</option>\n", HISTORY_ALL, (history_options == HISTORY_ALL) ? "selected" : "");
207 		printf("<option value=%d %s>All service alerts</option>\n", HISTORY_SERVICE_ALL, (history_options == HISTORY_SERVICE_ALL) ? "selected" : "");
208 		if(display_type == DISPLAY_HOSTS)
209 			printf("<option value=%d %s>All host alerts</option>\n", HISTORY_HOST_ALL, (history_options == HISTORY_HOST_ALL) ? "selected" : "");
210 		printf("<option value=%d %s>Service warning</option>\n", HISTORY_SERVICE_WARNING, (history_options == HISTORY_SERVICE_WARNING) ? "selected" : "");
211 		printf("<option value=%d %s>Service unknown</option>\n", HISTORY_SERVICE_UNKNOWN, (history_options == HISTORY_SERVICE_UNKNOWN) ? "selected" : "");
212 		printf("<option value=%d %s>Service critical</option>\n", HISTORY_SERVICE_CRITICAL, (history_options == HISTORY_SERVICE_CRITICAL) ? "selected" : "");
213 		printf("<option value=%d %s>Service recovery</option>\n", HISTORY_SERVICE_RECOVERY, (history_options == HISTORY_SERVICE_RECOVERY) ? "selected" : "");
214 		if(display_type == DISPLAY_HOSTS) {
215 			printf("<option value=%d %s>Host down</option>\n", HISTORY_HOST_DOWN, (history_options == HISTORY_HOST_DOWN) ? "selected" : "");
216 			printf("<option value=%d %s>Host unreachable</option>\n", HISTORY_HOST_UNREACHABLE, (history_options == HISTORY_HOST_UNREACHABLE) ? "selected" : "");
217 			printf("<option value=%d %s>Host recovery</option>\n", HISTORY_HOST_RECOVERY, (history_options == HISTORY_HOST_RECOVERY) ? "selected" : "");
218 			}
219 		printf("</select></td>\n");
220 		printf("</tr>\n");
221 
222 		printf("<tr>\n");
223 		printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='noflapping' %s> Hide Flapping Alerts</td>", (display_flapping_alerts == FALSE) ? "checked" : "");
224 		printf("</tr>\n");
225 		printf("<tr>\n");
226 		printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='nodowntime' %s> Hide Downtime Alerts</td>", (display_downtime_alerts == FALSE) ? "checked" : "");
227 		printf("</tr>\n");
228 
229 		printf("<tr>\n");
230 		printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='nosystem' %s> Hide Process Messages</td>", (display_system_messages == FALSE) ? "checked" : "");
231 		printf("</tr>\n");
232 		printf("<tr>\n");
233 		printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='oldestfirst' %s> Older Entries First</td>", (use_lifo == FALSE) ? "checked" : "");
234 		printf("</tr>\n");
235 
236 		printf("<tr>\n");
237 		printf("<td align=left CLASS='optBoxItem'><input type='submit' value='Update'></td>\n");
238 		printf("</tr>\n");
239 
240 		/* display context-sensitive help */
241 		printf("<tr>\n");
242 		printf("<td align=right>\n");
243 		display_context_help(CONTEXTHELP_HISTORY);
244 		printf("</td>\n");
245 		printf("</tr>\n");
246 
247 		printf("</table>\n");
248 		printf("</form>\n");
249 
250 		printf("</td>\n");
251 
252 		/* end of top table */
253 		printf("</tr>\n");
254 		printf("</table>\n");
255 
256 		}
257 
258 
259 	/* display history */
260 	get_history();
261 
262 	document_footer();
263 
264 	/* free allocated memory */
265 	free_memory();
266 
267 	return OK;
268 	}
269 
270 
271 
document_header(int use_stylesheet)272 void document_header(int use_stylesheet) {
273 	char date_time[MAX_DATETIME_LENGTH];
274 	time_t current_time;
275 	time_t expire_time;
276 
277 	printf("Cache-Control: no-store\r\n");
278 	printf("Pragma: no-cache\r\n");
279 
280 	time(&current_time);
281 	get_time_string(&current_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
282 	printf("Last-Modified: %s\r\n", date_time);
283 
284 	expire_time = (time_t)0L;
285 	get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
286 	printf("Expires: %s\r\n", date_time);
287 
288 	printf("Content-type: text/html; charset=utf-8\r\n\r\n");
289 
290 	if(embedded == TRUE)
291 		return;
292 
293 	printf("<html>\n");
294 	printf("<head>\n");
295 	printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
296 	printf("<title>\n");
297 	printf("Nagios History\n");
298 	printf("</title>\n");
299 
300 	if(use_stylesheet == TRUE) {
301 		printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
302 		printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, HISTORY_CSS);
303 		}
304 
305 	printf("</head>\n");
306 	printf("<BODY CLASS='history'>\n");
307 
308 	/* include user SSI header */
309 	include_ssi_files(HISTORY_CGI, SSI_HEADER);
310 
311 	return;
312 	}
313 
314 
document_footer(void)315 void document_footer(void) {
316 
317 	if(embedded == TRUE)
318 		return;
319 
320 	/* include user SSI footer */
321 	include_ssi_files(HISTORY_CGI, SSI_FOOTER);
322 
323 	printf("</body>\n");
324 	printf("</html>\n");
325 
326 	return;
327 	}
328 
329 
process_cgivars(void)330 int process_cgivars(void) {
331 	char **variables;
332 	int error = FALSE;
333 	int x;
334 
335 	variables = getcgivars();
336 
337 	for(x = 0; variables[x]; x++) {
338 
339 		/* do some basic length checking on the variable identifier to prevent buffer overflows */
340 		if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1)
341 			continue;
342 
343 		/* we found the host argument */
344 		else if(!strcmp(variables[x], "host")) {
345 			x++;
346 			if(variables[x] == NULL) {
347 				error = TRUE;
348 				break;
349 				}
350 
351 			if((host_name = (char *)strdup(variables[x])) == NULL)
352 				host_name = "";
353 			strip_html_brackets(host_name);
354 
355 			display_type = DISPLAY_HOSTS;
356 
357 			if(!strcmp(host_name, "all"))
358 				show_all_hosts = TRUE;
359 			else
360 				show_all_hosts = FALSE;
361 			}
362 
363 		/* we found the service argument */
364 		else if(!strcmp(variables[x], "service")) {
365 			x++;
366 			if(variables[x] == NULL) {
367 				error = TRUE;
368 				break;
369 				}
370 
371 			if((svc_description = (char *)strdup(variables[x])) == NULL)
372 				svc_description = "";
373 			strip_html_brackets(svc_description);
374 
375 			display_type = DISPLAY_SERVICES;
376 			}
377 
378 
379 		/* we found the history type argument */
380 		else if(!strcmp(variables[x], "type")) {
381 			x++;
382 			if(variables[x] == NULL) {
383 				error = TRUE;
384 				break;
385 				}
386 
387 			history_options = atoi(variables[x]);
388 			}
389 
390 		/* we found the history state type argument */
391 		else if(!strcmp(variables[x], "statetype")) {
392 			x++;
393 			if(variables[x] == NULL) {
394 				error = TRUE;
395 				break;
396 				}
397 
398 			state_options = atoi(variables[x]);
399 			}
400 
401 
402 		/* we found the log archive argument */
403 		else if(!strcmp(variables[x], "archive")) {
404 			x++;
405 			if(variables[x] == NULL) {
406 				error = TRUE;
407 				break;
408 				}
409 
410 			log_archive = atoi(variables[x]);
411 			if(log_archive < 0)
412 				log_archive = 0;
413 			}
414 
415 		/* we found the order argument */
416 		else if(!strcmp(variables[x], "oldestfirst")) {
417 			use_lifo = FALSE;
418 			}
419 
420 		/* we found the embed option */
421 		else if(!strcmp(variables[x], "embedded"))
422 			embedded = TRUE;
423 
424 		/* we found the noheader option */
425 		else if(!strcmp(variables[x], "noheader"))
426 			display_header = FALSE;
427 
428 		/* we found the nofrills option */
429 		else if(!strcmp(variables[x], "nofrills"))
430 			display_frills = FALSE;
431 
432 		/* we found the notimebreaks option */
433 		else if(!strcmp(variables[x], "notimebreaks"))
434 			display_timebreaks = FALSE;
435 
436 		/* we found the no system messages option */
437 		else if(!strcmp(variables[x], "nosystem"))
438 			display_system_messages = FALSE;
439 
440 		/* we found the no flapping alerts option */
441 		else if(!strcmp(variables[x], "noflapping"))
442 			display_flapping_alerts = FALSE;
443 
444 		/* we found the no downtime alerts option */
445 		else if(!strcmp(variables[x], "nodowntime"))
446 			display_downtime_alerts = FALSE;
447 		}
448 
449 	/* free memory allocated to the CGI variables */
450 	free_cgivars(variables);
451 
452 	return error;
453 	}
454 
455 
456 
get_history(void)457 void get_history(void) {
458 	mmapfile *thefile = NULL;
459 	char image[MAX_INPUT_BUFFER];
460 	char image_alt[MAX_INPUT_BUFFER];
461 	char *input = NULL;
462 	char *input2 = NULL;
463 	char match1[MAX_INPUT_BUFFER];
464 	char match2[MAX_INPUT_BUFFER];
465 	int found_line = FALSE;
466 	int system_message = FALSE;
467 	int display_line = FALSE;
468 	time_t t;
469 	char date_time[MAX_DATETIME_LENGTH];
470 	char *temp_buffer = NULL;
471 	int history_type = SERVICE_HISTORY;
472 	int history_detail_type = HISTORY_SERVICE_CRITICAL;
473 	char *entry_host_name = NULL;
474 	char *entry_service_desc = NULL;
475 	host *temp_host = NULL;
476 	service *temp_service = NULL;
477 	int result = 0;
478 
479 	char last_message_date[MAX_INPUT_BUFFER] = "";
480 	char current_message_date[MAX_INPUT_BUFFER] = "";
481 	struct tm *time_ptr = NULL;
482 
483 
484 	if(use_lifo == TRUE) {
485 		result = read_file_into_lifo(log_file_to_use);
486 		if(result != LIFO_OK) {
487 			if(result == LIFO_ERROR_MEMORY) {
488 				printf("<P><DIV CLASS='warningMessage'>Not enough memory to reverse log file - displaying history in natural order...</DIV></P>\n");
489 				}
490 			else if(result == LIFO_ERROR_FILE) {
491 				printf("<HR><P><DIV CLASS='errorMessage'>Error: Cannot open log file '%s' for reading!</DIV></P><HR>", log_file_to_use);
492 				return;
493 				}
494 			use_lifo = FALSE;
495 			}
496 		}
497 
498 	if(use_lifo == FALSE) {
499 
500 		if((thefile = mmap_fopen(log_file_to_use)) == NULL) {
501 			printf("<HR><P><DIV CLASS='errorMessage'>Error: Cannot open log file '%s' for reading!</DIV></P><HR>", log_file_to_use);
502 			return;
503 			}
504 		}
505 
506 	printf("<P><DIV CLASS='logEntries'>\n");
507 
508 	while(1) {
509 
510 		my_free(input);
511 		my_free(input2);
512 
513 		if(use_lifo == TRUE) {
514 			if((input = pop_lifo()) == NULL)
515 				break;
516 			}
517 		else {
518 			if((input = mmap_fgets(thefile)) == NULL)
519 				break;
520 			}
521 
522 		strip(input);
523 
524 		strcpy(image, "");
525 		strcpy(image_alt, "");
526 		system_message = FALSE;
527 
528 		if((input2 = (char *)strdup(input)) == NULL)
529 			continue;
530 
531 		/* service state alerts */
532 		if(strstr(input, "SERVICE ALERT:")) {
533 
534 			history_type = SERVICE_HISTORY;
535 
536 			/* get host and service names */
537 			temp_buffer = my_strtok(input2, "]");
538 			temp_buffer = my_strtok(NULL, ":");
539 			temp_buffer = my_strtok(NULL, ";");
540 			if(temp_buffer)
541 				entry_host_name = strdup(temp_buffer + 1);
542 			else
543 				entry_host_name = NULL;
544 			temp_buffer = my_strtok(NULL, ";");
545 			if(temp_buffer)
546 				entry_service_desc = strdup(temp_buffer);
547 			else
548 				entry_service_desc = NULL;
549 
550 			if(strstr(input, ";CRITICAL;")) {
551 				strncpy(image, CRITICAL_ICON, sizeof(image));
552 				strncpy(image_alt, CRITICAL_ICON_ALT, sizeof(image_alt));
553 				history_detail_type = HISTORY_SERVICE_CRITICAL;
554 				}
555 			else if(strstr(input, ";WARNING;")) {
556 				strncpy(image, WARNING_ICON, sizeof(image));
557 				strncpy(image_alt, WARNING_ICON_ALT, sizeof(image_alt));
558 				history_detail_type = HISTORY_SERVICE_WARNING;
559 				}
560 			else if(strstr(input, ";UNKNOWN;")) {
561 				strncpy(image, UNKNOWN_ICON, sizeof(image));
562 				strncpy(image_alt, UNKNOWN_ICON_ALT, sizeof(image_alt));
563 				history_detail_type = HISTORY_SERVICE_UNKNOWN;
564 				}
565 			else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;")) {
566 				strncpy(image, OK_ICON, sizeof(image));
567 				strncpy(image_alt, OK_ICON_ALT, sizeof(image_alt));
568 				history_detail_type = HISTORY_SERVICE_RECOVERY;
569 				}
570 			}
571 
572 		/* service flapping alerts */
573 		else if(strstr(input, "SERVICE FLAPPING ALERT:")) {
574 
575 			if(display_flapping_alerts == FALSE)
576 				continue;
577 
578 			history_type = SERVICE_FLAPPING_HISTORY;
579 
580 			/* get host and service names */
581 			temp_buffer = my_strtok(input2, "]");
582 			temp_buffer = my_strtok(NULL, ":");
583 			temp_buffer = my_strtok(NULL, ";");
584 			if(temp_buffer)
585 				entry_host_name = strdup(temp_buffer + 1);
586 			else
587 				entry_host_name = NULL;
588 			temp_buffer = my_strtok(NULL, ";");
589 			if(temp_buffer)
590 				entry_service_desc = strdup(temp_buffer);
591 			else
592 				entry_service_desc = NULL;
593 
594 			strncpy(image, FLAPPING_ICON, sizeof(image));
595 
596 			if(strstr(input, ";STARTED;"))
597 				strncpy(image_alt, "Service started flapping", sizeof(image_alt));
598 			else if(strstr(input, ";STOPPED;"))
599 				strncpy(image_alt, "Service stopped flapping", sizeof(image_alt));
600 			else if(strstr(input, ";DISABLED;"))
601 				strncpy(image_alt, "Service flap detection disabled", sizeof(image_alt));
602 			}
603 
604 		/* service downtime alerts */
605 		else if(strstr(input, "SERVICE DOWNTIME ALERT:")) {
606 
607 			if(display_downtime_alerts == FALSE)
608 				continue;
609 
610 			history_type = SERVICE_DOWNTIME_HISTORY;
611 
612 			/* get host and service names */
613 			temp_buffer = my_strtok(input2, "]");
614 			temp_buffer = my_strtok(NULL, ":");
615 			temp_buffer = my_strtok(NULL, ";");
616 			if(temp_buffer)
617 				entry_host_name = strdup(temp_buffer + 1);
618 			else
619 				entry_host_name = NULL;
620 			temp_buffer = my_strtok(NULL, ";");
621 			if(temp_buffer)
622 				entry_service_desc = strdup(temp_buffer);
623 			else
624 				entry_service_desc = NULL;
625 
626 			strncpy(image, SCHEDULED_DOWNTIME_ICON, sizeof(image));
627 
628 			if(strstr(input, ";STARTED;"))
629 				strncpy(image_alt, "Service entered a period of scheduled downtime", sizeof(image_alt));
630 			else if(strstr(input, ";STOPPED;"))
631 				strncpy(image_alt, "Service exited from a period of scheduled downtime", sizeof(image_alt));
632 			else if(strstr(input, ";CANCELLED;"))
633 				strncpy(image_alt, "Service scheduled downtime has been cancelled", sizeof(image_alt));
634 			}
635 
636 		/* host state alerts */
637 		else if(strstr(input, "HOST ALERT:")) {
638 
639 			history_type = HOST_HISTORY;
640 
641 			/* get host name */
642 			temp_buffer = my_strtok(input2, "]");
643 			temp_buffer = my_strtok(NULL, ":");
644 			temp_buffer = my_strtok(NULL, ";");
645 			if(temp_buffer)
646 				entry_host_name = strdup(temp_buffer + 1);
647 			else
648 				entry_host_name = NULL;
649 
650 			if(strstr(input, ";DOWN;")) {
651 				strncpy(image, HOST_DOWN_ICON, sizeof(image));
652 				strncpy(image_alt, HOST_DOWN_ICON_ALT, sizeof(image_alt));
653 				history_detail_type = HISTORY_HOST_DOWN;
654 				}
655 			else if(strstr(input, ";UNREACHABLE;")) {
656 				strncpy(image, HOST_UNREACHABLE_ICON, sizeof(image));
657 				strncpy(image_alt, HOST_UNREACHABLE_ICON_ALT, sizeof(image_alt));
658 				history_detail_type = HISTORY_HOST_UNREACHABLE;
659 				}
660 			else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;")) {
661 				strncpy(image, HOST_UP_ICON, sizeof(image));
662 				strncpy(image_alt, HOST_UP_ICON_ALT, sizeof(image_alt));
663 				history_detail_type = HISTORY_HOST_RECOVERY;
664 				}
665 			}
666 
667 		/* host flapping alerts */
668 		else if(strstr(input, "HOST FLAPPING ALERT:")) {
669 
670 			if(display_flapping_alerts == FALSE)
671 				continue;
672 
673 			history_type = HOST_FLAPPING_HISTORY;
674 
675 			/* get host name */
676 			temp_buffer = my_strtok(input2, "]");
677 			temp_buffer = my_strtok(NULL, ":");
678 			temp_buffer = my_strtok(NULL, ";");
679 			if(temp_buffer)
680 				entry_host_name = strdup(temp_buffer + 1);
681 			else
682 				entry_host_name = NULL;
683 
684 			strncpy(image, FLAPPING_ICON, sizeof(image));
685 
686 			if(strstr(input, ";STARTED;"))
687 				strncpy(image_alt, "Host started flapping", sizeof(image_alt));
688 			else if(strstr(input, ";STOPPED;"))
689 				strncpy(image_alt, "Host stopped flapping", sizeof(image_alt));
690 			else if(strstr(input, ";DISABLED;"))
691 				strncpy(image_alt, "Host flap detection disabled", sizeof(image_alt));
692 			}
693 
694 		/* host downtime alerts */
695 		else if(strstr(input, "HOST DOWNTIME ALERT:")) {
696 
697 			if(display_downtime_alerts == FALSE)
698 				continue;
699 
700 			history_type = HOST_DOWNTIME_HISTORY;
701 
702 			/* get host name */
703 			temp_buffer = my_strtok(input2, "]");
704 			temp_buffer = my_strtok(NULL, ":");
705 			temp_buffer = my_strtok(NULL, ";");
706 			if(temp_buffer)
707 				entry_host_name = strdup(temp_buffer + 1);
708 			else
709 				entry_host_name = NULL;
710 
711 			strncpy(image, SCHEDULED_DOWNTIME_ICON, sizeof(image));
712 
713 			if(strstr(input, ";STARTED;"))
714 				strncpy(image_alt, "Host entered a period of scheduled downtime", sizeof(image_alt));
715 			else if(strstr(input, ";STOPPED;"))
716 				strncpy(image_alt, "Host exited from a period of scheduled downtime", sizeof(image_alt));
717 			else if(strstr(input, ";CANCELLED;"))
718 				strncpy(image_alt, "Host scheduled downtime has been cancelled", sizeof(image_alt));
719 			}
720 
721 		else if(display_system_messages == FALSE)
722 			continue;
723 
724 		/* program start */
725 		else if(strstr(input, " starting...")) {
726 			strncpy(image, START_ICON, sizeof(image));
727 			strncpy(image_alt, START_ICON_ALT, sizeof(image_alt));
728 			system_message = TRUE;
729 			}
730 
731 		/* normal program termination */
732 		else if(strstr(input, " shutting down...")) {
733 			strncpy(image, STOP_ICON, sizeof(image));
734 			strncpy(image_alt, STOP_ICON_ALT, sizeof(image_alt));
735 			system_message = TRUE;
736 			}
737 
738 		/* abnormal program termination */
739 		else if(strstr(input, "Bailing out")) {
740 			strncpy(image, STOP_ICON, sizeof(image));
741 			strncpy(image_alt, STOP_ICON_ALT, sizeof(image_alt));
742 			system_message = TRUE;
743 			}
744 
745 		/* program restart */
746 		else if(strstr(input, " restarting...")) {
747 			strncpy(image, RESTART_ICON, sizeof(image));
748 			strncpy(image_alt, RESTART_ICON_ALT, sizeof(image_alt));
749 			system_message = TRUE;
750 			}
751 
752 		image[sizeof(image) - 1] = '\x0';
753 		image_alt[sizeof(image_alt) - 1] = '\x0';
754 
755 		/* get the timestamp */
756 		temp_buffer = strtok(input, "]");
757 		t = (temp_buffer == NULL) ? 0L : strtoul(temp_buffer + 1, NULL, 10);
758 
759 		time_ptr = localtime(&t);
760 		strftime(current_message_date, sizeof(current_message_date), "%B %d, %Y %H:00\n", time_ptr);
761 		current_message_date[sizeof(current_message_date) - 1] = '\x0';
762 
763 		get_time_string(&t, date_time, sizeof(date_time), SHORT_DATE_TIME);
764 		strip(date_time);
765 
766 		temp_buffer = strtok(NULL, "\n");
767 
768 		if(strcmp(image, "")) {
769 
770 			display_line = FALSE;
771 
772 			if(system_message == TRUE)
773 				display_line = TRUE;
774 
775 			else if(display_type == DISPLAY_HOSTS) {
776 
777 				if(history_type == HOST_HISTORY || history_type == SERVICE_HISTORY) {
778 					snprintf(match1, sizeof( match1),
779 							" HOST ALERT: %s;", host_name);
780 					snprintf(match2, sizeof( match2),
781 							" SERVICE ALERT: %s;", host_name);
782 					}
783 				else if(history_type == HOST_FLAPPING_HISTORY || history_type == SERVICE_FLAPPING_HISTORY) {
784 					snprintf(match1, sizeof( match1),
785 							" HOST FLAPPING ALERT: %s;", host_name);
786 					snprintf(match2, sizeof( match2),
787 							" SERVICE FLAPPING ALERT: %s;", host_name);
788 					}
789 				else if(history_type == HOST_DOWNTIME_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY) {
790 					snprintf(match1, sizeof( match1),
791 							" HOST DOWNTIME ALERT: %s;", host_name);
792 					snprintf(match2, sizeof( match2),
793 							" SERVICE DOWNTIME ALERT: %s;", host_name);
794 					}
795 
796 				if(show_all_hosts == TRUE)
797 					display_line = TRUE;
798 				else if(strstr(temp_buffer, match1))
799 					display_line = TRUE;
800 				else if(strstr(temp_buffer, match2))
801 					display_line = TRUE;
802 
803 				if(display_line == TRUE) {
804 					if(history_options == HISTORY_ALL)
805 						display_line = TRUE;
806 					else if(history_options == HISTORY_HOST_ALL && (history_type == HOST_HISTORY || history_type == HOST_FLAPPING_HISTORY || history_type == HOST_DOWNTIME_HISTORY))
807 						display_line = TRUE;
808 					else if(history_options == HISTORY_SERVICE_ALL && (history_type == SERVICE_HISTORY || history_type == SERVICE_FLAPPING_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY))
809 						display_line = TRUE;
810 					else if((history_type == HOST_HISTORY || history_type == SERVICE_HISTORY) && (history_detail_type & history_options))
811 						display_line = TRUE;
812 					else
813 						display_line = FALSE;
814 					}
815 
816 				/* check alert state types */
817 				if(display_line == TRUE && (history_type == HOST_HISTORY || history_type == SERVICE_HISTORY)) {
818 					if(state_options == STATE_ALL)
819 						display_line = TRUE;
820 					else if((state_options & STATE_SOFT) && strstr(temp_buffer, ";SOFT;"))
821 						display_line = TRUE;
822 					else if((state_options & STATE_HARD) && strstr(temp_buffer, ";HARD;"))
823 						display_line = TRUE;
824 					else
825 						display_line = FALSE;
826 					}
827 				}
828 
829 			else if(display_type == DISPLAY_SERVICES) {
830 
831 				if(history_type == SERVICE_HISTORY)
832 					snprintf(match1, sizeof( match1), " SERVICE ALERT: %s;%s;", host_name, svc_description);
833 				else if(history_type == SERVICE_FLAPPING_HISTORY)
834 					snprintf(match1, sizeof( match1), " SERVICE FLAPPING ALERT: %s;%s;", host_name, svc_description);
835 				else if(history_type == SERVICE_DOWNTIME_HISTORY)
836 					snprintf(match1, sizeof( match1), " SERVICE DOWNTIME ALERT: %s;%s;", host_name, svc_description);
837 
838 				if(strstr(temp_buffer, match1) && (history_type == SERVICE_HISTORY || history_type == SERVICE_FLAPPING_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY))
839 					display_line = TRUE;
840 
841 				if(display_line == TRUE) {
842 					if(history_options == HISTORY_ALL || history_options == HISTORY_SERVICE_ALL)
843 						display_line = TRUE;
844 					else if(history_options & history_detail_type)
845 						display_line = TRUE;
846 					else
847 						display_line = FALSE;
848 					}
849 
850 				/* check alert state type */
851 				if(display_line == TRUE && history_type == SERVICE_HISTORY) {
852 
853 					if(state_options == STATE_ALL)
854 						display_line = TRUE;
855 					else if((state_options & STATE_SOFT) && strstr(temp_buffer, ";SOFT;"))
856 						display_line = TRUE;
857 					else if((state_options & STATE_HARD) && strstr(temp_buffer, ";HARD;"))
858 						display_line = TRUE;
859 					else
860 						display_line = FALSE;
861 					}
862 				}
863 
864 
865 			/* make sure user is authorized to view this host or service information */
866 			if(system_message == FALSE) {
867 
868 				if(history_type == HOST_HISTORY || history_type == HOST_FLAPPING_HISTORY || history_type == HOST_DOWNTIME_HISTORY) {
869 					temp_host = find_host(entry_host_name);
870 					if(is_authorized_for_host(temp_host, &current_authdata) == FALSE)
871 						display_line = FALSE;
872 
873 					}
874 				else {
875 					temp_service = find_service(entry_host_name, entry_service_desc);
876 					if(is_authorized_for_service(temp_service, &current_authdata) == FALSE)
877 						display_line = FALSE;
878 					}
879 				}
880 
881 			/* display the entry if we should... */
882 			if(display_line == TRUE) {
883 
884 				if(strcmp(last_message_date, current_message_date) != 0 && display_timebreaks == TRUE) {
885 					printf("</DIV><BR CLEAR='all' />\n");
886 					printf("<DIV CLASS='dateTimeBreak'>\n");
887 					printf("<table border=0 width=95%%><tr>");
888 					printf("<td width=40%%><hr width=100%%></td>");
889 					printf("<td align=center CLASS='dateTimeBreak'>%s</td>", current_message_date);
890 					printf("<td width=40%%><hr width=100%%></td>");
891 					printf("</tr></table>\n");
892 					printf("</DIV>\n");
893 					printf("<BR CLEAR='all' /><DIV CLASS='logEntries'>\n");
894 					strncpy(last_message_date, current_message_date, sizeof(last_message_date));
895 					last_message_date[sizeof(last_message_date) - 1] = '\x0';
896 					}
897 
898 				if(display_frills == TRUE)
899 					printf("<img align='left' src='%s%s' alt='%s' title='%s' />", url_images_path, image, image_alt, image_alt);
900 				printf("[%s] %s", date_time, html_encode(temp_buffer, FALSE));
901 				if(enable_splunk_integration == TRUE) {
902 					printf("&nbsp;&nbsp;&nbsp;");
903 					display_splunk_generic_url(temp_buffer, 2);
904 					}
905 				printf("<br clear='all' />\n");
906 
907 				found_line = TRUE;
908 				}
909 			}
910 
911 		/* free memory */
912 		free(entry_host_name);
913 		entry_host_name = NULL;
914 		free(entry_service_desc);
915 		entry_service_desc = NULL;
916 		}
917 
918 	printf("</DIV></P>\n");
919 
920 	if(found_line == FALSE) {
921 		printf("<HR>\n");
922 		printf("<P><DIV CLASS='warningMessage'>No history information was found ");
923 		if(display_type == DISPLAY_HOSTS)
924 			printf("%s", (show_all_hosts == TRUE) ? "" : "for this host ");
925 		else
926 			printf("for this service ");
927 		printf("in %s log file</DIV></P>", (log_archive == 0) ? "the current" : "this archived");
928 		}
929 
930 	printf("<HR>\n");
931 
932 	my_free(input);
933 	my_free(input2);
934 
935 	if(use_lifo == TRUE)
936 		free_lifo_memory();
937 	else
938 		mmap_fclose(thefile);
939 
940 	return;
941 	}
942