1 /**************************************************************************
2 *
3 * HISTOGRAM.C - Nagios Alert Histogram CGI
4 *
5 * Copyright (c) 2001-2008 Ethan Galstad (egalstad@nagios.org)
6 * Last Modified: 10-15-2008
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/statusdata.h"
28
29 #include "../include/cgiutils.h"
30 #include "../include/getcgi.h"
31 #include "../include/cgiauth.h"
32
33 #include <gd.h> /* Boutell's GD library function */
34 #include <gdfonts.h> /* GD library small font definition */
35
36
37 /*#define DEBUG 1*/
38
39
40 #define HISTOGRAM_IMAGE "histogram.png"
41
42 /* archived state types */
43 #define AS_NO_DATA 0
44 #define AS_PROGRAM_START 1
45 #define AS_PROGRAM_END 2
46 #define AS_HOST_UP 3
47 #define AS_HOST_DOWN 4
48 #define AS_HOST_UNREACHABLE 5
49 #define AS_SVC_OK 6
50 #define AS_SVC_UNKNOWN 7
51 #define AS_SVC_WARNING 8
52 #define AS_SVC_CRITICAL 9
53
54
55 /* display types */
56 #define DISPLAY_HOST_HISTOGRAM 0
57 #define DISPLAY_SERVICE_HISTOGRAM 1
58 #define DISPLAY_NO_HISTOGRAM 2
59
60 /* input types */
61 #define GET_INPUT_NONE 0
62 #define GET_INPUT_TARGET_TYPE 1
63 #define GET_INPUT_HOST_TARGET 2
64 #define GET_INPUT_SERVICE_TARGET 3
65 #define GET_INPUT_OPTIONS 4
66
67 /* breakdown types */
68 #define BREAKDOWN_MONTHLY 0
69 #define BREAKDOWN_DAY_OF_MONTH 1
70 #define BREAKDOWN_DAY_OF_WEEK 2
71 #define BREAKDOWN_HOURLY 3
72
73 /* modes */
74 #define CREATE_HTML 0
75 #define CREATE_IMAGE 1
76
77 /* standard report times */
78 #define TIMEPERIOD_CUSTOM 0
79 #define TIMEPERIOD_TODAY 1
80 #define TIMEPERIOD_YESTERDAY 2
81 #define TIMEPERIOD_THISWEEK 3
82 #define TIMEPERIOD_LASTWEEK 4
83 #define TIMEPERIOD_THISMONTH 5
84 #define TIMEPERIOD_LASTMONTH 6
85 #define TIMEPERIOD_THISQUARTER 7
86 #define TIMEPERIOD_LASTQUARTER 8
87 #define TIMEPERIOD_THISYEAR 9
88 #define TIMEPERIOD_LASTYEAR 10
89 #define TIMEPERIOD_LAST24HOURS 11
90 #define TIMEPERIOD_LAST7DAYS 12
91 #define TIMEPERIOD_LAST31DAYS 13
92
93
94 #define MAX_ARCHIVE_SPREAD 65
95 #define MAX_ARCHIVE 65
96 #define MAX_ARCHIVE_BACKTRACKS 60
97
98 #define DRAWING_WIDTH 550
99 #define DRAWING_HEIGHT 195
100 #define DRAWING_X_OFFSET 60
101 #define DRAWING_Y_OFFSET 235
102
103 #define GRAPH_HOST_UP 1
104 #define GRAPH_HOST_DOWN 2
105 #define GRAPH_HOST_UNREACHABLE 4
106 #define GRAPH_SERVICE_OK 8
107 #define GRAPH_SERVICE_WARNING 16
108 #define GRAPH_SERVICE_UNKNOWN 32
109 #define GRAPH_SERVICE_CRITICAL 64
110
111 #define GRAPH_HOST_PROBLEMS 6
112 #define GRAPH_HOST_ALL 7
113
114 #define GRAPH_SERVICE_PROBLEMS 112
115 #define GRAPH_SERVICE_ALL 120
116
117 #define GRAPH_EVERYTHING 255
118
119
120 #define GRAPH_SOFT_STATETYPES 1
121 #define GRAPH_HARD_STATETYPES 2
122 #define GRAPH_ALL_STATETYPES 3
123
124
125
126
127 extern char main_config_file[MAX_FILENAME_LENGTH];
128 extern char url_html_path[MAX_FILENAME_LENGTH];
129 extern char url_images_path[MAX_FILENAME_LENGTH];
130 extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
131 extern char physical_images_path[MAX_FILENAME_LENGTH];
132
133 extern int log_rotation_method;
134
135 extern host *host_list;
136 extern service *service_list;
137
138
139
140 authdata current_authdata;
141
142
143 typedef struct timeslice_data_struct {
144 unsigned long service_ok;
145 unsigned long host_up;
146 unsigned long service_critical;
147 unsigned long host_down;
148 unsigned long service_unknown;
149 unsigned long host_unreachable;
150 unsigned long service_warning;
151 } timeslice_data;
152
153
154 timeslice_data *tsdata;
155
156
157 void convert_timeperiod_to_times(int);
158 void compute_report_times(void);
159 void graph_all_histogram_data(void);
160 void add_archived_state(int, time_t);
161 void read_archived_state_data(void);
162 void scan_log_file_for_archived_state_data(char *);
163 void draw_line(int, int, int, int, int);
164 void draw_dashed_line(int, int, int, int, int);
165
166 void document_header(int);
167 void document_footer(void);
168 int process_cgivars(void);
169
170
171 time_t t1;
172 time_t t2;
173
174 int start_second = 0;
175 int start_minute = 0;
176 int start_hour = 0;
177 int start_day = 1;
178 int start_month = 1;
179 int start_year = 2000;
180 int end_second = 0;
181 int end_minute = 0;
182 int end_hour = 24;
183 int end_day = 1;
184 int end_month = 1;
185 int end_year = 2000;
186
187 int display_type = DISPLAY_NO_HISTOGRAM;
188 int mode = CREATE_HTML;
189 int input_type = GET_INPUT_NONE;
190 int timeperiod_type = TIMEPERIOD_LAST24HOURS;
191 int breakdown_type = BREAKDOWN_HOURLY;
192 int compute_time_from_parts = FALSE;
193
194 int initial_states_logged = FALSE;
195 int assume_state_retention = TRUE;
196 int new_states_only = FALSE;
197
198 int last_state = AS_NO_DATA;
199 int program_restart_has_occurred = FALSE;
200
201 int graph_events = GRAPH_EVERYTHING;
202 int graph_statetypes = GRAPH_HARD_STATETYPES;
203
204 int embedded = FALSE;
205 int display_header = TRUE;
206
207 char *host_name = "";
208 char *svc_description = "";
209
210 gdImagePtr histogram_image = 0;
211 int color_white = 0;
212 int color_black = 0;
213 int color_red = 0;
214 int color_darkred = 0;
215 int color_green = 0;
216 int color_yellow = 0;
217 int color_orange = 0;
218 int color_lightgray = 0;
219 FILE *image_file = NULL;
220
221 int backtrack_archives = 0;
222 int earliest_archive = 0;
223 time_t earliest_time;
224 time_t latest_time;
225
226 int image_width = 900;
227 int image_height = 320;
228
229 int total_buckets = 96;
230
231
232
main(int argc,char ** argv)233 int main(int argc, char **argv) {
234 int result = OK;
235 char temp_buffer[MAX_INPUT_BUFFER];
236 char image_template[MAX_INPUT_BUFFER];
237 char start_timestring[MAX_INPUT_BUFFER];
238 char end_timestring[MAX_INPUT_BUFFER];
239 host *temp_host;
240 service *temp_service;
241 int is_authorized = TRUE;
242 int found = FALSE;
243 int days, hours, minutes, seconds;
244 char *first_service = NULL;
245 int x;
246 time_t t3;
247 time_t current_time;
248 struct tm *t;
249
250 /* initialize time period to last 24 hours */
251 time(&t2);
252 t1 = (time_t)(t2 - (60 * 60 * 24));
253
254 /* get the arguments passed in the URL */
255 process_cgivars();
256
257 /* reset internal CGI variables */
258 reset_cgi_vars();
259
260 /* read the CGI configuration file */
261 result = read_cgi_config_file(get_cgi_config_location());
262 if(result == ERROR) {
263 if(mode == CREATE_HTML) {
264 document_header(FALSE);
265 cgi_config_file_error(get_cgi_config_location());
266 document_footer();
267 }
268 return ERROR;
269 }
270
271 /* read the main configuration file */
272 result = read_main_config_file(main_config_file);
273 if(result == ERROR) {
274 if(mode == CREATE_HTML) {
275 document_header(FALSE);
276 main_config_file_error(main_config_file);
277 document_footer();
278 }
279 return ERROR;
280 }
281
282 /* read all object configuration data */
283 result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
284 if(result == ERROR) {
285 if(mode == CREATE_HTML) {
286 document_header(FALSE);
287 object_data_error();
288 document_footer();
289 }
290 return ERROR;
291 }
292
293 /* read all status data */
294 result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA);
295 if(result == ERROR) {
296 if(mode == CREATE_HTML) {
297 document_header(FALSE);
298 status_data_error();
299 document_footer();
300 }
301 free_memory();
302 return ERROR;
303 }
304
305 document_header(TRUE);
306
307 /* get authentication information */
308 get_authentication_information(¤t_authdata);
309
310 if(compute_time_from_parts == TRUE)
311 compute_report_times();
312
313 /* make sure times are sane, otherwise swap them */
314 if(t2 < t1) {
315 t3 = t2;
316 t2 = t1;
317 t1 = t3;
318 }
319
320
321 if(mode == CREATE_HTML && display_header == TRUE) {
322
323 /* begin top table */
324 printf("<table border=0 width=100%% cellspacing=0 cellpadding=0>\n");
325 printf("<tr>\n");
326
327 /* left column of the first row */
328 printf("<td align=left valign=top width=33%%>\n");
329
330 if(display_type == DISPLAY_HOST_HISTOGRAM)
331 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host Alert Histogram");
332 else if(display_type == DISPLAY_SERVICE_HISTOGRAM)
333 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service Alert Histogram");
334 else
335 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host and Service Alert Histogram");
336 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
337 display_info_table(temp_buffer, FALSE, ¤t_authdata);
338
339 if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
340
341 printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
342 printf("<TR><TD CLASS='linkBox'>\n");
343
344 if(display_type == DISPLAY_HOST_HISTOGRAM) {
345 #ifdef USE_TRENDS
346 printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Trends For This Host</a><BR>\n", TRENDS_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
347 #endif
348 printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s&show_log_entries'>View Availability Report For This Host</a><BR>\n", AVAIL_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
349 printf("<a href='%s?host=%s'>View Status Detail For This Host</a><BR>\n", STATUS_CGI, url_encode(host_name));
350 printf("<a href='%s?host=%s'>View History For This Host</a><BR>\n", HISTORY_CGI, url_encode(host_name));
351 printf("<a href='%s?host=%s'>View Notifications For This Host</a><BR>\n", NOTIFICATIONS_CGI, url_encode(host_name));
352 }
353 else {
354 #ifdef USE_TRENDS
355 printf("<a href='%s?host=%s", TRENDS_CGI, url_encode(host_name));
356 #endif
357 printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Trends For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
358 printf("<a href='%s?host=%s", AVAIL_CGI, url_encode(host_name));
359 printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s&show_log_entries'>View Availability Report For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
360 printf("<A HREF='%s?host=%s&", HISTORY_CGI, url_encode(host_name));
361 printf("service=%s'>View History For This Service</A><BR>\n", url_encode(svc_description));
362 printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
363 printf("service=%s'>View Notifications For This Service</A><BR>\n", url_encode(svc_description));
364 }
365
366 printf("</TD></TR>\n");
367 printf("</TABLE>\n");
368 }
369
370 printf("</td>\n");
371
372 /* center column of top row */
373 printf("<td align=center valign=top width=33%%>\n");
374
375 if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
376
377 printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
378 if(display_type == DISPLAY_HOST_HISTOGRAM)
379 printf("Host '%s'", host_name);
380 else if(display_type == DISPLAY_SERVICE_HISTOGRAM)
381 printf("Service '%s' On Host '%s'", svc_description, host_name);
382 printf("</DIV>\n");
383
384 printf("<BR>\n");
385
386 printf("<IMG SRC='%s%s' BORDER=0 ALT='%s Event Histogram' TITLE='%s Event Histogram'>\n", url_images_path, TRENDS_ICON, (display_type == DISPLAY_HOST_HISTOGRAM) ? "Host" : "Service", (display_type == DISPLAY_HOST_HISTOGRAM) ? "Host" : "Service");
387
388 printf("<BR CLEAR=ALL>\n");
389
390 get_time_string(&t1, start_timestring, sizeof(start_timestring) - 1, SHORT_DATE_TIME);
391 get_time_string(&t2, end_timestring, sizeof(end_timestring) - 1, SHORT_DATE_TIME);
392 printf("<div align=center class='reportRange'>%s to %s</div>\n", start_timestring, end_timestring);
393
394 get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds);
395 printf("<div align=center class='reportDuration'>Duration: %dd %dh %dm %ds</div>\n", days, hours, minutes, seconds);
396 }
397
398 printf("</td>\n");
399
400 /* right hand column of top row */
401 printf("<td align=right valign=bottom width=33%%>\n");
402
403 printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
404 printf("<table border=0 CLASS='optBox'>\n");
405
406 if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
407
408 printf("<tr><td CLASS='optBoxItem' valign=top align=left>Report period:</td><td CLASS='optBoxItem' valign=top align=left>Assume state retention:</td></tr>\n");
409 printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
410
411 printf("<input type='hidden' name='t1' value='%lu'>\n", (unsigned long)t1);
412 printf("<input type='hidden' name='t2' value='%lu'>\n", (unsigned long)t2);
413 printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
414 if(display_type == DISPLAY_SERVICE_HISTOGRAM)
415 printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
416
417 printf("<select name='timeperiod'>\n");
418 printf("<option value=custom>[ Current time range ]\n");
419 printf("<option value=today %s>Today\n", (timeperiod_type == TIMEPERIOD_TODAY) ? "SELECTED" : "");
420 printf("<option value=last24hours %s>Last 24 Hours\n", (timeperiod_type == TIMEPERIOD_LAST24HOURS) ? "SELECTED" : "");
421 printf("<option value=yesterday %s>Yesterday\n", (timeperiod_type == TIMEPERIOD_YESTERDAY) ? "SELECTED" : "");
422 printf("<option value=thisweek %s>This Week\n", (timeperiod_type == TIMEPERIOD_THISWEEK) ? "SELECTED" : "");
423 printf("<option value=last7days %s>Last 7 Days\n", (timeperiod_type == TIMEPERIOD_LAST7DAYS) ? "SELECTED" : "");
424 printf("<option value=lastweek %s>Last Week\n", (timeperiod_type == TIMEPERIOD_LASTWEEK) ? "SELECTED" : "");
425 printf("<option value=thismonth %s>This Month\n", (timeperiod_type == TIMEPERIOD_THISMONTH) ? "SELECTED" : "");
426 printf("<option value=last31days %s>Last 31 Days\n", (timeperiod_type == TIMEPERIOD_LAST31DAYS) ? "SELECTED" : "");
427 printf("<option value=lastmonth %s>Last Month\n", (timeperiod_type == TIMEPERIOD_LASTMONTH) ? "SELECTED" : "");
428 printf("<option value=thisyear %s>This Year\n", (timeperiod_type == TIMEPERIOD_THISYEAR) ? "SELECTED" : "");
429 printf("<option value=lastyear %s>Last Year\n", (timeperiod_type == TIMEPERIOD_LASTYEAR) ? "SELECTED" : "");
430 printf("</select>\n");
431 printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
432 printf("<select name='assumestateretention'>\n");
433 printf("<option value=yes %s>yes\n", (assume_state_retention == TRUE) ? "SELECTED" : "");
434 printf("<option value=no %s>no\n", (assume_state_retention == TRUE) ? "" : "SELECTED");
435 printf("</select>\n");
436 printf("</td></tr>\n");
437
438 printf("<tr><td CLASS='optBoxItem' valign=top align=left>Breakdown type:</td><td CLASS='optBoxItem' valign=top align=left>Initial states logged:</td></tr>\n");
439 printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
440 printf("<select name='breakdown'>\n");
441 printf("<option value=monthly %s>Month\n", (breakdown_type == BREAKDOWN_MONTHLY) ? "SELECTED" : "");
442 printf("<option value=dayofmonth %s>Day of the Month\n", (breakdown_type == BREAKDOWN_DAY_OF_MONTH) ? "SELECTED" : "");
443 printf("<option value=dayofweek %s>Day of the Week\n", (breakdown_type == BREAKDOWN_DAY_OF_WEEK) ? "SELECTED" : "");
444 printf("<option value=hourly %s>Hour of the Day\n", (breakdown_type == BREAKDOWN_HOURLY) ? "SELECTED" : "");
445 printf("</select>\n");
446 printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
447 printf("<select name='initialstateslogged'>\n");
448 printf("<option value=yes %s>yes\n", (initial_states_logged == TRUE) ? "SELECTED" : "");
449 printf("<option value=no %s>no\n", (initial_states_logged == TRUE) ? "" : "SELECTED");
450 printf("</select>\n");
451 printf("</td></tr>\n");
452
453 printf("<tr><td CLASS='optBoxItem' valign=top align=left>Events to graph:</td><td CLASS='optBoxItem' valign=top align=left>Ignore repeated states:</td></tr>\n");
454 printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
455 printf("<select name='graphevents'>\n");
456 if(display_type == DISPLAY_HOST_HISTOGRAM) {
457 printf("<option value=%d %s>All host events\n", GRAPH_HOST_ALL, (graph_events == GRAPH_HOST_ALL) ? "SELECTED" : "");
458 printf("<option value=%d %s>Host problem events\n", GRAPH_HOST_PROBLEMS, (graph_events == GRAPH_HOST_PROBLEMS) ? "SELECTED" : "");
459 printf("<option value=%d %s>Host up events\n", GRAPH_HOST_UP, (graph_events == GRAPH_HOST_UP) ? "SELECTED" : "");
460 printf("<option value=%d %s>Host down events\n", GRAPH_HOST_DOWN, (graph_events == GRAPH_HOST_DOWN) ? "SELECTED" : "");
461 printf("<option value=%d %s>Host unreachable events\n", GRAPH_HOST_UNREACHABLE, (graph_events == GRAPH_HOST_UNREACHABLE) ? "SELECTED" : "");
462 }
463 else {
464 printf("<option value=%d %s>All service events\n", GRAPH_SERVICE_ALL, (graph_events == GRAPH_SERVICE_ALL) ? "SELECTED" : "");
465 printf("<option value=%d %s>Service problem events\n", GRAPH_SERVICE_PROBLEMS, (graph_events == GRAPH_SERVICE_PROBLEMS) ? "SELECTED" : "");
466 printf("<option value=%d %s>Service ok events\n", GRAPH_SERVICE_OK, (graph_events == GRAPH_SERVICE_OK) ? "SELECTED" : "");
467 printf("<option value=%d %s>Service warning events\n", GRAPH_SERVICE_WARNING, (graph_events == GRAPH_SERVICE_WARNING) ? "SELECTED" : "");
468 printf("<option value=%d %s>Service unknown events\n", GRAPH_SERVICE_UNKNOWN, (graph_events == GRAPH_SERVICE_UNKNOWN) ? "SELECTED" : "");
469 printf("<option value=%d %s>Service critical events\n", GRAPH_SERVICE_CRITICAL, (graph_events == GRAPH_SERVICE_CRITICAL) ? "SELECTED" : "");
470 }
471 printf("</select>\n");
472 printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
473 printf("<select name='newstatesonly'>\n");
474 printf("<option value=yes %s>yes\n", (new_states_only == TRUE) ? "SELECTED" : "");
475 printf("<option value=no %s>no\n", (new_states_only == TRUE) ? "" : "SELECTED");
476 printf("</select>\n");
477 printf("</td></tr>\n");
478
479 printf("<tr><td CLASS='optBoxItem' valign=top align=left>State types to graph:</td><td CLASS='optBoxItem' valign=top align=left></td></tr>\n");
480 printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
481 printf("<select name='graphstatetypes'>\n");
482 printf("<option value=%d %s>Hard states\n", GRAPH_HARD_STATETYPES, (graph_statetypes == GRAPH_HARD_STATETYPES) ? "SELECTED" : "");
483 printf("<option value=%d %s>Soft states\n", GRAPH_SOFT_STATETYPES, (graph_statetypes == GRAPH_SOFT_STATETYPES) ? "SELECTED" : "");
484 printf("<option value=%d %s>Hard and soft states\n", GRAPH_ALL_STATETYPES, (graph_statetypes == GRAPH_ALL_STATETYPES) ? "SELECTED" : "");
485 printf("</select>\n");
486 printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
487 printf("<input type='submit' value='Update'>\n");
488 printf("</td></tr>\n");
489 }
490
491 /* display context-sensitive help */
492 printf("<tr><td></td><td align=right valign=bottom>\n");
493 if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
494 if(display_type == DISPLAY_HOST_HISTOGRAM)
495 display_context_help(CONTEXTHELP_HISTOGRAM_HOST);
496 else
497 display_context_help(CONTEXTHELP_HISTOGRAM_SERVICE);
498 }
499 else if(display_type == DISPLAY_NO_HISTOGRAM || input_type != GET_INPUT_NONE) {
500 if(input_type == GET_INPUT_NONE)
501 display_context_help(CONTEXTHELP_HISTOGRAM_MENU1);
502 else if(input_type == GET_INPUT_TARGET_TYPE)
503 display_context_help(CONTEXTHELP_HISTOGRAM_MENU1);
504 else if(input_type == GET_INPUT_HOST_TARGET)
505 display_context_help(CONTEXTHELP_HISTOGRAM_MENU2);
506 else if(input_type == GET_INPUT_SERVICE_TARGET)
507 display_context_help(CONTEXTHELP_HISTOGRAM_MENU3);
508 else if(input_type == GET_INPUT_OPTIONS)
509 display_context_help(CONTEXTHELP_HISTOGRAM_MENU4);
510 }
511 printf("</td></tr>\n");
512
513 printf("</table>\n");
514 printf("</form>\n");
515
516 printf("</td>\n");
517
518 /* end of top table */
519 printf("</tr>\n");
520 printf("</table>\n");
521 }
522
523 /* check authorization... */
524 if(display_type == DISPLAY_HOST_HISTOGRAM) {
525 temp_host = find_host(host_name);
526 if(temp_host == NULL || is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
527 is_authorized = FALSE;
528 }
529 else if(display_type == DISPLAY_SERVICE_HISTOGRAM) {
530 temp_service = find_service(host_name, svc_description);
531 if(temp_service == NULL || is_authorized_for_service(temp_service, ¤t_authdata) == FALSE)
532 is_authorized = FALSE;
533 }
534 if(is_authorized == FALSE) {
535
536 if(mode == CREATE_HTML)
537 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_HISTOGRAM) ? "host" : "service");
538
539 document_footer();
540 free_memory();
541 return ERROR;
542 }
543
544 if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
545
546 /* print URL to image */
547 if(mode == CREATE_HTML) {
548
549 printf("<BR><BR>\n");
550 printf("<DIV ALIGN=CENTER>\n");
551 printf("<IMG SRC='%s?createimage&t1=%lu&t2=%lu", HISTOGRAM_CGI, (unsigned long)t1, (unsigned long)t2);
552 printf("&host=%s", url_encode(host_name));
553 if(display_type == DISPLAY_SERVICE_HISTOGRAM)
554 printf("&service=%s", url_encode(svc_description));
555 printf("&breakdown=");
556 if(breakdown_type == BREAKDOWN_MONTHLY)
557 printf("monthly");
558 else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
559 printf("dayofmonth");
560 else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
561 printf("dayofweek");
562 else
563 printf("hourly");
564 printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
565 printf("&initialstateslogged=%s", (initial_states_logged == TRUE) ? "yes" : "no");
566 printf("&newstatesonly=%s", (new_states_only == TRUE) ? "yes" : "no");
567 printf("&graphevents=%d", graph_events);
568 printf("&graphstatetypes=%d", graph_statetypes);
569 printf("' BORDER=0 name='histogramimage'>\n");
570 printf("</DIV>\n");
571 }
572
573 /* read and process state data */
574 else {
575
576 /* allocate memory */
577 tsdata = NULL;
578 if(breakdown_type == BREAKDOWN_MONTHLY)
579 total_buckets = 12;
580 else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
581 total_buckets = 31;
582 else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
583 total_buckets = 7;
584 else
585 total_buckets = 96;
586
587 tsdata = (timeslice_data *)malloc(sizeof(timeslice_data) * total_buckets);
588 if(tsdata == NULL)
589 return ERROR;
590
591 for(x = 0; x < total_buckets; x++) {
592 tsdata[x].service_ok = 0L;
593 tsdata[x].service_unknown = 0L;
594 tsdata[x].service_warning = 0L;
595 tsdata[x].service_critical = 0L;
596 tsdata[x].host_up = 0L;
597 tsdata[x].host_down = 0L;
598 tsdata[x].host_unreachable = 0L;
599 }
600
601 /* read in all necessary archived state data */
602 read_archived_state_data();
603
604 #ifdef DEBUG
605 printf("Done reading archived state data.\n");
606 #endif
607
608 /* location of image template */
609 snprintf(image_template, sizeof(image_template) - 1, "%s/%s", physical_images_path, HISTOGRAM_IMAGE);
610 image_template[sizeof(image_template) - 1] = '\x0';
611
612 /* allocate buffer for storing image */
613 image_file = fopen(image_template, "r");
614 if(image_file != NULL) {
615 histogram_image = gdImageCreateFromPng(image_file);
616 fclose(image_file);
617 }
618 if(histogram_image == NULL)
619 histogram_image = gdImageCreate(image_width, image_height);
620 if(histogram_image == NULL) {
621 #ifdef DEBUG
622 printf("Error: Could not allocate memory for image\n");
623 #endif
624 return ERROR;
625 }
626
627 /* allocate colors used for drawing */
628 color_white = gdImageColorAllocate(histogram_image, 255, 255, 255);
629 color_black = gdImageColorAllocate(histogram_image, 0, 0, 0);
630 color_red = gdImageColorAllocate(histogram_image, 255, 0, 0);
631 color_darkred = gdImageColorAllocate(histogram_image, 128, 0, 0);
632 color_green = gdImageColorAllocate(histogram_image, 0, 128, 0);
633 color_yellow = gdImageColorAllocate(histogram_image, 176, 178, 20);
634 color_orange = gdImageColorAllocate(histogram_image, 255, 100, 25);
635 color_lightgray = gdImageColorAllocate(histogram_image, 192, 192, 192);
636
637 /* set transparency index */
638 gdImageColorTransparent(histogram_image, color_white);
639
640 /* make sure the graphic is interlaced */
641 gdImageInterlace(histogram_image, 1);
642
643 #ifdef DEBUG
644 printf("Starting to graph data...\n");
645 #endif
646
647 /* graph archived state histogram data */
648 graph_all_histogram_data();
649
650 #ifdef DEBUG
651 printf("Done graphing data.\n");
652 #endif
653
654 /* use STDOUT for writing the image data... */
655 image_file = stdout;
656
657 #ifdef DEBUG
658 image_file = fopen("/tmp/histogram.png", "w");
659 #endif
660
661 /* write the image to to STDOUT */
662 gdImagePng(histogram_image, image_file);
663
664 #ifdef DEBUG
665 fclose(image_file);
666 #endif
667
668 /* free memory allocated to image */
669 gdImageDestroy(histogram_image);
670
671 /* free memory allocated for data */
672 free(tsdata);
673 }
674 }
675
676
677 /* show user a selection of hosts and services to choose from... */
678 if(display_type == DISPLAY_NO_HISTOGRAM || input_type != GET_INPUT_NONE) {
679
680 /* ask the user for what host they want a report for */
681 if(input_type == GET_INPUT_HOST_TARGET) {
682
683 printf("<P><DIV ALIGN=CENTER>\n");
684 printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Host</DIV>\n");
685 printf("</DIV></P>\n");
686
687 printf("<P><DIV ALIGN=CENTER>\n");
688
689 printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
690 printf("<input type='hidden' name='input' value='getoptions'>\n");
691
692 printf("<TABLE BORDER=0 cellspacing=0 cellpadding=10>\n");
693 printf("<tr><td class='reportSelectSubTitle' valign=center>Host:</td>\n");
694 printf("<td class='reportSelectItem' valign=center>\n");
695 printf("<select name='host'>\n");
696
697 for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
698 if(is_authorized_for_host(temp_host, ¤t_authdata) == TRUE)
699 printf("<option value='%s'>%s\n", escape_string(temp_host->name), temp_host->name);
700 }
701
702 printf("</select>\n");
703 printf("</td></tr>\n");
704
705 printf("<tr><td></td><td class='reportSelectItem'>\n");
706 printf("<input type='submit' value='Continue to Step 3'>\n");
707 printf("</td></tr>\n");
708
709 printf("</TABLE>\n");
710 printf("</form>\n");
711
712 printf("</DIV></P>\n");
713 }
714
715 /* ask the user for what service they want a report for */
716 else if(input_type == GET_INPUT_SERVICE_TARGET) {
717
718 printf("<SCRIPT LANGUAGE='JavaScript'>\n");
719 printf("function gethostname(hostindex){\n");
720 printf("hostnames=[");
721
722 for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
723 if(is_authorized_for_service(temp_service, ¤t_authdata) == TRUE) {
724 if(found == TRUE)
725 printf(",");
726 else
727 first_service = temp_service->host_name;
728 printf(" \"%s\"", temp_service->host_name);
729 found = TRUE;
730 }
731 }
732
733 printf(" ]\n");
734 printf("return hostnames[hostindex];\n");
735 printf("}\n");
736 printf("</SCRIPT>\n");
737
738
739 printf("<P><DIV ALIGN=CENTER>\n");
740 printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Service</DIV>\n");
741 printf("</DIV></P>\n");
742
743 printf("<P><DIV ALIGN=CENTER>\n");
744
745 printf("<form method=\"GET\" action=\"%s\" name=\"serviceform\">\n", HISTOGRAM_CGI);
746 printf("<input type='hidden' name='input' value='getoptions'>\n");
747 printf("<input type='hidden' name='host' value='%s'>\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service));
748
749 printf("<TABLE BORDER=0 cellpadding=5>\n");
750 printf("<tr><td class='reportSelectSubTitle'>Service:</td>\n");
751 printf("<td class='reportSelectItem'>\n");
752 printf("<select name='service' onFocus='document.serviceform.host.value=gethostname(this.selectedIndex);' onChange='document.serviceform.host.value=gethostname(this.selectedIndex);'>\n");
753
754 for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
755 if(is_authorized_for_service(temp_service, ¤t_authdata) == TRUE)
756 printf("<option value='%s'>%s;%s\n", escape_string(temp_service->description), temp_service->host_name, temp_service->description);
757 }
758
759 printf("</select>\n");
760 printf("</td></tr>\n");
761
762 printf("<tr><td></td><td class='reportSelectItem'>\n");
763 printf("<input type='submit' value='Continue to Step 3'>\n");
764 printf("</td></tr>\n");
765
766 printf("</TABLE>\n");
767 printf("</form>\n");
768
769 printf("</DIV></P>\n");
770 }
771
772 /* ask the user for report range and options */
773 else if(input_type == GET_INPUT_OPTIONS) {
774
775 time(¤t_time);
776 t = localtime(¤t_time);
777
778 start_day = 1;
779 start_year = t->tm_year + 1900;
780 end_day = t->tm_mday;
781 end_year = t->tm_year + 1900;
782
783 printf("<P><DIV ALIGN=CENTER>\n");
784 printf("<DIV CLASS='reportSelectTitle'>Step 3: Select Report Options</DIV>\n");
785 printf("</DIV></P>\n");
786
787 printf("<P><DIV ALIGN=CENTER>\n");
788
789 printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
790 printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
791 if(display_type == DISPLAY_SERVICE_HISTOGRAM)
792 printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
793
794 printf("<TABLE BORDER=0 cellpadding=5>\n");
795 printf("<tr><td class='reportSelectSubTitle' align=right>Report Period:</td>\n");
796 printf("<td class='reportSelectItem'>\n");
797 printf("<select name='timeperiod'>\n");
798 printf("<option value=today>Today\n");
799 printf("<option value=last24hours>Last 24 Hours\n");
800 printf("<option value=yesterday>Yesterday\n");
801 printf("<option value=thisweek>This Week\n");
802 printf("<option value=last7days SELECTED>Last 7 Days\n");
803 printf("<option value=lastweek>Last Week\n");
804 printf("<option value=thismonth>This Month\n");
805 printf("<option value=last31days>Last 31 Days\n");
806 printf("<option value=lastmonth>Last Month\n");
807 printf("<option value=thisyear>This Year\n");
808 printf("<option value=lastyear>Last Year\n");
809 printf("<option value=custom>* CUSTOM REPORT PERIOD *\n");
810 printf("</select>\n");
811 printf("</td></tr>\n");
812
813 printf("<tr><td valign=top class='reportSelectSubTitle'>If Custom Report Period...</td></tr>\n");
814
815 printf("<tr>");
816 printf("<td valign=top class='reportSelectSubTitle'>Start Date (Inclusive):</td>\n");
817 printf("<td align=left valign=top class='reportSelectItem'>");
818 printf("<select name='smon'>\n");
819 printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
820 printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
821 printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
822 printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
823 printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
824 printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
825 printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
826 printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
827 printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
828 printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
829 printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
830 printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
831 printf("</select>\n ");
832 printf("<input type='text' size='2' maxlength='2' name='sday' value='%d'> ", start_day);
833 printf("<input type='text' size='4' maxlength='4' name='syear' value='%d'>", start_year);
834 printf("<input type='hidden' name='shour' value='0'>\n");
835 printf("<input type='hidden' name='smin' value='0'>\n");
836 printf("<input type='hidden' name='ssec' value='0'>\n");
837 printf("</td>\n");
838 printf("</tr>\n");
839
840 printf("<tr>");
841 printf("<td valign=top class='reportSelectSubTitle'>End Date (Inclusive):</td>\n");
842 printf("<td align=left valign=top class='reportSelectItem'>");
843 printf("<select name='emon'>\n");
844 printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
845 printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
846 printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
847 printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
848 printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
849 printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
850 printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
851 printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
852 printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
853 printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
854 printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
855 printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
856 printf("</select>\n ");
857 printf("<input type='text' size='2' maxlength='2' name='eday' value='%d'> ", end_day);
858 printf("<input type='text' size='4' maxlength='4' name='eyear' value='%d'>", end_year);
859 printf("<input type='hidden' name='ehour' value='24'>\n");
860 printf("<input type='hidden' name='emin' value='0'>\n");
861 printf("<input type='hidden' name='esec' value='0'>\n");
862 printf("</td>\n");
863 printf("</tr>\n");
864
865 printf("<tr><td colspan=2><br></td></tr>\n");
866
867 printf("<tr><td class='reportSelectSubTitle' align=right>Statistics Breakdown:</td>\n");
868 printf("<td class='reportSelectItem'>\n");
869 printf("<select name='breakdown'>\n");
870 printf("<option value=monthly>Month\n");
871 printf("<option value=dayofmonth SELECTED>Day of the Month\n");
872 printf("<option value=dayofweek>Day of the Week\n");
873 printf("<option value=hourly>Hour of the Day\n");
874 printf("</select>\n");
875 printf("</td></tr>\n");
876
877 printf("<tr><td class='reportSelectSubTitle' align=right>Events To Graph:</td>\n");
878 printf("<td class='reportSelectItem'>\n");
879 printf("<select name='graphevents'>\n");
880 if(display_type == DISPLAY_HOST_HISTOGRAM) {
881 printf("<option value=%d %s>All host events\n", GRAPH_HOST_ALL, (graph_events == GRAPH_HOST_ALL) ? "SELECTED" : "");
882 printf("<option value=%d %s>Host problem events\n", GRAPH_HOST_PROBLEMS, (graph_events == GRAPH_HOST_PROBLEMS) ? "SELECTED" : "");
883 printf("<option value=%d %s>Host up events\n", GRAPH_HOST_UP, (graph_events == GRAPH_HOST_UP) ? "SELECTED" : "");
884 printf("<option value=%d %s>Host down events\n", GRAPH_HOST_DOWN, (graph_events == GRAPH_HOST_DOWN) ? "SELECTED" : "");
885 printf("<option value=%d %s>Host unreachable events\n", GRAPH_HOST_UNREACHABLE, (graph_events == GRAPH_HOST_UNREACHABLE) ? "SELECTED" : "");
886 }
887 else {
888 printf("<option value=%d %s>All service events\n", GRAPH_SERVICE_ALL, (graph_events == GRAPH_SERVICE_ALL) ? "SELECTED" : "");
889 printf("<option value=%d %s>Service problem events\n", GRAPH_SERVICE_PROBLEMS, (graph_events == GRAPH_SERVICE_PROBLEMS) ? "SELECTED" : "");
890 printf("<option value=%d %s>Service ok events\n", GRAPH_SERVICE_OK, (graph_events == GRAPH_SERVICE_OK) ? "SELECTED" : "");
891 printf("<option value=%d %s>Service warning events\n", GRAPH_SERVICE_WARNING, (graph_events == GRAPH_SERVICE_WARNING) ? "SELECTED" : "");
892 printf("<option value=%d %s>Service unknown events\n", GRAPH_SERVICE_UNKNOWN, (graph_events == GRAPH_SERVICE_UNKNOWN) ? "SELECTED" : "");
893 printf("<option value=%d %s>Service critical events\n", GRAPH_SERVICE_CRITICAL, (graph_events == GRAPH_SERVICE_CRITICAL) ? "SELECTED" : "");
894 }
895 printf("</select>\n");
896 printf("</td></tr>\n");
897
898 printf("<tr><td class='reportSelectSubTitle' align=right>State Types To Graph:</td>\n");
899 printf("<td class='reportSelectItem'>\n");
900 printf("<select name='graphstatetypes'>\n");
901 printf("<option value=%d>Hard states\n", GRAPH_HARD_STATETYPES);
902 printf("<option value=%d>Soft states\n", GRAPH_SOFT_STATETYPES);
903 printf("<option value=%d SELECTED>Hard and soft states\n", GRAPH_ALL_STATETYPES);
904 printf("</select>\n");
905 printf("</td></tr>\n");
906
907 printf("<tr><td class='reportSelectSubTitle' align=right>Assume State Retention:</td>\n");
908 printf("<td class='reportSelectItem'>\n");
909 printf("<select name='assumestateretention'>\n");
910 printf("<option value='yes'>Yes\n");
911 printf("<option value='no'>No\n");
912 printf("</select>\n");
913 printf("</td></tr>\n");
914
915 printf("<tr><td class='reportSelectSubTitle' align=right>Initial States Logged:</td>\n");
916 printf("<td class='reportSelectItem'>\n");
917 printf("<select name='initialstateslogged'>\n");
918 printf("<option value='yes'>Yes\n");
919 printf("<option value='no' SELECTED>No\n");
920 printf("</select>\n");
921 printf("</td></tr>\n");
922
923 printf("<tr><td class='reportSelectSubTitle' align=right>Ignore Repeated States:</td>\n");
924 printf("<td class='reportSelectItem'>\n");
925 printf("<select name='newstatesonly'>\n");
926 printf("<option value='yes'>Yes\n");
927 printf("<option value='no' SELECTED>No\n");
928 printf("</select>\n");
929 printf("</td></tr>\n");
930
931 printf("<tr><td></td><td class='reportSelectItem'><input type='submit' value='Create Report'></td></tr>\n");
932
933 printf("</TABLE>\n");
934 printf("</form>\n");
935
936 printf("</DIV></P>\n");
937 }
938
939 /* as the user whether they want a graph for a host or service */
940 else {
941 printf("<P><DIV ALIGN=CENTER>\n");
942 printf("<DIV CLASS='reportSelectTitle'>Step 1: Select Report Type</DIV>\n");
943 printf("</DIV></P>\n");
944
945 printf("<P><DIV ALIGN=CENTER>\n");
946
947 printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
948 printf("<TABLE BORDER=0 cellpadding=5>\n");
949 printf("<tr><td class='reportSelectSubTitle' align=right>Type:</td>\n");
950 printf("<td class='reportSelectItem'>\n");
951 printf("<select name='input'>\n");
952 printf("<option value=gethost>Host\n");
953 printf("<option value=getservice>Service\n");
954 printf("</select>\n");
955 printf("</td></tr>\n");
956
957 printf("<tr><td></td><td class='reportSelectItem'>\n");
958 printf("<input type='submit' value='Continue to Step 2'>\n");
959 printf("</td></tr>\n");
960
961 printf("</TABLE>\n");
962 printf("</form>\n");
963
964 printf("</DIV></P>\n");
965 }
966
967 }
968
969 document_footer();
970
971 /* free all other allocated memory */
972 free_memory();
973
974 return OK;
975 }
976
977
document_header(int use_stylesheet)978 void document_header(int use_stylesheet) {
979 char date_time[MAX_DATETIME_LENGTH];
980 time_t current_time;
981 time_t expire_time;
982
983 if(mode == CREATE_HTML) {
984 printf("Cache-Control: no-store\r\n");
985 printf("Pragma: no-cache\r\n");
986
987 time(¤t_time);
988 get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
989 printf("Last-Modified: %s\r\n", date_time);
990
991 expire_time = (time_t)0;
992 get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
993 printf("Expires: %s\r\n", date_time);
994
995 printf("Content-type: text/html\r\n\r\n");
996
997 if(embedded == TRUE)
998 return;
999
1000 printf("<html>\n");
1001 printf("<head>\n");
1002 printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
1003 printf("<title>\n");
1004 printf("Nagios Histogram\n");
1005 printf("</title>\n");
1006
1007 if(use_stylesheet == TRUE) {
1008 printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
1009 printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, HISTOGRAM_CSS);
1010 }
1011
1012 printf("</head>\n");
1013
1014 printf("<BODY CLASS='histogram'>\n");
1015
1016 /* include user SSI header */
1017 include_ssi_files(HISTOGRAM_CGI, SSI_HEADER);
1018
1019 printf("<div id=\"popup\" style=\"position:absolute; z-index:1; visibility: hidden\"></div>\n");
1020 }
1021
1022 else {
1023 printf("Cache-Control: no-store\r\n");
1024 printf("Pragma: no-cache\r\n");
1025
1026 time(¤t_time);
1027 get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1028 printf("Last-Modified: %s\r\n", date_time);
1029
1030 expire_time = (time_t)0L;
1031 get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1032 printf("Expires: %s\r\n", date_time);
1033
1034 printf("Content-Type: image/png\r\n\r\n");
1035 }
1036
1037 return;
1038 }
1039
1040
1041
document_footer(void)1042 void document_footer(void) {
1043
1044 if(embedded == TRUE)
1045 return;
1046
1047 if(mode == CREATE_HTML) {
1048
1049 /* include user SSI footer */
1050 include_ssi_files(HISTOGRAM_CGI, SSI_FOOTER);
1051
1052 printf("</body>\n");
1053 printf("</html>\n");
1054 }
1055
1056 return;
1057 }
1058
1059
1060
process_cgivars(void)1061 int process_cgivars(void) {
1062 char **variables;
1063 int error = FALSE;
1064 int x;
1065
1066 variables = getcgivars();
1067
1068 for(x = 0; variables[x] != NULL; x++) {
1069
1070 /* do some basic length checking on the variable identifier to prevent buffer overflows */
1071 if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
1072 continue;
1073 }
1074
1075 /* we found the host argument */
1076 else if(!strcmp(variables[x], "host")) {
1077 x++;
1078 if(variables[x] == NULL) {
1079 error = TRUE;
1080 break;
1081 }
1082
1083 if((host_name = (char *)strdup(variables[x])) == NULL)
1084 host_name = "";
1085 strip_html_brackets(host_name);
1086
1087 display_type = DISPLAY_HOST_HISTOGRAM;
1088 }
1089
1090 /* we found the node width argument */
1091 else if(!strcmp(variables[x], "service")) {
1092 x++;
1093 if(variables[x] == NULL) {
1094 error = TRUE;
1095 break;
1096 }
1097
1098 if((svc_description = (char *)strdup(variables[x])) == NULL)
1099 svc_description = "";
1100 strip_html_brackets(svc_description);
1101
1102 display_type = DISPLAY_SERVICE_HISTOGRAM;
1103 }
1104
1105 /* we found first time argument */
1106 else if(!strcmp(variables[x], "t1")) {
1107 x++;
1108 if(variables[x] == NULL) {
1109 error = TRUE;
1110 break;
1111 }
1112
1113 t1 = (time_t)strtoul(variables[x], NULL, 10);
1114 timeperiod_type = TIMEPERIOD_CUSTOM;
1115 }
1116
1117 /* we found first time argument */
1118 else if(!strcmp(variables[x], "t2")) {
1119 x++;
1120 if(variables[x] == NULL) {
1121 error = TRUE;
1122 break;
1123 }
1124
1125 t2 = (time_t)strtoul(variables[x], NULL, 10);
1126 timeperiod_type = TIMEPERIOD_CUSTOM;
1127 }
1128
1129 /* we found the image creation option */
1130 else if(!strcmp(variables[x], "createimage")) {
1131 mode = CREATE_IMAGE;
1132 }
1133
1134 /* we found the backtrack archives argument */
1135 else if(!strcmp(variables[x], "backtrack")) {
1136 x++;
1137 if(variables[x] == NULL) {
1138 error = TRUE;
1139 break;
1140 }
1141
1142 backtrack_archives = atoi(variables[x]);
1143 if(backtrack_archives < 0)
1144 backtrack_archives = 0;
1145 if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
1146 backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
1147 }
1148
1149 /* we found the standard timeperiod argument */
1150 else if(!strcmp(variables[x], "timeperiod")) {
1151 x++;
1152 if(variables[x] == NULL) {
1153 error = TRUE;
1154 break;
1155 }
1156
1157 if(!strcmp(variables[x], "today"))
1158 timeperiod_type = TIMEPERIOD_TODAY;
1159 else if(!strcmp(variables[x], "yesterday"))
1160 timeperiod_type = TIMEPERIOD_YESTERDAY;
1161 else if(!strcmp(variables[x], "thisweek"))
1162 timeperiod_type = TIMEPERIOD_THISWEEK;
1163 else if(!strcmp(variables[x], "lastweek"))
1164 timeperiod_type = TIMEPERIOD_LASTWEEK;
1165 else if(!strcmp(variables[x], "thismonth"))
1166 timeperiod_type = TIMEPERIOD_THISMONTH;
1167 else if(!strcmp(variables[x], "lastmonth"))
1168 timeperiod_type = TIMEPERIOD_LASTMONTH;
1169 else if(!strcmp(variables[x], "thisquarter"))
1170 timeperiod_type = TIMEPERIOD_THISQUARTER;
1171 else if(!strcmp(variables[x], "lastquarter"))
1172 timeperiod_type = TIMEPERIOD_LASTQUARTER;
1173 else if(!strcmp(variables[x], "thisyear"))
1174 timeperiod_type = TIMEPERIOD_THISYEAR;
1175 else if(!strcmp(variables[x], "lastyear"))
1176 timeperiod_type = TIMEPERIOD_LASTYEAR;
1177 else if(!strcmp(variables[x], "last24hours"))
1178 timeperiod_type = TIMEPERIOD_LAST24HOURS;
1179 else if(!strcmp(variables[x], "last7days"))
1180 timeperiod_type = TIMEPERIOD_LAST7DAYS;
1181 else if(!strcmp(variables[x], "last31days"))
1182 timeperiod_type = TIMEPERIOD_LAST31DAYS;
1183 else if(!strcmp(variables[x], "custom"))
1184 timeperiod_type = TIMEPERIOD_CUSTOM;
1185 else
1186 timeperiod_type = TIMEPERIOD_TODAY;
1187
1188
1189 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1190 convert_timeperiod_to_times(timeperiod_type);
1191 }
1192
1193 /* we found time argument */
1194 else if(!strcmp(variables[x], "smon")) {
1195 x++;
1196 if(variables[x] == NULL) {
1197 error = TRUE;
1198 break;
1199 }
1200
1201 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1202 continue;
1203
1204 start_month = atoi(variables[x]);
1205 timeperiod_type = TIMEPERIOD_CUSTOM;
1206 compute_time_from_parts = TRUE;
1207 }
1208
1209 /* we found time argument */
1210 else if(!strcmp(variables[x], "sday")) {
1211 x++;
1212 if(variables[x] == NULL) {
1213 error = TRUE;
1214 break;
1215 }
1216
1217 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1218 continue;
1219
1220 start_day = atoi(variables[x]);
1221 timeperiod_type = TIMEPERIOD_CUSTOM;
1222 compute_time_from_parts = TRUE;
1223 }
1224
1225 /* we found time argument */
1226 else if(!strcmp(variables[x], "syear")) {
1227 x++;
1228 if(variables[x] == NULL) {
1229 error = TRUE;
1230 break;
1231 }
1232
1233 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1234 continue;
1235
1236 start_year = atoi(variables[x]);
1237 timeperiod_type = TIMEPERIOD_CUSTOM;
1238 compute_time_from_parts = TRUE;
1239 }
1240
1241 /* we found time argument */
1242 else if(!strcmp(variables[x], "smin")) {
1243 x++;
1244 if(variables[x] == NULL) {
1245 error = TRUE;
1246 break;
1247 }
1248
1249 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1250 continue;
1251
1252 start_minute = atoi(variables[x]);
1253 timeperiod_type = TIMEPERIOD_CUSTOM;
1254 compute_time_from_parts = TRUE;
1255 }
1256
1257 /* we found time argument */
1258 else if(!strcmp(variables[x], "ssec")) {
1259 x++;
1260 if(variables[x] == NULL) {
1261 error = TRUE;
1262 break;
1263 }
1264
1265 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1266 continue;
1267
1268 start_second = atoi(variables[x]);
1269 timeperiod_type = TIMEPERIOD_CUSTOM;
1270 compute_time_from_parts = TRUE;
1271 }
1272
1273 /* we found time argument */
1274 else if(!strcmp(variables[x], "shour")) {
1275 x++;
1276 if(variables[x] == NULL) {
1277 error = TRUE;
1278 break;
1279 }
1280
1281 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1282 continue;
1283
1284 start_hour = atoi(variables[x]);
1285 timeperiod_type = TIMEPERIOD_CUSTOM;
1286 compute_time_from_parts = TRUE;
1287 }
1288
1289
1290 /* we found time argument */
1291 else if(!strcmp(variables[x], "emon")) {
1292 x++;
1293 if(variables[x] == NULL) {
1294 error = TRUE;
1295 break;
1296 }
1297
1298 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1299 continue;
1300
1301 end_month = atoi(variables[x]);
1302 timeperiod_type = TIMEPERIOD_CUSTOM;
1303 compute_time_from_parts = TRUE;
1304 }
1305
1306 /* we found time argument */
1307 else if(!strcmp(variables[x], "eday")) {
1308 x++;
1309 if(variables[x] == NULL) {
1310 error = TRUE;
1311 break;
1312 }
1313
1314 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1315 continue;
1316
1317 end_day = atoi(variables[x]);
1318 timeperiod_type = TIMEPERIOD_CUSTOM;
1319 compute_time_from_parts = TRUE;
1320 }
1321
1322 /* we found time argument */
1323 else if(!strcmp(variables[x], "eyear")) {
1324 x++;
1325 if(variables[x] == NULL) {
1326 error = TRUE;
1327 break;
1328 }
1329
1330 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1331 continue;
1332
1333 end_year = atoi(variables[x]);
1334 timeperiod_type = TIMEPERIOD_CUSTOM;
1335 compute_time_from_parts = TRUE;
1336 }
1337
1338 /* we found time argument */
1339 else if(!strcmp(variables[x], "emin")) {
1340 x++;
1341 if(variables[x] == NULL) {
1342 error = TRUE;
1343 break;
1344 }
1345
1346 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1347 continue;
1348
1349 end_minute = atoi(variables[x]);
1350 timeperiod_type = TIMEPERIOD_CUSTOM;
1351 compute_time_from_parts = TRUE;
1352 }
1353
1354 /* we found time argument */
1355 else if(!strcmp(variables[x], "esec")) {
1356 x++;
1357 if(variables[x] == NULL) {
1358 error = TRUE;
1359 break;
1360 }
1361
1362 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1363 continue;
1364
1365 end_second = atoi(variables[x]);
1366 timeperiod_type = TIMEPERIOD_CUSTOM;
1367 compute_time_from_parts = TRUE;
1368 }
1369
1370 /* we found time argument */
1371 else if(!strcmp(variables[x], "ehour")) {
1372 x++;
1373 if(variables[x] == NULL) {
1374 error = TRUE;
1375 break;
1376 }
1377
1378 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1379 continue;
1380
1381 end_hour = atoi(variables[x]);
1382 timeperiod_type = TIMEPERIOD_CUSTOM;
1383 compute_time_from_parts = TRUE;
1384 }
1385
1386 /* we found the embed option */
1387 else if(!strcmp(variables[x], "embedded"))
1388 embedded = TRUE;
1389
1390 /* we found the noheader option */
1391 else if(!strcmp(variables[x], "noheader"))
1392 display_header = FALSE;
1393
1394 /* we found the input option */
1395 else if(!strcmp(variables[x], "input")) {
1396 x++;
1397 if(variables[x] == NULL) {
1398 error = TRUE;
1399 break;
1400 }
1401
1402 if(!strcmp(variables[x], "gethost"))
1403 input_type = GET_INPUT_HOST_TARGET;
1404 else if(!strcmp(variables[x], "getservice"))
1405 input_type = GET_INPUT_SERVICE_TARGET;
1406 else if(!strcmp(variables[x], "getoptions"))
1407 input_type = GET_INPUT_OPTIONS;
1408 else
1409 input_type = GET_INPUT_TARGET_TYPE;
1410 }
1411
1412 /* we found the graph states option */
1413 else if(!strcmp(variables[x], "graphevents")) {
1414 x++;
1415 if(variables[x] == NULL) {
1416 error = TRUE;
1417 break;
1418 }
1419
1420 graph_events = atoi(variables[x]);
1421 }
1422
1423 /* we found the graph state types option */
1424 else if(!strcmp(variables[x], "graphstatetypes")) {
1425 x++;
1426 if(variables[x] == NULL) {
1427 error = TRUE;
1428 break;
1429 }
1430
1431 graph_statetypes = atoi(variables[x]);
1432 }
1433
1434 /* we found the breakdown option */
1435 else if(!strcmp(variables[x], "breakdown")) {
1436 x++;
1437 if(variables[x] == NULL) {
1438 error = TRUE;
1439 break;
1440 }
1441
1442 if(!strcmp(variables[x], "monthly"))
1443 breakdown_type = BREAKDOWN_MONTHLY;
1444 else if(!strcmp(variables[x], "dayofmonth"))
1445 breakdown_type = BREAKDOWN_DAY_OF_MONTH;
1446 else if(!strcmp(variables[x], "dayofweek"))
1447 breakdown_type = BREAKDOWN_DAY_OF_WEEK;
1448 else
1449 breakdown_type = BREAKDOWN_HOURLY;
1450 }
1451
1452 /* we found the assume state retention option */
1453 else if(!strcmp(variables[x], "assumestateretention")) {
1454 x++;
1455 if(variables[x] == NULL) {
1456 error = TRUE;
1457 break;
1458 }
1459
1460 if(!strcmp(variables[x], "yes"))
1461 assume_state_retention = TRUE;
1462 else
1463 assume_state_retention = FALSE;
1464 }
1465
1466 /* we found the initial states logged option */
1467 else if(!strcmp(variables[x], "initialstateslogged")) {
1468 x++;
1469 if(variables[x] == NULL) {
1470 error = TRUE;
1471 break;
1472 }
1473
1474 if(!strcmp(variables[x], "yes"))
1475 initial_states_logged = TRUE;
1476 else
1477 initial_states_logged = FALSE;
1478
1479 }
1480
1481 /* we found the new states only option */
1482 else if(!strcmp(variables[x], "newstatesonly")) {
1483 x++;
1484 if(variables[x] == NULL) {
1485 error = TRUE;
1486 break;
1487 }
1488
1489 if(!strcmp(variables[x], "yes"))
1490 new_states_only = TRUE;
1491 else
1492 new_states_only = FALSE;
1493
1494 }
1495 }
1496
1497 /* free memory allocated to the CGI variables */
1498 free_cgivars(variables);
1499
1500 return error;
1501 }
1502
1503
1504
1505 /* graphs histogram data */
graph_all_histogram_data(void)1506 void graph_all_histogram_data(void) {
1507 int pixel_x;
1508 int pixel_y;
1509 int last_pixel_y;
1510 int current_bucket;
1511 int actual_bucket;
1512 unsigned long max_value;
1513 double x_scaling_factor;
1514 double y_scaling_factor;
1515 double x_units;
1516 double y_units;
1517 int current_unit;
1518 int actual_unit;
1519 char temp_buffer[MAX_INPUT_BUFFER];
1520 int string_width;
1521 int string_height;
1522 char *days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
1523 char *months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
1524 char start_time[MAX_INPUT_BUFFER];
1525 char end_time[MAX_INPUT_BUFFER];
1526
1527 unsigned long state1_max = 0L;
1528 unsigned long state1_min = 0L;
1529 int have_state1_min = FALSE;
1530 unsigned long state1_sum = 0L;
1531 double state1_avg = 0.0;
1532 unsigned long state2_max = 0L;
1533 unsigned long state2_min = 0L;
1534 int have_state2_min = FALSE;
1535 unsigned long state2_sum = 0L;
1536 double state2_avg = 0.0;
1537 unsigned long state3_max = 0L;
1538 unsigned long state3_min = 0L;
1539 int have_state3_min = FALSE;
1540 unsigned long state3_sum = 0L;
1541 double state3_avg = 0.0;
1542 unsigned long state4_max = 0L;
1543 unsigned long state4_min = 0L;
1544 int have_state4_min = FALSE;
1545 unsigned long state4_sum = 0L;
1546 double state4_avg = 0.0;
1547
1548
1549 #ifdef DEBUG
1550 printf("Total Buckets: %d\n", total_buckets);
1551 #endif
1552
1553 /* determine max value in the buckets (for scaling) */
1554 max_value = 0L;
1555 for(current_bucket = 0; current_bucket < total_buckets; current_bucket++) {
1556 if(tsdata[current_bucket].service_ok > max_value)
1557 max_value = tsdata[current_bucket].service_ok;
1558 if(tsdata[current_bucket].service_warning > max_value)
1559 max_value = tsdata[current_bucket].service_warning;
1560 if(tsdata[current_bucket].service_unknown > max_value)
1561 max_value = tsdata[current_bucket].service_unknown;
1562 if(tsdata[current_bucket].service_critical > max_value)
1563 max_value = tsdata[current_bucket].service_critical;
1564 if(tsdata[current_bucket].host_up > max_value)
1565 max_value = tsdata[current_bucket].host_up;
1566 if(tsdata[current_bucket].host_down > max_value)
1567 max_value = tsdata[current_bucket].host_down;
1568 if(tsdata[current_bucket].host_unreachable > max_value)
1569 max_value = tsdata[current_bucket].host_unreachable;
1570 }
1571
1572 #ifdef DEBUG
1573 printf("Done determining max bucket values\n");
1574 printf("MAX_VALUE=%lu\n", max_value);
1575 printf("DRAWING_HEIGHT=%lu\n", DRAWING_HEIGHT);
1576 #endif
1577
1578 /* min number of values to graph */
1579 if(max_value < 10)
1580 max_value = 10;
1581 #ifdef DEBUG
1582 printf("ADJUSTED MAX_VALUE=%lu\n", max_value);
1583 #endif
1584
1585 /* determine y scaling factor */
1586 /*y_scaling_factor=floor((double)DRAWING_HEIGHT/(double)max_value);*/
1587 y_scaling_factor = (double)((double)DRAWING_HEIGHT / (double)max_value);
1588
1589 /* determine x scaling factor */
1590 x_scaling_factor = (double)((double)DRAWING_WIDTH / (double)total_buckets);
1591
1592 /* determine y units resolution - we want a max of about 10 y grid lines */
1593 /*
1594 y_units=(double)((double)DRAWING_HEIGHT/19.0);
1595 y_units=ceil(y_units/y_scaling_factor)*y_scaling_factor;
1596 */
1597 y_units = ceil(19.0 / y_scaling_factor);
1598
1599 /* determine x units resolution */
1600 if(breakdown_type == BREAKDOWN_HOURLY)
1601 x_units = (double)((double)DRAWING_WIDTH / (double)(total_buckets / 4.0));
1602 else
1603 x_units = x_scaling_factor;
1604
1605 #ifdef DEBUG
1606 printf("DRAWING_WIDTH: %d\n", DRAWING_WIDTH);
1607 printf("DRAWING_HEIGHT: %d\n", DRAWING_HEIGHT);
1608 printf("max_value: %lu\n", max_value);
1609 printf("x_scaling_factor: %.3f\n", x_scaling_factor);
1610 printf("y_scaling_factor: %.3f\n", y_scaling_factor);
1611 printf("x_units: %.3f\n", x_units);
1612 printf("y_units: %.3f\n", y_units);
1613 printf("y units to draw: %.3f\n", ((double)max_value / y_units));
1614 #endif
1615
1616 string_height = gdFontSmall->h;
1617
1618 #ifdef DEBUG
1619 printf("Starting to draw Y grid lines...\n");
1620 #endif
1621
1622 /* draw y grid lines */
1623 if(max_value > 0) {
1624 for(current_unit = 1; (current_unit * y_units * y_scaling_factor) <= DRAWING_HEIGHT; current_unit++) {
1625 draw_dashed_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET - (current_unit * y_units * y_scaling_factor), DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET - (current_unit * y_units * y_scaling_factor), color_lightgray);
1626 #ifdef DEBUG
1627 printf(" Drawing Y unit #%d @ %d\n", current_unit, (int)(current_unit * y_units * y_scaling_factor));
1628 #endif
1629 }
1630 }
1631
1632 #ifdef DEBUG
1633 printf("Starting to draw X grid lines...\n");
1634 #endif
1635
1636 /* draw x grid lines */
1637 for(current_unit = 1; (int)(current_unit * x_units) <= DRAWING_WIDTH; current_unit++)
1638 draw_dashed_line(DRAWING_X_OFFSET + (int)(current_unit * x_units), DRAWING_Y_OFFSET, DRAWING_X_OFFSET + (int)(current_unit * x_units), DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_lightgray);
1639
1640 #ifdef DEBUG
1641 printf("Starting to draw grid units...\n");
1642 #endif
1643
1644 /* draw y units */
1645 if(max_value > 0) {
1646 for(current_unit = 0; (current_unit * y_units * y_scaling_factor) <= DRAWING_HEIGHT; current_unit++) {
1647 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%d", (int)(current_unit * y_units));
1648 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1649 string_width = gdFontSmall->w * strlen(temp_buffer);
1650 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET - string_width - 5, DRAWING_Y_OFFSET - (current_unit * y_units * y_scaling_factor) - (string_height / 2), (unsigned char *)temp_buffer, color_black);
1651 }
1652 }
1653
1654 /* draw x units */
1655 for(current_unit = 0, actual_unit = 0; (int)(current_unit * x_units) <= DRAWING_WIDTH; current_unit++, actual_unit++) {
1656
1657 if(actual_unit >= total_buckets)
1658 actual_unit = 0;
1659
1660 if(breakdown_type == BREAKDOWN_MONTHLY)
1661 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", months[actual_unit]);
1662 else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
1663 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%d", actual_unit + 1);
1664 else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
1665 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", days[actual_unit]);
1666 else
1667 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%02d:00", (actual_unit == 24) ? 0 : actual_unit);
1668
1669 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1670 string_width = gdFontSmall->w * strlen(temp_buffer);
1671
1672 gdImageStringUp(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (current_unit * x_units) - (string_height / 2), DRAWING_Y_OFFSET + 5 + string_width, (unsigned char *)temp_buffer, color_black);
1673 }
1674
1675 /* draw y unit measure */
1676 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Number of Events");
1677 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1678 string_width = gdFontSmall->w * strlen(temp_buffer);
1679 gdImageStringUp(histogram_image, gdFontSmall, 0, DRAWING_Y_OFFSET - (DRAWING_HEIGHT / 2) + (string_width / 2), (unsigned char *)temp_buffer, color_black);
1680
1681 /* draw x unit measure */
1682 if(breakdown_type == BREAKDOWN_MONTHLY)
1683 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Month");
1684 else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
1685 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Day of the Month");
1686 else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
1687 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Day of the Week");
1688 else
1689 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Hour of the Day (15 minute increments)");
1690 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1691 string_width = gdFontSmall->w * strlen(temp_buffer);
1692 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), DRAWING_Y_OFFSET + 70, (unsigned char *)temp_buffer, color_black);
1693
1694 /* draw title */
1695 snprintf(start_time, sizeof(start_time) - 1, "%s", ctime(&t1));
1696 start_time[sizeof(start_time) - 1] = '\x0';
1697 start_time[strlen(start_time) - 1] = '\x0';
1698 snprintf(end_time, sizeof(end_time) - 1, "%s", ctime(&t2));
1699 end_time[sizeof(end_time) - 1] = '\x0';
1700 end_time[strlen(end_time) - 1] = '\x0';
1701
1702 if(display_type == DISPLAY_HOST_HISTOGRAM)
1703 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Event History For Host '%s'", host_name);
1704 else
1705 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Event History For Service '%s' On Host '%s'", svc_description, host_name);
1706 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1707 string_width = gdFontSmall->w * strlen(temp_buffer);
1708 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), 0, (unsigned char *)temp_buffer, color_black);
1709
1710 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s to %s", start_time, end_time);
1711 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1712 string_width = gdFontSmall->w * strlen(temp_buffer);
1713 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), string_height + 5, (unsigned char *)temp_buffer, color_black);
1714
1715
1716 #ifdef DEBUG
1717 printf("About to starting graphing (total_buckets=%d)...\n", total_buckets);
1718 #endif
1719
1720
1721 /* graph service states */
1722 if(display_type == DISPLAY_HOST_HISTOGRAM) {
1723
1724 /* graph host recoveries */
1725 if(graph_events & GRAPH_HOST_UP) {
1726
1727 last_pixel_y = 0;
1728 for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
1729
1730 if(actual_bucket >= total_buckets)
1731 actual_bucket = 0;
1732
1733 pixel_x = (int)(current_bucket * x_scaling_factor);
1734
1735 pixel_y = (int)(tsdata[actual_bucket].host_up * y_scaling_factor);
1736
1737 if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
1738 draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_green);
1739
1740 last_pixel_y = pixel_y;
1741
1742 if(current_bucket < total_buckets) {
1743 if(have_state1_min == FALSE || tsdata[actual_bucket].host_up < state1_min) {
1744 state1_min = tsdata[actual_bucket].host_up;
1745 have_state1_min = TRUE;
1746 }
1747 if(state1_max == 0 || tsdata[actual_bucket].host_up > state1_max)
1748 state1_max = tsdata[actual_bucket].host_up;
1749 state1_sum += tsdata[actual_bucket].host_up;
1750 }
1751 }
1752 }
1753
1754 #ifdef DEBUG
1755 printf("Done graphing HOST UP states...\n");
1756 #endif
1757
1758 /* graph host down states */
1759 if(graph_events & GRAPH_HOST_DOWN) {
1760
1761 last_pixel_y = 0;
1762 for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
1763
1764 if(actual_bucket >= total_buckets)
1765 actual_bucket = 0;
1766
1767 pixel_x = (int)(current_bucket * x_scaling_factor);
1768
1769 pixel_y = (int)(tsdata[actual_bucket].host_down * y_scaling_factor);
1770
1771 if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
1772 draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_red);
1773
1774 last_pixel_y = pixel_y;
1775
1776 if(current_bucket < total_buckets) {
1777 if(have_state2_min == FALSE || tsdata[actual_bucket].host_down < state2_min) {
1778 state2_min = tsdata[actual_bucket].host_down;
1779 have_state2_min = TRUE;
1780 }
1781 if(state2_max == 0 || tsdata[actual_bucket].host_down > state2_max)
1782 state2_max = tsdata[actual_bucket].host_down;
1783 state2_sum += tsdata[actual_bucket].host_down;
1784 }
1785 }
1786 }
1787
1788 #ifdef DEBUG
1789 printf("Done graphing HOST DOWN states...\n");
1790 #endif
1791
1792 /* graph host unreachable states */
1793 if(graph_events & GRAPH_HOST_UNREACHABLE) {
1794
1795 last_pixel_y = 0;
1796 for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
1797
1798 if(actual_bucket >= total_buckets)
1799 actual_bucket = 0;
1800
1801 pixel_x = (int)(current_bucket * x_scaling_factor);
1802
1803 pixel_y = (int)(tsdata[actual_bucket].host_unreachable * y_scaling_factor);
1804
1805 if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
1806 draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_darkred);
1807
1808 last_pixel_y = pixel_y;
1809
1810 if(current_bucket < total_buckets) {
1811 if(have_state3_min == FALSE || tsdata[actual_bucket].host_unreachable < state3_min) {
1812 state3_min = tsdata[actual_bucket].host_unreachable;
1813 have_state3_min = TRUE;
1814 }
1815 if(state3_max == 0 || tsdata[actual_bucket].host_unreachable > state3_max)
1816 state3_max = tsdata[actual_bucket].host_unreachable;
1817 state3_sum += tsdata[actual_bucket].host_unreachable;
1818 }
1819 }
1820 }
1821
1822 #ifdef DEBUG
1823 printf("Done graphing HOST UNREACHABLE states...\n");
1824 #endif
1825
1826 }
1827
1828 /* graph service states */
1829 else {
1830
1831 /* graph service recoveries */
1832 if(graph_events & GRAPH_SERVICE_OK) {
1833
1834 last_pixel_y = 0;
1835 for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
1836
1837 if(actual_bucket >= total_buckets)
1838 actual_bucket = 0;
1839
1840 pixel_x = (int)(current_bucket * x_scaling_factor);
1841
1842 pixel_y = (int)(tsdata[actual_bucket].service_ok * y_scaling_factor);
1843
1844 if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
1845 draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_green);
1846
1847 last_pixel_y = pixel_y;
1848
1849 if(current_bucket < total_buckets) {
1850 if(have_state1_min == FALSE || tsdata[actual_bucket].service_ok < state1_min) {
1851 state1_min = tsdata[actual_bucket].service_ok;
1852 have_state1_min = TRUE;
1853 }
1854 if(state1_max == 0 || tsdata[actual_bucket].service_ok > state1_max)
1855 state1_max = tsdata[actual_bucket].service_ok;
1856 state1_sum += tsdata[actual_bucket].service_ok;
1857 }
1858 }
1859 }
1860
1861 /* graph service warning states */
1862 if(graph_events & GRAPH_SERVICE_WARNING) {
1863
1864 last_pixel_y = 0;
1865 for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
1866
1867 if(actual_bucket >= total_buckets)
1868 actual_bucket = 0;
1869
1870 pixel_x = (int)(current_bucket * x_scaling_factor);
1871
1872 pixel_y = (int)(tsdata[actual_bucket].service_warning * y_scaling_factor);
1873
1874 if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
1875 draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_yellow);
1876
1877 last_pixel_y = pixel_y;
1878
1879 if(current_bucket < total_buckets) {
1880 if(have_state2_min == FALSE || tsdata[actual_bucket].service_warning < state2_min) {
1881 state2_min = tsdata[actual_bucket].service_warning;
1882 have_state2_min = TRUE;
1883 }
1884 if(state2_max == 0 || tsdata[actual_bucket].service_warning > state2_max)
1885 state2_max = tsdata[actual_bucket].service_warning;
1886 state2_sum += tsdata[actual_bucket].service_warning;
1887 }
1888 }
1889 }
1890
1891 /* graph service unknown states */
1892 if(graph_events & GRAPH_SERVICE_UNKNOWN) {
1893
1894 last_pixel_y = 0;
1895 for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
1896
1897 if(actual_bucket >= total_buckets)
1898 actual_bucket = 0;
1899
1900 pixel_x = (int)(current_bucket * x_scaling_factor);
1901
1902 pixel_y = (int)(tsdata[actual_bucket].service_unknown * y_scaling_factor);
1903
1904 if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
1905 draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_orange);
1906
1907 last_pixel_y = pixel_y;
1908
1909 if(current_bucket < total_buckets) {
1910 if(have_state3_min == FALSE || tsdata[actual_bucket].service_unknown < state3_min) {
1911 state3_min = tsdata[actual_bucket].service_unknown;
1912 have_state3_min = TRUE;
1913 }
1914 if(state3_max == 0 || tsdata[actual_bucket].service_unknown > state3_max)
1915 state3_max = tsdata[actual_bucket].service_unknown;
1916 state3_sum += tsdata[actual_bucket].service_unknown;
1917 }
1918 }
1919 }
1920
1921 /* graph service critical states */
1922 if(graph_events & GRAPH_SERVICE_CRITICAL) {
1923
1924 last_pixel_y = 0;
1925 for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) {
1926
1927 if(actual_bucket >= total_buckets)
1928 actual_bucket = 0;
1929
1930 pixel_x = (int)(current_bucket * x_scaling_factor);
1931
1932 pixel_y = (int)(tsdata[actual_bucket].service_critical * y_scaling_factor);
1933
1934 if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0))
1935 draw_line(DRAWING_X_OFFSET + pixel_x - (int)x_scaling_factor, DRAWING_Y_OFFSET - last_pixel_y, DRAWING_X_OFFSET + pixel_x, DRAWING_Y_OFFSET - pixel_y, color_red);
1936
1937 last_pixel_y = pixel_y;
1938
1939 if(current_bucket < total_buckets) {
1940 if(have_state4_min == FALSE || tsdata[actual_bucket].service_critical < state4_min) {
1941 state4_min = tsdata[actual_bucket].service_critical;
1942 have_state4_min = TRUE;
1943 }
1944 if(state4_max == 0 || tsdata[actual_bucket].service_critical > state4_max)
1945 state4_max = tsdata[actual_bucket].service_critical;
1946 state4_sum += tsdata[actual_bucket].service_critical;
1947 }
1948 }
1949 }
1950 }
1951
1952 #ifdef DEBUG
1953 printf("Done graphing states...\n");
1954 #endif
1955
1956 /* draw graph boundaries */
1957 draw_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET, DRAWING_X_OFFSET, DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_black);
1958 draw_line(DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET, DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_black);
1959 draw_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET, DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET, color_black);
1960
1961
1962 /* graph stats */
1963 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "EVENT TYPE");
1964 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1965 string_width = gdFontSmall->w * strlen(temp_buffer);
1966 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT, (unsigned char *)temp_buffer, color_black);
1967
1968 snprintf(temp_buffer, sizeof(temp_buffer) - 1, " MIN MAX SUM AVG");
1969 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1970 string_width = gdFontSmall->w * strlen(temp_buffer);
1971 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT, (unsigned char *)temp_buffer, color_black);
1972
1973 draw_line(DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + string_height + 2, DRAWING_X_OFFSET + DRAWING_WIDTH + 275, DRAWING_Y_OFFSET - DRAWING_HEIGHT + string_height + 2, color_black);
1974
1975 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Recovery (%s):", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Ok" : "Up");
1976 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1977 string_width = gdFontSmall->w * strlen(temp_buffer);
1978 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 1), (unsigned char *)temp_buffer, color_green);
1979
1980 state1_avg = (double)((double)state1_sum / (double)total_buckets);
1981 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state1_min, state1_max, state1_sum, state1_avg);
1982 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1983 string_width = gdFontSmall->w * strlen(temp_buffer);
1984 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 1), (unsigned char *)temp_buffer, color_black);
1985
1986 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s:", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Warning" : "Down");
1987 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1988 string_width = gdFontSmall->w * strlen(temp_buffer);
1989 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 2), (unsigned char *)temp_buffer, (display_type == DISPLAY_SERVICE_HISTOGRAM) ? color_yellow : color_red);
1990
1991 state2_avg = (double)((double)state2_sum / (double)total_buckets);
1992 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state2_min, state2_max, state2_sum, state2_avg);
1993 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1994 string_width = gdFontSmall->w * strlen(temp_buffer);
1995 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 2), (unsigned char *)temp_buffer, color_black);
1996
1997 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s:", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Unknown" : "Unreachable");
1998 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
1999 string_width = gdFontSmall->w * strlen(temp_buffer);
2000 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 3), (unsigned char *)temp_buffer, (display_type == DISPLAY_SERVICE_HISTOGRAM) ? color_orange : color_darkred);
2001
2002 state3_avg = (double)((double)state3_sum / (double)total_buckets);
2003 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state3_min, state3_max, state3_sum, state3_avg);
2004 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
2005 string_width = gdFontSmall->w * strlen(temp_buffer);
2006 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 3), (unsigned char *)temp_buffer, color_black);
2007
2008 if(display_type == DISPLAY_SERVICE_HISTOGRAM) {
2009
2010 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Critical:");
2011 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
2012 string_width = gdFontSmall->w * strlen(temp_buffer);
2013 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 4), (unsigned char *)temp_buffer, color_red);
2014
2015 state4_avg = (double)((double)state4_sum / (double)total_buckets);
2016 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state4_min, state4_max, state4_sum, state4_avg);
2017 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
2018 string_width = gdFontSmall->w * strlen(temp_buffer);
2019 gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT + ((string_height + 5) * 4), (unsigned char *)temp_buffer, color_black);
2020 }
2021
2022 return;
2023 }
2024
2025
2026 /* adds an archived state entry */
add_archived_state(int state_type,time_t time_stamp)2027 void add_archived_state(int state_type, time_t time_stamp) {
2028 struct tm *our_time;
2029 int bucket;
2030 int skip_state = FALSE;
2031
2032 #ifdef DEBUG2
2033 printf("NEW ENTRY: last=%d this=%d\n", last_state, state_type);
2034 #endif
2035
2036 /* don't record program starts/stops, just make a note that one occurred */
2037 if(state_type == AS_PROGRAM_START || state_type == AS_PROGRAM_END) {
2038 #ifdef DEBUG2
2039 printf("Recording a program start: %d\n", state_type);
2040 #endif
2041 program_restart_has_occurred = TRUE;
2042 return;
2043 }
2044
2045 /* see if we should even take into account this event */
2046 if(program_restart_has_occurred == TRUE) {
2047
2048 #ifdef DEBUG2
2049 printf("program_restart_has_occurred: last=%d this=%d\n", last_state, state_type);
2050 #endif
2051
2052 if(initial_states_logged == TRUE) {
2053 if(state_type == AS_SVC_OK && last_state == AS_SVC_OK)
2054 skip_state = TRUE;
2055 if(state_type == AS_HOST_UP && last_state == AS_HOST_UP)
2056 skip_state = TRUE;
2057 }
2058
2059 if(assume_state_retention == TRUE && initial_states_logged == TRUE) {
2060 if(state_type == AS_SVC_WARNING && last_state == AS_SVC_WARNING)
2061 skip_state = TRUE;
2062 if(state_type == AS_SVC_UNKNOWN && last_state == AS_SVC_UNKNOWN)
2063 skip_state = TRUE;
2064 if(state_type == AS_SVC_CRITICAL && last_state == AS_SVC_CRITICAL)
2065 skip_state = TRUE;
2066 if(state_type == AS_HOST_DOWN && last_state == AS_HOST_DOWN)
2067 skip_state = TRUE;
2068 if(state_type == AS_HOST_UNREACHABLE && last_state == AS_HOST_UNREACHABLE)
2069 skip_state = TRUE;
2070 }
2071
2072 if(skip_state == TRUE) {
2073 program_restart_has_occurred = FALSE;
2074 #ifdef DEBUG2
2075 printf("Skipping state...\n");
2076 #endif
2077 return;
2078 }
2079 }
2080
2081 /* reset program restart variable */
2082 program_restart_has_occurred = FALSE;
2083
2084 /* are we only processing new states */
2085 if(new_states_only == TRUE && state_type == last_state) {
2086 #ifdef DEBUG2
2087 printf("Skipping state (not a new state)...\n");
2088 #endif
2089 return;
2090 }
2091
2092 #ifdef DEBUG2
2093 printf("GOODSTATE: %d @ %lu\n", state_type, (unsigned long)time_stamp);
2094 #endif
2095
2096
2097
2098 our_time = localtime(&time_stamp);
2099
2100 /* calculate the correct bucket to dump the data into */
2101 if(breakdown_type == BREAKDOWN_MONTHLY)
2102 bucket = our_time->tm_mon;
2103
2104 else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
2105 bucket = our_time->tm_mday - 1;
2106
2107 else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
2108 bucket = our_time->tm_wday;
2109
2110 else
2111 bucket = (our_time->tm_hour * 4) + (our_time->tm_min / 15);
2112
2113 #ifdef DEBUG2
2114 printf("\tBucket=%d\n", bucket);
2115 #endif
2116
2117 /* save the data in the correct bucket */
2118 if(state_type == AS_SVC_OK)
2119 tsdata[bucket].service_ok++;
2120 else if(state_type == AS_SVC_UNKNOWN)
2121 tsdata[bucket].service_unknown++;
2122 else if(state_type == AS_SVC_WARNING)
2123 tsdata[bucket].service_warning++;
2124 else if(state_type == AS_SVC_CRITICAL)
2125 tsdata[bucket].service_critical++;
2126 else if(state_type == AS_HOST_UP)
2127 tsdata[bucket].host_up++;
2128 else if(state_type == AS_HOST_DOWN)
2129 tsdata[bucket].host_down++;
2130 else if(state_type == AS_HOST_UNREACHABLE)
2131 tsdata[bucket].host_unreachable++;
2132
2133 /* record last state type */
2134 last_state = state_type;
2135
2136 return;
2137 }
2138
2139
2140
2141 /* reads log files for archived state data */
read_archived_state_data(void)2142 void read_archived_state_data(void) {
2143 char filename[MAX_FILENAME_LENGTH];
2144 int newest_archive = 0;
2145 int oldest_archive = 0;
2146 int current_archive;
2147
2148 #ifdef DEBUG2
2149 printf("Determining archives to use...\n");
2150 #endif
2151
2152 /* determine earliest archive to use */
2153 oldest_archive = determine_archive_to_use_from_time(t1);
2154 if(log_rotation_method != LOG_ROTATION_NONE)
2155 oldest_archive += backtrack_archives;
2156
2157 /* determine most recent archive to use */
2158 newest_archive = determine_archive_to_use_from_time(t2);
2159
2160 if(oldest_archive < newest_archive)
2161 oldest_archive = newest_archive;
2162
2163 #ifdef DEBUG2
2164 printf("Oldest archive: %d\n", oldest_archive);
2165 printf("Newest archive: %d\n", newest_archive);
2166 #endif
2167
2168 /* read in all the necessary archived logs */
2169 for(current_archive = newest_archive; current_archive <= oldest_archive; current_archive++) {
2170
2171 /* get the name of the log file that contains this archive */
2172 get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1);
2173
2174 #ifdef DEBUG2
2175 printf("\tCurrent archive: %d (%s)\n", current_archive, filename);
2176 #endif
2177
2178 /* scan the log file for archived state data */
2179 scan_log_file_for_archived_state_data(filename);
2180 }
2181
2182 return;
2183 }
2184
2185
2186
2187 /* grabs archives state data from a log file */
scan_log_file_for_archived_state_data(char * filename)2188 void scan_log_file_for_archived_state_data(char *filename) {
2189 char *input = NULL;
2190 char *input2 = NULL;
2191 char entry_host_name[MAX_INPUT_BUFFER];
2192 char entry_svc_description[MAX_INPUT_BUFFER];
2193 char *temp_buffer;
2194 time_t time_stamp;
2195 mmapfile *thefile;
2196
2197 /* print something so browser doesn't time out */
2198 if(mode == CREATE_HTML) {
2199 printf(" ");
2200 fflush(NULL);
2201 }
2202
2203 if((thefile = mmap_fopen(filename)) == NULL) {
2204 #ifdef DEBUG2
2205 printf("Could not open file '%s' for reading.\n", filename);
2206 #endif
2207 return;
2208 }
2209
2210 #ifdef DEBUG2
2211 printf("Scanning log file '%s' for archived state data...\n", filename);
2212 #endif
2213
2214 while(1) {
2215
2216 /* free memory */
2217 free(input);
2218 free(input2);
2219 input = NULL;
2220 input2 = NULL;
2221
2222 /* read the next line */
2223 if((input = mmap_fgets(thefile)) == NULL)
2224 break;
2225
2226 strip(input);
2227
2228 if((input2 = strdup(input)) == NULL)
2229 continue;
2230
2231 temp_buffer = my_strtok(input2, "]");
2232 time_stamp = (temp_buffer == NULL) ? (time_t)0 : (time_t)strtoul(temp_buffer + 1, NULL, 10);
2233
2234 /* program starts/restarts */
2235 if(strstr(input, " starting..."))
2236 add_archived_state(AS_PROGRAM_START, time_stamp);
2237 if(strstr(input, " restarting..."))
2238 add_archived_state(AS_PROGRAM_START, time_stamp);
2239
2240 /* program stops */
2241 if(strstr(input, " shutting down..."))
2242 add_archived_state(AS_PROGRAM_END, time_stamp);
2243 if(strstr(input, "Bailing out"))
2244 add_archived_state(AS_PROGRAM_END, time_stamp);
2245
2246 if(display_type == DISPLAY_HOST_HISTOGRAM) {
2247 if(strstr(input, "HOST ALERT:")) {
2248
2249 /* get host name */
2250 temp_buffer = my_strtok(NULL, ":");
2251 temp_buffer = my_strtok(NULL, ";");
2252 strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2253 entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2254
2255 if(strcmp(host_name, entry_host_name))
2256 continue;
2257
2258 /* skip soft states if necessary */
2259 if(!(graph_statetypes & GRAPH_SOFT_STATETYPES) && strstr(input, ";SOFT;"))
2260 continue;
2261
2262 /* skip hard states if necessary */
2263 if(!(graph_statetypes & GRAPH_HARD_STATETYPES) && strstr(input, ";HARD;"))
2264 continue;
2265
2266 if(strstr(input, ";DOWN;"))
2267 add_archived_state(AS_HOST_DOWN, time_stamp);
2268 else if(strstr(input, ";UNREACHABLE;"))
2269 add_archived_state(AS_HOST_UNREACHABLE, time_stamp);
2270 else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;"))
2271 add_archived_state(AS_HOST_UP, time_stamp);
2272 }
2273 }
2274 if(display_type == DISPLAY_SERVICE_HISTOGRAM) {
2275 if(strstr(input, "SERVICE ALERT:")) {
2276
2277 /* get host name */
2278 temp_buffer = my_strtok(NULL, ":");
2279 temp_buffer = my_strtok(NULL, ";");
2280 strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2281 entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2282
2283 if(strcmp(host_name, entry_host_name))
2284 continue;
2285
2286 /* get service description */
2287 temp_buffer = my_strtok(NULL, ";");
2288 strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(entry_svc_description));
2289 entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
2290
2291 if(strcmp(svc_description, entry_svc_description))
2292 continue;
2293
2294 /* skip soft states if necessary */
2295 if(!(graph_statetypes & GRAPH_SOFT_STATETYPES) && strstr(input, ";SOFT;"))
2296 continue;
2297
2298 /* skip hard states if necessary */
2299 if(!(graph_statetypes & GRAPH_HARD_STATETYPES) && strstr(input, ";HARD;"))
2300 continue;
2301
2302 if(strstr(input, ";CRITICAL;"))
2303 add_archived_state(AS_SVC_CRITICAL, time_stamp);
2304 else if(strstr(input, ";WARNING;"))
2305 add_archived_state(AS_SVC_WARNING, time_stamp);
2306 else if(strstr(input, ";UNKNOWN;"))
2307 add_archived_state(AS_SVC_UNKNOWN, time_stamp);
2308 else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))
2309 add_archived_state(AS_SVC_OK, time_stamp);
2310 }
2311 }
2312
2313 }
2314
2315 /* free memory and close the file */
2316 free(input);
2317 free(input2);
2318 mmap_fclose(thefile);
2319
2320 return;
2321 }
2322
2323
2324
2325
convert_timeperiod_to_times(int type)2326 void convert_timeperiod_to_times(int type) {
2327 time_t current_time;
2328 struct tm *t;
2329
2330 /* get the current time */
2331 time(¤t_time);
2332
2333 t = localtime(¤t_time);
2334
2335 t->tm_sec = 0;
2336 t->tm_min = 0;
2337 t->tm_hour = 0;
2338 t->tm_isdst = -1;
2339
2340 switch(type) {
2341 case TIMEPERIOD_LAST24HOURS:
2342 t1 = current_time - (60 * 60 * 24);
2343 t2 = current_time;
2344 break;
2345 case TIMEPERIOD_TODAY:
2346 t1 = mktime(t);
2347 t2 = current_time;
2348 break;
2349 case TIMEPERIOD_YESTERDAY:
2350 t1 = (time_t)(mktime(t) - (60 * 60 * 24));
2351 t2 = (time_t)mktime(t);
2352 break;
2353 case TIMEPERIOD_THISWEEK:
2354 t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
2355 t2 = current_time;
2356 break;
2357 case TIMEPERIOD_LASTWEEK:
2358 t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday) - (60 * 60 * 24 * 7));
2359 t2 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
2360 break;
2361 case TIMEPERIOD_THISMONTH:
2362 t->tm_mday = 1;
2363 t1 = mktime(t);
2364 t2 = current_time;
2365 break;
2366 case TIMEPERIOD_LASTMONTH:
2367 t->tm_mday = 1;
2368 t2 = mktime(t);
2369 if(t->tm_mon == 0) {
2370 t->tm_mon = 11;
2371 t->tm_year--;
2372 }
2373 else
2374 t->tm_mon--;
2375 t1 = mktime(t);
2376 break;
2377 case TIMEPERIOD_THISQUARTER:
2378 break;
2379 case TIMEPERIOD_LASTQUARTER:
2380 break;
2381 case TIMEPERIOD_THISYEAR:
2382 t->tm_mon = 0;
2383 t->tm_mday = 1;
2384 t1 = mktime(t);
2385 t2 = current_time;
2386 break;
2387 case TIMEPERIOD_LASTYEAR:
2388 t->tm_mon = 0;
2389 t->tm_mday = 1;
2390 t2 = mktime(t);
2391 t->tm_year--;
2392 t1 = mktime(t);
2393 break;
2394 case TIMEPERIOD_LAST7DAYS:
2395 t2 = current_time;
2396 t1 = current_time - (7 * 24 * 60 * 60);
2397 break;
2398 case TIMEPERIOD_LAST31DAYS:
2399 t2 = current_time;
2400 t1 = current_time - (31 * 24 * 60 * 60);
2401 break;
2402 default:
2403 break;
2404 }
2405
2406 return;
2407 }
2408
2409
2410
compute_report_times(void)2411 void compute_report_times(void) {
2412 time_t current_time;
2413 struct tm *st;
2414 struct tm *et;
2415
2416 /* get the current time */
2417 time(¤t_time);
2418
2419 st = localtime(¤t_time);
2420
2421 st->tm_sec = start_second;
2422 st->tm_min = start_minute;
2423 st->tm_hour = start_hour;
2424 st->tm_mday = start_day;
2425 st->tm_mon = start_month - 1;
2426 st->tm_year = start_year - 1900;
2427 st->tm_isdst = -1;
2428
2429 t1 = mktime(st);
2430
2431 et = localtime(¤t_time);
2432
2433 et->tm_sec = end_second;
2434 et->tm_min = end_minute;
2435 et->tm_hour = end_hour;
2436 et->tm_mday = end_day;
2437 et->tm_mon = end_month - 1;
2438 et->tm_year = end_year - 1900;
2439 et->tm_isdst = -1;
2440
2441 t2 = mktime(et);
2442 }
2443
2444
2445
2446 /* draws a solid line */
draw_line(int x1,int y1,int x2,int y2,int color)2447 void draw_line(int x1, int y1, int x2, int y2, int color) {
2448 int styleSolid[1];
2449
2450 styleSolid[0] = color;
2451
2452 /* sets current style to a solid line */
2453 gdImageSetStyle(histogram_image, styleSolid, 1);
2454
2455 /* draws a line (dashed) */
2456 gdImageLine(histogram_image, x1, y1, x2, y2, gdStyled);
2457
2458 return;
2459 }
2460
2461
2462 /* draws a dashed line */
draw_dashed_line(int x1,int y1,int x2,int y2,int color)2463 void draw_dashed_line(int x1, int y1, int x2, int y2, int color) {
2464 int styleDashed[6];
2465
2466 styleDashed[0] = color;
2467 styleDashed[1] = color;
2468 styleDashed[2] = gdTransparent;
2469 styleDashed[3] = gdTransparent;
2470 styleDashed[4] = gdTransparent;
2471 styleDashed[5] = gdTransparent;
2472
2473 /* sets current style to a solid line */
2474 gdImageSetStyle(histogram_image, styleDashed, 6);
2475
2476 /* draws a line (dashed) */
2477 gdImageLine(histogram_image, x1, y1, x2, y2, gdStyled);
2478
2479 return;
2480 }
2481