/************************************************************************** * * HISTOGRAM.C - Nagios Alert Histogram CGI * * * License: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *************************************************************************/ #include "../include/config.h" #include "../include/common.h" #include "../include/objects.h" #include "../include/statusdata.h" #include "../include/cgiutils.h" #include "../include/getcgi.h" #include "../include/cgiauth.h" #include /* Boutell's GD library function */ #include /* GD library small font definition */ /*#define DEBUG 1*/ #define HISTOGRAM_IMAGE "histogram.png" /* archived state types */ #define AS_NO_DATA 0 #define AS_PROGRAM_START 1 #define AS_PROGRAM_END 2 #define AS_HOST_UP 3 #define AS_HOST_DOWN 4 #define AS_HOST_UNREACHABLE 5 #define AS_SVC_OK 6 #define AS_SVC_UNKNOWN 7 #define AS_SVC_WARNING 8 #define AS_SVC_CRITICAL 9 /* display types */ #define DISPLAY_HOST_HISTOGRAM 0 #define DISPLAY_SERVICE_HISTOGRAM 1 #define DISPLAY_NO_HISTOGRAM 2 /* input types */ #define GET_INPUT_NONE 0 #define GET_INPUT_TARGET_TYPE 1 #define GET_INPUT_HOST_TARGET 2 #define GET_INPUT_SERVICE_TARGET 3 #define GET_INPUT_OPTIONS 4 /* breakdown types */ #define BREAKDOWN_MONTHLY 0 #define BREAKDOWN_DAY_OF_MONTH 1 #define BREAKDOWN_DAY_OF_WEEK 2 #define BREAKDOWN_HOURLY 3 /* modes */ #define CREATE_HTML 0 #define CREATE_IMAGE 1 /* standard report times */ #define TIMEPERIOD_CUSTOM 0 #define TIMEPERIOD_TODAY 1 #define TIMEPERIOD_YESTERDAY 2 #define TIMEPERIOD_THISWEEK 3 #define TIMEPERIOD_LASTWEEK 4 #define TIMEPERIOD_THISMONTH 5 #define TIMEPERIOD_LASTMONTH 6 #define TIMEPERIOD_THISQUARTER 7 #define TIMEPERIOD_LASTQUARTER 8 #define TIMEPERIOD_THISYEAR 9 #define TIMEPERIOD_LASTYEAR 10 #define TIMEPERIOD_LAST24HOURS 11 #define TIMEPERIOD_LAST7DAYS 12 #define TIMEPERIOD_LAST31DAYS 13 #define MAX_ARCHIVE_SPREAD 65 #define MAX_ARCHIVE 65 #define MAX_ARCHIVE_BACKTRACKS 60 #define DRAWING_WIDTH 550 #define DRAWING_HEIGHT 195 #define DRAWING_X_OFFSET 60 #define DRAWING_Y_OFFSET 235 #define GRAPH_HOST_UP 1 #define GRAPH_HOST_DOWN 2 #define GRAPH_HOST_UNREACHABLE 4 #define GRAPH_SERVICE_OK 8 #define GRAPH_SERVICE_WARNING 16 #define GRAPH_SERVICE_UNKNOWN 32 #define GRAPH_SERVICE_CRITICAL 64 #define GRAPH_HOST_PROBLEMS 6 #define GRAPH_HOST_ALL 7 #define GRAPH_SERVICE_PROBLEMS 112 #define GRAPH_SERVICE_ALL 120 #define GRAPH_EVERYTHING 255 #define GRAPH_SOFT_STATETYPES 1 #define GRAPH_HARD_STATETYPES 2 #define GRAPH_ALL_STATETYPES 3 extern char main_config_file[MAX_FILENAME_LENGTH]; extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char physical_images_path[MAX_FILENAME_LENGTH]; extern char *status_file; authdata current_authdata; typedef struct timeslice_data_struct { unsigned long service_ok; unsigned long host_up; unsigned long service_critical; unsigned long host_down; unsigned long service_unknown; unsigned long host_unreachable; unsigned long service_warning; } timeslice_data; timeslice_data *tsdata; void convert_timeperiod_to_times(int); void compute_report_times(void); void graph_all_histogram_data(void); void add_archived_state(int, time_t); void read_archived_state_data(void); void scan_log_file_for_archived_state_data(char *); void draw_line(int, int, int, int, int); void draw_dashed_line(int, int, int, int, int); void document_header(int); void document_footer(void); int process_cgivars(void); time_t t1; time_t t2; int start_second = 0; int start_minute = 0; int start_hour = 0; int start_day = 1; int start_month = 1; int start_year = 2000; int end_second = 0; int end_minute = 0; int end_hour = 24; int end_day = 1; int end_month = 1; int end_year = 2000; int display_type = DISPLAY_NO_HISTOGRAM; int mode = CREATE_HTML; int input_type = GET_INPUT_NONE; int timeperiod_type = TIMEPERIOD_LAST24HOURS; int breakdown_type = BREAKDOWN_HOURLY; int compute_time_from_parts = FALSE; int initial_states_logged = FALSE; int assume_state_retention = TRUE; int new_states_only = FALSE; int last_state = AS_NO_DATA; int program_restart_has_occurred = FALSE; int graph_events = GRAPH_EVERYTHING; int graph_statetypes = GRAPH_HARD_STATETYPES; int embedded = FALSE; int display_header = TRUE; char *host_name = ""; char *svc_description = ""; gdImagePtr histogram_image = 0; int color_white = 0; int color_black = 0; int color_red = 0; int color_darkred = 0; int color_green = 0; int color_yellow = 0; int color_orange = 0; int color_lightgray = 0; FILE *image_file = NULL; int backtrack_archives = 0; int earliest_archive = 0; time_t earliest_time; time_t latest_time; int image_width = 900; int image_height = 320; int total_buckets = 96; int main(int argc, char **argv) { int result = OK; char temp_buffer[MAX_INPUT_BUFFER]; char image_template[MAX_INPUT_BUFFER]; char start_timestring[MAX_INPUT_BUFFER]; char end_timestring[MAX_INPUT_BUFFER]; host *temp_host; service *temp_service; int is_authorized = TRUE; int found = FALSE; int days, hours, minutes, seconds; char *first_service = NULL; int x; time_t t3; time_t current_time; struct tm *t; /* initialize time period to last 24 hours */ time(&t2); t1 = (time_t)(t2 - (60 * 60 * 24)); /* get the arguments passed in the URL */ process_cgivars(); /* reset internal CGI variables */ reset_cgi_vars(); /* Initialize shared configuration variables */ init_shared_cfg_vars(1); /* read the CGI configuration file */ result = read_cgi_config_file(get_cgi_config_location()); if(result == ERROR) { if(mode == CREATE_HTML) { document_header(FALSE); cgi_config_file_error(get_cgi_config_location()); document_footer(); } return ERROR; } /* read the main configuration file */ result = read_main_config_file(main_config_file); if(result == ERROR) { if(mode == CREATE_HTML) { document_header(FALSE); main_config_file_error(main_config_file); document_footer(); } return ERROR; } /* read all object configuration data */ result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); if(result == ERROR) { if(mode == CREATE_HTML) { document_header(FALSE); object_data_error(); document_footer(); } return ERROR; } /* read all status data */ result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); if(result == ERROR) { if(mode == CREATE_HTML) { document_header(FALSE); status_data_error(); document_footer(); } free_memory(); return ERROR; } document_header(TRUE); /* get authentication information */ get_authentication_information(¤t_authdata); if(compute_time_from_parts == TRUE) compute_report_times(); /* make sure times are sane, otherwise swap them */ if(t2 < t1) { t3 = t2; t2 = t1; t1 = t3; } if(mode == CREATE_HTML && display_header == TRUE) { /* begin top table */ printf("\n"); printf("\n"); /* left column of the first row */ printf("\n"); /* center column of top row */ printf("\n"); /* right hand column of top row */ printf("\n"); /* end of top table */ printf("\n"); printf("
\n"); if(display_type == DISPLAY_HOST_HISTOGRAM) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host Alert Histogram"); else if(display_type == DISPLAY_SERVICE_HISTOGRAM) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service Alert Histogram"); else snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host and Service Alert Histogram"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; display_info_table(temp_buffer, FALSE, ¤t_authdata); if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) { printf("\n"); printf("\n"); printf("\n"); } printf("\n"); if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) { printf("
\n"); if(display_type == DISPLAY_HOST_HISTOGRAM) printf("Host '%s'", host_name); else if(display_type == DISPLAY_SERVICE_HISTOGRAM) printf("Service '%s' On Host '%s'", svc_description, host_name); printf("
\n"); printf("
\n"); printf("%s Event Histogram\n", url_images_path, TRENDS_ICON, (display_type == DISPLAY_HOST_HISTOGRAM) ? "Host" : "Service", (display_type == DISPLAY_HOST_HISTOGRAM) ? "Host" : "Service"); printf("
\n"); get_time_string(&t1, start_timestring, sizeof(start_timestring) - 1, SHORT_DATE_TIME); get_time_string(&t2, end_timestring, sizeof(end_timestring) - 1, SHORT_DATE_TIME); printf("
%s to %s
\n", start_timestring, end_timestring); get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds); printf("
Duration: %dd %dh %dm %ds
\n", days, hours, minutes, seconds); } printf("
\n"); #ifdef LEGACY_GRAPHICAL_CGIS printf("
\n", HISTOGRAM_CGI); #else printf("\n", LEGACY_HISTOGRAM_CGI); #endif printf("\n"); if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) { printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); } /* display context-sensitive help */ printf("\n"); printf("
Report period:Assume state retention:
\n"); printf("\n", (unsigned long)t1); printf("\n", (unsigned long)t2); printf("\n", escape_string(host_name)); if(display_type == DISPLAY_SERVICE_HISTOGRAM) printf("\n", escape_string(svc_description)); printf("\n"); printf("\n"); printf("\n"); printf("
Breakdown type:Initial states logged:
\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Events to graph:Ignore repeated states:
\n"); printf("\n"); printf("\n"); printf("\n"); printf("
State types to graph:
\n"); printf("\n"); printf("\n"); printf("\n"); printf("
\n"); if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) { if(display_type == DISPLAY_HOST_HISTOGRAM) display_context_help(CONTEXTHELP_HISTOGRAM_HOST); else display_context_help(CONTEXTHELP_HISTOGRAM_SERVICE); } else if(display_type == DISPLAY_NO_HISTOGRAM || input_type != GET_INPUT_NONE) { if(input_type == GET_INPUT_NONE) display_context_help(CONTEXTHELP_HISTOGRAM_MENU1); else if(input_type == GET_INPUT_TARGET_TYPE) display_context_help(CONTEXTHELP_HISTOGRAM_MENU1); else if(input_type == GET_INPUT_HOST_TARGET) display_context_help(CONTEXTHELP_HISTOGRAM_MENU2); else if(input_type == GET_INPUT_SERVICE_TARGET) display_context_help(CONTEXTHELP_HISTOGRAM_MENU3); else if(input_type == GET_INPUT_OPTIONS) display_context_help(CONTEXTHELP_HISTOGRAM_MENU4); } printf("
\n"); printf("
\n"); printf("
\n"); } /* check authorization... */ if(display_type == DISPLAY_HOST_HISTOGRAM) { temp_host = find_host(host_name); if(temp_host == NULL || is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) is_authorized = FALSE; } else if(display_type == DISPLAY_SERVICE_HISTOGRAM) { temp_service = find_service(host_name, svc_description); if(temp_service == NULL || is_authorized_for_service(temp_service, ¤t_authdata) == FALSE) is_authorized = FALSE; } if(is_authorized == FALSE) { if(mode == CREATE_HTML) printf("

It appears as though you are not authorized to view information for the specified %s...

\n", (display_type == DISPLAY_HOST_HISTOGRAM) ? "host" : "service"); document_footer(); free_memory(); return ERROR; } if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) { /* print URL to image */ if(mode == CREATE_HTML) { printf("

\n"); printf("
\n"); #ifdef LEGACY_GRAPHICAL_CGIS printf("\n"); printf("
\n"); } /* read and process state data */ else { /* allocate memory */ tsdata = NULL; if(breakdown_type == BREAKDOWN_MONTHLY) total_buckets = 12; else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH) total_buckets = 31; else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK) total_buckets = 7; else total_buckets = 96; tsdata = (timeslice_data *)malloc(sizeof(timeslice_data) * total_buckets); if(tsdata == NULL) return ERROR; for(x = 0; x < total_buckets; x++) { tsdata[x].service_ok = 0L; tsdata[x].service_unknown = 0L; tsdata[x].service_warning = 0L; tsdata[x].service_critical = 0L; tsdata[x].host_up = 0L; tsdata[x].host_down = 0L; tsdata[x].host_unreachable = 0L; } /* read in all necessary archived state data */ read_archived_state_data(); #ifdef DEBUG printf("Done reading archived state data.\n"); #endif /* location of image template */ snprintf(image_template, sizeof(image_template) - 1, "%s/%s", physical_images_path, HISTOGRAM_IMAGE); image_template[sizeof(image_template) - 1] = '\x0'; /* allocate buffer for storing image */ image_file = fopen(image_template, "r"); if(image_file != NULL) { histogram_image = gdImageCreateFromPng(image_file); fclose(image_file); } if(histogram_image == NULL) histogram_image = gdImageCreate(image_width, image_height); if(histogram_image == NULL) { #ifdef DEBUG printf("Error: Could not allocate memory for image\n"); #endif return ERROR; } /* allocate colors used for drawing */ color_white = gdImageColorAllocate(histogram_image, 255, 255, 255); color_black = gdImageColorAllocate(histogram_image, 0, 0, 0); color_red = gdImageColorAllocate(histogram_image, 255, 0, 0); color_darkred = gdImageColorAllocate(histogram_image, 128, 0, 0); color_green = gdImageColorAllocate(histogram_image, 0, 128, 0); color_yellow = gdImageColorAllocate(histogram_image, 176, 178, 20); color_orange = gdImageColorAllocate(histogram_image, 255, 100, 25); color_lightgray = gdImageColorAllocate(histogram_image, 192, 192, 192); /* set transparency index */ gdImageColorTransparent(histogram_image, color_white); /* make sure the graphic is interlaced */ gdImageInterlace(histogram_image, 1); #ifdef DEBUG printf("Starting to graph data...\n"); #endif /* graph archived state histogram data */ graph_all_histogram_data(); #ifdef DEBUG printf("Done graphing data.\n"); #endif /* use STDOUT for writing the image data... */ image_file = stdout; #ifdef DEBUG image_file = fopen("/tmp/histogram.png", "w"); #endif /* write the image to to STDOUT */ gdImagePng(histogram_image, image_file); #ifdef DEBUG fclose(image_file); #endif /* free memory allocated to image */ gdImageDestroy(histogram_image); /* free memory allocated for data */ free(tsdata); } } /* show user a selection of hosts and services to choose from... */ if(display_type == DISPLAY_NO_HISTOGRAM || input_type != GET_INPUT_NONE) { /* ask the user for what host they want a report for */ if(input_type == GET_INPUT_HOST_TARGET) { printf("

\n"); printf("
Step 2: Select Host
\n"); printf("

\n"); printf("

\n"); #ifdef LEGACY_GRAPHICAL_CGIS printf("
\n", HISTOGRAM_CGI); #else printf("\n", LEGACY_HISTOGRAM_CGI); #endif printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Host:\n"); printf("\n"); printf("
\n"); printf("\n"); printf("
\n"); printf("
\n"); printf("

\n"); } /* ask the user for what service they want a report for */ else if(input_type == GET_INPUT_SERVICE_TARGET) { printf("\n"); printf("

\n"); printf("
Step 2: Select Service
\n"); printf("

\n"); printf("

\n"); #ifdef LEGACY_GRAPHICAL_CGIS printf("
\n", HISTOGRAM_CGI); #else printf("\n", LEGACY_HISTOGRAM_CGI); #endif printf("\n"); printf("\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service)); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Service:\n"); printf("\n"); printf("
\n"); printf("\n"); printf("
\n"); printf("
\n"); printf("

