nagios4/cgi/histogram.c

2482 lines
82 KiB
C

/**************************************************************************
*
* HISTOGRAM.C - Nagios Alert Histogram CGI
*
* Copyright (c) 2001-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-15-2008
*
* 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 <gd.h> /* Boutell's GD library function */
#include <gdfonts.h> /* 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 int log_rotation_method;
extern host *host_list;
extern service *service_list;
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();
/* 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(get_cgi_config_location(), 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(&current_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("<table border=0 width=100%% cellspacing=0 cellpadding=0>\n");
printf("<tr>\n");
/* left column of the first row */
printf("<td align=left valign=top width=33%%>\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, &current_authdata);
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
printf("<TR><TD CLASS='linkBox'>\n");
if(display_type == DISPLAY_HOST_HISTOGRAM) {
#ifdef USE_TRENDS
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");
#endif
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");
printf("<a href='%s?host=%s'>View Status Detail For This Host</a><BR>\n", STATUS_CGI, url_encode(host_name));
printf("<a href='%s?host=%s'>View History For This Host</a><BR>\n", HISTORY_CGI, url_encode(host_name));
printf("<a href='%s?host=%s'>View Notifications For This Host</a><BR>\n", NOTIFICATIONS_CGI, url_encode(host_name));
}
else {
#ifdef USE_TRENDS
printf("<a href='%s?host=%s", TRENDS_CGI, url_encode(host_name));
#endif
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");
printf("<a href='%s?host=%s", AVAIL_CGI, url_encode(host_name));
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");
printf("<A HREF='%s?host=%s&", HISTORY_CGI, url_encode(host_name));
printf("service=%s'>View History For This Service</A><BR>\n", url_encode(svc_description));
printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
printf("service=%s'>View Notifications For This Service</A><BR>\n", url_encode(svc_description));
}
printf("</TD></TR>\n");
printf("</TABLE>\n");
}
printf("</td>\n");
/* center column of top row */
printf("<td align=center valign=top width=33%%>\n");
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\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("</DIV>\n");
printf("<BR>\n");
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");
printf("<BR CLEAR=ALL>\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("<div align=center class='reportRange'>%s to %s</div>\n", start_timestring, end_timestring);
get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds);
printf("<div align=center class='reportDuration'>Duration: %dd %dh %dm %ds</div>\n", days, hours, minutes, seconds);
}
printf("</td>\n");
/* right hand column of top row */
printf("<td align=right valign=bottom width=33%%>\n");
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
printf("<table border=0 CLASS='optBox'>\n");
if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) {
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");
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<input type='hidden' name='t1' value='%lu'>\n", (unsigned long)t1);
printf("<input type='hidden' name='t2' value='%lu'>\n", (unsigned long)t2);
printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
if(display_type == DISPLAY_SERVICE_HISTOGRAM)
printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
printf("<select name='timeperiod'>\n");
printf("<option value=custom>[ Current time range ]\n");
printf("<option value=today %s>Today\n", (timeperiod_type == TIMEPERIOD_TODAY) ? "SELECTED" : "");
printf("<option value=last24hours %s>Last 24 Hours\n", (timeperiod_type == TIMEPERIOD_LAST24HOURS) ? "SELECTED" : "");
printf("<option value=yesterday %s>Yesterday\n", (timeperiod_type == TIMEPERIOD_YESTERDAY) ? "SELECTED" : "");
printf("<option value=thisweek %s>This Week\n", (timeperiod_type == TIMEPERIOD_THISWEEK) ? "SELECTED" : "");
printf("<option value=last7days %s>Last 7 Days\n", (timeperiod_type == TIMEPERIOD_LAST7DAYS) ? "SELECTED" : "");
printf("<option value=lastweek %s>Last Week\n", (timeperiod_type == TIMEPERIOD_LASTWEEK) ? "SELECTED" : "");
printf("<option value=thismonth %s>This Month\n", (timeperiod_type == TIMEPERIOD_THISMONTH) ? "SELECTED" : "");
printf("<option value=last31days %s>Last 31 Days\n", (timeperiod_type == TIMEPERIOD_LAST31DAYS) ? "SELECTED" : "");
printf("<option value=lastmonth %s>Last Month\n", (timeperiod_type == TIMEPERIOD_LASTMONTH) ? "SELECTED" : "");
printf("<option value=thisyear %s>This Year\n", (timeperiod_type == TIMEPERIOD_THISYEAR) ? "SELECTED" : "");
printf("<option value=lastyear %s>Last Year\n", (timeperiod_type == TIMEPERIOD_LASTYEAR) ? "SELECTED" : "");
printf("</select>\n");
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<select name='assumestateretention'>\n");
printf("<option value=yes %s>yes\n", (assume_state_retention == TRUE) ? "SELECTED" : "");
printf("<option value=no %s>no\n", (assume_state_retention == TRUE) ? "" : "SELECTED");
printf("</select>\n");
printf("</td></tr>\n");
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");
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<select name='breakdown'>\n");
printf("<option value=monthly %s>Month\n", (breakdown_type == BREAKDOWN_MONTHLY) ? "SELECTED" : "");
printf("<option value=dayofmonth %s>Day of the Month\n", (breakdown_type == BREAKDOWN_DAY_OF_MONTH) ? "SELECTED" : "");
printf("<option value=dayofweek %s>Day of the Week\n", (breakdown_type == BREAKDOWN_DAY_OF_WEEK) ? "SELECTED" : "");
printf("<option value=hourly %s>Hour of the Day\n", (breakdown_type == BREAKDOWN_HOURLY) ? "SELECTED" : "");
printf("</select>\n");
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<select name='initialstateslogged'>\n");
printf("<option value=yes %s>yes\n", (initial_states_logged == TRUE) ? "SELECTED" : "");
printf("<option value=no %s>no\n", (initial_states_logged == TRUE) ? "" : "SELECTED");
printf("</select>\n");
printf("</td></tr>\n");
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");
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<select name='graphevents'>\n");
if(display_type == DISPLAY_HOST_HISTOGRAM) {
printf("<option value=%d %s>All host events\n", GRAPH_HOST_ALL, (graph_events == GRAPH_HOST_ALL) ? "SELECTED" : "");
printf("<option value=%d %s>Host problem events\n", GRAPH_HOST_PROBLEMS, (graph_events == GRAPH_HOST_PROBLEMS) ? "SELECTED" : "");
printf("<option value=%d %s>Host up events\n", GRAPH_HOST_UP, (graph_events == GRAPH_HOST_UP) ? "SELECTED" : "");
printf("<option value=%d %s>Host down events\n", GRAPH_HOST_DOWN, (graph_events == GRAPH_HOST_DOWN) ? "SELECTED" : "");
printf("<option value=%d %s>Host unreachable events\n", GRAPH_HOST_UNREACHABLE, (graph_events == GRAPH_HOST_UNREACHABLE) ? "SELECTED" : "");
}
else {
printf("<option value=%d %s>All service events\n", GRAPH_SERVICE_ALL, (graph_events == GRAPH_SERVICE_ALL) ? "SELECTED" : "");
printf("<option value=%d %s>Service problem events\n", GRAPH_SERVICE_PROBLEMS, (graph_events == GRAPH_SERVICE_PROBLEMS) ? "SELECTED" : "");
printf("<option value=%d %s>Service ok events\n", GRAPH_SERVICE_OK, (graph_events == GRAPH_SERVICE_OK) ? "SELECTED" : "");
printf("<option value=%d %s>Service warning events\n", GRAPH_SERVICE_WARNING, (graph_events == GRAPH_SERVICE_WARNING) ? "SELECTED" : "");
printf("<option value=%d %s>Service unknown events\n", GRAPH_SERVICE_UNKNOWN, (graph_events == GRAPH_SERVICE_UNKNOWN) ? "SELECTED" : "");
printf("<option value=%d %s>Service critical events\n", GRAPH_SERVICE_CRITICAL, (graph_events == GRAPH_SERVICE_CRITICAL) ? "SELECTED" : "");
}
printf("</select>\n");
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<select name='newstatesonly'>\n");
printf("<option value=yes %s>yes\n", (new_states_only == TRUE) ? "SELECTED" : "");
printf("<option value=no %s>no\n", (new_states_only == TRUE) ? "" : "SELECTED");
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td CLASS='optBoxItem' valign=top align=left>State types to graph:</td><td CLASS='optBoxItem' valign=top align=left></td></tr>\n");
printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<select name='graphstatetypes'>\n");
printf("<option value=%d %s>Hard states\n", GRAPH_HARD_STATETYPES, (graph_statetypes == GRAPH_HARD_STATETYPES) ? "SELECTED" : "");
printf("<option value=%d %s>Soft states\n", GRAPH_SOFT_STATETYPES, (graph_statetypes == GRAPH_SOFT_STATETYPES) ? "SELECTED" : "");
printf("<option value=%d %s>Hard and soft states\n", GRAPH_ALL_STATETYPES, (graph_statetypes == GRAPH_ALL_STATETYPES) ? "SELECTED" : "");
printf("</select>\n");
printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
printf("<input type='submit' value='Update'>\n");
printf("</td></tr>\n");
}
/* display context-sensitive help */
printf("<tr><td></td><td align=right valign=bottom>\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("</td></tr>\n");
printf("</table>\n");
printf("</form>\n");
printf("</td>\n");
/* end of top table */
printf("</tr>\n");
printf("</table>\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, &current_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, &current_authdata) == FALSE)
is_authorized = FALSE;
}
if(is_authorized == FALSE) {
if(mode == CREATE_HTML)
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");
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("<BR><BR>\n");
printf("<DIV ALIGN=CENTER>\n");
printf("<IMG SRC='%s?createimage&t1=%lu&t2=%lu", HISTOGRAM_CGI, (unsigned long)t1, (unsigned long)t2);
printf("&host=%s", url_encode(host_name));
if(display_type == DISPLAY_SERVICE_HISTOGRAM)
printf("&service=%s", url_encode(svc_description));
printf("&breakdown=");
if(breakdown_type == BREAKDOWN_MONTHLY)
printf("monthly");
else if(breakdown_type == BREAKDOWN_DAY_OF_MONTH)
printf("dayofmonth");
else if(breakdown_type == BREAKDOWN_DAY_OF_WEEK)
printf("dayofweek");
else
printf("hourly");
printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
printf("&initialstateslogged=%s", (initial_states_logged == TRUE) ? "yes" : "no");
printf("&newstatesonly=%s", (new_states_only == TRUE) ? "yes" : "no");
printf("&graphevents=%d", graph_events);
printf("&graphstatetypes=%d", graph_statetypes);
printf("' BORDER=0 name='histogramimage'>\n");
printf("</DIV>\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("<P><DIV ALIGN=CENTER>\n");
printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Host</DIV>\n");
printf("</DIV></P>\n");
printf("<P><DIV ALIGN=CENTER>\n");
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
printf("<input type='hidden' name='input' value='getoptions'>\n");
printf("<TABLE BORDER=0 cellspacing=0 cellpadding=10>\n");
printf("<tr><td class='reportSelectSubTitle' valign=center>Host:</td>\n");
printf("<td class='reportSelectItem' valign=center>\n");
printf("<select name='host'>\n");
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_authorized_for_host(temp_host, &current_authdata) == TRUE)
printf("<option value='%s'>%s\n", escape_string(temp_host->name), temp_host->name);
}
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td></td><td class='reportSelectItem'>\n");
printf("<input type='submit' value='Continue to Step 3'>\n");
printf("</td></tr>\n");
printf("</TABLE>\n");
printf("</form>\n");
printf("</DIV></P>\n");
}
/* ask the user for what service they want a report for */
else if(input_type == GET_INPUT_SERVICE_TARGET) {
printf("<SCRIPT LANGUAGE='JavaScript'>\n");
printf("function gethostname(hostindex){\n");
printf("hostnames=[");
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
if(is_authorized_for_service(temp_service, &current_authdata) == TRUE) {
if(found == TRUE)
printf(",");
else
first_service = temp_service->host_name;
printf(" \"%s\"", temp_service->host_name);
found = TRUE;
}
}
printf(" ]\n");
printf("return hostnames[hostindex];\n");
printf("}\n");
printf("</SCRIPT>\n");
printf("<P><DIV ALIGN=CENTER>\n");
printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Service</DIV>\n");
printf("</DIV></P>\n");
printf("<P><DIV ALIGN=CENTER>\n");
printf("<form method=\"GET\" action=\"%s\" name=\"serviceform\">\n", HISTOGRAM_CGI);
printf("<input type='hidden' name='input' value='getoptions'>\n");
printf("<input type='hidden' name='host' value='%s'>\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service));
printf("<TABLE BORDER=0 cellpadding=5>\n");
printf("<tr><td class='reportSelectSubTitle'>Service:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='service' onFocus='document.serviceform.host.value=gethostname(this.selectedIndex);' onChange='document.serviceform.host.value=gethostname(this.selectedIndex);'>\n");
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
if(is_authorized_for_service(temp_service, &current_authdata) == TRUE)
printf("<option value='%s'>%s;%s\n", escape_string(temp_service->description), temp_service->host_name, temp_service->description);
}
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td></td><td class='reportSelectItem'>\n");
printf("<input type='submit' value='Continue to Step 3'>\n");
printf("</td></tr>\n");
printf("</TABLE>\n");
printf("</form>\n");
printf("</DIV></P>\n");
}
/* ask the user for report range and options */
else if(input_type == GET_INPUT_OPTIONS) {
time(&current_time);
t = localtime(&current_time);
start_day = 1;
start_year = t->tm_year + 1900;
end_day = t->tm_mday;
end_year = t->tm_year + 1900;
printf("<P><DIV ALIGN=CENTER>\n");
printf("<DIV CLASS='reportSelectTitle'>Step 3: Select Report Options</DIV>\n");
printf("</DIV></P>\n");
printf("<P><DIV ALIGN=CENTER>\n");
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
if(display_type == DISPLAY_SERVICE_HISTOGRAM)
printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
printf("<TABLE BORDER=0 cellpadding=5>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>Report Period:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='timeperiod'>\n");
printf("<option value=today>Today\n");
printf("<option value=last24hours>Last 24 Hours\n");
printf("<option value=yesterday>Yesterday\n");
printf("<option value=thisweek>This Week\n");
printf("<option value=last7days SELECTED>Last 7 Days\n");
printf("<option value=lastweek>Last Week\n");
printf("<option value=thismonth>This Month\n");
printf("<option value=last31days>Last 31 Days\n");
printf("<option value=lastmonth>Last Month\n");
printf("<option value=thisyear>This Year\n");
printf("<option value=lastyear>Last Year\n");
printf("<option value=custom>* CUSTOM REPORT PERIOD *\n");
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td valign=top class='reportSelectSubTitle'>If Custom Report Period...</td></tr>\n");
printf("<tr>");
printf("<td valign=top class='reportSelectSubTitle'>Start Date (Inclusive):</td>\n");
printf("<td align=left valign=top class='reportSelectItem'>");
printf("<select name='smon'>\n");
printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
printf("</select>\n ");
printf("<input type='text' size='2' maxlength='2' name='sday' value='%d'> ", start_day);
printf("<input type='text' size='4' maxlength='4' name='syear' value='%d'>", start_year);
printf("<input type='hidden' name='shour' value='0'>\n");
printf("<input type='hidden' name='smin' value='0'>\n");
printf("<input type='hidden' name='ssec' value='0'>\n");
printf("</td>\n");
printf("</tr>\n");
printf("<tr>");
printf("<td valign=top class='reportSelectSubTitle'>End Date (Inclusive):</td>\n");
printf("<td align=left valign=top class='reportSelectItem'>");
printf("<select name='emon'>\n");
printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
printf("</select>\n ");
printf("<input type='text' size='2' maxlength='2' name='eday' value='%d'> ", end_day);
printf("<input type='text' size='4' maxlength='4' name='eyear' value='%d'>", end_year);
printf("<input type='hidden' name='ehour' value='24'>\n");
printf("<input type='hidden' name='emin' value='0'>\n");
printf("<input type='hidden' name='esec' value='0'>\n");
printf("</td>\n");
printf("</tr>\n");
printf("<tr><td colspan=2><br></td></tr>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>Statistics Breakdown:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='breakdown'>\n");
printf("<option value=monthly>Month\n");
printf("<option value=dayofmonth SELECTED>Day of the Month\n");
printf("<option value=dayofweek>Day of the Week\n");
printf("<option value=hourly>Hour of the Day\n");
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>Events To Graph:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='graphevents'>\n");
if(display_type == DISPLAY_HOST_HISTOGRAM) {
printf("<option value=%d %s>All host events\n", GRAPH_HOST_ALL, (graph_events == GRAPH_HOST_ALL) ? "SELECTED" : "");
printf("<option value=%d %s>Host problem events\n", GRAPH_HOST_PROBLEMS, (graph_events == GRAPH_HOST_PROBLEMS) ? "SELECTED" : "");
printf("<option value=%d %s>Host up events\n", GRAPH_HOST_UP, (graph_events == GRAPH_HOST_UP) ? "SELECTED" : "");
printf("<option value=%d %s>Host down events\n", GRAPH_HOST_DOWN, (graph_events == GRAPH_HOST_DOWN) ? "SELECTED" : "");
printf("<option value=%d %s>Host unreachable events\n", GRAPH_HOST_UNREACHABLE, (graph_events == GRAPH_HOST_UNREACHABLE) ? "SELECTED" : "");
}
else {
printf("<option value=%d %s>All service events\n", GRAPH_SERVICE_ALL, (graph_events == GRAPH_SERVICE_ALL) ? "SELECTED" : "");
printf("<option value=%d %s>Service problem events\n", GRAPH_SERVICE_PROBLEMS, (graph_events == GRAPH_SERVICE_PROBLEMS) ? "SELECTED" : "");
printf("<option value=%d %s>Service ok events\n", GRAPH_SERVICE_OK, (graph_events == GRAPH_SERVICE_OK) ? "SELECTED" : "");
printf("<option value=%d %s>Service warning events\n", GRAPH_SERVICE_WARNING, (graph_events == GRAPH_SERVICE_WARNING) ? "SELECTED" : "");
printf("<option value=%d %s>Service unknown events\n", GRAPH_SERVICE_UNKNOWN, (graph_events == GRAPH_SERVICE_UNKNOWN) ? "SELECTED" : "");
printf("<option value=%d %s>Service critical events\n", GRAPH_SERVICE_CRITICAL, (graph_events == GRAPH_SERVICE_CRITICAL) ? "SELECTED" : "");
}
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>State Types To Graph:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='graphstatetypes'>\n");
printf("<option value=%d>Hard states\n", GRAPH_HARD_STATETYPES);
printf("<option value=%d>Soft states\n", GRAPH_SOFT_STATETYPES);
printf("<option value=%d SELECTED>Hard and soft states\n", GRAPH_ALL_STATETYPES);
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>Assume State Retention:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='assumestateretention'>\n");
printf("<option value='yes'>Yes\n");
printf("<option value='no'>No\n");
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>Initial States Logged:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='initialstateslogged'>\n");
printf("<option value='yes'>Yes\n");
printf("<option value='no' SELECTED>No\n");
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>Ignore Repeated States:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='newstatesonly'>\n");
printf("<option value='yes'>Yes\n");
printf("<option value='no' SELECTED>No\n");
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td></td><td class='reportSelectItem'><input type='submit' value='Create Report'></td></tr>\n");
printf("</TABLE>\n");
printf("</form>\n");
printf("</DIV></P>\n");
}
/* as the user whether they want a graph for a host or service */
else {
printf("<P><DIV ALIGN=CENTER>\n");
printf("<DIV CLASS='reportSelectTitle'>Step 1: Select Report Type</DIV>\n");
printf("</DIV></P>\n");
printf("<P><DIV ALIGN=CENTER>\n");
printf("<form method=\"GET\" action=\"%s\">\n", HISTOGRAM_CGI);
printf("<TABLE BORDER=0 cellpadding=5>\n");
printf("<tr><td class='reportSelectSubTitle' align=right>Type:</td>\n");
printf("<td class='reportSelectItem'>\n");
printf("<select name='input'>\n");
printf("<option value=gethost>Host\n");
printf("<option value=getservice>Service\n");
printf("</select>\n");
printf("</td></tr>\n");
printf("<tr><td></td><td class='reportSelectItem'>\n");
printf("<input type='submit' value='Continue to Step 2'>\n");
printf("</td></tr>\n");
printf("</TABLE>\n");
printf("</form>\n");
printf("</DIV></P>\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(&current_time);
get_time_string(&current_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\r\n\r\n");
if(embedded == TRUE)
return;
printf("<html>\n");
printf("<head>\n");
printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
printf("<title>\n");
printf("Nagios Histogram\n");
printf("</title>\n");
if(use_stylesheet == TRUE) {
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, HISTOGRAM_CSS);
}
printf("</head>\n");
printf("<BODY CLASS='histogram'>\n");
/* include user SSI header */
include_ssi_files(HISTOGRAM_CGI, SSI_HEADER);
printf("<div id=\"popup\" style=\"position:absolute; z-index:1; visibility: hidden\"></div>\n");
}
else {
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(&current_time);
get_time_string(&current_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 */
include_ssi_files(HISTOGRAM_CGI, SSI_FOOTER);
printf("</body>\n");
printf("</html>\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) {
x++;
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(&current_time);
t = localtime(&current_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(&current_time);
st = localtime(&current_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(&current_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;
}