nagios4/xdata/xrddefault.c

1719 lines
72 KiB
C

/*****************************************************************************
*
* XRDDEFAULT.C - Default external state retention routines for Nagios
*
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/sretention.h"
#include "../include/comments.h"
#include "../include/downtime.h"
#include "xrddefault.h"
/******************************************************************/
/********************* INIT/CLEANUP FUNCTIONS *********************/
/******************************************************************/
/* initialize retention data */
int xrddefault_initialize_retention_data(const char *cfgfile) {
nagios_macros *mac;
/* initialize locations if necessary */
if(retention_file == NULL)
retention_file = (char *)strdup(DEFAULT_RETENTION_FILE);
/* make sure we have everything */
if(retention_file == NULL)
return ERROR;
mac = get_global_macros();
/* save the retention file macro */
my_free(mac->x[MACRO_RETENTIONDATAFILE]);
mac->x[MACRO_RETENTIONDATAFILE] = retention_file;
if((mac->x[MACRO_RETENTIONDATAFILE] = (char *)strdup(retention_file)))
strip(mac->x[MACRO_RETENTIONDATAFILE]);
return OK;
}
/* cleanup retention data before terminating */
int xrddefault_cleanup_retention_data(void) {
/* free memory */
my_free(retention_file);
return OK;
}
/******************************************************************/
/**************** DEFAULT STATE OUTPUT FUNCTION *******************/
/******************************************************************/
int xrddefault_save_state_information(void) {
char *tmp_file = NULL;
customvariablesmember *temp_customvariablesmember = NULL;
time_t current_time = 0L;
int result = OK;
FILE *fp = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
contact *temp_contact = NULL;
nagios_comment *temp_comment = NULL;
scheduled_downtime *temp_downtime = NULL;
int x = 0;
int fd = 0;
unsigned long host_attribute_mask = 0L;
unsigned long service_attribute_mask = 0L;
unsigned long contact_attribute_mask = 0L;
unsigned long contact_host_attribute_mask = 0L;
unsigned long contact_service_attribute_mask = 0L;
unsigned long process_host_attribute_mask = 0L;
unsigned long process_service_attribute_mask = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "xrddefault_save_state_information()\n");
/* make sure we have everything */
if(retention_file == NULL || temp_file == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: We don't have the required file names to store retention data!\n");
return ERROR;
}
/* open a safe temp file for output */
asprintf(&tmp_file, "%sXXXXXX", temp_file);
if(tmp_file == NULL)
return ERROR;
if((fd = mkstemp(tmp_file)) == -1)
return ERROR;
log_debug_info(DEBUGL_RETENTIONDATA, 2, "Writing retention data to temp file '%s'\n", tmp_file);
fp = (FILE *)fdopen(fd, "w");
if(fp == NULL) {
close(fd);
unlink(tmp_file);
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not open temp state retention file '%s' for writing!\n", tmp_file);
my_free(tmp_file);
return ERROR;
}
/* what attributes should be masked out? */
/* NOTE: host/service/contact-specific values may be added in the future, but for now we only have global masks */
process_host_attribute_mask = retained_process_host_attribute_mask;
process_service_attribute_mask = retained_process_service_attribute_mask;
host_attribute_mask = retained_host_attribute_mask;
service_attribute_mask = retained_service_attribute_mask;
contact_host_attribute_mask = retained_contact_host_attribute_mask;
contact_service_attribute_mask = retained_contact_service_attribute_mask;
/* write version info to status file */
fprintf(fp, "########################################\n");
fprintf(fp, "# NAGIOS STATE RETENTION FILE\n");
fprintf(fp, "#\n");
fprintf(fp, "# THIS FILE IS AUTOMATICALLY GENERATED\n");
fprintf(fp, "# BY NAGIOS. DO NOT MODIFY THIS FILE!\n");
fprintf(fp, "########################################\n");
time(&current_time);
/* write file info */
fprintf(fp, "info {\n");
fprintf(fp, "created=%llu\n", (unsigned long long)current_time);
fprintf(fp, "version=%s\n", PROGRAM_VERSION);
fprintf(fp, "last_update_check=%llu\n", (unsigned long long)last_update_check);
fprintf(fp, "update_available=%d\n", update_available);
fprintf(fp, "update_uid=%lu\n", update_uid);
fprintf(fp, "last_version=%s\n", (last_program_version == NULL) ? "" : last_program_version);
fprintf(fp, "new_version=%s\n", (new_program_version == NULL) ? "" : new_program_version);
fprintf(fp, "}\n");
/* save program state information */
fprintf(fp, "program {\n");
fprintf(fp, "modified_host_attributes=%lu\n", (modified_host_process_attributes & ~process_host_attribute_mask));
fprintf(fp, "modified_service_attributes=%lu\n", (modified_service_process_attributes & ~process_service_attribute_mask));
fprintf(fp, "enable_notifications=%d\n", enable_notifications);
fprintf(fp, "active_service_checks_enabled=%d\n", execute_service_checks);
fprintf(fp, "passive_service_checks_enabled=%d\n", accept_passive_service_checks);
fprintf(fp, "active_host_checks_enabled=%d\n", execute_host_checks);
fprintf(fp, "passive_host_checks_enabled=%d\n", accept_passive_host_checks);
fprintf(fp, "enable_event_handlers=%d\n", enable_event_handlers);
fprintf(fp, "obsess_over_services=%d\n", obsess_over_services);
fprintf(fp, "obsess_over_hosts=%d\n", obsess_over_hosts);
fprintf(fp, "check_service_freshness=%d\n", check_service_freshness);
fprintf(fp, "check_host_freshness=%d\n", check_host_freshness);
fprintf(fp, "enable_flap_detection=%d\n", enable_flap_detection);
fprintf(fp, "process_performance_data=%d\n", process_performance_data);
fprintf(fp, "global_host_event_handler=%s\n", (global_host_event_handler == NULL) ? "" : global_host_event_handler);
fprintf(fp, "global_service_event_handler=%s\n", (global_service_event_handler == NULL) ? "" : global_service_event_handler);
fprintf(fp, "next_comment_id=%lu\n", next_comment_id);
fprintf(fp, "next_downtime_id=%lu\n", next_downtime_id);
fprintf(fp, "next_event_id=%lu\n", next_event_id);
fprintf(fp, "next_problem_id=%lu\n", next_problem_id);
fprintf(fp, "next_notification_id=%lu\n", next_notification_id);
fprintf(fp, "}\n");
/* save host state information */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
fprintf(fp, "host {\n");
fprintf(fp, "host_name=%s\n", temp_host->name);
fprintf(fp, "modified_attributes=%lu\n", (temp_host->modified_attributes & ~host_attribute_mask));
fprintf(fp, "check_command=%s\n", (temp_host->check_command == NULL) ? "" : temp_host->check_command);
fprintf(fp, "check_period=%s\n", (temp_host->check_period == NULL) ? "" : temp_host->check_period);
fprintf(fp, "notification_period=%s\n", (temp_host->notification_period == NULL) ? "" : temp_host->notification_period);
fprintf(fp, "event_handler=%s\n", (temp_host->event_handler == NULL) ? "" : temp_host->event_handler);
fprintf(fp, "has_been_checked=%d\n", temp_host->has_been_checked);
fprintf(fp, "check_execution_time=%.3f\n", temp_host->execution_time);
fprintf(fp, "check_latency=%.3f\n", temp_host->latency);
fprintf(fp, "check_type=%d\n", temp_host->check_type);
fprintf(fp, "current_state=%d\n", temp_host->current_state);
fprintf(fp, "last_state=%d\n", temp_host->last_state);
fprintf(fp, "last_hard_state=%d\n", temp_host->last_hard_state);
fprintf(fp, "last_event_id=%lu\n", temp_host->last_event_id);
fprintf(fp, "current_event_id=%lu\n", temp_host->current_event_id);
fprintf(fp, "current_problem_id=%lu\n", temp_host->current_problem_id);
fprintf(fp, "last_problem_id=%lu\n", temp_host->last_problem_id);
fprintf(fp, "plugin_output=%s\n", (temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output);
fprintf(fp, "long_plugin_output=%s\n", (temp_host->long_plugin_output == NULL) ? "" : temp_host->long_plugin_output);
fprintf(fp, "performance_data=%s\n", (temp_host->perf_data == NULL) ? "" : temp_host->perf_data);
fprintf(fp, "last_check=%llu\n", (unsigned long long)temp_host->last_check);
fprintf(fp, "next_check=%llu\n", (unsigned long long)temp_host->next_check);
fprintf(fp, "check_options=%d\n", temp_host->check_options);
fprintf(fp, "current_attempt=%d\n", temp_host->current_attempt);
fprintf(fp, "max_attempts=%d\n", temp_host->max_attempts);
fprintf(fp, "check_interval=%f\n", temp_host->check_interval);
fprintf(fp, "retry_interval=%f\n", temp_host->retry_interval);
fprintf(fp, "state_type=%d\n", temp_host->state_type);
fprintf(fp, "last_state_change=%llu\n", (unsigned long long)temp_host->last_state_change);
fprintf(fp, "last_hard_state_change=%llu\n", (unsigned long long)temp_host->last_hard_state_change);
fprintf(fp, "last_time_up=%llu\n", (unsigned long long)temp_host->last_time_up);
fprintf(fp, "last_time_down=%llu\n", (unsigned long long)temp_host->last_time_down);
fprintf(fp, "last_time_unreachable=%llu\n", (unsigned long long)temp_host->last_time_unreachable);
fprintf(fp, "notified_on_down=%d\n", flag_isset(temp_host->notified_on, OPT_DOWN));
fprintf(fp, "notified_on_unreachable=%d\n", flag_isset(temp_host->notified_on, OPT_UNREACHABLE));
fprintf(fp, "last_notification=%llu\n", (unsigned long long)temp_host->last_notification);
fprintf(fp, "current_notification_number=%d\n", temp_host->current_notification_number);
fprintf(fp, "current_notification_id=%lu\n", temp_host->current_notification_id);
fprintf(fp, "notifications_enabled=%d\n", temp_host->notifications_enabled);
fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_host->problem_has_been_acknowledged);
fprintf(fp, "acknowledgement_type=%d\n", temp_host->acknowledgement_type);
fprintf(fp, "active_checks_enabled=%d\n", temp_host->checks_enabled);
fprintf(fp, "passive_checks_enabled=%d\n", temp_host->accept_passive_checks);
fprintf(fp, "event_handler_enabled=%d\n", temp_host->event_handler_enabled);
fprintf(fp, "flap_detection_enabled=%d\n", temp_host->flap_detection_enabled);
fprintf(fp, "process_performance_data=%d\n", temp_host->process_performance_data);
fprintf(fp, "obsess=%d\n", temp_host->obsess);
fprintf(fp, "is_flapping=%d\n", temp_host->is_flapping);
fprintf(fp, "percent_state_change=%.2f\n", temp_host->percent_state_change);
fprintf(fp, "check_flapping_recovery_notification=%d\n", temp_host->check_flapping_recovery_notification);
fprintf(fp, "flapping_comment_id=%lu\n", temp_host->flapping_comment_id);
fprintf(fp, "state_history=");
for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++)
fprintf(fp, "%s%d", (x > 0) ? "," : "", temp_host->state_history[(x + temp_host->state_history_index) % MAX_STATE_HISTORY_ENTRIES]);
fprintf(fp, "\n");
/* custom variables */
for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(temp_customvariablesmember->variable_name)
fprintf(fp, "_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
}
fprintf(fp, "}\n");
}
/* save service state information */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
fprintf(fp, "service {\n");
fprintf(fp, "host_name=%s\n", temp_service->host_name);
fprintf(fp, "service_description=%s\n", temp_service->description);
fprintf(fp, "modified_attributes=%lu\n", (temp_service->modified_attributes & ~service_attribute_mask));
fprintf(fp, "check_command=%s\n", (temp_service->check_command == NULL) ? "" : temp_service->check_command);
fprintf(fp, "check_period=%s\n", (temp_service->check_period == NULL) ? "" : temp_service->check_period);
fprintf(fp, "notification_period=%s\n", (temp_service->notification_period == NULL) ? "" : temp_service->notification_period);
fprintf(fp, "event_handler=%s\n", (temp_service->event_handler == NULL) ? "" : temp_service->event_handler);
fprintf(fp, "has_been_checked=%d\n", temp_service->has_been_checked);
fprintf(fp, "check_execution_time=%.3f\n", temp_service->execution_time);
fprintf(fp, "check_latency=%.3f\n", temp_service->latency);
fprintf(fp, "check_type=%d\n", temp_service->check_type);
fprintf(fp, "current_state=%d\n", temp_service->current_state);
fprintf(fp, "last_state=%d\n", temp_service->last_state);
fprintf(fp, "last_hard_state=%d\n", temp_service->last_hard_state);
fprintf(fp, "last_event_id=%lu\n", temp_service->last_event_id);
fprintf(fp, "current_event_id=%lu\n", temp_service->current_event_id);
fprintf(fp, "current_problem_id=%lu\n", temp_service->current_problem_id);
fprintf(fp, "last_problem_id=%lu\n", temp_service->last_problem_id);
fprintf(fp, "current_attempt=%d\n", temp_service->current_attempt);
fprintf(fp, "max_attempts=%d\n", temp_service->max_attempts);
fprintf(fp, "check_interval=%f\n", temp_service->check_interval);
fprintf(fp, "retry_interval=%f\n", temp_service->retry_interval);
fprintf(fp, "state_type=%d\n", temp_service->state_type);
fprintf(fp, "last_state_change=%llu\n", (unsigned long long)temp_service->last_state_change);
fprintf(fp, "last_hard_state_change=%llu\n", (unsigned long long)temp_service->last_hard_state_change);
fprintf(fp, "last_time_ok=%llu\n", (unsigned long long)temp_service->last_time_ok);
fprintf(fp, "last_time_warning=%llu\n", (unsigned long long)temp_service->last_time_warning);
fprintf(fp, "last_time_unknown=%llu\n", (unsigned long long)temp_service->last_time_unknown);
fprintf(fp, "last_time_critical=%llu\n", (unsigned long long)temp_service->last_time_critical);
fprintf(fp, "plugin_output=%s\n", (temp_service->plugin_output == NULL) ? "" : temp_service->plugin_output);
fprintf(fp, "long_plugin_output=%s\n", (temp_service->long_plugin_output == NULL) ? "" : temp_service->long_plugin_output);
fprintf(fp, "performance_data=%s\n", (temp_service->perf_data == NULL) ? "" : temp_service->perf_data);
fprintf(fp, "last_check=%llu\n", (unsigned long long)temp_service->last_check);
fprintf(fp, "next_check=%llu\n", (unsigned long long)temp_service->next_check);
fprintf(fp, "check_options=%d\n", temp_service->check_options);
fprintf(fp, "notified_on_unknown=%d\n", flag_isset(temp_service->notified_on, OPT_UNKNOWN));
fprintf(fp, "notified_on_warning=%d\n", flag_isset(temp_service->notified_on, OPT_WARNING));
fprintf(fp, "notified_on_critical=%d\n", flag_isset(temp_service->notified_on, OPT_CRITICAL));
fprintf(fp, "current_notification_number=%d\n", temp_service->current_notification_number);
fprintf(fp, "current_notification_id=%lu\n", temp_service->current_notification_id);
fprintf(fp, "last_notification=%llu\n", (unsigned long long)temp_service->last_notification);
fprintf(fp, "notifications_enabled=%d\n", temp_service->notifications_enabled);
fprintf(fp, "active_checks_enabled=%d\n", temp_service->checks_enabled);
fprintf(fp, "passive_checks_enabled=%d\n", temp_service->accept_passive_checks);
fprintf(fp, "event_handler_enabled=%d\n", temp_service->event_handler_enabled);
fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_service->problem_has_been_acknowledged);
fprintf(fp, "acknowledgement_type=%d\n", temp_service->acknowledgement_type);
fprintf(fp, "flap_detection_enabled=%d\n", temp_service->flap_detection_enabled);
fprintf(fp, "process_performance_data=%d\n", temp_service->process_performance_data);
fprintf(fp, "obsess=%d\n", temp_service->obsess);
fprintf(fp, "is_flapping=%d\n", temp_service->is_flapping);
fprintf(fp, "percent_state_change=%.2f\n", temp_service->percent_state_change);
fprintf(fp, "check_flapping_recovery_notification=%d\n", temp_service->check_flapping_recovery_notification);
fprintf(fp, "flapping_comment_id=%lu\n", temp_service->flapping_comment_id);
fprintf(fp, "state_history=");
for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++)
fprintf(fp, "%s%d", (x > 0) ? "," : "", temp_service->state_history[(x + temp_service->state_history_index) % MAX_STATE_HISTORY_ENTRIES]);
fprintf(fp, "\n");
/* custom variables */
for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(temp_customvariablesmember->variable_name)
fprintf(fp, "_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
}
fprintf(fp, "}\n");
}
/* save contact state information */
for(temp_contact = contact_list; temp_contact != NULL; temp_contact = temp_contact->next) {
fprintf(fp, "contact {\n");
fprintf(fp, "contact_name=%s\n", temp_contact->name);
fprintf(fp, "modified_attributes=%lu\n", (temp_contact->modified_attributes & ~contact_attribute_mask));
fprintf(fp, "modified_host_attributes=%lu\n", (temp_contact->modified_host_attributes & ~contact_host_attribute_mask));
fprintf(fp, "modified_service_attributes=%lu\n", (temp_contact->modified_service_attributes & ~contact_service_attribute_mask));
fprintf(fp, "host_notification_period=%s\n", (temp_contact->host_notification_period == NULL) ? "" : temp_contact->host_notification_period);
fprintf(fp, "service_notification_period=%s\n", (temp_contact->service_notification_period == NULL) ? "" : temp_contact->service_notification_period);
fprintf(fp, "last_host_notification=%llu\n", (unsigned long long)temp_contact->last_host_notification);
fprintf(fp, "last_service_notification=%llu\n", (unsigned long long)temp_contact->last_service_notification);
fprintf(fp, "host_notifications_enabled=%d\n", temp_contact->host_notifications_enabled);
fprintf(fp, "service_notifications_enabled=%d\n", temp_contact->service_notifications_enabled);
/* custom variables */
for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(temp_customvariablesmember->variable_name)
fprintf(fp, "_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
}
fprintf(fp, "}\n");
}
/* save all comments */
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) {
if(temp_comment->comment_type == HOST_COMMENT)
fprintf(fp, "hostcomment {\n");
else
fprintf(fp, "servicecomment {\n");
fprintf(fp, "host_name=%s\n", temp_comment->host_name);
if(temp_comment->comment_type == SERVICE_COMMENT)
fprintf(fp, "service_description=%s\n", temp_comment->service_description);
fprintf(fp, "entry_type=%d\n", temp_comment->entry_type);
fprintf(fp, "comment_id=%lu\n", temp_comment->comment_id);
fprintf(fp, "source=%d\n", temp_comment->source);
fprintf(fp, "persistent=%d\n", temp_comment->persistent);
fprintf(fp, "entry_time=%llu\n", (unsigned long long)temp_comment->entry_time);
fprintf(fp, "expires=%d\n", temp_comment->expires);
fprintf(fp, "expire_time=%llu\n", (unsigned long long)temp_comment->expire_time);
fprintf(fp, "author=%s\n", temp_comment->author);
fprintf(fp, "comment_data=%s\n", temp_comment->comment_data);
fprintf(fp, "}\n");
}
/* save all downtime */
for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) {
if(temp_downtime->type == HOST_DOWNTIME)
fprintf(fp, "hostdowntime {\n");
else
fprintf(fp, "servicedowntime {\n");
fprintf(fp, "host_name=%s\n", temp_downtime->host_name);
if(temp_downtime->type == SERVICE_DOWNTIME)
fprintf(fp, "service_description=%s\n", temp_downtime->service_description);
fprintf(fp, "comment_id=%lu\n", temp_downtime->comment_id);
fprintf(fp, "downtime_id=%lu\n", temp_downtime->downtime_id);
fprintf(fp, "entry_time=%llu\n", (unsigned long long)temp_downtime->entry_time);
fprintf(fp, "start_time=%llu\n", (unsigned long long)temp_downtime->start_time);
fprintf(fp, "flex_downtime_start=%llu\n", (unsigned long long)temp_downtime->flex_downtime_start);
fprintf(fp, "end_time=%llu\n", (unsigned long long)temp_downtime->end_time);
fprintf(fp, "triggered_by=%lu\n", temp_downtime->triggered_by);
fprintf(fp, "fixed=%d\n", temp_downtime->fixed);
fprintf(fp, "duration=%lu\n", temp_downtime->duration);
fprintf(fp, "is_in_effect=%d\n", temp_downtime->is_in_effect);
fprintf(fp, "start_notification_sent=%d\n", temp_downtime->start_notification_sent);
fprintf(fp, "author=%s\n", temp_downtime->author);
fprintf(fp, "comment=%s\n", temp_downtime->comment);
fprintf(fp, "}\n");
}
fflush(fp);
fsync(fd);
result = fclose(fp);
/* save/close was successful */
if(result == 0) {
result = OK;
/* move the temp file to the retention file (overwrite the old retention file) */
if(my_rename(tmp_file, retention_file)) {
unlink(tmp_file);
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to update retention file '%s': %s", retention_file, strerror(errno));
result = ERROR;
}
}
/* a problem occurred saving the file */
else {
result = ERROR;
/* remove temp file and log an error */
unlink(tmp_file);
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to save retention file: %s", strerror(errno));
}
/* free memory */
my_free(tmp_file);
return result;
}
/******************************************************************/
/***************** DEFAULT STATE INPUT FUNCTION *******************/
/******************************************************************/
int xrddefault_read_state_information(void) {
char *input = NULL;
char *inputbuf = NULL;
char *temp_ptr = NULL;
mmapfile *thefile;
char *host_name = NULL;
char *service_description = NULL;
char *contact_name = NULL;
char *author = NULL;
char *comment_data = NULL;
int data_type = XRDDEFAULT_NO_DATA;
int x = 0;
host *temp_host = NULL;
service *temp_service = NULL;
contact *temp_contact = NULL;
command *temp_command = NULL;
timeperiod *temp_timeperiod = NULL;
customvariablesmember *temp_customvariablesmember = NULL;
char *customvarname = NULL;
char *var = NULL;
char *val = NULL;
char *tempval = NULL;
char *ch = NULL;
unsigned long comment_id = 0;
int persistent = FALSE;
int expires = FALSE;
time_t expire_time = 0L;
int entry_type = USER_COMMENT;
int source = COMMENTSOURCE_INTERNAL;
time_t entry_time = 0L;
time_t creation_time;
time_t current_time;
int scheduling_info_is_ok = FALSE;
unsigned long downtime_id = 0;
time_t start_time = 0L;
time_t flex_downtime_start = ( time_t)0;
time_t end_time = 0L;
int fixed = FALSE;
unsigned long triggered_by = 0;
unsigned long duration = 0L;
unsigned long host_attribute_mask = 0L;
unsigned long service_attribute_mask = 0L;
unsigned long contact_attribute_mask = 0L;
unsigned long contact_host_attribute_mask = 0L;
unsigned long contact_service_attribute_mask = 0L;
unsigned long process_host_attribute_mask = 0L;
unsigned long process_service_attribute_mask = 0L;
int remove_comment = FALSE;
int ack = FALSE;
int was_flapping = FALSE;
int allow_flapstart_notification = TRUE;
struct timeval tv[2];
double runtime[2];
int found_directive = FALSE;
int is_in_effect = FALSE;
int start_notification_sent = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "xrddefault_read_state_information() start\n");
/* make sure we have what we need */
if(retention_file == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: We don't have a filename for retention data!\n");
return ERROR;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[0], NULL);
/* open the retention file for reading */
if((thefile = mmap_fopen(retention_file)) == NULL)
return ERROR;
/* what attributes should be masked out? */
/* NOTE: host/service/contact-specific values may be added in the future, but for now we only have global masks */
process_host_attribute_mask = retained_process_host_attribute_mask;
process_service_attribute_mask = retained_process_host_attribute_mask;
host_attribute_mask = retained_host_attribute_mask;
service_attribute_mask = retained_host_attribute_mask;
contact_host_attribute_mask = retained_contact_host_attribute_mask;
contact_service_attribute_mask = retained_contact_service_attribute_mask;
/* Big speedup when reading retention.dat in bulk */
defer_downtime_sorting = 1;
defer_comment_sorting = 1;
/* read all lines in the retention file */
while(1) {
/* free memory */
my_free(inputbuf);
/* read the next line */
if((inputbuf = mmap_fgets(thefile)) == NULL)
break;
input = inputbuf;
/* far better than strip()ing */
if(input[0] == '\t')
input++;
strip(input);
if(!strcmp(input, "service {"))
data_type = XRDDEFAULT_SERVICESTATUS_DATA;
else if(!strcmp(input, "host {"))
data_type = XRDDEFAULT_HOSTSTATUS_DATA;
else if(!strcmp(input, "contact {"))
data_type = XRDDEFAULT_CONTACTSTATUS_DATA;
else if(!strcmp(input, "hostcomment {"))
data_type = XRDDEFAULT_HOSTCOMMENT_DATA;
else if(!strcmp(input, "servicecomment {"))
data_type = XRDDEFAULT_SERVICECOMMENT_DATA;
else if(!strcmp(input, "hostdowntime {"))
data_type = XRDDEFAULT_HOSTDOWNTIME_DATA;
else if(!strcmp(input, "servicedowntime {"))
data_type = XRDDEFAULT_SERVICEDOWNTIME_DATA;
else if(!strcmp(input, "info {"))
data_type = XRDDEFAULT_INFO_DATA;
else if(!strcmp(input, "program {"))
data_type = XRDDEFAULT_PROGRAMSTATUS_DATA;
else if(!strcmp(input, "}")) {
switch(data_type) {
case XRDDEFAULT_INFO_DATA:
break;
case XRDDEFAULT_PROGRAMSTATUS_DATA:
/* adjust modified attributes if necessary */
if(use_retained_program_state == FALSE) {
modified_host_process_attributes = MODATTR_NONE;
modified_service_process_attributes = MODATTR_NONE;
}
break;
case XRDDEFAULT_HOSTSTATUS_DATA:
if(temp_host != NULL) {
/* adjust modified attributes if necessary */
if(temp_host->retain_nonstatus_information == FALSE)
temp_host->modified_attributes = MODATTR_NONE;
/* adjust modified attributes if no custom variables have been changed */
if(temp_host->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(temp_customvariablesmember->has_been_modified == TRUE)
break;
}
if(temp_customvariablesmember == NULL)
temp_host->modified_attributes -= MODATTR_CUSTOM_VARIABLE;
}
/* calculate next possible notification time */
if(temp_host->current_state != HOST_UP && temp_host->last_notification != (time_t)0)
temp_host->next_notification = get_next_host_notification_time(temp_host, temp_host->last_notification);
/* ADDED 01/23/2009 adjust current check attempts if host in hard problem state (max attempts may have changed in config since restart) */
if(temp_host->current_state != HOST_UP && temp_host->state_type == HARD_STATE)
temp_host->current_attempt = temp_host->max_attempts;
/* ADDED 02/20/08 assume same flapping state if large install tweaks enabled */
if(use_large_installation_tweaks == TRUE) {
temp_host->is_flapping = was_flapping;
}
/* else use normal startup flap detection logic */
else {
/* host was flapping before program started */
/* 11/10/07 don't allow flapping notifications to go out */
if(was_flapping == TRUE)
allow_flapstart_notification = FALSE;
else
/* flapstart notifications are okay */
allow_flapstart_notification = TRUE;
/* check for flapping */
check_for_host_flapping(temp_host, FALSE, FALSE, allow_flapstart_notification);
/* host was flapping before and isn't now, so clear recovery check variable if host isn't flapping now */
if(was_flapping == TRUE && temp_host->is_flapping == FALSE)
temp_host->check_flapping_recovery_notification = FALSE;
}
/* handle new vars added in 2.x */
if(temp_host->last_hard_state_change == (time_t)0)
temp_host->last_hard_state_change = temp_host->last_state_change;
/* update host status */
update_host_status(temp_host, FALSE);
}
/* reset vars */
was_flapping = FALSE;
allow_flapstart_notification = TRUE;
my_free(host_name);
host_name = NULL;
temp_host = NULL;
break;
case XRDDEFAULT_SERVICESTATUS_DATA:
if(temp_service != NULL) {
/* adjust modified attributes if necessary */
if(temp_service->retain_nonstatus_information == FALSE)
temp_service->modified_attributes = MODATTR_NONE;
/* adjust modified attributes if no custom variables have been changed */
if(temp_service->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(temp_customvariablesmember->has_been_modified == TRUE)
break;
}
if(temp_customvariablesmember == NULL)
temp_service->modified_attributes -= MODATTR_CUSTOM_VARIABLE;
}
/* calculate next possible notification time */
if(temp_service->current_state != STATE_OK && temp_service->last_notification != (time_t)0)
temp_service->next_notification = get_next_service_notification_time(temp_service, temp_service->last_notification);
/* fix old vars */
if(temp_service->has_been_checked == FALSE && temp_service->state_type == SOFT_STATE)
temp_service->state_type = HARD_STATE;
/* ADDED 01/23/2009 adjust current check attempt if service is in hard problem state (max attempts may have changed in config since restart) */
if(temp_service->current_state != STATE_OK && temp_service->state_type == HARD_STATE)
temp_service->current_attempt = temp_service->max_attempts;
/* ADDED 02/20/08 assume same flapping state if large install tweaks enabled */
if(use_large_installation_tweaks == TRUE) {
temp_service->is_flapping = was_flapping;
}
/* else use normal startup flap detection logic */
else {
/* service was flapping before program started */
/* 11/10/07 don't allow flapping notifications to go out */
if(was_flapping == TRUE)
allow_flapstart_notification = FALSE;
else
/* flapstart notifications are okay */
allow_flapstart_notification = TRUE;
/* check for flapping */
check_for_service_flapping(temp_service, FALSE, allow_flapstart_notification);
/* service was flapping before and isn't now, so clear recovery check variable if service isn't flapping now */
if(was_flapping == TRUE && temp_service->is_flapping == FALSE)
temp_service->check_flapping_recovery_notification = FALSE;
}
/* handle new vars added in 2.x */
if(temp_service->last_hard_state_change == (time_t)0)
temp_service->last_hard_state_change = temp_service->last_state_change;
/* update service status */
update_service_status(temp_service, FALSE);
}
/* reset vars */
was_flapping = FALSE;
allow_flapstart_notification = TRUE;
my_free(host_name);
my_free(service_description);
temp_service = NULL;
break;
case XRDDEFAULT_CONTACTSTATUS_DATA:
if(temp_contact != NULL) {
/* adjust modified attributes if necessary */
if(temp_contact->retain_nonstatus_information == FALSE)
temp_contact->modified_attributes = MODATTR_NONE;
/* adjust modified attributes if no custom variables have been changed */
if(temp_contact->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(temp_customvariablesmember->has_been_modified == TRUE)
break;
}
if(temp_customvariablesmember == NULL)
temp_contact->modified_attributes -= MODATTR_CUSTOM_VARIABLE;
}
/* update contact status */
update_contact_status(temp_contact, FALSE);
}
my_free(contact_name);
temp_contact = NULL;
break;
case XRDDEFAULT_HOSTCOMMENT_DATA:
case XRDDEFAULT_SERVICECOMMENT_DATA:
/* add the comment */
add_comment((data_type == XRDDEFAULT_HOSTCOMMENT_DATA) ? HOST_COMMENT : SERVICE_COMMENT, entry_type, host_name, service_description, entry_time, author, comment_data, comment_id, persistent, expires, expire_time, source);
/* delete the comment if necessary */
/* it seems a bit backwards to add and then immediately delete the comment, but its necessary to track comment deletions in the event broker */
remove_comment = FALSE;
/* host no longer exists */
if((temp_host = find_host(host_name)) == NULL)
remove_comment = TRUE;
/* service no longer exists */
else if(data_type == XRDDEFAULT_SERVICECOMMENT_DATA && (temp_service = find_service(host_name, service_description)) == NULL)
remove_comment = TRUE;
/* acknowledgement comments get deleted if they're not persistent and the original problem is no longer acknowledged */
else if(entry_type == ACKNOWLEDGEMENT_COMMENT) {
ack = FALSE;
if(data_type == XRDDEFAULT_HOSTCOMMENT_DATA)
ack = temp_host->problem_has_been_acknowledged;
else
ack = temp_service->problem_has_been_acknowledged;
if(ack == FALSE && persistent == FALSE)
remove_comment = TRUE;
}
/* non-persistent comments don't last past restarts UNLESS they're acks (see above) */
else if(persistent == FALSE && (sigrestart == FALSE || entry_type == DOWNTIME_COMMENT))
remove_comment = TRUE;
if(remove_comment == TRUE)
delete_comment((data_type == XRDDEFAULT_HOSTCOMMENT_DATA) ? HOST_COMMENT : SERVICE_COMMENT, comment_id);
/* free temp memory */
my_free(host_name);
my_free(service_description);
my_free(author);
my_free(comment_data);
/* reset defaults */
entry_type = USER_COMMENT;
comment_id = 0;
source = COMMENTSOURCE_INTERNAL;
persistent = FALSE;
entry_time = 0L;
expires = FALSE;
expire_time = 0L;
break;
case XRDDEFAULT_HOSTDOWNTIME_DATA:
case XRDDEFAULT_SERVICEDOWNTIME_DATA:
/* add the downtime */
if(data_type == XRDDEFAULT_HOSTDOWNTIME_DATA)
add_host_downtime(host_name, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent);
else
add_service_downtime(host_name, service_description, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent);
/* must register the downtime with Nagios so it can schedule it, add comments, etc. */
register_downtime((data_type == XRDDEFAULT_HOSTDOWNTIME_DATA) ? HOST_DOWNTIME : SERVICE_DOWNTIME, downtime_id);
/* free temp memory */
my_free(host_name);
my_free(service_description);
my_free(author);
my_free(comment_data);
/* reset defaults */
downtime_id = 0;
entry_time = 0L;
start_time = 0L;
flex_downtime_start = ( time_t)0;
end_time = 0L;
fixed = FALSE;
triggered_by = 0;
duration = 0L;
break;
default:
break;
}
data_type = XRDDEFAULT_NO_DATA;
}
else if(data_type != XRDDEFAULT_NO_DATA) {
/* slightly faster than strtok () */
var = input;
if((val = strchr(input, '=')) == NULL)
continue;
val[0] = '\x0';
val++;
found_directive = TRUE;
switch(data_type) {
case XRDDEFAULT_INFO_DATA:
if(!strcmp(var, "created")) {
creation_time = strtoul(val, NULL, 10);
time(&current_time);
if(current_time - creation_time < retention_scheduling_horizon)
scheduling_info_is_ok = TRUE;
else
scheduling_info_is_ok = FALSE;
last_program_stop = creation_time;
}
else if(!strcmp(var, "version")) {
/* initialize last version in case we're reading a pre-3.1.0 retention file */
if(last_program_version == NULL)
last_program_version = (char *)strdup(val);
}
else if(!strcmp(var, "last_update_check"))
last_update_check = strtoul(val, NULL, 10);
else if(!strcmp(var, "update_available"))
update_available = atoi(val);
else if(!strcmp(var, "update_uid"))
update_uid = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_version")) {
if(last_program_version)
my_free(last_program_version);
last_program_version = (char *)strdup(val);
}
else if(!strcmp(var, "new_version"))
new_program_version = (char *)strdup(val);
break;
case XRDDEFAULT_PROGRAMSTATUS_DATA:
if(!strcmp(var, "modified_host_attributes")) {
modified_host_process_attributes = strtoul(val, NULL, 10);
/* mask out attributes we don't want to retain */
modified_host_process_attributes &= ~process_host_attribute_mask;
}
else if(!strcmp(var, "modified_service_attributes")) {
modified_service_process_attributes = strtoul(val, NULL, 10);
/* mask out attributes we don't want to retain */
modified_service_process_attributes &= ~process_service_attribute_mask;
}
if(use_retained_program_state == TRUE) {
if(!strcmp(var, "enable_notifications")) {
if(modified_host_process_attributes & MODATTR_NOTIFICATIONS_ENABLED)
enable_notifications = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "active_service_checks_enabled")) {
if(modified_service_process_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
execute_service_checks = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "passive_service_checks_enabled")) {
if(modified_service_process_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
accept_passive_service_checks = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "active_host_checks_enabled")) {
if(modified_host_process_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
execute_host_checks = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "passive_host_checks_enabled")) {
if(modified_host_process_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
accept_passive_host_checks = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "enable_event_handlers")) {
if(modified_host_process_attributes & MODATTR_EVENT_HANDLER_ENABLED)
enable_event_handlers = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "obsess_over_services")) {
if(modified_service_process_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
obsess_over_services = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "obsess_over_hosts")) {
if(modified_host_process_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
obsess_over_hosts = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "check_service_freshness")) {
if(modified_service_process_attributes & MODATTR_FRESHNESS_CHECKS_ENABLED)
check_service_freshness = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "check_host_freshness")) {
if(modified_host_process_attributes & MODATTR_FRESHNESS_CHECKS_ENABLED)
check_host_freshness = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "enable_flap_detection")) {
if(modified_host_process_attributes & MODATTR_FLAP_DETECTION_ENABLED)
enable_flap_detection = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "process_performance_data")) {
if(modified_host_process_attributes & MODATTR_PERFORMANCE_DATA_ENABLED)
process_performance_data = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "global_host_event_handler")) {
if(modified_host_process_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
/* make sure the check command still exists... */
tempval = (char *)strdup(val);
temp_ptr = my_strtok(tempval, "!");
temp_command = find_command(temp_ptr);
temp_ptr = (char *)strdup(val);
my_free(tempval);
if(temp_command != NULL && temp_ptr != NULL) {
my_free(global_host_event_handler);
global_host_event_handler = temp_ptr;
}
}
}
else if(!strcmp(var, "global_service_event_handler")) {
if(modified_service_process_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
/* make sure the check command still exists... */
tempval = (char *)strdup(val);
temp_ptr = my_strtok(tempval, "!");
temp_command = find_command(temp_ptr);
temp_ptr = (char *)strdup(val);
my_free(tempval);
if(temp_command != NULL && temp_ptr != NULL) {
my_free(global_service_event_handler);
global_service_event_handler = temp_ptr;
}
}
}
else if(!strcmp(var, "next_comment_id"))
next_comment_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "next_downtime_id"))
next_downtime_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "next_event_id"))
next_event_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "next_problem_id"))
next_problem_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "next_notification_id"))
next_notification_id = strtoul(val, NULL, 10);
}
break;
case XRDDEFAULT_HOSTSTATUS_DATA:
if(temp_host == NULL) {
if(!strcmp(var, "host_name")) {
host_name = (char *)strdup(val);
temp_host = find_host(host_name);
}
}
else {
if(!strcmp(var, "modified_attributes")) {
temp_host->modified_attributes = strtoul(val, NULL, 10);
/* mask out attributes we don't want to retain */
temp_host->modified_attributes &= ~host_attribute_mask;
/* break out */
break;
}
if(temp_host->retain_status_information == TRUE) {
if(!strcmp(var, "has_been_checked"))
temp_host->has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "check_execution_time"))
temp_host->execution_time = strtod(val, NULL);
else if(!strcmp(var, "check_latency"))
temp_host->latency = strtod(val, NULL);
else if(!strcmp(var, "check_type"))
temp_host->check_type = atoi(val);
else if(!strcmp(var, "current_state"))
temp_host->current_state = atoi(val);
else if(!strcmp(var, "last_state"))
temp_host->last_state = atoi(val);
else if(!strcmp(var, "last_hard_state"))
temp_host->last_hard_state = atoi(val);
else if(!strcmp(var, "plugin_output")) {
my_free(temp_host->plugin_output);
temp_host->plugin_output = (char *)strdup(val);
}
else if(!strcmp(var, "long_plugin_output")) {
my_free(temp_host->long_plugin_output);
temp_host->long_plugin_output = (char *)strdup(val);
}
else if(!strcmp(var, "performance_data")) {
my_free(temp_host->perf_data);
temp_host->perf_data = (char *)strdup(val);
}
else if(!strcmp(var, "last_check"))
temp_host->last_check = strtoul(val, NULL, 10);
else if(!strcmp(var, "next_check")) {
if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
temp_host->next_check = strtoul(val, NULL, 10);
}
else if(!strcmp(var, "check_options")) {
if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
temp_host->check_options = atoi(val);
}
else if(!strcmp(var, "current_attempt"))
temp_host->current_attempt = atoi(val);
else if(!strcmp(var, "current_event_id"))
temp_host->current_event_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_event_id"))
temp_host->last_event_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "current_problem_id"))
temp_host->current_problem_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_problem_id"))
temp_host->last_problem_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "state_type"))
temp_host->state_type = atoi(val);
else if(!strcmp(var, "last_state_change"))
temp_host->last_state_change = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_hard_state_change"))
temp_host->last_hard_state_change = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_time_up"))
temp_host->last_time_up = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_time_down"))
temp_host->last_time_down = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_time_unreachable"))
temp_host->last_time_unreachable = strtoul(val, NULL, 10);
else if(!strcmp(var, "notified_on_down"))
temp_host->notified_on |= (atoi(val) > 0 ? OPT_DOWN : 0);
else if(!strcmp(var, "notified_on_unreachable"))
temp_host->notified_on |= (atoi(val) > 0 ? OPT_UNREACHABLE : 0);
else if(!strcmp(var, "last_notification"))
temp_host->last_notification = strtoul(val, NULL, 10);
else if(!strcmp(var, "current_notification_number"))
temp_host->current_notification_number = atoi(val);
else if(!strcmp(var, "current_notification_id"))
temp_host->current_notification_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "is_flapping"))
was_flapping = atoi(val);
else if(!strcmp(var, "percent_state_change"))
temp_host->percent_state_change = strtod(val, NULL);
else if(!strcmp(var, "check_flapping_recovery_notification"))
temp_host->check_flapping_recovery_notification = atoi(val);
else if(!strcmp(var, "state_history")) {
temp_ptr = val;
for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if((ch = my_strsep(&temp_ptr, ",")) != NULL)
temp_host->state_history[x] = atoi(ch);
else
break;
}
temp_host->state_history_index = 0;
}
else if(!strcmp(var, "flapping_comment_id") && sigrestart == TRUE)
temp_host->flapping_comment_id = strtoul(val, NULL, 10);
else
found_directive = FALSE;
}
if(temp_host->retain_nonstatus_information == TRUE) {
/* null-op speeds up logic */
if(found_directive == TRUE);
else if(!strcmp(var, "problem_has_been_acknowledged"))
temp_host->problem_has_been_acknowledged = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "acknowledgement_type"))
temp_host->acknowledgement_type = atoi(val);
else if(!strcmp(var, "notifications_enabled")) {
if(temp_host->modified_attributes & MODATTR_NOTIFICATIONS_ENABLED)
temp_host->notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "active_checks_enabled")) {
if(temp_host->modified_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
temp_host->checks_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "passive_checks_enabled")) {
if(temp_host->modified_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
temp_host->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "event_handler_enabled")) {
if(temp_host->modified_attributes & MODATTR_EVENT_HANDLER_ENABLED)
temp_host->event_handler_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "flap_detection_enabled")) {
if(temp_host->modified_attributes & MODATTR_FLAP_DETECTION_ENABLED)
temp_host->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "process_performance_data")) {
if(temp_host->modified_attributes & MODATTR_PERFORMANCE_DATA_ENABLED)
temp_host->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "obsess_over_host") || !strcmp(var, "obsess")) {
if(temp_host->modified_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
temp_host->obsess = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "check_command")) {
if(temp_host->modified_attributes & MODATTR_CHECK_COMMAND) {
/* make sure the check command still exists... */
tempval = (char *)strdup(val);
temp_ptr = my_strtok(tempval, "!");
temp_command = find_command(temp_ptr);
temp_ptr = (char *)strdup(val);
my_free(tempval);
if(temp_command != NULL && temp_ptr != NULL) {
my_free(temp_host->check_command);
temp_host->check_command = temp_ptr;
}
else
temp_host->modified_attributes -= MODATTR_CHECK_COMMAND;
}
}
else if(!strcmp(var, "check_period")) {
if(temp_host->modified_attributes & MODATTR_CHECK_TIMEPERIOD) {
/* make sure the timeperiod still exists... */
temp_timeperiod = find_timeperiod(val);
temp_ptr = (char *)strdup(val);
if(temp_timeperiod != NULL && temp_ptr != NULL) {
my_free(temp_host->check_period);
temp_host->check_period = temp_ptr;
}
else
temp_host->modified_attributes -= MODATTR_CHECK_TIMEPERIOD;
}
}
else if(!strcmp(var, "notification_period")) {
if(temp_host->modified_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
/* make sure the timeperiod still exists... */
temp_timeperiod = find_timeperiod(val);
temp_ptr = (char *)strdup(val);
if(temp_timeperiod != NULL && temp_ptr != NULL) {
my_free(temp_host->notification_period);
temp_host->notification_period = temp_ptr;
}
else
temp_host->modified_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
}
}
else if(!strcmp(var, "event_handler")) {
if(temp_host->modified_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
/* make sure the check command still exists... */
tempval = (char *)strdup(val);
temp_ptr = my_strtok(tempval, "!");
temp_command = find_command(temp_ptr);
temp_ptr = (char *)strdup(val);
my_free(tempval);
if(temp_command != NULL && temp_ptr != NULL) {
my_free(temp_host->event_handler);
temp_host->event_handler = temp_ptr;
}
else
temp_host->modified_attributes -= MODATTR_EVENT_HANDLER_COMMAND;
}
}
else if(!strcmp(var, "check_interval")) {
if(temp_host->modified_attributes & MODATTR_NORMAL_CHECK_INTERVAL && strtod(val, NULL) >= 0)
temp_host->check_interval = strtod(val, NULL);
}
else if(!strcmp(var, "retry_interval")) {
if(temp_host->modified_attributes & MODATTR_RETRY_CHECK_INTERVAL && strtod(val, NULL) >= 0)
temp_host->retry_interval = strtod(val, NULL);
}
else if(!strcmp(var, "max_attempts")) {
if(temp_host->modified_attributes & MODATTR_MAX_CHECK_ATTEMPTS && atoi(val) >= 1) {
temp_host->max_attempts = atoi(val);
/* adjust current attempt number if in a hard state */
if(temp_host->state_type == HARD_STATE && temp_host->current_state != HOST_UP && temp_host->current_attempt > 1)
temp_host->current_attempt = temp_host->max_attempts;
}
}
/* custom variables */
else if(var[0] == '_') {
if(temp_host->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
/* get the variable name */
if((customvarname = (char *)strdup(var + 1))) {
for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(!strcmp(customvarname, temp_customvariablesmember->variable_name)) {
if((x = atoi(val)) > 0 && strlen(val) > 3) {
my_free(temp_customvariablesmember->variable_value);
temp_customvariablesmember->variable_value = (char *)strdup(val + 2);
temp_customvariablesmember->has_been_modified = (x > 0) ? TRUE : FALSE;
}
break;
}
}
/* free memory */
my_free(customvarname);
}
}
}
}
}
break;
case XRDDEFAULT_SERVICESTATUS_DATA:
if(temp_service == NULL) {
if(!strcmp(var, "host_name")) {
host_name = (char *)strdup(val);
/*temp_service=find_service(host_name,service_description);*/
/* break out */
break;
}
else if(!strcmp(var, "service_description")) {
service_description = (char *)strdup(val);
temp_service = find_service(host_name, service_description);
/* break out */
break;
}
}
else {
if(!strcmp(var, "modified_attributes")) {
temp_service->modified_attributes = strtoul(val, NULL, 10);
/* mask out attributes we don't want to retain */
temp_service->modified_attributes &= ~service_attribute_mask;
}
if(temp_service->retain_status_information == TRUE) {
if(!strcmp(var, "has_been_checked"))
temp_service->has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "check_execution_time"))
temp_service->execution_time = strtod(val, NULL);
else if(!strcmp(var, "check_latency"))
temp_service->latency = strtod(val, NULL);
else if(!strcmp(var, "check_type"))
temp_service->check_type = atoi(val);
else if(!strcmp(var, "current_state"))
temp_service->current_state = atoi(val);
else if(!strcmp(var, "last_state"))
temp_service->last_state = atoi(val);
else if(!strcmp(var, "last_hard_state"))
temp_service->last_hard_state = atoi(val);
else if(!strcmp(var, "current_attempt"))
temp_service->current_attempt = atoi(val);
else if(!strcmp(var, "current_event_id"))
temp_service->current_event_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_event_id"))
temp_service->last_event_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "current_problem_id"))
temp_service->current_problem_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_problem_id"))
temp_service->last_problem_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "state_type"))
temp_service->state_type = atoi(val);
else if(!strcmp(var, "last_state_change"))
temp_service->last_state_change = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_hard_state_change"))
temp_service->last_hard_state_change = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_time_ok"))
temp_service->last_time_ok = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_time_warning"))
temp_service->last_time_warning = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_time_unknown"))
temp_service->last_time_unknown = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_time_critical"))
temp_service->last_time_critical = strtoul(val, NULL, 10);
else if(!strcmp(var, "plugin_output")) {
my_free(temp_service->plugin_output);
temp_service->plugin_output = (char *)strdup(val);
}
else if(!strcmp(var, "long_plugin_output")) {
my_free(temp_service->long_plugin_output);
temp_service->long_plugin_output = (char *)strdup(val);
}
else if(!strcmp(var, "performance_data")) {
my_free(temp_service->perf_data);
temp_service->perf_data = (char *)strdup(val);
}
else if(!strcmp(var, "last_check"))
temp_service->last_check = strtoul(val, NULL, 10);
else if(!strcmp(var, "next_check")) {
if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
temp_service->next_check = strtoul(val, NULL, 10);
}
else if(!strcmp(var, "check_options")) {
if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
temp_service->check_options = atoi(val);
}
else if(!strcmp(var, "notified_on_unknown"))
temp_service->notified_on |= ((atoi(val) > 0) ? OPT_UNKNOWN : 0);
else if(!strcmp(var, "notified_on_warning"))
temp_service->notified_on |= ((atoi(val) > 0) ? OPT_WARNING : 0);
else if(!strcmp(var, "notified_on_critical"))
temp_service->notified_on |= ((atoi(val) > 0) ? OPT_CRITICAL : 0);
else if(!strcmp(var, "current_notification_number"))
temp_service->current_notification_number = atoi(val);
else if(!strcmp(var, "current_notification_id"))
temp_service->current_notification_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_notification"))
temp_service->last_notification = strtoul(val, NULL, 10);
else if(!strcmp(var, "is_flapping"))
was_flapping = atoi(val);
else if(!strcmp(var, "percent_state_change"))
temp_service->percent_state_change = strtod(val, NULL);
else if(!strcmp(var, "check_flapping_recovery_notification"))
temp_service->check_flapping_recovery_notification = atoi(val);
else if(!strcmp(var, "state_history")) {
temp_ptr = val;
for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if((ch = my_strsep(&temp_ptr, ",")) != NULL)
temp_service->state_history[x] = atoi(ch);
else
break;
}
temp_service->state_history_index = 0;
}
else if(!strcmp(var, "flapping_comment_id") && sigrestart == TRUE)
temp_service->flapping_comment_id = strtoul(val, NULL, 10);
else
found_directive = FALSE;
}
if(temp_service->retain_nonstatus_information == TRUE) {
/* null-op speeds up logic */
if(found_directive == TRUE);
else if(!strcmp(var, "problem_has_been_acknowledged"))
temp_service->problem_has_been_acknowledged = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "acknowledgement_type"))
temp_service->acknowledgement_type = atoi(val);
else if(!strcmp(var, "notifications_enabled")) {
if(temp_service->modified_attributes & MODATTR_NOTIFICATIONS_ENABLED)
temp_service->notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "active_checks_enabled")) {
if(temp_service->modified_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
temp_service->checks_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "passive_checks_enabled")) {
if(temp_service->modified_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
temp_service->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "event_handler_enabled")) {
if(temp_service->modified_attributes & MODATTR_EVENT_HANDLER_ENABLED)
temp_service->event_handler_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "flap_detection_enabled")) {
if(temp_service->modified_attributes & MODATTR_FLAP_DETECTION_ENABLED)
temp_service->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "process_performance_data")) {
if(temp_service->modified_attributes & MODATTR_PERFORMANCE_DATA_ENABLED)
temp_service->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "obsess_over_service") || !strcmp(var, "obsess")) {
if(temp_service->modified_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
temp_service->obsess = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "check_command")) {
if(temp_service->modified_attributes & MODATTR_CHECK_COMMAND) {
/* make sure the check command still exists... */
tempval = (char *)strdup(val);
temp_ptr = my_strtok(tempval, "!");
temp_command = find_command(temp_ptr);
temp_ptr = (char *)strdup(val);
my_free(tempval);
if(temp_command != NULL && temp_ptr != NULL) {
my_free(temp_service->check_command);
temp_service->check_command = temp_ptr;
}
else
temp_service->modified_attributes -= MODATTR_CHECK_COMMAND;
}
}
else if(!strcmp(var, "check_period")) {
if(temp_service->modified_attributes & MODATTR_CHECK_TIMEPERIOD) {
/* make sure the timeperiod still exists... */
temp_timeperiod = find_timeperiod(val);
temp_ptr = (char *)strdup(val);
if(temp_timeperiod != NULL && temp_ptr != NULL) {
my_free(temp_service->check_period);
temp_service->check_period = temp_ptr;
}
else
temp_service->modified_attributes -= MODATTR_CHECK_TIMEPERIOD;
}
}
else if(!strcmp(var, "notification_period")) {
if(temp_service->modified_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
/* make sure the timeperiod still exists... */
temp_timeperiod = find_timeperiod(val);
temp_ptr = (char *)strdup(val);
if(temp_timeperiod != NULL && temp_ptr != NULL) {
my_free(temp_service->notification_period);
temp_service->notification_period = temp_ptr;
}
else
temp_service->modified_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
}
}
else if(!strcmp(var, "event_handler")) {
if(temp_service->modified_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
/* make sure the check command still exists... */
tempval = (char *)strdup(val);
temp_ptr = my_strtok(tempval, "!");
temp_command = find_command(temp_ptr);
temp_ptr = (char *)strdup(val);
my_free(tempval);
if(temp_command != NULL && temp_ptr != NULL) {
my_free(temp_service->event_handler);
temp_service->event_handler = temp_ptr;
}
else
temp_service->modified_attributes -= MODATTR_EVENT_HANDLER_COMMAND;
}
}
else if(!strcmp(var, "check_interval")) {
if(temp_service->modified_attributes & MODATTR_NORMAL_CHECK_INTERVAL && strtod(val, NULL) >= 0)
temp_service->check_interval = strtod(val, NULL);
}
else if(!strcmp(var, "retry_interval")) {
if(temp_service->modified_attributes & MODATTR_RETRY_CHECK_INTERVAL && strtod(val, NULL) >= 0)
temp_service->retry_interval = strtod(val, NULL);
}
else if(!strcmp(var, "max_attempts")) {
if(temp_service->modified_attributes & MODATTR_MAX_CHECK_ATTEMPTS && atoi(val) >= 1) {
temp_service->max_attempts = atoi(val);
/* adjust current attempt number if in a hard state */
if(temp_service->state_type == HARD_STATE && temp_service->current_state != STATE_OK && temp_service->current_attempt > 1)
temp_service->current_attempt = temp_service->max_attempts;
}
}
/* custom variables */
else if(var[0] == '_') {
if(temp_service->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
/* get the variable name */
if((customvarname = (char *)strdup(var + 1))) {
for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(!strcmp(customvarname, temp_customvariablesmember->variable_name)) {
if((x = atoi(val)) > 0 && strlen(val) > 3) {
my_free(temp_customvariablesmember->variable_value);
temp_customvariablesmember->variable_value = (char *)strdup(val + 2);
temp_customvariablesmember->has_been_modified = (x > 0) ? TRUE : FALSE;
}
break;
}
}
/* free memory */
my_free(customvarname);
}
}
}
}
}
break;
case XRDDEFAULT_CONTACTSTATUS_DATA:
if(temp_contact == NULL) {
if(!strcmp(var, "contact_name")) {
contact_name = (char *)strdup(val);
temp_contact = find_contact(contact_name);
}
}
else {
if(!strcmp(var, "modified_attributes")) {
temp_contact->modified_attributes = strtoul(val, NULL, 10);
/* mask out attributes we don't want to retain */
temp_contact->modified_attributes &= ~contact_attribute_mask;
}
else if(!strcmp(var, "modified_host_attributes")) {
temp_contact->modified_host_attributes = strtoul(val, NULL, 10);
/* mask out attributes we don't want to retain */
temp_contact->modified_host_attributes &= ~contact_host_attribute_mask;
}
else if(!strcmp(var, "modified_service_attributes")) {
temp_contact->modified_service_attributes = strtoul(val, NULL, 10);
/* mask out attributes we don't want to retain */
temp_contact->modified_service_attributes &= ~contact_service_attribute_mask;
}
else if(temp_contact->retain_status_information == TRUE) {
if(!strcmp(var, "last_host_notification"))
temp_contact->last_host_notification = strtoul(val, NULL, 10);
else if(!strcmp(var, "last_service_notification"))
temp_contact->last_service_notification = strtoul(val, NULL, 10);
else
found_directive = FALSE;
}
if(temp_contact->retain_nonstatus_information == TRUE) {
/* null-op speeds up logic */
if(found_directive == TRUE);
else if(!strcmp(var, "host_notification_period")) {
if(temp_contact->modified_host_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
/* make sure the timeperiod still exists... */
temp_timeperiod = find_timeperiod(val);
temp_ptr = (char *)strdup(val);
if(temp_timeperiod != NULL && temp_ptr != NULL) {
my_free(temp_contact->host_notification_period);
temp_contact->host_notification_period = temp_ptr;
}
else
temp_contact->modified_host_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
}
}
else if(!strcmp(var, "service_notification_period")) {
if(temp_contact->modified_service_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
/* make sure the timeperiod still exists... */
temp_timeperiod = find_timeperiod(val);
temp_ptr = (char *)strdup(val);
if(temp_timeperiod != NULL && temp_ptr != NULL) {
my_free(temp_contact->service_notification_period);
temp_contact->service_notification_period = temp_ptr;
}
else
temp_contact->modified_service_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
}
}
else if(!strcmp(var, "host_notifications_enabled")) {
if(temp_contact->modified_host_attributes & MODATTR_NOTIFICATIONS_ENABLED)
temp_contact->host_notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
else if(!strcmp(var, "service_notifications_enabled")) {
if(temp_contact->modified_service_attributes & MODATTR_NOTIFICATIONS_ENABLED)
temp_contact->service_notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
}
/* custom variables */
else if(var[0] == '_') {
if(temp_contact->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
/* get the variable name */
if((customvarname = (char *)strdup(var + 1))) {
for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
if(!strcmp(customvarname, temp_customvariablesmember->variable_name)) {
if((x = atoi(val)) > 0 && strlen(val) > 3) {
my_free(temp_customvariablesmember->variable_value);
temp_customvariablesmember->variable_value = (char *)strdup(val + 2);
temp_customvariablesmember->has_been_modified = (x > 0) ? TRUE : FALSE;
}
break;
}
}
/* free memory */
my_free(customvarname);
}
}
}
}
}
break;
case XRDDEFAULT_HOSTCOMMENT_DATA:
case XRDDEFAULT_SERVICECOMMENT_DATA:
if(!strcmp(var, "host_name"))
host_name = (char *)strdup(val);
else if(!strcmp(var, "service_description"))
service_description = (char *)strdup(val);
else if(!strcmp(var, "entry_type"))
entry_type = atoi(val);
else if(!strcmp(var, "comment_id"))
comment_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "source"))
source = atoi(val);
else if(!strcmp(var, "persistent"))
persistent = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "entry_time"))
entry_time = strtoul(val, NULL, 10);
else if(!strcmp(var, "expires"))
expires = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "expire_time"))
expire_time = strtoul(val, NULL, 10);
else if(!strcmp(var, "author"))
author = (char *)strdup(val);
else if(!strcmp(var, "comment_data"))
comment_data = (char *)strdup(val);
break;
case XRDDEFAULT_HOSTDOWNTIME_DATA:
case XRDDEFAULT_SERVICEDOWNTIME_DATA:
if(!strcmp(var, "host_name"))
host_name = (char *)strdup(val);
else if(!strcmp(var, "service_description"))
service_description = (char *)strdup(val);
else if(!strcmp(var, "downtime_id"))
downtime_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "comment_id"))
comment_id = strtoul(val, NULL, 10);
else if(!strcmp(var, "entry_time"))
entry_time = strtoul(val, NULL, 10);
else if(!strcmp(var, "start_time"))
start_time = strtoul(val, NULL, 10);
else if(!strcmp(var, "flex_downtime_start"))
flex_downtime_start = strtoul(val, NULL, 10);
else if(!strcmp(var, "end_time"))
end_time = strtoul(val, NULL, 10);
else if(!strcmp(var, "fixed"))
fixed = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "triggered_by"))
triggered_by = strtoul(val, NULL, 10);
else if(!strcmp(var, "is_in_effect"))
is_in_effect = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "start_notification_sent"))
start_notification_sent = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "duration"))
duration = strtoul(val, NULL, 10);
else if(!strcmp(var, "author"))
author = (char *)strdup(val);
else if(!strcmp(var, "comment"))
comment_data = (char *)strdup(val);
break;
default:
break;
}
}
}
/* free memory and close the file */
my_free(inputbuf);
mmap_fclose(thefile);
if(sort_downtime() != OK)
return ERROR;
if(sort_comments() != OK)
return ERROR;
if(test_scheduling == TRUE)
gettimeofday(&tv[1], NULL);
if(test_scheduling == TRUE) {
runtime[0] = (double)((double)(tv[1].tv_sec - tv[0].tv_sec) + (double)((tv[1].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0);
runtime[1] = (double)((double)(tv[1].tv_sec - tv[0].tv_sec) + (double)((tv[1].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0);
printf("RETENTION DATA TIMES\n");
printf("----------------------------------\n");
printf("Read and Process: %.6lf sec\n", runtime[0]);
printf(" ============\n");
printf("TOTAL: %.6lf sec\n", runtime[1]);
printf("\n\n");
}
return OK;
}