/*****************************************************************************
 *
 * CONFIG.C - Configuration input and verification routines for Icinga
 *
 * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
 * Copyright (c) 2009-2013 Nagios Core Development Team and Community Contributors
 * Copyright (c) 2009-2015 Icinga Development Team
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *****************************************************************************/

#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/macros.h"
#include "../include/icinga.h"
#include "../include/broker.h"
#include "../include/nebmods.h"
#include "../include/nebmodules.h"
#include "../xdata/xodtemplate.h"


extern char	*log_file;
extern char     *command_file;
extern char     *temp_file;
extern char     *temp_path;
extern char     *check_result_path;
extern char     *lock_file;
extern char	*log_archive_path;
extern char     *auth_file;
extern char	*p1_file;

extern char     *nagios_user;
extern char     *nagios_group;

extern char     *macro_user[MAX_USER_MACROS];

extern char     *global_host_event_handler;
extern char     *global_service_event_handler;
extern command  *global_host_event_handler_ptr;
extern command  *global_service_event_handler_ptr;

extern char     *ocsp_command;
extern char     *ochp_command;
extern command  *ocsp_command_ptr;
extern command  *ochp_command_ptr;

extern char     *illegal_object_chars;
extern char     *illegal_output_chars;
extern char	illegal_output_char_map[256];

extern int      use_regexp_matches;
extern int      use_true_regexp_matching;

extern int      use_daemon_log;
extern int      use_syslog;
extern int      use_syslog_local_facility;
extern int      syslog_local_facility;
extern int      log_notifications;
extern int      log_service_retries;
extern int      log_host_retries;
extern int      log_event_handlers;
extern int      log_external_commands;
extern int      log_passive_checks;
extern int      log_long_plugin_output;
extern int      log_anonymized_external_command_author;

extern int      service_check_timeout;
extern int      service_check_timeout_state;
extern int      host_check_timeout;
extern int      event_handler_timeout;
extern int      notification_timeout;
extern int      ocsp_timeout;
extern int      ochp_timeout;

extern int      log_initial_states;
extern int      log_current_states;

extern int      daemon_mode;
extern int      daemon_dumps_core;

extern int      verify_config;
extern int      verify_object_relationships;
extern int      verify_circular_paths;
extern int      test_scheduling;
extern int      precache_objects;
extern int      use_precached_objects;

extern double   sleep_time;
extern int      interval_length;
extern int      service_inter_check_delay_method;
extern int      host_inter_check_delay_method;
extern int      service_interleave_factor_method;
extern int      max_host_check_spread;
extern int      max_service_check_spread;

extern sched_info scheduling_info;

extern int      max_child_process_time;

extern int      max_parallel_service_checks;

extern int      command_check_interval;
extern int      check_reaper_interval;
extern int      max_check_reaper_time;
extern int      service_freshness_check_interval;
extern int      host_freshness_check_interval;
extern int      auto_rescheduling_interval;
extern int      auto_rescheduling_window;

extern int      check_external_commands;
extern int      check_orphaned_services;
extern int      check_orphaned_hosts;
extern int      check_service_freshness;
extern int      check_host_freshness;
extern int      auto_reschedule_checks;

extern int      additional_freshness_latency;

extern int      use_aggressive_host_checking;
extern unsigned long cached_host_check_horizon;
extern unsigned long cached_service_check_horizon;
extern int      enable_predictive_host_dependency_checks;
extern int      enable_predictive_service_dependency_checks;

extern int      soft_state_dependencies;

extern int      retain_state_information;
extern int      retention_update_interval;
extern int      use_retained_program_state;
extern int	dump_retained_host_service_states_to_neb;
extern int      use_retained_scheduling_info;
extern int      retention_scheduling_horizon;
extern unsigned long retained_host_attribute_mask;
extern unsigned long retained_service_attribute_mask;
extern unsigned long retained_contact_host_attribute_mask;
extern unsigned long retained_contact_service_attribute_mask;
extern unsigned long retained_process_host_attribute_mask;
extern unsigned long retained_process_service_attribute_mask;

extern int      log_rotation_method;

extern int      enable_notifications;
extern int      execute_service_checks;
extern int      accept_passive_service_checks;
extern int      execute_host_checks;
extern int      accept_passive_host_checks;
extern int      enable_event_handlers;
extern int      obsess_over_services;
extern int      obsess_over_hosts;
extern int      enable_failure_prediction;

extern int      translate_passive_host_checks;
extern int      passive_host_checks_are_soft;

extern int      aggregate_status_updates;
extern int      status_update_interval;

extern int      time_change_threshold;

extern unsigned long event_broker_options;

extern int      process_performance_data;

extern int      enable_flap_detection;

extern double   low_service_flap_threshold;
extern double   high_service_flap_threshold;
extern double   low_host_flap_threshold;
extern double   high_host_flap_threshold;

extern int      use_large_installation_tweaks;
extern int      enable_environment_macros;
extern int      free_child_process_memory;
extern int      child_processes_fork_twice;

extern int      enable_embedded_perl;
extern int      use_embedded_perl_implicitly;

extern int      stalking_event_handlers_for_hosts;
extern int      stalking_event_handlers_for_services;
extern int      stalking_notifications_for_hosts;
extern int      stalking_notifications_for_services;

extern int      date_format;
extern char     *use_timezone;

extern int	keep_unknown_macros;

extern contact		*contact_list;
extern contactgroup	*contactgroup_list;
extern host             *host_list;
extern hostgroup	*hostgroup_list;
extern service          *service_list;
extern servicegroup     *servicegroup_list;
extern notification     *notification_list;
extern command          *command_list;
extern timeperiod       *timeperiod_list;
extern serviceescalation *serviceescalation_list;
extern servicedependency *servicedependency_list;
extern hostdependency   *hostdependency_list;
extern hostescalation   *hostescalation_list;
extern module           *module_list;

extern host		**host_hashlist;
extern service		**service_hashlist;

extern int              external_command_buffer_slots;

extern unsigned long    max_check_result_file_age;

extern char             *debug_file;
extern int              debug_level;
extern int              debug_verbosity;
extern unsigned long    max_debug_file_size;

extern int              allow_empty_hostgroup_assignment;

extern unsigned long    max_check_result_list_items;
extern int		enable_state_based_escalation_ranges;

/******************************************************************/
/************** CONFIGURATION INPUT FUNCTIONS *********************/
/******************************************************************/

/* read all configuration data */
int read_all_object_data(char *main_config_file) {
	int result = OK;
	int options = 0;
	int cache = FALSE;
	int precache = FALSE;

	options = READ_ALL_OBJECT_DATA;

	/* cache object definitions if we're up and running */
	if (verify_config == FALSE && test_scheduling == FALSE)
		cache = TRUE;

	/* precache object definitions */
	if (precache_objects == TRUE && (verify_config || test_scheduling == TRUE))
		precache = TRUE;

	/* read in all host configuration data from external sources */
	result = read_object_config_data(main_config_file, options, cache, precache);
	if (result != OK)
		return ERROR;

	return OK;
}

/* log generic deprecation warning on variables */
static void log_deprecation_warning(char *var) {

	if (!var)
		return;

	logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: config setting '%s' ignored. This has been deprecated. Remove it from your configuration!", var);
}

/* log generic removed warning on variables */
static void log_removed_warning(char *var) {

	if (!var)
		return;

	logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: config setting '%s' unknown. Remove it from your configuration!", var);
}

