1 /**************************************************************************
2 *
3 * TRENDS.C - Nagios State Trends CGI
4 *
5 *
6 * License:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *************************************************************************/
21
22 #include "../include/config.h"
23 #include "../include/common.h"
24 #include "../include/objects.h"
25 #include "../include/comments.h"
26 #include "../include/statusdata.h"
27
28 #include "../include/cgiutils.h"
29 #include "../include/getcgi.h"
30 #include "../include/cgiauth.h"
31
32 #include <gd.h> /* Boutell's GD library function */
33 #include <gdfonts.h> /* GD library small font definition */
34
35
36 /*#define DEBUG 1*/
37
38
39 extern char main_config_file[MAX_FILENAME_LENGTH];
40 extern char url_html_path[MAX_FILENAME_LENGTH];
41 extern char url_images_path[MAX_FILENAME_LENGTH];
42 extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
43 extern char physical_images_path[MAX_FILENAME_LENGTH];
44 extern char *status_file;
45
46 extern int log_rotation_method;
47
48 /* archived state types */
49 #define AS_CURRENT_STATE -1 /* special case for initial assumed state */
50 #define AS_NO_DATA 0
51 #define AS_PROGRAM_END 1
52 #define AS_PROGRAM_START 2
53 #define AS_HOST_UP 3
54 #define AS_HOST_DOWN 4
55 #define AS_HOST_UNREACHABLE 5
56 #define AS_SVC_OK 6
57 #define AS_SVC_UNKNOWN 7
58 #define AS_SVC_WARNING 8
59 #define AS_SVC_CRITICAL 9
60
61 #define AS_SOFT_STATE 1
62 #define AS_HARD_STATE 2
63
64 /* display types */
65 #define DISPLAY_HOST_TRENDS 0
66 #define DISPLAY_SERVICE_TRENDS 1
67 #define DISPLAY_NO_TRENDS 2
68
69 /* input types */
70 #define GET_INPUT_NONE 0
71 #define GET_INPUT_TARGET_TYPE 1
72 #define GET_INPUT_HOST_TARGET 2
73 #define GET_INPUT_SERVICE_TARGET 3
74 #define GET_INPUT_OPTIONS 4
75
76 /* modes */
77 #define CREATE_HTML 0
78 #define CREATE_IMAGE 1
79
80 /* standard report times */
81 #define TIMEPERIOD_CUSTOM 0
82 #define TIMEPERIOD_TODAY 1
83 #define TIMEPERIOD_YESTERDAY 2
84 #define TIMEPERIOD_THISWEEK 3
85 #define TIMEPERIOD_LASTWEEK 4
86 #define TIMEPERIOD_THISMONTH 5
87 #define TIMEPERIOD_LASTMONTH 6
88 #define TIMEPERIOD_THISQUARTER 7
89 #define TIMEPERIOD_LASTQUARTER 8
90 #define TIMEPERIOD_THISYEAR 9
91 #define TIMEPERIOD_LASTYEAR 10
92 #define TIMEPERIOD_LAST24HOURS 11
93 #define TIMEPERIOD_LAST7DAYS 12
94 #define TIMEPERIOD_LAST31DAYS 13
95 #define TIMEPERIOD_NEXTPROBLEM 14
96
97 #define MIN_TIMESTAMP_SPACING 10
98
99 #define MAX_ARCHIVE_SPREAD 65
100 #define MAX_ARCHIVE 65
101 #define MAX_ARCHIVE_BACKTRACKS 60
102
103 authdata current_authdata;
104
105 typedef struct archived_state_struct {
106 time_t time_stamp;
107 int entry_type;
108 int processed_state;
109 int state_type;
110 char *state_info;
111 struct archived_state_struct *next;
112 } archived_state;
113
114
115 archived_state *as_list = NULL;
116
117 time_t t1;
118 time_t t2;
119
120 int start_second = 0;
121 int start_minute = 0;
122 int start_hour = 0;
123 int start_day = 1;
124 int start_month = 1;
125 int start_year = 2000;
126 int end_second = 0;
127 int end_minute = 0;
128 int end_hour = 24;
129 int end_day = 1;
130 int end_month = 1;
131 int end_year = 2000;
132
133 int display_type = DISPLAY_NO_TRENDS;
134 int mode = CREATE_HTML;
135 int input_type = GET_INPUT_NONE;
136 int timeperiod_type = TIMEPERIOD_LAST24HOURS;
137 int compute_time_from_parts = FALSE;
138
139 int display_popups = TRUE;
140 int use_map = TRUE;
141 int small_image = FALSE;
142 int embedded = FALSE;
143 int display_header = TRUE;
144
145 int assume_initial_states = TRUE;
146 int assume_state_retention = TRUE;
147 int assume_states_during_notrunning = TRUE;
148 int include_soft_states = FALSE;
149
150 char *host_name = "";
151 char *svc_description = "";
152
153
154
155 void graph_all_trend_data(void);
156 void graph_trend_data(int, int, time_t, time_t, time_t, char *);
157 void draw_timestamps(void);
158 void draw_timestamp(int, time_t);
159 void draw_time_breakdowns(void);
160 void draw_horizontal_grid_lines(void);
161 void draw_dashed_line(int, int, int, int, int);
162
163 int convert_host_state_to_archived_state(int);
164 int convert_service_state_to_archived_state(int);
165 void add_archived_state(int, int, time_t, char *);
166 void free_archived_state_list(void);
167 void read_archived_state_data(void);
168 void scan_log_file_for_archived_state_data(char *);
169 void convert_timeperiod_to_times(int);
170 void compute_report_times(void);
171 void get_time_breakdown_string(unsigned long, unsigned long, char *, char *buffer, int);
172
173 void document_header(int);
174 void document_footer(void);
175 int process_cgivars(void);
176 void write_popup_code(void);
177
178 gdImagePtr trends_image = 0;
179 int color_white = 0;
180 int color_black = 0;
181 int color_red = 0;
182 int color_darkred = 0;
183 int color_green = 0;
184 int color_darkgreen = 0;
185 int color_yellow = 0;
186 int color_orange = 0;
187 FILE *image_file = NULL;
188
189 int image_width = 900;
190 int image_height = 300;
191
192 #define HOST_DRAWING_WIDTH 498
193 #define HOST_DRAWING_HEIGHT 70
194 #define HOST_DRAWING_X_OFFSET 116
195 #define HOST_DRAWING_Y_OFFSET 55
196
197 #define SVC_DRAWING_WIDTH 498
198 #define SVC_DRAWING_HEIGHT 90
199 #define SVC_DRAWING_X_OFFSET 116
200 #define SVC_DRAWING_Y_OFFSET 55
201
202 #define SMALL_HOST_DRAWING_WIDTH 500
203 #define SMALL_HOST_DRAWING_HEIGHT 20
204 #define SMALL_HOST_DRAWING_X_OFFSET 0
205 #define SMALL_HOST_DRAWING_Y_OFFSET 0
206
207 #define SMALL_SVC_DRAWING_WIDTH 500
208 #define SMALL_SVC_DRAWING_HEIGHT 20
209 #define SMALL_SVC_DRAWING_X_OFFSET 0
210 #define SMALL_SVC_DRAWING_Y_OFFSET 0
211
212 int drawing_width = 0;
213 int drawing_height = 0;
214
215 int drawing_x_offset = 0;
216 int drawing_y_offset = 0;
217
218 int last_known_state = AS_NO_DATA;
219
220 int zoom_factor = 4;
221 int backtrack_archives = 2;
222 int earliest_archive = 0;
223 time_t earliest_time;
224 time_t latest_time;
225 int earliest_state = AS_NO_DATA;
226 int latest_state = AS_NO_DATA;
227
228 int initial_assumed_host_state = AS_NO_DATA;
229 int initial_assumed_service_state = AS_NO_DATA;
230
231 unsigned long time_up = 0L;
232 unsigned long time_down = 0L;
233 unsigned long time_unreachable = 0L;
234 unsigned long time_ok = 0L;
235 unsigned long time_warning = 0L;
236 unsigned long time_unknown = 0L;
237 unsigned long time_critical = 0L;
238
239 int problem_found;
240
241
242
main(int argc,char ** argv)243 int main(int argc, char **argv) {
244 int result = OK;
245 char temp_buffer[MAX_INPUT_BUFFER];
246 char image_template[MAX_INPUT_BUFFER];
247 char start_time[MAX_INPUT_BUFFER];
248 char end_time[MAX_INPUT_BUFFER];
249 int string_width;
250 int string_height;
251 char start_timestring[MAX_INPUT_BUFFER];
252 char end_timestring[MAX_INPUT_BUFFER];
253 host *temp_host;
254 service *temp_service;
255 int is_authorized = TRUE;
256 int found = FALSE;
257 int days, hours, minutes, seconds;
258 char *first_service = NULL;
259 time_t t3;
260 time_t current_time;
261 struct tm *t;
262
263
264 /* reset internal CGI variables */
265 reset_cgi_vars();
266
267 /* Initialize shared configuration variables */
268 init_shared_cfg_vars(1);
269
270 /* read the CGI configuration file */
271 result = read_cgi_config_file(get_cgi_config_location(), NULL);
272 if(result == ERROR) {
273 if(mode == CREATE_HTML) {
274 document_header(FALSE);
275 cgi_config_file_error(get_cgi_config_location());
276 document_footer();
277 }
278 return ERROR;
279 }
280
281 /* read the main configuration file */
282 result = read_main_config_file(main_config_file);
283 if(result == ERROR) {
284 if(mode == CREATE_HTML) {
285 document_header(FALSE);
286 main_config_file_error(main_config_file);
287 document_footer();
288 }
289 return ERROR;
290 }
291
292
293 /* initialize time period to last 24 hours */
294 time(¤t_time);
295 t2 = current_time;
296 t1 = (time_t)(current_time - (60 * 60 * 24));
297
298 /* default number of backtracked archives */
299 switch(log_rotation_method) {
300 case LOG_ROTATION_MONTHLY:
301 backtrack_archives = 1;
302 break;
303 case LOG_ROTATION_WEEKLY:
304 backtrack_archives = 2;
305 break;
306 case LOG_ROTATION_DAILY:
307 backtrack_archives = 4;
308 break;
309 case LOG_ROTATION_HOURLY:
310 backtrack_archives = 8;
311 break;
312 default:
313 backtrack_archives = 2;
314 break;
315 }
316
317 /* get the arguments passed in the URL */
318 process_cgivars();
319
320 /* get authentication information */
321 get_authentication_information(¤t_authdata);
322
323 result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
324 if(result == ERROR) {
325 if(mode == CREATE_HTML) {
326 document_header(FALSE);
327 object_data_error();
328 document_footer();
329 }
330 return ERROR;
331 }
332
333 /* read all status data */
334 result = read_all_status_data(status_file, READ_ALL_STATUS_DATA);
335 if(result == ERROR) {
336 if(mode == CREATE_HTML) {
337 document_header(FALSE);
338 status_data_error();
339 document_footer();
340 }
341 return ERROR;
342 }
343
344 document_header(TRUE);
345
346 if(compute_time_from_parts == TRUE)
347 compute_report_times();
348
349 /* make sure times are sane, otherwise swap them */
350 if(t2 < t1) {
351 t3 = t2;
352 t2 = t1;
353 t1 = t3;
354 }
355
356 /* don't let user create reports in the future */
357 if(t2 > current_time) {
358 t2 = current_time;
359 if(t1 > t2)
360 t1 = t2 - (60 * 60 * 24);
361 }
362
363 if(mode == CREATE_HTML && display_header == TRUE) {
364 time_t old_t1 = t1, old_t2 = t2;
365
366 /* begin top table */
367 printf("<table border=0 width=100%% cellspacing=0 cellpadding=0>\n");
368 printf("<tr>\n");
369
370 /* left column of the first row */
371 printf("<td align=left valign=top width=33%%>\n");
372
373 if(display_type == DISPLAY_HOST_TRENDS)
374 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host State Trends");
375 else if(display_type == DISPLAY_SERVICE_TRENDS)
376 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service State Trends");
377 else
378 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host and Service State Trends");
379 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
380 display_info_table(temp_buffer, FALSE, ¤t_authdata);
381
382 if(timeperiod_type == TIMEPERIOD_NEXTPROBLEM) {
383 archived_state *temp_as;
384 time_t problem_t1, problem_t2 = 0;
385
386 t1 = t2;
387 t2 = current_time;
388 read_archived_state_data();
389
390 problem_found = FALSE;
391 if(display_type == DISPLAY_HOST_TRENDS) {
392 for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
393 if((temp_as->entry_type == SD_HOST_DOWN || temp_as->entry_type == SD_HOST_UNREACHABLE) && temp_as->time_stamp > t1) {
394 problem_t1 = temp_as->time_stamp;
395 problem_found = TRUE;
396 break;
397 }
398 }
399 if(problem_found == TRUE) {
400 for(; temp_as != NULL; temp_as = temp_as->next) {
401 if(temp_as->entry_type == AS_HOST_UP && temp_as->time_stamp > problem_t1) {
402 problem_t2 = temp_as->time_stamp;
403 break;
404 }
405 }
406 }
407 }
408 else {
409 for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
410 if((temp_as->entry_type == AS_SVC_UNKNOWN || temp_as->entry_type == AS_SVC_CRITICAL || temp_as->entry_type == AS_SVC_WARNING) && temp_as->time_stamp > t1) {
411 problem_t1 = temp_as->time_stamp;
412 problem_found = TRUE;
413 break;
414 }
415 }
416 if(problem_found == TRUE) {
417 for(; temp_as != NULL; temp_as = temp_as->next) {
418 if(temp_as->entry_type == AS_SVC_OK && temp_as->time_stamp > problem_t1) {
419 problem_t2 = temp_as->time_stamp;
420 break;
421 }
422 }
423 }
424 }
425 if(problem_found == TRUE) {
426 time_t margin;
427
428 if(problem_t2 == 0) {
429 margin = 12 * 60 * 60;
430 problem_t2 = problem_t1;
431 }
432 else
433 margin = (problem_t2 - problem_t1) / 2;
434
435 t1 = problem_t1 - margin;
436 t2 = problem_t2 + margin;
437 }
438 }
439
440 if(timeperiod_type == TIMEPERIOD_NEXTPROBLEM && problem_found == FALSE) {
441 t1 = old_t1;
442 t2 = old_t2;
443 }
444
445 if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
446
447 printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
448 printf("<TR><TD CLASS='linkBox'>\n");
449
450 if(display_type == DISPLAY_HOST_TRENDS) {
451 printf("<a href='%s?host=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedhoststate=%d&backtrack=%d&show_log_entries'>View Availability Report For This Host</a><BR>\n", AVAIL_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives);
452 #ifdef USE_HISTOGRAM
453 printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Alert Histogram For This Host</a><BR>\n", HISTOGRAM_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
454 #endif
455 printf("<a href='%s?host=%s'>View Status Detail For This Host</a><BR>\n", STATUS_CGI, url_encode(host_name));
456 printf("<a href='%s?host=%s'>View Alert History For This Host</a><BR>\n", HISTORY_CGI, url_encode(host_name));
457 printf("<a href='%s?host=%s'>View Notifications For This Host</a><BR>\n", NOTIFICATIONS_CGI, url_encode(host_name));
458 }
459 else {
460 #ifdef LEGACY_GRAPHICAL_CGIS
461 printf("<a href='%s?host=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d'>View Trends For This Host</a><BR>\n", TRENDS_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
462 #else
463 printf("<a href='%s?host=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d'>View Trends For This Host</a><BR>\n", LEGACY_TRENDS_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
464 #endif
465 printf("<a href='%s?host=%s", AVAIL_CGI, url_encode(host_name));
466 printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s&includesoftstates=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d&show_log_entries'>View Availability Report For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
467 printf("<a href='%s?host=%s", HISTOGRAM_CGI, url_encode(host_name));
468 printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Alert Histogram For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
469 printf("<A HREF='%s?host=%s&", HISTORY_CGI, url_encode(host_name));
470 printf("service=%s'>View Alert History For This Service</A><BR>\n", url_encode(svc_description));
471 printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
472 printf("service=%s'>View Notifications For This Service</A><BR>\n", url_encode(svc_description));
473 }
474
475 printf("</TD></TR>\n");
476 printf("</TABLE>\n");
477 }
478
479 printf("</td>\n");
480
481 /* center column of top row */
482 printf("<td align=center valign=top width=33%%>\n");
483
484 if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
485
486 printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
487 if(display_type == DISPLAY_HOST_TRENDS)
488 printf("Host '%s'", host_name);
489 else if(display_type == DISPLAY_SERVICE_TRENDS)
490 printf("Service '%s' On Host '%s'", svc_description, host_name);
491 printf("</DIV>\n");
492
493 printf("<BR>\n");
494
495 printf("<IMG SRC='%s%s' BORDER=0 ALT='%s State Trends' TITLE='%s State Trends'>\n", url_images_path, TRENDS_ICON, (display_type == DISPLAY_HOST_TRENDS) ? "Host" : "Service", (display_type == DISPLAY_HOST_TRENDS) ? "Host" : "Service");
496
497 printf("<BR CLEAR=ALL>\n");
498
499 get_time_string(&t1, start_timestring, sizeof(start_timestring) - 1, SHORT_DATE_TIME);
500 get_time_string(&t2, end_timestring, sizeof(end_timestring) - 1, SHORT_DATE_TIME);
501 printf("<div align=center class='reportRange'>%s to %s</div>\n", start_timestring, end_timestring);
502
503 get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds);
504 printf("<div align=center class='reportDuration'>Duration: %dd %dh %dm %ds</div>\n", days, hours, minutes, seconds);
505 }
506
507 printf("</td>\n");
508
509 /* right hand column of top row */
510 printf("<td align=right valign=bottom width=33%%>\n");
511
512 #ifdef LEGACY_GRAPHICAL_CGIS
513 printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
514 #else
515 printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
516 #endif
517 printf("<table border=0 CLASS='optBox'>\n");
518
519 if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
520
521 printf("<tr><td CLASS='optBoxItem' valign=top align=left>First assumed %s state:</td><td CLASS='optBoxItem' valign=top align=left>Backtracked archives:</td></tr>\n", (display_type == DISPLAY_HOST_TRENDS) ? "host" : "service");
522 printf("<tr><td CLASS='optBoxItem' valign=top align=left>");
523 if(display_popups == FALSE)
524 printf("<input type='hidden' name='nopopups' value=''>\n");
525 if(use_map == FALSE)
526 printf("<input type='hidden' name='nomap' value=''>\n");
527 printf("<input type='hidden' name='t1' value='%lu'>\n", (unsigned long)t1);
528 printf("<input type='hidden' name='t2' value='%lu'>\n", (unsigned long)t2);
529 printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
530 if(display_type == DISPLAY_SERVICE_TRENDS)
531 printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
532
533 printf("<input type='hidden' name='assumeinitialstates' value='%s'>\n", (assume_initial_states == TRUE) ? "yes" : "no");
534 printf("<input type='hidden' name='assumestateretention' value='%s'>\n", (assume_state_retention == TRUE) ? "yes" : "no");
535 printf("<input type='hidden' name='assumestatesduringnotrunning' value='%s'>\n", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
536 printf("<input type='hidden' name='includesoftstates' value='%s'>\n", (include_soft_states == TRUE) ? "yes" : "no");
537
538 if(display_type == DISPLAY_HOST_TRENDS) {
539 printf("<input type='hidden' name='initialassumedservicestate' value='%d'>", initial_assumed_service_state);
540 printf("<select name='initialassumedhoststate'>\n");
541 printf("<option value=%d %s>Unspecified\n", AS_NO_DATA, (initial_assumed_host_state == AS_NO_DATA) ? "SELECTED" : "");
542 printf("<option value=%d %s>Current State\n", AS_CURRENT_STATE, (initial_assumed_host_state == AS_CURRENT_STATE) ? "SELECTED" : "");
543 printf("<option value=%d %s>Host Up\n", AS_HOST_UP, (initial_assumed_host_state == AS_HOST_UP) ? "SELECTED" : "");
544 printf("<option value=%d %s>Host Down\n", AS_HOST_DOWN, (initial_assumed_host_state == AS_HOST_DOWN) ? "SELECTED" : "");
545 printf("<option value=%d %s>Host Unreachable\n", AS_HOST_UNREACHABLE, (initial_assumed_host_state == AS_HOST_UNREACHABLE) ? "SELECTED" : "");
546 }
547 else {
548 printf("<input type='hidden' name='initialassumedhoststate' value='%d'>", initial_assumed_host_state);
549 printf("<select name='initialassumedservicestate'>\n");
550 printf("<option value=%d %s>Unspecified\n", AS_NO_DATA, (initial_assumed_service_state == AS_NO_DATA) ? "SELECTED" : "");
551 printf("<option value=%d %s>Current State\n", AS_CURRENT_STATE, (initial_assumed_service_state == AS_CURRENT_STATE) ? "SELECTED" : "");
552 printf("<option value=%d %s>Service Ok\n", AS_SVC_OK, (initial_assumed_service_state == AS_SVC_OK) ? "SELECTED" : "");
553 printf("<option value=%d %s>Service Warning\n", AS_SVC_WARNING, (initial_assumed_service_state == AS_SVC_WARNING) ? "SELECTED" : "");
554 printf("<option value=%d %s>Service Unknown\n", AS_SVC_UNKNOWN, (initial_assumed_service_state == AS_SVC_UNKNOWN) ? "SELECTED" : "");
555 printf("<option value=%d %s>Service Critical\n", AS_SVC_CRITICAL, (initial_assumed_service_state == AS_SVC_CRITICAL) ? "SELECTED" : "");
556 }
557 printf("</select>\n");
558 printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
559 printf("<input type='text' name='backtrack' size='2' maxlength='2' value='%d'>\n", backtrack_archives);
560 printf("</td></tr>\n");
561
562 printf("<tr><td CLASS='optBoxItem' valign=top align=left>Report period:</td><td CLASS='optBoxItem' valign=top align=left>Zoom factor:</td></tr>\n");
563 printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
564 printf("<select name='timeperiod'>\n");
565 printf("<option>[ Current time range ]\n");
566 printf("<option value=today %s>Today\n", (timeperiod_type == TIMEPERIOD_TODAY) ? "SELECTED" : "");
567 printf("<option value=last24hours %s>Last 24 Hours\n", (timeperiod_type == TIMEPERIOD_LAST24HOURS) ? "SELECTED" : "");
568 printf("<option value=yesterday %s>Yesterday\n", (timeperiod_type == TIMEPERIOD_YESTERDAY) ? "SELECTED" : "");
569 printf("<option value=thisweek %s>This Week\n", (timeperiod_type == TIMEPERIOD_THISWEEK) ? "SELECTED" : "");
570 printf("<option value=last7days %s>Last 7 Days\n", (timeperiod_type == TIMEPERIOD_LAST7DAYS) ? "SELECTED" : "");
571 printf("<option value=lastweek %s>Last Week\n", (timeperiod_type == TIMEPERIOD_LASTWEEK) ? "SELECTED" : "");
572 printf("<option value=thismonth %s>This Month\n", (timeperiod_type == TIMEPERIOD_THISMONTH) ? "SELECTED" : "");
573 printf("<option value=last31days %s>Last 31 Days\n", (timeperiod_type == TIMEPERIOD_LAST31DAYS) ? "SELECTED" : "");
574 printf("<option value=lastmonth %s>Last Month\n", (timeperiod_type == TIMEPERIOD_LASTMONTH) ? "SELECTED" : "");
575 printf("<option value=thisyear %s>This Year\n", (timeperiod_type == TIMEPERIOD_THISYEAR) ? "SELECTED" : "");
576 printf("<option value=lastyear %s>Last Year\n", (timeperiod_type == TIMEPERIOD_LASTYEAR) ? "SELECTED" : "");
577 if(display_type == DISPLAY_HOST_TRENDS)
578 printf("<option value=nextproblem %s>Next Host Problem\n", (timeperiod_type == TIMEPERIOD_NEXTPROBLEM) ? "SELECTED" : "");
579 else
580 printf("<option value=nextproblem %s>Next Service Problem\n", (timeperiod_type == TIMEPERIOD_NEXTPROBLEM) ? "SELECTED" : "");
581 printf("</select>\n");
582 printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
583 printf("<select name='zoom'>\n");
584 printf("<option value=%d selected>%d\n", zoom_factor, zoom_factor);
585 printf("<option value=+2>+2\n");
586 printf("<option value=+3>+3\n");
587 printf("<option value=+4>+4\n");
588 printf("<option value=-2>-2\n");
589 printf("<option value=-3>-3\n");
590 printf("<option value=-4>-4\n");
591 printf("</select>\n");
592 printf("</td></tr>\n");
593
594 printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
595 printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
596 printf("<input type='submit' value='Update'>\n");
597 printf("</td></tr>\n");
598 }
599
600 /* display context-sensitive help */
601 printf("<tr><td></td><td align=right valign=bottom>\n");
602 if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
603 if(display_type == DISPLAY_HOST_TRENDS)
604 display_context_help(CONTEXTHELP_TRENDS_HOST);
605 else
606 display_context_help(CONTEXTHELP_TRENDS_SERVICE);
607 }
608 else if(display_type == DISPLAY_NO_TRENDS || input_type != GET_INPUT_NONE) {
609 if(input_type == GET_INPUT_NONE)
610 display_context_help(CONTEXTHELP_TRENDS_MENU1);
611 else if(input_type == GET_INPUT_TARGET_TYPE)
612 display_context_help(CONTEXTHELP_TRENDS_MENU1);
613 else if(input_type == GET_INPUT_HOST_TARGET)
614 display_context_help(CONTEXTHELP_TRENDS_MENU2);
615 else if(input_type == GET_INPUT_SERVICE_TARGET)
616 display_context_help(CONTEXTHELP_TRENDS_MENU3);
617 else if(input_type == GET_INPUT_OPTIONS)
618 display_context_help(CONTEXTHELP_TRENDS_MENU4);
619 }
620 printf("</td></tr>\n");
621
622 printf("</table>\n");
623 printf("</form>\n");
624
625 printf("</td>\n");
626
627 /* end of top table */
628 printf("</tr>\n");
629 printf("</table>\n");
630 }
631
632
633 #ifndef DEBUG
634
635 /* check authorization... */
636 if(display_type == DISPLAY_HOST_TRENDS) {
637 temp_host = find_host(host_name);
638 if(temp_host == NULL || is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
639 is_authorized = FALSE;
640 }
641 else if(display_type == DISPLAY_SERVICE_TRENDS) {
642 temp_service = find_service(host_name, svc_description);
643 if(temp_service == NULL || is_authorized_for_service(temp_service, ¤t_authdata) == FALSE)
644 is_authorized = FALSE;
645 }
646 if(is_authorized == FALSE) {
647
648 if(mode == CREATE_HTML)
649 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_TRENDS) ? "host" : "service");
650
651 document_footer();
652 free_memory();
653 return ERROR;
654 }
655 #endif
656
657
658 if(timeperiod_type == TIMEPERIOD_NEXTPROBLEM && problem_found == FALSE) {
659 printf("<P><DIV ALIGN=CENTER CLASS='errorMessage'>No problem found between end of display and end of recording</DIV></P>\n");
660
661 document_footer();
662 free_memory();
663 return ERROR;
664 }
665 /* set drawing parameters, etc */
666
667 if(small_image == TRUE) {
668 image_height = 20;
669 image_width = 500;
670 }
671 else {
672 image_height = 300;
673 image_width = 900;
674 }
675
676 if(display_type == DISPLAY_HOST_TRENDS) {
677
678 if(small_image == TRUE) {
679 drawing_width = SMALL_HOST_DRAWING_WIDTH;
680 drawing_height = SMALL_HOST_DRAWING_HEIGHT;
681 drawing_x_offset = SMALL_HOST_DRAWING_X_OFFSET;
682 drawing_y_offset = SMALL_HOST_DRAWING_Y_OFFSET;
683 }
684 else {
685 drawing_width = HOST_DRAWING_WIDTH;
686 drawing_height = HOST_DRAWING_HEIGHT;
687 drawing_x_offset = HOST_DRAWING_X_OFFSET;
688 drawing_y_offset = HOST_DRAWING_Y_OFFSET;
689 }
690 }
691 else if(display_type == DISPLAY_SERVICE_TRENDS) {
692
693 if(small_image == TRUE) {
694 drawing_width = SMALL_SVC_DRAWING_WIDTH;
695 drawing_height = SMALL_SVC_DRAWING_HEIGHT;
696 drawing_x_offset = SMALL_SVC_DRAWING_X_OFFSET;
697 drawing_y_offset = SMALL_SVC_DRAWING_Y_OFFSET;
698 }
699 else {
700 drawing_width = SVC_DRAWING_WIDTH;
701 drawing_height = SVC_DRAWING_HEIGHT;
702 drawing_x_offset = SVC_DRAWING_X_OFFSET;
703 drawing_y_offset = SVC_DRAWING_Y_OFFSET;
704 }
705 }
706
707 /* last known state should always be initially set to indeterminate! */
708 last_known_state = AS_NO_DATA;
709
710
711 /* initialize PNG image */
712 if(display_type != DISPLAY_NO_TRENDS && mode == CREATE_IMAGE) {
713
714 if(small_image == TRUE) {
715 trends_image = gdImageCreate(image_width, image_height);
716 if(trends_image == NULL) {
717 #ifdef DEBUG
718 printf("Error: Could not allocate memory for image\n");
719 #endif
720 return ERROR;
721 }
722 }
723
724 else {
725
726 if(display_type == DISPLAY_HOST_TRENDS)
727 snprintf(image_template, sizeof(image_template) - 1, "%s/trendshost.png", physical_images_path);
728 else
729 snprintf(image_template, sizeof(image_template) - 1, "%s/trendssvc.png", physical_images_path);
730 image_template[sizeof(image_template) - 1] = '\x0';
731
732 /* allocate buffer for storing image */
733 trends_image = NULL;
734 image_file = fopen(image_template, "r");
735 if(image_file != NULL) {
736 trends_image = gdImageCreateFromPng(image_file);
737 fclose(image_file);
738 }
739 if(trends_image == NULL)
740 trends_image = gdImageCreate(image_width, image_height);
741 if(trends_image == NULL) {
742 #ifdef DEBUG
743 printf("Error: Could not allocate memory for image\n");
744 #endif
745 return ERROR;
746 }
747 }
748
749 /* allocate colors used for drawing */
750 color_white = gdImageColorAllocate(trends_image, 255, 255, 255);
751 color_black = gdImageColorAllocate(trends_image, 0, 0, 0);
752 color_red = gdImageColorAllocate(trends_image, 255, 0, 0);
753 color_darkred = gdImageColorAllocate(trends_image, 128, 0, 0);
754 color_green = gdImageColorAllocate(trends_image, 0, 210, 0);
755 color_darkgreen = gdImageColorAllocate(trends_image, 0, 128, 0);
756 color_yellow = gdImageColorAllocate(trends_image, 176, 178, 20);
757 color_orange = gdImageColorAllocate(trends_image, 255, 100, 25);
758
759 /* set transparency index */
760 gdImageColorTransparent(trends_image, color_white);
761
762 /* make sure the graphic is interlaced */
763 gdImageInterlace(trends_image, 1);
764
765 if(small_image == FALSE) {
766
767 /* title */
768 snprintf(start_time, sizeof(start_time) - 1, "%s", ctime(&t1));
769 start_time[sizeof(start_time) - 1] = '\x0';
770 start_time[strlen(start_time) - 1] = '\x0';
771 snprintf(end_time, sizeof(end_time) - 1, "%s", ctime(&t2));
772 end_time[sizeof(end_time) - 1] = '\x0';
773 end_time[strlen(end_time) - 1] = '\x0';
774
775 string_height = gdFontSmall->h;
776
777 if(display_type == DISPLAY_HOST_TRENDS)
778 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "State History For Host '%s'", host_name);
779 else
780 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "State History For Service '%s' On Host '%s'", svc_description, host_name);
781 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
782 string_width = gdFontSmall->w * strlen(temp_buffer);
783 gdImageString(trends_image, gdFontSmall, (drawing_width / 2) - (string_width / 2) + drawing_x_offset, string_height, (unsigned char *)temp_buffer, color_black);
784
785 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s to %s", start_time, end_time);
786 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
787 string_width = gdFontSmall->w * strlen(temp_buffer);
788 gdImageString(trends_image, gdFontSmall, (drawing_width / 2) - (string_width / 2) + drawing_x_offset, (string_height * 2) + 5, (unsigned char *)temp_buffer, color_black);
789
790
791 /* first time stamp */
792 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", start_time);
793 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
794 string_width = gdFontSmall->w * strlen(temp_buffer);
795 gdImageStringUp(trends_image, gdFontSmall, drawing_x_offset - (string_height / 2), drawing_y_offset + drawing_height + string_width + 5, (unsigned char *)temp_buffer, color_black);
796 }
797 }
798
799 if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
800
801
802 if(mode == CREATE_IMAGE || (mode == CREATE_HTML && use_map == TRUE)) {
803
804 /* read in all necessary archived state data */
805 read_archived_state_data();
806
807 /* graph archived state trend data */
808 graph_all_trend_data();
809 }
810
811 /* print URL to image */
812 if(mode == CREATE_HTML) {
813
814 printf("<BR><BR>\n");
815 printf("<DIV ALIGN=CENTER>\n");
816 #ifdef LEGACY_GRAPHICAL_CGIS
817 printf("<IMG SRC='%s?createimage&t1=%lu&t2=%lu", TRENDS_CGI, (unsigned long)t1, (unsigned long)t2);
818 #else
819 printf("<IMG SRC='%s?createimage&t1=%lu&t2=%lu", LEGACY_TRENDS_CGI, (unsigned long)t1, (unsigned long)t2);
820 #endif
821 printf("&assumeinitialstates=%s", (assume_initial_states == TRUE) ? "yes" : "no");
822 printf("&assumestatesduringnotrunning=%s", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
823 printf("&initialassumedhoststate=%d", initial_assumed_host_state);
824 printf("&initialassumedservicestate=%d", initial_assumed_service_state);
825 printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
826 printf("&includesoftstates=%s", (include_soft_states == TRUE) ? "yes" : "no");
827 printf("&host=%s", url_encode(host_name));
828 if(display_type == DISPLAY_SERVICE_TRENDS)
829 printf("&service=%s", url_encode(svc_description));
830 if(backtrack_archives > 0)
831 printf("&backtrack=%d", backtrack_archives);
832 printf("&zoom=%d", zoom_factor);
833 printf("' BORDER=0 name='trendsimage' useMap='#trendsmap' width=%d>\n", image_width);
834 printf("</DIV>\n");
835 }
836
837 if(mode == CREATE_IMAGE || (mode == CREATE_HTML && use_map == TRUE)) {
838
839 /* draw timestamps */
840 draw_timestamps();
841
842 /* draw horizontal lines */
843 draw_horizontal_grid_lines();
844
845 /* draw state time breakdowns */
846 draw_time_breakdowns();
847 }
848
849 if(mode == CREATE_IMAGE) {
850
851 /* use STDOUT for writing the image data... */
852 image_file = stdout;
853
854 #ifndef DEBUG
855 /* write the image to file */
856 gdImagePng(trends_image, image_file);
857 #endif
858 #ifdef DEBUG
859 image_file = fopen("trends.png", "w");
860 if(image_file == NULL)
861 printf("Could not open trends.png for writing!\n");
862 else {
863 gdImagePng(trends_image, image_file);
864 fclose(image_file);
865 }
866 #endif
867
868 /* free memory allocated to image */
869 gdImageDestroy(trends_image);
870 }
871 }
872
873
874 /* show user a selection of hosts and services to choose from... */
875 if(display_type == DISPLAY_NO_TRENDS || input_type != GET_INPUT_NONE) {
876
877 /* ask the user for what host they want a report for */
878 if(input_type == GET_INPUT_HOST_TARGET) {
879
880 printf("<P><DIV ALIGN=CENTER>\n");
881 printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Host</DIV>\n");
882 printf("</DIV></P>\n");
883
884 printf("<P><DIV ALIGN=CENTER>\n");
885
886 #ifdef LEGACY_GRAPHICAL_CGIS
887 printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
888 #else
889 printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
890 #endif
891 printf("<input type='hidden' name='input' value='getoptions'>\n");
892 printf("<TABLE BORDER=0 cellspacing=0 cellpadding=10>\n");
893
894 printf("<tr><td class='reportSelectSubTitle' valign=center>Host:</td>\n");
895 printf("<td class='reportSelectItem' valign=center>\n");
896 printf("<select name='host'>\n");
897
898 for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
899 if(is_authorized_for_host(temp_host, ¤t_authdata) == TRUE)
900 printf("<option value='%s'>%s\n", escape_string(temp_host->name), temp_host->name);
901 }
902
903 printf("</select>\n");
904 printf("</td></tr>\n");
905
906 printf("<tr><td></td><td class='reportSelectItem'>\n");
907 printf("<input type='submit' value='Continue to Step 3'>\n");
908 printf("</td></tr>\n");
909
910 printf("</TABLE>\n");
911 printf("</form>\n");
912
913 printf("</DIV></P>\n");
914 }
915
916 /* ask the user for what service they want a report for */
917 else if(input_type == GET_INPUT_SERVICE_TARGET) {
918
919 printf("<SCRIPT LANGUAGE='JavaScript'>\n");
920 printf("function gethostname(hostindex){\n");
921 printf("hostnames=[");
922
923 for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
924 if(is_authorized_for_service(temp_service, ¤t_authdata) == TRUE) {
925 if(found == TRUE)
926 printf(",");
927 else
928 first_service = temp_service->host_name;
929 printf(" \"%s\"", temp_service->host_name);
930 found = TRUE;
931 }
932 }
933
934 printf(" ]\n");
935 printf("return hostnames[hostindex];\n");
936 printf("}\n");
937 printf("</SCRIPT>\n");
938
939
940 printf("<P><DIV ALIGN=CENTER>\n");
941 printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Service</DIV>\n");
942 printf("</DIV></P>\n");
943
944 printf("<P><DIV ALIGN=CENTER>\n");
945
946 #ifdef LEGACY_GRAPHICAL_CGIS
947 printf("<form method=\"GET\" action=\"%s\" name=\"serviceform\">\n", TRENDS_CGI);
948 #else
949 printf("<form method=\"GET\" action=\"%s\" name=\"serviceform\">\n", LEGACY_TRENDS_CGI);
950 #endif
951 printf("<input type='hidden' name='input' value='getoptions'>\n");
952 printf("<input type='hidden' name='host' value='%s'>\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service));
953 printf("<TABLE BORDER=0 cellpadding=5>\n");
954
955 printf("<tr><td class='reportSelectSubTitle'>Service:</td>\n");
956 printf("<td class='reportSelectItem'>\n");
957 printf("<select name='service' onFocus='document.serviceform.host.value=gethostname(this.selectedIndex);' onChange='document.serviceform.host.value=gethostname(this.selectedIndex);'>\n");
958
959 for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
960 if(is_authorized_for_service(temp_service, ¤t_authdata) == TRUE)
961 printf("<option value='%s'>%s;%s\n", escape_string(temp_service->description), temp_service->host_name, temp_service->description);
962 }
963
964 printf("</select>\n");
965 printf("</td></tr>\n");
966
967 printf("<tr><td></td><td class='reportSelectItem'>\n");
968 printf("<input type='submit' value='Continue to Step 3'>\n");
969 printf("</td></tr>\n");
970
971 printf("</TABLE>\n");
972 printf("</form>\n");
973
974 printf("</DIV></P>\n");
975 }
976
977 /* ask the user for report range and options */
978 else if(input_type == GET_INPUT_OPTIONS) {
979
980 time(¤t_time);
981 t = localtime(¤t_time);
982
983 start_day = 1;
984 start_year = t->tm_year + 1900;
985 end_day = t->tm_mday;
986 end_year = t->tm_year + 1900;
987
988 printf("<P><DIV ALIGN=CENTER>\n");
989 printf("<DIV CLASS='reportSelectTitle'>Step 3: Select Report Options</DIV>\n");
990 printf("</DIV></P>\n");
991
992 printf("<P><DIV ALIGN=CENTER>\n");
993
994 #ifdef LEGACY_GRAPHICAL_CGIS
995 printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
996 #else
997 printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
998 #endif
999 printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
1000 if(display_type == DISPLAY_SERVICE_TRENDS)
1001 printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
1002 printf("<TABLE BORDER=0 CELLPADDING=5>\n");
1003
1004 printf("<tr><td class='reportSelectSubTitle' align=right>Report period:</td>\n");
1005 printf("<td class='reportSelectItem'>\n");
1006 printf("<select name='timeperiod'>\n");
1007 printf("<option value=today>Today\n");
1008 printf("<option value=last24hours>Last 24 Hours\n");
1009 printf("<option value=yesterday>Yesterday\n");
1010 printf("<option value=thisweek>This Week\n");
1011 printf("<option value=last7days SELECTED>Last 7 Days\n");
1012 printf("<option value=lastweek>Last Week\n");
1013 printf("<option value=thismonth>This Month\n");
1014 printf("<option value=last31days>Last 31 Days\n");
1015 printf("<option value=lastmonth>Last Month\n");
1016 printf("<option value=thisyear>This Year\n");
1017 printf("<option value=lastyear>Last Year\n");
1018 printf("<option value=custom>* CUSTOM REPORT PERIOD *\n");
1019 printf("</select>\n");
1020 printf("</td></tr>\n");
1021
1022 printf("<tr><td valign=top class='reportSelectSubTitle'>If Custom Report Period...</td></tr>\n");
1023
1024 printf("<tr>");
1025 printf("<td valign=top class='reportSelectSubTitle'>Start Date (Inclusive):</td>\n");
1026 printf("<td align=left valign=top class='reportSelectItem'>");
1027 printf("<select name='smon'>\n");
1028 printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
1029 printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
1030 printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
1031 printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
1032 printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
1033 printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
1034 printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
1035 printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
1036 printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
1037 printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
1038 printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
1039 printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
1040 printf("</select>\n ");
1041 printf("<input type='text' size='2' maxlength='2' name='sday' value='%d'> ", start_day);
1042 printf("<input type='text' size='4' maxlength='4' name='syear' value='%d'>", start_year);
1043 printf("<input type='hidden' name='shour' value='0'>\n");
1044 printf("<input type='hidden' name='smin' value='0'>\n");
1045 printf("<input type='hidden' name='ssec' value='0'>\n");
1046 printf("</td>\n");
1047 printf("</tr>\n");
1048
1049 printf("<tr>");
1050 printf("<td valign=top class='reportSelectSubTitle'>End Date (Inclusive):</td>\n");
1051 printf("<td align=left valign=top class='reportSelectItem'>");
1052 printf("<select name='emon'>\n");
1053 printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
1054 printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
1055 printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
1056 printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
1057 printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
1058 printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
1059 printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
1060 printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
1061 printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
1062 printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
1063 printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
1064 printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
1065 printf("</select>\n ");
1066 printf("<input type='text' size='2' maxlength='2' name='eday' value='%d'> ", end_day);
1067 printf("<input type='text' size='4' maxlength='4' name='eyear' value='%d'>", end_year);
1068 printf("<input type='hidden' name='ehour' value='24'>\n");
1069 printf("<input type='hidden' name='emin' value='0'>\n");
1070 printf("<input type='hidden' name='esec' value='0'>\n");
1071 printf("</td>\n");
1072 printf("</tr>\n");
1073
1074 printf("<tr><td colspan=2><br></td></tr>\n");
1075
1076 printf("<tr><td class='reportSelectSubTitle' align=right>Assume Initial States:</td>\n");
1077 printf("<td class='reportSelectItem'>\n");
1078 printf("<select name='assumeinitialstates'>\n");
1079 printf("<option value=yes>Yes\n");
1080 printf("<option value=no>No\n");
1081 printf("</select>\n");
1082 printf("</td></tr>\n");
1083
1084 printf("<tr><td class='reportSelectSubTitle' align=right>Assume State Retention:</td>\n");
1085 printf("<td class='reportSelectItem'>\n");
1086 printf("<select name='assumestateretention'>\n");
1087 printf("<option value=yes>Yes\n");
1088 printf("<option value=no>No\n");
1089 printf("</select>\n");
1090 printf("</td></tr>\n");
1091
1092 printf("<tr><td class='reportSelectSubTitle' align=right>Assume States During Program Downtime:</td>\n");
1093 printf("<td class='reportSelectItem'>\n");
1094 printf("<select name='assumestatesduringnotrunning'>\n");
1095 printf("<option value=yes>Yes\n");
1096 printf("<option value=no>No\n");
1097 printf("</select>\n");
1098 printf("</td></tr>\n");
1099
1100 printf("<tr><td class='reportSelectSubTitle' align=right>Include Soft States:</td>\n");
1101 printf("<td class='reportSelectItem'>\n");
1102 printf("<select name='includesoftstates'>\n");
1103 printf("<option value=yes>Yes\n");
1104 printf("<option value=no SELECTED>No\n");
1105 printf("</select>\n");
1106 printf("</td></tr>\n");
1107
1108 printf("<tr><td class='reportSelectSubTitle' align=right>First Assumed %s State:</td>\n", (display_type == DISPLAY_HOST_TRENDS) ? "Host" : "Service");
1109 printf("<td class='reportSelectItem'>\n");
1110 if(display_type == DISPLAY_HOST_TRENDS) {
1111 printf("<select name='initialassumedhoststate'>\n");
1112 printf("<option value=%d>Unspecified\n", AS_NO_DATA);
1113 printf("<option value=%d>Current State\n", AS_CURRENT_STATE);
1114 printf("<option value=%d>Host Up\n", AS_HOST_UP);
1115 printf("<option value=%d>Host Down\n", AS_HOST_DOWN);
1116 printf("<option value=%d>Host Unreachable\n", AS_HOST_UNREACHABLE);
1117 }
1118 else {
1119 printf("<select name='initialassumedservicestate'>\n");
1120 printf("<option value=%d>Unspecified\n", AS_NO_DATA);
1121 printf("<option value=%d>Current State\n", AS_CURRENT_STATE);
1122 printf("<option value=%d>Service Ok\n", AS_SVC_OK);
1123 printf("<option value=%d>Service Warning\n", AS_SVC_WARNING);
1124 printf("<option value=%d>Service Unknown\n", AS_SVC_UNKNOWN);
1125 printf("<option value=%d>Service Critical\n", AS_SVC_CRITICAL);
1126 }
1127 printf("</select>\n");
1128 printf("</td></tr>\n");
1129
1130 printf("<tr><td class='reportSelectSubTitle' align=right>Backtracked Archives (To Scan For Initial States):</td>\n");
1131 printf("<td class='reportSelectItem'>\n");
1132 printf("<input type='text' name='backtrack' size='2' maxlength='2' value='%d'>\n", backtrack_archives);
1133 printf("</td></tr>\n");
1134
1135 printf("<tr><td class='reportSelectSubTitle' align=right>Suppress image map:</td><td class='reportSelectItem'><input type='checkbox' name='nomap'></td></tr>");
1136 printf("<tr><td class='reportSelectSubTitle' align=right>Suppress popups:</td><td class='reportSelectItem'><input type='checkbox' name='nopopups'></td></tr>\n");
1137
1138 printf("<tr><td></td><td class='reportSelectItem'><input type='submit' value='Create Report'></td></tr>\n");
1139
1140 printf("</TABLE>\n");
1141 printf("</form>\n");
1142
1143 printf("</DIV></P>\n");
1144
1145 /*
1146 printf("<P><DIV ALIGN=CENTER CLASS='helpfulHint'>\n");
1147 printf("Note: Choosing the 'suppress image map' option will make the report run approximately twice as fast as it would otherwise, but it will prevent you from being able to zoom in on specific time periods.\n");
1148 printf("</DIV></P>\n");
1149 */
1150 }
1151
1152 /* as the user whether they want a graph for a host or service */
1153 else {
1154 printf("<P><DIV ALIGN=CENTER>\n");
1155 printf("<DIV CLASS='reportSelectTitle'>Step 1: Select Report Type</DIV>\n");
1156 printf("</DIV></P>\n");
1157
1158 printf("<P><DIV ALIGN=CENTER>\n");
1159
1160 #ifdef LEGACY_GRAPHICAL_CGIS
1161 printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
1162 #else
1163 printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
1164 #endif
1165 printf("<TABLE BORDER=0 cellpadding=5>\n");
1166
1167 printf("<tr><td class='reportSelectSubTitle' align=right>Type:</td>\n");
1168 printf("<td class='reportSelectItem'>\n");
1169 printf("<select name='input'>\n");
1170 printf("<option value=gethost>Host\n");
1171 printf("<option value=getservice>Service\n");
1172 printf("</select>\n");
1173 printf("</td></tr>\n");
1174
1175 printf("<tr><td></td><td class='reportSelectItem'>\n");
1176 printf("<input type='submit' value='Continue to Step 2'>\n");
1177 printf("</td></tr>\n");
1178
1179 printf("</TABLE>\n");
1180 printf("</form>\n");
1181
1182 printf("</DIV></P>\n");
1183 }
1184
1185 }
1186
1187 document_footer();
1188
1189 /* free memory allocated to the archived state data list */
1190 free_archived_state_list();
1191
1192 /* free all other allocated memory */
1193 free_memory();
1194
1195 return OK;
1196 }
1197
1198
1199
document_header(int use_stylesheet)1200 void document_header(int use_stylesheet) {
1201 char date_time[MAX_DATETIME_LENGTH];
1202 time_t current_time;
1203 time_t expire_time;
1204
1205 if(mode == CREATE_HTML) {
1206 printf("Cache-Control: no-store\r\n");
1207 printf("Pragma: no-cache\r\n");
1208
1209 time(¤t_time);
1210 get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1211 printf("Last-Modified: %s\r\n", date_time);
1212
1213 expire_time = (time_t)0;
1214 get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1215 printf("Expires: %s\r\n", date_time);
1216
1217 printf("Content-type: text/html; charset=utf-8\r\n\r\n");
1218
1219 if(embedded == TRUE)
1220 return;
1221
1222 printf("<html>\n");
1223 printf("<head>\n");
1224 printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
1225 printf("<title>\n");
1226 printf("Nagios Trends\n");
1227 printf("</title>\n");
1228
1229 if(use_stylesheet == TRUE) {
1230 printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
1231 printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, TRENDS_CSS);
1232 }
1233
1234 /* write JavaScript code for popup window */
1235 if(display_type != DISPLAY_NO_TRENDS)
1236 write_popup_code();
1237
1238 printf("</head>\n");
1239
1240 printf("<BODY CLASS='trends'>\n");
1241
1242 /* include user SSI header */
1243 #ifdef LEGACY_GRAPHICAL_CGIS
1244 include_ssi_files(TRENDS_CGI, SSI_HEADER);
1245 #else
1246 include_ssi_files(LEGACY_TRENDS_CGI, SSI_HEADER);
1247 #endif
1248
1249 printf("<div id=\"popup\" style=\"position:absolute; z-index:1; visibility: hidden\"></div>\n");
1250 }
1251
1252 else {
1253 printf("Cache-Control: no-store\r\n");
1254 printf("Pragma: no-cache\r\n");
1255
1256 time(¤t_time);
1257 get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1258 printf("Last-Modified: %s\r\n", date_time);
1259
1260 expire_time = (time_t)0L;
1261 get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1262 printf("Expires: %s\r\n", date_time);
1263
1264 printf("Content-Type: image/png\r\n\r\n");
1265 }
1266
1267 return;
1268 }
1269
1270
1271
document_footer(void)1272 void document_footer(void) {
1273
1274 if(embedded == TRUE)
1275 return;
1276
1277 if(mode == CREATE_HTML) {
1278
1279 /* include user SSI footer */
1280 #ifdef LEGACY_GRAPHICAL_CGIS
1281 include_ssi_files(TRENDS_CGI, SSI_FOOTER);
1282 #else
1283 include_ssi_files(LEGACY_TRENDS_CGI, SSI_FOOTER);
1284 #endif
1285
1286 printf("</body>\n");
1287 printf("</html>\n");
1288 }
1289
1290 return;
1291 }
1292
1293
1294
process_cgivars(void)1295 int process_cgivars(void) {
1296 char **variables;
1297 int error = FALSE;
1298 int x;
1299
1300 variables = getcgivars();
1301
1302 for(x = 0; variables[x]; x++) {
1303
1304 /* do some basic length checking on the variable identifier to prevent buffer overflows */
1305 if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
1306 continue;
1307 }
1308
1309 /* we found the host argument */
1310 else if(!strcmp(variables[x], "host")) {
1311 x++;
1312 if(variables[x] == NULL) {
1313 error = TRUE;
1314 break;
1315 }
1316
1317 if((host_name = (char *)strdup(variables[x])) == NULL)
1318 host_name = "";
1319 strip_html_brackets(host_name);
1320
1321 display_type = DISPLAY_HOST_TRENDS;
1322 }
1323
1324 /* we found the node width argument */
1325 else if(!strcmp(variables[x], "service")) {
1326 x++;
1327 if(variables[x] == NULL) {
1328 error = TRUE;
1329 break;
1330 }
1331
1332 if((svc_description = (char *)strdup(variables[x])) == NULL)
1333 svc_description = "";
1334 strip_html_brackets(svc_description);
1335
1336 display_type = DISPLAY_SERVICE_TRENDS;
1337 }
1338
1339 /* we found first time argument */
1340 else if(!strcmp(variables[x], "t1")) {
1341 x++;
1342 if(variables[x] == NULL) {
1343 error = TRUE;
1344 break;
1345 }
1346
1347 t1 = (time_t)strtoul(variables[x], NULL, 10);
1348 timeperiod_type = TIMEPERIOD_CUSTOM;
1349 }
1350
1351 /* we found first time argument */
1352 else if(!strcmp(variables[x], "t2")) {
1353 x++;
1354 if(variables[x] == NULL) {
1355 error = TRUE;
1356 break;
1357 }
1358
1359 t2 = (time_t)strtoul(variables[x], NULL, 10);
1360 timeperiod_type = TIMEPERIOD_CUSTOM;
1361 }
1362
1363 /* we found the image creation option */
1364 else if(!strcmp(variables[x], "createimage")) {
1365 mode = CREATE_IMAGE;
1366 }
1367
1368 /* we found the assume initial states option */
1369 else if(!strcmp(variables[x], "assumeinitialstates")) {
1370 x++;
1371 if(variables[x] == NULL) {
1372 error = TRUE;
1373 break;
1374 }
1375
1376 if(!strcmp(variables[x], "yes"))
1377 assume_initial_states = TRUE;
1378 else
1379 assume_initial_states = FALSE;
1380 }
1381
1382 /* we found the initial assumed host state option */
1383 else if(!strcmp(variables[x], "initialassumedhoststate")) {
1384 x++;
1385 if(variables[x] == NULL) {
1386 error = TRUE;
1387 break;
1388 }
1389
1390 initial_assumed_host_state = atoi(variables[x]);
1391 }
1392
1393 /* we found the initial assumed service state option */
1394 else if(!strcmp(variables[x], "initialassumedservicestate")) {
1395 x++;
1396 if(variables[x] == NULL) {
1397 error = TRUE;
1398 break;
1399 }
1400
1401 initial_assumed_service_state = atoi(variables[x]);
1402 }
1403
1404 /* we found the assume state during program not running option */
1405 else if(!strcmp(variables[x], "assumestatesduringnotrunning")) {
1406 x++;
1407 if(variables[x] == NULL) {
1408 error = TRUE;
1409 break;
1410 }
1411
1412 if(!strcmp(variables[x], "yes"))
1413 assume_states_during_notrunning = TRUE;
1414 else
1415 assume_states_during_notrunning = FALSE;
1416 }
1417
1418 /* we found the assume state retention option */
1419 else if(!strcmp(variables[x], "assumestateretention")) {
1420 x++;
1421 if(variables[x] == NULL) {
1422 error = TRUE;
1423 break;
1424 }
1425
1426 if(!strcmp(variables[x], "yes"))
1427 assume_state_retention = TRUE;
1428 else
1429 assume_state_retention = FALSE;
1430 }
1431
1432 /* we found the include soft states option */
1433 else if(!strcmp(variables[x], "includesoftstates")) {
1434 x++;
1435 if(variables[x] == NULL) {
1436 error = TRUE;
1437 break;
1438 }
1439
1440 if(!strcmp(variables[x], "yes"))
1441 include_soft_states = TRUE;
1442 else
1443 include_soft_states = FALSE;
1444 }
1445
1446 /* we found the zoom factor argument */
1447 else if(!strcmp(variables[x], "zoom")) {
1448 x++;
1449 if(variables[x] == NULL) {
1450 error = TRUE;
1451 break;
1452 }
1453
1454 zoom_factor = atoi(variables[x]);
1455 if(zoom_factor == 0)
1456 zoom_factor = 1;
1457 }
1458
1459 /* we found the backtrack archives argument */
1460 else if(!strcmp(variables[x], "backtrack")) {
1461 x++;
1462 if(variables[x] == NULL) {
1463 error = TRUE;
1464 break;
1465 }
1466
1467 backtrack_archives = atoi(variables[x]);
1468 if(backtrack_archives < 0)
1469 backtrack_archives = 0;
1470 if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
1471 backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
1472 }
1473
1474 /* we found the standard timeperiod argument */
1475 else if(!strcmp(variables[x], "timeperiod")) {
1476 x++;
1477 if(variables[x] == NULL) {
1478 error = TRUE;
1479 break;
1480 }
1481
1482 if(!strcmp(variables[x], "today"))
1483 timeperiod_type = TIMEPERIOD_TODAY;
1484 else if(!strcmp(variables[x], "yesterday"))
1485 timeperiod_type = TIMEPERIOD_YESTERDAY;
1486 else if(!strcmp(variables[x], "thisweek"))
1487 timeperiod_type = TIMEPERIOD_THISWEEK;
1488 else if(!strcmp(variables[x], "lastweek"))
1489 timeperiod_type = TIMEPERIOD_LASTWEEK;
1490 else if(!strcmp(variables[x], "thismonth"))
1491 timeperiod_type = TIMEPERIOD_THISMONTH;
1492 else if(!strcmp(variables[x], "lastmonth"))
1493 timeperiod_type = TIMEPERIOD_LASTMONTH;
1494 else if(!strcmp(variables[x], "thisquarter"))
1495 timeperiod_type = TIMEPERIOD_THISQUARTER;
1496 else if(!strcmp(variables[x], "lastquarter"))
1497 timeperiod_type = TIMEPERIOD_LASTQUARTER;
1498 else if(!strcmp(variables[x], "thisyear"))
1499 timeperiod_type = TIMEPERIOD_THISYEAR;
1500 else if(!strcmp(variables[x], "lastyear"))
1501 timeperiod_type = TIMEPERIOD_LASTYEAR;
1502 else if(!strcmp(variables[x], "nextproblem"))
1503 timeperiod_type = TIMEPERIOD_NEXTPROBLEM;
1504 else if(!strcmp(variables[x], "last24hours"))
1505 timeperiod_type = TIMEPERIOD_LAST24HOURS;
1506 else if(!strcmp(variables[x], "last7days"))
1507 timeperiod_type = TIMEPERIOD_LAST7DAYS;
1508 else if(!strcmp(variables[x], "last31days"))
1509 timeperiod_type = TIMEPERIOD_LAST31DAYS;
1510 else if(!strcmp(variables[x], "custom"))
1511 timeperiod_type = TIMEPERIOD_CUSTOM;
1512 else
1513 continue;
1514
1515 convert_timeperiod_to_times(timeperiod_type);
1516 }
1517
1518 /* we found time argument */
1519 else if(!strcmp(variables[x], "smon")) {
1520 x++;
1521 if(variables[x] == NULL) {
1522 error = TRUE;
1523 break;
1524 }
1525
1526 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1527 continue;
1528
1529 start_month = atoi(variables[x]);
1530 timeperiod_type = TIMEPERIOD_CUSTOM;
1531 compute_time_from_parts = TRUE;
1532 }
1533
1534 /* we found time argument */
1535 else if(!strcmp(variables[x], "sday")) {
1536 x++;
1537 if(variables[x] == NULL) {
1538 error = TRUE;
1539 break;
1540 }
1541
1542 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1543 continue;
1544
1545 start_day = atoi(variables[x]);
1546 timeperiod_type = TIMEPERIOD_CUSTOM;
1547 compute_time_from_parts = TRUE;
1548 }
1549
1550 /* we found time argument */
1551 else if(!strcmp(variables[x], "syear")) {
1552 x++;
1553 if(variables[x] == NULL) {
1554 error = TRUE;
1555 break;
1556 }
1557
1558 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1559 continue;
1560
1561 start_year = atoi(variables[x]);
1562 timeperiod_type = TIMEPERIOD_CUSTOM;
1563 compute_time_from_parts = TRUE;
1564 }
1565
1566 /* we found time argument */
1567 else if(!strcmp(variables[x], "smin")) {
1568 x++;
1569 if(variables[x] == NULL) {
1570 error = TRUE;
1571 break;
1572 }
1573
1574 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1575 continue;
1576
1577 start_minute = atoi(variables[x]);
1578 timeperiod_type = TIMEPERIOD_CUSTOM;
1579 compute_time_from_parts = TRUE;
1580 }
1581
1582 /* we found time argument */
1583 else if(!strcmp(variables[x], "ssec")) {
1584 x++;
1585 if(variables[x] == NULL) {
1586 error = TRUE;
1587 break;
1588 }
1589
1590 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1591 continue;
1592
1593 start_second = atoi(variables[x]);
1594 timeperiod_type = TIMEPERIOD_CUSTOM;
1595 compute_time_from_parts = TRUE;
1596 }
1597
1598 /* we found time argument */
1599 else if(!strcmp(variables[x], "shour")) {
1600 x++;
1601 if(variables[x] == NULL) {
1602 error = TRUE;
1603 break;
1604 }
1605
1606 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1607 continue;
1608
1609 start_hour = atoi(variables[x]);
1610 timeperiod_type = TIMEPERIOD_CUSTOM;
1611 compute_time_from_parts = TRUE;
1612 }
1613
1614
1615 /* we found time argument */
1616 else if(!strcmp(variables[x], "emon")) {
1617 x++;
1618 if(variables[x] == NULL) {
1619 error = TRUE;
1620 break;
1621 }
1622
1623 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1624 continue;
1625
1626 end_month = atoi(variables[x]);
1627 timeperiod_type = TIMEPERIOD_CUSTOM;
1628 compute_time_from_parts = TRUE;
1629 }
1630
1631 /* we found time argument */
1632 else if(!strcmp(variables[x], "eday")) {
1633 x++;
1634 if(variables[x] == NULL) {
1635 error = TRUE;
1636 break;
1637 }
1638
1639 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1640 continue;
1641
1642 end_day = atoi(variables[x]);
1643 timeperiod_type = TIMEPERIOD_CUSTOM;
1644 compute_time_from_parts = TRUE;
1645 }
1646
1647 /* we found time argument */
1648 else if(!strcmp(variables[x], "eyear")) {
1649 x++;
1650 if(variables[x] == NULL) {
1651 error = TRUE;
1652 break;
1653 }
1654
1655 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1656 continue;
1657
1658 end_year = atoi(variables[x]);
1659 timeperiod_type = TIMEPERIOD_CUSTOM;
1660 compute_time_from_parts = TRUE;
1661 }
1662
1663 /* we found time argument */
1664 else if(!strcmp(variables[x], "emin")) {
1665 x++;
1666 if(variables[x] == NULL) {
1667 error = TRUE;
1668 break;
1669 }
1670
1671 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1672 continue;
1673
1674 end_minute = atoi(variables[x]);
1675 timeperiod_type = TIMEPERIOD_CUSTOM;
1676 compute_time_from_parts = TRUE;
1677 }
1678
1679 /* we found time argument */
1680 else if(!strcmp(variables[x], "esec")) {
1681 x++;
1682 if(variables[x] == NULL) {
1683 error = TRUE;
1684 break;
1685 }
1686
1687 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1688 continue;
1689
1690 end_second = atoi(variables[x]);
1691 timeperiod_type = TIMEPERIOD_CUSTOM;
1692 compute_time_from_parts = TRUE;
1693 }
1694
1695 /* we found time argument */
1696 else if(!strcmp(variables[x], "ehour")) {
1697 x++;
1698 if(variables[x] == NULL) {
1699 error = TRUE;
1700 break;
1701 }
1702
1703 if(timeperiod_type != TIMEPERIOD_CUSTOM)
1704 continue;
1705
1706 end_hour = atoi(variables[x]);
1707 timeperiod_type = TIMEPERIOD_CUSTOM;
1708 compute_time_from_parts = TRUE;
1709 }
1710
1711 /* we found the embed option */
1712 else if(!strcmp(variables[x], "embedded"))
1713 embedded = TRUE;
1714
1715 /* we found the noheader option */
1716 else if(!strcmp(variables[x], "noheader"))
1717 display_header = FALSE;
1718
1719 /* we found the nopopups option */
1720 else if(!strcmp(variables[x], "nopopups"))
1721 display_popups = FALSE;
1722
1723 /* we found the nomap option */
1724 else if(!strcmp(variables[x], "nomap")) {
1725 display_popups = FALSE;
1726 use_map = FALSE;
1727 }
1728
1729 /* we found the input option */
1730 else if(!strcmp(variables[x], "input")) {
1731 x++;
1732 if(variables[x] == NULL) {
1733 error = TRUE;
1734 break;
1735 }
1736
1737 if(!strcmp(variables[x], "gethost"))
1738 input_type = GET_INPUT_HOST_TARGET;
1739 else if(!strcmp(variables[x], "getservice"))
1740 input_type = GET_INPUT_SERVICE_TARGET;
1741 else if(!strcmp(variables[x], "getoptions"))
1742 input_type = GET_INPUT_OPTIONS;
1743 else
1744 input_type = GET_INPUT_TARGET_TYPE;
1745 }
1746
1747 /* we found the small image option */
1748 else if(!strcmp(variables[x], "smallimage"))
1749 small_image = TRUE;
1750
1751 }
1752
1753 /* free memory allocated to the CGI variables */
1754 free_cgivars(variables);
1755
1756 return error;
1757 }
1758
1759
1760
1761 /* top level routine for graphic all trend data */
graph_all_trend_data(void)1762 void graph_all_trend_data(void) {
1763 archived_state *temp_as;
1764 archived_state *last_as;
1765 time_t a;
1766 time_t b;
1767 time_t current_time;
1768 int current_state = AS_NO_DATA;
1769 int have_some_real_data = FALSE;
1770 hoststatus *hststatus = NULL;
1771 servicestatus *svcstatus = NULL;
1772 unsigned long wobble = 300;
1773 time_t initial_assumed_time;
1774 int initial_assumed_state = AS_SVC_OK;
1775 int error = FALSE;
1776
1777
1778 time(¤t_time);
1779
1780 /* if left hand of graph is after current time, we can't do anything at all.... */
1781 if(t1 > current_time)
1782 return;
1783
1784 /* find current state for host or service */
1785 if(display_type == DISPLAY_HOST_TRENDS)
1786 hststatus = find_hoststatus(host_name);
1787 else
1788 svcstatus = find_servicestatus(host_name, svc_description);
1789
1790
1791 /************************************/
1792 /* INSERT CURRENT STATE (IF WE CAN) */
1793 /************************************/
1794
1795 /* if current time DOES NOT fall within graph bounds, so we can't do anything as far as assuming current state */
1796 /* the "wobble" value is necessary because when the CGI is called to do the PNG generation, t2 will actually be less that current_time by a bit */
1797
1798 /* if we don't have any data, assume current state (if possible) */
1799 if(as_list == NULL && current_time > t1 && current_time < (time_t)(t2 + wobble)) {
1800
1801 /* we don't have any historical information, but the current time falls within the reporting period, so use */
1802 /* the current status of the host/service as the starting data */
1803 if(display_type == DISPLAY_HOST_TRENDS) {
1804 if(hststatus != NULL) {
1805
1806 if(hststatus->status == SD_HOST_DOWN)
1807 last_known_state = AS_HOST_DOWN;
1808 else if(hststatus->status == SD_HOST_UNREACHABLE)
1809 last_known_state = AS_HOST_UNREACHABLE;
1810 else
1811 last_known_state = AS_HOST_UP;
1812
1813 /* add a dummy archived state item, so something can get graphed */
1814 add_archived_state(last_known_state, AS_HARD_STATE, t1, "Current Host State Assumed (Faked Log Entry)");
1815 }
1816 }
1817 else {
1818 if(svcstatus != NULL) {
1819
1820 if(svcstatus->status == SERVICE_OK)
1821 last_known_state = AS_SVC_OK;
1822 else if(svcstatus->status == SERVICE_WARNING)
1823 last_known_state = AS_SVC_WARNING;
1824 else if(svcstatus->status == SERVICE_CRITICAL)
1825 last_known_state = AS_SVC_CRITICAL;
1826 else if(svcstatus->status == SERVICE_UNKNOWN)
1827 last_known_state = AS_SVC_UNKNOWN;
1828
1829 /* add a dummy archived state item, so something can get graphed */
1830 add_archived_state(last_known_state, AS_HARD_STATE, t1, "Current Service State Assumed (Faked Log Entry)");
1831 }
1832 }
1833 }
1834
1835
1836 /******************************************/
1837 /* INSERT FIRST ASSUMED STATE (IF WE CAN) */
1838 /******************************************/
1839
1840 if((display_type == DISPLAY_HOST_TRENDS && initial_assumed_host_state != AS_NO_DATA) || (display_type == DISPLAY_SERVICE_TRENDS && initial_assumed_service_state != AS_NO_DATA)) {
1841
1842 /* see if its okay to assume initial state for this subject */
1843 error = FALSE;
1844 if(display_type == DISPLAY_SERVICE_TRENDS) {
1845 if(initial_assumed_service_state != AS_SVC_OK && initial_assumed_service_state != AS_SVC_WARNING && initial_assumed_service_state != AS_SVC_UNKNOWN && initial_assumed_service_state != AS_SVC_CRITICAL && initial_assumed_service_state != AS_CURRENT_STATE)
1846 error = TRUE;
1847 else
1848 initial_assumed_state = initial_assumed_service_state;
1849 if(initial_assumed_service_state == AS_CURRENT_STATE && svcstatus == NULL)
1850 error = TRUE;
1851 }
1852 else {
1853 if(initial_assumed_host_state != AS_HOST_UP && initial_assumed_host_state != AS_HOST_DOWN && initial_assumed_host_state != AS_HOST_UNREACHABLE && initial_assumed_host_state != AS_CURRENT_STATE)
1854 error = TRUE;
1855 else
1856 initial_assumed_state = initial_assumed_host_state;
1857 if(initial_assumed_host_state == AS_CURRENT_STATE && hststatus == NULL)
1858 error = TRUE;
1859 }
1860
1861 /* get the current state if applicable */
1862 if(((display_type == DISPLAY_HOST_TRENDS && initial_assumed_host_state == AS_CURRENT_STATE) || (display_type == DISPLAY_SERVICE_TRENDS && initial_assumed_service_state == AS_CURRENT_STATE)) && error == FALSE) {
1863 if(display_type == DISPLAY_HOST_TRENDS) {
1864 switch(hststatus->status) {
1865 case SD_HOST_DOWN:
1866 initial_assumed_state = AS_HOST_DOWN;
1867 break;
1868 case SD_HOST_UNREACHABLE:
1869 initial_assumed_state = AS_HOST_UNREACHABLE;
1870 break;
1871 case SD_HOST_UP:
1872 initial_assumed_state = AS_HOST_UP;
1873 break;
1874 default:
1875 error = TRUE;
1876 break;
1877 }
1878 }
1879 else {
1880 switch(svcstatus->status) {
1881 case SERVICE_OK:
1882 initial_assumed_state = AS_SVC_OK;
1883 break;
1884 case SERVICE_WARNING:
1885 initial_assumed_state = AS_SVC_WARNING;
1886 break;
1887 case SERVICE_UNKNOWN:
1888 initial_assumed_state = AS_SVC_UNKNOWN;
1889 break;
1890 case SERVICE_CRITICAL:
1891 initial_assumed_state = AS_SVC_CRITICAL;
1892 break;
1893 default:
1894 error = TRUE;
1895 break;
1896 }
1897 }
1898 }
1899
1900 if(error == FALSE) {
1901
1902 /* add this assumed state entry before any entries in the list and <= t1 */
1903 if(as_list == NULL)
1904 initial_assumed_time = t1;
1905 else if(as_list->time_stamp > t1)
1906 initial_assumed_time = t1;
1907 else
1908 initial_assumed_time = as_list->time_stamp - 1;
1909
1910 if(display_type == DISPLAY_HOST_TRENDS)
1911 add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Host State Assumed (Faked Log Entry)");
1912 else
1913 add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Service State Assumed (Faked Log Entry)");
1914 }
1915 }
1916
1917
1918
1919
1920 /**************************************/
1921 /* BAIL OUT IF WE DON'T HAVE ANYTHING */
1922 /**************************************/
1923
1924 have_some_real_data = FALSE;
1925 for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
1926 if(temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_START && temp_as->entry_type != AS_PROGRAM_END) {
1927 have_some_real_data = TRUE;
1928 break;
1929 }
1930 }
1931 if(have_some_real_data == FALSE)
1932 return;
1933
1934
1935
1936
1937 /* if we're creating the HTML, start map code... */
1938 if(mode == CREATE_HTML)
1939 printf("<MAP name='trendsmap'>\n");
1940
1941 last_as = NULL;
1942 earliest_time = t2;
1943 latest_time = t1;
1944
1945
1946
1947 #ifdef DEBUG
1948 printf("--- BEGINNING/MIDDLE SECTION ---<BR>\n");
1949 #endif
1950
1951 /**********************************/
1952 /* BEGINNING/MIDDLE SECTION */
1953 /**********************************/
1954
1955 for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
1956
1957 /* keep this as last known state if this is the first entry or if it occurs before the starting point of the graph */
1958 if((temp_as->time_stamp <= t1 || temp_as == as_list) && (temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_END && temp_as->entry_type != AS_PROGRAM_START)) {
1959 last_known_state = temp_as->entry_type;
1960 #ifdef DEBUG
1961 printf("SETTING LAST KNOWN STATE=%d<br>\n", last_known_state);
1962 #endif
1963 }
1964
1965 /* skip this entry if it occurs before the starting point of the graph */
1966 if(temp_as->time_stamp <= t1) {
1967 #ifdef DEBUG
1968 printf("SKIPPING PRE-EVENT: %d @ %lu<br>\n", temp_as->entry_type, temp_as->time_stamp);
1969 #endif
1970 last_as = temp_as;
1971 continue;
1972 }
1973
1974 /* graph this span if we're not on the first item */
1975 if(last_as != NULL) {
1976
1977 a = last_as->time_stamp;
1978 b = temp_as->time_stamp;
1979
1980 /* we've already passed the last time displayed in the graph */
1981 if(a > t2)
1982 break;
1983
1984 /* only graph this data if its on the graph */
1985 else if(b > t1) {
1986
1987 /* clip last time if it exceeds graph limits */
1988 if(b > t2)
1989 b = t2;
1990
1991 /* clip first time if it precedes graph limits */
1992 if(a < t1)
1993 a = t1;
1994
1995 /* save this time if its the earliest we've graphed */
1996 if(a < earliest_time) {
1997 earliest_time = a;
1998 earliest_state = last_as->entry_type;
1999 }
2000
2001 /* save this time if its the latest we've graphed */
2002 if(b > latest_time) {
2003 latest_time = b;
2004 latest_state = last_as->entry_type;
2005 }
2006
2007 /* compute availability times for this chunk */
2008 graph_trend_data(last_as->entry_type, temp_as->entry_type, last_as->time_stamp, a, b, last_as->state_info);
2009
2010 /* return if we've reached the end of the graph limits */
2011 if(b >= t2) {
2012 last_as = temp_as;
2013 break;
2014 }
2015 }
2016 }
2017
2018
2019 /* keep track of the last item */
2020 last_as = temp_as;
2021 }
2022
2023
2024 #ifdef DEBUG
2025 printf("--- END SECTION ---<BR>\n");
2026 #endif
2027
2028 /**********************************/
2029 /* END SECTION */
2030 /**********************************/
2031
2032 if(last_as != NULL) {
2033
2034 /* don't process an entry that is beyond the limits of the graph */
2035 if(last_as->time_stamp < t2) {
2036
2037 time(¤t_time);
2038 b = current_time;
2039 if(b > t2)
2040 b = t2;
2041
2042 a = last_as->time_stamp;
2043 if(a < t1)
2044 a = t1;
2045
2046 /* fake the current state (it doesn't really matter for graphing) */
2047 if(display_type == DISPLAY_HOST_TRENDS)
2048 current_state = AS_HOST_UP;
2049 else
2050 current_state = AS_SVC_OK;
2051
2052 /* compute availability times for last state */
2053 graph_trend_data(last_as->entry_type, current_state, a, a, b, last_as->state_info);
2054 }
2055 }
2056
2057
2058
2059 /* if we're creating the HTML, close the map code */
2060 if(mode == CREATE_HTML)
2061 printf("</MAP>\n");
2062
2063 return;
2064 }
2065
2066
2067
2068 /* graphs trend data */
graph_trend_data(int first_state,int last_state,time_t real_start_time,time_t start_time,time_t end_time,char * state_info)2069 void graph_trend_data(int first_state, int last_state, time_t real_start_time, time_t start_time, time_t end_time, char *state_info) {
2070 int start_state;
2071 int start_pixel = 0;
2072 int end_pixel = 0;
2073 int color_to_use = 0;
2074 int height = 0;
2075 double start_pixel_ratio;
2076 double end_pixel_ratio;
2077 char temp_buffer[MAX_INPUT_BUFFER];
2078 char state_string[MAX_INPUT_BUFFER];
2079 char end_timestring[MAX_INPUT_BUFFER];
2080 char start_timestring[MAX_INPUT_BUFFER];
2081 time_t center_time;
2082 time_t next_start_time;
2083 time_t next_end_time;
2084 int days = 0;
2085 int hours = 0;
2086 int minutes = 0;
2087 int seconds = 0;
2088
2089 /* can't graph if we don't have data... */
2090 if(first_state == AS_NO_DATA || last_state == AS_NO_DATA)
2091 return;
2092 if(first_state == AS_PROGRAM_START && (last_state == AS_PROGRAM_END || last_state == AS_PROGRAM_START)) {
2093 if(assume_initial_states == FALSE)
2094 return;
2095 }
2096 if(first_state == AS_PROGRAM_END) {
2097 if(assume_states_during_notrunning == TRUE)
2098 first_state = last_known_state;
2099 else
2100 return;
2101 }
2102
2103 /* special case if first entry was program start */
2104 if(first_state == AS_PROGRAM_START) {
2105 #ifdef DEBUG
2106 printf("First state=program start!\n");
2107 #endif
2108 if(assume_initial_states == TRUE) {
2109 #ifdef DEBUG
2110 printf("\tWe are assuming initial states...\n");
2111 #endif
2112 if(assume_state_retention == TRUE) {
2113 start_state = last_known_state;
2114 #ifdef DEBUG
2115 printf("\tWe are assuming state retention (%d)...\n", start_state);
2116 #endif
2117 }
2118 else {
2119 #ifdef DEBUG
2120 printf("\tWe are NOT assuming state retention...\n");
2121 #endif
2122 if(display_type == DISPLAY_HOST_TRENDS)
2123 start_state = AS_HOST_UP;
2124 else
2125 start_state = AS_SVC_OK;
2126 }
2127 }
2128 else {
2129 #ifdef DEBUG
2130 printf("We ARE NOT assuming initial states!\n");
2131 #endif
2132 return;
2133 }
2134 }
2135 else {
2136 start_state = first_state;
2137 last_known_state = first_state;
2138 }
2139
2140 #ifdef DEBUG
2141 printf("Graphing state %d\n", start_state);
2142 printf("\tfrom %s", ctime(&start_time));
2143 printf("\tto %s", ctime(&end_time));
2144 #endif
2145
2146 if(start_time < t1)
2147 start_time = t1;
2148 if(end_time > t2)
2149 end_time = t2;
2150 if(end_time < t1 || start_time > t2)
2151 return;
2152
2153 /* calculate the first and last pixels to use */
2154 if(start_time == t1)
2155 start_pixel = 0;
2156 else {
2157 start_pixel_ratio = ((double)(start_time - t1)) / ((double)(t2 - t1));
2158 start_pixel = (int)(start_pixel_ratio * (drawing_width - 1));
2159 }
2160 if(end_time == t1)
2161 end_pixel = 0;
2162 else {
2163 end_pixel_ratio = ((double)(end_time - t1)) / ((double)(t2 - t1));
2164 end_pixel = (int)(end_pixel_ratio * (drawing_width - 1));
2165 }
2166
2167 #ifdef DEBUG
2168 printf("\tPixel %d to %d\n\n", start_pixel, end_pixel);
2169 #endif
2170
2171
2172 /* we're creating the image, so draw... */
2173 if(mode == CREATE_IMAGE) {
2174
2175 /* figure out the color to use for drawing */
2176 switch(start_state) {
2177 case AS_HOST_UP:
2178 color_to_use = color_green;
2179 height = 60;
2180 break;
2181 case AS_HOST_DOWN:
2182 color_to_use = color_red;
2183 height = 40;
2184 break;
2185 case AS_HOST_UNREACHABLE:
2186 color_to_use = color_darkred;
2187 height = 20;
2188 break;
2189 case AS_SVC_OK:
2190 color_to_use = color_green;
2191 height = 80;
2192 break;
2193 case AS_SVC_WARNING:
2194 color_to_use = color_yellow;
2195 height = 60;
2196 break;
2197 case AS_SVC_UNKNOWN:
2198 color_to_use = color_orange;
2199 height = 40;
2200 break;
2201 case AS_SVC_CRITICAL:
2202 color_to_use = color_red;
2203 height = 20;
2204 break;
2205 default:
2206 color_to_use = color_black;
2207 height = 0;
2208 break;
2209 }
2210
2211 /* draw a rectangle */
2212 if(start_state != AS_NO_DATA)
2213 gdImageFilledRectangle(trends_image, start_pixel + drawing_x_offset, drawing_height - height + drawing_y_offset, end_pixel + drawing_x_offset, drawing_height + drawing_y_offset, color_to_use);
2214 }
2215
2216 /* else we're creating the HTML, so write map area code... */
2217 else {
2218
2219
2220 /* figure out the the state string to use */
2221 switch(start_state) {
2222 case AS_HOST_UP:
2223 strcpy(state_string, "UP");
2224 height = 60;
2225 break;
2226 case AS_HOST_DOWN:
2227 strcpy(state_string, "DOWN");
2228 height = 40;
2229 break;
2230 case AS_HOST_UNREACHABLE:
2231 strcpy(state_string, "UNREACHABLE");
2232 height = 20;
2233 break;
2234 case AS_SVC_OK:
2235 strcpy(state_string, "OK");
2236 height = 80;
2237 break;
2238 case AS_SVC_WARNING:
2239 strcpy(state_string, "WARNING");
2240 height = 60;
2241 break;
2242 case AS_SVC_UNKNOWN:
2243 strcpy(state_string, "UNKNOWN");
2244 height = 40;
2245 break;
2246 case AS_SVC_CRITICAL:
2247 strcpy(state_string, "CRITICAL");
2248 height = 20;
2249 break;
2250 default:
2251 strcpy(state_string, "?");
2252 height = 5;
2253 break;
2254 }
2255
2256 /* get the center of this time range */
2257 center_time = start_time + ((end_time - start_time) / 2);
2258
2259 /* determine next start and end time range with zoom factor */
2260 if(zoom_factor > 0) {
2261 next_start_time = center_time - (((t2 - t1) / 2) / zoom_factor);
2262 next_end_time = center_time + (((t2 - t1) / 2) / zoom_factor);
2263 }
2264 else {
2265 next_start_time = center_time + (((t2 - t1) / 2) * zoom_factor);
2266 next_end_time = center_time - (((t2 - t1) / 2) * zoom_factor);
2267 }
2268
2269 printf("<AREA shape='rect' ");
2270
2271 printf("coords='%d,%d,%d,%d' ", drawing_x_offset + start_pixel, drawing_y_offset + (drawing_height - height), drawing_x_offset + end_pixel, drawing_y_offset + drawing_height);
2272
2273 #ifdef LEGACY_GRAPHICAL_CGIS
2274 printf("href='%s?t1=%llu&t2=%llu&host=%s", TRENDS_CGI, (unsigned long long)next_start_time, (unsigned long long)next_end_time, url_encode(host_name));
2275 #else
2276 printf("href='%s?t1=%llu&t2=%llu&host=%s", LEGACY_TRENDS_CGI, (unsigned long long)next_start_time, (unsigned long long)next_end_time, url_encode(host_name));
2277 #endif
2278 if(display_type == DISPLAY_SERVICE_TRENDS)
2279 printf("&service=%s", url_encode(svc_description));
2280 printf("&assumeinitialstates=%s", (assume_initial_states == TRUE) ? "yes" : "no");
2281 printf("&initialassumedhoststate=%d", initial_assumed_host_state);
2282 printf("&initialassumedservicestate=%d", initial_assumed_service_state);
2283 printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
2284 printf("&assumestatesduringnotrunning=%s", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
2285 printf("&includesoftstates=%s", (include_soft_states == TRUE) ? "yes" : "no");
2286 if(backtrack_archives > 0)
2287 printf("&backtrack=%d", backtrack_archives);
2288 printf("&zoom=%d", zoom_factor);
2289
2290 printf("' ");
2291
2292 /* display popup text */
2293 if(display_popups == TRUE) {
2294
2295 snprintf(start_timestring, sizeof(start_timestring) - 1, "%s", ctime(&real_start_time));
2296 start_timestring[sizeof(start_timestring) - 1] = '\x0';
2297 start_timestring[strlen(start_timestring) - 1] = '\x0';
2298
2299 snprintf(end_timestring, sizeof(end_timestring) - 1, "%s", ctime(&end_time));
2300 end_timestring[sizeof(end_timestring) - 1] = '\x0';
2301 end_timestring[strlen(end_timestring) - 1] = '\x0';
2302
2303 /* calculate total time in this state */
2304 get_time_breakdown((time_t)(end_time - start_time), &days, &hours, &minutes, &seconds);
2305
2306 /* sanitize plugin output */
2307 sanitize_plugin_output(state_info);
2308
2309 printf("onMouseOver='showPopup(\"");
2310 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "<B><U>%s</U></B><BR><B>Time Range</B>: <I>%s</I> to <I>%s</I><BR><B>Duration</B>: <I>%dd %dh %dm %ds</I><BR><B>State Info</B>: <I>%s</I>", state_string, start_timestring, end_timestring, days, hours, minutes, seconds, (state_info == NULL) ? "N/A" : state_info);
2311 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
2312 printf("%s", temp_buffer);
2313 printf("\",event)' onMouseOut='hidePopup()'");
2314 }
2315
2316 printf(">\n");
2317
2318 }
2319
2320
2321 /* calculate time in this state */
2322 switch(start_state) {
2323 case AS_HOST_UP:
2324 time_up += (unsigned long)(end_time - start_time);
2325 break;
2326 case AS_HOST_DOWN:
2327 time_down += (unsigned long)(end_time - start_time);
2328 break;
2329 case AS_HOST_UNREACHABLE:
2330 time_unreachable += (unsigned long)(end_time - start_time);
2331 break;
2332 case AS_SVC_OK:
2333 time_ok += (unsigned long)(end_time - start_time);
2334 break;
2335 case AS_SVC_WARNING:
2336 time_warning += (unsigned long)(end_time - start_time);
2337 break;
2338 case AS_SVC_UNKNOWN:
2339 time_unknown += (unsigned long)(end_time - start_time);
2340 break;
2341 case AS_SVC_CRITICAL:
2342 time_critical += (unsigned long)(end_time - start_time);
2343 break;
2344 default:
2345 break;
2346 }
2347
2348 return;
2349 }
2350
2351
2352
2353 /* convert current host state to archived state value */
convert_host_state_to_archived_state(int current_status)2354 int convert_host_state_to_archived_state(int current_status) {
2355
2356 if(current_status == SD_HOST_UP)
2357 return AS_HOST_UP;
2358 if(current_status == SD_HOST_DOWN)
2359 return AS_HOST_DOWN;
2360 if(current_status == SD_HOST_UNREACHABLE)
2361 return AS_HOST_UNREACHABLE;
2362
2363 return AS_NO_DATA;
2364 }
2365
2366
2367 /* convert current service state to archived state value */
convert_service_state_to_archived_state(int current_status)2368 int convert_service_state_to_archived_state(int current_status) {
2369
2370 if(current_status == SERVICE_OK)
2371 return AS_SVC_OK;
2372 if(current_status == SERVICE_UNKNOWN)
2373 return AS_SVC_UNKNOWN;
2374 if(current_status == SERVICE_WARNING)
2375 return AS_SVC_WARNING;
2376 if(current_status == SERVICE_CRITICAL)
2377 return AS_SVC_CRITICAL;
2378
2379 return AS_NO_DATA;
2380 }
2381
2382
2383
2384 /* adds an archived state entry */
add_archived_state(int entry_type,int state_type,time_t time_stamp,char * state_info)2385 void add_archived_state(int entry_type, int state_type, time_t time_stamp, char *state_info) {
2386 archived_state *last_as = NULL;
2387 archived_state *temp_as = NULL;
2388 archived_state *new_as = NULL;
2389
2390 #ifdef DEBUG
2391 printf("Added state %d @ %s", state_type, ctime(&time_stamp));
2392 #endif
2393
2394 /* allocate memory for the new entry */
2395 new_as = (archived_state *)malloc(sizeof(archived_state));
2396 if(new_as == NULL)
2397 return;
2398
2399 /* allocate memory fo the state info */
2400 if(state_info != NULL) {
2401 new_as->state_info = (char *)malloc(strlen(state_info) + 1);
2402 if(new_as->state_info != NULL)
2403 strcpy(new_as->state_info, state_info);
2404 }
2405 else new_as->state_info = NULL;
2406
2407 new_as->entry_type = entry_type;
2408 new_as->processed_state = entry_type;
2409 new_as->state_type = state_type;
2410 new_as->time_stamp = time_stamp;
2411
2412 /* add the new entry to the list in memory, sorted by time */
2413 last_as = as_list;
2414 for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
2415 if(new_as->time_stamp < temp_as->time_stamp) {
2416 new_as->next = temp_as;
2417 if(temp_as == as_list)
2418 as_list = new_as;
2419 else
2420 last_as->next = new_as;
2421 break;
2422 }
2423 else
2424 last_as = temp_as;
2425 }
2426 if(as_list == NULL) {
2427 new_as->next = NULL;
2428 as_list = new_as;
2429 }
2430 else if(temp_as == NULL) {
2431 new_as->next = NULL;
2432 last_as->next = new_as;
2433 }
2434
2435 return;
2436 }
2437
2438
2439 /* frees memory allocated to the archived state list */
free_archived_state_list(void)2440 void free_archived_state_list(void) {
2441 archived_state *this_as = NULL;
2442 archived_state *next_as = NULL;
2443
2444 for(this_as = as_list; this_as != NULL;) {
2445 next_as = this_as->next;
2446 if(this_as->state_info != NULL)
2447 free(this_as->state_info);
2448 free(this_as);
2449 this_as = next_as;
2450 }
2451
2452 as_list = NULL;
2453
2454 return;
2455 }
2456
2457
2458 /* reads log files for archived state data */
read_archived_state_data(void)2459 void read_archived_state_data(void) {
2460 char filename[MAX_FILENAME_LENGTH];
2461 int newest_archive = 0;
2462 int oldest_archive = 0;
2463 int current_archive;
2464
2465 #ifdef DEBUG
2466 printf("Determining archives to use...\n");
2467 #endif
2468
2469 /* determine earliest archive to use */
2470 oldest_archive = determine_archive_to_use_from_time(t1);
2471 if(log_rotation_method != LOG_ROTATION_NONE)
2472 oldest_archive += backtrack_archives;
2473
2474 /* determine most recent archive to use */
2475 newest_archive = determine_archive_to_use_from_time(t2);
2476
2477 if(oldest_archive < newest_archive)
2478 oldest_archive = newest_archive;
2479
2480 #ifdef DEBUG
2481 printf("Oldest archive: %d\n", oldest_archive);
2482 printf("Newest archive: %d\n", newest_archive);
2483 #endif
2484
2485 /* read in all the necessary archived logs */
2486 for(current_archive = newest_archive; current_archive <= oldest_archive; current_archive++) {
2487
2488 /* get the name of the log file that contains this archive */
2489 get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1);
2490
2491 #ifdef DEBUG
2492 printf("\tCurrent archive: %d (%s)\n", current_archive, filename);
2493 #endif
2494
2495 /* scan the log file for archived state data */
2496 scan_log_file_for_archived_state_data(filename);
2497 }
2498
2499 return;
2500 }
2501
2502
2503
2504 /* grabs archives state data from a log file */
scan_log_file_for_archived_state_data(char * filename)2505 void scan_log_file_for_archived_state_data(char *filename) {
2506 char *input = NULL;
2507 char *input2 = NULL;
2508 char entry_host_name[MAX_INPUT_BUFFER];
2509 char entry_svc_description[MAX_INPUT_BUFFER];
2510 char *plugin_output = NULL;
2511 char *temp_buffer = NULL;
2512 time_t time_stamp;
2513 mmapfile *thefile = NULL;
2514 int state_type = 0;
2515
2516 /* print something so browser doesn't time out */
2517 if(mode == CREATE_HTML) {
2518 printf(" ");
2519 fflush(NULL);
2520 }
2521
2522 if((thefile = mmap_fopen(filename)) == NULL) {
2523 #ifdef DEBUG
2524 printf("Could not open file '%s' for reading.\n", filename);
2525 #endif
2526 return;
2527 }
2528
2529 #ifdef DEBUG
2530 printf("Scanning log file '%s' for archived state data...\n", filename);
2531 #endif
2532
2533 while(1) {
2534
2535 /* free memory */
2536 free(input);
2537 free(input2);
2538 input = NULL;
2539 input2 = NULL;
2540
2541 /* read the next line */
2542 if((input = mmap_fgets(thefile)) == NULL)
2543 break;
2544
2545 strip(input);
2546
2547 if((input2 = strdup(input)) == NULL)
2548 continue;
2549
2550 temp_buffer = my_strtok(input2, "]");
2551 time_stamp = (temp_buffer == NULL) ? (time_t)0 : (time_t)strtoul(temp_buffer + 1, NULL, 10);
2552
2553 /* program starts/restarts */
2554 if(strstr(input, " starting..."))
2555 add_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program start");
2556 if(strstr(input, " restarting..."))
2557 add_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program restart");
2558
2559 /* program stops */
2560 if(strstr(input, " shutting down..."))
2561 add_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Normal program termination");
2562 if(strstr(input, "Bailing out"))
2563 add_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Abnormal program termination");
2564
2565 if(display_type == DISPLAY_HOST_TRENDS) {
2566 if(strstr(input, "HOST ALERT:") || strstr(input, "INITIAL HOST STATE:") || strstr(input, "CURRENT HOST STATE:")) {
2567
2568 free(input2);
2569 if((input2 = strdup(input)) == NULL)
2570 continue;
2571
2572 /* get host name */
2573 temp_buffer = my_strtok(input2, "]");
2574 temp_buffer = my_strtok(NULL, ":");
2575 temp_buffer = my_strtok(NULL, ";");
2576 strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2577 entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2578
2579 if(strcmp(host_name, entry_host_name))
2580 continue;
2581
2582 /* state types */
2583 if(strstr(input, ";SOFT;")) {
2584 if(include_soft_states == FALSE)
2585 continue;
2586 state_type = AS_SOFT_STATE;
2587 }
2588 if(strstr(input, ";HARD;"))
2589 state_type = AS_HARD_STATE;
2590
2591 /* get the plugin output */
2592 temp_buffer = my_strtok(NULL, ";");
2593 temp_buffer = my_strtok(NULL, ";");
2594 temp_buffer = my_strtok(NULL, ";");
2595 plugin_output = my_strtok(NULL, "\n");
2596
2597 if(strstr(input, ";DOWN;"))
2598 add_archived_state(AS_HOST_DOWN, state_type, time_stamp, plugin_output);
2599 else if(strstr(input, ";UNREACHABLE;"))
2600 add_archived_state(AS_HOST_UNREACHABLE, state_type, time_stamp, plugin_output);
2601 else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;"))
2602 add_archived_state(AS_HOST_UP, state_type, time_stamp, plugin_output);
2603 else
2604 add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output);
2605 }
2606 }
2607 if(display_type == DISPLAY_SERVICE_TRENDS) {
2608 if(strstr(input, "SERVICE ALERT:") || strstr(input, "INITIAL SERVICE STATE:") || strstr(input, "CURRENT SERVICE STATE:")) {
2609
2610 free(input2);
2611 if((input2 = strdup(input)) == NULL)
2612 continue;
2613
2614 /* get host name */
2615 temp_buffer = my_strtok(input2, "]");
2616 temp_buffer = my_strtok(NULL, ":");
2617 temp_buffer = my_strtok(NULL, ";");
2618 strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2619 entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2620
2621 if(strcmp(host_name, entry_host_name))
2622 continue;
2623
2624 /* get service description */
2625 temp_buffer = my_strtok(NULL, ";");
2626 strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(entry_svc_description));
2627 entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
2628
2629 if(strcmp(svc_description, entry_svc_description))
2630 continue;
2631
2632 /* state types */
2633 if(strstr(input, ";SOFT;")) {
2634 if(include_soft_states == FALSE)
2635 continue;
2636 state_type = AS_SOFT_STATE;
2637 }
2638 if(strstr(input, ";HARD;"))
2639 state_type = AS_HARD_STATE;
2640
2641 /* get the plugin output */
2642 temp_buffer = my_strtok(NULL, ";");
2643 temp_buffer = my_strtok(NULL, ";");
2644 temp_buffer = my_strtok(NULL, ";");
2645 plugin_output = my_strtok(NULL, "\n");
2646
2647 if(strstr(input, ";CRITICAL;"))
2648 add_archived_state(AS_SVC_CRITICAL, state_type, time_stamp, plugin_output);
2649 else if(strstr(input, ";WARNING;"))
2650 add_archived_state(AS_SVC_WARNING, state_type, time_stamp, plugin_output);
2651 else if(strstr(input, ";UNKNOWN;"))
2652 add_archived_state(AS_SVC_UNKNOWN, state_type, time_stamp, plugin_output);
2653 else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))
2654 add_archived_state(AS_SVC_OK, state_type, time_stamp, plugin_output);
2655 else
2656 add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output);
2657
2658 }
2659 }
2660
2661 }
2662
2663 /* free memory and close the file */
2664 free(input);
2665 free(input2);
2666 mmap_fclose(thefile);
2667
2668 return;
2669 }
2670
2671
2672
2673 /* write JavaScript code and layer for popup window */
write_popup_code(void)2674 void write_popup_code(void) {
2675 char *border_color = "#000000";
2676 char *background_color = "#ffffcc";
2677 int border = 1;
2678 int padding = 3;
2679 int x_offset = 3;
2680 int y_offset = 3;
2681
2682 printf("<SCRIPT LANGUAGE='JavaScript'>\n");
2683 printf("<!--\n");
2684 printf("// JavaScript popup based on code originally found at http://www.helpmaster.com/htmlhelp/javascript/popjbpopup.htm\n");
2685 printf("function showPopup(text, eventObj){\n");
2686 printf("if(!document.all && document.getElementById)\n");
2687 printf("{ document.all=document.getElementsByTagName(\"*\")}\n");
2688 printf("ieLayer = 'document.all[\\'popup\\']';\n");
2689 printf("nnLayer = 'document.layers[\\'popup\\']';\n");
2690 printf("moLayer = 'document.getElementById(\\'popup\\')';\n");
2691
2692 printf("if(!(document.all||document.layers||document.documentElement)) return;\n");
2693
2694 printf("if(document.all) { document.popup=eval(ieLayer); }\n");
2695 printf("else {\n");
2696 printf(" if (document.documentElement) document.popup=eval(moLayer);\n");
2697 printf(" else document.popup=eval(nnLayer);\n");
2698 printf("}\n");
2699
2700 printf("var table = \"\";\n");
2701
2702 printf("if (document.all||document.documentElement){\n");
2703 printf("table += \"<table bgcolor='%s' border=%d cellpadding=%d cellspacing=0>\";\n", background_color, border, padding);
2704 printf("table += \"<tr><td>\";\n");
2705 printf("table += \"<table cellspacing=0 cellpadding=%d>\";\n", padding);
2706 printf("table += \"<tr><td bgcolor='%s' class='popupText'>\" + text + \"</td></tr>\";\n", background_color);
2707 printf("table += \"</table></td></tr></table>\"\n");
2708 printf("document.popup.innerHTML = table;\n");
2709 printf("document.popup.style.left = (document.all ? eventObj.x : eventObj.layerX) + %d;\n", x_offset);
2710 printf("document.popup.style.top = (document.all ? eventObj.y : eventObj.layerY) + %d;\n", y_offset);
2711 printf("document.popup.style.visibility = \"visible\";\n");
2712 printf("} \n");
2713
2714
2715 printf("else{\n");
2716 printf("table += \"<table cellpadding=%d border=%d cellspacing=0 bordercolor='%s'>\";\n", padding, border, border_color);
2717 printf("table += \"<tr><td bgcolor='%s' class='popupText'>\" + text + \"</td></tr></table>\";\n", background_color);
2718 printf("document.popup.document.open();\n");
2719 printf("document.popup.document.write(table);\n");
2720 printf("document.popup.document.close();\n");
2721
2722 /* set x coordinate */
2723 printf("document.popup.left = eventObj.layerX + %d;\n", x_offset);
2724
2725 /* make sure we don't overlap the right side of the screen */
2726 printf("if(document.popup.left + document.popup.document.width + %d > window.innerWidth) document.popup.left = window.innerWidth - document.popup.document.width - %d - 16;\n", x_offset, x_offset);
2727
2728 /* set y coordinate */
2729 printf("document.popup.top = eventObj.layerY + %d;\n", y_offset);
2730
2731 /* make sure we don't overlap the bottom edge of the screen */
2732 printf("if(document.popup.top + document.popup.document.height + %d > window.innerHeight) document.popup.top = window.innerHeight - document.popup.document.height - %d - 16;\n", y_offset, y_offset);
2733
2734 /* make the popup visible */
2735 printf("document.popup.visibility = \"visible\";\n");
2736 printf("}\n");
2737 printf("}\n");
2738
2739 printf("function hidePopup(){ \n");
2740 printf("if (!(document.all || document.layers || document.documentElement)) return;\n");
2741 printf("if (document.popup == null){ }\n");
2742 printf("else if (document.all||document.documentElement) document.popup.style.visibility = \"hidden\";\n");
2743 printf("else document.popup.visibility = \"hidden\";\n");
2744 printf("document.popup = null;\n");
2745 printf("}\n");
2746 printf("//-->\n");
2747
2748 printf("</SCRIPT>\n");
2749
2750 return;
2751 }
2752
2753
2754
2755
2756 /* write timestamps */
draw_timestamps(void)2757 void draw_timestamps(void) {
2758 int last_timestamp = 0;
2759 archived_state *temp_as;
2760 double start_pixel_ratio;
2761 int start_pixel;
2762
2763 if(mode != CREATE_IMAGE)
2764 return;
2765
2766 /* draw first timestamp */
2767 draw_timestamp(0, t1);
2768 last_timestamp = 0;
2769
2770 for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
2771
2772 if(temp_as->time_stamp < t1 || temp_as->time_stamp > t2)
2773 continue;
2774
2775 start_pixel_ratio = ((double)(temp_as->time_stamp - t1)) / ((double)(t2 - t1));
2776 start_pixel = (int)(start_pixel_ratio * (drawing_width - 1));
2777
2778 /* draw start timestamp if possible */
2779 if((start_pixel > last_timestamp + MIN_TIMESTAMP_SPACING) && (start_pixel < drawing_width - 1 - MIN_TIMESTAMP_SPACING)) {
2780 draw_timestamp(start_pixel, temp_as->time_stamp);
2781 last_timestamp = start_pixel;
2782 }
2783 }
2784
2785 /* draw last timestamp */
2786 draw_timestamp(drawing_width - 1, t2);
2787
2788 return;
2789 }
2790
2791
2792 /* write timestamp below graph */
draw_timestamp(int ts_pixel,time_t ts_time)2793 void draw_timestamp(int ts_pixel, time_t ts_time) {
2794 char temp_buffer[MAX_INPUT_BUFFER];
2795 int string_height;
2796 int string_width;
2797
2798 snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", ctime(&ts_time));
2799 temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
2800 temp_buffer[strlen(temp_buffer) - 1] = '\x0';
2801
2802 string_height = gdFontSmall->h;
2803 string_width = gdFontSmall->w * strlen(temp_buffer);
2804
2805 if(small_image == FALSE)
2806 gdImageStringUp(trends_image, gdFontSmall, ts_pixel + drawing_x_offset - (string_height / 2), drawing_y_offset + drawing_height + string_width + 5, (unsigned char *)temp_buffer, color_black);
2807
2808 /* draw a dashed vertical line at this point */
2809 if(ts_pixel > 0 && ts_pixel < (drawing_width - 1))
2810 draw_dashed_line(ts_pixel + drawing_x_offset, drawing_y_offset, ts_pixel + drawing_x_offset, drawing_y_offset + drawing_height, color_black);
2811
2812 return;
2813 }
2814
2815
2816
2817 /* draw total state times */
draw_time_breakdowns(void)2818 void draw_time_breakdowns(void) {
2819 char temp_buffer[MAX_INPUT_BUFFER];
2820 unsigned long total_time = 0L;
2821 unsigned long total_state_time;
2822 unsigned long time_indeterminate = 0L;
2823
2824 if(mode == CREATE_HTML)
2825 return;
2826
2827 if(small_image == TRUE)
2828 return;
2829
2830 total_time = (unsigned long)(t2 - t1);
2831
2832 if(display_type == DISPLAY_HOST_TRENDS)
2833 total_state_time = time_up + time_down + time_unreachable;
2834 else
2835 total_state_time = time_ok + time_warning + time_unknown + time_critical;
2836
2837 if(total_state_time >= total_time)
2838 time_indeterminate = 0L;
2839 else
2840 time_indeterminate = total_time - total_state_time;
2841
2842
2843 if(display_type == DISPLAY_HOST_TRENDS) {
2844
2845 get_time_breakdown_string(total_time, time_up, "Up", &temp_buffer[0], sizeof(temp_buffer));
2846 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 5, (unsigned char *)temp_buffer, color_darkgreen);
2847 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 2), drawing_y_offset + 5, (unsigned char *)"Up", color_darkgreen);
2848
2849 get_time_breakdown_string(total_time, time_down, "Down", &temp_buffer[0], sizeof(temp_buffer));
2850 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 25, (unsigned char *)temp_buffer, color_red);
2851 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 4), drawing_y_offset + 25, (unsigned char *)"Down", color_red);
2852
2853 get_time_breakdown_string(total_time, time_unreachable, "Unreachable", &temp_buffer[0], sizeof(temp_buffer));
2854 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 45, (unsigned char *)temp_buffer, color_darkred);
2855 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 11), drawing_y_offset + 45, (unsigned char *)"Unreachable", color_darkred);
2856
2857 get_time_breakdown_string(total_time, time_indeterminate, "Indeterminate", &temp_buffer[0], sizeof(temp_buffer));
2858 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 65, (unsigned char *)temp_buffer, color_black);
2859 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 13), drawing_y_offset + 65, (unsigned char *)"Indeterminate", color_black);
2860 }
2861 else {
2862 get_time_breakdown_string(total_time, time_ok, "Ok", &temp_buffer[0], sizeof(temp_buffer));
2863 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 5, (unsigned char *)temp_buffer, color_darkgreen);
2864 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 2), drawing_y_offset + 5, (unsigned char *)"Ok", color_darkgreen);
2865
2866 get_time_breakdown_string(total_time, time_warning, "Warning", &temp_buffer[0], sizeof(temp_buffer));
2867 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 25, (unsigned char *)temp_buffer, color_yellow);
2868 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 7), drawing_y_offset + 25, (unsigned char *)"Warning", color_yellow);
2869
2870 get_time_breakdown_string(total_time, time_unknown, "Unknown", &temp_buffer[0], sizeof(temp_buffer));
2871 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 45, (unsigned char *)temp_buffer, color_orange);
2872 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 7), drawing_y_offset + 45, (unsigned char *)"Unknown", color_orange);
2873
2874 get_time_breakdown_string(total_time, time_critical, "Critical", &temp_buffer[0], sizeof(temp_buffer));
2875 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 65, (unsigned char *)temp_buffer, color_red);
2876 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 8), drawing_y_offset + 65, (unsigned char *)"Critical", color_red);
2877
2878 get_time_breakdown_string(total_time, time_indeterminate, "Indeterminate", &temp_buffer[0], sizeof(temp_buffer));
2879 gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 85, (unsigned char *)temp_buffer, color_black);
2880 gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 13), drawing_y_offset + 85, (unsigned char *)"Indeterminate", color_black);
2881 }
2882
2883 return;
2884 }
2885
2886
get_time_breakdown_string(unsigned long total_time,unsigned long state_time,char * state_string,char * buffer,int buffer_length)2887 void get_time_breakdown_string(unsigned long total_time, unsigned long state_time, char *state_string, char *buffer, int buffer_length) {
2888 int days;
2889 int hours;
2890 int minutes;
2891 int seconds;
2892 double percent_time;
2893
2894 get_time_breakdown(state_time, &days, &hours, &minutes, &seconds);
2895 if(total_time == 0L)
2896 percent_time = 0.0;
2897 else
2898 percent_time = ((double)state_time / total_time) * 100.0;
2899 snprintf(buffer, buffer_length - 1, "%-13s: (%.3f%%) %dd %dh %dm %ds", state_string, percent_time, days, hours, minutes, seconds);
2900 buffer[buffer_length - 1] = '\x0';
2901
2902 return;
2903 }
2904
2905
convert_timeperiod_to_times(int type)2906 void convert_timeperiod_to_times(int type) {
2907 time_t current_time;
2908 struct tm *t;
2909
2910 /* get the current time */
2911 time(¤t_time);
2912
2913 t = localtime(¤t_time);
2914
2915 t->tm_sec = 0;
2916 t->tm_min = 0;
2917 t->tm_hour = 0;
2918 t->tm_isdst = -1;
2919
2920 switch(type) {
2921 case TIMEPERIOD_LAST24HOURS:
2922 t1 = current_time - (60 * 60 * 24);
2923 t2 = current_time;
2924 break;
2925 case TIMEPERIOD_TODAY:
2926 t1 = mktime(t);
2927 t2 = current_time;
2928 break;
2929 case TIMEPERIOD_YESTERDAY:
2930 t1 = (time_t)(mktime(t) - (60 * 60 * 24));
2931 t2 = (time_t)mktime(t);
2932 break;
2933 case TIMEPERIOD_THISWEEK:
2934 t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
2935 t2 = current_time;
2936 break;
2937 case TIMEPERIOD_LASTWEEK:
2938 t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday) - (60 * 60 * 24 * 7));
2939 t2 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
2940 break;
2941 case TIMEPERIOD_THISMONTH:
2942 t->tm_mday = 1;
2943 t1 = mktime(t);
2944 t2 = current_time;
2945 break;
2946 case TIMEPERIOD_LASTMONTH:
2947 t->tm_mday = 1;
2948 t2 = mktime(t);
2949 if(t->tm_mon == 0) {
2950 t->tm_mon = 11;
2951 t->tm_year--;
2952 }
2953 else
2954 t->tm_mon--;
2955 t1 = mktime(t);
2956 break;
2957 case TIMEPERIOD_THISQUARTER:
2958 break;
2959 case TIMEPERIOD_LASTQUARTER:
2960 break;
2961 case TIMEPERIOD_THISYEAR:
2962 t->tm_mon = 0;
2963 t->tm_mday = 1;
2964 t1 = mktime(t);
2965 t2 = current_time;
2966 break;
2967 case TIMEPERIOD_LASTYEAR:
2968 t->tm_mon = 0;
2969 t->tm_mday = 1;
2970 t2 = mktime(t);
2971 t->tm_year--;
2972 t1 = mktime(t);
2973 break;
2974 case TIMEPERIOD_NEXTPROBLEM:
2975 /* Time period will be defined later */
2976 break;
2977 case TIMEPERIOD_LAST7DAYS:
2978 t2 = current_time;
2979 t1 = current_time - (7 * 24 * 60 * 60);
2980 break;
2981 case TIMEPERIOD_LAST31DAYS:
2982 t2 = current_time;
2983 t1 = current_time - (31 * 24 * 60 * 60);
2984 break;
2985 default:
2986 break;
2987 }
2988
2989 return;
2990 }
2991
2992
compute_report_times(void)2993 void compute_report_times(void) {
2994 time_t current_time;
2995 struct tm *st;
2996 struct tm *et;
2997
2998 /* get the current time */
2999 time(¤t_time);
3000
3001 st = localtime(¤t_time);
3002
3003 st->tm_sec = start_second;
3004 st->tm_min = start_minute;
3005 st->tm_hour = start_hour;
3006 st->tm_mday = start_day;
3007 st->tm_mon = start_month - 1;
3008 st->tm_year = start_year - 1900;
3009 st->tm_isdst = -1;
3010
3011 t1 = mktime(st);
3012
3013 et = localtime(¤t_time);
3014
3015 et->tm_sec = end_second;
3016 et->tm_min = end_minute;
3017 et->tm_hour = end_hour;
3018 et->tm_mday = end_day;
3019 et->tm_mon = end_month - 1;
3020 et->tm_year = end_year - 1900;
3021 et->tm_isdst = -1;
3022
3023 t2 = mktime(et);
3024 }
3025
3026
3027
3028 /* draws a dashed line */
draw_dashed_line(int x1,int y1,int x2,int y2,int color)3029 void draw_dashed_line(int x1, int y1, int x2, int y2, int color) {
3030 int styleDashed[12];
3031
3032 styleDashed[0] = color;
3033 styleDashed[1] = color;
3034 styleDashed[2] = gdTransparent;
3035 styleDashed[3] = gdTransparent;
3036 styleDashed[4] = color;
3037 styleDashed[5] = color;
3038 styleDashed[6] = gdTransparent;
3039 styleDashed[7] = gdTransparent;
3040 styleDashed[8] = color;
3041 styleDashed[9] = color;
3042 styleDashed[10] = gdTransparent;
3043 styleDashed[11] = gdTransparent;
3044
3045 /* sets current style to a dashed line */
3046 gdImageSetStyle(trends_image, styleDashed, 12);
3047
3048 /* draws a line (dashed) */
3049 gdImageLine(trends_image, x1, y1, x2, y2, gdStyled);
3050
3051 return;
3052 }
3053
3054
3055 /* draws horizontal grid lines */
draw_horizontal_grid_lines(void)3056 void draw_horizontal_grid_lines(void) {
3057
3058 if(mode == CREATE_HTML)
3059 return;
3060
3061 if(small_image == TRUE)
3062 return;
3063
3064 draw_dashed_line(drawing_x_offset, drawing_y_offset + 10, drawing_x_offset + drawing_width, drawing_y_offset + 10, color_black);
3065 draw_dashed_line(drawing_x_offset, drawing_y_offset + 30, drawing_x_offset + drawing_width, drawing_y_offset + 30, color_black);
3066 draw_dashed_line(drawing_x_offset, drawing_y_offset + 50, drawing_x_offset + drawing_width, drawing_y_offset + 50, color_black);
3067 if(display_type == DISPLAY_SERVICE_TRENDS)
3068 draw_dashed_line(drawing_x_offset, drawing_y_offset + 70, drawing_x_offset + drawing_width, drawing_y_offset + 70, color_black);
3069
3070 return;
3071 }
3072