1 /**************************************************************************
2  *
3  * AVAIL.C -  Nagios Availability CGI
4  *
5  * Copyright (c) 2000-2010 Ethan Galstad (egalstad@nagios.org)
6  * Last Modified: 08-05-2010
7  *
8  * License:
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *************************************************************************/
23 
24 #include "../include/config.h"
25 #include "../include/common.h"
26 #include "../include/objects.h"
27 #include "../include/comments.h"
28 #include "../include/statusdata.h"
29 
30 #include "../include/cgiutils.h"
31 #include "../include/cgiauth.h"
32 #include "../include/getcgi.h"
33 
34 
35 extern char main_config_file[MAX_FILENAME_LENGTH];
36 extern char url_html_path[MAX_FILENAME_LENGTH];
37 extern char url_images_path[MAX_FILENAME_LENGTH];
38 extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
39 
40 extern host      *host_list;
41 extern hostgroup *hostgroup_list;
42 extern servicegroup *servicegroup_list;
43 extern service   *service_list;
44 extern timeperiod *timeperiod_list;
45 
46 extern int       log_rotation_method;
47 
48 #ifndef max
49 #define max(a,b)  (((a) > (b)) ? (a) : (b))
50 #endif
51 #ifndef min
52 #define min(a,b)  (((a) < (b)) ? (a) : (b))
53 #endif
54 
55 
56 
57 /* output types */
58 #define HTML_OUTPUT             0
59 #define CSV_OUTPUT              1
60 
61 
62 /* archived state types */
63 #define AS_CURRENT_STATE        -1   /* special case for initial assumed state */
64 #define AS_NO_DATA		0
65 #define AS_PROGRAM_END		1
66 #define AS_PROGRAM_START	2
67 #define AS_HOST_UP		3
68 #define AS_HOST_DOWN		4
69 #define AS_HOST_UNREACHABLE	5
70 #define AS_SVC_OK		6
71 #define AS_SVC_UNKNOWN		7
72 #define AS_SVC_WARNING		8
73 #define AS_SVC_CRITICAL		9
74 
75 #define AS_SVC_DOWNTIME_START   10
76 #define AS_SVC_DOWNTIME_END     11
77 #define AS_HOST_DOWNTIME_START  12
78 #define AS_HOST_DOWNTIME_END    13
79 
80 #define AS_SOFT_STATE           1
81 #define AS_HARD_STATE           2
82 
83 
84 /* display types */
85 #define DISPLAY_NO_AVAIL        0
86 #define DISPLAY_HOSTGROUP_AVAIL 1
87 #define DISPLAY_HOST_AVAIL      2
88 #define DISPLAY_SERVICE_AVAIL   3
89 #define DISPLAY_SERVICEGROUP_AVAIL 4
90 
91 /* subject types */
92 #define HOST_SUBJECT            0
93 #define SERVICE_SUBJECT         1
94 
95 
96 /* standard report times */
97 #define TIMEPERIOD_CUSTOM	0
98 #define TIMEPERIOD_TODAY	1
99 #define TIMEPERIOD_YESTERDAY	2
100 #define TIMEPERIOD_THISWEEK	3
101 #define TIMEPERIOD_LASTWEEK	4
102 #define TIMEPERIOD_THISMONTH	5
103 #define TIMEPERIOD_LASTMONTH	6
104 #define TIMEPERIOD_THISQUARTER	7
105 #define TIMEPERIOD_LASTQUARTER	8
106 #define TIMEPERIOD_THISYEAR	9
107 #define TIMEPERIOD_LASTYEAR	10
108 #define TIMEPERIOD_LAST24HOURS	11
109 #define TIMEPERIOD_LAST7DAYS	12
110 #define TIMEPERIOD_LAST31DAYS	13
111 
112 #define MIN_TIMESTAMP_SPACING	10
113 
114 #define MAX_ARCHIVE_SPREAD	65
115 #define MAX_ARCHIVE		65
116 #define MAX_ARCHIVE_BACKTRACKS	60
117 
118 authdata current_authdata;
119 
120 typedef struct archived_state_struct {
121 	time_t  time_stamp;
122 	int     entry_type;
123 	int     state_type;
124 	char    *state_info;
125 	int     processed_state;
126 	struct archived_state_struct *misc_ptr;
127 	struct archived_state_struct *next;
128 	} archived_state;
129 
130 typedef struct avail_subject_struct {
131 	int type;
132 	char *host_name;
133 	char *service_description;
134 	archived_state *as_list;        /* archived state list */
135 	archived_state *as_list_tail;
136 	archived_state *sd_list;        /* scheduled downtime list */
137 	int last_known_state;
138 	time_t earliest_time;
139 	time_t latest_time;
140 	int earliest_state;
141 	int latest_state;
142 
143 	unsigned long time_up;
144 	unsigned long time_down;
145 	unsigned long time_unreachable;
146 	unsigned long time_ok;
147 	unsigned long time_warning;
148 	unsigned long time_unknown;
149 	unsigned long time_critical;
150 
151 	unsigned long scheduled_time_up;
152 	unsigned long scheduled_time_down;
153 	unsigned long scheduled_time_unreachable;
154 	unsigned long scheduled_time_ok;
155 	unsigned long scheduled_time_warning;
156 	unsigned long scheduled_time_unknown;
157 	unsigned long scheduled_time_critical;
158 	unsigned long scheduled_time_indeterminate;
159 
160 	unsigned long time_indeterminate_nodata;
161 	unsigned long time_indeterminate_notrunning;
162 
163 	struct avail_subject_struct *next;
164 	} avail_subject;
165 
166 avail_subject *subject_list = NULL;
167 
168 time_t t1;
169 time_t t2;
170 
171 int display_type = DISPLAY_NO_AVAIL;
172 int timeperiod_type = TIMEPERIOD_LAST24HOURS;
173 int show_log_entries = FALSE;
174 int full_log_entries = FALSE;
175 int show_scheduled_downtime = TRUE;
176 
177 int start_second = 0;
178 int start_minute = 0;
179 int start_hour = 0;
180 int start_day = 1;
181 int start_month = 1;
182 int start_year = 2000;
183 int end_second = 0;
184 int end_minute = 0;
185 int end_hour = 24;
186 int end_day = 1;
187 int end_month = 1;
188 int end_year = 2000;
189 
190 int get_date_parts = FALSE;
191 int select_hostgroups = FALSE;
192 int select_hosts = FALSE;
193 int select_servicegroups = FALSE;
194 int select_services = FALSE;
195 int select_output_format = FALSE;
196 
197 int compute_time_from_parts = FALSE;
198 
199 int show_all_hostgroups = FALSE;
200 int show_all_hosts = FALSE;
201 int show_all_servicegroups = FALSE;
202 int show_all_services = FALSE;
203 
204 int assume_initial_states = TRUE;
205 int assume_state_retention = TRUE;
206 int assume_states_during_notrunning = TRUE;
207 int initial_assumed_host_state = AS_NO_DATA;
208 int initial_assumed_service_state = AS_NO_DATA;
209 int include_soft_states = FALSE;
210 
211 char *hostgroup_name = "";
212 char *host_name = "";
213 char *servicegroup_name = "";
214 char *svc_description = "";
215 
216 void create_subject_list(void);
217 void add_subject(int, char *, char *);
218 avail_subject *find_subject(int, char *, char *);
219 void compute_availability(void);
220 void compute_subject_availability(avail_subject *, time_t);
221 void compute_subject_availability_times(int, int, time_t, time_t, time_t, avail_subject *, archived_state *);
222 void compute_subject_downtime(avail_subject *, time_t);
223 void compute_subject_downtime_times(time_t, time_t, avail_subject *, archived_state *);
224 void compute_subject_downtime_part_times(time_t, time_t, int, avail_subject *);
225 void display_hostgroup_availability(void);
226 void display_specific_hostgroup_availability(hostgroup *);
227 void display_servicegroup_availability(void);
228 void display_specific_servicegroup_availability(servicegroup *);
229 void display_host_availability(void);
230 void display_service_availability(void);
231 void write_log_entries(avail_subject *);
232 
233 void get_running_average(double *, double, int);
234 
235 void host_report_url(char *, char *);
236 void service_report_url(char *, char *, char *);
237 void compute_report_times(void);
238 
239 int convert_host_state_to_archived_state(int);
240 int convert_service_state_to_archived_state(int);
241 void add_global_archived_state(int, int, time_t, char *);
242 void add_archived_state(int, int, time_t, char *, avail_subject *);
243 void add_scheduled_downtime(int, time_t, avail_subject *);
244 void free_availability_data(void);
245 void free_archived_state_list(archived_state *);
246 void read_archived_state_data(void);
247 void scan_log_file_for_archived_state_data(char *);
248 void convert_timeperiod_to_times(int);
249 unsigned long calculate_total_time(time_t, time_t);
250 
251 void document_header(int);
252 void document_footer(void);
253 int process_cgivars(void);
254 
255 
256 
257 int backtrack_archives = 2;
258 int earliest_archive = 0;
259 
260 int embedded = FALSE;
261 int display_header = TRUE;
262 
263 timeperiod *current_timeperiod = NULL;
264 
265 int output_format = HTML_OUTPUT;
266 
267 
268 
main(int argc,char ** argv)269 int main(int argc, char **argv) {
270 	int result = OK;
271 	char temp_buffer[MAX_INPUT_BUFFER];
272 	char start_timestring[MAX_DATETIME_LENGTH];
273 	char end_timestring[MAX_DATETIME_LENGTH];
274 	host *temp_host;
275 	service *temp_service;
276 	int is_authorized = TRUE;
277 	time_t report_start_time;
278 	time_t report_end_time;
279 	int days, hours, minutes, seconds;
280 	hostgroup *temp_hostgroup;
281 	servicegroup *temp_servicegroup;
282 	timeperiod *temp_timeperiod;
283 	time_t t3;
284 	time_t current_time;
285 	struct tm *t;
286 	char *firsthostpointer;
287 
288 	/* reset internal CGI variables */
289 	reset_cgi_vars();
290 
291 	/* read the CGI configuration file */
292 	result = read_cgi_config_file(get_cgi_config_location());
293 	if(result == ERROR) {
294 		document_header(FALSE);
295 		cgi_config_file_error(get_cgi_config_location());
296 		document_footer();
297 		return ERROR;
298 		}
299 
300 	/* read the main configuration file */
301 	result = read_main_config_file(main_config_file);
302 	if(result == ERROR) {
303 		document_header(FALSE);
304 		main_config_file_error(main_config_file);
305 		document_footer();
306 		return ERROR;
307 		}
308 
309 	/* read all object configuration data */
310 	result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
311 	if(result == ERROR) {
312 		document_header(FALSE);
313 		object_data_error();
314 		document_footer();
315 		return ERROR;
316 		}
317 
318 	/* read all status data */
319 	result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA);
320 	if(result == ERROR) {
321 		document_header(FALSE);
322 		status_data_error();
323 		document_footer();
324 		return ERROR;
325 		}
326 
327 	/* initialize time period to last 24 hours */
328 	time(&current_time);
329 	t2 = current_time;
330 	t1 = (time_t)(current_time - (60 * 60 * 24));
331 
332 	/* default number of backtracked archives */
333 	switch(log_rotation_method) {
334 		case LOG_ROTATION_MONTHLY:
335 			backtrack_archives = 1;
336 			break;
337 		case LOG_ROTATION_WEEKLY:
338 			backtrack_archives = 2;
339 			break;
340 		case LOG_ROTATION_DAILY:
341 			backtrack_archives = 4;
342 			break;
343 		case LOG_ROTATION_HOURLY:
344 			backtrack_archives = 8;
345 			break;
346 		default:
347 			backtrack_archives = 2;
348 			break;
349 		}
350 
351 	/* get the arguments passed in the URL */
352 	process_cgivars();
353 
354 	document_header(TRUE);
355 
356 	/* get authentication information */
357 	get_authentication_information(&current_authdata);
358 
359 
360 	if(compute_time_from_parts == TRUE)
361 		compute_report_times();
362 
363 	/* make sure times are sane, otherwise swap them */
364 	if(t2 < t1) {
365 		t3 = t2;
366 		t2 = t1;
367 		t1 = t3;
368 		}
369 
370 	/* don't let user create reports in the future */
371 	if(t2 > current_time) {
372 		t2 = current_time;
373 		if(t1 > t2)
374 			t1 = t2 - (60 * 60 * 24);
375 		}
376 
377 	if(display_header == TRUE) {
378 
379 		/* begin top table */
380 		printf("<table border=0 width=100%% cellspacing=0 cellpadding=0>\n");
381 		printf("<tr>\n");
382 
383 		/* left column of the first row */
384 		printf("<td align=left valign=top width=33%%>\n");
385 
386 		switch(display_type) {
387 			case DISPLAY_HOST_AVAIL:
388 				snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host Availability Report");
389 				break;
390 			case DISPLAY_SERVICE_AVAIL:
391 				snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service Availability Report");
392 				break;
393 			case DISPLAY_HOSTGROUP_AVAIL:
394 				snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Hostgroup Availability Report");
395 				break;
396 			case DISPLAY_SERVICEGROUP_AVAIL:
397 				snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Servicegroup Availability Report");
398 				break;
399 			default:
400 				snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Availability Report");
401 				break;
402 			}
403 		temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
404 		display_info_table(temp_buffer, FALSE, &current_authdata);
405 
406 		if(((display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE) || (display_type == DISPLAY_SERVICE_AVAIL && show_all_services == FALSE)) && get_date_parts == FALSE) {
407 
408 			printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
409 			printf("<TR><TD CLASS='linkBox'>\n");
410 
411 			if(display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE) {
412 				host_report_url("all", "View Availability Report For All Hosts");
413 				printf("<BR>\n");
414 #ifdef USE_TRENDS
415 				printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s&assumeinitialstates=%s&includesoftstates=%s&assumestatesduringnotrunning=%s&initialassumedhoststate=%d&backtrack=%d'>View Trends For This Host</a><BR>\n", TRENDS_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives);
416 #endif
417 #ifdef USE_HISTOGRAM
418 				printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Alert Histogram For This Host</a><BR>\n", HISTOGRAM_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
419 #endif
420 				printf("<a href='%s?host=%s'>View Status Detail For This Host</a><BR>\n", STATUS_CGI, url_encode(host_name));
421 				printf("<a href='%s?host=%s'>View Alert History For This Host</a><BR>\n", HISTORY_CGI, url_encode(host_name));
422 				printf("<a href='%s?host=%s'>View Notifications For This Host</a><BR>\n", NOTIFICATIONS_CGI, url_encode(host_name));
423 				}
424 			else if(display_type == DISPLAY_SERVICE_AVAIL && show_all_services == FALSE) {
425 				host_report_url(host_name, "View Availability Report For This Host");
426 				printf("<BR>\n");
427 				service_report_url("null", "all", "View Availability Report For All Services");
428 				printf("<BR>\n");
429 #ifdef USE_TRENDS
430 				printf("<a href='%s?host=%s", TRENDS_CGI, url_encode(host_name));
431 				printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s&includesoftstates=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d'>View Trends For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
432 #endif
433 #ifdef USE_HISTOGRAM
434 				printf("<a href='%s?host=%s", HISTOGRAM_CGI, url_encode(host_name));
435 				printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Alert Histogram For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
436 #endif
437 				printf("<A HREF='%s?host=%s&", HISTORY_CGI, url_encode(host_name));
438 				printf("service=%s'>View Alert History For This Service</A><BR>\n", url_encode(svc_description));
439 				printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
440 				printf("service=%s'>View Notifications For This Service</A><BR>\n", url_encode(svc_description));
441 				}
442 
443 			printf("</TD></TR>\n");
444 			printf("</TABLE>\n");
445 			}
446 
447 		printf("</td>\n");
448 
449 		/* center column of top row */
450 		printf("<td align=center valign=top width=33%%>\n");
451 
452 		if(display_type != DISPLAY_NO_AVAIL && get_date_parts == FALSE) {
453 
454 			printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
455 			if(display_type == DISPLAY_HOST_AVAIL) {
456 				if(show_all_hosts == TRUE)
457 					printf("All Hosts");
458 				else
459 					printf("Host '%s'", host_name);
460 				}
461 			else if(display_type == DISPLAY_SERVICE_AVAIL) {
462 				if(show_all_services == TRUE)
463 					printf("All Services");
464 				else
465 					printf("Service '%s' On Host '%s'", svc_description, host_name);
466 				}
467 			else if(display_type == DISPLAY_HOSTGROUP_AVAIL) {
468 				if(show_all_hostgroups == TRUE)
469 					printf("All Hostgroups");
470 				else
471 					printf("Hostgroup '%s'", hostgroup_name);
472 				}
473 			else if(display_type == DISPLAY_SERVICEGROUP_AVAIL) {
474 				if(show_all_servicegroups == TRUE)
475 					printf("All Servicegroups");
476 				else
477 					printf("Servicegroup '%s'", servicegroup_name);
478 				}
479 			printf("</DIV>\n");
480 
481 			printf("<BR>\n");
482 
483 			printf("<IMG SRC='%s%s' BORDER=0 ALT='Availability Report' TITLE='Availability Report'>\n", url_images_path, TRENDS_ICON);
484 
485 			printf("<BR CLEAR=ALL>\n");
486 
487 			get_time_string(&t1, start_timestring, sizeof(start_timestring) - 1, SHORT_DATE_TIME);
488 			get_time_string(&t2, end_timestring, sizeof(end_timestring) - 1, SHORT_DATE_TIME);
489 			printf("<div align=center class='reportRange'>%s to %s</div>\n", start_timestring, end_timestring);
490 
491 			get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds);
492 			printf("<div align=center class='reportDuration'>Duration: %dd %dh %dm %ds</div>\n", days, hours, minutes, seconds);
493 			}
494 
495 		printf("</td>\n");
496 
497 		/* right hand column of top row */
498 		printf("<td align=right valign=bottom width=33%%>\n");
499 
500 		printf("<form method=\"GET\" action=\"%s\">\n", AVAIL_CGI);
501 		printf("<table border=0 CLASS='optBox'>\n");
502 
503 		if(display_type != DISPLAY_NO_AVAIL && get_date_parts == FALSE) {
504 
505 			printf("<tr><td valign=top align=left class='optBoxItem'>First assumed %s state:</td><td valign=top align=left class='optBoxItem'>%s</td></tr>\n", (display_type == DISPLAY_SERVICE_AVAIL) ? "service" : "host", (display_type == DISPLAY_HOST_AVAIL || display_type == DISPLAY_HOSTGROUP_AVAIL || display_type == DISPLAY_SERVICEGROUP_AVAIL) ? "First assumed service state" : "");
506 			printf("<tr>\n");
507 			printf("<td valign=top align=left class='optBoxItem'>\n");
508 
509 			printf("<input type='hidden' name='t1' value='%lu'>\n", (unsigned long)t1);
510 			printf("<input type='hidden' name='t2' value='%lu'>\n", (unsigned long)t2);
511 			if(show_log_entries == TRUE)
512 				printf("<input type='hidden' name='show_log_entries' value=''>\n");
513 			if(full_log_entries == TRUE)
514 				printf("<input type='hidden' name='full_log_entries' value=''>\n");
515 			if(display_type == DISPLAY_HOSTGROUP_AVAIL)
516 				printf("<input type='hidden' name='hostgroup' value='%s'>\n", escape_string(hostgroup_name));
517 			if(display_type == DISPLAY_HOST_AVAIL || display_type == DISPLAY_SERVICE_AVAIL)
518 				printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
519 			if(display_type == DISPLAY_SERVICE_AVAIL)
520 				printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
521 			if(display_type == DISPLAY_SERVICEGROUP_AVAIL)
522 				printf("<input type='hidden' name='servicegroup' value='%s'>\n", escape_string(servicegroup_name));
523 
524 			printf("<input type='hidden' name='assumeinitialstates' value='%s'>\n", (assume_initial_states == TRUE) ? "yes" : "no");
525 			printf("<input type='hidden' name='assumestateretention' value='%s'>\n", (assume_state_retention == TRUE) ? "yes" : "no");
526 			printf("<input type='hidden' name='assumestatesduringnotrunning' value='%s'>\n", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
527 			printf("<input type='hidden' name='includesoftstates' value='%s'>\n", (include_soft_states == TRUE) ? "yes" : "no");
528 
529 			if(display_type == DISPLAY_HOST_AVAIL || display_type == DISPLAY_HOSTGROUP_AVAIL || display_type == DISPLAY_SERVICEGROUP_AVAIL) {
530 				printf("<select name='initialassumedhoststate'>\n");
531 				printf("<option value=%d %s>Unspecified\n", AS_NO_DATA, (initial_assumed_host_state == AS_NO_DATA) ? "SELECTED" : "");
532 				printf("<option value=%d %s>Current State\n", AS_CURRENT_STATE, (initial_assumed_host_state == AS_CURRENT_STATE) ? "SELECTED" : "");
533 				printf("<option value=%d %s>Host Up\n", AS_HOST_UP, (initial_assumed_host_state == AS_HOST_UP) ? "SELECTED" : "");
534 				printf("<option value=%d %s>Host Down\n", AS_HOST_DOWN, (initial_assumed_host_state == AS_HOST_DOWN) ? "SELECTED" : "");
535 				printf("<option value=%d %s>Host Unreachable\n", AS_HOST_UNREACHABLE, (initial_assumed_host_state == AS_HOST_UNREACHABLE) ? "SELECTED" : "");
536 				printf("</select>\n");
537 				}
538 			else {
539 				printf("<input type='hidden' name='initialassumedhoststate' value='%d'>", initial_assumed_host_state);
540 				printf("<select name='initialassumedservicestate'>\n");
541 				printf("<option value=%d %s>Unspecified\n", AS_NO_DATA, (initial_assumed_service_state == AS_NO_DATA) ? "SELECTED" : "");
542 				printf("<option value=%d %s>Current State\n", AS_CURRENT_STATE, (initial_assumed_service_state == AS_CURRENT_STATE) ? "SELECTED" : "");
543 				printf("<option value=%d %s>Service Ok\n", AS_SVC_OK, (initial_assumed_service_state == AS_SVC_OK) ? "SELECTED" : "");
544 				printf("<option value=%d %s>Service Warning\n", AS_SVC_WARNING, (initial_assumed_service_state == AS_SVC_WARNING) ? "SELECTED" : "");
545 				printf("<option value=%d %s>Service Unknown\n", AS_SVC_UNKNOWN, (initial_assumed_service_state == AS_SVC_UNKNOWN) ? "SELECTED" : "");
546 				printf("<option value=%d %s>Service Critical\n", AS_SVC_CRITICAL, (initial_assumed_service_state == AS_SVC_CRITICAL) ? "SELECTED" : "");
547 				printf("</select>\n");
548 				}
549 			printf("</td>\n");
550 			printf("<td CLASS='optBoxItem'>\n");
551 			if(display_type == DISPLAY_HOST_AVAIL || display_type == DISPLAY_HOSTGROUP_AVAIL || display_type == DISPLAY_SERVICEGROUP_AVAIL) {
552 				printf("<select name='initialassumedservicestate'>\n");
553 				printf("<option value=%d %s>Unspecified\n", AS_NO_DATA, (initial_assumed_service_state == AS_NO_DATA) ? "SELECTED" : "");
554 				printf("<option value=%d %s>Current State\n", AS_CURRENT_STATE, (initial_assumed_service_state == AS_CURRENT_STATE) ? "SELECTED" : "");
555 				printf("<option value=%d %s>Service Ok\n", AS_SVC_OK, (initial_assumed_service_state == AS_SVC_OK) ? "SELECTED" : "");
556 				printf("<option value=%d %s>Service Warning\n", AS_SVC_WARNING, (initial_assumed_service_state == AS_SVC_WARNING) ? "SELECTED" : "");
557 				printf("<option value=%d %s>Service Unknown\n", AS_SVC_UNKNOWN, (initial_assumed_service_state == AS_SVC_UNKNOWN) ? "SELECTED" : "");
558 				printf("<option value=%d %s>Service Critical\n", AS_SVC_CRITICAL, (initial_assumed_service_state == AS_SVC_CRITICAL) ? "SELECTED" : "");
559 				printf("</select>\n");
560 				}
561 			printf("</td>\n");
562 			printf("</tr>\n");
563 
564 			printf("<tr><td valign=top align=left class='optBoxItem'>Report period:</td><td valign=top align=left class='optBoxItem'>Backtracked archives:</td></tr>\n");
565 			printf("<tr>\n");
566 			printf("<td valign=top align=left class='optBoxItem'>\n");
567 			printf("<select name='timeperiod'>\n");
568 			printf("<option SELECTED>[ Current time range ]\n");
569 			printf("<option value=today %s>Today\n", (timeperiod_type == TIMEPERIOD_TODAY) ? "SELECTED" : "");
570 			printf("<option value=last24hours %s>Last 24 Hours\n", (timeperiod_type == TIMEPERIOD_LAST24HOURS) ? "SELECTED" : "");
571 			printf("<option value=yesterday %s>Yesterday\n", (timeperiod_type == TIMEPERIOD_YESTERDAY) ? "SELECTED" : "");
572 			printf("<option value=thisweek %s>This Week\n", (timeperiod_type == TIMEPERIOD_THISWEEK) ? "SELECTED" : "");
573 			printf("<option value=last7days %s>Last 7 Days\n", (timeperiod_type == TIMEPERIOD_LAST7DAYS) ? "SELECTED" : "");
574 			printf("<option value=lastweek %s>Last Week\n", (timeperiod_type == TIMEPERIOD_LASTWEEK) ? "SELECTED" : "");
575 			printf("<option value=thismonth %s>This Month\n", (timeperiod_type == TIMEPERIOD_THISMONTH) ? "SELECTED" : "");
576 			printf("<option value=last31days %s>Last 31 Days\n", (timeperiod_type == TIMEPERIOD_LAST31DAYS) ? "SELECTED" : "");
577 			printf("<option value=lastmonth %s>Last Month\n", (timeperiod_type == TIMEPERIOD_LASTMONTH) ? "SELECTED" : "");
578 			printf("<option value=thisyear %s>This Year\n", (timeperiod_type == TIMEPERIOD_THISYEAR) ? "SELECTED" : "");
579 			printf("<option value=lastyear %s>Last Year\n", (timeperiod_type == TIMEPERIOD_LASTYEAR) ? "SELECTED" : "");
580 			printf("</select>\n");
581 			printf("</td>\n");
582 			printf("<td valign=top align=left CLASS='optBoxItem'>\n");
583 			printf("<input type='text' size='2' maxlength='2' name='backtrack' value='%d'>\n", backtrack_archives);
584 			printf("</td>\n");
585 			printf("</tr>\n");
586 
587 			printf("<tr><td valign=top align=left></td>\n");
588 			printf("<td valign=top align=left CLASS='optBoxItem'>\n");
589 			printf("<input type='submit' value='Update'>\n");
590 			printf("</td>\n");
591 			printf("</tr>\n");
592 			}
593 
594 		/* display context-sensitive help */
595 		printf("<tr><td></td><td align=right valign=bottom>\n");
596 		if(get_date_parts == TRUE)
597 			display_context_help(CONTEXTHELP_AVAIL_MENU5);
598 		else if(select_hostgroups == TRUE)
599 			display_context_help(CONTEXTHELP_AVAIL_MENU2);
600 		else if(select_hosts == TRUE)
601 			display_context_help(CONTEXTHELP_AVAIL_MENU3);
602 		else if(select_services == TRUE)
603 			display_context_help(CONTEXTHELP_AVAIL_MENU4);
604 		else if(display_type == DISPLAY_HOSTGROUP_AVAIL)
605 			display_context_help(CONTEXTHELP_AVAIL_HOSTGROUP);
606 		else if(display_type == DISPLAY_HOST_AVAIL)
607 			display_context_help(CONTEXTHELP_AVAIL_HOST);
608 		else if(display_type == DISPLAY_SERVICE_AVAIL)
609 			display_context_help(CONTEXTHELP_AVAIL_SERVICE);
610 		else if(display_type == DISPLAY_SERVICEGROUP_AVAIL)
611 			display_context_help(CONTEXTHELP_AVAIL_SERVICEGROUP);
612 		else
613 			display_context_help(CONTEXTHELP_AVAIL_MENU1);
614 		printf("</td></tr>\n");
615 
616 		printf("</table>\n");
617 		printf("</form>\n");
618 
619 		printf("</td>\n");
620 
621 		/* end of top table */
622 		printf("</tr>\n");
623 		printf("</table>\n");
624 		}
625 
626 
627 
628 
629 	/* step 3 - ask user for report date range */
630 	if(get_date_parts == TRUE) {
631 
632 		time(&current_time);
633 		t = localtime(&current_time);
634 
635 		start_day = 1;
636 		start_year = t->tm_year + 1900;
637 		end_day = t->tm_mday;
638 		end_year = t->tm_year + 1900;
639 
640 		printf("<P><DIV ALIGN=CENTER CLASS='dateSelectTitle'>Step 3: Select Report Options</DIV></p>\n");
641 
642 		printf("<P><DIV ALIGN=CENTER>\n");
643 
644 		printf("<form method=\"get\" action=\"%s\">\n", AVAIL_CGI);
645 		printf("<input type='hidden' name='show_log_entries' value=''>\n");
646 		if(display_type == DISPLAY_HOSTGROUP_AVAIL)
647 			printf("<input type='hidden' name='hostgroup' value='%s'>\n", escape_string(hostgroup_name));
648 		if(display_type == DISPLAY_HOST_AVAIL || display_type == DISPLAY_SERVICE_AVAIL)
649 			printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
650 		if(display_type == DISPLAY_SERVICE_AVAIL)
651 			printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
652 		if(display_type == DISPLAY_SERVICEGROUP_AVAIL)
653 			printf("<input type='hidden' name='servicegroup' value='%s'>\n", escape_string(servicegroup_name));
654 
655 		printf("<table border=0 cellpadding=5>\n");
656 
657 		printf("<tr>");
658 		printf("<td valign=top class='reportSelectSubTitle'>Report Period:</td>\n");
659 		printf("<td valign=top align=left class='optBoxItem'>\n");
660 		printf("<select name='timeperiod'>\n");
661 		printf("<option value=today>Today\n");
662 		printf("<option value=last24hours>Last 24 Hours\n");
663 		printf("<option value=yesterday>Yesterday\n");
664 		printf("<option value=thisweek>This Week\n");
665 		printf("<option value=last7days SELECTED>Last 7 Days\n");
666 		printf("<option value=lastweek>Last Week\n");
667 		printf("<option value=thismonth>This Month\n");
668 		printf("<option value=last31days>Last 31 Days\n");
669 		printf("<option value=lastmonth>Last Month\n");
670 		printf("<option value=thisyear>This Year\n");
671 		printf("<option value=lastyear>Last Year\n");
672 		printf("<option value=custom>* CUSTOM REPORT PERIOD *\n");
673 		printf("</select>\n");
674 		printf("</td>\n");
675 		printf("</tr>\n");
676 
677 		printf("<tr><td valign=top class='reportSelectSubTitle'>If Custom Report Period...</td></tr>\n");
678 
679 		printf("<tr>");
680 		printf("<td valign=top class='reportSelectSubTitle'>Start Date (Inclusive):</td>\n");
681 		printf("<td align=left valign=top class='reportSelectItem'>");
682 		printf("<select name='smon'>\n");
683 		printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
684 		printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
685 		printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
686 		printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
687 		printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
688 		printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
689 		printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
690 		printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
691 		printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
692 		printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
693 		printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
694 		printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
695 		printf("</select>\n ");
696 		printf("<input type='text' size='2' maxlength='2' name='sday' value='%d'> ", start_day);
697 		printf("<input type='text' size='4' maxlength='4' name='syear' value='%d'>", start_year);
698 		printf("<input type='hidden' name='shour' value='0'>\n");
699 		printf("<input type='hidden' name='smin' value='0'>\n");
700 		printf("<input type='hidden' name='ssec' value='0'>\n");
701 		printf("</td>\n");
702 		printf("</tr>\n");
703 
704 		printf("<tr>");
705 		printf("<td valign=top class='reportSelectSubTitle'>End Date (Inclusive):</td>\n");
706 		printf("<td align=left valign=top class='reportSelectItem'>");
707 		printf("<select name='emon'>\n");
708 		printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
709 		printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
710 		printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
711 		printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
712 		printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
713 		printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
714 		printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
715 		printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
716 		printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
717 		printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
718 		printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
719 		printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
720 		printf("</select>\n ");
721 		printf("<input type='text' size='2' maxlength='2' name='eday' value='%d'> ", end_day);
722 		printf("<input type='text' size='4' maxlength='4' name='eyear' value='%d'>", end_year);
723 		printf("<input type='hidden' name='ehour' value='24'>\n");
724 		printf("<input type='hidden' name='emin' value='0'>\n");
725 		printf("<input type='hidden' name='esec' value='0'>\n");
726 		printf("</td>\n");
727 		printf("</tr>\n");
728 
729 		printf("<tr><td colspan=2><br></td></tr>\n");
730 
731 		printf("<tr>");
732 		printf("<td valign=top class='reportSelectSubTitle'>Report time Period:</td>\n");
733 		printf("<td valign=top align=left class='optBoxItem'>\n");
734 		printf("<select name='rpttimeperiod'>\n");
735 		printf("<option value=\"\">None\n");
736 		/* check all the time periods... */
737 		for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next)
738 			printf("<option value=%s>%s\n", escape_string(temp_timeperiod->name), temp_timeperiod->name);
739 		printf("</select>\n");
740 		printf("</td>\n");
741 		printf("</tr>\n");
742 		printf("<tr><td colspan=2><br></td></tr>\n");
743 
744 		printf("<tr><td class='reportSelectSubTitle' align=right>Assume Initial States:</td>\n");
745 		printf("<td class='reportSelectItem'>\n");
746 		printf("<select name='assumeinitialstates'>\n");
747 		printf("<option value=yes>Yes\n");
748 		printf("<option value=no>No\n");
749 		printf("</select>\n");
750 		printf("</td></tr>\n");
751 
752 		printf("<tr><td class='reportSelectSubTitle' align=right>Assume State Retention:</td>\n");
753 		printf("<td class='reportSelectItem'>\n");
754 		printf("<select name='assumestateretention'>\n");
755 		printf("<option value=yes>Yes\n");
756 		printf("<option value=no>No\n");
757 		printf("</select>\n");
758 		printf("</td></tr>\n");
759 
760 		printf("<tr><td class='reportSelectSubTitle' align=right>Assume States During Program Downtime:</td>\n");
761 		printf("<td class='reportSelectItem'>\n");
762 		printf("<select name='assumestatesduringnotrunning'>\n");
763 		printf("<option value=yes>Yes\n");
764 		printf("<option value=no>No\n");
765 		printf("</select>\n");
766 		printf("</td></tr>\n");
767 
768 		printf("<tr><td class='reportSelectSubTitle' align=right>Include Soft States:</td>\n");
769 		printf("<td class='reportSelectItem'>\n");
770 		printf("<select name='includesoftstates'>\n");
771 		printf("<option value=yes>Yes\n");
772 		printf("<option value=no SELECTED>No\n");
773 		printf("</select>\n");
774 		printf("</td></tr>\n");
775 
776 		if(display_type != DISPLAY_SERVICE_AVAIL) {
777 			printf("<tr><td class='reportSelectSubTitle' align=right>First Assumed Host State:</td>\n");
778 			printf("<td class='reportSelectItem'>\n");
779 			printf("<select name='initialassumedhoststate'>\n");
780 			printf("<option value=%d>Unspecified\n", AS_NO_DATA);
781 			printf("<option value=%d>Current State\n", AS_CURRENT_STATE);
782 			printf("<option value=%d>Host Up\n", AS_HOST_UP);
783 			printf("<option value=%d>Host Down\n", AS_HOST_DOWN);
784 			printf("<option value=%d>Host Unreachable\n", AS_HOST_UNREACHABLE);
785 			printf("</select>\n");
786 			printf("</td></tr>\n");
787 			}
788 
789 		printf("<tr><td class='reportSelectSubTitle' align=right>First Assumed Service State:</td>\n");
790 		printf("<td class='reportSelectItem'>\n");
791 		printf("<select name='initialassumedservicestate'>\n");
792 		printf("<option value=%d>Unspecified\n", AS_NO_DATA);
793 		printf("<option value=%d>Current State\n", AS_CURRENT_STATE);
794 		printf("<option value=%d>Service Ok\n", AS_SVC_OK);
795 		printf("<option value=%d>Service Warning\n", AS_SVC_WARNING);
796 		printf("<option value=%d>Service Unknown\n", AS_SVC_UNKNOWN);
797 		printf("<option value=%d>Service Critical\n", AS_SVC_CRITICAL);
798 		printf("</select>\n");
799 		printf("</td></tr>\n");
800 
801 		printf("<tr><td class='reportSelectSubTitle' align=right>Backtracked Archives (To Scan For Initial States):</td>\n");
802 		printf("<td class='reportSelectItem'>\n");
803 		printf("<input type='text' name='backtrack' size='2' maxlength='2' value='%d'>\n", backtrack_archives);
804 		printf("</td></tr>\n");
805 
806 		if((display_type == DISPLAY_HOST_AVAIL && show_all_hosts == TRUE) || (display_type == DISPLAY_SERVICE_AVAIL && show_all_services == TRUE)) {
807 			printf("<tr>");
808 			printf("<td valign=top class='reportSelectSubTitle'>Output in CSV Format:</td>\n");
809 			printf("<td valign=top class='reportSelectItem'>");
810 			printf("<input type='checkbox' name='csvoutput' value=''>\n");
811 			printf("</td>\n");
812 			printf("</tr>\n");
813 			}
814 
815 		printf("<tr><td></td><td align=left class='dateSelectItem'><input type='submit' value='Create Availability Report!'></td></tr>\n");
816 
817 		printf("</table>\n");
818 
819 		printf("</form>\n");
820 		printf("</DIV></P>\n");
821 		}
822 
823 
824 	/* step 2 - the user wants to select a hostgroup */
825 	else if(select_hostgroups == TRUE) {
826 		printf("<p><div align=center class='reportSelectTitle'>Step 2: Select Hostgroup</div></p>\n");
827 
828 		printf("<p><div align=center>\n");
829 
830 		printf("<form method=\"get\" action=\"%s\">\n", AVAIL_CGI);
831 		printf("<input type='hidden' name='get_date_parts'>\n");
832 
833 		printf("<table border=0 cellpadding=5>\n");
834 
835 		printf("<tr><td class='reportSelectSubTitle' valign=center>Hostgroup(s):</td><td align=left valign=center class='reportSelectItem'>\n");
836 		printf("<select name='hostgroup'>\n");
837 		printf("<option value='all'>** ALL HOSTGROUPS **\n");
838 		for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
839 			if(is_authorized_for_hostgroup(temp_hostgroup, &current_authdata) == TRUE)
840 				printf("<option value='%s'>%s\n", escape_string(temp_hostgroup->group_name), temp_hostgroup->group_name);
841 			}
842 		printf("</select>\n");
843 		printf("</td></tr>\n");
844 
845 		printf("<tr><td></td><td align=left class='dateSelectItem'><input type='submit' value='Continue to Step 3'></td></tr>\n");
846 
847 		printf("</table>\n");
848 
849 		printf("</form>\n");
850 
851 		printf("</div></p>\n");
852 		}
853 
854 	/* step 2 - the user wants to select a host */
855 	else if(select_hosts == TRUE) {
856 		printf("<p><div align=center class='reportSelectTitle'>Step 2: Select Host</div></p>\n");
857 
858 		printf("<p><div align=center>\n");
859 
860 		printf("<form method=\"get\" action=\"%s\">\n", AVAIL_CGI);
861 		printf("<input type='hidden' name='get_date_parts'>\n");
862 
863 		printf("<table border=0 cellpadding=5>\n");
864 
865 		printf("<tr><td class='reportSelectSubTitle' valign=center>Host(s):</td><td align=left valign=center class='reportSelectItem'>\n");
866 		printf("<select name='host'>\n");
867 		printf("<option value='all'>** ALL HOSTS **\n");
868 		for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
869 			if(is_authorized_for_host(temp_host, &current_authdata) == TRUE)
870 				printf("<option value='%s'>%s\n", escape_string(temp_host->name), temp_host->name);
871 			}
872 		printf("</select>\n");
873 		printf("</td></tr>\n");
874 
875 		printf("<tr><td></td><td align=left class='dateSelectItem'><input type='submit' value='Continue to Step 3'></td></tr>\n");
876 
877 		printf("</table>\n");
878 
879 		printf("</form>\n");
880 
881 		printf("</div></p>\n");
882 
883 		printf("<div align=center class='helpfulHint'>Tip: If you want to have the option of getting the availability data in CSV format, select '<b>** ALL HOSTS **</b>' from the pull-down menu.\n");
884 		}
885 
886 	/* step 2 - the user wants to select a servicegroup */
887 	else if(select_servicegroups == TRUE) {
888 		printf("<p><div align=center class='reportSelectTitle'>Step 2: Select Servicegroup</div></p>\n");
889 
890 		printf("<p><div align=center>\n");
891 
892 		printf("<form method=\"get\" action=\"%s\">\n", AVAIL_CGI);
893 		printf("<input type='hidden' name='get_date_parts'>\n");
894 
895 		printf("<table border=0 cellpadding=5>\n");
896 
897 		printf("<tr><td class='reportSelectSubTitle' valign=center>Servicegroup(s):</td><td align=left valign=center class='reportSelectItem'>\n");
898 		printf("<select name='servicegroup'>\n");
899 		printf("<option value='all'>** ALL SERVICEGROUPS **\n");
900 		for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
901 			if(is_authorized_for_servicegroup(temp_servicegroup, &current_authdata) == TRUE)
902 				printf("<option value='%s'>%s\n", escape_string(temp_servicegroup->group_name), temp_servicegroup->group_name);
903 			}
904 		printf("</select>\n");
905 		printf("</td></tr>\n");
906 
907 		printf("<tr><td></td><td align=left class='dateSelectItem'><input type='submit' value='Continue to Step 3'></td></tr>\n");
908 
909 		printf("</table>\n");
910 
911 		printf("</form>\n");
912 
913 		printf("</div></p>\n");
914 		}
915 
916 	/* step 2 - the user wants to select a service */
917 	else if(select_services == TRUE) {
918 
919 		printf("<SCRIPT LANGUAGE='JavaScript'>\n");
920 		printf("function gethostname(hostindex){\n");
921 		printf("hostnames=[\"all\"");
922 
923 		firsthostpointer = NULL;
924 		for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
925 			if(is_authorized_for_service(temp_service, &current_authdata) == TRUE) {
926 				if(!firsthostpointer)
927 					firsthostpointer = temp_service->host_name;
928 				printf(", \"%s\"", temp_service->host_name);
929 				}
930 			}
931 
932 		printf(" ]\n");
933 		printf("return hostnames[hostindex];\n");
934 		printf("}\n");
935 		printf("</SCRIPT>\n");
936 
937 		printf("<p><div align=center class='reportSelectTitle'>Step 2: Select Service</div></p>\n");
938 
939 		printf("<p><div align=center>\n");
940 
941 		printf("<form method=\"get\" action=\"%s\" name='serviceform'>\n", AVAIL_CGI);
942 		printf("<input type='hidden' name='get_date_parts'>\n");
943 		printf("<input type='hidden' name='host' value='%s'>\n", (firsthostpointer == NULL) ? "unknown" : (char *)escape_string(firsthostpointer));
944 
945 		printf("<table border=0 cellpadding=5>\n");
946 
947 		printf("<tr><td class='reportSelectSubTitle' valign=center>Service(s):</td><td align=left valign=center class='reportSelectItem'>\n");
948 		printf("<select name='service' onFocus='document.serviceform.host.value=gethostname(this.selectedIndex);' onChange='document.serviceform.host.value=gethostname(this.selectedIndex);'>\n");
949 		printf("<option value='all'>** ALL SERVICES **\n");
950 		for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
951 			if(is_authorized_for_service(temp_service, &current_authdata) == TRUE)
952 				printf("<option value='%s'>%s;%s\n", escape_string(temp_service->description), temp_service->host_name, temp_service->description);
953 			}
954 
955 		printf("</select>\n");
956 		printf("</td></tr>\n");
957 
958 		printf("<tr><td></td><td align=left class='dateSelectItem'><input type='submit' value='Continue to Step 3'></td></tr>\n");
959 
960 		printf("</table>\n");
961 
962 		printf("</form>\n");
963 
964 		printf("</div></p>\n");
965 
966 		printf("<div align=center class='helpfulHint'>Tip: If you want to have the option of getting the availability data in CSV format, select '<b>** ALL SERVICES **</b>' from the pull-down menu.\n");
967 		}
968 
969 
970 	/* generate availability report */
971 	else if(display_type != DISPLAY_NO_AVAIL) {
972 
973 		/* check authorization */
974 		is_authorized = TRUE;
975 		if((display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE) || (display_type == DISPLAY_SERVICE_AVAIL && show_all_services == FALSE)) {
976 
977 			if(display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE)
978 				is_authorized = is_authorized_for_host(find_host(host_name), &current_authdata);
979 			else
980 				is_authorized = is_authorized_for_service(find_service(host_name, svc_description), &current_authdata);
981 			}
982 
983 		if(is_authorized == FALSE)
984 			printf("<P><DIV ALIGN=CENTER CLASS='errorMessage'>It appears as though you are not authorized to view information for the specified %s...</DIV></P>\n", (display_type == DISPLAY_HOST_AVAIL) ? "host" : "service");
985 
986 		else {
987 
988 			time(&report_start_time);
989 
990 			/* create list of subjects to collect availability data for */
991 			create_subject_list();
992 
993 			/* read in all necessary archived state data */
994 			read_archived_state_data();
995 
996 			/* compute availability data */
997 			compute_availability();
998 
999 			time(&report_end_time);
1000 
1001 			if(output_format == HTML_OUTPUT) {
1002 				get_time_breakdown((time_t)(report_end_time - report_start_time), &days, &hours, &minutes, &seconds);
1003 				printf("<div align=center class='reportTime'>[ Availability report completed in %d min %d sec ]</div>\n", minutes, seconds);
1004 				printf("<BR><BR>\n");
1005 				}
1006 
1007 			/* display availability data */
1008 			if(display_type == DISPLAY_HOST_AVAIL)
1009 				display_host_availability();
1010 			else if(display_type == DISPLAY_SERVICE_AVAIL)
1011 				display_service_availability();
1012 			else if(display_type == DISPLAY_HOSTGROUP_AVAIL)
1013 				display_hostgroup_availability();
1014 			else if(display_type == DISPLAY_SERVICEGROUP_AVAIL)
1015 				display_servicegroup_availability();
1016 
1017 			/* free memory allocated to availability data */
1018 			free_availability_data();
1019 			}
1020 		}
1021 
1022 
1023 	/* step 1 - ask the user what kind of report they want */
1024 	else {
1025 
1026 		printf("<p><div align=center class='reportSelectTitle'>Step 1: Select Report Type</div></p>\n");
1027 
1028 		printf("<p><div align=center>\n");
1029 
1030 		printf("<form method=\"get\" action=\"%s\">\n", AVAIL_CGI);
1031 
1032 		printf("<table border=0 cellpadding=5>\n");
1033 
1034 		printf("<tr><td class='reportSelectSubTitle' align=right>Type:</td>\n");
1035 		printf("<td class='reportSelectItem'>\n");
1036 		printf("<select name='report_type'>\n");
1037 		printf("<option value=hostgroups>Hostgroup(s)\n");
1038 		printf("<option value=hosts>Host(s)\n");
1039 		printf("<option value=servicegroups>Servicegroup(s)\n");
1040 		printf("<option value=services>Service(s)\n");
1041 		printf("</select>\n");
1042 		printf("</td></tr>\n");
1043 
1044 		printf("<tr><td></td><td align=left class='dateSelectItem'><input type='submit' value='Continue to Step 2'></td></tr>\n");
1045 
1046 		printf("</table>\n");
1047 
1048 		printf("</form>\n");
1049 
1050 		printf("</div></p>\n");
1051 		}
1052 
1053 
1054 	document_footer();
1055 
1056 	/* free all other allocated memory */
1057 	free_memory();
1058 
1059 	return OK;
1060 	}
1061 
1062 
1063 
document_header(int use_stylesheet)1064 void document_header(int use_stylesheet) {
1065 	char date_time[MAX_DATETIME_LENGTH];
1066 	time_t current_time;
1067 	time_t expire_time;
1068 
1069 	printf("Cache-Control: no-store\r\n");
1070 	printf("Pragma: no-cache\r\n");
1071 
1072 	time(&current_time);
1073 	get_time_string(&current_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1074 	printf("Last-Modified: %s\r\n", date_time);
1075 
1076 	expire_time = (time_t)0;
1077 	get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1078 	printf("Expires: %s\r\n", date_time);
1079 
1080 	if(output_format == HTML_OUTPUT)
1081 		printf("Content-type: text/html\r\n\r\n");
1082 	else {
1083 		printf("Content-type: text/csv\r\n\r\n");
1084 		return;
1085 		}
1086 
1087 	if(embedded == TRUE || output_format == CSV_OUTPUT)
1088 		return;
1089 
1090 	printf("<html>\n");
1091 	printf("<head>\n");
1092 	printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
1093 	printf("<title>\n");
1094 	printf("Nagios Availability\n");
1095 	printf("</title>\n");
1096 
1097 	if(use_stylesheet == TRUE) {
1098 		printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
1099 		printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, AVAIL_CSS);
1100 		}
1101 
1102 	printf("</head>\n");
1103 
1104 	printf("<BODY CLASS='avail'>\n");
1105 
1106 	/* include user SSI header */
1107 	include_ssi_files(AVAIL_CGI, SSI_HEADER);
1108 
1109 	return;
1110 	}
1111 
1112 
1113 
document_footer(void)1114 void document_footer(void) {
1115 
1116 	if(output_format != HTML_OUTPUT)
1117 		return;
1118 
1119 	if(embedded == TRUE)
1120 		return;
1121 
1122 	/* include user SSI footer */
1123 	include_ssi_files(AVAIL_CGI, SSI_FOOTER);
1124 
1125 	printf("</body>\n");
1126 	printf("</html>\n");
1127 
1128 	return;
1129 	}
1130 
1131 
1132 
process_cgivars(void)1133 int process_cgivars(void) {
1134 	char **variables;
1135 	int error = FALSE;
1136 	int x;
1137 
1138 	variables = getcgivars();
1139 
1140 	for(x = 0; variables[x] != NULL; x++) {
1141 
1142 		/* do some basic length checking on the variable identifier to prevent buffer overflows */
1143 		if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
1144 			continue;
1145 			}
1146 
1147 		/* we found the hostgroup argument */
1148 		else if(!strcmp(variables[x], "hostgroup")) {
1149 			x++;
1150 			if(variables[x] == NULL) {
1151 				error = TRUE;
1152 				break;
1153 				}
1154 
1155 			if((hostgroup_name = (char *)strdup(variables[x])) == NULL)
1156 				hostgroup_name = "";
1157 			strip_html_brackets(hostgroup_name);
1158 
1159 			display_type = DISPLAY_HOSTGROUP_AVAIL;
1160 			show_all_hostgroups = (strcmp(hostgroup_name, "all")) ? FALSE : TRUE;
1161 			}
1162 
1163 		/* we found the servicegroup argument */
1164 		else if(!strcmp(variables[x], "servicegroup")) {
1165 			x++;
1166 			if(variables[x] == NULL) {
1167 				error = TRUE;
1168 				break;
1169 				}
1170 
1171 			if((servicegroup_name = (char *)strdup(variables[x])) == NULL)
1172 				servicegroup_name = "";
1173 			strip_html_brackets(servicegroup_name);
1174 
1175 			display_type = DISPLAY_SERVICEGROUP_AVAIL;
1176 			show_all_servicegroups = (strcmp(servicegroup_name, "all")) ? FALSE : TRUE;
1177 			}
1178 
1179 		/* we found the host argument */
1180 		else if(!strcmp(variables[x], "host")) {
1181 			x++;
1182 			if(variables[x] == NULL) {
1183 				error = TRUE;
1184 				break;
1185 				}
1186 
1187 			if((host_name = (char *)strdup(variables[x])) == NULL)
1188 				host_name = "";
1189 			strip_html_brackets(host_name);
1190 
1191 			display_type = DISPLAY_HOST_AVAIL;
1192 			show_all_hosts = (strcmp(host_name, "all")) ? FALSE : TRUE;
1193 			}
1194 
1195 		/* we found the service description argument */
1196 		else if(!strcmp(variables[x], "service")) {
1197 			x++;
1198 			if(variables[x] == NULL) {
1199 				error = TRUE;
1200 				break;
1201 				}
1202 
1203 			if((svc_description = (char *)strdup(variables[x])) == NULL)
1204 				svc_description = "";
1205 			strip_html_brackets(svc_description);
1206 
1207 			display_type = DISPLAY_SERVICE_AVAIL;
1208 			show_all_services = (strcmp(svc_description, "all")) ? FALSE : TRUE;
1209 			}
1210 
1211 		/* we found first time argument */
1212 		else if(!strcmp(variables[x], "t1")) {
1213 			x++;
1214 			if(variables[x] == NULL) {
1215 				error = TRUE;
1216 				break;
1217 				}
1218 
1219 			t1 = (time_t)strtoul(variables[x], NULL, 10);
1220 			timeperiod_type = TIMEPERIOD_CUSTOM;
1221 			compute_time_from_parts = FALSE;
1222 			}
1223 
1224 		/* we found first time argument */
1225 		else if(!strcmp(variables[x], "t2")) {
1226 			x++;
1227 			if(variables[x] == NULL) {
1228 				error = TRUE;
1229 				break;
1230 				}
1231 
1232 			t2 = (time_t)strtoul(variables[x], NULL, 10);
1233 			timeperiod_type = TIMEPERIOD_CUSTOM;
1234 			compute_time_from_parts = FALSE;
1235 			}
1236 
1237 		/* we found the assume initial states option */
1238 		else if(!strcmp(variables[x], "assumeinitialstates")) {
1239 			x++;
1240 			if(variables[x] == NULL) {
1241 				error = TRUE;
1242 				break;
1243 				}
1244 
1245 			if(!strcmp(variables[x], "yes"))
1246 				assume_initial_states = TRUE;
1247 			else
1248 				assume_initial_states = FALSE;
1249 			}
1250 
1251 		/* we found the assume state during program not running option */
1252 		else if(!strcmp(variables[x], "assumestatesduringnotrunning")) {
1253 			x++;
1254 			if(variables[x] == NULL) {
1255 				error = TRUE;
1256 				break;
1257 				}
1258 
1259 			if(!strcmp(variables[x], "yes"))
1260 				assume_states_during_notrunning = TRUE;
1261 			else
1262 				assume_states_during_notrunning = FALSE;
1263 			}
1264 
1265 		/* we found the initial assumed host state option */
1266 		else if(!strcmp(variables[x], "initialassumedhoststate")) {
1267 			x++;
1268 			if(variables[x] == NULL) {
1269 				error = TRUE;
1270 				break;
1271 				}
1272 
1273 			initial_assumed_host_state = atoi(variables[x]);
1274 			}
1275 
1276 		/* we found the initial assumed service state option */
1277 		else if(!strcmp(variables[x], "initialassumedservicestate")) {
1278 			x++;
1279 			if(variables[x] == NULL) {
1280 				error = TRUE;
1281 				break;
1282 				}
1283 
1284 			initial_assumed_service_state = atoi(variables[x]);
1285 			}
1286 
1287 		/* we found the assume state retention option */
1288 		else if(!strcmp(variables[x], "assumestateretention")) {
1289 			x++;
1290 			if(variables[x] == NULL) {
1291 				error = TRUE;
1292 				break;
1293 				}
1294 
1295 			if(!strcmp(variables[x], "yes"))
1296 				assume_state_retention = TRUE;
1297 			else
1298 				assume_state_retention = FALSE;
1299 			}
1300 
1301 		/* we found the include soft states option */
1302 		else if(!strcmp(variables[x], "includesoftstates")) {
1303 			x++;
1304 			if(variables[x] == NULL) {
1305 				error = TRUE;
1306 				break;
1307 				}
1308 
1309 			if(!strcmp(variables[x], "yes"))
1310 				include_soft_states = TRUE;
1311 			else
1312 				include_soft_states = FALSE;
1313 			}
1314 
1315 		/* we found the backtrack archives argument */
1316 		else if(!strcmp(variables[x], "backtrack")) {
1317 			x++;
1318 			if(variables[x] == NULL) {
1319 				error = TRUE;
1320 				break;
1321 				}
1322 
1323 			backtrack_archives = atoi(variables[x]);
1324 			if(backtrack_archives < 0)
1325 				backtrack_archives = 0;
1326 			if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
1327 				backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
1328 
1329 #ifdef DEBUG
1330 			printf("BACKTRACK ARCHIVES: %d\n", backtrack_archives);
1331 #endif
1332 			}
1333 
1334 		/* we found the standard timeperiod argument */
1335 		else if(!strcmp(variables[x], "timeperiod")) {
1336 			x++;
1337 			if(variables[x] == NULL) {
1338 				error = TRUE;
1339 				break;
1340 				}
1341 
1342 			if(!strcmp(variables[x], "today"))
1343 				timeperiod_type = TIMEPERIOD_TODAY;
1344 			else if(!strcmp(variables[x], "yesterday"))
1345 				timeperiod_type = TIMEPERIOD_YESTERDAY;
1346 			else if(!strcmp(variables[x], "thisweek"))
1347 				timeperiod_type = TIMEPERIOD_THISWEEK;
1348 			else if(!strcmp(variables[x], "lastweek"))
1349 				timeperiod_type = TIMEPERIOD_LASTWEEK;
1350 			else if(!strcmp(variables[x], "thismonth"))
1351 				timeperiod_type = TIMEPERIOD_THISMONTH;
1352 			else if(!strcmp(variables[x], "lastmonth"))
1353 				timeperiod_type = TIMEPERIOD_LASTMONTH;
1354 			else if(!strcmp(variables[x], "thisquarter"))
1355 				timeperiod_type = TIMEPERIOD_THISQUARTER;
1356 			else if(!strcmp(variables[x], "lastquarter"))
1357 				timeperiod_type = TIMEPERIOD_LASTQUARTER;
1358 			else if(!strcmp(variables[x], "thisyear"))
1359 				timeperiod_type = TIMEPERIOD_THISYEAR;
1360 			else if(!strcmp(variables[x], "lastyear"))
1361 				timeperiod_type = TIMEPERIOD_LASTYEAR;
1362 			else if(!strcmp(variables[x], "last24hours"))
1363 				timeperiod_type = TIMEPERIOD_LAST24HOURS;
1364 			else if(!strcmp(variables[x], "last7days"))
1365 				timeperiod_type = TIMEPERIOD_LAST7DAYS;
1366 			else if(!strcmp(variables[x], "last31days"))
1367 				timeperiod_type = TIMEPERIOD_LAST31DAYS;
1368 			else if(!strcmp(variables[x], "custom"))
1369 				timeperiod_type = TIMEPERIOD_CUSTOM;
1370 			else
1371 				continue;
1372 
1373 			convert_timeperiod_to_times(timeperiod_type);
1374 			compute_time_from_parts = FALSE;
1375 			}
1376 
1377 		/* we found the embed option */
1378 		else if(!strcmp(variables[x], "embedded"))
1379 			embedded = TRUE;
1380 
1381 		/* we found the noheader option */
1382 		else if(!strcmp(variables[x], "noheader"))
1383 			display_header = FALSE;
1384 
1385 		/* we found the CSV output option */
1386 		else if(!strcmp(variables[x], "csvoutput")) {
1387 			display_header = FALSE;
1388 			output_format = CSV_OUTPUT;
1389 			}
1390 
1391 		/* we found the log entries option  */
1392 		else if(!strcmp(variables[x], "show_log_entries"))
1393 			show_log_entries = TRUE;
1394 
1395 		/* we found the full log entries option */
1396 		else if(!strcmp(variables[x], "full_log_entries"))
1397 			full_log_entries = TRUE;
1398 
1399 		/* we found the get date parts option */
1400 		else if(!strcmp(variables[x], "get_date_parts"))
1401 			get_date_parts = TRUE;
1402 
1403 		/* we found the report type selection option */
1404 		else if(!strcmp(variables[x], "report_type")) {
1405 			x++;
1406 			if(variables[x] == NULL) {
1407 				error = TRUE;
1408 				break;
1409 				}
1410 			if(!strcmp(variables[x], "hostgroups"))
1411 				select_hostgroups = TRUE;
1412 			else if(!strcmp(variables[x], "servicegroups"))
1413 				select_servicegroups = TRUE;
1414 			else if(!strcmp(variables[x], "hosts"))
1415 				select_hosts = TRUE;
1416 			else
1417 				select_services = TRUE;
1418 			}
1419 
1420 		/* we found time argument */
1421 		else if(!strcmp(variables[x], "smon")) {
1422 			x++;
1423 			if(variables[x] == NULL) {
1424 				error = TRUE;
1425 				break;
1426 				}
1427 
1428 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1429 				continue;
1430 
1431 			start_month = atoi(variables[x]);
1432 			timeperiod_type = TIMEPERIOD_CUSTOM;
1433 			compute_time_from_parts = TRUE;
1434 			}
1435 
1436 		/* we found time argument */
1437 		else if(!strcmp(variables[x], "sday")) {
1438 			x++;
1439 			if(variables[x] == NULL) {
1440 				error = TRUE;
1441 				break;
1442 				}
1443 
1444 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1445 				continue;
1446 
1447 			start_day = atoi(variables[x]);
1448 			timeperiod_type = TIMEPERIOD_CUSTOM;
1449 			compute_time_from_parts = TRUE;
1450 			}
1451 
1452 		/* we found time argument */
1453 		else if(!strcmp(variables[x], "syear")) {
1454 			x++;
1455 			if(variables[x] == NULL) {
1456 				error = TRUE;
1457 				break;
1458 				}
1459 
1460 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1461 				continue;
1462 
1463 			start_year = atoi(variables[x]);
1464 			timeperiod_type = TIMEPERIOD_CUSTOM;
1465 			compute_time_from_parts = TRUE;
1466 			}
1467 
1468 		/* we found time argument */
1469 		else if(!strcmp(variables[x], "smin")) {
1470 			x++;
1471 			if(variables[x] == NULL) {
1472 				error = TRUE;
1473 				break;
1474 				}
1475 
1476 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1477 				continue;
1478 
1479 			start_minute = atoi(variables[x]);
1480 			timeperiod_type = TIMEPERIOD_CUSTOM;
1481 			compute_time_from_parts = TRUE;
1482 			}
1483 
1484 		/* we found time argument */
1485 		else if(!strcmp(variables[x], "ssec")) {
1486 			x++;
1487 			if(variables[x] == NULL) {
1488 				error = TRUE;
1489 				break;
1490 				}
1491 
1492 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1493 				continue;
1494 
1495 			start_second = atoi(variables[x]);
1496 			timeperiod_type = TIMEPERIOD_CUSTOM;
1497 			compute_time_from_parts = TRUE;
1498 			}
1499 
1500 		/* we found time argument */
1501 		else if(!strcmp(variables[x], "shour")) {
1502 			x++;
1503 			if(variables[x] == NULL) {
1504 				error = TRUE;
1505 				break;
1506 				}
1507 
1508 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1509 				continue;
1510 
1511 			start_hour = atoi(variables[x]);
1512 			timeperiod_type = TIMEPERIOD_CUSTOM;
1513 			compute_time_from_parts = TRUE;
1514 			}
1515 
1516 
1517 		/* we found time argument */
1518 		else if(!strcmp(variables[x], "emon")) {
1519 			x++;
1520 			if(variables[x] == NULL) {
1521 				error = TRUE;
1522 				break;
1523 				}
1524 
1525 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1526 				continue;
1527 
1528 			end_month = atoi(variables[x]);
1529 			timeperiod_type = TIMEPERIOD_CUSTOM;
1530 			compute_time_from_parts = TRUE;
1531 			}
1532 
1533 		/* we found time argument */
1534 		else if(!strcmp(variables[x], "eday")) {
1535 			x++;
1536 			if(variables[x] == NULL) {
1537 				error = TRUE;
1538 				break;
1539 				}
1540 
1541 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1542 				continue;
1543 
1544 			end_day = atoi(variables[x]);
1545 			timeperiod_type = TIMEPERIOD_CUSTOM;
1546 			compute_time_from_parts = TRUE;
1547 			}
1548 
1549 		/* we found time argument */
1550 		else if(!strcmp(variables[x], "eyear")) {
1551 			x++;
1552 			if(variables[x] == NULL) {
1553 				error = TRUE;
1554 				break;
1555 				}
1556 
1557 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1558 				continue;
1559 
1560 			end_year = atoi(variables[x]);
1561 			timeperiod_type = TIMEPERIOD_CUSTOM;
1562 			compute_time_from_parts = TRUE;
1563 			}
1564 
1565 		/* we found time argument */
1566 		else if(!strcmp(variables[x], "emin")) {
1567 			x++;
1568 			if(variables[x] == NULL) {
1569 				error = TRUE;
1570 				break;
1571 				}
1572 
1573 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1574 				continue;
1575 
1576 			end_minute = atoi(variables[x]);
1577 			timeperiod_type = TIMEPERIOD_CUSTOM;
1578 			compute_time_from_parts = TRUE;
1579 			}
1580 
1581 		/* we found time argument */
1582 		else if(!strcmp(variables[x], "esec")) {
1583 			x++;
1584 			if(variables[x] == NULL) {
1585 				error = TRUE;
1586 				break;
1587 				}
1588 
1589 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1590 				continue;
1591 
1592 			end_second = atoi(variables[x]);
1593 			timeperiod_type = TIMEPERIOD_CUSTOM;
1594 			compute_time_from_parts = TRUE;
1595 			}
1596 
1597 		/* we found time argument */
1598 		else if(!strcmp(variables[x], "ehour")) {
1599 			x++;
1600 			if(variables[x] == NULL) {
1601 				error = TRUE;
1602 				break;
1603 				}
1604 
1605 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1606 				continue;
1607 
1608 			end_hour = atoi(variables[x]);
1609 			timeperiod_type = TIMEPERIOD_CUSTOM;
1610 			compute_time_from_parts = TRUE;
1611 			}
1612 
1613 		/* we found the show scheduled downtime option */
1614 		else if(!strcmp(variables[x], "showscheduleddowntime")) {
1615 			x++;
1616 			if(variables[x] == NULL) {
1617 				error = TRUE;
1618 				break;
1619 				}
1620 
1621 			if(!strcmp(variables[x], "yes"))
1622 				show_scheduled_downtime = TRUE;
1623 			else
1624 				show_scheduled_downtime = FALSE;
1625 			}
1626 
1627 		/* we found the report timeperiod option */
1628 		else if(!strcmp(variables[x], "rpttimeperiod")) {
1629 			timeperiod *temp_timeperiod;
1630 			x++;
1631 			if(variables[x] == NULL) {
1632 				error = TRUE;
1633 				break;
1634 				}
1635 
1636 			for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next) {
1637 				if(!strcmp(url_encode(temp_timeperiod->name), variables[x])) {
1638 					current_timeperiod = temp_timeperiod;
1639 					break;
1640 					}
1641 				}
1642 			}
1643 
1644 		}
1645 
1646 	/* free memory allocated to the CGI variables */
1647 	free_cgivars(variables);
1648 
1649 	return error;
1650 	}
1651 
1652 
1653 
1654 /* computes availability data for all subjects */
compute_availability(void)1655 void compute_availability(void) {
1656 	avail_subject *temp_subject;
1657 	time_t current_time;
1658 
1659 	time(&current_time);
1660 
1661 	for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
1662 		compute_subject_availability(temp_subject, current_time);
1663 		compute_subject_downtime(temp_subject, current_time);
1664 		}
1665 
1666 	return;
1667 	}
1668 
1669 
1670 
1671 /* computes availability data for a given subject */
compute_subject_availability(avail_subject * subject,time_t current_time)1672 void compute_subject_availability(avail_subject *subject, time_t current_time) {
1673 	archived_state *temp_as;
1674 	archived_state *last_as;
1675 	time_t a;
1676 	time_t b;
1677 	int current_state = AS_NO_DATA;
1678 	int have_some_real_data = FALSE;
1679 	hoststatus *hststatus = NULL;
1680 	servicestatus *svcstatus = NULL;
1681 	int first_real_state = AS_NO_DATA;
1682 	time_t initial_assumed_time;
1683 	int initial_assumed_state = AS_NO_DATA;
1684 	int error;
1685 
1686 
1687 	/* if left hand of graph is after current time, we can't do anything at all.... */
1688 	if(t1 > current_time)
1689 		return;
1690 
1691 	/* get current state of host or service if possible */
1692 	if(subject->type == HOST_SUBJECT)
1693 		hststatus = find_hoststatus(subject->host_name);
1694 	else
1695 		svcstatus = find_servicestatus(subject->host_name, subject->service_description);
1696 
1697 
1698 	/************************************/
1699 	/* INSERT CURRENT STATE (IF WE CAN) */
1700 	/************************************/
1701 
1702 	/* if current time DOES NOT fall within graph bounds, so we can't do anything as far as assuming current state */
1703 
1704 	/* if we don't have any data, assume current state (if possible) */
1705 	if(subject->as_list == NULL && current_time > t1 && current_time <= t2) {
1706 
1707 		/* we don't have any historical information, but the current time falls within the reporting period, so use */
1708 		/* the current status of the host/service as the starting data */
1709 		if(subject->type == HOST_SUBJECT) {
1710 			if(hststatus != NULL) {
1711 
1712 				if(hststatus->status == HOST_DOWN)
1713 					subject->last_known_state = AS_HOST_DOWN;
1714 				else if(hststatus->status == HOST_UNREACHABLE)
1715 					subject->last_known_state = AS_HOST_UNREACHABLE;
1716 				else if(hststatus->status == HOST_UP)
1717 					subject->last_known_state = AS_HOST_UP;
1718 				else
1719 					subject->last_known_state = AS_NO_DATA;
1720 
1721 				if(subject->last_known_state != AS_NO_DATA) {
1722 
1723 					/* add a dummy archived state item, so something can get graphed */
1724 					add_archived_state(subject->last_known_state, AS_HARD_STATE, t1, "Current Host State Assumed (Faked Log Entry)", subject);
1725 
1726 					/* use the current state as the last known real state */
1727 					first_real_state = subject->last_known_state;
1728 					}
1729 				}
1730 			}
1731 		else {
1732 			if(svcstatus != NULL) {
1733 
1734 				if(svcstatus->status == SERVICE_OK)
1735 					subject->last_known_state = AS_SVC_OK;
1736 				else if(svcstatus->status == SERVICE_WARNING)
1737 					subject->last_known_state = AS_SVC_WARNING;
1738 				else if(svcstatus->status == SERVICE_CRITICAL)
1739 					subject->last_known_state = AS_SVC_CRITICAL;
1740 				else if(svcstatus->status == SERVICE_UNKNOWN)
1741 					subject->last_known_state = AS_SVC_UNKNOWN;
1742 				else
1743 					subject->last_known_state = AS_NO_DATA;
1744 
1745 				if(subject->last_known_state != AS_NO_DATA) {
1746 
1747 					/* add a dummy archived state item, so something can get graphed */
1748 					add_archived_state(subject->last_known_state, AS_HARD_STATE, t1, "Current Service State Assumed (Faked Log Entry)", subject);
1749 
1750 					/* use the current state as the last known real state */
1751 					first_real_state = subject->last_known_state;
1752 					}
1753 				}
1754 			}
1755 		}
1756 
1757 
1758 
1759 	/******************************************/
1760 	/* INSERT FIRST ASSUMED STATE (IF WE CAN) */
1761 	/******************************************/
1762 
1763 	if((subject->type == HOST_SUBJECT && initial_assumed_host_state != AS_NO_DATA) || (subject->type == SERVICE_SUBJECT && initial_assumed_service_state != AS_NO_DATA)) {
1764 
1765 		/* see if its okay to assume initial state for this subject */
1766 		error = FALSE;
1767 		if(subject->type == SERVICE_SUBJECT) {
1768 			if(initial_assumed_service_state != AS_SVC_OK && initial_assumed_service_state != AS_SVC_WARNING && initial_assumed_service_state != AS_SVC_UNKNOWN && initial_assumed_service_state != AS_SVC_CRITICAL && initial_assumed_service_state != AS_CURRENT_STATE)
1769 				error = TRUE;
1770 			else
1771 				initial_assumed_state = initial_assumed_service_state;
1772 			if(initial_assumed_service_state == AS_CURRENT_STATE && svcstatus == NULL)
1773 				error = TRUE;
1774 			}
1775 		else {
1776 			if(initial_assumed_host_state != AS_HOST_UP && initial_assumed_host_state != AS_HOST_DOWN && initial_assumed_host_state != AS_HOST_UNREACHABLE && initial_assumed_host_state != AS_CURRENT_STATE)
1777 				error = TRUE;
1778 			else
1779 				initial_assumed_state = initial_assumed_host_state;
1780 			if(initial_assumed_host_state == AS_CURRENT_STATE && hststatus == NULL)
1781 				error = TRUE;
1782 			}
1783 
1784 		/* get the current state if applicable */
1785 		if(((subject->type == HOST_SUBJECT && initial_assumed_host_state == AS_CURRENT_STATE) || (subject->type == SERVICE_SUBJECT && initial_assumed_service_state == AS_CURRENT_STATE)) && error == FALSE) {
1786 			if(subject->type == SERVICE_SUBJECT) {
1787 				switch(svcstatus->status) {
1788 					case SERVICE_OK:
1789 						initial_assumed_state = AS_SVC_OK;
1790 						break;
1791 					case SERVICE_WARNING:
1792 						initial_assumed_state = AS_SVC_WARNING;
1793 						break;
1794 					case SERVICE_UNKNOWN:
1795 						initial_assumed_state = AS_SVC_UNKNOWN;
1796 						break;
1797 					case SERVICE_CRITICAL:
1798 						initial_assumed_state = AS_SVC_CRITICAL;
1799 						break;
1800 					default:
1801 						error = TRUE;
1802 						break;
1803 					}
1804 				}
1805 			else {
1806 				switch(hststatus->status) {
1807 					case HOST_DOWN:
1808 						initial_assumed_state = AS_HOST_DOWN;
1809 						break;
1810 					case HOST_UNREACHABLE:
1811 						initial_assumed_state = AS_HOST_UNREACHABLE;
1812 						break;
1813 					case HOST_UP:
1814 						initial_assumed_state = AS_HOST_UP;
1815 						break;
1816 					default:
1817 						error = TRUE;
1818 						break;
1819 					}
1820 				}
1821 			}
1822 
1823 		if(error == FALSE) {
1824 
1825 			/* add this assumed state entry before any entries in the list and <= t1 */
1826 			if(subject->as_list == NULL)
1827 				initial_assumed_time = t1;
1828 			else if(subject->as_list->time_stamp > t1)
1829 				initial_assumed_time = t1;
1830 			else
1831 				initial_assumed_time = subject->as_list->time_stamp - 1;
1832 
1833 			if(subject->type == HOST_SUBJECT)
1834 				add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Host State Assumed (Faked Log Entry)", subject);
1835 			else
1836 				add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Service State Assumed (Faked Log Entry)", subject);
1837 			}
1838 		}
1839 
1840 
1841 
1842 
1843 	/**************************************/
1844 	/* BAIL OUT IF WE DON'T HAVE ANYTHING */
1845 	/**************************************/
1846 
1847 	have_some_real_data = FALSE;
1848 	for(temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
1849 		if(temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_START && temp_as->entry_type != AS_PROGRAM_END) {
1850 			have_some_real_data = TRUE;
1851 			break;
1852 			}
1853 		}
1854 	if(have_some_real_data == FALSE)
1855 		return;
1856 
1857 
1858 
1859 
1860 	last_as = NULL;
1861 	subject->earliest_time = t2;
1862 	subject->latest_time = t1;
1863 
1864 
1865 #ifdef DEBUG
1866 	printf("--- BEGINNING/MIDDLE SECTION ---<BR>\n");
1867 #endif
1868 
1869 	/**********************************/
1870 	/*    BEGINNING/MIDDLE SECTION    */
1871 	/**********************************/
1872 
1873 	for(temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
1874 
1875 		/* keep this as last known state if this is the first entry or if it occurs before the starting point of the graph */
1876 		if((temp_as->time_stamp <= t1 || temp_as == subject->as_list) && (temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_END && temp_as->entry_type != AS_PROGRAM_START)) {
1877 			subject->last_known_state = temp_as->entry_type;
1878 #ifdef DEBUG
1879 			printf("SETTING LAST KNOWN STATE=%d<br>\n", subject->last_known_state);
1880 #endif
1881 			}
1882 
1883 		/* skip this entry if it occurs before the starting point of the graph */
1884 		if(temp_as->time_stamp <= t1) {
1885 #ifdef DEBUG
1886 			printf("SKIPPING PRE-EVENT: %d @ %lu<br>\n", temp_as->entry_type, temp_as->time_stamp);
1887 #endif
1888 			last_as = temp_as;
1889 			continue;
1890 			}
1891 
1892 		/* graph this span if we're not on the first item */
1893 		if(last_as != NULL) {
1894 
1895 			a = last_as->time_stamp;
1896 			b = temp_as->time_stamp;
1897 
1898 			/* we've already passed the last time displayed in the graph */
1899 			if(a > t2)
1900 				break;
1901 
1902 			/* only graph this data if its on the graph */
1903 			else if(b > t1) {
1904 
1905 				/* clip last time if it exceeds graph limits */
1906 				if(b > t2)
1907 					b = t2;
1908 
1909 				/* clip first time if it precedes graph limits */
1910 				if(a < t1)
1911 					a = t1;
1912 
1913 				/* save this time if its the earliest we've graphed */
1914 				if(a < subject->earliest_time) {
1915 					subject->earliest_time = a;
1916 					subject->earliest_state = last_as->entry_type;
1917 					}
1918 
1919 				/* save this time if its the latest we've graphed */
1920 				if(b > subject->latest_time) {
1921 					subject->latest_time = b;
1922 					subject->latest_state = last_as->entry_type;
1923 					}
1924 
1925 				/* compute availability times for this chunk */
1926 				compute_subject_availability_times(last_as->entry_type, temp_as->entry_type, last_as->time_stamp, a, b, subject, temp_as);
1927 
1928 				/* return if we've reached the end of the graph limits */
1929 				if(b >= t2) {
1930 					last_as = temp_as;
1931 					break;
1932 					}
1933 				}
1934 			}
1935 
1936 
1937 		/* keep track of the last item */
1938 		last_as = temp_as;
1939 		}
1940 
1941 
1942 #ifdef DEBUG
1943 	printf("--- END SECTION ---<BR>\n");
1944 #endif
1945 
1946 	/**********************************/
1947 	/*           END SECTION          */
1948 	/**********************************/
1949 
1950 	if(last_as != NULL) {
1951 
1952 		/* don't process an entry that is beyond the limits of the graph */
1953 		if(last_as->time_stamp < t2) {
1954 
1955 			time(&current_time);
1956 			b = current_time;
1957 			if(b > t2)
1958 				b = t2;
1959 
1960 			a = last_as->time_stamp;
1961 			if(a < t1)
1962 				a = t1;
1963 
1964 			/* fake the current state (it doesn't really matter for graphing) */
1965 			if(subject->type == HOST_SUBJECT)
1966 				current_state = AS_HOST_UP;
1967 			else
1968 				current_state = AS_SVC_OK;
1969 
1970 			/* compute availability times for last state */
1971 			compute_subject_availability_times(last_as->entry_type, current_state, last_as->time_stamp, a, b, subject, last_as);
1972 			}
1973 		}
1974 
1975 
1976 	return;
1977 	}
1978 
1979 
1980 /* computes availability times */
compute_subject_availability_times(int first_state,int last_state,time_t real_start_time,time_t start_time,time_t end_time,avail_subject * subject,archived_state * as)1981 void compute_subject_availability_times(int first_state, int last_state, time_t real_start_time, time_t start_time, time_t end_time, avail_subject *subject, archived_state *as) {
1982 	int start_state;
1983 	int end_state;
1984 	unsigned long state_duration;
1985 	struct tm *t;
1986 	unsigned long midnight_today;
1987 	int weekday;
1988 	timerange *temp_timerange;
1989 	unsigned long temp_duration;
1990 	unsigned long temp_end;
1991 	unsigned long temp_start;
1992 	unsigned long start;
1993 	unsigned long end;
1994 
1995 #ifdef DEBUG
1996 	if(subject->type == HOST_SUBJECT)
1997 		printf("HOST '%s'...\n", subject->host_name);
1998 	else
1999 		printf("SERVICE '%s' ON HOST '%s'...\n", subject->service_description, subject->host_name);
2000 
2001 	printf("COMPUTING %d->%d FROM %lu to %lu (%lu seconds) FOR %s<br>\n", first_state, last_state, start_time, end_time, (end_time - start_time), (subject->type == HOST_SUBJECT) ? "HOST" : "SERVICE");
2002 #endif
2003 
2004 	/* clip times if necessary */
2005 	if(start_time < t1)
2006 		start_time = t1;
2007 	if(end_time > t2)
2008 		end_time = t2;
2009 
2010 	/* make sure this is a valid time */
2011 	if(start_time > t2)
2012 		return;
2013 	if(end_time < t1)
2014 		return;
2015 
2016 	/* MickeM - attempt to handle the current time_period (if any) */
2017 	if(current_timeperiod != NULL) {
2018 		t = localtime((time_t *)&start_time);
2019 		state_duration = 0;
2020 
2021 		/* calculate the start of the day (midnight, 00:00 hours) */
2022 		t->tm_sec = 0;
2023 		t->tm_min = 0;
2024 		t->tm_hour = 0;
2025 		t->tm_isdst = -1;
2026 		midnight_today = (unsigned long)mktime(t);
2027 		weekday = t->tm_wday;
2028 
2029 		while(midnight_today < end_time) {
2030 			temp_duration = 0;
2031 			temp_end = min(86400, end_time - midnight_today);
2032 			temp_start = 0;
2033 			if(start_time > midnight_today)
2034 				temp_start = start_time - midnight_today;
2035 #ifdef DEBUG
2036 			printf("<b>Matching: %ld -> %ld. (%ld -> %ld)</b><br>\n", temp_start, temp_end, midnight_today + temp_start, midnight_today + temp_end);
2037 #endif
2038 			/* check all time ranges for this day of the week */
2039 			for(temp_timerange = current_timeperiod->days[weekday]; temp_timerange != NULL; temp_timerange = temp_timerange->next) {
2040 
2041 #ifdef DEBUG
2042 				printf("<li>Matching in timerange[%d]: %d -> %d (%ld -> %ld)<br>\n", weekday, temp_timerange->range_start, temp_timerange->range_end, temp_start, temp_end);
2043 #endif
2044 				start = max(temp_timerange->range_start, temp_start);
2045 				end = min(temp_timerange->range_end, temp_end);
2046 
2047 				if(start < end) {
2048 					temp_duration += end - start;
2049 #ifdef DEBUG
2050 					printf("<li>Matched time: %ld -> %ld = %d<br>\n", start, end, temp_duration);
2051 #endif
2052 					}
2053 #ifdef DEBUG
2054 				else
2055 					printf("<li>Ignored time: %ld -> %ld<br>\n", start, end);
2056 #endif
2057 				}
2058 			state_duration += temp_duration;
2059 			temp_start = 0;
2060 			midnight_today += 86400;
2061 			if(++weekday > 6)
2062 				weekday = 0;
2063 			}
2064 		}
2065 
2066 	/* no report timeperiod was selected (assume 24x7) */
2067 	else {
2068 		/* calculate time in this state */
2069 		state_duration = (unsigned long)(end_time - start_time);
2070 		}
2071 
2072 	/* can't graph if we don't have data... */
2073 	if(first_state == AS_NO_DATA || last_state == AS_NO_DATA) {
2074 		subject->time_indeterminate_nodata += state_duration;
2075 		return;
2076 		}
2077 	if(first_state == AS_PROGRAM_START && (last_state == AS_PROGRAM_END || last_state == AS_PROGRAM_START)) {
2078 		if(assume_initial_states == FALSE) {
2079 			subject->time_indeterminate_nodata += state_duration;
2080 			return;
2081 			}
2082 		}
2083 	if(first_state == AS_PROGRAM_END) {
2084 
2085 		/* added 7/24/03 */
2086 		if(assume_states_during_notrunning == TRUE) {
2087 			first_state = subject->last_known_state;
2088 			}
2089 		else {
2090 			subject->time_indeterminate_notrunning += state_duration;
2091 			return;
2092 			}
2093 		}
2094 
2095 	/* special case if first entry was program start */
2096 	if(first_state == AS_PROGRAM_START) {
2097 
2098 		if(assume_initial_states == TRUE) {
2099 
2100 			if(assume_state_retention == TRUE)
2101 				start_state = subject->last_known_state;
2102 
2103 			else {
2104 				if(subject->type == HOST_SUBJECT)
2105 					start_state = AS_HOST_UP;
2106 				else
2107 					start_state = AS_SVC_OK;
2108 				}
2109 			}
2110 		else
2111 			return;
2112 		}
2113 	else {
2114 		start_state = first_state;
2115 		subject->last_known_state = first_state;
2116 		}
2117 
2118 	/* special case if last entry was program stop */
2119 	if(last_state == AS_PROGRAM_END)
2120 		end_state = first_state;
2121 	else
2122 		end_state = last_state;
2123 
2124 	/* save "processed state" info */
2125 	as->processed_state = start_state;
2126 
2127 #ifdef DEBUG
2128 	printf("PASSED TIME CHECKS, CLIPPED VALUES: START=%lu, END=%lu\n", start_time, end_time);
2129 #endif
2130 
2131 
2132 	/* add time in this state to running totals */
2133 	switch(start_state) {
2134 		case AS_HOST_UP:
2135 			subject->time_up += state_duration;
2136 			break;
2137 		case AS_HOST_DOWN:
2138 			subject->time_down += state_duration;
2139 			break;
2140 		case AS_HOST_UNREACHABLE:
2141 			subject->time_unreachable += state_duration;
2142 			break;
2143 		case AS_SVC_OK:
2144 			subject->time_ok += state_duration;
2145 			break;
2146 		case AS_SVC_WARNING:
2147 			subject->time_warning += state_duration;
2148 			break;
2149 		case AS_SVC_UNKNOWN:
2150 			subject->time_unknown += state_duration;
2151 			break;
2152 		case AS_SVC_CRITICAL:
2153 			subject->time_critical += state_duration;
2154 			break;
2155 		default:
2156 			break;
2157 		}
2158 
2159 	return;
2160 	}
2161 
2162 
2163 /* computes downtime data for a given subject */
compute_subject_downtime(avail_subject * subject,time_t current_time)2164 void compute_subject_downtime(avail_subject *subject, time_t current_time) {
2165 	archived_state *temp_sd;
2166 	time_t start_time;
2167 	time_t end_time;
2168 	int host_downtime_depth = 0;
2169 	int service_downtime_depth = 0;
2170 	int process_chunk = FALSE;
2171 
2172 #ifdef DEBUG2
2173 	printf("COMPUTE_SUBJECT_DOWNTIME\n");
2174 #endif
2175 
2176 	/* if left hand of graph is after current time, we can't do anything at all.... */
2177 	if(t1 > current_time)
2178 		return;
2179 
2180 	/* no scheduled downtime data for subject... */
2181 	if(subject->sd_list == NULL)
2182 		return;
2183 
2184 	/* all data we have occurs after last time on graph... */
2185 	if(subject->sd_list->time_stamp >= t2)
2186 		return;
2187 
2188 	/* initialize pointer */
2189 	temp_sd = subject->sd_list;
2190 
2191 	/* special case if first entry is the end of scheduled downtime */
2192 	if((temp_sd->entry_type == AS_HOST_DOWNTIME_END || temp_sd->entry_type == AS_SVC_DOWNTIME_END) && temp_sd->time_stamp > t1) {
2193 
2194 #ifdef DEBUG2
2195 		printf("\tSPECIAL DOWNTIME CASE\n");
2196 #endif
2197 		start_time = t1;
2198 		end_time = (temp_sd->time_stamp > t2) ? t2 : temp_sd->time_stamp;
2199 		compute_subject_downtime_times(start_time, end_time, subject, NULL);
2200 		temp_sd = temp_sd->next;
2201 		}
2202 
2203 	/* process all periods of scheduled downtime */
2204 	for(; temp_sd != NULL; temp_sd = temp_sd->next) {
2205 
2206 		/* we've passed graph bounds... */
2207 		if(temp_sd->time_stamp >= t2)
2208 			break;
2209 
2210 		if(temp_sd->entry_type == AS_HOST_DOWNTIME_START)
2211 			host_downtime_depth++;
2212 		else if(temp_sd->entry_type == AS_HOST_DOWNTIME_END)
2213 			host_downtime_depth--;
2214 		else if(temp_sd->entry_type == AS_SVC_DOWNTIME_START)
2215 			service_downtime_depth++;
2216 		else if(temp_sd->entry_type == AS_SVC_DOWNTIME_END)
2217 			service_downtime_depth--;
2218 		else
2219 			continue;
2220 
2221 		process_chunk = FALSE;
2222 		if(temp_sd->entry_type == AS_HOST_DOWNTIME_START || temp_sd->entry_type == AS_SVC_DOWNTIME_START)
2223 			process_chunk = TRUE;
2224 		else if(subject->type == SERVICE_SUBJECT && (host_downtime_depth > 0 || service_downtime_depth > 0))
2225 			process_chunk = TRUE;
2226 
2227 		/* process this specific "chunk" of scheduled downtime */
2228 		if(process_chunk == TRUE) {
2229 
2230 			start_time = temp_sd->time_stamp;
2231 			end_time = (temp_sd->next == NULL) ? current_time : temp_sd->next->time_stamp;
2232 
2233 			/* check time sanity */
2234 			if(end_time <= t1)
2235 				continue;
2236 			if(start_time >= t2)
2237 				continue;
2238 			if(start_time >= end_time)
2239 				continue;
2240 
2241 			/* clip time values */
2242 			if(start_time < t1)
2243 				start_time = t1;
2244 			if(end_time > t2)
2245 				end_time = t2;
2246 
2247 			compute_subject_downtime_times(start_time, end_time, subject, temp_sd);
2248 			}
2249 		}
2250 
2251 	return;
2252 	}
2253 
2254 
2255 
2256 /* computes downtime times */
compute_subject_downtime_times(time_t start_time,time_t end_time,avail_subject * subject,archived_state * sd)2257 void compute_subject_downtime_times(time_t start_time, time_t end_time, avail_subject *subject, archived_state *sd) {
2258 	archived_state *temp_as = NULL;
2259 	time_t part_start_time = 0L;
2260 	time_t part_subject_state = 0L;
2261 	int saved_status = 0;
2262 	int saved_stamp = 0;
2263 	int count = 0;
2264 	archived_state *temp_before = NULL;
2265 	archived_state *last = NULL;
2266 
2267 #ifdef DEBUG2
2268 	printf("<P><b>ENTERING COMPUTE_SUBJECT_DOWNTIME_TIMES: start=%lu, end=%lu, t1=%lu, t2=%lu </b></P>", start_time, end_time, t1, t2);
2269 #endif
2270 
2271 	/* times are weird, so bail out... */
2272 	if(start_time > end_time)
2273 		return;
2274 	if(start_time < t1 || end_time > t2)
2275 		return;
2276 
2277 	/* find starting point in archived state list */
2278 	if(sd == NULL) {
2279 #ifdef DEBUG2
2280 		printf("<P>TEMP_AS=SUBJECT->AS_LIST </P>");
2281 #endif
2282 		temp_as = subject->as_list;
2283 		}
2284 	else if(sd->misc_ptr == NULL) {
2285 #ifdef DEBUG2
2286 		printf("<P>TEMP_AS=SUBJECT->AS_LIST</P>");
2287 #endif
2288 		temp_as = subject->as_list;
2289 		}
2290 	else if(sd->misc_ptr->next == NULL) {
2291 #ifdef DEBUG2
2292 		printf("<P>TEMP_AS=SD->MISC_PTR</P>");
2293 #endif
2294 		temp_as = sd->misc_ptr;
2295 		}
2296 	else {
2297 #ifdef DEBUG2
2298 		printf("<P>TEMP_AS=SD->MISC_PTR->NEXT</P>");
2299 #endif
2300 		temp_as = sd->misc_ptr->next;
2301 		}
2302 
2303 	/* initialize values */
2304 	part_start_time = start_time;
2305 	if(temp_as == NULL)
2306 		part_subject_state = AS_NO_DATA;
2307 	else if(temp_as->processed_state == AS_PROGRAM_START || temp_as->processed_state == AS_PROGRAM_END || temp_as->processed_state == AS_NO_DATA) {
2308 #ifdef DEBUG2
2309 		printf("<P>ENTRY TYPE #1: %d</P>", temp_as->entry_type);
2310 #endif
2311 		part_subject_state = AS_NO_DATA;
2312 		}
2313 	else {
2314 #ifdef DEBUG2
2315 		printf("<P>ENTRY TYPE #2: %d</P>", temp_as->entry_type);
2316 #endif
2317 		part_subject_state = temp_as->processed_state;
2318 		}
2319 
2320 #ifdef DEBUG2
2321 	printf("<P>TEMP_AS=%s</P>", (temp_as == NULL) ? "NULL" : "Not NULL");
2322 	printf("<P>SD=%s</P>", (sd == NULL) ? "NULL" : "Not NULL");
2323 #endif
2324 
2325 	/* temp_as now points to first event to possibly "break" this chunk */
2326 	for(; temp_as != NULL; temp_as = temp_as->next) {
2327 		count++;
2328 		last = temp_as;
2329 
2330 		if(temp_before == NULL) {
2331 			if(last->time_stamp > start_time) {
2332 				if(last->time_stamp > end_time)
2333 					compute_subject_downtime_part_times(start_time, end_time, part_subject_state, subject);
2334 				else
2335 					compute_subject_downtime_part_times(start_time, last->time_stamp, part_subject_state, subject);
2336 				}
2337 			temp_before = temp_as;
2338 			saved_status = temp_as->entry_type;
2339 			saved_stamp = temp_as->time_stamp;
2340 
2341 			/* check if first time is before schedule downtime */
2342 			if(saved_stamp < start_time)
2343 				saved_stamp = start_time;
2344 
2345 			continue;
2346 			}
2347 
2348 		/* if status changed, we have to calculate */
2349 		if(saved_status != temp_as->entry_type) {
2350 
2351 			/* is outside schedule time, use end schdule downtime */
2352 			if(temp_as->time_stamp > end_time) {
2353 				if(saved_stamp < start_time)
2354 					compute_subject_downtime_part_times(start_time, end_time, saved_status, subject);
2355 				else
2356 					compute_subject_downtime_part_times(saved_stamp, end_time, saved_status, subject);
2357 				}
2358 			else {
2359 				if(saved_stamp < start_time)
2360 					compute_subject_downtime_part_times(start_time, temp_as->time_stamp, saved_status, subject);
2361 				else
2362 					compute_subject_downtime_part_times(saved_stamp, temp_as->time_stamp, saved_status, subject);
2363 				}
2364 			saved_status = temp_as->entry_type;
2365 			saved_stamp = temp_as->time_stamp;
2366 			}
2367 		}
2368 
2369 	/* just one entry inside the scheduled downtime */
2370 	if(count == 0)
2371 		compute_subject_downtime_part_times(start_time, end_time, part_subject_state, subject);
2372 	else {
2373 		/* is outside scheduled time, use end schdule downtime */
2374 		if(last->time_stamp > end_time)
2375 			compute_subject_downtime_part_times(saved_stamp, end_time, saved_status, subject);
2376 		else
2377 			compute_subject_downtime_part_times(saved_stamp, last->time_stamp, saved_status, subject);
2378 		}
2379 
2380 	return;
2381 	}
2382 
2383 
2384 
2385 /* computes downtime times */
compute_subject_downtime_part_times(time_t start_time,time_t end_time,int subject_state,avail_subject * subject)2386 void compute_subject_downtime_part_times(time_t start_time, time_t end_time, int subject_state, avail_subject *subject) {
2387 	unsigned long state_duration;
2388 
2389 #ifdef DEBUG2
2390 	printf("ENTERING COMPUTE_SUBJECT_DOWNTIME_PART_TIMES\n");
2391 #endif
2392 
2393 	/* times are weird */
2394 	if(start_time > end_time)
2395 		return;
2396 
2397 	state_duration = (unsigned long)(end_time - start_time);
2398 
2399 	switch(subject_state) {
2400 		case AS_HOST_UP:
2401 			subject->scheduled_time_up += state_duration;
2402 			break;
2403 		case AS_HOST_DOWN:
2404 			subject->scheduled_time_down += state_duration;
2405 			break;
2406 		case AS_HOST_UNREACHABLE:
2407 			subject->scheduled_time_unreachable += state_duration;
2408 			break;
2409 		case AS_SVC_OK:
2410 			subject->scheduled_time_ok += state_duration;
2411 			break;
2412 		case AS_SVC_WARNING:
2413 			subject->scheduled_time_warning += state_duration;
2414 			break;
2415 		case AS_SVC_UNKNOWN:
2416 			subject->scheduled_time_unknown += state_duration;
2417 			break;
2418 		case AS_SVC_CRITICAL:
2419 			subject->scheduled_time_critical += state_duration;
2420 			break;
2421 		default:
2422 			subject->scheduled_time_indeterminate += state_duration;
2423 			break;
2424 		}
2425 
2426 #ifdef DEBUG2
2427 	printf("\tSUBJECT DOWNTIME: Host '%s', Service '%s', State=%d, Duration=%lu, Start=%lu\n", subject->host_name, (subject->service_description == NULL) ? "NULL" : subject->service_description, subject_state, state_duration, start_time);
2428 #endif
2429 
2430 	return;
2431 	}
2432 
2433 
2434 
2435 /* convert current host state to archived state value */
convert_host_state_to_archived_state(int current_status)2436 int convert_host_state_to_archived_state(int current_status) {
2437 
2438 	if(current_status == HOST_UP)
2439 		return AS_HOST_UP;
2440 	if(current_status == HOST_DOWN)
2441 		return AS_HOST_DOWN;
2442 	if(current_status == HOST_UNREACHABLE)
2443 		return AS_HOST_UNREACHABLE;
2444 
2445 	return AS_NO_DATA;
2446 	}
2447 
2448 
2449 /* convert current service state to archived state value */
convert_service_state_to_archived_state(int current_status)2450 int convert_service_state_to_archived_state(int current_status) {
2451 
2452 	if(current_status == SERVICE_OK)
2453 		return AS_SVC_OK;
2454 	if(current_status == SERVICE_UNKNOWN)
2455 		return AS_SVC_UNKNOWN;
2456 	if(current_status == SERVICE_WARNING)
2457 		return AS_SVC_WARNING;
2458 	if(current_status == SERVICE_CRITICAL)
2459 		return AS_SVC_CRITICAL;
2460 
2461 	return AS_NO_DATA;
2462 	}
2463 
2464 
2465 
2466 /* create list of subjects to collect availability data for */
create_subject_list(void)2467 void create_subject_list(void) {
2468 	hostgroup *temp_hostgroup;
2469 	hostsmember *temp_hgmember;
2470 	servicegroup *temp_servicegroup;
2471 	servicesmember *temp_sgmember;
2472 	host *temp_host;
2473 	service *temp_service;
2474 	char *last_host_name = "";
2475 
2476 	/* we're displaying one or more hosts */
2477 	if(display_type == DISPLAY_HOST_AVAIL && host_name && strcmp(host_name, "")) {
2478 
2479 		/* we're only displaying a specific host (and summaries for all services associated with it) */
2480 		if(show_all_hosts == FALSE) {
2481 			add_subject(HOST_SUBJECT, host_name, NULL);
2482 			for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
2483 				if(!strcmp(temp_service->host_name, host_name))
2484 					add_subject(SERVICE_SUBJECT, host_name, temp_service->description);
2485 				}
2486 			}
2487 
2488 		/* we're displaying all hosts */
2489 		else {
2490 			for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next)
2491 				add_subject(HOST_SUBJECT, temp_host->name, NULL);
2492 			}
2493 		}
2494 
2495 	/* we're displaying a specific service */
2496 	else if(display_type == DISPLAY_SERVICE_AVAIL && svc_description && strcmp(svc_description, "")) {
2497 
2498 		/* we're only displaying a specific service */
2499 		if(show_all_services == FALSE)
2500 			add_subject(SERVICE_SUBJECT, host_name, svc_description);
2501 
2502 		/* we're displaying all services */
2503 		else {
2504 			for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next)
2505 				add_subject(SERVICE_SUBJECT, temp_service->host_name, temp_service->description);
2506 			}
2507 		}
2508 
2509 	/* we're displaying one or more hostgroups (the host members of the groups) */
2510 	else if(display_type == DISPLAY_HOSTGROUP_AVAIL && hostgroup_name && strcmp(hostgroup_name, "")) {
2511 
2512 		/* we're displaying all hostgroups */
2513 		if(show_all_hostgroups == TRUE) {
2514 			for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
2515 				for(temp_hgmember = temp_hostgroup->members; temp_hgmember != NULL; temp_hgmember = temp_hgmember->next)
2516 					add_subject(HOST_SUBJECT, temp_hgmember->host_name, NULL);
2517 				}
2518 			}
2519 		/* we're only displaying a specific hostgroup */
2520 		else {
2521 			temp_hostgroup = find_hostgroup(hostgroup_name);
2522 			if(temp_hostgroup != NULL) {
2523 				for(temp_hgmember = temp_hostgroup->members; temp_hgmember != NULL; temp_hgmember = temp_hgmember->next)
2524 					add_subject(HOST_SUBJECT, temp_hgmember->host_name, NULL);
2525 				}
2526 			}
2527 		}
2528 
2529 	/* we're displaying one or more servicegroups (the host and service members of the groups) */
2530 	else if(display_type == DISPLAY_SERVICEGROUP_AVAIL && servicegroup_name && strcmp(servicegroup_name, "")) {
2531 
2532 		/* we're displaying all servicegroups */
2533 		if(show_all_servicegroups == TRUE) {
2534 			for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
2535 				for(temp_sgmember = temp_servicegroup->members; temp_sgmember != NULL; temp_sgmember = temp_sgmember->next) {
2536 					add_subject(SERVICE_SUBJECT, temp_sgmember->host_name, temp_sgmember->service_description);
2537 					if(strcmp(last_host_name, temp_sgmember->host_name))
2538 						add_subject(HOST_SUBJECT, temp_sgmember->host_name, NULL);
2539 					last_host_name = temp_sgmember->host_name;
2540 					}
2541 				}
2542 			}
2543 		/* we're only displaying a specific servicegroup */
2544 		else {
2545 			temp_servicegroup = find_servicegroup(servicegroup_name);
2546 			if(temp_servicegroup != NULL) {
2547 				for(temp_sgmember = temp_servicegroup->members; temp_sgmember != NULL; temp_sgmember = temp_sgmember->next) {
2548 					add_subject(SERVICE_SUBJECT, temp_sgmember->host_name, temp_sgmember->service_description);
2549 					if(strcmp(last_host_name, temp_sgmember->host_name))
2550 						add_subject(HOST_SUBJECT, temp_sgmember->host_name, NULL);
2551 					last_host_name = temp_sgmember->host_name;
2552 					}
2553 				}
2554 			}
2555 		}
2556 
2557 	return;
2558 	}
2559 
2560 
2561 
2562 /* adds a subject */
add_subject(int subject_type,char * hn,char * sd)2563 void add_subject(int subject_type, char *hn, char *sd) {
2564 	avail_subject *last_subject = NULL;
2565 	avail_subject *temp_subject = NULL;
2566 	avail_subject *new_subject = NULL;
2567 	int is_authorized = FALSE;
2568 
2569 	/* bail if we've already added the subject */
2570 	if(find_subject(subject_type, hn, sd))
2571 		return;
2572 
2573 	/* see if the user is authorized to see data for this host or service */
2574 	if(subject_type == HOST_SUBJECT)
2575 		is_authorized = is_authorized_for_host(find_host(hn), &current_authdata);
2576 	else
2577 		is_authorized = is_authorized_for_service(find_service(hn, sd), &current_authdata);
2578 	if(is_authorized == FALSE)
2579 		return;
2580 
2581 	/* allocate memory for the new entry */
2582 	new_subject = (avail_subject *)malloc(sizeof(avail_subject));
2583 	if(new_subject == NULL)
2584 		return;
2585 
2586 	/* allocate memory for the host name */
2587 	if(hn != NULL) {
2588 		new_subject->host_name = (char *)malloc(strlen(hn) + 1);
2589 		if(new_subject->host_name != NULL)
2590 			strcpy(new_subject->host_name, hn);
2591 		}
2592 	else
2593 		new_subject->host_name = NULL;
2594 
2595 	/* allocate memory for the service description */
2596 	if(sd != NULL) {
2597 		new_subject->service_description = (char *)malloc(strlen(sd) + 1);
2598 		if(new_subject->service_description != NULL)
2599 			strcpy(new_subject->service_description, sd);
2600 		}
2601 	else
2602 		new_subject->service_description = NULL;
2603 
2604 	new_subject->type = subject_type;
2605 	new_subject->earliest_state = AS_NO_DATA;
2606 	new_subject->latest_state = AS_NO_DATA;
2607 	new_subject->time_up = 0L;
2608 	new_subject->time_down = 0L;
2609 	new_subject->time_unreachable = 0L;
2610 	new_subject->time_ok = 0L;
2611 	new_subject->time_warning = 0L;
2612 	new_subject->time_unknown = 0L;
2613 	new_subject->time_critical = 0L;
2614 	new_subject->scheduled_time_up = 0L;
2615 	new_subject->scheduled_time_down = 0L;
2616 	new_subject->scheduled_time_unreachable = 0L;
2617 	new_subject->scheduled_time_ok = 0L;
2618 	new_subject->scheduled_time_warning = 0L;
2619 	new_subject->scheduled_time_unknown = 0L;
2620 	new_subject->scheduled_time_critical = 0L;
2621 	new_subject->scheduled_time_indeterminate = 0L;
2622 	new_subject->time_indeterminate_nodata = 0L;
2623 	new_subject->time_indeterminate_notrunning = 0L;
2624 	new_subject->as_list = NULL;
2625 	new_subject->as_list_tail = NULL;
2626 	new_subject->sd_list = NULL;
2627 	new_subject->last_known_state = AS_NO_DATA;
2628 
2629 	/* add the new entry to the list in memory, sorted by host name */
2630 	last_subject = subject_list;
2631 	for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
2632 		if(strcmp(new_subject->host_name, temp_subject->host_name) < 0) {
2633 			new_subject->next = temp_subject;
2634 			if(temp_subject == subject_list)
2635 				subject_list = new_subject;
2636 			else
2637 				last_subject->next = new_subject;
2638 			break;
2639 			}
2640 		else
2641 			last_subject = temp_subject;
2642 		}
2643 	if(subject_list == NULL) {
2644 		new_subject->next = NULL;
2645 		subject_list = new_subject;
2646 		}
2647 	else if(temp_subject == NULL) {
2648 		new_subject->next = NULL;
2649 		last_subject->next = new_subject;
2650 		}
2651 
2652 	return;
2653 	}
2654 
2655 
2656 
2657 /* finds a specific subject */
find_subject(int type,char * hn,char * sd)2658 avail_subject *find_subject(int type, char *hn, char *sd) {
2659 	avail_subject *temp_subject;
2660 
2661 	if(hn == NULL)
2662 		return NULL;
2663 
2664 	if(type == SERVICE_SUBJECT && sd == NULL)
2665 		return NULL;
2666 
2667 	for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
2668 		if(temp_subject->type != type)
2669 			continue;
2670 		if(strcmp(hn, temp_subject->host_name))
2671 			continue;
2672 		if(type == SERVICE_SUBJECT && strcmp(sd, temp_subject->service_description))
2673 			continue;
2674 		return temp_subject;
2675 		}
2676 
2677 	return NULL;
2678 	}
2679 
2680 
2681 
2682 /* adds an archived state entry to all subjects */
add_global_archived_state(int entry_type,int state_type,time_t time_stamp,char * state_info)2683 void add_global_archived_state(int entry_type, int state_type, time_t time_stamp, char *state_info) {
2684 	avail_subject *temp_subject;
2685 
2686 	for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next)
2687 		add_archived_state(entry_type, state_type, time_stamp, state_info, temp_subject);
2688 
2689 	return;
2690 	}
2691 
2692 
2693 
2694 
2695 /* adds an archived state entry to a specific subject */
add_archived_state(int entry_type,int state_type,time_t time_stamp,char * state_info,avail_subject * subject)2696 void add_archived_state(int entry_type, int state_type, time_t time_stamp, char *state_info, avail_subject *subject) {
2697 	archived_state *last_as = NULL;
2698 	archived_state *temp_as = NULL;
2699 	archived_state *new_as = NULL;
2700 
2701 	/* allocate memory for the new entry */
2702 	new_as = (archived_state *)malloc(sizeof(archived_state));
2703 	if(new_as == NULL)
2704 		return;
2705 
2706 	/* allocate memory for the state info */
2707 	if(state_info != NULL) {
2708 		new_as->state_info = (char *)malloc(strlen(state_info) + 1);
2709 		if(new_as->state_info != NULL)
2710 			strcpy(new_as->state_info, state_info);
2711 		}
2712 	else new_as->state_info = NULL;
2713 
2714 	/* initialize the "processed state" value - this gets modified later for most entries */
2715 	if(entry_type != AS_PROGRAM_START && entry_type != AS_PROGRAM_END && entry_type != AS_NO_DATA)
2716 		new_as->processed_state = entry_type;
2717 	else
2718 		new_as->processed_state = AS_NO_DATA;
2719 
2720 	new_as->entry_type = entry_type;
2721 	new_as->state_type = state_type;
2722 	new_as->time_stamp = time_stamp;
2723 	new_as->misc_ptr = NULL;
2724 
2725 	/* add the new entry to the list in memory, sorted by time (more recent entries should appear towards end of list) */
2726 	last_as = subject->as_list;
2727 	for(temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
2728 		if(new_as->time_stamp < temp_as->time_stamp) {
2729 			new_as->next = temp_as;
2730 			if(temp_as == subject->as_list)
2731 				subject->as_list = new_as;
2732 			else
2733 				last_as->next = new_as;
2734 			break;
2735 			}
2736 		else
2737 			last_as = temp_as;
2738 		}
2739 	if(subject->as_list == NULL) {
2740 		new_as->next = NULL;
2741 		subject->as_list = new_as;
2742 		}
2743 	else if(temp_as == NULL) {
2744 		new_as->next = NULL;
2745 		last_as->next = new_as;
2746 		}
2747 
2748 	/* update "tail" of the list - not really the tail, just last item added */
2749 	subject->as_list_tail = new_as;
2750 
2751 	return;
2752 	}
2753 
2754 
2755 /* adds a scheduled downtime entry to a specific subject */
add_scheduled_downtime(int state_type,time_t time_stamp,avail_subject * subject)2756 void add_scheduled_downtime(int state_type, time_t time_stamp, avail_subject *subject) {
2757 	archived_state *last_sd = NULL;
2758 	archived_state *temp_sd = NULL;
2759 	archived_state *new_sd = NULL;
2760 
2761 	/* allocate memory for the new entry */
2762 	new_sd = (archived_state *)malloc(sizeof(archived_state));
2763 	if(new_sd == NULL)
2764 		return;
2765 
2766 	new_sd->state_info = NULL;
2767 	new_sd->processed_state = state_type;
2768 	new_sd->entry_type = state_type;
2769 	new_sd->time_stamp = time_stamp;
2770 	new_sd->misc_ptr = subject->as_list_tail;
2771 
2772 	/* add the new entry to the list in memory, sorted by time (more recent entries should appear towards end of list) */
2773 	last_sd = subject->sd_list;
2774 	for(temp_sd = subject->sd_list; temp_sd != NULL; temp_sd = temp_sd->next) {
2775 		if(new_sd->time_stamp <= temp_sd->time_stamp) {
2776 			new_sd->next = temp_sd;
2777 			if(temp_sd == subject->sd_list)
2778 				subject->sd_list = new_sd;
2779 			else
2780 				last_sd->next = new_sd;
2781 			break;
2782 			}
2783 		else
2784 			last_sd = temp_sd;
2785 		}
2786 	if(subject->sd_list == NULL) {
2787 		new_sd->next = NULL;
2788 		subject->sd_list = new_sd;
2789 		}
2790 	else if(temp_sd == NULL) {
2791 		new_sd->next = NULL;
2792 		last_sd->next = new_sd;
2793 		}
2794 
2795 	return;
2796 	}
2797 
2798 
2799 /* frees memory allocated to all availability data */
free_availability_data(void)2800 void free_availability_data(void) {
2801 	avail_subject *this_subject;
2802 	avail_subject *next_subject;
2803 
2804 	for(this_subject = subject_list; this_subject != NULL;) {
2805 		next_subject = this_subject->next;
2806 		if(this_subject->host_name != NULL)
2807 			free(this_subject->host_name);
2808 		if(this_subject->service_description != NULL)
2809 			free(this_subject->service_description);
2810 		free_archived_state_list(this_subject->as_list);
2811 		free_archived_state_list(this_subject->sd_list);
2812 		free(this_subject);
2813 		this_subject = next_subject;
2814 		}
2815 
2816 	return;
2817 	}
2818 
2819 /* frees memory allocated to the archived state list */
free_archived_state_list(archived_state * as_list)2820 void free_archived_state_list(archived_state *as_list) {
2821 	archived_state *this_as = NULL;
2822 	archived_state *next_as = NULL;
2823 
2824 	for(this_as = as_list; this_as != NULL;) {
2825 		next_as = this_as->next;
2826 		if(this_as->state_info != NULL)
2827 			free(this_as->state_info);
2828 		free(this_as);
2829 		this_as = next_as;
2830 		}
2831 
2832 	as_list = NULL;
2833 
2834 	return;
2835 	}
2836 
2837 
2838 
2839 /* reads log files for archived state data */
read_archived_state_data(void)2840 void read_archived_state_data(void) {
2841 	char filename[MAX_FILENAME_LENGTH];
2842 	int oldest_archive = 0;
2843 	int newest_archive = 0;
2844 	int current_archive = 0;
2845 
2846 	/* determine oldest archive to use when scanning for data (include backtracked archives as well) */
2847 	oldest_archive = determine_archive_to_use_from_time(t1);
2848 	if(log_rotation_method != LOG_ROTATION_NONE)
2849 		oldest_archive += backtrack_archives;
2850 
2851 	/* determine most recent archive to use when scanning for data */
2852 	newest_archive = determine_archive_to_use_from_time(t2);
2853 
2854 	if(oldest_archive < newest_archive)
2855 		oldest_archive = newest_archive;
2856 
2857 	/* read in all the necessary archived logs (from most recent to earliest) */
2858 	for(current_archive = newest_archive; current_archive <= oldest_archive; current_archive++) {
2859 
2860 #ifdef DEBUG
2861 		printf("Reading archive #%d\n", current_archive);
2862 #endif
2863 
2864 		/* get the name of the log file that contains this archive */
2865 		get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1);
2866 
2867 #ifdef DEBUG
2868 		printf("Archive name: '%s'\n", filename);
2869 #endif
2870 
2871 		/* scan the log file for archived state data */
2872 		scan_log_file_for_archived_state_data(filename);
2873 		}
2874 
2875 	return;
2876 	}
2877 
2878 
2879 
2880 /* grabs archives state data from a log file */
scan_log_file_for_archived_state_data(char * filename)2881 void scan_log_file_for_archived_state_data(char *filename) {
2882 	char *input = NULL;
2883 	char *input2 = NULL;
2884 	char entry_host_name[MAX_INPUT_BUFFER];
2885 	char entry_svc_description[MAX_INPUT_BUFFER];
2886 	char *plugin_output = NULL;
2887 	char *temp_buffer = NULL;
2888 	time_t time_stamp;
2889 	mmapfile *thefile = NULL;
2890 	avail_subject *temp_subject = NULL;
2891 	int state_type = 0;
2892 
2893 	if((thefile = mmap_fopen(filename)) == NULL)
2894 		return;
2895 
2896 	while(1) {
2897 
2898 		/* free memory */
2899 		free(input);
2900 		free(input2);
2901 		input = NULL;
2902 		input2 = NULL;
2903 
2904 		/* read the next line */
2905 		if((input = mmap_fgets(thefile)) == NULL)
2906 			break;
2907 
2908 		strip(input);
2909 
2910 		if((input2 = strdup(input)) == NULL)
2911 			continue;
2912 
2913 		temp_buffer = my_strtok(input2, "]");
2914 		time_stamp = (temp_buffer == NULL) ? (time_t)0 : (time_t)strtoul(temp_buffer + 1, NULL, 10);
2915 
2916 		/* program starts/restarts */
2917 		if(strstr(input, " starting..."))
2918 			add_global_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program start");
2919 		if(strstr(input, " restarting..."))
2920 			add_global_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program restart");
2921 
2922 		/* program stops */
2923 		if(strstr(input, " shutting down..."))
2924 			add_global_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Normal program termination");
2925 		if(strstr(input, "Bailing out"))
2926 			add_global_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Abnormal program termination");
2927 
2928 		if(display_type == DISPLAY_HOST_AVAIL || display_type == DISPLAY_HOSTGROUP_AVAIL || display_type == DISPLAY_SERVICEGROUP_AVAIL) {
2929 
2930 			/* normal host alerts and initial/current states */
2931 			if(strstr(input, "HOST ALERT:") || strstr(input, "INITIAL HOST STATE:") || strstr(input, "CURRENT HOST STATE:")) {
2932 
2933 				/* get host name */
2934 				temp_buffer = my_strtok(NULL, ":");
2935 				temp_buffer = my_strtok(NULL, ";");
2936 				strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2937 				entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2938 
2939 				/* see if there is a corresponding subject for this host */
2940 				temp_subject = find_subject(HOST_SUBJECT, entry_host_name, NULL);
2941 				if(temp_subject == NULL)
2942 					continue;
2943 
2944 				/* state types */
2945 				if(strstr(input, ";SOFT;")) {
2946 					if(include_soft_states == FALSE)
2947 						continue;
2948 					state_type = AS_SOFT_STATE;
2949 					}
2950 				if(strstr(input, ";HARD;"))
2951 					state_type = AS_HARD_STATE;
2952 
2953 				/* get the plugin output */
2954 				temp_buffer = my_strtok(NULL, ";");
2955 				temp_buffer = my_strtok(NULL, ";");
2956 				temp_buffer = my_strtok(NULL, ";");
2957 				plugin_output = my_strtok(NULL, "\n");
2958 
2959 				if(strstr(input, ";DOWN;"))
2960 					add_archived_state(AS_HOST_DOWN, state_type, time_stamp, plugin_output, temp_subject);
2961 				else if(strstr(input, ";UNREACHABLE;"))
2962 					add_archived_state(AS_HOST_UNREACHABLE, state_type, time_stamp, plugin_output, temp_subject);
2963 				else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;"))
2964 					add_archived_state(AS_HOST_UP, state_type, time_stamp, plugin_output, temp_subject);
2965 				else
2966 					add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output, temp_subject);
2967 				}
2968 
2969 			/* scheduled downtime notices */
2970 			else if(strstr(input, "HOST DOWNTIME ALERT:")) {
2971 
2972 				/* get host name */
2973 				temp_buffer = my_strtok(NULL, ":");
2974 				temp_buffer = my_strtok(NULL, ";");
2975 				strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2976 				entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2977 
2978 				/* see if there is a corresponding subject for this host */
2979 				temp_subject = find_subject(HOST_SUBJECT, entry_host_name, NULL);
2980 				if(temp_subject == NULL)
2981 					continue;
2982 
2983 				if(show_scheduled_downtime == FALSE)
2984 					continue;
2985 
2986 				if(strstr(input, ";STARTED;"))
2987 					add_scheduled_downtime(AS_HOST_DOWNTIME_START, time_stamp, temp_subject);
2988 				else
2989 					add_scheduled_downtime(AS_HOST_DOWNTIME_END, time_stamp, temp_subject);
2990 
2991 				}
2992 			}
2993 
2994 		if(display_type == DISPLAY_SERVICE_AVAIL || display_type == DISPLAY_HOST_AVAIL || display_type == DISPLAY_SERVICEGROUP_AVAIL) {
2995 
2996 			/* normal service alerts and initial/current states */
2997 			if(strstr(input, "SERVICE ALERT:") || strstr(input, "INITIAL SERVICE STATE:") || strstr(input, "CURRENT SERVICE STATE:")) {
2998 
2999 				/* get host name */
3000 				temp_buffer = my_strtok(NULL, ":");
3001 				temp_buffer = my_strtok(NULL, ";");
3002 				strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
3003 				entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
3004 
3005 				/* get service description */
3006 				temp_buffer = my_strtok(NULL, ";");
3007 				strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(entry_svc_description));
3008 				entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
3009 
3010 				/* see if there is a corresponding subject for this service */
3011 				temp_subject = find_subject(SERVICE_SUBJECT, entry_host_name, entry_svc_description);
3012 				if(temp_subject == NULL)
3013 					continue;
3014 
3015 				/* state types */
3016 				if(strstr(input, ";SOFT;")) {
3017 					if(include_soft_states == FALSE)
3018 						continue;
3019 					state_type = AS_SOFT_STATE;
3020 					}
3021 				if(strstr(input, ";HARD;"))
3022 					state_type = AS_HARD_STATE;
3023 
3024 				/* get the plugin output */
3025 				temp_buffer = my_strtok(NULL, ";");
3026 				temp_buffer = my_strtok(NULL, ";");
3027 				temp_buffer = my_strtok(NULL, ";");
3028 				plugin_output = my_strtok(NULL, "\n");
3029 
3030 				if(strstr(input, ";CRITICAL;"))
3031 					add_archived_state(AS_SVC_CRITICAL, state_type, time_stamp, plugin_output, temp_subject);
3032 				else if(strstr(input, ";WARNING;"))
3033 					add_archived_state(AS_SVC_WARNING, state_type, time_stamp, plugin_output, temp_subject);
3034 				else if(strstr(input, ";UNKNOWN;"))
3035 					add_archived_state(AS_SVC_UNKNOWN, state_type, time_stamp, plugin_output, temp_subject);
3036 				else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))
3037 					add_archived_state(AS_SVC_OK, state_type, time_stamp, plugin_output, temp_subject);
3038 				else
3039 					add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output, temp_subject);
3040 
3041 				}
3042 
3043 			/* scheduled service downtime notices */
3044 			else if(strstr(input, "SERVICE DOWNTIME ALERT:")) {
3045 
3046 				/* get host name */
3047 				temp_buffer = my_strtok(NULL, ":");
3048 				temp_buffer = my_strtok(NULL, ";");
3049 				strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
3050 				entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
3051 
3052 				/* get service description */
3053 				temp_buffer = my_strtok(NULL, ";");
3054 				strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(entry_svc_description));
3055 				entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
3056 
3057 				/* see if there is a corresponding subject for this service */
3058 				temp_subject = find_subject(SERVICE_SUBJECT, entry_host_name, entry_svc_description);
3059 				if(temp_subject == NULL)
3060 					continue;
3061 
3062 				if(show_scheduled_downtime == FALSE)
3063 					continue;
3064 
3065 				if(strstr(input, ";STARTED;"))
3066 					add_scheduled_downtime(AS_SVC_DOWNTIME_START, time_stamp, temp_subject);
3067 				else
3068 					add_scheduled_downtime(AS_SVC_DOWNTIME_END, time_stamp, temp_subject);
3069 				}
3070 
3071 			/* scheduled host downtime notices */
3072 			else if(strstr(input, "HOST DOWNTIME ALERT:")) {
3073 
3074 				/* get host name */
3075 				temp_buffer = my_strtok(NULL, ":");
3076 				temp_buffer = my_strtok(NULL, ";");
3077 				strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
3078 				entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
3079 
3080 				/* this host downtime entry must be added to all service subjects associated with the host! */
3081 				for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
3082 
3083 					if(temp_subject->type != SERVICE_SUBJECT)
3084 						continue;
3085 
3086 					if(strcmp(temp_subject->host_name, entry_host_name))
3087 						continue;
3088 
3089 					if(show_scheduled_downtime == FALSE)
3090 						continue;
3091 
3092 					if(strstr(input, ";STARTED;"))
3093 						add_scheduled_downtime(AS_HOST_DOWNTIME_START, time_stamp, temp_subject);
3094 					else
3095 						add_scheduled_downtime(AS_HOST_DOWNTIME_END, time_stamp, temp_subject);
3096 					}
3097 				}
3098 			}
3099 
3100 		}
3101 
3102 	/* free memory and close the file */
3103 	free(input);
3104 	free(input2);
3105 	mmap_fclose(thefile);
3106 
3107 	return;
3108 	}
3109 
3110 
3111 
3112 
convert_timeperiod_to_times(int type)3113 void convert_timeperiod_to_times(int type) {
3114 	time_t current_time;
3115 	struct tm *t;
3116 
3117 	/* get the current time */
3118 	time(&current_time);
3119 
3120 	t = localtime(&current_time);
3121 
3122 	t->tm_sec = 0;
3123 	t->tm_min = 0;
3124 	t->tm_hour = 0;
3125 	t->tm_isdst = -1;
3126 
3127 	switch(type) {
3128 		case TIMEPERIOD_LAST24HOURS:
3129 			t1 = current_time - (60 * 60 * 24);
3130 			t2 = current_time;
3131 			break;
3132 		case TIMEPERIOD_TODAY:
3133 			t1 = mktime(t);
3134 			t2 = current_time;
3135 			break;
3136 		case TIMEPERIOD_YESTERDAY:
3137 			t1 = (time_t)(mktime(t) - (60 * 60 * 24));
3138 			t2 = (time_t)mktime(t);
3139 			break;
3140 		case TIMEPERIOD_THISWEEK:
3141 			t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
3142 			t2 = current_time;
3143 			break;
3144 		case TIMEPERIOD_LASTWEEK:
3145 			t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday) - (60 * 60 * 24 * 7));
3146 			t2 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
3147 			break;
3148 		case TIMEPERIOD_THISMONTH:
3149 			t->tm_mday = 1;
3150 			t1 = mktime(t);
3151 			t2 = current_time;
3152 			break;
3153 		case TIMEPERIOD_LASTMONTH:
3154 			t->tm_mday = 1;
3155 			t2 = mktime(t);
3156 			if(t->tm_mon == 0) {
3157 				t->tm_mon = 11;
3158 				t->tm_year--;
3159 				}
3160 			else
3161 				t->tm_mon--;
3162 			t1 = mktime(t);
3163 			break;
3164 		case TIMEPERIOD_THISQUARTER:
3165 			/* not implemented */
3166 			break;
3167 		case TIMEPERIOD_LASTQUARTER:
3168 			/* not implemented */
3169 			break;
3170 		case TIMEPERIOD_THISYEAR:
3171 			t->tm_mon = 0;
3172 			t->tm_mday = 1;
3173 			t1 = mktime(t);
3174 			t2 = current_time;
3175 			break;
3176 		case TIMEPERIOD_LASTYEAR:
3177 			t->tm_mon = 0;
3178 			t->tm_mday = 1;
3179 			t2 = mktime(t);
3180 			t->tm_year--;
3181 			t1 = mktime(t);
3182 			break;
3183 		case TIMEPERIOD_LAST7DAYS:
3184 			t2 = current_time;
3185 			t1 = current_time - (7 * 24 * 60 * 60);
3186 			break;
3187 		case TIMEPERIOD_LAST31DAYS:
3188 			t2 = current_time;
3189 			t1 = current_time - (31 * 24 * 60 * 60);
3190 			break;
3191 		default:
3192 			break;
3193 		}
3194 
3195 	return;
3196 	}
3197 
3198 
3199 
compute_report_times(void)3200 void compute_report_times(void) {
3201 	time_t current_time;
3202 	struct tm *st;
3203 	struct tm *et;
3204 
3205 	/* get the current time */
3206 	time(&current_time);
3207 
3208 	st = localtime(&current_time);
3209 
3210 	st->tm_sec = start_second;
3211 	st->tm_min = start_minute;
3212 	st->tm_hour = start_hour;
3213 	st->tm_mday = start_day;
3214 	st->tm_mon = start_month - 1;
3215 	st->tm_year = start_year - 1900;
3216 	st->tm_isdst = -1;
3217 
3218 	t1 = mktime(st);
3219 
3220 	et = localtime(&current_time);
3221 
3222 	et->tm_sec = end_second;
3223 	et->tm_min = end_minute;
3224 	et->tm_hour = end_hour;
3225 	et->tm_mday = end_day;
3226 	et->tm_mon = end_month - 1;
3227 	et->tm_year = end_year - 1900;
3228 	et->tm_isdst = -1;
3229 
3230 	t2 = mktime(et);
3231 	}
3232 
3233 
3234 /* writes log entries to screen */
write_log_entries(avail_subject * subject)3235 void write_log_entries(avail_subject *subject) {
3236 	archived_state *temp_as;
3237 	archived_state *temp_sd;
3238 	time_t current_time;
3239 	char start_date_time[MAX_DATETIME_LENGTH];
3240 	char end_date_time[MAX_DATETIME_LENGTH];
3241 	char duration[20];
3242 	char *bgclass = "";
3243 	char *ebgclass = "";
3244 	char *entry_type = "";
3245 	char *state_type = "";
3246 	int days;
3247 	int hours;
3248 	int minutes;
3249 	int seconds;
3250 	int odd = 0;
3251 
3252 
3253 	if(output_format != HTML_OUTPUT)
3254 		return;
3255 
3256 	if(show_log_entries == FALSE)
3257 		return;
3258 
3259 	if(subject == NULL)
3260 		return;
3261 
3262 	time(&current_time);
3263 
3264 	/* inject all scheduled downtime entries into the main list for display purposes */
3265 	for(temp_sd = subject->sd_list; temp_sd != NULL; temp_sd = temp_sd->next) {
3266 		switch(temp_sd->entry_type) {
3267 			case AS_SVC_DOWNTIME_START:
3268 			case AS_HOST_DOWNTIME_START:
3269 				entry_type = "Start of scheduled downtime";
3270 				break;
3271 			case AS_SVC_DOWNTIME_END:
3272 			case AS_HOST_DOWNTIME_END:
3273 				entry_type = "End of scheduled downtime";
3274 				break;
3275 			default:
3276 				entry_type = "?";
3277 				break;
3278 			}
3279 		add_archived_state(temp_sd->entry_type, AS_NO_DATA, temp_sd->time_stamp, entry_type, subject);
3280 		}
3281 
3282 
3283 	printf("<BR><BR>\n");
3284 
3285 	printf("<DIV ALIGN=CENTER CLASS='dataTitle'>%s Log Entries:</DIV>\n", (subject->type == HOST_SUBJECT) ? "Host" : "Service");
3286 
3287 	printf("<DIV ALIGN=CENTER CLASS='infoMessage'>");
3288 	if(full_log_entries == TRUE) {
3289 		full_log_entries = FALSE;
3290 		if(subject->type == HOST_SUBJECT)
3291 			host_report_url(subject->host_name, "[ View condensed log entries ]");
3292 		else
3293 			service_report_url(subject->host_name, subject->service_description, "[ View condensed log entries ]");
3294 		full_log_entries = TRUE;
3295 		}
3296 	else {
3297 		full_log_entries = TRUE;
3298 		if(subject->type == HOST_SUBJECT)
3299 			host_report_url(subject->host_name, "[ View full log entries ]");
3300 		else
3301 			service_report_url(subject->host_name, subject->service_description, "[ View full log entries ]");
3302 		full_log_entries = FALSE;
3303 		}
3304 	printf("</DIV>\n");
3305 
3306 	printf("<DIV ALIGN=CENTER>\n");
3307 
3308 	printf("<table border=1 cellspacing=0 cellpadding=3 class='logEntries'>\n");
3309 	printf("<tr><th class='logEntries'>Event Start Time</th><th class='logEntries'>Event End Time</th><th class='logEntries'>Event Duration</th><th class='logEntries'>Event/State Type</th><th class='logEntries'>Event/State Information</th></tr>\n");
3310 
3311 	/* write all archived state entries */
3312 	for(temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
3313 
3314 		if(temp_as->state_type == AS_HARD_STATE)
3315 			state_type = " (HARD)";
3316 		else if(temp_as->state_type == AS_SOFT_STATE)
3317 			state_type = " (SOFT)";
3318 		else
3319 			state_type = "";
3320 
3321 		switch(temp_as->entry_type) {
3322 			case AS_NO_DATA:
3323 				if(full_log_entries == FALSE)
3324 					continue;
3325 				entry_type = "NO DATA";
3326 				ebgclass = "INDETERMINATE";
3327 				break;
3328 			case AS_PROGRAM_END:
3329 				if(full_log_entries == FALSE)
3330 					continue;
3331 				entry_type = "PROGRAM END";
3332 				ebgclass = "INDETERMINATE";
3333 				break;
3334 			case AS_PROGRAM_START:
3335 				if(full_log_entries == FALSE)
3336 					continue;
3337 				entry_type = "PROGRAM (RE)START";
3338 				ebgclass = "INDETERMINATE";
3339 				break;
3340 			case AS_HOST_UP:
3341 				entry_type = "HOST UP";
3342 				ebgclass = "UP";
3343 				break;
3344 			case AS_HOST_DOWN:
3345 				entry_type = "HOST DOWN";
3346 				ebgclass = "DOWN";
3347 				break;
3348 			case AS_HOST_UNREACHABLE:
3349 				entry_type = "HOST UNREACHABLE";
3350 				ebgclass = "UNREACHABLE";
3351 				break;
3352 			case AS_SVC_OK:
3353 				entry_type = "SERVICE OK";
3354 				ebgclass = "OK";
3355 				break;
3356 			case AS_SVC_UNKNOWN:
3357 				entry_type = "SERVICE UNKNOWN";
3358 				ebgclass = "UNKNOWN";
3359 				break;
3360 			case AS_SVC_WARNING:
3361 				entry_type = "SERVICE WARNING";
3362 				ebgclass = "WARNING";
3363 				break;
3364 			case AS_SVC_CRITICAL:
3365 				entry_type = "SERVICE CRITICAL";
3366 				ebgclass = "CRITICAL";
3367 				break;
3368 			case AS_SVC_DOWNTIME_START:
3369 				entry_type = "SERVICE DOWNTIME START";
3370 				ebgclass = "INDETERMINATE";
3371 				break;
3372 			case AS_SVC_DOWNTIME_END:
3373 				entry_type = "SERVICE DOWNTIME END";
3374 				ebgclass = "INDETERMINATE";
3375 				break;
3376 			case AS_HOST_DOWNTIME_START:
3377 				entry_type = "HOST DOWNTIME START";
3378 				ebgclass = "INDETERMINATE";
3379 				break;
3380 			case AS_HOST_DOWNTIME_END:
3381 				entry_type = "HOST DOWNTIME END";
3382 				ebgclass = "INDETERMINATE";
3383 				break;
3384 			default:
3385 				if(full_log_entries == FALSE)
3386 					continue;
3387 				entry_type = "?";
3388 				ebgclass = "INDETERMINATE";
3389 			}
3390 
3391 		get_time_string(&(temp_as->time_stamp), start_date_time, sizeof(start_date_time) - 1, SHORT_DATE_TIME);
3392 		if(temp_as->next == NULL) {
3393 			get_time_string(&t2, end_date_time, sizeof(end_date_time) - 1, SHORT_DATE_TIME);
3394 			get_time_breakdown((time_t)(t2 - temp_as->time_stamp), &days, &hours, &minutes, &seconds);
3395 			snprintf(duration, sizeof(duration) - 1, "%dd %dh %dm %ds+", days, hours, minutes, seconds);
3396 			}
3397 		else {
3398 			get_time_string(&(temp_as->next->time_stamp), end_date_time, sizeof(end_date_time) - 1, SHORT_DATE_TIME);
3399 			get_time_breakdown((time_t)(temp_as->next->time_stamp - temp_as->time_stamp), &days, &hours, &minutes, &seconds);
3400 			snprintf(duration, sizeof(duration) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3401 			}
3402 
3403 		if(odd) {
3404 			bgclass = "Odd";
3405 			odd = 0;
3406 			}
3407 		else {
3408 			bgclass = "Even";
3409 			odd = 1;
3410 			}
3411 
3412 		printf("<tr class='logEntries%s'>", bgclass);
3413 		printf("<td class='logEntries%s'>%s</td>", bgclass, start_date_time);
3414 		printf("<td class='logEntries%s'>%s</td>", bgclass, end_date_time);
3415 		printf("<td class='logEntries%s'>%s</td>", bgclass, duration);
3416 		printf("<td class='logEntries%s'>%s%s</td>", ebgclass, entry_type, state_type);
3417 		printf("<td class='logEntries%s'>%s</td>", bgclass, (temp_as->state_info == NULL) ? "" : html_encode(temp_as->state_info, FALSE));
3418 		printf("</tr>\n");
3419 		}
3420 
3421 	printf("</table>\n");
3422 
3423 	printf("</DIV>\n");
3424 
3425 	return;
3426 	}
3427 
3428 
3429 
3430 /* display hostgroup availability */
display_hostgroup_availability(void)3431 void display_hostgroup_availability(void) {
3432 	hostgroup *temp_hostgroup;
3433 
3434 	/* display data for a specific hostgroup */
3435 	if(show_all_hostgroups == FALSE) {
3436 		temp_hostgroup = find_hostgroup(hostgroup_name);
3437 		display_specific_hostgroup_availability(temp_hostgroup);
3438 		}
3439 
3440 	/* display data for all hostgroups */
3441 	else {
3442 		for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next)
3443 			display_specific_hostgroup_availability(temp_hostgroup);
3444 		}
3445 
3446 	return;
3447 	}
3448 
3449 
3450 
3451 /* display availability for a specific hostgroup */
display_specific_hostgroup_availability(hostgroup * hg)3452 void display_specific_hostgroup_availability(hostgroup *hg) {
3453 	unsigned long total_time;
3454 	unsigned long time_determinate;
3455 	unsigned long time_indeterminate;
3456 	avail_subject *temp_subject;
3457 	double percent_time_up = 0.0;
3458 	double percent_time_down = 0.0;
3459 	double percent_time_unreachable = 0.0;
3460 	double percent_time_up_known = 0.0;
3461 	double percent_time_down_known = 0.0;
3462 	double percent_time_unreachable_known = 0.0;
3463 	double percent_time_indeterminate = 0.0;
3464 
3465 	double average_percent_time_up = 0.0;
3466 	double average_percent_time_up_known = 0.0;
3467 	double average_percent_time_down = 0.0;
3468 	double average_percent_time_down_known = 0.0;
3469 	double average_percent_time_unreachable = 0.0;
3470 	double average_percent_time_unreachable_known = 0.0;
3471 	double average_percent_time_indeterminate = 0.0;
3472 
3473 	int current_subject = 0;
3474 
3475 	char *bgclass = "";
3476 	int odd = 1;
3477 	host *temp_host;
3478 
3479 	if(hg == NULL)
3480 		return;
3481 
3482 	/* the user isn't authorized to view this hostgroup */
3483 	if(is_authorized_for_hostgroup(hg, &current_authdata) == FALSE)
3484 		return;
3485 
3486 	/* calculate total time during period based on timeperiod used for reporting */
3487 	total_time = calculate_total_time(t1, t2);
3488 
3489 	printf("<BR><BR>\n");
3490 	printf("<DIV ALIGN=CENTER CLASS='dataTitle'>Hostgroup '%s' Host State Breakdowns:</DIV>\n", hg->group_name);
3491 
3492 	printf("<DIV ALIGN=CENTER>\n");
3493 	printf("<TABLE BORDER=0 CLASS='data'>\n");
3494 	printf("<TR><TH CLASS='data'>Host</TH><TH CLASS='data'>%% Time Up</TH><TH CLASS='data'>%% Time Down</TH><TH CLASS='data'>%% Time Unreachable</TH><TH CLASS='data'>%% Time Undetermined</TH></TR>\n");
3495 
3496 	for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
3497 
3498 		if(temp_subject->type != HOST_SUBJECT)
3499 			continue;
3500 
3501 		temp_host = find_host(temp_subject->host_name);
3502 		if(temp_host == NULL)
3503 			continue;
3504 
3505 		if(is_host_member_of_hostgroup(hg, temp_host) == FALSE)
3506 			continue;
3507 
3508 		current_subject++;
3509 
3510 		/* reset variables */
3511 		percent_time_up = 0.0;
3512 		percent_time_down = 0.0;
3513 		percent_time_unreachable = 0.0;
3514 		percent_time_indeterminate = 0.0;
3515 		percent_time_up_known = 0.0;
3516 		percent_time_down_known = 0.0;
3517 		percent_time_unreachable_known = 0.0;
3518 
3519 		time_determinate = temp_subject->time_up + temp_subject->time_down + temp_subject->time_unreachable;
3520 		time_indeterminate = total_time - time_determinate;
3521 
3522 		if(total_time > 0) {
3523 			percent_time_up = (double)(((double)temp_subject->time_up * 100.0) / (double)total_time);
3524 			percent_time_down = (double)(((double)temp_subject->time_down * 100.0) / (double)total_time);
3525 			percent_time_unreachable = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)total_time);
3526 			percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
3527 			if(time_determinate > 0) {
3528 				percent_time_up_known = (double)(((double)temp_subject->time_up * 100.0) / (double)time_determinate);
3529 				percent_time_down_known = (double)(((double)temp_subject->time_down * 100.0) / (double)time_determinate);
3530 				percent_time_unreachable_known = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)time_determinate);
3531 				}
3532 			}
3533 
3534 		if(odd) {
3535 			odd = 0;
3536 			bgclass = "Odd";
3537 			}
3538 		else {
3539 			odd = 1;
3540 			bgclass = "Even";
3541 			}
3542 
3543 		printf("<tr CLASS='data%s'><td CLASS='data%s'>", bgclass, bgclass);
3544 		host_report_url(temp_subject->host_name, temp_subject->host_name);
3545 		printf("</td><td CLASS='hostUP'>%2.3f%% (%2.3f%%)</td><td CLASS='hostDOWN'>%2.3f%% (%2.3f%%)</td><td CLASS='hostUNREACHABLE'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", percent_time_up, percent_time_up_known, percent_time_down, percent_time_down_known, percent_time_unreachable, percent_time_unreachable_known, bgclass, percent_time_indeterminate);
3546 
3547 		get_running_average(&average_percent_time_up, percent_time_up, current_subject);
3548 		get_running_average(&average_percent_time_up_known, percent_time_up_known, current_subject);
3549 		get_running_average(&average_percent_time_down, percent_time_down, current_subject);
3550 		get_running_average(&average_percent_time_down_known, percent_time_down_known, current_subject);
3551 		get_running_average(&average_percent_time_unreachable, percent_time_unreachable, current_subject);
3552 		get_running_average(&average_percent_time_unreachable_known, percent_time_unreachable_known, current_subject);
3553 		get_running_average(&average_percent_time_indeterminate, percent_time_indeterminate, current_subject);
3554 		}
3555 
3556 	/* average statistics */
3557 	if(odd) {
3558 		odd = 0;
3559 		bgclass = "Odd";
3560 		}
3561 	else {
3562 		odd = 1;
3563 		bgclass = "Even";
3564 		}
3565 	printf("<tr CLASS='data%s'><td CLASS='data%s'>Average</td><td CLASS='hostUP'>%2.3f%% (%2.3f%%)</td><td CLASS='hostDOWN'>%2.3f%% (%2.3f%%)</td><td CLASS='hostUNREACHABLE'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>", bgclass, bgclass, average_percent_time_up, average_percent_time_up_known, average_percent_time_down, average_percent_time_down_known, average_percent_time_unreachable, average_percent_time_unreachable_known, bgclass, average_percent_time_indeterminate);
3566 
3567 	printf("</table>\n");
3568 	printf("</DIV>\n");
3569 
3570 	return;
3571 	}
3572 
3573 
3574 /* display servicegroup availability */
display_servicegroup_availability(void)3575 void display_servicegroup_availability(void) {
3576 	servicegroup *temp_servicegroup;
3577 
3578 	/* display data for a specific servicegroup */
3579 	if(show_all_servicegroups == FALSE) {
3580 		temp_servicegroup = find_servicegroup(servicegroup_name);
3581 		display_specific_servicegroup_availability(temp_servicegroup);
3582 		}
3583 
3584 	/* display data for all servicegroups */
3585 	else {
3586 		for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next)
3587 			display_specific_servicegroup_availability(temp_servicegroup);
3588 		}
3589 
3590 	return;
3591 	}
3592 
3593 
3594 
3595 /* display availability for a specific servicegroup */
display_specific_servicegroup_availability(servicegroup * sg)3596 void display_specific_servicegroup_availability(servicegroup *sg) {
3597 	unsigned long total_time;
3598 	unsigned long time_determinate;
3599 	unsigned long time_indeterminate;
3600 	avail_subject *temp_subject;
3601 	double percent_time_up = 0.0;
3602 	double percent_time_down = 0.0;
3603 	double percent_time_unreachable = 0.0;
3604 	double percent_time_up_known = 0.0;
3605 	double percent_time_down_known = 0.0;
3606 	double percent_time_unreachable_known = 0.0;
3607 	double percent_time_indeterminate = 0.0;
3608 	double percent_time_ok = 0.0;
3609 	double percent_time_warning = 0.0;
3610 	double percent_time_unknown = 0.0;
3611 	double percent_time_critical = 0.0;
3612 	double percent_time_ok_known = 0.0;
3613 	double percent_time_warning_known = 0.0;
3614 	double percent_time_unknown_known = 0.0;
3615 	double percent_time_critical_known = 0.0;
3616 
3617 	double average_percent_time_up = 0.0;
3618 	double average_percent_time_up_known = 0.0;
3619 	double average_percent_time_down = 0.0;
3620 	double average_percent_time_down_known = 0.0;
3621 	double average_percent_time_unreachable = 0.0;
3622 	double average_percent_time_unreachable_known = 0.0;
3623 	double average_percent_time_ok = 0.0;
3624 	double average_percent_time_ok_known = 0.0;
3625 	double average_percent_time_unknown = 0.0;
3626 	double average_percent_time_unknown_known = 0.0;
3627 	double average_percent_time_warning = 0.0;
3628 	double average_percent_time_warning_known = 0.0;
3629 	double average_percent_time_critical = 0.0;
3630 	double average_percent_time_critical_known = 0.0;
3631 	double average_percent_time_indeterminate = 0.0;
3632 
3633 	int current_subject = 0;
3634 
3635 	char *bgclass = "";
3636 	int odd = 1;
3637 	host *temp_host;
3638 	service *temp_service;
3639 	char last_host[MAX_INPUT_BUFFER];
3640 
3641 	if(sg == NULL)
3642 		return;
3643 
3644 	/* the user isn't authorized to view this servicegroup */
3645 	if(is_authorized_for_servicegroup(sg, &current_authdata) == FALSE)
3646 		return;
3647 
3648 	/* calculate total time during period based on timeperiod used for reporting */
3649 	total_time = calculate_total_time(t1, t2);
3650 
3651 	printf("<BR><BR>\n");
3652 	printf("<DIV ALIGN=CENTER CLASS='dataTitle'>Servicegroup '%s' Host State Breakdowns:</DIV>\n", sg->group_name);
3653 
3654 	printf("<DIV ALIGN=CENTER>\n");
3655 	printf("<TABLE BORDER=0 CLASS='data'>\n");
3656 	printf("<TR><TH CLASS='data'>Host</TH><TH CLASS='data'>%% Time Up</TH><TH CLASS='data'>%% Time Down</TH><TH CLASS='data'>%% Time Unreachable</TH><TH CLASS='data'>%% Time Undetermined</TH></TR>\n");
3657 
3658 	for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
3659 
3660 		if(temp_subject->type != HOST_SUBJECT)
3661 			continue;
3662 
3663 		temp_host = find_host(temp_subject->host_name);
3664 		if(temp_host == NULL)
3665 			continue;
3666 
3667 		if(is_host_member_of_servicegroup(sg, temp_host) == FALSE)
3668 			continue;
3669 
3670 		current_subject++;
3671 
3672 		/* reset variables */
3673 		percent_time_up = 0.0;
3674 		percent_time_down = 0.0;
3675 		percent_time_unreachable = 0.0;
3676 		percent_time_indeterminate = 0.0;
3677 		percent_time_up_known = 0.0;
3678 		percent_time_down_known = 0.0;
3679 		percent_time_unreachable_known = 0.0;
3680 
3681 		time_determinate = temp_subject->time_up + temp_subject->time_down + temp_subject->time_unreachable;
3682 		time_indeterminate = total_time - time_determinate;
3683 
3684 		if(total_time > 0) {
3685 			percent_time_up = (double)(((double)temp_subject->time_up * 100.0) / (double)total_time);
3686 			percent_time_down = (double)(((double)temp_subject->time_down * 100.0) / (double)total_time);
3687 			percent_time_unreachable = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)total_time);
3688 			percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
3689 			if(time_determinate > 0) {
3690 				percent_time_up_known = (double)(((double)temp_subject->time_up * 100.0) / (double)time_determinate);
3691 				percent_time_down_known = (double)(((double)temp_subject->time_down * 100.0) / (double)time_determinate);
3692 				percent_time_unreachable_known = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)time_determinate);
3693 				}
3694 			}
3695 
3696 		if(odd) {
3697 			odd = 0;
3698 			bgclass = "Odd";
3699 			}
3700 		else {
3701 			odd = 1;
3702 			bgclass = "Even";
3703 			}
3704 
3705 		printf("<tr CLASS='data%s'><td CLASS='data%s'>", bgclass, bgclass);
3706 		host_report_url(temp_subject->host_name, temp_subject->host_name);
3707 		printf("</td><td CLASS='hostUP'>%2.3f%% (%2.3f%%)</td><td CLASS='hostDOWN'>%2.3f%% (%2.3f%%)</td><td CLASS='hostUNREACHABLE'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", percent_time_up, percent_time_up_known, percent_time_down, percent_time_down_known, percent_time_unreachable, percent_time_unreachable_known, bgclass, percent_time_indeterminate);
3708 
3709 		get_running_average(&average_percent_time_up, percent_time_up, current_subject);
3710 		get_running_average(&average_percent_time_up_known, percent_time_up_known, current_subject);
3711 		get_running_average(&average_percent_time_down, percent_time_down, current_subject);
3712 		get_running_average(&average_percent_time_down_known, percent_time_down_known, current_subject);
3713 		get_running_average(&average_percent_time_unreachable, percent_time_unreachable, current_subject);
3714 		get_running_average(&average_percent_time_unreachable_known, percent_time_unreachable_known, current_subject);
3715 		get_running_average(&average_percent_time_indeterminate, percent_time_indeterminate, current_subject);
3716 		}
3717 
3718 	/* average statistics */
3719 	if(odd) {
3720 		odd = 0;
3721 		bgclass = "Odd";
3722 		}
3723 	else {
3724 		odd = 1;
3725 		bgclass = "Even";
3726 		}
3727 	printf("<tr CLASS='data%s'><td CLASS='data%s'>Average</td><td CLASS='hostUP'>%2.3f%% (%2.3f%%)</td><td CLASS='hostDOWN'>%2.3f%% (%2.3f%%)</td><td CLASS='hostUNREACHABLE'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>", bgclass, bgclass, average_percent_time_up, average_percent_time_up_known, average_percent_time_down, average_percent_time_down_known, average_percent_time_unreachable, average_percent_time_unreachable_known, bgclass, average_percent_time_indeterminate);
3728 
3729 	printf("</table>\n");
3730 	printf("</DIV>\n");
3731 
3732 	printf("<BR>\n");
3733 	printf("<DIV ALIGN=CENTER CLASS='dataTitle'>Servicegroup '%s' Service State Breakdowns:</DIV>\n", sg->group_name);
3734 
3735 	printf("<DIV ALIGN=CENTER>\n");
3736 	printf("<TABLE BORDER=0 CLASS='data'>\n");
3737 	printf("<TR><TH CLASS='data'>Host</TH><TH CLASS='data'>Service</TH><TH CLASS='data'>%% Time OK</TH><TH CLASS='data'>%% Time Warning</TH><TH CLASS='data'>%% Time Unknown</TH><TH CLASS='data'>%% Time Critical</TH><TH CLASS='data'>%% Time Undetermined</TH></TR>\n");
3738 
3739 	current_subject = 0;
3740 	average_percent_time_indeterminate = 0.0;
3741 
3742 	for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
3743 
3744 		if(temp_subject->type != SERVICE_SUBJECT)
3745 			continue;
3746 
3747 		temp_service = find_service(temp_subject->host_name, temp_subject->service_description);
3748 		if(temp_service == NULL)
3749 			continue;
3750 
3751 		if(is_service_member_of_servicegroup(sg, temp_service) == FALSE)
3752 			continue;
3753 
3754 		current_subject++;
3755 
3756 		time_determinate = temp_subject->time_ok + temp_subject->time_warning + temp_subject->time_unknown + temp_subject->time_critical;
3757 		time_indeterminate = total_time - time_determinate;
3758 
3759 		/* adjust indeterminate time due to insufficient data (not all was caught) */
3760 		temp_subject->time_indeterminate_nodata = time_indeterminate - temp_subject->time_indeterminate_notrunning;
3761 
3762 		/* initialize values */
3763 		percent_time_ok = 0.0;
3764 		percent_time_warning = 0.0;
3765 		percent_time_unknown = 0.0;
3766 		percent_time_critical = 0.0;
3767 		percent_time_indeterminate = 0.0;
3768 		percent_time_ok_known = 0.0;
3769 		percent_time_warning_known = 0.0;
3770 		percent_time_unknown_known = 0.0;
3771 		percent_time_critical_known = 0.0;
3772 
3773 		if(total_time > 0) {
3774 			percent_time_ok = (double)(((double)temp_subject->time_ok * 100.0) / (double)total_time);
3775 			percent_time_warning = (double)(((double)temp_subject->time_warning * 100.0) / (double)total_time);
3776 			percent_time_unknown = (double)(((double)temp_subject->time_unknown * 100.0) / (double)total_time);
3777 			percent_time_critical = (double)(((double)temp_subject->time_critical * 100.0) / (double)total_time);
3778 			percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
3779 			if(time_determinate > 0) {
3780 				percent_time_ok_known = (double)(((double)temp_subject->time_ok * 100.0) / (double)time_determinate);
3781 				percent_time_warning_known = (double)(((double)temp_subject->time_warning * 100.0) / (double)time_determinate);
3782 				percent_time_unknown_known = (double)(((double)temp_subject->time_unknown * 100.0) / (double)time_determinate);
3783 				percent_time_critical_known = (double)(((double)temp_subject->time_critical * 100.0) / (double)time_determinate);
3784 				}
3785 			}
3786 
3787 		if(odd) {
3788 			odd = 0;
3789 			bgclass = "Odd";
3790 			}
3791 		else {
3792 			odd = 1;
3793 			bgclass = "Even";
3794 			}
3795 
3796 		printf("<tr CLASS='data%s'><td CLASS='data%s'>", bgclass, bgclass);
3797 		if(strcmp(temp_subject->host_name, last_host))
3798 			host_report_url(temp_subject->host_name, temp_subject->host_name);
3799 		printf("</td><td CLASS='data%s'>", bgclass);
3800 		service_report_url(temp_subject->host_name, temp_subject->service_description, temp_subject->service_description);
3801 		printf("</td><td CLASS='serviceOK'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceWARNING'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceUNKNOWN'>%2.3f%% (%2.3f%%)</td><td class='serviceCRITICAL'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", percent_time_ok, percent_time_ok_known, percent_time_warning, percent_time_warning_known, percent_time_unknown, percent_time_unknown_known, percent_time_critical, percent_time_critical_known, bgclass, percent_time_indeterminate);
3802 
3803 		strncpy(last_host, temp_subject->host_name, sizeof(last_host) - 1);
3804 		last_host[sizeof(last_host) - 1] = '\x0';
3805 
3806 		get_running_average(&average_percent_time_ok, percent_time_ok, current_subject);
3807 		get_running_average(&average_percent_time_ok_known, percent_time_ok_known, current_subject);
3808 		get_running_average(&average_percent_time_unknown, percent_time_unknown, current_subject);
3809 		get_running_average(&average_percent_time_unknown_known, percent_time_unknown_known, current_subject);
3810 		get_running_average(&average_percent_time_warning, percent_time_warning, current_subject);
3811 		get_running_average(&average_percent_time_warning_known, percent_time_warning_known, current_subject);
3812 		get_running_average(&average_percent_time_critical, percent_time_critical, current_subject);
3813 		get_running_average(&average_percent_time_critical_known, percent_time_critical_known, current_subject);
3814 		get_running_average(&average_percent_time_indeterminate, percent_time_indeterminate, current_subject);
3815 		}
3816 
3817 	/* display average stats */
3818 	if(odd) {
3819 		odd = 0;
3820 		bgclass = "Odd";
3821 		}
3822 	else {
3823 		odd = 1;
3824 		bgclass = "Even";
3825 		}
3826 
3827 	printf("<tr CLASS='data%s'><td CLASS='data%s' colspan='2'>Average</td><td CLASS='serviceOK'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceWARNING'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceUNKNOWN'>%2.3f%% (%2.3f%%)</td><td class='serviceCRITICAL'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", bgclass, bgclass, average_percent_time_ok, average_percent_time_ok_known, average_percent_time_warning, average_percent_time_warning_known, average_percent_time_unknown, average_percent_time_unknown_known, average_percent_time_critical, average_percent_time_critical_known, bgclass, average_percent_time_indeterminate);
3828 
3829 	printf("</table>\n");
3830 	printf("</DIV>\n");
3831 
3832 	return;
3833 	}
3834 
3835 
3836 /* display host availability */
display_host_availability(void)3837 void display_host_availability(void) {
3838 	unsigned long total_time;
3839 	unsigned long time_determinate;
3840 	unsigned long time_indeterminate;
3841 	avail_subject *temp_subject;
3842 	host *temp_host;
3843 	service *temp_service;
3844 	int days, hours, minutes, seconds;
3845 	char time_indeterminate_string[48];
3846 	char time_determinate_string[48];
3847 	char total_time_string[48];
3848 	double percent_time_ok = 0.0;
3849 	double percent_time_warning = 0.0;
3850 	double percent_time_unknown = 0.0;
3851 	double percent_time_critical = 0.0;
3852 	double percent_time_indeterminate = 0.0;
3853 	double percent_time_ok_known = 0.0;
3854 	double percent_time_warning_known = 0.0;
3855 	double percent_time_unknown_known = 0.0;
3856 	double percent_time_critical_known = 0.0;
3857 	char time_up_string[48];
3858 	char time_down_string[48];
3859 	char time_unreachable_string[48];
3860 	double percent_time_up = 0.0;
3861 	double percent_time_down = 0.0;
3862 	double percent_time_unreachable = 0.0;
3863 	double percent_time_up_known = 0.0;
3864 	double percent_time_down_known = 0.0;
3865 	double percent_time_unreachable_known = 0.0;
3866 
3867 	double percent_time_up_scheduled = 0.0;
3868 	double percent_time_up_unscheduled = 0.0;
3869 	double percent_time_down_scheduled = 0.0;
3870 	double percent_time_down_unscheduled = 0.0;
3871 	double percent_time_unreachable_scheduled = 0.0;
3872 	double percent_time_unreachable_unscheduled = 0.0;
3873 	double percent_time_up_scheduled_known = 0.0;
3874 	double percent_time_up_unscheduled_known = 0.0;
3875 	double percent_time_down_scheduled_known = 0.0;
3876 	double percent_time_down_unscheduled_known = 0.0;
3877 	double percent_time_unreachable_scheduled_known = 0.0;
3878 	double percent_time_unreachable_unscheduled_known = 0.0;
3879 	char time_up_scheduled_string[48];
3880 	char time_up_unscheduled_string[48];
3881 	char time_down_scheduled_string[48];
3882 	char time_down_unscheduled_string[48];
3883 	char time_unreachable_scheduled_string[48];
3884 	char time_unreachable_unscheduled_string[48];
3885 
3886 	char time_indeterminate_scheduled_string[48];
3887 	char time_indeterminate_unscheduled_string[48];
3888 	double percent_time_indeterminate_scheduled = 0.0;
3889 	double percent_time_indeterminate_unscheduled = 0.0;
3890 	char time_indeterminate_notrunning_string[48];
3891 	char time_indeterminate_nodata_string[48];
3892 	double percent_time_indeterminate_notrunning = 0.0;
3893 	double percent_time_indeterminate_nodata = 0.0;
3894 
3895 	double average_percent_time_up = 0.0;
3896 	double average_percent_time_up_known = 0.0;
3897 	double average_percent_time_down = 0.0;
3898 	double average_percent_time_down_known = 0.0;
3899 	double average_percent_time_unreachable = 0.0;
3900 	double average_percent_time_unreachable_known = 0.0;
3901 	double average_percent_time_indeterminate = 0.0;
3902 
3903 	double average_percent_time_ok = 0.0;
3904 	double average_percent_time_ok_known = 0.0;
3905 	double average_percent_time_unknown = 0.0;
3906 	double average_percent_time_unknown_known = 0.0;
3907 	double average_percent_time_warning = 0.0;
3908 	double average_percent_time_warning_known = 0.0;
3909 	double average_percent_time_critical = 0.0;
3910 	double average_percent_time_critical_known = 0.0;
3911 
3912 	int current_subject = 0;
3913 
3914 	char *bgclass = "";
3915 	int odd = 1;
3916 
3917 	/* calculate total time during period based on timeperiod used for reporting */
3918 	total_time = calculate_total_time(t1, t2);
3919 
3920 #ifdef DEBUG
3921 	printf("Total time: '%ld' seconds<br>\n", total_time);
3922 #endif
3923 
3924 	/* show data for a specific host */
3925 	if(show_all_hosts == FALSE) {
3926 
3927 		temp_subject = find_subject(HOST_SUBJECT, host_name, NULL);
3928 		if(temp_subject == NULL)
3929 			return;
3930 
3931 		temp_host = find_host(temp_subject->host_name);
3932 		if(temp_host == NULL)
3933 			return;
3934 
3935 		/* the user isn't authorized to view this host */
3936 		if(is_authorized_for_host(temp_host, &current_authdata) == FALSE)
3937 			return;
3938 
3939 		time_determinate = temp_subject->time_up + temp_subject->time_down + temp_subject->time_unreachable;
3940 		time_indeterminate = total_time - time_determinate;
3941 
3942 		/* adjust indeterminate time due to insufficient data (not all was caught) */
3943 		temp_subject->time_indeterminate_nodata = time_indeterminate - temp_subject->time_indeterminate_notrunning;
3944 
3945 		/* up times */
3946 		get_time_breakdown(temp_subject->time_up, &days, &hours, &minutes, &seconds);
3947 		snprintf(time_up_string, sizeof(time_up_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3948 		get_time_breakdown(temp_subject->scheduled_time_up, &days, &hours, &minutes, &seconds);
3949 		snprintf(time_up_scheduled_string, sizeof(time_up_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3950 		get_time_breakdown(temp_subject->time_up - temp_subject->scheduled_time_up, &days, &hours, &minutes, &seconds);
3951 		snprintf(time_up_unscheduled_string, sizeof(time_up_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3952 
3953 		/* down times */
3954 		get_time_breakdown(temp_subject->time_down, &days, &hours, &minutes, &seconds);
3955 		snprintf(time_down_string, sizeof(time_down_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3956 		get_time_breakdown(temp_subject->scheduled_time_down, &days, &hours, &minutes, &seconds);
3957 		snprintf(time_down_scheduled_string, sizeof(time_down_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3958 		get_time_breakdown(temp_subject->time_down - temp_subject->scheduled_time_down, &days, &hours, &minutes, &seconds);
3959 		snprintf(time_down_unscheduled_string, sizeof(time_down_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3960 
3961 		/* unreachable times */
3962 		get_time_breakdown(temp_subject->time_unreachable, &days, &hours, &minutes, &seconds);
3963 		snprintf(time_unreachable_string, sizeof(time_unreachable_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3964 		get_time_breakdown(temp_subject->scheduled_time_unreachable, &days, &hours, &minutes, &seconds);
3965 		snprintf(time_unreachable_scheduled_string, sizeof(time_unreachable_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3966 		get_time_breakdown(temp_subject->time_unreachable - temp_subject->scheduled_time_unreachable, &days, &hours, &minutes, &seconds);
3967 		snprintf(time_unreachable_unscheduled_string, sizeof(time_unreachable_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3968 
3969 		/* indeterminate times */
3970 		get_time_breakdown(time_indeterminate, &days, &hours, &minutes, &seconds);
3971 		snprintf(time_indeterminate_string, sizeof(time_indeterminate_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3972 		get_time_breakdown(temp_subject->scheduled_time_indeterminate, &days, &hours, &minutes, &seconds);
3973 		snprintf(time_indeterminate_scheduled_string, sizeof(time_indeterminate_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3974 		get_time_breakdown(time_indeterminate - temp_subject->scheduled_time_indeterminate, &days, &hours, &minutes, &seconds);
3975 		snprintf(time_indeterminate_unscheduled_string, sizeof(time_indeterminate_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3976 		get_time_breakdown(temp_subject->time_indeterminate_notrunning, &days, &hours, &minutes, &seconds);
3977 		snprintf(time_indeterminate_notrunning_string, sizeof(time_indeterminate_notrunning_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3978 		get_time_breakdown(temp_subject->time_indeterminate_nodata, &days, &hours, &minutes, &seconds);
3979 		snprintf(time_indeterminate_nodata_string, sizeof(time_indeterminate_nodata_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3980 
3981 		get_time_breakdown(time_determinate, &days, &hours, &minutes, &seconds);
3982 		snprintf(time_determinate_string, sizeof(time_determinate_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3983 
3984 		get_time_breakdown(total_time, &days, &hours, &minutes, &seconds);
3985 		snprintf(total_time_string, sizeof(total_time_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
3986 
3987 		if(total_time > 0) {
3988 			percent_time_up = (double)(((double)temp_subject->time_up * 100.0) / (double)total_time);
3989 			percent_time_up_scheduled = (double)(((double)temp_subject->scheduled_time_up * 100.0) / (double)total_time);
3990 			percent_time_up_unscheduled = percent_time_up - percent_time_up_scheduled;
3991 			percent_time_down = (double)(((double)temp_subject->time_down * 100.0) / (double)total_time);
3992 			percent_time_down_scheduled = (double)(((double)temp_subject->scheduled_time_down * 100.0) / (double)total_time);
3993 			percent_time_down_unscheduled = percent_time_down - percent_time_down_scheduled;
3994 			percent_time_unreachable = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)total_time);
3995 			percent_time_unreachable_scheduled = (double)(((double)temp_subject->scheduled_time_unreachable * 100.0) / (double)total_time);
3996 			percent_time_unreachable_unscheduled = percent_time_unreachable - percent_time_unreachable_scheduled;
3997 			percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
3998 			percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time);
3999 			percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled;
4000 			percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time);
4001 			percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time);
4002 			if(time_determinate > 0) {
4003 				percent_time_up_known = (double)(((double)temp_subject->time_up * 100.0) / (double)time_determinate);
4004 				percent_time_up_scheduled_known = (double)(((double)temp_subject->scheduled_time_up * 100.0) / (double)time_determinate);
4005 				percent_time_up_unscheduled_known = percent_time_up_known - percent_time_up_scheduled_known;
4006 				percent_time_down_known = (double)(((double)temp_subject->time_down * 100.0) / (double)time_determinate);
4007 				percent_time_down_scheduled_known = (double)(((double)temp_subject->scheduled_time_down * 100.0) / (double)time_determinate);
4008 				percent_time_down_unscheduled_known = percent_time_down_known - percent_time_down_scheduled_known;
4009 				percent_time_unreachable_known = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)time_determinate);
4010 				percent_time_unreachable_scheduled_known = (double)(((double)temp_subject->scheduled_time_unreachable * 100.0) / (double)time_determinate);
4011 				percent_time_unreachable_unscheduled_known = percent_time_unreachable_known - percent_time_unreachable_scheduled_known;
4012 				}
4013 			}
4014 
4015 		printf("<DIV ALIGN=CENTER CLASS='dataTitle'>Host State Breakdowns:</DIV>\n");
4016 
4017 #ifdef USE_TRENDS
4018 		printf("<p align='center'>\n");
4019 		printf("<a href='%s?host=%s", TRENDS_CGI, url_encode(host_name));
4020 		printf("&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedhoststate=%d&backtrack=%d'>", t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives);
4021 		printf("<img src='%s?createimage&smallimage&host=%s", TRENDS_CGI, url_encode(host_name));
4022 		printf("&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedhoststate=%d&backtrack=%d' border=1 alt='Host State Trends' title='Host State Trends' width='500' height='20'>", t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives);
4023 		printf("</a><br>\n");
4024 		printf("</p>\n");
4025 #endif
4026 		printf("<DIV ALIGN=CENTER>\n");
4027 		printf("<TABLE BORDER=0 CLASS='data'>\n");
4028 		printf("<TR><TH CLASS='data'>State</TH><TH CLASS='data'>Type / Reason</TH><TH CLASS='data'>Time</TH><TH CLASS='data'>%% Total Time</TH><TH CLASS='data'>%% Known Time</TH></TR>\n");
4029 
4030 		/* up times */
4031 		printf("<tr CLASS='dataEven'><td CLASS='hostUP' rowspan=3>UP</td>");
4032 		printf("<td CLASS='dataEven'>Unscheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td class='dataEven'>%2.3f%%</td></tr>\n", time_up_unscheduled_string, percent_time_up, percent_time_up_known);
4033 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>Scheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td class='dataEven'>%2.3f%%</td></tr>\n", time_up_scheduled_string, percent_time_up_scheduled, percent_time_up_scheduled_known);
4034 		printf("<tr CLASS='hostUP'><td CLASS='hostUP'>Total</td><td CLASS='hostUP'>%s</td><td CLASS='hostUP'>%2.3f%%</td><td class='hostUP'>%2.3f%%</td></tr>\n", time_up_string, percent_time_up, percent_time_up_known);
4035 
4036 		/* down times */
4037 		printf("<tr CLASS='dataOdd'><td CLASS='hostDOWN' rowspan=3>DOWN</td>");
4038 		printf("<td CLASS='dataOdd'>Unscheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td class='dataOdd'>%2.3f%%</td></tr>\n", time_down_unscheduled_string, percent_time_down_unscheduled, percent_time_down_unscheduled_known);
4039 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd'>Scheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td class='dataOdd'>%2.3f%%</td></tr>\n", time_down_scheduled_string, percent_time_down_scheduled, percent_time_down_scheduled_known);
4040 		printf("<tr CLASS='hostDOWN'><td CLASS='hostDOWN'>Total</td><td CLASS='hostDOWN'>%s</td><td CLASS='hostDOWN'>%2.3f%%</td><td class='hostDOWN'>%2.3f%%</td></tr>\n", time_down_string, percent_time_down, percent_time_down_known);
4041 
4042 		/* unreachable times */
4043 		printf("<tr CLASS='dataEven'><td CLASS='hostUNREACHABLE' rowspan=3>UNREACHABLE</td>");
4044 		printf("<td CLASS='dataEven'>Unscheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td class='dataEven'>%2.3f%%</td></tr>\n", time_unreachable_unscheduled_string, percent_time_unreachable, percent_time_unreachable_known);
4045 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>Scheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td class='dataEven'>%2.3f%%</td></tr>\n", time_unreachable_scheduled_string, percent_time_unreachable_scheduled, percent_time_unreachable_scheduled_known);
4046 		printf("<tr CLASS='hostUNREACHABLE'><td CLASS='hostUNREACHABLE'>Total</td><td CLASS='hostUNREACHABLE'>%s</td><td CLASS='hostUNREACHABLE'>%2.3f%%</td><td class='hostUNREACHABLE'>%2.3f%%</td></tr>\n", time_unreachable_string, percent_time_unreachable, percent_time_unreachable_known);
4047 
4048 		/* indeterminate times */
4049 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd' rowspan=3>Undetermined</td>");
4050 		printf("<td CLASS='dataOdd'>Nagios Not Running</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td CLASS='dataOdd'></td></tr>\n", time_indeterminate_notrunning_string, percent_time_indeterminate_notrunning);
4051 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd'>Insufficient Data</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td CLASS='dataOdd'></td></tr>\n", time_indeterminate_nodata_string, percent_time_indeterminate_nodata);
4052 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd'>Total</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td CLASS='dataOdd'></td></tr>\n", time_indeterminate_string, percent_time_indeterminate);
4053 
4054 		printf("<tr><td colspan=3></td></tr>\n");
4055 
4056 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>All</td><td class='dataEven'>Total</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>100.000%%</td><td CLASS='dataEven'>100.000%%</td></tr>\n", total_time_string);
4057 		printf("</table>\n");
4058 		printf("</DIV>\n");
4059 
4060 
4061 
4062 		/* display state breakdowns for all services on this host */
4063 
4064 		printf("<BR><BR>\n");
4065 		printf("<DIV ALIGN=CENTER CLASS='dataTitle'>State Breakdowns For Host Services:</DIV>\n");
4066 
4067 		printf("<DIV ALIGN=CENTER>\n");
4068 		printf("<TABLE BORDER=0 CLASS='data'>\n");
4069 		printf("<TR><TH CLASS='data'>Service</TH><TH CLASS='data'>%% Time OK</TH><TH CLASS='data'>%% Time Warning</TH><TH CLASS='data'>%% Time Unknown</TH><TH CLASS='data'>%% Time Critical</TH><TH CLASS='data'>%% Time Undetermined</TH></TR>\n");
4070 
4071 		for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
4072 
4073 			if(temp_subject->type != SERVICE_SUBJECT)
4074 				continue;
4075 
4076 			temp_service = find_service(temp_subject->host_name, temp_subject->service_description);
4077 			if(temp_service == NULL)
4078 				continue;
4079 
4080 			/* the user isn't authorized to view this service */
4081 			if(is_authorized_for_service(temp_service, &current_authdata) == FALSE)
4082 				continue;
4083 
4084 			current_subject++;
4085 
4086 			if(odd) {
4087 				odd = 0;
4088 				bgclass = "Odd";
4089 				}
4090 			else {
4091 				odd = 1;
4092 				bgclass = "Even";
4093 				}
4094 
4095 			/* reset variables */
4096 			percent_time_ok = 0.0;
4097 			percent_time_warning = 0.0;
4098 			percent_time_unknown = 0.0;
4099 			percent_time_critical = 0.0;
4100 			percent_time_indeterminate = 0.0;
4101 			percent_time_ok_known = 0.0;
4102 			percent_time_warning_known = 0.0;
4103 			percent_time_unknown_known = 0.0;
4104 			percent_time_critical_known = 0.0;
4105 
4106 			time_determinate = temp_subject->time_ok + temp_subject->time_warning + temp_subject->time_unknown + temp_subject->time_critical;
4107 			time_indeterminate = total_time - time_determinate;
4108 
4109 			if(total_time > 0) {
4110 				percent_time_ok = (double)(((double)temp_subject->time_ok * 100.0) / (double)total_time);
4111 				percent_time_warning = (double)(((double)temp_subject->time_warning * 100.0) / (double)total_time);
4112 				percent_time_unknown = (double)(((double)temp_subject->time_unknown * 100.0) / (double)total_time);
4113 				percent_time_critical = (double)(((double)temp_subject->time_critical * 100.0) / (double)total_time);
4114 				percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
4115 				if(time_determinate > 0) {
4116 					percent_time_ok_known = (double)(((double)temp_subject->time_ok * 100.0) / (double)time_determinate);
4117 					percent_time_warning_known = (double)(((double)temp_subject->time_warning * 100.0) / (double)time_determinate);
4118 					percent_time_unknown_known = (double)(((double)temp_subject->time_unknown * 100.0) / (double)time_determinate);
4119 					percent_time_critical_known = (double)(((double)temp_subject->time_critical * 100.0) / (double)time_determinate);
4120 					}
4121 				}
4122 
4123 			printf("<tr CLASS='data%s'><td CLASS='data%s'>", bgclass, bgclass);
4124 			service_report_url(temp_subject->host_name, temp_subject->service_description, temp_subject->service_description);
4125 			printf("</td><td CLASS='serviceOK'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceWARNING'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceUNKNOWN'>%2.3f%% (%2.3f%%)</td><td class='serviceCRITICAL'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", percent_time_ok, percent_time_ok_known, percent_time_warning, percent_time_warning_known, percent_time_unknown, percent_time_unknown_known, percent_time_critical, percent_time_critical_known, bgclass, percent_time_indeterminate);
4126 
4127 			get_running_average(&average_percent_time_ok, percent_time_ok, current_subject);
4128 			get_running_average(&average_percent_time_ok_known, percent_time_ok_known, current_subject);
4129 			get_running_average(&average_percent_time_unknown, percent_time_unknown, current_subject);
4130 			get_running_average(&average_percent_time_unknown_known, percent_time_unknown_known, current_subject);
4131 			get_running_average(&average_percent_time_warning, percent_time_warning, current_subject);
4132 			get_running_average(&average_percent_time_warning_known, percent_time_warning_known, current_subject);
4133 			get_running_average(&average_percent_time_critical, percent_time_critical, current_subject);
4134 			get_running_average(&average_percent_time_critical_known, percent_time_critical_known, current_subject);
4135 			get_running_average(&average_percent_time_indeterminate, percent_time_indeterminate, current_subject);
4136 			}
4137 
4138 		/* display average stats */
4139 		if(odd) {
4140 			odd = 0;
4141 			bgclass = "Odd";
4142 			}
4143 		else {
4144 			odd = 1;
4145 			bgclass = "Even";
4146 			}
4147 
4148 		printf("<tr CLASS='data%s'><td CLASS='data%s'>Average</td><td CLASS='serviceOK'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceWARNING'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceUNKNOWN'>%2.3f%% (%2.3f%%)</td><td class='serviceCRITICAL'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", bgclass, bgclass, average_percent_time_ok, average_percent_time_ok_known, average_percent_time_warning, average_percent_time_warning_known, average_percent_time_unknown, average_percent_time_unknown_known, average_percent_time_critical, average_percent_time_critical_known, bgclass, average_percent_time_indeterminate);
4149 
4150 		printf("</table>\n");
4151 		printf("</DIV>\n");
4152 
4153 
4154 		/* write log entries for the host */
4155 		temp_subject = find_subject(HOST_SUBJECT, host_name, NULL);
4156 		write_log_entries(temp_subject);
4157 		}
4158 
4159 
4160 	/* display data for all hosts */
4161 	else {
4162 
4163 		if(output_format == HTML_OUTPUT) {
4164 
4165 			printf("<BR><BR>\n");
4166 			printf("<DIV ALIGN=CENTER CLASS='dataTitle'>Host State Breakdowns:</DIV>\n");
4167 
4168 			printf("<DIV ALIGN=CENTER>\n");
4169 			printf("<TABLE BORDER=0 CLASS='data'>\n");
4170 			printf("<TR><TH CLASS='data'>Host</TH><TH CLASS='data'>%% Time Up</TH><TH CLASS='data'>%% Time Down</TH><TH CLASS='data'>%% Time Unreachable</TH><TH CLASS='data'>%% Time Undetermined</TH></TR>\n");
4171 			}
4172 
4173 		else if(output_format == CSV_OUTPUT) {
4174 			printf("HOST_NAME,");
4175 
4176 			printf(" TIME_UP_SCHEDULED, PERCENT_TIME_UP_SCHEDULED, PERCENT_KNOWN_TIME_UP_SCHEDULED, TIME_UP_UNSCHEDULED, PERCENT_TIME_UP_UNSCHEDULED, PERCENT_KNOWN_TIME_UP_UNSCHEDULED, TOTAL_TIME_UP, PERCENT_TOTAL_TIME_UP, PERCENT_KNOWN_TIME_UP,");
4177 
4178 			printf(" TIME_DOWN_SCHEDULED, PERCENT_TIME_DOWN_SCHEDULED, PERCENT_KNOWN_TIME_DOWN_SCHEDULED, TIME_DOWN_UNSCHEDULED, PERCENT_TIME_DOWN_UNSCHEDULED, PERCENT_KNOWN_TIME_DOWN_UNSCHEDULED, TOTAL_TIME_DOWN, PERCENT_TOTAL_TIME_DOWN, PERCENT_KNOWN_TIME_DOWN,");
4179 
4180 			printf(" TIME_UNREACHABLE_SCHEDULED, PERCENT_TIME_UNREACHABLE_SCHEDULED, PERCENT_KNOWN_TIME_UNREACHABLE_SCHEDULED, TIME_UNREACHABLE_UNSCHEDULED, PERCENT_TIME_UNREACHABLE_UNSCHEDULED, PERCENT_KNOWN_TIME_UNREACHABLE_UNSCHEDULED, TOTAL_TIME_UNREACHABLE, PERCENT_TOTAL_TIME_UNREACHABLE, PERCENT_KNOWN_TIME_UNREACHABLE,");
4181 
4182 			printf(" TIME_UNDETERMINED_NOT_RUNNING, PERCENT_TIME_UNDETERMINED_NOT_RUNNING, TIME_UNDETERMINED_NO_DATA, PERCENT_TIME_UNDETERMINED_NO_DATA, TOTAL_TIME_UNDETERMINED, PERCENT_TOTAL_TIME_UNDETERMINED\n");
4183 			}
4184 
4185 
4186 		for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
4187 
4188 			if(temp_subject->type != HOST_SUBJECT)
4189 				continue;
4190 
4191 			temp_host = find_host(temp_subject->host_name);
4192 			if(temp_host == NULL)
4193 				continue;
4194 
4195 			/* the user isn't authorized to view this host */
4196 			if(is_authorized_for_host(temp_host, &current_authdata) == FALSE)
4197 				continue;
4198 
4199 			current_subject++;
4200 
4201 			time_determinate = temp_subject->time_up + temp_subject->time_down + temp_subject->time_unreachable;
4202 			time_indeterminate = total_time - time_determinate;
4203 
4204 			/* adjust indeterminate time due to insufficient data (not all was caught) */
4205 			temp_subject->time_indeterminate_nodata = time_indeterminate - temp_subject->time_indeterminate_notrunning;
4206 
4207 			/* initialize values */
4208 			percent_time_up = 0.0;
4209 			percent_time_up_scheduled = 0.0;
4210 			percent_time_up_unscheduled = 0.0;
4211 			percent_time_down = 0.0;
4212 			percent_time_down_scheduled = 0.0;
4213 			percent_time_down_unscheduled = 0.0;
4214 			percent_time_unreachable = 0.0;
4215 			percent_time_unreachable_scheduled = 0.0;
4216 			percent_time_unreachable_unscheduled = 0.0;
4217 			percent_time_indeterminate = 0.0;
4218 			percent_time_indeterminate_scheduled = 0.0;
4219 			percent_time_indeterminate_unscheduled = 0.0;
4220 			percent_time_indeterminate_notrunning = 0.0;
4221 			percent_time_indeterminate_nodata = 0.0;
4222 			percent_time_up_known = 0.0;
4223 			percent_time_up_scheduled_known = 0.0;
4224 			percent_time_up_unscheduled_known = 0.0;
4225 			percent_time_down_known = 0.0;
4226 			percent_time_down_scheduled_known = 0.0;
4227 			percent_time_down_unscheduled_known = 0.0;
4228 			percent_time_unreachable_known = 0.0;
4229 			percent_time_unreachable_scheduled_known = 0.0;
4230 			percent_time_unreachable_unscheduled_known = 0.0;
4231 
4232 			if(total_time > 0) {
4233 				percent_time_up = (double)(((double)temp_subject->time_up * 100.0) / (double)total_time);
4234 				percent_time_up_scheduled = (double)(((double)temp_subject->scheduled_time_up * 100.0) / (double)total_time);
4235 				percent_time_up_unscheduled = percent_time_up - percent_time_up_scheduled;
4236 				percent_time_down = (double)(((double)temp_subject->time_down * 100.0) / (double)total_time);
4237 				percent_time_down_scheduled = (double)(((double)temp_subject->scheduled_time_down * 100.0) / (double)total_time);
4238 				percent_time_down_unscheduled = percent_time_down - percent_time_down_scheduled;
4239 				percent_time_unreachable = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)total_time);
4240 				percent_time_unreachable_scheduled = (double)(((double)temp_subject->scheduled_time_unreachable * 100.0) / (double)total_time);
4241 				percent_time_unreachable_unscheduled = percent_time_unreachable - percent_time_unreachable_scheduled;
4242 				percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
4243 				percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time);
4244 				percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled;
4245 				percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time);
4246 				percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time);
4247 				if(time_determinate > 0) {
4248 					percent_time_up_known = (double)(((double)temp_subject->time_up * 100.0) / (double)time_determinate);
4249 					percent_time_up_scheduled_known = (double)(((double)temp_subject->scheduled_time_up * 100.0) / (double)time_determinate);
4250 					percent_time_up_unscheduled_known = percent_time_up_known - percent_time_up_scheduled_known;
4251 					percent_time_down_known = (double)(((double)temp_subject->time_down * 100.0) / (double)time_determinate);
4252 					percent_time_down_scheduled_known = (double)(((double)temp_subject->scheduled_time_down * 100.0) / (double)time_determinate);
4253 					percent_time_down_unscheduled_known = percent_time_down_known - percent_time_down_scheduled_known;
4254 					percent_time_unreachable_known = (double)(((double)temp_subject->time_unreachable * 100.0) / (double)time_determinate);
4255 					percent_time_unreachable_scheduled_known = (double)(((double)temp_subject->scheduled_time_unreachable * 100.0) / (double)time_determinate);
4256 					percent_time_unreachable_unscheduled_known = percent_time_unreachable_known - percent_time_unreachable_scheduled_known;
4257 					}
4258 				}
4259 
4260 			if(output_format == HTML_OUTPUT) {
4261 
4262 				if(odd) {
4263 					odd = 0;
4264 					bgclass = "Odd";
4265 					}
4266 				else {
4267 					odd = 1;
4268 					bgclass = "Even";
4269 					}
4270 
4271 				printf("<tr CLASS='data%s'><td CLASS='data%s'>", bgclass, bgclass);
4272 				host_report_url(temp_subject->host_name, temp_subject->host_name);
4273 				printf("</td><td CLASS='hostUP'>%2.3f%% (%2.3f%%)</td><td CLASS='hostDOWN'>%2.3f%% (%2.3f%%)</td><td CLASS='hostUNREACHABLE'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", percent_time_up, percent_time_up_known, percent_time_down, percent_time_down_known, percent_time_unreachable, percent_time_unreachable_known, bgclass, percent_time_indeterminate);
4274 				}
4275 			else if(output_format == CSV_OUTPUT) {
4276 
4277 				/* host name */
4278 				printf("\"%s\",", temp_subject->host_name);
4279 
4280 				/* up times */
4281 				printf(" %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%,", temp_subject->scheduled_time_up, percent_time_up_scheduled, percent_time_up_scheduled_known, temp_subject->time_up - temp_subject->scheduled_time_up, percent_time_up_unscheduled, percent_time_up_unscheduled_known, temp_subject->time_up, percent_time_up, percent_time_up_known);
4282 
4283 				/* down times */
4284 				printf(" %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%,", temp_subject->scheduled_time_down, percent_time_down_scheduled, percent_time_down_scheduled_known, temp_subject->time_down - temp_subject->scheduled_time_down, percent_time_down_unscheduled, percent_time_down_unscheduled_known, temp_subject->time_down, percent_time_down, percent_time_down_known);
4285 
4286 				/* unreachable times */
4287 				printf(" %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%,", temp_subject->scheduled_time_unreachable, percent_time_unreachable_scheduled, percent_time_unreachable_scheduled_known, temp_subject->time_unreachable - temp_subject->scheduled_time_unreachable, percent_time_unreachable_unscheduled, percent_time_unreachable_unscheduled_known, temp_subject->time_unreachable, percent_time_unreachable, percent_time_unreachable_known);
4288 
4289 				/* indeterminate times */
4290 				printf(" %lu, %2.3f%%, %lu, %2.3f%%, %lu, %2.3f%%\n", temp_subject->time_indeterminate_notrunning, percent_time_indeterminate_notrunning, temp_subject->time_indeterminate_nodata, percent_time_indeterminate_nodata, time_indeterminate, percent_time_indeterminate);
4291 				}
4292 
4293 			get_running_average(&average_percent_time_up, percent_time_up, current_subject);
4294 			get_running_average(&average_percent_time_up_known, percent_time_up_known, current_subject);
4295 			get_running_average(&average_percent_time_down, percent_time_down, current_subject);
4296 			get_running_average(&average_percent_time_down_known, percent_time_down_known, current_subject);
4297 			get_running_average(&average_percent_time_unreachable, percent_time_unreachable, current_subject);
4298 			get_running_average(&average_percent_time_unreachable_known, percent_time_unreachable_known, current_subject);
4299 			get_running_average(&average_percent_time_indeterminate, percent_time_indeterminate, current_subject);
4300 			}
4301 
4302 		if(output_format == HTML_OUTPUT) {
4303 
4304 			/* average statistics */
4305 			if(odd) {
4306 				odd = 0;
4307 				bgclass = "Odd";
4308 				}
4309 			else {
4310 				odd = 1;
4311 				bgclass = "Even";
4312 				}
4313 			printf("<tr CLASS='data%s'><td CLASS='data%s'>Average</td><td CLASS='hostUP'>%2.3f%% (%2.3f%%)</td><td CLASS='hostDOWN'>%2.3f%% (%2.3f%%)</td><td CLASS='hostUNREACHABLE'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>", bgclass, bgclass, average_percent_time_up, average_percent_time_up_known, average_percent_time_down, average_percent_time_down_known, average_percent_time_unreachable, average_percent_time_unreachable_known, bgclass, average_percent_time_indeterminate);
4314 
4315 			printf("</table>\n");
4316 			printf("</DIV>\n");
4317 			}
4318 		}
4319 
4320 	return;
4321 	}
4322 
4323 
4324 /* display service availability */
display_service_availability(void)4325 void display_service_availability(void) {
4326 	unsigned long total_time;
4327 	unsigned long time_determinate;
4328 	unsigned long time_indeterminate;
4329 	avail_subject *temp_subject;
4330 	service *temp_service;
4331 	int days, hours, minutes, seconds;
4332 	char time_ok_string[48];
4333 	char time_warning_string[48];
4334 	char time_unknown_string[48];
4335 	char time_critical_string[48];
4336 	char time_indeterminate_string[48];
4337 	char time_determinate_string[48];
4338 	char total_time_string[48];
4339 	double percent_time_ok = 0.0;
4340 	double percent_time_warning = 0.0;
4341 	double percent_time_unknown = 0.0;
4342 	double percent_time_critical = 0.0;
4343 	double percent_time_indeterminate = 0.0;
4344 	double percent_time_ok_known = 0.0;
4345 	double percent_time_warning_known = 0.0;
4346 	double percent_time_unknown_known = 0.0;
4347 	double percent_time_critical_known = 0.0;
4348 
4349 	char time_critical_scheduled_string[48];
4350 	char time_critical_unscheduled_string[48];
4351 	double percent_time_critical_scheduled = 0.0;
4352 	double percent_time_critical_unscheduled = 0.0;
4353 	double percent_time_critical_scheduled_known = 0.0;
4354 	double percent_time_critical_unscheduled_known = 0.0;
4355 	char time_unknown_scheduled_string[48];
4356 	char time_unknown_unscheduled_string[48];
4357 	double percent_time_unknown_scheduled = 0.0;
4358 	double percent_time_unknown_unscheduled = 0.0;
4359 	double percent_time_unknown_scheduled_known = 0.0;
4360 	double percent_time_unknown_unscheduled_known = 0.0;
4361 	char time_warning_scheduled_string[48];
4362 	char time_warning_unscheduled_string[48];
4363 	double percent_time_warning_scheduled = 0.0;
4364 	double percent_time_warning_unscheduled = 0.0;
4365 	double percent_time_warning_scheduled_known = 0.0;
4366 	double percent_time_warning_unscheduled_known = 0.0;
4367 	char time_ok_scheduled_string[48];
4368 	char time_ok_unscheduled_string[48];
4369 	double percent_time_ok_scheduled = 0.0;
4370 	double percent_time_ok_unscheduled = 0.0;
4371 	double percent_time_ok_scheduled_known = 0.0;
4372 	double percent_time_ok_unscheduled_known = 0.0;
4373 
4374 	double average_percent_time_ok = 0.0;
4375 	double average_percent_time_ok_known = 0.0;
4376 	double average_percent_time_unknown = 0.0;
4377 	double average_percent_time_unknown_known = 0.0;
4378 	double average_percent_time_warning = 0.0;
4379 	double average_percent_time_warning_known = 0.0;
4380 	double average_percent_time_critical = 0.0;
4381 	double average_percent_time_critical_known = 0.0;
4382 	double average_percent_time_indeterminate = 0.0;
4383 
4384 	int current_subject = 0;
4385 
4386 	char time_indeterminate_scheduled_string[48];
4387 	char time_indeterminate_unscheduled_string[48];
4388 	double percent_time_indeterminate_scheduled = 0.0;
4389 	double percent_time_indeterminate_unscheduled = 0.0;
4390 	char time_indeterminate_notrunning_string[48];
4391 	char time_indeterminate_nodata_string[48];
4392 	double percent_time_indeterminate_notrunning = 0.0;
4393 	double percent_time_indeterminate_nodata = 0.0;
4394 
4395 	int odd = 1;
4396 	char *bgclass = "";
4397 	char last_host[128] = "";
4398 
4399 
4400 	/* calculate total time during period based on timeperiod used for reporting */
4401 	total_time = calculate_total_time(t1, t2);
4402 
4403 	/* we're only getting data for one service */
4404 	if(show_all_services == FALSE) {
4405 
4406 		temp_subject = find_subject(SERVICE_SUBJECT, host_name, svc_description);
4407 		if(temp_subject == NULL)
4408 			return;
4409 
4410 		temp_service = find_service(temp_subject->host_name, temp_subject->service_description);
4411 		if(temp_service == NULL)
4412 			return;
4413 
4414 		/* the user isn't authorized to view this service */
4415 		if(is_authorized_for_service(temp_service, &current_authdata) == FALSE)
4416 			return;
4417 
4418 		time_determinate = temp_subject->time_ok + temp_subject->time_warning + temp_subject->time_unknown + temp_subject->time_critical;
4419 		time_indeterminate = total_time - time_determinate;
4420 
4421 		/* adjust indeterminate time due to insufficient data (not all was caught) */
4422 		temp_subject->time_indeterminate_nodata = time_indeterminate - temp_subject->time_indeterminate_notrunning;
4423 
4424 		/* ok states */
4425 		get_time_breakdown(temp_subject->time_ok, &days, &hours, &minutes, &seconds);
4426 		snprintf(time_ok_string, sizeof(time_ok_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4427 		get_time_breakdown(temp_subject->scheduled_time_ok, &days, &hours, &minutes, &seconds);
4428 		snprintf(time_ok_scheduled_string, sizeof(time_ok_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4429 		get_time_breakdown(temp_subject->time_ok - temp_subject->scheduled_time_ok, &days, &hours, &minutes, &seconds);
4430 		snprintf(time_ok_unscheduled_string, sizeof(time_ok_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4431 
4432 		/* warning states */
4433 		get_time_breakdown(temp_subject->time_warning, &days, &hours, &minutes, &seconds);
4434 		snprintf(time_warning_string, sizeof(time_warning_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4435 		get_time_breakdown(temp_subject->scheduled_time_warning, &days, &hours, &minutes, &seconds);
4436 		snprintf(time_warning_scheduled_string, sizeof(time_warning_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4437 		get_time_breakdown(temp_subject->time_warning - temp_subject->scheduled_time_warning, &days, &hours, &minutes, &seconds);
4438 		snprintf(time_warning_unscheduled_string, sizeof(time_warning_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4439 
4440 		/* unknown states */
4441 		get_time_breakdown(temp_subject->time_unknown, &days, &hours, &minutes, &seconds);
4442 		snprintf(time_unknown_string, sizeof(time_unknown_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4443 		get_time_breakdown(temp_subject->scheduled_time_unknown, &days, &hours, &minutes, &seconds);
4444 		snprintf(time_unknown_scheduled_string, sizeof(time_unknown_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4445 		get_time_breakdown(temp_subject->time_unknown - temp_subject->scheduled_time_unknown, &days, &hours, &minutes, &seconds);
4446 		snprintf(time_unknown_unscheduled_string, sizeof(time_unknown_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4447 
4448 		/* critical states */
4449 		get_time_breakdown(temp_subject->time_critical, &days, &hours, &minutes, &seconds);
4450 		snprintf(time_critical_string, sizeof(time_critical_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4451 		get_time_breakdown(temp_subject->scheduled_time_critical, &days, &hours, &minutes, &seconds);
4452 		snprintf(time_critical_scheduled_string, sizeof(time_critical_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4453 		get_time_breakdown(temp_subject->time_critical - temp_subject->scheduled_time_critical, &days, &hours, &minutes, &seconds);
4454 		snprintf(time_critical_unscheduled_string, sizeof(time_critical_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4455 
4456 		/* indeterminate time */
4457 		get_time_breakdown(time_indeterminate, &days, &hours, &minutes, &seconds);
4458 		snprintf(time_indeterminate_string, sizeof(time_indeterminate_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4459 		get_time_breakdown(temp_subject->scheduled_time_indeterminate, &days, &hours, &minutes, &seconds);
4460 		snprintf(time_indeterminate_scheduled_string, sizeof(time_indeterminate_scheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4461 		get_time_breakdown(time_indeterminate - temp_subject->scheduled_time_indeterminate, &days, &hours, &minutes, &seconds);
4462 		snprintf(time_indeterminate_unscheduled_string, sizeof(time_indeterminate_unscheduled_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4463 		get_time_breakdown(temp_subject->time_indeterminate_notrunning, &days, &hours, &minutes, &seconds);
4464 		snprintf(time_indeterminate_notrunning_string, sizeof(time_indeterminate_notrunning_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4465 		get_time_breakdown(temp_subject->time_indeterminate_nodata, &days, &hours, &minutes, &seconds);
4466 		snprintf(time_indeterminate_nodata_string, sizeof(time_indeterminate_nodata_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4467 
4468 		get_time_breakdown(time_determinate, &days, &hours, &minutes, &seconds);
4469 		snprintf(time_determinate_string, sizeof(time_determinate_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4470 
4471 		get_time_breakdown(total_time, &days, &hours, &minutes, &seconds);
4472 		snprintf(total_time_string, sizeof(total_time_string) - 1, "%dd %dh %dm %ds", days, hours, minutes, seconds);
4473 
4474 		if(total_time > 0) {
4475 			percent_time_ok = (double)(((double)temp_subject->time_ok * 100.0) / (double)total_time);
4476 			percent_time_ok_scheduled = (double)(((double)temp_subject->scheduled_time_ok * 100.0) / (double)total_time);
4477 			percent_time_ok_unscheduled = percent_time_ok - percent_time_ok_scheduled;
4478 			percent_time_warning = (double)(((double)temp_subject->time_warning * 100.0) / (double)total_time);
4479 			percent_time_warning_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time);
4480 			percent_time_warning_unscheduled = percent_time_warning - percent_time_warning_scheduled;
4481 			percent_time_unknown = (double)(((double)temp_subject->time_unknown * 100.0) / (double)total_time);
4482 			percent_time_unknown_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time);
4483 			percent_time_unknown_unscheduled = percent_time_unknown - percent_time_unknown_scheduled;
4484 			percent_time_critical = (double)(((double)temp_subject->time_critical * 100.0) / (double)total_time);
4485 			percent_time_critical_scheduled = (double)(((double)temp_subject->scheduled_time_critical * 100.0) / (double)total_time);
4486 			percent_time_critical_unscheduled = percent_time_critical - percent_time_critical_scheduled;
4487 			percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
4488 			percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time);
4489 			percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled;
4490 			percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time);
4491 			percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time);
4492 			if(time_determinate > 0) {
4493 				percent_time_ok_known = (double)(((double)temp_subject->time_ok * 100.0) / (double)time_determinate);
4494 				percent_time_ok_scheduled_known = (double)(((double)temp_subject->scheduled_time_ok * 100.0) / (double)time_determinate);
4495 				percent_time_ok_unscheduled_known = percent_time_ok_known - percent_time_ok_scheduled_known;
4496 				percent_time_warning_known = (double)(((double)temp_subject->time_warning * 100.0) / (double)time_determinate);
4497 				percent_time_warning_scheduled_known = (double)(((double)temp_subject->scheduled_time_warning * 100.0) / (double)time_determinate);
4498 				percent_time_warning_unscheduled_known = percent_time_warning_known - percent_time_warning_scheduled_known;
4499 				percent_time_unknown_known = (double)(((double)temp_subject->time_unknown * 100.0) / (double)time_determinate);
4500 				percent_time_unknown_scheduled_known = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)time_determinate);
4501 				percent_time_unknown_unscheduled_known = percent_time_unknown_known - percent_time_unknown_scheduled_known;
4502 				percent_time_critical_known = (double)(((double)temp_subject->time_critical * 100.0) / (double)time_determinate);
4503 				percent_time_critical_scheduled_known = (double)(((double)temp_subject->scheduled_time_critical * 100.0) / (double)time_determinate);
4504 				percent_time_critical_unscheduled_known = percent_time_critical_known - percent_time_critical_scheduled_known;
4505 				}
4506 			}
4507 
4508 		printf("<DIV ALIGN=CENTER CLASS='dataTitle'>Service State Breakdowns:</DIV>\n");
4509 #ifdef USE_TRENDS
4510 		printf("<p align='center'>\n");
4511 		printf("<a href='%s?host=%s", TRENDS_CGI, url_encode(host_name));
4512 		printf("&service=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d'>", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
4513 		printf("<img src='%s?createimage&smallimage&host=%s", TRENDS_CGI, url_encode(host_name));
4514 		printf("&service=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d' border=1 alt='Service State Trends' title='Service State Trends' width='500' height='20'>", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
4515 		printf("</a><br>\n");
4516 		printf("</p>\n");
4517 #endif
4518 
4519 		printf("<DIV ALIGN=CENTER>\n");
4520 		printf("<TABLE BORDER=0 CLASS='data'>\n");
4521 		printf("<TR><TH CLASS='data'>State</TH><TH CLASS='data'>Type / Reason</TH><TH CLASS='data'>Time</TH><TH CLASS='data'>%% Total Time</TH><TH CLASS='data'>%% Known Time</TH></TR>\n");
4522 
4523 		/* ok states */
4524 		printf("<tr CLASS='dataEven'><td CLASS='serviceOK' rowspan=3>OK</td>");
4525 		printf("<td CLASS='dataEven'>Unscheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'>%2.3f%%</td></tr>\n", time_ok_unscheduled_string, percent_time_ok_unscheduled, percent_time_ok_unscheduled_known);
4526 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>Scheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'>%2.3f%%</td></tr>\n", time_ok_scheduled_string, percent_time_ok_scheduled, percent_time_ok_scheduled_known);
4527 		printf("<tr CLASS='serviceOK'><td CLASS='serviceOK'>Total</td><td CLASS='serviceOK'>%s</td><td CLASS='serviceOK'>%2.3f%%</td><td CLASS='serviceOK'>%2.3f%%</td></tr>\n", time_ok_string, percent_time_ok, percent_time_ok_known);
4528 
4529 		/* warning states */
4530 		printf("<tr CLASS='dataOdd'><td CLASS='serviceWARNING' rowspan=3>WARNING</td>");
4531 		printf("<td CLASS='dataOdd'>Unscheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td CLASS='dataOdd'>%2.3f%%</td></tr>\n", time_warning_unscheduled_string, percent_time_warning_unscheduled, percent_time_warning_unscheduled_known);
4532 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd'>Scheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td CLASS='dataOdd'>%2.3f%%</td></tr>\n", time_warning_scheduled_string, percent_time_warning_scheduled, percent_time_warning_scheduled_known);
4533 		printf("<tr CLASS='serviceWARNING'><td CLASS='serviceWARNING'>Total</td><td CLASS='serviceWARNING'>%s</td><td CLASS='serviceWARNING'>%2.3f%%</td><td CLASS='serviceWARNING'>%2.3f%%</td></tr>\n", time_warning_string, percent_time_warning, percent_time_warning_known);
4534 
4535 		/* unknown states */
4536 		printf("<tr CLASS='dataEven'><td CLASS='serviceUNKNOWN' rowspan=3>UNKNOWN</td>");
4537 		printf("<td CLASS='dataEven'>Unscheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'>%2.3f%%</td></tr>\n", time_unknown_unscheduled_string, percent_time_unknown_unscheduled, percent_time_unknown_unscheduled_known);
4538 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>Scheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'>%2.3f%%</td></tr>\n", time_unknown_scheduled_string, percent_time_unknown_scheduled, percent_time_unknown_scheduled_known);
4539 		printf("<tr CLASS='serviceUNKNOWN'><td CLASS='serviceUNKNOWN'>Total</td><td CLASS='serviceUNKNOWN'>%s</td><td CLASS='serviceUNKNOWN'>%2.3f%%</td><td CLASS='serviceUNKNOWN'>%2.3f%%</td></tr>\n", time_unknown_string, percent_time_unknown, percent_time_unknown_known);
4540 
4541 		/* critical states */
4542 		printf("<tr CLASS='dataOdd'><td CLASS='serviceCRITICAL' rowspan=3>CRITICAL</td>");
4543 		printf("<td CLASS='dataOdd'>Unscheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td CLASS='dataOdd'>%2.3f%%</td></tr>\n", time_critical_unscheduled_string, percent_time_critical_unscheduled, percent_time_critical_unscheduled_known);
4544 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd'>Scheduled</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>%2.3f%%</td><td CLASS='dataOdd'>%2.3f%%</td></tr>\n", time_critical_scheduled_string, percent_time_critical_scheduled, percent_time_critical_scheduled_known);
4545 		printf("<tr CLASS='serviceCRITICAL'><td CLASS='serviceCRITICAL'>Total</td><td CLASS='serviceCRITICAL'>%s</td><td CLASS='serviceCRITICAL'>%2.3f%%</td><td CLASS='serviceCRITICAL'>%2.3f%%</td></tr>\n", time_critical_string, percent_time_critical, percent_time_critical_known);
4546 
4547 
4548 		printf("<tr CLASS='dataEven'><td CLASS='dataEven' rowspan=3>Undetermined</td>");
4549 		/*
4550 		printf("<td CLASS='dataEven'>Unscheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'></td></tr>\n",time_indeterminate_unscheduled_string,percent_time_indeterminate_unscheduled);
4551 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>Scheduled</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'></td></tr>\n",time_indeterminate_scheduled_string,percent_time_indeterminate_scheduled);
4552 		*/
4553 		printf("<td CLASS='dataEven'>Nagios Not Running</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'></td></tr>\n", time_indeterminate_notrunning_string, percent_time_indeterminate_notrunning);
4554 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>Insufficient Data</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'></td></tr>\n", time_indeterminate_nodata_string, percent_time_indeterminate_nodata);
4555 		printf("<tr CLASS='dataEven'><td CLASS='dataEven'>Total</td><td CLASS='dataEven'>%s</td><td CLASS='dataEven'>%2.3f%%</td><td CLASS='dataEven'></td></tr>\n", time_indeterminate_string, percent_time_indeterminate);
4556 
4557 		printf("<tr><td colspan=3></td></tr>\n");
4558 		printf("<tr CLASS='dataOdd'><td CLASS='dataOdd'>All</td><td CLASS='dataOdd'>Total</td><td CLASS='dataOdd'>%s</td><td CLASS='dataOdd'>100.000%%</td><td CLASS='dataOdd'>100.000%%</td></tr>\n", total_time_string);
4559 		printf("</table>\n");
4560 		printf("</DIV>\n");
4561 
4562 
4563 		write_log_entries(temp_subject);
4564 		}
4565 
4566 
4567 	/* display data for all services */
4568 	else {
4569 
4570 		if(output_format == HTML_OUTPUT) {
4571 
4572 			printf("<DIV ALIGN=CENTER CLASS='dataTitle'>Service State Breakdowns:</DIV>\n");
4573 
4574 			printf("<DIV ALIGN=CENTER>\n");
4575 			printf("<TABLE BORDER=0 CLASS='data'>\n");
4576 			printf("<TR><TH CLASS='data'>Host</TH><TH CLASS='data'>Service</TH><TH CLASS='data'>%% Time OK</TH><TH CLASS='data'>%% Time Warning</TH><TH CLASS='data'>%% Time Unknown</TH><TH CLASS='data'>%% Time Critical</TH><TH CLASS='data'>%% Time Undetermined</TH></TR>\n");
4577 			}
4578 		else if(output_format == CSV_OUTPUT) {
4579 			printf("HOST_NAME, SERVICE_DESCRIPTION,");
4580 
4581 			printf(" TIME_OK_SCHEDULED, PERCENT_TIME_OK_SCHEDULED, PERCENT_KNOWN_TIME_OK_SCHEDULED, TIME_OK_UNSCHEDULED, PERCENT_TIME_OK_UNSCHEDULED, PERCENT_KNOWN_TIME_OK_UNSCHEDULED, TOTAL_TIME_OK, PERCENT_TOTAL_TIME_OK, PERCENT_KNOWN_TIME_OK,");
4582 
4583 			printf(" TIME_WARNING_SCHEDULED, PERCENT_TIME_WARNING_SCHEDULED, PERCENT_KNOWN_TIME_WARNING_SCHEDULED, TIME_WARNING_UNSCHEDULED, PERCENT_TIME_WARNING_UNSCHEDULED, PERCENT_KNOWN_TIME_WARNING_UNSCHEDULED, TOTAL_TIME_WARNING, PERCENT_TOTAL_TIME_WARNING, PERCENT_KNOWN_TIME_WARNING,");
4584 
4585 			printf(" TIME_UNKNOWN_SCHEDULED, PERCENT_TIME_UNKNOWN_SCHEDULED, PERCENT_KNOWN_TIME_UNKNOWN_SCHEDULED, TIME_UNKNOWN_UNSCHEDULED, PERCENT_TIME_UNKNOWN_UNSCHEDULED, PERCENT_KNOWN_TIME_UNKNOWN_UNSCHEDULED, TOTAL_TIME_UNKNOWN, PERCENT_TOTAL_TIME_UNKNOWN, PERCENT_KNOWN_TIME_UNKNOWN,");
4586 
4587 			printf(" TIME_CRITICAL_SCHEDULED, PERCENT_TIME_CRITICAL_SCHEDULED, PERCENT_KNOWN_TIME_CRITICAL_SCHEDULED, TIME_CRITICAL_UNSCHEDULED, PERCENT_TIME_CRITICAL_UNSCHEDULED, PERCENT_KNOWN_TIME_CRITICAL_UNSCHEDULED, TOTAL_TIME_CRITICAL, PERCENT_TOTAL_TIME_CRITICAL, PERCENT_KNOWN_TIME_CRITICAL,");
4588 
4589 			printf(" TIME_UNDETERMINED_NOT_RUNNING, PERCENT_TIME_UNDETERMINED_NOT_RUNNING, TIME_UNDETERMINED_NO_DATA, PERCENT_TIME_UNDETERMINED_NO_DATA, TOTAL_TIME_UNDETERMINED, PERCENT_TOTAL_TIME_UNDETERMINED\n");
4590 			}
4591 
4592 
4593 		for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
4594 
4595 			if(temp_subject->type != SERVICE_SUBJECT)
4596 				continue;
4597 
4598 			temp_service = find_service(temp_subject->host_name, temp_subject->service_description);
4599 			if(temp_service == NULL)
4600 				continue;
4601 
4602 			/* the user isn't authorized to view this service */
4603 			if(is_authorized_for_service(temp_service, &current_authdata) == FALSE)
4604 				continue;
4605 
4606 			current_subject++;
4607 
4608 			time_determinate = temp_subject->time_ok + temp_subject->time_warning + temp_subject->time_unknown + temp_subject->time_critical;
4609 			time_indeterminate = total_time - time_determinate;
4610 
4611 			/* adjust indeterminate time due to insufficient data (not all was caught) */
4612 			temp_subject->time_indeterminate_nodata = time_indeterminate - temp_subject->time_indeterminate_notrunning;
4613 
4614 			/* initialize values */
4615 			percent_time_ok = 0.0;
4616 			percent_time_ok_scheduled = 0.0;
4617 			percent_time_ok_unscheduled = 0.0;
4618 			percent_time_warning = 0.0;
4619 			percent_time_warning_scheduled = 0.0;
4620 			percent_time_warning_unscheduled = 0.0;
4621 			percent_time_unknown = 0.0;
4622 			percent_time_unknown_scheduled = 0.0;
4623 			percent_time_unknown_unscheduled = 0.0;
4624 			percent_time_critical = 0.0;
4625 			percent_time_critical_scheduled = 0.0;
4626 			percent_time_critical_unscheduled = 0.0;
4627 			percent_time_indeterminate = 0.0;
4628 			percent_time_indeterminate_scheduled = 0.0;
4629 			percent_time_indeterminate_unscheduled = 0.0;
4630 			percent_time_indeterminate_notrunning = 0.0;
4631 			percent_time_indeterminate_nodata = 0.0;
4632 			percent_time_ok_known = 0.0;
4633 			percent_time_ok_scheduled_known = 0.0;
4634 			percent_time_ok_unscheduled_known = 0.0;
4635 			percent_time_warning_known = 0.0;
4636 			percent_time_warning_scheduled_known = 0.0;
4637 			percent_time_warning_unscheduled_known = 0.0;
4638 			percent_time_unknown_known = 0.0;
4639 			percent_time_unknown_scheduled_known = 0.0;
4640 			percent_time_unknown_unscheduled_known = 0.0;
4641 			percent_time_critical_known = 0.0;
4642 			percent_time_critical_scheduled_known = 0.0;
4643 			percent_time_critical_unscheduled_known = 0.0;
4644 
4645 			if(total_time > 0) {
4646 				percent_time_ok = (double)(((double)temp_subject->time_ok * 100.0) / (double)total_time);
4647 				percent_time_ok_scheduled = (double)(((double)temp_subject->scheduled_time_ok * 100.0) / (double)total_time);
4648 				percent_time_ok_unscheduled = percent_time_ok - percent_time_ok_scheduled;
4649 				percent_time_warning = (double)(((double)temp_subject->time_warning * 100.0) / (double)total_time);
4650 				percent_time_warning_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time);
4651 				percent_time_warning_unscheduled = percent_time_warning - percent_time_warning_scheduled;
4652 				percent_time_unknown = (double)(((double)temp_subject->time_unknown * 100.0) / (double)total_time);
4653 				percent_time_unknown_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time);
4654 				percent_time_unknown_unscheduled = percent_time_unknown - percent_time_unknown_scheduled;
4655 				percent_time_critical = (double)(((double)temp_subject->time_critical * 100.0) / (double)total_time);
4656 				percent_time_critical_scheduled = (double)(((double)temp_subject->scheduled_time_critical * 100.0) / (double)total_time);
4657 				percent_time_critical_unscheduled = percent_time_critical - percent_time_critical_scheduled;
4658 				percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time);
4659 				percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time);
4660 				percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled;
4661 				percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time);
4662 				percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time);
4663 				if(time_determinate > 0) {
4664 					percent_time_ok_known = (double)(((double)temp_subject->time_ok * 100.0) / (double)time_determinate);
4665 					percent_time_ok_scheduled_known = (double)(((double)temp_subject->scheduled_time_ok * 100.0) / (double)time_determinate);
4666 					percent_time_ok_unscheduled_known = percent_time_ok_known - percent_time_ok_scheduled_known;
4667 					percent_time_warning_known = (double)(((double)temp_subject->time_warning * 100.0) / (double)time_determinate);
4668 					percent_time_warning_scheduled_known = (double)(((double)temp_subject->scheduled_time_warning * 100.0) / (double)time_determinate);
4669 					percent_time_warning_unscheduled_known = percent_time_warning_known - percent_time_warning_scheduled_known;
4670 					percent_time_unknown_known = (double)(((double)temp_subject->time_unknown * 100.0) / (double)time_determinate);
4671 					percent_time_unknown_scheduled_known = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)time_determinate);
4672 					percent_time_unknown_unscheduled_known = percent_time_unknown_known - percent_time_unknown_scheduled_known;
4673 					percent_time_critical_known = (double)(((double)temp_subject->time_critical * 100.0) / (double)time_determinate);
4674 					percent_time_critical_scheduled_known = (double)(((double)temp_subject->scheduled_time_critical * 100.0) / (double)time_determinate);
4675 					percent_time_critical_unscheduled_known = percent_time_critical_known - percent_time_critical_scheduled_known;
4676 					}
4677 				}
4678 
4679 			if(output_format == HTML_OUTPUT) {
4680 
4681 				if(odd) {
4682 					odd = 0;
4683 					bgclass = "Odd";
4684 					}
4685 				else {
4686 					odd = 1;
4687 					bgclass = "Even";
4688 					}
4689 
4690 				printf("<tr CLASS='data%s'><td CLASS='data%s'>", bgclass, bgclass);
4691 				if(strcmp(temp_subject->host_name, last_host))
4692 					host_report_url(temp_subject->host_name, temp_subject->host_name);
4693 				printf("</td><td CLASS='data%s'>", bgclass);
4694 				service_report_url(temp_subject->host_name, temp_subject->service_description, temp_subject->service_description);
4695 				printf("</td><td CLASS='serviceOK'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceWARNING'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceUNKNOWN'>%2.3f%% (%2.3f%%)</td><td class='serviceCRITICAL'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", percent_time_ok, percent_time_ok_known, percent_time_warning, percent_time_warning_known, percent_time_unknown, percent_time_unknown_known, percent_time_critical, percent_time_critical_known, bgclass, percent_time_indeterminate);
4696 				}
4697 			else if(output_format == CSV_OUTPUT) {
4698 
4699 				/* host name and service description */
4700 				printf("\"%s\", \"%s\",", temp_subject->host_name, temp_subject->service_description);
4701 
4702 				/* ok times */
4703 				printf(" %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%,", temp_subject->scheduled_time_ok, percent_time_ok_scheduled, percent_time_ok_scheduled_known, temp_subject->time_ok - temp_subject->scheduled_time_ok, percent_time_ok_unscheduled, percent_time_ok_unscheduled_known, temp_subject->time_ok, percent_time_ok, percent_time_ok_known);
4704 
4705 				/* warning times */
4706 				printf(" %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%,", temp_subject->scheduled_time_warning, percent_time_warning_scheduled, percent_time_warning_scheduled_known, temp_subject->time_warning - temp_subject->scheduled_time_warning, percent_time_warning_unscheduled, percent_time_warning_unscheduled_known, temp_subject->time_warning, percent_time_warning, percent_time_warning_known);
4707 
4708 				/* unknown times */
4709 				printf(" %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%,", temp_subject->scheduled_time_unknown, percent_time_unknown_scheduled, percent_time_unknown_scheduled_known, temp_subject->time_unknown - temp_subject->scheduled_time_unknown, percent_time_unknown_unscheduled, percent_time_unknown_unscheduled_known, temp_subject->time_unknown, percent_time_unknown, percent_time_unknown_known);
4710 
4711 				/* critical times */
4712 				printf(" %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%, %lu, %2.3f%%, %2.3f%%,", temp_subject->scheduled_time_critical, percent_time_critical_scheduled, percent_time_critical_scheduled_known, temp_subject->time_critical - temp_subject->scheduled_time_critical, percent_time_critical_unscheduled, percent_time_critical_unscheduled_known, temp_subject->time_critical, percent_time_critical, percent_time_critical_known);
4713 
4714 				/* indeterminate times */
4715 				printf(" %lu, %2.3f%%, %lu, %2.3f%%, %lu, %2.3f%%\n", temp_subject->time_indeterminate_notrunning, percent_time_indeterminate_notrunning, temp_subject->time_indeterminate_nodata, percent_time_indeterminate_nodata, time_indeterminate, percent_time_indeterminate);
4716 				}
4717 
4718 			strncpy(last_host, temp_subject->host_name, sizeof(last_host) - 1);
4719 			last_host[sizeof(last_host) - 1] = '\x0';
4720 
4721 			get_running_average(&average_percent_time_ok, percent_time_ok, current_subject);
4722 			get_running_average(&average_percent_time_ok_known, percent_time_ok_known, current_subject);
4723 			get_running_average(&average_percent_time_unknown, percent_time_unknown, current_subject);
4724 			get_running_average(&average_percent_time_unknown_known, percent_time_unknown_known, current_subject);
4725 			get_running_average(&average_percent_time_warning, percent_time_warning, current_subject);
4726 			get_running_average(&average_percent_time_warning_known, percent_time_warning_known, current_subject);
4727 			get_running_average(&average_percent_time_critical, percent_time_critical, current_subject);
4728 			get_running_average(&average_percent_time_critical_known, percent_time_critical_known, current_subject);
4729 			get_running_average(&average_percent_time_indeterminate, percent_time_indeterminate, current_subject);
4730 			}
4731 
4732 		if(output_format == HTML_OUTPUT) {
4733 
4734 			/* average statistics */
4735 			if(odd) {
4736 				odd = 0;
4737 				bgclass = "Odd";
4738 				}
4739 			else {
4740 				odd = 1;
4741 				bgclass = "Even";
4742 				}
4743 			printf("<tr CLASS='data%s'><td CLASS='data%s' colspan='2'>Average</td><td CLASS='serviceOK'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceWARNING'>%2.3f%% (%2.3f%%)</td><td CLASS='serviceUNKNOWN'>%2.3f%% (%2.3f%%)</td><td class='serviceCRITICAL'>%2.3f%% (%2.3f%%)</td><td class='data%s'>%2.3f%%</td></tr>\n", bgclass, bgclass, average_percent_time_ok, average_percent_time_ok_known, average_percent_time_warning, average_percent_time_warning_known, average_percent_time_unknown, average_percent_time_unknown_known, average_percent_time_critical, average_percent_time_critical_known, bgclass, average_percent_time_indeterminate);
4744 
4745 			printf("</table>\n");
4746 			printf("</DIV>\n");
4747 			}
4748 		}
4749 
4750 	return;
4751 	}
4752 
4753 
4754 
4755 
host_report_url(char * hn,char * label)4756 void host_report_url(char *hn, char *label) {
4757 
4758 	printf("<a href='%s?host=%s", AVAIL_CGI, url_encode(hn));
4759 	printf("&show_log_entries");
4760 	printf("&t1=%lu&t2=%lu", t1, t2);
4761 	printf("&backtrack=%d", backtrack_archives);
4762 	printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
4763 	printf("&assumeinitialstates=%s", (assume_initial_states == TRUE) ? "yes" : "no");
4764 	printf("&assumestatesduringnotrunning=%s", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
4765 	printf("&initialassumedhoststate=%d", initial_assumed_host_state);
4766 	printf("&initialassumedservicestate=%d", initial_assumed_service_state);
4767 	if(show_log_entries == TRUE)
4768 		printf("&show_log_entries");
4769 	if(full_log_entries == TRUE)
4770 		printf("&full_log_entries");
4771 	printf("&showscheduleddowntime=%s", (show_scheduled_downtime == TRUE) ? "yes" : "no");
4772 	if(current_timeperiod != NULL)
4773 		printf("&rpttimeperiod=%s", url_encode(current_timeperiod->name));
4774 	printf("'>%s</a>", label);
4775 
4776 	return;
4777 	}
4778 
4779 
service_report_url(char * hn,char * sd,char * label)4780 void service_report_url(char *hn, char *sd, char *label) {
4781 
4782 	printf("<a href='%s?host=%s", AVAIL_CGI, url_encode(hn));
4783 	printf("&service=%s", url_encode(sd));
4784 	printf("&t1=%lu&t2=%lu", t1, t2);
4785 	printf("&backtrack=%d", backtrack_archives);
4786 	printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
4787 	printf("&assumeinitialstates=%s", (assume_initial_states == TRUE) ? "yes" : "no");
4788 	printf("&assumestatesduringnotrunning=%s", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
4789 	printf("&initialassumedhoststate=%d", initial_assumed_host_state);
4790 	printf("&initialassumedservicestate=%d", initial_assumed_service_state);
4791 	if(show_log_entries == TRUE)
4792 		printf("&show_log_entries");
4793 	if(full_log_entries == TRUE)
4794 		printf("&full_log_entries");
4795 	printf("&showscheduleddowntime=%s", (show_scheduled_downtime == TRUE) ? "yes" : "no");
4796 	if(current_timeperiod != NULL)
4797 		printf("&rpttimeperiod=%s", url_encode(current_timeperiod->name));
4798 	printf("'>%s</a>", label);
4799 
4800 	return;
4801 	}
4802 
4803 
4804 /* calculates running average */
get_running_average(double * running_average,double new_value,int current_item)4805 void get_running_average(double *running_average, double new_value, int current_item) {
4806 
4807 	*running_average = (((*running_average * ((double)current_item - 1.0)) + new_value) / (double)current_item);
4808 
4809 	return;
4810 	}
4811 
4812 
4813 /* used in reports where a timeperiod is selected */
calculate_total_time(time_t start_time,time_t end_time)4814 unsigned long calculate_total_time(time_t start_time, time_t end_time) {
4815 	struct tm *t;
4816 	unsigned long midnight_today;
4817 	int weekday;
4818 	unsigned long total_time;
4819 	timerange *temp_timerange;
4820 	unsigned long temp_duration;
4821 	unsigned long temp_end;
4822 	unsigned long temp_start;
4823 	unsigned long start;
4824 	unsigned long end;
4825 
4826 	/* attempt to handle the current time_period */
4827 	if(current_timeperiod != NULL) {
4828 
4829 		/* "A day" is 86400 seconds */
4830 		t = localtime(&start_time);
4831 
4832 		/* calculate the start of the day (midnight, 00:00 hours) */
4833 		t->tm_sec = 0;
4834 		t->tm_min = 0;
4835 		t->tm_hour = 0;
4836 		t->tm_isdst = -1;
4837 		midnight_today = (unsigned long)mktime(t);
4838 		weekday = t->tm_wday;
4839 
4840 		total_time = 0;
4841 		while(midnight_today < end_time) {
4842 			temp_duration = 0;
4843 			temp_end = min(86400, t2 - midnight_today);
4844 			temp_start = 0;
4845 			if(t1 > midnight_today)
4846 				temp_start = t1 - midnight_today;
4847 
4848 			/* check all time ranges for this day of the week */
4849 			for(temp_timerange = current_timeperiod->days[weekday]; temp_timerange != NULL; temp_timerange = temp_timerange->next) {
4850 				start = max(temp_timerange->range_start, temp_start);
4851 				end = min(temp_timerange->range_end, temp_end);
4852 #ifdef DEBUG
4853 				printf("<li>Matching in timerange[%d]: %d -> %d (%ld -> %ld) %d -> %d = %ld<br>\n", weekday, temp_timerange->range_start, temp_timerange->range_end, temp_start, temp_end, start, end, end - start);
4854 #endif
4855 				if(end > start)
4856 					temp_duration += end - start;
4857 				}
4858 			total_time += temp_duration;
4859 			temp_start = 0;
4860 			midnight_today += 86400;
4861 			if(++weekday > 6)
4862 				weekday = 0;
4863 			}
4864 
4865 		return total_time;
4866 		}
4867 
4868 	/* no timeperiod was selected */
4869 	return end_time - start_time;
4870 	}
4871