/* process the main configuration file */
int read_main_config_file(char *main_config_file) {
	char *input = NULL;
	char *variable = NULL;
	char *value = NULL;
	char *error_message = NULL;
	char *temp_ptr = NULL;
	mmapfile *thefile = NULL;
	int current_line = 0;
	int error = FALSE;
	int command_check_interval_is_seconds = FALSE;
	char *modptr = NULL;
	char *argptr = NULL;
	DIR *tmpdir = NULL;
	icinga_macros *mac;

	mac = get_global_macros();

	/* open the config file for reading */
	if ((thefile = mmap_fopen(main_config_file)) == NULL) {
		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open main configuration file '%s' for reading!", main_config_file);
		return ERROR;
	}

	/* save the main config file macro */
	my_free(mac->x[MACRO_MAINCONFIGFILE]);
	if ((mac->x[MACRO_MAINCONFIGFILE] = (char *)strdup(main_config_file)))
		strip(mac->x[MACRO_MAINCONFIGFILE]);

	/* process all lines in the config file */
	while (1) {

		/* free memory */
		my_free(input);
		my_free(variable);
		my_free(value);

		/* read the next line */
		if ((input = mmap_fgets_multiline(thefile)) == NULL)
			break;

		current_line = thefile->current_line;

		strip(input);

		/* skip blank lines and comments */
		if (input[0] == '\x0' || input[0] == '#')
			continue;

		/* get the variable name */
		if ((temp_ptr = my_strtok(input, "=")) == NULL) {
			asprintf(&error_message, "NULL variable");
			error = TRUE;
			break;
		}
		if ((variable = (char *)strdup(temp_ptr)) == NULL) {
			asprintf(&error_message, "malloc() error");
			error = TRUE;
			break;
		}

		/* get the value */
		if ((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
			asprintf(&error_message, "NULL value");
			error = TRUE;
			break;
		}
		if ((value = (char *)strdup(temp_ptr)) == NULL) {
			asprintf(&error_message, "malloc() error");
			error = TRUE;
			break;
		}
		strip(variable);
		strip(value);

		/* process the variable/value */

		if (!strcmp(variable, "resource_file")) {

			/* save the macro */
			my_free(mac->x[MACRO_RESOURCEFILE]);
			mac->x[MACRO_RESOURCEFILE] = (char *)strdup(value);

			/* process the resource file */
			if(read_resource_file(value) == ERROR) {
                                asprintf(&error_message, "Resource file parsing failed");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "log_file")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Log file is too long");
				error = TRUE;
				break;
			}

			my_free(log_file);
			log_file = (char *)strdup(value);

			/* save the macro */
			my_free(mac->x[MACRO_LOGFILE]);
			mac->x[MACRO_LOGFILE] = (char *)strdup(log_file);
		}

		else if (!strcmp(variable, "debug_level"))
			debug_level = atoi(value);

		else if (!strcmp(variable, "debug_verbosity"))
			debug_verbosity = atoi(value);

		else if (!strcmp(variable, "debug_file")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Debug log file is too long");
				error = TRUE;
				break;
			}

			my_free(debug_file);
			debug_file = (char *)strdup(value);
		}

		else if (!strcmp(variable, "max_debug_file_size"))
			max_debug_file_size = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "command_file")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Command file is too long");
				error = TRUE;
				break;
			}

			my_free(command_file);
			command_file = (char *)strdup(value);

			/* save the macro */
			my_free(mac->x[MACRO_COMMANDFILE]);
			mac->x[MACRO_COMMANDFILE] = (char *)strdup(value);
		}

		else if (!strcmp(variable, "temp_file")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Temp file is too long");
				error = TRUE;
				break;
			}

			my_free(temp_file);
			temp_file = (char *)strdup(value);

			/* save the macro */
			my_free(mac->x[MACRO_TEMPFILE]);
			mac->x[MACRO_TEMPFILE] = (char *)strdup(temp_file);
		}

		else if (!strcmp(variable, "temp_path")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Temp path is too long");
				error = TRUE;
				break;
			}

			if ((tmpdir = opendir((char *)value)) == NULL) {
				asprintf(&error_message, "Temp path is not a valid directory");
				error = TRUE;
				break;
			}
			closedir(tmpdir);

			my_free(temp_path);
			if ((temp_path = (char *)strdup(value))) {
				strip(temp_path);
				/* make sure we don't have a trailing slash */
				if (temp_path[strlen(temp_path)-1] == '/')
					temp_path[strlen(temp_path)-1] = '\x0';
			}

			/* save the macro */
			my_free(mac->x[MACRO_TEMPPATH]);
			mac->x[MACRO_TEMPPATH] = (char *)strdup(temp_path);
		}

		else if (!strcmp(variable, "check_result_path")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Check result path is too long");
				error = TRUE;
				break;
			}

			if ((tmpdir = opendir((char *)value)) == NULL) {
				asprintf(&error_message, "Check result path is not a valid directory");
				error = TRUE;
				break;
			}
			closedir(tmpdir);

			my_free(check_result_path);
			if ((check_result_path = (char *)strdup(value))) {
				strip(check_result_path);
				/* make sure we don't have a trailing slash */
				if (check_result_path[strlen(check_result_path)-1] == '/')
					check_result_path[strlen(check_result_path)-1] = '\x0';
			}
		}

		else if (!strcmp(variable, "max_check_result_file_age"))
			max_check_result_file_age = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "lock_file")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Lock file is too long");
				error = TRUE;
				break;
			}

			my_free(lock_file);
			lock_file = (char *)strdup(value);
		}

		else if (!strcmp(variable, "global_host_event_handler")) {
			my_free(global_host_event_handler);
			global_host_event_handler = (char *)strdup(value);
		}

		else if (!strcmp(variable, "global_service_event_handler")) {
			my_free(global_service_event_handler);
			global_service_event_handler = (char *)strdup(value);
		}

		else if (!strcmp(variable, "ocsp_command")) {
			my_free(ocsp_command);
			ocsp_command = (char *)strdup(value);
		}

		else if (!strcmp(variable, "ochp_command")) {
			my_free(ochp_command);
			ochp_command = (char *)strdup(value);
		}

		else if (!strcmp(variable, "icinga_user") || !strcmp(variable, "nagios_user")) {
			my_free(nagios_user);
			nagios_user = (char *)strdup(value);
		}

		else if (!strcmp(variable, "icinga_group") || !strcmp(variable, "nagios_group")) {
			my_free(nagios_group);
			nagios_group = (char *)strdup(value);
		}

		else if (!strcmp(variable, "admin_email")) {

			/* save the macro */
			my_free(mac->x[MACRO_ADMINEMAIL]);
			mac->x[MACRO_ADMINEMAIL] = (char *)strdup(value);
		}

		else if (!strcmp(variable, "admin_pager")) {

			/* save the macro */
			my_free(mac->x[MACRO_ADMINPAGER]);
			mac->x[MACRO_ADMINPAGER] = (char *)strdup(value);
		}

		else if (!strcmp(variable, "use_daemon_log")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_daemon_log");
				error = TRUE;
				break;
			}

			use_daemon_log = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "use_syslog")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_syslog");
				error = TRUE;
				break;
			}

			use_syslog = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "use_syslog_local_facility")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_syslog_local_facility");
				error = TRUE;
				break;
			}

			use_syslog_local_facility = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "syslog_local_facility")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '7') {
				asprintf(&error_message, "Illegal value for syslog_local_facility");
				error = TRUE;
				break;
			}

			syslog_local_facility = atoi(value);
		}

		else if (!strcmp(variable, "log_notifications")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_notifications");
				error = TRUE;
				break;
			}

			log_notifications = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_service_retries")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_service_retries");
				error = TRUE;
				break;
			}

			log_service_retries = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_host_retries")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_host_retries");
				error = TRUE;
				break;
			}

			log_host_retries = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_event_handlers")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_event_handlers");
				error = TRUE;
				break;
			}

			log_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_external_commands")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_external_commands");
				error = TRUE;
				break;
			}

			log_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_passive_checks")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_passive_checks");
				error = TRUE;
				break;
			}

			log_passive_checks = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_long_plugin_output")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_long_plugin_output");
				error = TRUE;
				break;
			}

			log_long_plugin_output = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_initial_states")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_initial_states");
				error = TRUE;
				break;
			}

			log_initial_states = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_current_states")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_current_states");
				error = TRUE;
				break;
			}

			log_current_states = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_anonymized_external_command_author")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for log_anonymized_external_command_author");
				error = TRUE;
				break;
			}

			log_anonymized_external_command_author = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "retain_state_information")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for retain_state_information");
				error = TRUE;
				break;
			}

			retain_state_information = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "retention_update_interval")) {

			retention_update_interval = atoi(value);
			if (retention_update_interval < 0) {
				asprintf(&error_message, "Illegal value for retention_update_interval");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "use_retained_program_state")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_retained_program_state");
				error = TRUE;
				break;
			}

			use_retained_program_state = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "dump_retained_host_service_states_to_neb")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for dump_retained_host_service_states_to_neb");
				error = TRUE;
				break;
			}

			dump_retained_host_service_states_to_neb = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "use_retained_scheduling_info")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_retained_scheduling_info");
				error = TRUE;
				break;
			}

			use_retained_scheduling_info = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "retention_scheduling_horizon")) {

			retention_scheduling_horizon = atoi(value);

			if (retention_scheduling_horizon <= 0) {
				asprintf(&error_message, "Illegal value for retention_scheduling_horizon");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "additional_freshness_latency"))
			additional_freshness_latency = atoi(value);

		else if (!strcmp(variable, "retained_host_attribute_mask"))
			retained_host_attribute_mask = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "retained_service_attribute_mask"))
			retained_service_attribute_mask = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "retained_process_host_attribute_mask"))
			retained_process_host_attribute_mask = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "retained_process_service_attribute_mask"))
			retained_process_service_attribute_mask = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "retained_contact_host_attribute_mask"))
			retained_contact_host_attribute_mask = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "retained_contact_service_attribute_mask"))
			retained_contact_service_attribute_mask = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "obsess_over_services")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for obsess_over_services");
				error = TRUE;
				break;
			}

			obsess_over_services = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "obsess_over_hosts")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for obsess_over_hosts");
				error = TRUE;
				break;
			}

			obsess_over_hosts = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "translate_passive_host_checks")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for translate_passive_host_checks");
				error = TRUE;
				break;
			}

			translate_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "passive_host_checks_are_soft"))
			passive_host_checks_are_soft = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "service_check_timeout")) {

			service_check_timeout = atoi(value);

			if (service_check_timeout <= 0) {
				asprintf(&error_message, "Illegal value for service_check_timeout");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "service_check_timeout_state")) {

			if (!strcmp(value, "o"))
				service_check_timeout_state = STATE_OK;
			else if (!strcmp(value, "w"))
				service_check_timeout_state = STATE_WARNING;
			else if (!strcmp(value, "c"))
				service_check_timeout_state = STATE_CRITICAL;
			else if (!strcmp(value, "u"))
				service_check_timeout_state = STATE_UNKNOWN;
			else {
				asprintf(&error_message, "Illegal value for service_check_timeout_state");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "host_check_timeout")) {

			host_check_timeout = atoi(value);

			if (host_check_timeout <= 0) {
				asprintf(&error_message, "Illegal value for host_check_timeout");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "event_handler_timeout")) {

			event_handler_timeout = atoi(value);

			if (event_handler_timeout <= 0) {
				asprintf(&error_message, "Illegal value for event_handler_timeout");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "notification_timeout")) {

			notification_timeout = atoi(value);

			if (notification_timeout <= 0) {
				asprintf(&error_message, "Illegal value for notification_timeout");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "ocsp_timeout")) {

			ocsp_timeout = atoi(value);

			if (ocsp_timeout <= 0) {
				asprintf(&error_message, "Illegal value for ocsp_timeout");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "ochp_timeout")) {

			ochp_timeout = atoi(value);

			if (ochp_timeout <= 0) {
				asprintf(&error_message, "Illegal value for ochp_timeout");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "use_agressive_host_checking") || !strcmp(variable, "use_aggressive_host_checking")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_aggressive_host_checking");
				error = TRUE;
				break;
			}

			use_aggressive_host_checking = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "cached_host_check_horizon"))
			cached_host_check_horizon = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "enable_predictive_host_dependency_checks"))
			enable_predictive_host_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "cached_service_check_horizon"))
			cached_service_check_horizon = strtoul(value, NULL, 0);

		else if (!strcmp(variable, "enable_predictive_service_dependency_checks"))
			enable_predictive_service_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "soft_state_dependencies")) {
			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for soft_state_dependencies");
				error = TRUE;
				break;
			}

			soft_state_dependencies = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "log_rotation_method")) {
			if (!strcmp(value, "n"))
				log_rotation_method = LOG_ROTATION_NONE;
			else if (!strcmp(value, "h"))
				log_rotation_method = LOG_ROTATION_HOURLY;
			else if (!strcmp(value, "d"))
				log_rotation_method = LOG_ROTATION_DAILY;
			else if (!strcmp(value, "w"))
				log_rotation_method = LOG_ROTATION_WEEKLY;
			else if (!strcmp(value, "m"))
				log_rotation_method = LOG_ROTATION_MONTHLY;
			else {
				asprintf(&error_message, "Illegal value for log_rotation_method");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "log_archive_path")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Log archive path too long");
				error = TRUE;
				break;
			}

			my_free(log_archive_path);
			log_archive_path = (char *)strdup(value);
		}

		else if (!strcmp(variable, "enable_event_handlers"))
			enable_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "enable_notifications"))
			enable_notifications = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "execute_service_checks"))
			execute_service_checks = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "accept_passive_service_checks"))
			accept_passive_service_checks = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "execute_host_checks"))
			execute_host_checks = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "accept_passive_host_checks"))
			accept_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "service_inter_check_delay_method")) {
			if (!strcmp(value, "n"))
				service_inter_check_delay_method = ICD_NONE;
			else if (!strcmp(value, "d"))
				service_inter_check_delay_method = ICD_DUMB;
			else if (!strcmp(value, "s"))
				service_inter_check_delay_method = ICD_SMART;
			else {
				service_inter_check_delay_method = ICD_USER;
				scheduling_info.service_inter_check_delay = strtod(value, NULL);
				if (scheduling_info.service_inter_check_delay <= 0.0) {
					asprintf(&error_message, "Illegal value for service_inter_check_delay_method");
					error = TRUE;
					break;
				}
			}
		}

		else if (!strcmp(variable, "max_service_check_spread")) {
			strip(value);
			max_service_check_spread = atoi(value);
			if (max_service_check_spread < 1) {
				asprintf(&error_message, "Illegal value for max_service_check_spread");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "host_inter_check_delay_method")) {

			if (!strcmp(value, "n"))
				host_inter_check_delay_method = ICD_NONE;
			else if (!strcmp(value, "d"))
				host_inter_check_delay_method = ICD_DUMB;
			else if (!strcmp(value, "s"))
				host_inter_check_delay_method = ICD_SMART;
			else {
				host_inter_check_delay_method = ICD_USER;
				scheduling_info.host_inter_check_delay = strtod(value, NULL);
				if (scheduling_info.host_inter_check_delay <= 0.0) {
					asprintf(&error_message, "Illegal value for host_inter_check_delay_method");
					error = TRUE;
					break;
				}
			}
		}

		else if (!strcmp(variable, "max_host_check_spread")) {

			max_host_check_spread = atoi(value);
			if (max_host_check_spread < 1) {
				asprintf(&error_message, "Illegal value for max_host_check_spread");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "service_interleave_factor")) {
			if (!strcmp(value, "s"))
				service_interleave_factor_method = ILF_SMART;
			else {
				service_interleave_factor_method = ILF_USER;
				scheduling_info.service_interleave_factor = atoi(value);
				if (scheduling_info.service_interleave_factor < 1)
					scheduling_info.service_interleave_factor = 1;
			}
		}

		else if (!strcmp(variable, "max_concurrent_checks")) {

			max_parallel_service_checks = atoi(value);
			if (max_parallel_service_checks < 0) {
				asprintf(&error_message, "Illegal value for max_concurrent_checks");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "check_result_reaper_frequency") || !strcmp(variable, "service_reaper_frequency")) {

			check_reaper_interval = atoi(value);
			if (check_reaper_interval < 1) {
				asprintf(&error_message, "Illegal value for check_result_reaper_frequency");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "max_check_result_reaper_time")) {

			max_check_reaper_time = atoi(value);
			if (max_check_reaper_time < 1) {
				asprintf(&error_message, "Illegal value for max_check_result_reaper_time");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "sleep_time")) {

			sleep_time = atof(value);
			if (sleep_time <= 0.0) {
				asprintf(&error_message, "Illegal value for sleep_time");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "interval_length")) {

			interval_length = atoi(value);
			if (interval_length < 1) {
				asprintf(&error_message, "Illegal value for interval_length");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "check_external_commands")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for check_external_commands");
				error = TRUE;
				break;
			}

			check_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "command_check_interval")) {

			command_check_interval_is_seconds = (strstr(value, "s")) ? TRUE : FALSE;
			command_check_interval = atoi(value);
			if (command_check_interval < -1 || command_check_interval == 0) {
				asprintf(&error_message, "Illegal value for command_check_interval");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "check_for_orphaned_services")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for check_for_orphaned_services");
				error = TRUE;
				break;
			}

			check_orphaned_services = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "check_for_orphaned_hosts")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for check_for_orphaned_hosts");
				error = TRUE;
				break;
			}

			check_orphaned_hosts = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "check_service_freshness")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for check_service_freshness");
				error = TRUE;
				break;
			}

			check_service_freshness = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "check_host_freshness")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for check_host_freshness");
				error = TRUE;
				break;
			}

			check_host_freshness = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "service_freshness_check_interval") || !strcmp(variable, "freshness_check_interval")) {

			service_freshness_check_interval = atoi(value);
			if (service_freshness_check_interval <= 0) {
				asprintf(&error_message, "Illegal value for service_freshness_check_interval");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "host_freshness_check_interval")) {

			host_freshness_check_interval = atoi(value);
			if (host_freshness_check_interval <= 0) {
				asprintf(&error_message, "Illegal value for host_freshness_check_interval");
				error = TRUE;
				break;
			}
		} else if (!strcmp(variable, "auto_reschedule_checks")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for auto_reschedule_checks");
				error = TRUE;
				break;
			}

			auto_reschedule_checks = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "auto_rescheduling_interval")) {

			auto_rescheduling_interval = atoi(value);
			if (auto_rescheduling_interval <= 0) {
				asprintf(&error_message, "Illegal value for auto_rescheduling_interval");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "auto_rescheduling_window")) {

			auto_rescheduling_window = atoi(value);
			if (auto_rescheduling_window <= 0) {
				asprintf(&error_message, "Illegal value for auto_rescheduling_window");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "aggregate_status_updates")) {

			logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: aggregate_status_updates directive ignored.  All status file updates are now aggregated.");
		}

		else if (!strcmp(variable, "status_update_interval")) {

			status_update_interval = atoi(value);
			if (status_update_interval <= 1) {
				asprintf(&error_message, "Illegal value for status_update_interval");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "time_change_threshold")) {

			time_change_threshold = atoi(value);

			if (time_change_threshold <= 5) {
				asprintf(&error_message, "Illegal value for time_change_threshold");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "process_performance_data"))
			process_performance_data = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "enable_flap_detection"))
			enable_flap_detection = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "enable_failure_prediction"))
			enable_failure_prediction = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "low_service_flap_threshold")) {

			low_service_flap_threshold = strtod(value, NULL);
			if (low_service_flap_threshold <= 0.0 || low_service_flap_threshold >= 100.0) {
				asprintf(&error_message, "Illegal value for low_service_flap_threshold");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "high_service_flap_threshold")) {

			high_service_flap_threshold = strtod(value, NULL);
			if (high_service_flap_threshold <= 0.0 ||  high_service_flap_threshold > 100.0) {
				asprintf(&error_message, "Illegal value for high_service_flap_threshold");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "low_host_flap_threshold")) {

			low_host_flap_threshold = strtod(value, NULL);
			if (low_host_flap_threshold <= 0.0 || low_host_flap_threshold >= 100.0) {
				asprintf(&error_message, "Illegal value for low_host_flap_threshold");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "high_host_flap_threshold")) {

			high_host_flap_threshold = strtod(value, NULL);
			if (high_host_flap_threshold <= 0.0 || high_host_flap_threshold > 100.0) {
				asprintf(&error_message, "Illegal value for high_host_flap_threshold");
				error = TRUE;
				break;
			}
		}

		else if (!strcmp(variable, "date_format")) {

			if (!strcmp(value, "euro"))
				date_format = DATE_FORMAT_EURO;
			else if (!strcmp(value, "iso8601"))
				date_format = DATE_FORMAT_ISO8601;
			else if (!strcmp(value, "strict-iso8601"))
				date_format = DATE_FORMAT_STRICT_ISO8601;
			else
				date_format = DATE_FORMAT_US;
		}

		else if (!strcmp(variable, "use_timezone")) {
			my_free(use_timezone);
			use_timezone = (char *)strdup(value);
		}

		else if (!strcmp(variable, "p1_file")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "P1 file is too long");
				error = TRUE;
				break;
			}

			my_free(p1_file);
			p1_file = (char *)strdup(value);
		}

		else if (!strcmp(variable, "event_broker_options")) {

			if (!strcmp(value, "-1"))
				event_broker_options = BROKER_EVERYTHING;
			else
				event_broker_options = strtoul(value, NULL, 0);
		}

		else if (!strcmp(variable, "illegal_object_name_chars"))
			illegal_object_chars = (char *)strdup(value);

		else if (!strcmp(variable, "illegal_macro_output_chars"))
			illegal_output_chars = (char *)strdup(value);


		else if (!strcmp(variable, "broker_module")) {
			logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: config setting '%s' has been deprecated. Please use the 'module' object configuration instead!", variable);

			modptr = strtok(value, " \n");
			argptr = strtok(NULL, "\n");
#ifdef USE_EVENT_BROKER
			neb_add_module(modptr, argptr, TRUE);
#endif
		}

		else if (!strcmp(variable, "use_regexp_matching"))
			use_regexp_matches = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "use_true_regexp_matching"))
			use_true_regexp_matching = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "daemon_dumps_core")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for daemon_dumps_core");
				error = TRUE;
				break;
			}

			daemon_dumps_core = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "use_large_installation_tweaks")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_large_installation_tweaks ");
				error = TRUE;
				break;
			}

			use_large_installation_tweaks = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "enable_environment_macros"))
			enable_environment_macros = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "free_child_process_memory"))
			free_child_process_memory = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "child_processes_fork_twice"))
			child_processes_fork_twice = (atoi(value) > 0) ? TRUE : FALSE;

		else if (!strcmp(variable, "enable_embedded_perl")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for enable_embedded_perl");
				error = TRUE;
				break;
			}

			enable_embedded_perl = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "use_embedded_perl_implicitly")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "Illegal value for use_embedded_perl_implicitly");
				error = TRUE;
				break;
			}

			use_embedded_perl_implicitly = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "stalking_event_handlers_for_hosts")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "stalking_event_handlers_for_hosts");
				error = TRUE;
				break;
			}

			stalking_event_handlers_for_hosts = (atoi(value) > 0) ? TRUE : FALSE;
		}

		else if (!strcmp(variable, "stalking_event_handlers_for_services")) {

			if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
				asprintf(&error_message, "stalking_event_handlers_for_services");
				error = TRUE;
				break;
			}

			stalking_event_handlers_for_services = (atoi(value) > 0) ? TRUE : FALSE;
		}

                else if (!strcmp(variable, "stalking_notifications_for_hosts")) {

                        if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
                                asprintf(&error_message, "stalking_notifications_for_hosts");
                                error = TRUE;
                                break;
                        }

                        stalking_notifications_for_hosts = (atoi(value) > 0) ? TRUE : FALSE;
                }

                else if (!strcmp(variable, "stalking_notifications_for_services")) {

                        if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
                                asprintf(&error_message, "stalking_notifications_for_services");
                                error = TRUE;
                                break;
                        }

                        stalking_notifications_for_services = (atoi(value) > 0) ? TRUE : FALSE;
                }

		else if (!strcmp(variable, "external_command_buffer_slots"))
			external_command_buffer_slots = atoi(value);

		else if (!strcmp(variable, "check_for_updates")) {
			/* ignore it for compatibility reasons */
			logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: check_for_updates variable ignored. Icinga Core does not support program update checking");
		}

		else if (!strcmp(variable, "bare_update_check")) {
			/* ignore it for compatibility reasons */
			logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: bare_update_check variable ignored. Icinga Core does not support program update checking");
		}

		else if (!strcmp(variable, "allow_empty_hostgroup_assignment")) {
			allow_empty_hostgroup_assignment = (atoi(value) > 0) ? TRUE : FALSE;
		}

                else if (!strcmp(variable, "keep_unknown_macros")) {

                        if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
                                asprintf(&error_message, "Illegal value for check_service_freshness");
                                error = TRUE;
                                break;
                        }

                        keep_unknown_macros = (atoi(value) > 0) ? TRUE : FALSE;
                }

		else if (!strcmp(variable, "max_check_result_list_items"))
			max_check_result_list_items = strtoul(value, NULL, 0);

                else if (!strcmp(variable, "enable_state_based_escalation_ranges")) {

                        if (strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
                                asprintf(&error_message, "Illegal value for enable_state_based_escalation_ranges");
                                error = TRUE;
                                break;
                        }

                        enable_state_based_escalation_ranges = (atoi(value) > 0) ? TRUE : FALSE;
                }

		/*** AUTH_FILE VARIABLE USED BY EMBEDDED PERL INTERPRETER ***/
		else if (!strcmp(variable, "auth_file")) {

			if (strlen(value) > MAX_FILENAME_LENGTH - 1) {
				asprintf(&error_message, "Auth file is too long");
				error = TRUE;
				break;
			}

			my_free(auth_file);
			auth_file = (char *)strdup(value);
		}

		/* skip external data directives */
		else if (strstr(input, "x") == input)
			continue;

		/* ignore external variables */
		else if (!strcmp(variable, "status_file"))
			continue;
		else if (!strcmp(variable, "perfdata_timeout"))
			continue;
		else if (strstr(variable, "host_perfdata") == variable)
			continue;
		else if (strstr(variable, "service_perfdata") == variable)
			continue;
		else if (strstr(input, "cfg_file=") == input || strstr(input, "cfg_dir=") == input)
			continue;
		else if (strstr(input, "state_retention_file=") == input)
			continue;
		else if (strstr(input, "sync_retention_file=") == input)
			continue;
		else if (strstr(input, "object_cache_file=") == input)
			continue;
		else if (strstr(input, "precached_object_file=") == input)
			continue;

		/* DEPRECATED variables */
		else if (!strcmp(variable, "event_profiling_enabled")) {
			log_removed_warning(variable);
		}

		/* we don't know what this variable is... */
		else {
			asprintf(&error_message, "UNKNOWN VARIABLE");
			error = TRUE;
			break;
		}

	}

	/* adjust timezone values */
	if (use_timezone != NULL)
		set_environment_var("TZ", use_timezone, 1);
	tzset();

	/* adjust command check interval */
	if (command_check_interval_is_seconds == FALSE && command_check_interval != -1)
		command_check_interval *= interval_length;

	/* adjust tweaks */
	if (free_child_process_memory == -1)
		free_child_process_memory = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE;
	if (child_processes_fork_twice == -1)
		child_processes_fork_twice = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE;


	/* handle errors */
	if (error == TRUE) {
		logit(NSLOG_CONFIG_ERROR, TRUE, "Error in configuration file '%s' - Line %d (%s)", main_config_file, current_line, (error_message == NULL) ? "NULL" : error_message);
		return ERROR;
	}

	/* free leftover memory and close the file */
	my_free(input);
	mmap_fclose(thefile);

	/* free memory */
	my_free(error_message);
	my_free(input);
	my_free(variable);
	my_free(value);

	/* make sure a log file has been specified */
	strip(log_file);
	if (!strcmp(log_file, "")) {
		if (daemon_mode == FALSE)
			printf("Error: Log file is not specified anywhere in main config file '%s'!\n", main_config_file);
		return ERROR;
	}

	return OK;
}