\n"); } /* ask the user for report range and options */ else if(input_type == GET_INPUT_OPTIONS) { time(¤t_time); t = localtime(¤t_time); start_day = 1; start_year = t->tm_year + 1900; end_day = t->tm_mday; end_year = t->tm_year + 1900; printf("

\n"); printf("
Step 3: Select Report Options
\n"); printf("

\n"); printf("

\n"); #ifdef LEGACY_GRAPHICAL_CGIS printf("
\n", HISTOGRAM_CGI); #else printf("\n", LEGACY_HISTOGRAM_CGI); #endif printf("\n", escape_string(host_name)); if(display_type == DISPLAY_SERVICE_HISTOGRAM) printf("\n", escape_string(svc_description)); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf(""); printf("\n"); printf("\n"); printf("\n"); printf(""); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Report Period:\n"); printf("\n"); printf("
If Custom Report Period...
Start Date (Inclusive):"); printf("\n "); printf(" ", start_day); printf("", start_year); printf("\n"); printf("\n"); printf("\n"); printf("
End Date (Inclusive):"); printf("\n "); printf(" ", end_day); printf("", end_year); printf("\n"); printf("\n"); printf("\n"); printf("

Statistics Breakdown:\n"); printf("\n"); printf("
Events To Graph:\n"); printf("\n"); printf("
State Types To Graph:\n"); printf("\n"); printf("
Assume State Retention:\n"); printf("\n"); printf("
Initial States Logged:\n"); printf("\n"); printf("
Ignore Repeated States:\n"); printf("\n"); printf("
\n"); printf("
\n"); printf("

\n"); } /* as the user whether they want a graph for a host or service */ else { printf("

\n"); printf("
Step 1: Select Report Type
\n"); printf("

\n"); printf("

\n"); #ifdef LEGACY_GRAPHICAL_CGIS printf("
\n", HISTOGRAM_CGI); #else printf("\n", LEGACY_HISTOGRAM_CGI); #endif printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Type:\n"); printf("\n"); printf("
\n"); printf("\n"); printf("
\n"); printf("
\n"); printf("

\n"); } } document_footer(); /* free all other allocated memory */ free_memory(); return OK; } void document_header(int use_stylesheet) { char date_time[MAX_DATETIME_LENGTH]; time_t current_time; time_t expire_time; if(mode == CREATE_HTML) { printf("Cache-Control: no-store\r\n"); printf("Pragma: no-cache\r\n"); time(¤t_time); get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Last-Modified: %s\r\n", date_time); expire_time = (time_t)0; get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; printf("\n"); printf("\n"); printf("\n", url_images_path); printf("\n"); printf("Nagios Histogram\n"); printf("\n"); if(use_stylesheet == TRUE) { printf("\n", url_stylesheets_path, COMMON_CSS); printf("\n", url_stylesheets_path, HISTOGRAM_CSS); } printf("\n"); printf("\n"); /* include user SSI header */ #ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(HISTOGRAM_CGI, SSI_HEADER); #else include_ssi_files(LEGACY_HISTOGRAM_CGI, SSI_HEADER); #endif printf("
\n"); } else { printf("Cache-Control: no-store\r\n"); printf("Pragma: no-cache\r\n"); time(¤t_time); get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Last-Modified: %s\r\n", date_time); expire_time = (time_t)0L; get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); printf("Content-Type: image/png\r\n\r\n"); } return; } void document_footer(void) { if(embedded == TRUE) return; if(mode == CREATE_HTML) { /* include user SSI footer */ #ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(HISTOGRAM_CGI, SSI_FOOTER); #else include_ssi_files(LEGACY_HISTOGRAM_CGI, SSI_FOOTER); #endif printf("\n"); printf("\n"); } return; } int process_cgivars(void) { char **variables; int error = FALSE; int x; variables = getcgivars(); for(x = 0; variables[x] != NULL; x++) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { continue; } /* we found the host argument */ else if(!strcmp(variables[x], "host")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if((host_name = (char *)strdup(variables[x])) == NULL) host_name = ""; strip_html_brackets(host_name); display_type = DISPLAY_HOST_HISTOGRAM; } /* we found the node width argument */ else if(!strcmp(variables[x], "service")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if((svc_description = (char *)strdup(variables[x])) == NULL) svc_description = ""; strip_html_brackets(svc_description); display_type = DISPLAY_SERVICE_HISTOGRAM; } /* we found first time argument */ else if(!strcmp(variables[x], "t1")) { x++; if(variables[x] == NULL) { error = TRUE; break; } t1 = (time_t)strtoul(variables[x], NULL, 10); timeperiod_type = TIMEPERIOD_CUSTOM; } /* we found first time argument */ else if(!strcmp(variables[x], "t2")) { x++; if(variables[x] == NULL) { error = TRUE; break; } t2 = (time_t)strtoul(variables[x], NULL, 10); timeperiod_type = TIMEPERIOD_CUSTOM; } /* we found the image creation option */ else if(!strcmp(variables[x], "createimage")) { mode = CREATE_IMAGE; } /* we found the backtrack archives argument */ else if(!strcmp(variables[x], "backtrack")) { x++; if(variables[x] == NULL) { error = TRUE; break; } backtrack_archives = atoi(variables[x]); if(backtrack_archives < 0) backtrack_archives = 0; if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS) backtrack_archives = MAX_ARCHIVE_BACKTRACKS; } /* we found the standard timeperiod argument */ else if(!strcmp(variables[x], "timeperiod")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(!strcmp(variables[x], "today")) timeperiod_type = TIMEPERIOD_TODAY; else if(!strcmp(variables[x], "yesterday")) timeperiod_type = TIMEPERIOD_YESTERDAY; else if(!strcmp(variables[x], "thisweek")) timeperiod_type = TIMEPERIOD_THISWEEK; else if(!strcmp(variables[x], "lastweek")) timeperiod_type = TIMEPERIOD_LASTWEEK; else if(!strcmp(variables[x], "thismonth")) timeperiod_type = TIMEPERIOD_THISMONTH; else if(!strcmp(variables[x], "lastmonth")) timeperiod_type = TIMEPERIOD_LASTMONTH; else if(!strcmp(variables[x], "thisquarter")) timeperiod_type = TIMEPERIOD_THISQUARTER; else if(!strcmp(variables[x], "lastquarter")) timeperiod_type = TIMEPERIOD_LASTQUARTER; else if(!strcmp(variables[x], "thisyear")) timeperiod_type = TIMEPERIOD_THISYEAR; else if(!strcmp(variables[x], "lastyear")) timeperiod_type = TIMEPERIOD_LASTYEAR; else if(!strcmp(variables[x], "last24hours")) timeperiod_type = TIMEPERIOD_LAST24HOURS; else if(!strcmp(variables[x], "last7days")) timeperiod_type = TIMEPERIOD_LAST7DAYS; else if(!strcmp(variables[x], "last31days")) timeperiod_type = TIMEPERIOD_LAST31DAYS; else if(!strcmp(variables[x], "custom")) timeperiod_type = TIMEPERIOD_CUSTOM; else timeperiod_type = TIMEPERIOD_TODAY; if(timeperiod_type != TIMEPERIOD_CUSTOM) convert_timeperiod_to_times(timeperiod_type); } /* we found time argument */ else if(!strcmp(variables[x], "smon")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; start_month = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "sday")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; start_day = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "syear")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; start_year = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "smin")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; start_minute = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "ssec")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; start_second = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "shour")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; start_hour = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "emon")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; end_month = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "eday")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; end_day = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "eyear")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; end_year = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "emin")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; end_minute = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "esec")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; end_second = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found time argument */ else if(!strcmp(variables[x], "ehour")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(timeperiod_type != TIMEPERIOD_CUSTOM) continue; end_hour = atoi(variables[x]); timeperiod_type = TIMEPERIOD_CUSTOM; compute_time_from_parts = TRUE; } /* we found the embed option */ else if(!strcmp(variables[x], "embedded")) embedded = TRUE; /* we found the noheader option */ else if(!strcmp(variables[x], "noheader")) display_header = FALSE; /* we found the input option */ else if(!strcmp(variables[x], "input")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(!strcmp(variables[x], "gethost")) input_type = GET_INPUT_HOST_TARGET; else if(!strcmp(variables[x], "getservice")) input_type = GET_INPUT_SERVICE_TARGET; else if(!strcmp(variables[x], "getoptions")) input_type = GET_INPUT_OPTIONS; else input_type = GET_INPUT_TARGET_TYPE; } /* we found the graph states option */ else if(!strcmp(variables[x], "graphevents")) { x++; if(variables[x] == NULL) { error = TRUE; break; } graph_events = atoi(variables[x]); } /* we found the graph state types option */ else if(!strcmp(variables[x], "graphstatetypes")) { x++; if(variables[x] == NULL) { error = TRUE; break; } graph_statetypes = atoi(variables[x]); } /* we found the breakdown option */ else if(!strcmp(variables[x], "breakdown")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(!strcmp(variables[x], "monthly")) breakdown_type = BREAKDOWN_MONTHLY; else if(!strcmp(variables[x], "dayofmonth")) breakdown_type = BREAKDOWN_DAY_OF_MONTH; else if(!strcmp(variables[x], "dayofweek")) breakdown_type = BREAKDOWN_DAY_OF_WEEK; else breakdown_type = BREAKDOWN_HOURLY; } /* we found the assume state retention option */ else if(!strcmp(variables[x], "assumestateretention")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(!strcmp(variables[x], "yes")) assume_state_retention = TRUE; else assume_state_retention = FALSE; } /* we found the initial states logged option */ else if(!strcmp(variables[x], "initialstateslogged")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(!strcmp(variables[x], "yes")) initial_states_logged = TRUE; else initial_states_logged = FALSE; } /* we found the new states only option */ else if(!strcmp(variables[x], "newstatesonly")) { x++; if(variables[x] == NULL) { error = TRUE; break; } if(!strcmp(variables[x], "yes")) new_states_only = TRUE; else new_states_only = FALSE; } } /* free memory allocated to the CGI variables */ free_cgivars(variables); return error; } /* graphs histogram data */ void graph_all_histogram_data(void) { int pixel_x; int pixel_y; int last_pixel_y; int current_bucket; int actual_bucket; unsigned long max_value; double x_scaling_factor; double y_scaling_factor; double x_units; double y_units; int current_unit; int actual_unit; char temp_buffer[MAX_INPUT_BUFFER]; int string_width; int string_height; char *days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; char *months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; char start_time[MAX_INPUT_BUFFER]; char end_time[MAX_INPUT_BUFFER]; unsigned long state1_max = 0L; unsigned long state1_min = 0L; int have_state1_min = FALSE; unsigned long state1_sum = 0L; double state1_avg = 0.0; unsigned long state2_max = 0L; unsigned long state2_min = 0L; int have_state2_min = FALSE; unsigned long state2_sum = 0L; double state2_avg = 0.0; unsigned long state3_max = 0L; unsigned long state3_min = 0L; int have_state3_min = FALSE; unsigned long state3_sum = 0L; double state3_avg = 0.0; unsigned long state4_max = 0L; unsigned long state4_min = 0L; int have_state4_min = FALSE; unsigned long state4_sum = 0L; double state4_avg = 0.0; #ifdef DEBUG printf("Total Buckets: %d\n", total_buckets); #endif /* determine max value in the buckets (for scaling) */ max_value = 0L; for(current_bucket = 0; current_bucket < total_buckets; current_bucket++) { if(tsdata[current_bucket].service_ok > max_value) max_value = tsdata[current_bucket].service_ok; if(tsdata[current_bucket].service_warning > max_value) max_value = tsdata[current_bucket].service_warning; if(tsdata[current_bucket].service_unknown > max_value) max_value = tsdata[current_bucket].service_unknown; if(tsdata[current_bucket].service_critical > max_value) max_value = tsdata[current_bucket].service_critical; if(tsdata[current_bucket].host_up > max_value) max_value = tsdata[current_bucket].host_up; if(tsdata[current_bucket].host_down > max_value) max_value = tsdata[current_bucket].host_down; if(tsdata[current_bucket].host_unreachable > max_value) max_value = tsdata[current_bucket].host_unreachable; } #ifdef DEBUG printf("Done determining max bucket values\n"); printf("MAX_VALUE=%lu\n", max_value); printf("DRAWING_HEIGHT=%lu\n", DRAWING_HEIGHT); #endif /* min number of values to graph */ if(max_value < 10) max_value = 10; #ifdef DEBUG printf("ADJUSTED MAX_VALUE=%lu\n", max_value); #endif /* determine y scaling factor */ /*y_scaling_factor=floor((double)DRAWING_HEIGHT/(double)max_value);*/ y_scaling_factor = (double)((double)DRAWING_HEIGHT / (double)max_value); /* determine x scaling factor */ x_scaling_factor = (double)((double)DRAWING_WIDTH / (double)total_buckets); /* determine y units resolution - we want a max of about 10 y grid lines */ /* y_units=(double)((double)DRAWING_HEIGHT/19.0); y_units=ceil(y_units/y_scaling_factor)*y_scaling_factor; */ y_units = ceil(19.0 / y_scaling_factor); /* determine x units resolution */ if(breakdown_type == BREAKDOWN_HOURLY) x_units = (double)((double)DRAWING_WIDTH / (double)(total_buckets / 4.0)); else x_units = x_scaling_factor; #ifdef DEBUG printf("DRAWING_WIDTH: %d\n", DRAWING_WIDTH); printf("DRAWING_HEIGHT: %d\n", DRAWING_HEIGHT); printf("max_value: %lu\n", max_value); printf("x_scaling_factor: %.3f\n", x_scaling_factor); printf("y_scaling_factor: %.3f\n", y_scaling_factor); printf("x_units: %.3f\n", x_units); printf("y_units: %.3f\n", y_units); printf("y units to draw: %.3f\n", ((double)max_value / y_units)); #endif string_height = gdFontSmall->h; #ifdef DEBUG printf("Starting to draw Y grid lines...\n"); #endif /* draw y grid lines */ if(max_value > 0) { for(current_unit = 1; (current_unit * y_units * y_scaling_factor) <= DRAWING_HEIGHT; current_unit++) { 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); #ifdef DEBUG printf(" Drawing Y unit #%d @ %d\n", current_unit, (int)(current_unit * y_units * y_scaling_factor)); #endif } } #ifdef DEBUG printf("Starting to draw X grid lines...\n"); #endif /* draw x grid lines */ for(current_unit = 1; (int)(current_unit * x_units) <= DRAWING_WIDTH; current_unit++) 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); #ifdef DEBUG printf("Starting to draw grid units...\n"); #endif /* draw y units */ if(max_value > 0) { for(current_unit = 0; (current_unit * y_units * y_scaling_factor) <= DRAWING_HEIGHT; current_unit++) { snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%d", (int)(current_unit * y_units)); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); } } /* draw x units */ for(current_unit = 0, actual_unit = 0; (int)(current_unit * x_units) <= DRAWING_WIDTH; current_unit++, actual_unit++) { if(actual_unit >= total_buckets) actual_unit = 0; if(breakdown_type == BREAKDOWN_MONTHLY) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", months[actual_unit]); else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%d", actual_unit + 1); else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", days[actual_unit]); else snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%02d:00", (actual_unit == 24) ? 0 : actual_unit); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); } /* draw y unit measure */ snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Number of Events"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); gdImageStringUp(histogram_image, gdFontSmall, 0, DRAWING_Y_OFFSET - (DRAWING_HEIGHT / 2) + (string_width / 2), (unsigned char *)temp_buffer, color_black); /* draw x unit measure */ if(breakdown_type == BREAKDOWN_MONTHLY) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Month"); else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Day of the Month"); else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Day of the Week"); else snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Hour of the Day (15 minute increments)"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), DRAWING_Y_OFFSET + 70, (unsigned char *)temp_buffer, color_black); /* draw title */ snprintf(start_time, sizeof(start_time) - 1, "%s", ctime(&t1)); start_time[sizeof(start_time) - 1] = '\x0'; start_time[strlen(start_time) - 1] = '\x0'; snprintf(end_time, sizeof(end_time) - 1, "%s", ctime(&t2)); end_time[sizeof(end_time) - 1] = '\x0'; end_time[strlen(end_time) - 1] = '\x0'; if(display_type == DISPLAY_HOST_HISTOGRAM) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Event History For Host '%s'", host_name); else snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Event History For Service '%s' On Host '%s'", svc_description, host_name); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), 0, (unsigned char *)temp_buffer, color_black); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s to %s", start_time, end_time); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + (DRAWING_WIDTH / 2) - (string_width / 2), string_height + 5, (unsigned char *)temp_buffer, color_black); #ifdef DEBUG printf("About to starting graphing (total_buckets=%d)...\n", total_buckets); #endif /* graph service states */ if(display_type == DISPLAY_HOST_HISTOGRAM) { /* graph host recoveries */ if(graph_events & GRAPH_HOST_UP) { last_pixel_y = 0; for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) { if(actual_bucket >= total_buckets) actual_bucket = 0; pixel_x = (int)(current_bucket * x_scaling_factor); pixel_y = (int)(tsdata[actual_bucket].host_up * y_scaling_factor); if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0)) 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); last_pixel_y = pixel_y; if(current_bucket < total_buckets) { if(have_state1_min == FALSE || tsdata[actual_bucket].host_up < state1_min) { state1_min = tsdata[actual_bucket].host_up; have_state1_min = TRUE; } if(state1_max == 0 || tsdata[actual_bucket].host_up > state1_max) state1_max = tsdata[actual_bucket].host_up; state1_sum += tsdata[actual_bucket].host_up; } } } #ifdef DEBUG printf("Done graphing HOST UP states...\n"); #endif /* graph host down states */ if(graph_events & GRAPH_HOST_DOWN) { last_pixel_y = 0; for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) { if(actual_bucket >= total_buckets) actual_bucket = 0; pixel_x = (int)(current_bucket * x_scaling_factor); pixel_y = (int)(tsdata[actual_bucket].host_down * y_scaling_factor); if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0)) 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); last_pixel_y = pixel_y; if(current_bucket < total_buckets) { if(have_state2_min == FALSE || tsdata[actual_bucket].host_down < state2_min) { state2_min = tsdata[actual_bucket].host_down; have_state2_min = TRUE; } if(state2_max == 0 || tsdata[actual_bucket].host_down > state2_max) state2_max = tsdata[actual_bucket].host_down; state2_sum += tsdata[actual_bucket].host_down; } } } #ifdef DEBUG printf("Done graphing HOST DOWN states...\n"); #endif /* graph host unreachable states */ if(graph_events & GRAPH_HOST_UNREACHABLE) { last_pixel_y = 0; for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) { if(actual_bucket >= total_buckets) actual_bucket = 0; pixel_x = (int)(current_bucket * x_scaling_factor); pixel_y = (int)(tsdata[actual_bucket].host_unreachable * y_scaling_factor); if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0)) 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); last_pixel_y = pixel_y; if(current_bucket < total_buckets) { if(have_state3_min == FALSE || tsdata[actual_bucket].host_unreachable < state3_min) { state3_min = tsdata[actual_bucket].host_unreachable; have_state3_min = TRUE; } if(state3_max == 0 || tsdata[actual_bucket].host_unreachable > state3_max) state3_max = tsdata[actual_bucket].host_unreachable; state3_sum += tsdata[actual_bucket].host_unreachable; } } } #ifdef DEBUG printf("Done graphing HOST UNREACHABLE states...\n"); #endif } /* graph service states */ else { /* graph service recoveries */ if(graph_events & GRAPH_SERVICE_OK) { last_pixel_y = 0; for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) { if(actual_bucket >= total_buckets) actual_bucket = 0; pixel_x = (int)(current_bucket * x_scaling_factor); pixel_y = (int)(tsdata[actual_bucket].service_ok * y_scaling_factor); if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0)) 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); last_pixel_y = pixel_y; if(current_bucket < total_buckets) { if(have_state1_min == FALSE || tsdata[actual_bucket].service_ok < state1_min) { state1_min = tsdata[actual_bucket].service_ok; have_state1_min = TRUE; } if(state1_max == 0 || tsdata[actual_bucket].service_ok > state1_max) state1_max = tsdata[actual_bucket].service_ok; state1_sum += tsdata[actual_bucket].service_ok; } } } /* graph service warning states */ if(graph_events & GRAPH_SERVICE_WARNING) { last_pixel_y = 0; for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) { if(actual_bucket >= total_buckets) actual_bucket = 0; pixel_x = (int)(current_bucket * x_scaling_factor); pixel_y = (int)(tsdata[actual_bucket].service_warning * y_scaling_factor); if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0)) 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); last_pixel_y = pixel_y; if(current_bucket < total_buckets) { if(have_state2_min == FALSE || tsdata[actual_bucket].service_warning < state2_min) { state2_min = tsdata[actual_bucket].service_warning; have_state2_min = TRUE; } if(state2_max == 0 || tsdata[actual_bucket].service_warning > state2_max) state2_max = tsdata[actual_bucket].service_warning; state2_sum += tsdata[actual_bucket].service_warning; } } } /* graph service unknown states */ if(graph_events & GRAPH_SERVICE_UNKNOWN) { last_pixel_y = 0; for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) { if(actual_bucket >= total_buckets) actual_bucket = 0; pixel_x = (int)(current_bucket * x_scaling_factor); pixel_y = (int)(tsdata[actual_bucket].service_unknown * y_scaling_factor); if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0)) 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); last_pixel_y = pixel_y; if(current_bucket < total_buckets) { if(have_state3_min == FALSE || tsdata[actual_bucket].service_unknown < state3_min) { state3_min = tsdata[actual_bucket].service_unknown; have_state3_min = TRUE; } if(state3_max == 0 || tsdata[actual_bucket].service_unknown > state3_max) state3_max = tsdata[actual_bucket].service_unknown; state3_sum += tsdata[actual_bucket].service_unknown; } } } /* graph service critical states */ if(graph_events & GRAPH_SERVICE_CRITICAL) { last_pixel_y = 0; for(current_bucket = 0, actual_bucket = 0; current_bucket <= total_buckets; current_bucket++, actual_bucket++) { if(actual_bucket >= total_buckets) actual_bucket = 0; pixel_x = (int)(current_bucket * x_scaling_factor); pixel_y = (int)(tsdata[actual_bucket].service_critical * y_scaling_factor); if(current_bucket > 0 && !(last_pixel_y == 0 && pixel_y == 0)) 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); last_pixel_y = pixel_y; if(current_bucket < total_buckets) { if(have_state4_min == FALSE || tsdata[actual_bucket].service_critical < state4_min) { state4_min = tsdata[actual_bucket].service_critical; have_state4_min = TRUE; } if(state4_max == 0 || tsdata[actual_bucket].service_critical > state4_max) state4_max = tsdata[actual_bucket].service_critical; state4_sum += tsdata[actual_bucket].service_critical; } } } } #ifdef DEBUG printf("Done graphing states...\n"); #endif /* draw graph boundaries */ draw_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET, DRAWING_X_OFFSET, DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_black); draw_line(DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET, DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET - DRAWING_HEIGHT, color_black); draw_line(DRAWING_X_OFFSET, DRAWING_Y_OFFSET, DRAWING_X_OFFSET + DRAWING_WIDTH, DRAWING_Y_OFFSET, color_black); /* graph stats */ snprintf(temp_buffer, sizeof(temp_buffer) - 1, "EVENT TYPE"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 15, DRAWING_Y_OFFSET - DRAWING_HEIGHT, (unsigned char *)temp_buffer, color_black); snprintf(temp_buffer, sizeof(temp_buffer) - 1, " MIN MAX SUM AVG"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); gdImageString(histogram_image, gdFontSmall, DRAWING_X_OFFSET + DRAWING_WIDTH + 115, DRAWING_Y_OFFSET - DRAWING_HEIGHT, (unsigned char *)temp_buffer, color_black); 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); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Recovery (%s):", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Ok" : "Up"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); state1_avg = (double)((double)state1_sum / (double)total_buckets); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state1_min, state1_max, state1_sum, state1_avg); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s:", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Warning" : "Down"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); state2_avg = (double)((double)state2_sum / (double)total_buckets); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state2_min, state2_max, state2_sum, state2_avg); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s:", (display_type == DISPLAY_SERVICE_HISTOGRAM) ? "Unknown" : "Unreachable"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); state3_avg = (double)((double)state3_sum / (double)total_buckets); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state3_min, state3_max, state3_sum, state3_avg); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); if(display_type == DISPLAY_SERVICE_HISTOGRAM) { snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Critical:"); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); state4_avg = (double)((double)state4_sum / (double)total_buckets); snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%5lu %5lu %5lu %.2f", state4_min, state4_max, state4_sum, state4_avg); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; string_width = gdFontSmall->w * strlen(temp_buffer); 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); } return; } /* adds an archived state entry */ void add_archived_state(int state_type, time_t time_stamp) { struct tm *our_time; int bucket; int skip_state = FALSE; #ifdef DEBUG2 printf("NEW ENTRY: last=%d this=%d\n", last_state, state_type); #endif /* don't record program starts/stops, just make a note that one occurred */ if(state_type == AS_PROGRAM_START || state_type == AS_PROGRAM_END) { #ifdef DEBUG2 printf("Recording a program start: %d\n", state_type); #endif program_restart_has_occurred = TRUE; return; } /* see if we should even take into account this event */ if(program_restart_has_occurred == TRUE) { #ifdef DEBUG2 printf("program_restart_has_occurred: last=%d this=%d\n", last_state, state_type); #endif if(initial_states_logged == TRUE) { if(state_type == AS_SVC_OK && last_state == AS_SVC_OK) skip_state = TRUE; if(state_type == AS_HOST_UP && last_state == AS_HOST_UP) skip_state = TRUE; } if(assume_state_retention == TRUE && initial_states_logged == TRUE) { if(state_type == AS_SVC_WARNING && last_state == AS_SVC_WARNING) skip_state = TRUE; if(state_type == AS_SVC_UNKNOWN && last_state == AS_SVC_UNKNOWN) skip_state = TRUE; if(state_type == AS_SVC_CRITICAL && last_state == AS_SVC_CRITICAL) skip_state = TRUE; if(state_type == AS_HOST_DOWN && last_state == AS_HOST_DOWN) skip_state = TRUE; if(state_type == AS_HOST_UNREACHABLE && last_state == AS_HOST_UNREACHABLE) skip_state = TRUE; } if(skip_state == TRUE) { program_restart_has_occurred = FALSE; #ifdef DEBUG2 printf("Skipping state...\n"); #endif return; } } /* reset program restart variable */ program_restart_has_occurred = FALSE; /* are we only processing new states */ if(new_states_only == TRUE && state_type == last_state) { #ifdef DEBUG2 printf("Skipping state (not a new state)...\n"); #endif return; } #ifdef DEBUG2 printf("GOODSTATE: %d @ %lu\n", state_type, (unsigned long)time_stamp); #endif our_time = localtime(&time_stamp); /* calculate the correct bucket to dump the data into */ if(breakdown_type == BREAKDOWN_MONTHLY) bucket = our_time->tm_mon; else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH) bucket = our_time->tm_mday - 1; else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK) bucket = our_time->tm_wday; else bucket = (our_time->tm_hour * 4) + (our_time->tm_min / 15); #ifdef DEBUG2 printf("\tBucket=%d\n", bucket); #endif /* save the data in the correct bucket */ if(state_type == AS_SVC_OK) tsdata[bucket].service_ok++; else if(state_type == AS_SVC_UNKNOWN) tsdata[bucket].service_unknown++; else if(state_type == AS_SVC_WARNING) tsdata[bucket].service_warning++; else if(state_type == AS_SVC_CRITICAL) tsdata[bucket].service_critical++; else if(state_type == AS_HOST_UP) tsdata[bucket].host_up++; else if(state_type == AS_HOST_DOWN) tsdata[bucket].host_down++; else if(state_type == AS_HOST_UNREACHABLE) tsdata[bucket].host_unreachable++; /* record last state type */ last_state = state_type; return; } /* reads log files for archived state data */ void read_archived_state_data(void) { char filename[MAX_FILENAME_LENGTH]; int newest_archive = 0; int oldest_archive = 0; int current_archive; #ifdef DEBUG2 printf("Determining archives to use...\n"); #endif /* determine earliest archive to use */ oldest_archive = determine_archive_to_use_from_time(t1); if(log_rotation_method != LOG_ROTATION_NONE) oldest_archive += backtrack_archives; /* determine most recent archive to use */ newest_archive = determine_archive_to_use_from_time(t2); if(oldest_archive < newest_archive) oldest_archive = newest_archive; #ifdef DEBUG2 printf("Oldest archive: %d\n", oldest_archive); printf("Newest archive: %d\n", newest_archive); #endif /* read in all the necessary archived logs */ for(current_archive = newest_archive; current_archive <= oldest_archive; current_archive++) { /* get the name of the log file that contains this archive */ get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1); #ifdef DEBUG2 printf("\tCurrent archive: %d (%s)\n", current_archive, filename); #endif /* scan the log file for archived state data */ scan_log_file_for_archived_state_data(filename); } return; } /* grabs archives state data from a log file */ void scan_log_file_for_archived_state_data(char *filename) { char *input = NULL; char *input2 = NULL; char entry_host_name[MAX_INPUT_BUFFER]; char entry_svc_description[MAX_INPUT_BUFFER]; char *temp_buffer; time_t time_stamp; mmapfile *thefile; /* print something so browser doesn't time out */ if(mode == CREATE_HTML) { printf(" "); fflush(NULL); } if((thefile = mmap_fopen(filename)) == NULL) { #ifdef DEBUG2 printf("Could not open file '%s' for reading.\n", filename); #endif return; } #ifdef DEBUG2 printf("Scanning log file '%s' for archived state data...\n", filename); #endif while(1) { /* free memory */ free(input); free(input2); input = NULL; input2 = NULL; /* read the next line */ if((input = mmap_fgets(thefile)) == NULL) break; strip(input); if((input2 = strdup(input)) == NULL) continue; temp_buffer = my_strtok(input2, "]"); time_stamp = (temp_buffer == NULL) ? (time_t)0 : (time_t)strtoul(temp_buffer + 1, NULL, 10); /* program starts/restarts */ if(strstr(input, " starting...")) add_archived_state(AS_PROGRAM_START, time_stamp); if(strstr(input, " restarting...")) add_archived_state(AS_PROGRAM_START, time_stamp); /* program stops */ if(strstr(input, " shutting down...")) add_archived_state(AS_PROGRAM_END, time_stamp); if(strstr(input, "Bailing out")) add_archived_state(AS_PROGRAM_END, time_stamp); if(display_type == DISPLAY_HOST_HISTOGRAM) { if(strstr(input, "HOST ALERT:")) { /* get host name */ temp_buffer = my_strtok(NULL, ":"); temp_buffer = my_strtok(NULL, ";"); strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name)); entry_host_name[sizeof(entry_host_name) - 1] = '\x0'; if(strcmp(host_name, entry_host_name)) continue; /* skip soft states if necessary */ if(!(graph_statetypes & GRAPH_SOFT_STATETYPES) && strstr(input, ";SOFT;")) continue; /* skip hard states if necessary */ if(!(graph_statetypes & GRAPH_HARD_STATETYPES) && strstr(input, ";HARD;")) continue; if(strstr(input, ";DOWN;")) add_archived_state(AS_HOST_DOWN, time_stamp); else if(strstr(input, ";UNREACHABLE;")) add_archived_state(AS_HOST_UNREACHABLE, time_stamp); else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;")) add_archived_state(AS_HOST_UP, time_stamp); } } if(display_type == DISPLAY_SERVICE_HISTOGRAM) { if(strstr(input, "SERVICE ALERT:")) { /* get host name */ temp_buffer = my_strtok(NULL, ":"); temp_buffer = my_strtok(NULL, ";"); strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name)); entry_host_name[sizeof(entry_host_name) - 1] = '\x0'; if(strcmp(host_name, entry_host_name)) continue; /* get service description */ temp_buffer = my_strtok(NULL, ";"); strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(entry_svc_description)); entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0'; if(strcmp(svc_description, entry_svc_description)) continue; /* skip soft states if necessary */ if(!(graph_statetypes & GRAPH_SOFT_STATETYPES) && strstr(input, ";SOFT;")) continue; /* skip hard states if necessary */ if(!(graph_statetypes & GRAPH_HARD_STATETYPES) && strstr(input, ";HARD;")) continue; if(strstr(input, ";CRITICAL;")) add_archived_state(AS_SVC_CRITICAL, time_stamp); else if(strstr(input, ";WARNING;")) add_archived_state(AS_SVC_WARNING, time_stamp); else if(strstr(input, ";UNKNOWN;")) add_archived_state(AS_SVC_UNKNOWN, time_stamp); else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;")) add_archived_state(AS_SVC_OK, time_stamp); } } } /* free memory and close the file */ free(input); free(input2); mmap_fclose(thefile); return; } void convert_timeperiod_to_times(int type) { time_t current_time; struct tm *t; /* get the current time */ time(¤t_time); t = localtime(¤t_time); t->tm_sec = 0; t->tm_min = 0; t->tm_hour = 0; t->tm_isdst = -1; switch(type) { case TIMEPERIOD_LAST24HOURS: t1 = current_time - (60 * 60 * 24); t2 = current_time; break; case TIMEPERIOD_TODAY: t1 = mktime(t); t2 = current_time; break; case TIMEPERIOD_YESTERDAY: t1 = (time_t)(mktime(t) - (60 * 60 * 24)); t2 = (time_t)mktime(t); break; case TIMEPERIOD_THISWEEK: t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday)); t2 = current_time; break; case TIMEPERIOD_LASTWEEK: t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday) - (60 * 60 * 24 * 7)); t2 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday)); break; case TIMEPERIOD_THISMONTH: t->tm_mday = 1; t1 = mktime(t); t2 = current_time; break; case TIMEPERIOD_LASTMONTH: t->tm_mday = 1; t2 = mktime(t); if(t->tm_mon == 0) { t->tm_mon = 11; t->tm_year--; } else t->tm_mon--; t1 = mktime(t); break; case TIMEPERIOD_THISQUARTER: break; case TIMEPERIOD_LASTQUARTER: break; case TIMEPERIOD_THISYEAR: t->tm_mon = 0; t->tm_mday = 1; t1 = mktime(t); t2 = current_time; break; case TIMEPERIOD_LASTYEAR: t->tm_mon = 0; t->tm_mday = 1; t2 = mktime(t); t->tm_year--; t1 = mktime(t); break; case TIMEPERIOD_LAST7DAYS: t2 = current_time; t1 = current_time - (7 * 24 * 60 * 60); break; case TIMEPERIOD_LAST31DAYS: t2 = current_time; t1 = current_time - (31 * 24 * 60 * 60); break; default: break; } return; } void compute_report_times(void) { time_t current_time; struct tm *st; struct tm *et; /* get the current time */ time(¤t_time); st = localtime(¤t_time); st->tm_sec = start_second; st->tm_min = start_minute; st->tm_hour = start_hour; st->tm_mday = start_day; st->tm_mon = start_month - 1; st->tm_year = start_year - 1900; st->tm_isdst = -1; t1 = mktime(st); et = localtime(¤t_time); et->tm_sec = end_second; et->tm_min = end_minute; et->tm_hour = end_hour; et->tm_mday = end_day; et->tm_mon = end_month - 1; et->tm_year = end_year - 1900; et->tm_isdst = -1; t2 = mktime(et); } /* draws a solid line */ void draw_line(int x1, int y1, int x2, int y2, int color) { int styleSolid[1]; styleSolid[0] = color; /* sets current style to a solid line */ gdImageSetStyle(histogram_image, styleSolid, 1); /* draws a line (dashed) */ gdImageLine(histogram_image, x1, y1, x2, y2, gdStyled); return; } /* draws a dashed line */ void draw_dashed_line(int x1, int y1, int x2, int y2, int color) { int styleDashed[6]; styleDashed[0] = color; styleDashed[1] = color; styleDashed[2] = gdTransparent; styleDashed[3] = gdTransparent; styleDashed[4] = gdTransparent; styleDashed[5] = gdTransparent; /* sets current style to a solid line */ gdImageSetStyle(histogram_image, styleDashed, 6); /* draws a line (dashed) */ gdImageLine(histogram_image, x1, y1, x2, y2, gdStyled); return; }