/* processes macros in resource file */
int read_resource_file(char *resource_file) {
	char *input = NULL;
	char *variable = NULL;
	char *value = NULL;
	char *temp_ptr = NULL;
	mmapfile *thefile = NULL;
	int current_line = 1;
	int error = FALSE;
	int user_index = 0;

	if ((thefile = mmap_fopen(resource_file)) == NULL) {
		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open resource file '%s' for reading!", resource_file);
		return ERROR;
	}

	/* process all lines in the resource file */
	while (1) {

		/* free memory */
		my_free(input);
		my_free(variable);
		my_free(value);

		/* read the next line */
		if ((input = mmap_fgets_multiline(thefile)) == NULL)
			break;

		current_line = thefile->current_line;

		/* skip blank lines and comments */
		if (input[0] == '#' || input[0] == '\x0' || input[0] == '\n' || input[0] == '\r')
			continue;

		strip(input);

		/* get the variable name */
		if ((temp_ptr = my_strtok(input, "=")) == NULL) {
			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable - Line %d of resource file '%s'", current_line, resource_file);
			error = TRUE;
			break;
		}
		if ((variable = (char *)strdup(temp_ptr)) == NULL) {
			error = TRUE;
			break;
		}

		/* get the value */
		if ((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable value - Line %d of resource file '%s'", current_line, resource_file);
			error = TRUE;
			break;
		}
		if ((value = (char *)strdup(temp_ptr)) == NULL) {
			error = TRUE;
			break;
		}

		/* what should we do with the variable/value pair? */

		/* check for macro declarations */
		if (variable[0] == '$' && variable[strlen(variable)-1] == '$') {

			/* $USERx$ macro declarations */
			if (strstr(variable, "$USER") == variable  && strlen(variable) > 5) {
				user_index = atoi(variable + 5) - 1;
				if (user_index >= 0 && user_index < MAX_USER_MACROS) {
					my_free(macro_user[user_index]);
					macro_user[user_index] = (char *)strdup(value);
				}
			}
		}
	}

	/* free leftover memory and close the file */
	my_free(input);
	mmap_fclose(thefile);

	/* free memory */
	my_free(variable);
	my_free(value);

	if (error == TRUE)
		return ERROR;

	return OK;
}






/****************************************************************/
/**************** CONFIG VERIFICATION FUNCTIONS *****************/
/****************************************************************/

/* do a pre-flight check to make sure object relationships, etc. make sense */
int pre_flight_check(void) {
	char *buf = NULL;
	command *temp_command = NULL;
	char *temp_command_name = "";
	int warnings = 0;
	int errors = 0;
	struct timeval tv[4];
	double runtime[4];
	int temp_path_fd = -1;


	if (test_scheduling == TRUE)
		gettimeofday(&tv[0], NULL);

	/********************************************/
	/* check object relationships               */
	/********************************************/
	pre_flight_object_check(&warnings, &errors);
	if (test_scheduling == TRUE)
		gettimeofday(&tv[1], NULL);


	/********************************************/
	/* check for circular paths between hosts   */
	/********************************************/
	pre_flight_circular_check(&warnings, &errors);
	if (test_scheduling == TRUE)
		gettimeofday(&tv[2], NULL);

	purge_debuginfo();

	/********************************************/
	/* check global event handler commands...   */
	/********************************************/
	if (verify_config)
		printf("Checking global event handlers...\n");
	if (global_host_event_handler != NULL) {

		/* check the event handler command */
		buf = (char *)strdup(global_host_event_handler);

		/* get the command name, leave any arguments behind */
		temp_command_name = my_strtok(buf, "!");

		temp_command = find_command(temp_command_name);
		if (temp_command == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global host event handler command '%s' is not defined anywhere!", temp_command_name);
			errors++;
		}

		/* save the pointer to the command for later */
		global_host_event_handler_ptr = temp_command;

		my_free(buf);
	}
	if (global_service_event_handler != NULL) {

		/* check the event handler command */
		buf = (char *)strdup(global_service_event_handler);

		/* get the command name, leave any arguments behind */
		temp_command_name = my_strtok(buf, "!");

		temp_command = find_command(temp_command_name);
		if (temp_command == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global service event handler command '%s' is not defined anywhere!", temp_command_name);
			errors++;
		}

		/* save the pointer to the command for later */
		global_service_event_handler_ptr = temp_command;

		my_free(buf);
	}


	/**************************************************/
	/* check obsessive processor commands...          */
	/**************************************************/
	if (verify_config)
		printf("Checking obsessive compulsive processor commands...\n");
	if (ocsp_command != NULL) {

		buf = (char *)strdup(ocsp_command);

		/* get the command name, leave any arguments behind */
		temp_command_name = my_strtok(buf, "!");

		temp_command = find_command(temp_command_name);
		if (temp_command == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Obsessive compulsive service processor command '%s' is not defined anywhere!", temp_command_name);
			errors++;
		}

		/* save the pointer to the command for later */
		ocsp_command_ptr = temp_command;

		my_free(buf);
	}
	if (ochp_command != NULL) {

		buf = (char *)strdup(ochp_command);

		/* get the command name, leave any arguments behind */
		temp_command_name = my_strtok(buf, "!");

		temp_command = find_command(temp_command_name);
		if (temp_command == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Obsessive compulsive host processor command '%s' is not defined anywhere!", temp_command_name);
			errors++;
		}

		/* save the pointer to the command for later */
		ochp_command_ptr = temp_command;

		my_free(buf);
	}


	/**************************************************/
	/* check various settings...                      */
	/**************************************************/
	if (verify_config)
		printf("Checking misc settings...\n");

	/* check if we can write to temp_path */
	asprintf(&buf, "%s/nagiosXXXXXX", temp_path);
	if ((temp_path_fd = mkstemp(buf)) == -1) {
		logit(NSLOG_VERIFICATION_ERROR, TRUE, "\tError: Unable to write to temp_path ('%s') - %s\n", temp_path, strerror(errno));
		errors++;
	} else {
		close(temp_path_fd);
		remove(buf);
	}
	my_free(buf);

	/* check if we can write to check_result_path */
	asprintf(&buf, "%s/nagiosXXXXXX", check_result_path);
	if ((temp_path_fd = mkstemp(buf)) == -1) {
		logit(NSLOG_VERIFICATION_WARNING, TRUE, "\tError: Unable to write to check_result_path ('%s') - %s\n", check_result_path, strerror(errno));
		errors++;
	} else {
		close(temp_path_fd);
		remove(buf);
	}
	my_free(buf);

	/* warn if user didn't specify any illegal macro output chars */
	if (illegal_output_chars == NULL) {
		logit(NSLOG_VERIFICATION_WARNING, TRUE, "%s", "Warning: Nothing specified for illegal_macro_output_chars variable!\n");
		warnings++;
	}
	else {
		char *p;
		for (p = illegal_output_chars; *p; p++) {
			illegal_output_char_map[(unsigned char)*p] = 1;
		}
	}

	if (verify_config) {
		printf("\n");
		printf("Total Warnings: %d\n", warnings);
		printf("Total Errors:   %d\n", errors);
	}

	if (test_scheduling == TRUE)
		gettimeofday(&tv[3], NULL);

	if (test_scheduling == TRUE) {

		if (verify_object_relationships == 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);
		else
			runtime[0] = 0.0;
		if (verify_circular_paths == TRUE)
			runtime[1] = (double)((double)(tv[2].tv_sec - tv[1].tv_sec) + (double)((tv[2].tv_usec - tv[1].tv_usec) / 1000.0) / 1000.0);
		else
			runtime[1] = 0.0;
		runtime[2] = (double)((double)(tv[3].tv_sec - tv[2].tv_sec) + (double)((tv[3].tv_usec - tv[2].tv_usec) / 1000.0) / 1000.0);
		runtime[3] = runtime[0] + runtime[1] + runtime[2];

		printf("Timing information on configuration verification is listed below.\n\n");

		printf("CONFIG VERIFICATION TIMES          (* = Potential for speedup with -x option)\n");
		printf("----------------------------------\n");
		printf("Object Relationships: %.6lf sec\n", runtime[0]);
		printf("Circular Paths:       %.6lf sec  *\n", runtime[1]);
		printf("Misc:                 %.6lf sec\n", runtime[2]);
		printf("                      ============\n");
		printf("TOTAL:                %.6lf sec  * = %.6lf sec (%.1f%%) estimated savings\n", runtime[3], runtime[1], (runtime[1] / runtime[3]) * 100.0);
		printf("\n\n");
	}

	return (errors > 0) ? ERROR : OK;
}



/* do a pre-flight check to make sure object relationships make sense */
int pre_flight_object_check(int *w, int *e) {
	contact *temp_contact = NULL;
	commandsmember *temp_commandsmember = NULL;
	contactgroup *temp_contactgroup = NULL;
	contactsmember *temp_contactsmember = NULL;
	contactgroupsmember *temp_contactgroupsmember = NULL;
	host *temp_host = NULL;
	host *temp_host2 = NULL;
	hostsmember *temp_hostsmember = NULL;
	hostgroup *temp_hostgroup = NULL;
	servicegroup *temp_servicegroup = NULL;
	servicesmember *temp_servicesmember = NULL;
	service *temp_service = NULL;
	service *temp_service2 = NULL;
	command *temp_command = NULL;
	timeperiod *temp_timeperiod = NULL;
	timeperiod *temp_timeperiod2 = NULL;
	timeperiodexclusion *temp_timeperiodexclusion = NULL;
	serviceescalation *temp_se = NULL;
	hostescalation *temp_he = NULL;
	servicedependency *temp_sd = NULL;
	hostdependency *temp_hd = NULL;
	escalation_condition *temp_escalation_condition = NULL;
	module *temp_module = NULL;
	char *buf = NULL;
	char *temp_command_name = "";
	int total_objects = 0;
	int warnings = 0;
	int errors = 0;


#ifdef TEST
	void *ptr = NULL;
	char *buf1 = "";
	char *buf2 = "";
	buf1 = "temptraxe1";
	buf2 = "Probe 2";
	for (temp_se = get_first_serviceescalation_by_service(buf1, buf2, &ptr); temp_se != NULL; temp_se = get_next_serviceescalation_by_service(buf1, buf2, &ptr)) {
		printf("FOUND ESCALATION FOR SVC '%s'/'%s': %d-%d/%.3f, PTR=%p\n", buf1, buf2, temp_se->first_notification, temp_se->last_notification, temp_se->notification_interval, ptr);
	}
	for (temp_he = get_first_hostescalation_by_host(buf1, &ptr); temp_he != NULL; temp_he = get_next_hostescalation_by_host(buf1, &ptr)) {
		printf("FOUND ESCALATION FOR HOST '%s': %d-%d/%d, PTR=%p\n", buf1, temp_he->first_notification, temp_he->last_notification, temp_he->notification_interval, ptr);
	}
#endif

	/* bail out if we aren't supposed to verify object relationships */
	if (verify_object_relationships == FALSE)
		return OK;


	/*****************************************/
	/* check each service...                 */
	/*****************************************/
	if (verify_config)
		printf("Checking services...\n");
	if (get_service_count() == 0) {
		logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: There are no services defined!");
		warnings++;
	}
	total_objects = 0;
	for (temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {

		total_objects++;

		/* check for a valid host */
		temp_host = find_host(temp_service->host_name);

		/* we couldn't find an associated host! */
		if (!temp_host) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in service '%s' (%s) not defined anywhere!", temp_service->host_name, temp_service->description, format_debuginfo(temp_service));
			errors++;
		}

		/* save the host pointer for later */
		temp_service->host_ptr = temp_host;

		/* add a reverse link from the host to the service for faster lookups later */
		add_service_link_to_host(temp_host, temp_service);

		/* check the event handler command */
		if (temp_service->event_handler != NULL) {

			/* check the event handler command */
			buf = (char *)strdup(temp_service->event_handler);

			/* get the command name, leave any arguments behind */
			temp_command_name = my_strtok(buf, "!");

			temp_command = find_command(temp_command_name);
			if (temp_command == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified in service '%s' for host '%s' (%s) not defined anywhere", temp_command_name, temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
				errors++;
			}

			my_free(buf);

			/* save the pointer to the event handler for later */
			temp_service->event_handler_ptr = temp_command;
		}

		/* check the service check_command */
		buf = (char *)strdup(temp_service->service_check_command);

		/* get the command name, leave any arguments behind */
		temp_command_name = my_strtok(buf, "!");

		temp_command = find_command(temp_command_name);
		if (temp_command == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service check command '%s' specified in service '%s' for host '%s' (%s) not defined anywhere!", temp_command_name, temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
			errors++;
		}

		my_free(buf);

		/* save the pointer to the check command for later */
		temp_service->check_command_ptr = temp_command;

		/* check for sane recovery options */
		if (temp_service->notify_on_recovery == TRUE && temp_service->notify_on_warning == FALSE && temp_service->notify_on_critical == FALSE) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in service '%s' for host '%s' (%s) doesn't make any sense - specify warning and/or critical options as well", temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
			warnings++;
		}

		/* check for valid contacts */
		for (temp_contactsmember = temp_service->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {

			temp_contact = find_contact(temp_contactsmember->contact_name);

			if (temp_contact == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in service '%s' for host '%s' (%s) is not defined anywhere!", temp_contactsmember->contact_name, temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
				errors++;
			}

			/* save the contact pointer for later */
			temp_contactsmember->contact_ptr = temp_contact;
		}

		/* check all contact groupss */
		for (temp_contactgroupsmember = temp_service->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {

			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);

			if (temp_contactgroup == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in service '%s' for host '%s' (%s) is not defined anywhere!", temp_contactgroupsmember->group_name, temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
				errors++;
			}

			/* save the contact group pointer for later */
			temp_contactgroupsmember->group_ptr = temp_contactgroup;
		}

		/* check to see if there is at least one contact/group */
		if (temp_service->contacts == NULL && temp_service->contact_groups == NULL) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' (%s) has no default contacts or contactgroups defined!", temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
			warnings++;
		}

		/* verify service check timeperiod */
		if (temp_service->check_period == NULL) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' (%s) has no check time period defined!", temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
			warnings++;
		} else {
			temp_timeperiod = find_timeperiod(temp_service->check_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Check period '%s' specified for service '%s' on host '%s' (%s) is not defined anywhere!", temp_service->check_period, temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
				errors++;
			}

			/* save the pointer to the check timeperiod for later */
			temp_service->check_period_ptr = temp_timeperiod;
		}

		/* check service notification timeperiod */
		if (temp_service->notification_period == NULL) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' (%s) has no notification time period defined!", temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
			warnings++;
		}

		else {
			temp_timeperiod = find_timeperiod(temp_service->notification_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Notification period '%s' specified for service '%s' on host '%s' (%s) is not defined anywhere!", temp_service->notification_period, temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
				errors++;
			}

			/* save the pointer to the notification timeperiod for later */
			temp_service->notification_period_ptr = temp_timeperiod;
		}

		/* see if the notification interval is less than the check interval */
		if (temp_service->notification_interval < temp_service->check_interval && temp_service->notification_interval != 0) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' (%s) has a notification interval less than its check interval!  Notifications are only re-sent after checks are made, so the effective notification interval will be that of the check interval.", temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
			warnings++;
		}

		/* check for illegal characters in service description */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_service->description) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The description string for service '%s' on host '%s' (%s) contains one or more illegal characters.", temp_service->description, temp_service->host_name, format_debuginfo(temp_service));
				errors++;
			}
		}
	}

	if (verify_config)
		printf("\tChecked %d services.\n", total_objects);



	/*****************************************/
	/* check all hosts...                    */
	/*****************************************/
	if (verify_config)
		printf("Checking hosts...\n");

	if (get_host_count() == 0) {
		logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: There are no hosts defined!");
		warnings++;
	}

	total_objects = 0;
	for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {

		total_objects++;

		/* make sure each host has at least one service associated with it */
		if(temp_host->total_services == 0 && verify_config >= 2) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' (%s) has no services associated with it!", temp_host->name, format_debuginfo(temp_host));
			warnings++;
		}

		/* check the event handler command */
		if (temp_host->event_handler != NULL) {

			/* check the event handler command */
			buf = (char *)strdup(temp_host->event_handler);

			/* get the command name, leave any arguments behind */
			temp_command_name = my_strtok(buf, "!");

			temp_command = find_command(temp_command_name);
			if (temp_command == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified for host '%s' (%s) not defined anywhere", temp_command_name, temp_host->name, format_debuginfo(temp_host));
				errors++;
			}

			my_free(buf);

			/* save the pointer to the event handler command for later */
			temp_host->event_handler_ptr = temp_command;
		}

		/* hosts that don't have check commands defined shouldn't ever be checked... */
		if (temp_host->host_check_command != NULL) {

			/* check the host check_command */
			buf = (char *)strdup(temp_host->host_check_command);

			/* get the command name, leave any arguments behind */
			temp_command_name = my_strtok(buf, "!");

			temp_command = find_command(temp_command_name);
			if (temp_command == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host check command '%s' specified for host '%s' (%s) is not defined anywhere!", temp_command_name, temp_host->name, format_debuginfo(temp_host));
				errors++;
			}

			/* save the pointer to the check command for later */
			temp_host->check_command_ptr = temp_command;

			my_free(buf);
		}

		/* check host check timeperiod */
		if (temp_host->check_period != NULL) {
			temp_timeperiod = find_timeperiod(temp_host->check_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Check period '%s' specified for host '%s' (%s) is not defined anywhere!", temp_host->check_period, temp_host->name, format_debuginfo(temp_host));
				errors++;
			}

			/* save the pointer to the check timeperiod for later */
			temp_host->check_period_ptr = temp_timeperiod;
		}

		/* check all contacts */
		for (temp_contactsmember = temp_host->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {

			temp_contact = find_contact(temp_contactsmember->contact_name);

			if (temp_contact == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in host '%s' (%s) is not defined anywhere!", temp_contactsmember->contact_name, temp_host->name, format_debuginfo(temp_host));
				errors++;
			}

			/* save the contact pointer for later */
			temp_contactsmember->contact_ptr = temp_contact;
		}

		/* check all contact groups */
		for (temp_contactgroupsmember = temp_host->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {

			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);

			if (temp_contactgroup == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in host '%s' (%s) is not defined anywhere!", temp_contactgroupsmember->group_name, temp_host->name, format_debuginfo(temp_host));
				errors++;
			}

			/* save the contact group pointer for later */
			temp_contactgroupsmember->group_ptr = temp_contactgroup;
		}

		/* check to see if there is at least one contact/group */
		if (temp_host->contacts == NULL && temp_host->contact_groups == NULL) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' (%s) has no default contacts or contactgroups defined!", temp_host->name, format_debuginfo(temp_host));
			warnings++;
		}

		/* check notification timeperiod */
		if (temp_host->notification_period != NULL) {
			temp_timeperiod = find_timeperiod(temp_host->notification_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Notification period '%s' specified for host '%s' (%s) is not defined anywhere!", temp_host->notification_period, temp_host->name, format_debuginfo(temp_host));
				errors++;
			}

			/* save the pointer to the notification timeperiod for later */
			temp_host->notification_period_ptr = temp_timeperiod;
		}

		/* check all parent parent host */
		for (temp_hostsmember = temp_host->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {

			if ((temp_host2 = find_host(temp_hostsmember->host_name)) == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: '%s' is not a valid parent for host '%s' (%s)!", temp_hostsmember->host_name, temp_host->name, format_debuginfo(temp_host));
				errors++;
			}

			/* save the parent host pointer for later */
			temp_hostsmember->host_ptr = temp_host2;

			/* add a reverse (child) link to make searches faster later on */
			add_child_link_to_host(temp_host2, temp_host);
		}

		/* check for sane recovery options */
		if (temp_host->notify_on_recovery == TRUE && temp_host->notify_on_down == FALSE && temp_host->notify_on_unreachable == FALSE) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in host '%s' (%s) definition doesn't make any sense - specify down and/or unreachable options as well", temp_host->name, format_debuginfo(temp_host));
			warnings++;
		}

		/* check for illegal characters in host name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_host->name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of host '%s' (%s) contains one or more illegal characters.", temp_host->name, format_debuginfo(temp_host));
				errors++;
			}
		}
	}


	if (verify_config)
		printf("\tChecked %d hosts.\n", total_objects);


	/*****************************************/
	/* check each host group...              */
	/*****************************************/
	if (verify_config)
		printf("Checking host groups...\n");
	for (temp_hostgroup = hostgroup_list, total_objects = 0; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next, total_objects++) {

		/* check all group members */
		for (temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {

			temp_host = find_host(temp_hostsmember->host_name);
			if (temp_host == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in host group '%s' (%s) is not defined anywhere!", temp_hostsmember->host_name, temp_hostgroup->group_name, format_debuginfo(temp_hostgroup));
				errors++;
			}

			/* save a pointer to this hostgroup for faster host/group membership lookups later */
			else
				add_object_to_objectlist(&temp_host->hostgroups_ptr, (void *)temp_hostgroup);

			/* save host pointer for later */
			temp_hostsmember->host_ptr = temp_host;
		}

		/* check for illegal characters in hostgroup name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_hostgroup->group_name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of hostgroup '%s' (%s) contains one or more illegal characters.", temp_hostgroup->group_name, format_debuginfo(temp_hostgroup));
				errors++;
			}
		}
	}

	if (verify_config)
		printf("\tChecked %d host groups.\n", total_objects);


	/*****************************************/
	/* check each service group...           */
	/*****************************************/
	if (verify_config)
		printf("Checking service groups...\n");
	for (temp_servicegroup = servicegroup_list, total_objects = 0; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next, total_objects++) {

		/* check all group members */
		for (temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {

			temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description);
			if (temp_service == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service group '%s' (%s) is not defined anywhere!", temp_servicesmember->service_description, temp_servicesmember->host_name, temp_servicegroup->group_name, format_debuginfo(temp_servicegroup));
				errors++;
			}

			/* save a pointer to this servicegroup for faster service/group membership lookups later */
			else
				add_object_to_objectlist(&temp_service->servicegroups_ptr, (void *)temp_servicegroup);

			/* save service pointer for later */
			temp_servicesmember->service_ptr = temp_service;
		}

		/* check for illegal characters in servicegroup name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_servicegroup->group_name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of servicegroup '%s' (%s) contains one or more illegal characters.", temp_servicegroup->group_name, format_debuginfo(temp_servicegroup));
				errors++;
			}
		}
	}

	if (verify_config)
		printf("\tChecked %d service groups.\n", total_objects);



	/*****************************************/
	/* check all contacts...                 */
	/*****************************************/
	if (verify_config)
		printf("Checking contacts...\n");
	if (contact_list == NULL) {
		logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: There are no contacts defined!");
		warnings++;
	}
	for (temp_contact = contact_list, total_objects = 0; temp_contact != NULL; temp_contact = temp_contact->next, total_objects++) {

		/* check service notification commands */
		if (temp_contact->service_notification_commands == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' (%s) has no service notification commands defined!", temp_contact->name, format_debuginfo(temp_contact));
			errors++;
		} else for (temp_commandsmember = temp_contact->service_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {

				/* check the host notification command */
				buf = (char *)strdup(temp_commandsmember->command);

				/* get the command name, leave any arguments behind */
				temp_command_name = my_strtok(buf, "!");

				temp_command = find_command(temp_command_name);
				if (temp_command == NULL) {
					logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification command '%s' specified for contact '%s' (%s) is not defined anywhere!", temp_command_name, temp_contact->name, format_debuginfo(temp_contact));
					errors++;
				}

				/* save pointer to the command for later */
				temp_commandsmember->command_ptr = temp_command;

				my_free(buf);
			}

		/* check host notification commands */
		if (temp_contact->host_notification_commands == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' (%s) has no host notification commands defined!", temp_contact->name, format_debuginfo(temp_contact));
			errors++;
		} else for (temp_commandsmember = temp_contact->host_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {

				/* check the host notification command */
				buf = (char *)strdup(temp_commandsmember->command);

				/* get the command name, leave any arguments behind */
				temp_command_name = my_strtok(buf, "!");

				temp_command = find_command(temp_command_name);
				if (temp_command == NULL) {
					logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification command '%s' specified for contact '%s' (%s) is not defined anywhere!", temp_command_name, temp_contact->name, format_debuginfo(temp_contact));
					errors++;
				}

				/* save pointer to the command for later */
				temp_commandsmember->command_ptr = temp_command;

				my_free(buf);
			}

		/* check service notification timeperiod */
		if (temp_contact->service_notification_period == NULL) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' (%s) has no service notification time period defined!", temp_contact->name, format_debuginfo(temp_contact));
			warnings++;
		}

		else {
			temp_timeperiod = find_timeperiod(temp_contact->service_notification_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification period '%s' specified for contact '%s' (%s) is not defined anywhere!", temp_contact->service_notification_period, temp_contact->name, format_debuginfo(temp_contact));
				errors++;
			}

			/* save the pointer to the service notification timeperiod for later */
			temp_contact->service_notification_period_ptr = temp_timeperiod;
		}

		/* check host notification timeperiod */
		if (temp_contact->host_notification_period == NULL) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' (%s) has no host notification time period defined!", temp_contact->name, format_debuginfo(temp_contact));
			warnings++;
		}

		else {
			temp_timeperiod = find_timeperiod(temp_contact->host_notification_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification period '%s' specified for contact '%s' (%s) is not defined anywhere!", temp_contact->host_notification_period, temp_contact->name, format_debuginfo(temp_contact));
				errors++;
			}

			/* save the pointer to the host notification timeperiod for later */
			temp_contact->host_notification_period_ptr = temp_timeperiod;
		}

		/* check for sane host recovery options */
		if (temp_contact->notify_on_host_recovery == TRUE && temp_contact->notify_on_host_down == FALSE && temp_contact->notify_on_host_unreachable == FALSE) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host recovery notification option for contact '%s' (%s) doesn't make any sense - specify down and/or unreachable options as well", temp_contact->name, format_debuginfo(temp_contact));
			warnings++;
		}

		/* check for sane service recovery options */
		if (temp_contact->notify_on_service_recovery == TRUE && temp_contact->notify_on_service_critical == FALSE && temp_contact->notify_on_service_warning == FALSE) {
			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service recovery notification option for contact '%s' (%s) doesn't make any sense - specify critical and/or warning options as well", temp_contact->name, format_debuginfo(temp_contact));
			warnings++;
		}

		/* check for illegal characters in contact name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_contact->name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact '%s' (%s) contains one or more illegal characters.", temp_contact->name, format_debuginfo(temp_contact));
				errors++;
			}
		}
	}

	if (verify_config)
		printf("\tChecked %d contacts.\n", total_objects);



	/*****************************************/
	/* check each contact group...           */
	/*****************************************/
	if (verify_config)
		printf("Checking contact groups...\n");
	for (temp_contactgroup = contactgroup_list, total_objects = 0; temp_contactgroup != NULL; temp_contactgroup = temp_contactgroup->next, total_objects++) {

		/* check all the group members */
		for (temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {

			temp_contact = find_contact(temp_contactsmember->contact_name);
			if (temp_contact == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in contact group '%s' (%s) is not defined anywhere!", temp_contactsmember->contact_name, temp_contactgroup->group_name, format_debuginfo(temp_contactgroup));
				errors++;
			}

			/* save a pointer to this contactgroup for faster contact/group membership lookups later */
			else
				add_object_to_objectlist(&temp_contact->contactgroups_ptr, (void *)temp_contactgroup);

			/* save the contact pointer for later */
			temp_contactsmember->contact_ptr = temp_contact;
		}

		/* check for illegal characters in contactgroup name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_contactgroup->group_name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact group '%s' (%s) contains one or more illegal characters.", temp_contactgroup->group_name, format_debuginfo(temp_contactgroup));
				errors++;
			}
		}
	}

	if (verify_config)
		printf("\tChecked %d contact groups.\n", total_objects);



	/*****************************************/
	/* check all service escalations...     */
	/*****************************************/
	if (verify_config)
		printf("Checking service escalations...\n");

	for (temp_se = serviceescalation_list, total_objects = 0; temp_se != NULL; temp_se = temp_se->next, total_objects++) {

		/* find the service */
		temp_service = find_service(temp_se->host_name, temp_se->description);
		if (temp_service == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service escalation (%s) is not defined anywhere!", temp_se->description, temp_se->host_name, format_debuginfo(temp_se));
			errors++;
		}

		/* save the service pointer for later */
		temp_se->service_ptr = temp_service;

		/* find the timeperiod */
		if (temp_se->escalation_period != NULL) {
			temp_timeperiod = find_timeperiod(temp_se->escalation_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in service escalation for service '%s' on host '%s' (%s) is not defined anywhere!", temp_se->escalation_period, temp_se->description, temp_se->host_name, format_debuginfo(temp_se));
				errors++;
			}

			/* save the timeperiod pointer for later */
			temp_se->escalation_period_ptr = temp_timeperiod;
		}

		/* find the contacts */
		for (temp_contactsmember = temp_se->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {

			/* find the contact */
			temp_contact = find_contact(temp_contactsmember->contact_name);
			if (temp_contact == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in service escalation for service '%s' on host '%s' (%s) is not defined anywhere!", temp_contactsmember->contact_name, temp_se->description, temp_se->host_name, format_debuginfo(temp_se));
				errors++;
			}

			/* save the contact pointer for later */
			temp_contactsmember->contact_ptr = temp_contact;
		}

		/* check all contact groups */
		for (temp_contactgroupsmember = temp_se->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {

			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);

			if (temp_contactgroup == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in service escalation for service '%s' on host '%s' (%s) is not defined anywhere!", temp_contactgroupsmember->group_name, temp_se->description, temp_se->host_name, format_debuginfo(temp_se));
				errors++;
			}

			/* save the contact group pointer for later */
			temp_contactgroupsmember->group_ptr = temp_contactgroup;
		}

		/* check escalation conditions */
		for (temp_escalation_condition = temp_se->condition; temp_escalation_condition != NULL; temp_escalation_condition = temp_escalation_condition->next) {

			/* find the host */
			temp_host = find_host(temp_escalation_condition->host_name);
			if (temp_host == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in service escalation condition (%s) is not defined anywhere!", temp_escalation_condition->host_name, format_debuginfo(temp_se));
				errors++;
			}

			else if (temp_escalation_condition->service_description != NULL) {
				/* find the service */
				temp_service = find_service(temp_escalation_condition->host_name, temp_escalation_condition->service_description);
				if (temp_service == NULL) {
					logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service escalation (%s) is not defined anywhere!", temp_escalation_condition->service_description, temp_escalation_condition->host_name, format_debuginfo(temp_se));
					errors++;
				}
			}
		}

	}

	if (verify_config)
		printf("\tChecked %d service escalations.\n", total_objects);



	/*****************************************/
	/* check all service dependencies...     */
	/*****************************************/
	if (verify_config)
		printf("Checking service dependencies...\n");

	for (temp_sd = servicedependency_list, total_objects = 0; temp_sd != NULL; temp_sd = temp_sd->next, total_objects++) {

		/* find the dependent service */
		temp_service = find_service(temp_sd->dependent_host_name, temp_sd->dependent_service_description);
		if (temp_service == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependent service '%s' on host '%s' specified in service dependency for service '%s' on host '%s' (%s) is not defined anywhere!", temp_sd->dependent_service_description, temp_sd->dependent_host_name, temp_sd->service_description, temp_sd->host_name, format_debuginfo(temp_sd));
			errors++;
		}

		/* save pointer for later */
		temp_sd->dependent_service_ptr = temp_service;

		/* find the service we're depending on */
		temp_service2 = find_service(temp_sd->host_name, temp_sd->service_description);
		if (temp_service2 == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service dependency for service '%s' on host '%s' (%s) is not defined anywhere!", temp_sd->service_description, temp_sd->host_name, temp_sd->dependent_service_description, temp_sd->dependent_host_name, format_debuginfo(temp_sd));
			errors++;
		}

		/* save pointer for later */
		temp_sd->master_service_ptr = temp_service2;

		/* make sure they're not the same service */
		if (temp_service == temp_service2) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service dependency definition for service '%s' on host '%s' (%s) is circular (it depends on itself)!", temp_sd->dependent_service_description, temp_sd->dependent_host_name, format_debuginfo(temp_sd));
			errors++;
		}

		/* find the timeperiod */
		if (temp_sd->dependency_period != NULL) {
			temp_timeperiod = find_timeperiod(temp_sd->dependency_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependency period '%s' specified in service dependency for service '%s' on host '%s' (%s) is not defined anywhere!", temp_sd->dependency_period, temp_sd->dependent_service_description, temp_sd->dependent_host_name, format_debuginfo(temp_sd));
				errors++;
			}

			/* save the timeperiod pointer for later */
			temp_sd->dependency_period_ptr = temp_timeperiod;
		}
	}

	if (verify_config)
		printf("\tChecked %d service dependencies.\n", total_objects);



	/*****************************************/
	/* check all host escalations...     */
	/*****************************************/
	if (verify_config)
		printf("Checking host escalations...\n");

	for (temp_he = hostescalation_list, total_objects = 0; temp_he != NULL; temp_he = temp_he->next, total_objects++) {

		/* find the host */
		temp_host = find_host(temp_he->host_name);
		if (temp_host == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in host escalation is not defined anywhere!", temp_he->host_name);
			errors++;
		}

		/* save the host pointer for later */
		temp_he->host_ptr = temp_host;

		/* find the timeperiod */
		if (temp_he->escalation_period != NULL) {
			temp_timeperiod = find_timeperiod(temp_he->escalation_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in host escalation for host '%s' (%s) is not defined anywhere!", temp_he->escalation_period, temp_he->host_name, format_debuginfo(temp_he));
				errors++;
			}

			/* save the timeperiod pointer for later */
			temp_he->escalation_period_ptr = temp_timeperiod;
		}

		/* find the contacts */
		for (temp_contactsmember = temp_he->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {

			/* find the contact*/
			temp_contact = find_contact(temp_contactsmember->contact_name);
			if (temp_contact == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in host escalation for host '%s' (%s) is not defined anywhere!", temp_contactsmember->contact_name, temp_he->host_name, format_debuginfo(temp_he));
				errors++;
			}

			/* save the contact pointer for later */
			temp_contactsmember->contact_ptr = temp_contact;
		}

		/* check all contact groups */
		for (temp_contactgroupsmember = temp_he->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {

			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);

			if (temp_contactgroup == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in host escalation for host '%s' (%s) is not defined anywhere!", temp_contactgroupsmember->group_name, temp_he->host_name, format_debuginfo(temp_he));
				errors++;
			}

			/* save the contact group pointer for later */
			temp_contactgroupsmember->group_ptr = temp_contactgroup;
		}

		/* check escalation conditions */
		for (temp_escalation_condition = temp_he->condition; temp_escalation_condition != NULL; temp_escalation_condition = temp_escalation_condition->next) {

			/* find the host */
			temp_host = find_host(temp_escalation_condition->host_name);
			if (temp_host == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in service escalation condition (%s) is not defined anywhere!", temp_escalation_condition->host_name, format_debuginfo(temp_he));
				errors++;
			}

			else if (temp_escalation_condition->service_description != NULL) {
				/* find the service */
				temp_service = find_service(temp_escalation_condition->host_name, temp_escalation_condition->service_description);
				if (temp_service == NULL) {
					logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service escalation (%s) is not defined anywhere!", temp_escalation_condition->service_description, temp_escalation_condition->host_name, format_debuginfo(temp_he));
					errors++;
				}
			}
		}

	}

	if (verify_config)
		printf("\tChecked %d host escalations.\n", total_objects);



	/*****************************************/
	/* check all host dependencies...     */
	/*****************************************/
	if (verify_config)
		printf("Checking host dependencies...\n");

	for (temp_hd = hostdependency_list, total_objects = 0; temp_hd != NULL; temp_hd = temp_hd->next, total_objects++) {

		/* find the dependent host */
		temp_host = find_host(temp_hd->dependent_host_name);
		if (temp_host == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependent host specified in host dependency for host '%s' (%s) is not defined anywhere!", temp_hd->dependent_host_name, format_debuginfo(temp_hd));
			errors++;
		}

		/* save pointer for later */
		temp_hd->dependent_host_ptr = temp_host;

		/* find the host we're depending on */
		temp_host2 = find_host(temp_hd->host_name);
		if (temp_host2 == NULL) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host specified in host dependency for host '%s' (%s) is not defined anywhere!", temp_hd->dependent_host_name, format_debuginfo(temp_hd));
			errors++;
		}

		/* save pointer for later */
		temp_hd->master_host_ptr = temp_host2;

		/* make sure they're not the same host */
		if (temp_host == temp_host2) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host dependency definition for host '%s' (%s) is circular (it depends on itself)!", temp_hd->dependent_host_name, format_debuginfo(temp_hd));
			errors++;
		}

		/* find the timeperiod */
		if (temp_hd->dependency_period != NULL) {
			temp_timeperiod = find_timeperiod(temp_hd->dependency_period);
			if (temp_timeperiod == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependency period '%s' specified in host dependency for host '%s' (%s) is not defined anywhere!", temp_hd->dependency_period, temp_hd->dependent_host_name, format_debuginfo(temp_hd));
				errors++;
			}

			/* save the timeperiod pointer for later */
			temp_hd->dependency_period_ptr = temp_timeperiod;
		}
	}

	if (verify_config)
		printf("\tChecked %d host dependencies.\n", total_objects);



	/*****************************************/
	/* check all commands...                 */
	/*****************************************/
	if (verify_config)
		printf("Checking commands...\n");

	for (temp_command = command_list, total_objects = 0; temp_command != NULL; temp_command = temp_command->next, total_objects++) {

		/* check for illegal characters in command name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_command->name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of command '%s' (%s) contains one or more illegal characters.", temp_command->name, format_debuginfo(temp_command));
				errors++;
			}
		}
	}

	if (verify_config)
		printf("\tChecked %d commands.\n", total_objects);



	/*****************************************/
	/* check all timeperiods...              */
	/*****************************************/
	if (verify_config)
		printf("Checking time periods...\n");

	for (temp_timeperiod = timeperiod_list, total_objects = 0; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next, total_objects++) {

		/* check for illegal characters in timeperiod name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_timeperiod->name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of time period '%s' (%s) contains one or more illegal characters.", temp_timeperiod->name, format_debuginfo(temp_timeperiod));
				errors++;
			}
		}

		/* check for valid timeperiod names in exclusion list */
		for (temp_timeperiodexclusion = temp_timeperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) {

			temp_timeperiod2 = find_timeperiod(temp_timeperiodexclusion->timeperiod_name);
			if (temp_timeperiod2 == NULL) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Excluded time period '%s' specified in timeperiod '%s' (%s) is not defined anywhere!", temp_timeperiodexclusion->timeperiod_name, temp_timeperiod->name, format_debuginfo(temp_timeperiod));
				errors++;
			}

			/* save the timeperiod pointer for later */
			temp_timeperiodexclusion->timeperiod_ptr = temp_timeperiod2;
		}
	}

	if (verify_config)
		printf("\tChecked %d time periods.\n", total_objects);


	/*****************************************/
	/* check all modules...                  */
	/*****************************************/
	if (verify_config)
		printf("Checking modules...\n");

	for (temp_module = module_list, total_objects = 0; temp_module != NULL; temp_module = temp_module->next, total_objects++) {

		/* check for illegal characters in module name */
		if (use_precached_objects == FALSE) {
			if (contains_illegal_object_chars(temp_module->name) == TRUE) {
				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of module '%s' (%s) contains one or more illegal characters.", temp_module->name, format_debuginfo(temp_module));
				errors++;
			}
		}
	}

	if (verify_config)
		printf("\tChecked %d modules.\n", total_objects);


	/* update warning and error count */
	*w += warnings;
	*e += errors;

	return (errors > 0) ? ERROR : OK;
}


/* dfs status values */
#define DFS_UNCHECKED                    0  /* default value */
#define DFS_TEMP_CHECKED                 1  /* check just one time */
#define DFS_OK                           2  /* no problem */
#define DFS_NEAR_LOOP                    3  /* has trouble sons */
#define DFS_LOOPY                        4  /* is a part of a loop */

#define dfs_get_status(h) h->circular_path_checked
#define dfs_unset_status(h) h->circular_path_checked = 0
#define dfs_set_status(h, flag) h->circular_path_checked = (flag)
#define dfs_host_status(h) (h ? dfs_get_status(h) : DFS_OK)

/**
 * Modified version of Depth-first Search
 * http://en.wikipedia.org/wiki/Depth-first_search
 */
static int dfs_host_path(host *root) {
	hostsmember *child = NULL;

	if (!root)
		return DFS_NEAR_LOOP;

	if (dfs_get_status(root) != DFS_UNCHECKED)
		return dfs_get_status(root);

	/* Mark the root temporary checked */
	dfs_set_status(root, DFS_TEMP_CHECKED);

	/* We are scanning the children */
	for (child = root->child_hosts; child != NULL; child = child->next) {
		int child_status = dfs_get_status(child->host_ptr);

		/* If a child is not checked, check it */
		if (child_status == DFS_UNCHECKED)
			child_status = dfs_host_path(child->host_ptr);

		/* If a child already temporary checked, its a problem,
		 * loop inside, and its a acked status */
		if (child_status == DFS_TEMP_CHECKED) {
			dfs_set_status(child->host_ptr, DFS_LOOPY);
			dfs_set_status(root, DFS_LOOPY);
		}

		/* If a child already temporary checked, its a problem, loop inside */
		if (child_status == DFS_NEAR_LOOP || child_status == DFS_LOOPY) {
			/* if a node is know to be part of a loop, do not let it be less */
			if (dfs_get_status(root) != DFS_LOOPY)
				dfs_set_status(root, DFS_NEAR_LOOP);

			/* we already saw this child, it's a problem */
			dfs_set_status(child->host_ptr, DFS_LOOPY);
		}
	}

	/*
	 * If root have been modified, do not set it OK
	 * A node is OK if and only if all of his children are OK
	 * If it does not have child, goes ok
	 */
	if (dfs_get_status(root) == DFS_TEMP_CHECKED)
		dfs_set_status(root, DFS_OK);
	return dfs_get_status(root);
}


/* check for circular paths and dependencies */
int pre_flight_circular_check(int *w, int *e) {
	host *temp_host = NULL;
	servicedependency *temp_sd = NULL;
	servicedependency *temp_sd2 = NULL;
	hostdependency *temp_hd = NULL;
	hostdependency *temp_hd2 = NULL;
	int found = FALSE;
	int warnings = 0;
	int errors = 0;


	/* bail out if we aren't supposed to verify circular paths */
	if (verify_circular_paths == FALSE)
		return OK;


	/********************************************/
	/* check for circular paths between hosts   */
	/********************************************/
	if (verify_config)
		printf("Checking for circular paths between hosts...\n");

	/* check routes between all hosts */
	found = FALSE;


	/* We clean the dsf status from previous check */
	for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
		dfs_set_status(temp_host, DFS_UNCHECKED);
	}

	for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
		if (dfs_host_path(temp_host) == DFS_LOOPY)
			errors = 1;
	}

	for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
		if (dfs_get_status(temp_host) == DFS_LOOPY)
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The host '%s' is part of a circular parent/child chain!", temp_host->name);
		/* clean DFS status */
		dfs_set_status(temp_host, DFS_UNCHECKED);
	}


	/********************************************/
	/* check for circular dependencies         */
	/********************************************/
	if (verify_config)
		printf("Checking for circular host and service dependencies...\n");

	/* check execution dependencies between all services */
	for (temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) {

		/* clear checked flag for all dependencies */
		for (temp_sd2 = servicedependency_list; temp_sd2 != NULL; temp_sd2 = temp_sd2->next)
			temp_sd2->circular_path_checked = FALSE;

		found = check_for_circular_servicedependency_path(temp_sd, temp_sd, EXECUTION_DEPENDENCY);
		if (found == TRUE) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular execution dependency (which could result in a deadlock) exists for service '%s' on host '%s' (%s)!", temp_sd->service_description, temp_sd->host_name, format_debuginfo(temp_sd));
			errors++;
		}
	}

	/* check notification dependencies between all services */
	for (temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) {

		/* clear checked flag for all dependencies */
		for (temp_sd2 = servicedependency_list; temp_sd2 != NULL; temp_sd2 = temp_sd2->next)
			temp_sd2->circular_path_checked = FALSE;

		found = check_for_circular_servicedependency_path(temp_sd, temp_sd, NOTIFICATION_DEPENDENCY);
		if (found == TRUE) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular notification dependency (which could result in a deadlock) exists for service '%s' on host '%s' (%s)!", temp_sd->service_description, temp_sd->host_name, format_debuginfo(temp_sd));
			errors++;
		}
	}

	/* check execution dependencies between all hosts */
	for (temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) {

		/* clear checked flag for all dependencies */
		for (temp_hd2 = hostdependency_list; temp_hd2 != NULL; temp_hd2 = temp_hd2->next)
			temp_hd2->circular_path_checked = FALSE;

		found = check_for_circular_hostdependency_path(temp_hd, temp_hd, EXECUTION_DEPENDENCY);
		if (found == TRUE) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular execution dependency (which could result in a deadlock) exists for host '%s' (%s)!", temp_hd->host_name, format_debuginfo(temp_hd));
			errors++;
		}
	}

	/* check notification dependencies between all hosts */
	for (temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) {

		/* clear checked flag for all dependencies */
		for (temp_hd2 = hostdependency_list; temp_hd2 != NULL; temp_hd2 = temp_hd2->next)
			temp_hd2->circular_path_checked = FALSE;

		found = check_for_circular_hostdependency_path(temp_hd, temp_hd, NOTIFICATION_DEPENDENCY);
		if (found == TRUE) {
			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular notification dependency (which could result in a deadlock) exists for host '%s' (%s)!", temp_hd->host_name, format_debuginfo(temp_hd));
			errors++;
		}
	}


	/* update warning and error count */
	*w += warnings;
	*e += errors;

	return (errors > 0) ? ERROR : OK;
}
