1 /*****************************************************************************
2  *
3  * XRDDEFAULT.C - Default external state retention routines for Nagios
4  *
5  *
6  * License:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  *****************************************************************************/
22 
23 
24 /*********** COMMON HEADER FILES ***********/
25 
26 #include "../include/config.h"
27 #include "../include/common.h"
28 #include "../include/objects.h"
29 #include "../include/statusdata.h"
30 #include "../include/macros.h"
31 #include "../include/nagios.h"
32 #include "../include/sretention.h"
33 #include "../include/comments.h"
34 #include "../include/downtime.h"
35 #include "xrddefault.h"
36 
37 
38 /******************************************************************/
39 /********************* INIT/CLEANUP FUNCTIONS *********************/
40 /******************************************************************/
41 
42 
43 /* initialize retention data */
xrddefault_initialize_retention_data(const char * cfgfile)44 int xrddefault_initialize_retention_data(const char *cfgfile) {
45 	nagios_macros *mac;
46 
47 	/* initialize locations if necessary  */
48 	if(retention_file == NULL)
49 		retention_file = (char *)strdup(DEFAULT_RETENTION_FILE);
50 
51 	/* make sure we have everything */
52 	if(retention_file == NULL)
53 		return ERROR;
54 
55 	mac = get_global_macros();
56 
57 	/* save the retention file macro */
58 	my_free(mac->x[MACRO_RETENTIONDATAFILE]);
59 	mac->x[MACRO_RETENTIONDATAFILE] = retention_file;
60 	if((mac->x[MACRO_RETENTIONDATAFILE] = (char *)strdup(retention_file)))
61 		strip(mac->x[MACRO_RETENTIONDATAFILE]);
62 
63 	return OK;
64 	}
65 
66 
67 /* cleanup retention data before terminating */
xrddefault_cleanup_retention_data(void)68 int xrddefault_cleanup_retention_data(void) {
69 
70 	/* free memory */
71 	my_free(retention_file);
72 
73 	return OK;
74 	}
75 
76 
77 /******************************************************************/
78 /**************** DEFAULT STATE OUTPUT FUNCTION *******************/
79 /******************************************************************/
80 
xrddefault_save_state_information(void)81 int xrddefault_save_state_information(void) {
82 	char *tmp_file = NULL;
83 	customvariablesmember *temp_customvariablesmember = NULL;
84 	time_t current_time = 0L;
85 	int result = OK;
86 	FILE *fp = NULL;
87 	host *temp_host = NULL;
88 	service *temp_service = NULL;
89 	contact *temp_contact = NULL;
90 	nagios_comment *temp_comment = NULL;
91 	scheduled_downtime *temp_downtime = NULL;
92 	int x = 0;
93 	int fd = 0;
94 	unsigned long host_attribute_mask = 0L;
95 	unsigned long service_attribute_mask = 0L;
96 	unsigned long contact_attribute_mask = 0L;
97 	unsigned long contact_host_attribute_mask = 0L;
98 	unsigned long contact_service_attribute_mask = 0L;
99 	unsigned long process_host_attribute_mask = 0L;
100 	unsigned long process_service_attribute_mask = 0L;
101 
102 
103 	log_debug_info(DEBUGL_FUNCTIONS, 0, "xrddefault_save_state_information()\n");
104 
105 	/* make sure we have everything */
106 	if(retention_file == NULL || temp_file == NULL) {
107 		logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: We don't have the required file names to store retention data!\n");
108 		return ERROR;
109 		}
110 
111 	/* open a safe temp file for output */
112 	asprintf(&tmp_file, "%sXXXXXX", temp_file);
113 	if(tmp_file == NULL)
114 		return ERROR;
115 	if((fd = mkstemp(tmp_file)) == -1)
116 		return ERROR;
117 
118 	log_debug_info(DEBUGL_RETENTIONDATA, 2, "Writing retention data to temp file '%s'\n", tmp_file);
119 
120 	fp = (FILE *)fdopen(fd, "w");
121 	if(fp == NULL) {
122 
123 		close(fd);
124 		unlink(tmp_file);
125 
126 		logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not open temp state retention file '%s' for writing!\n", tmp_file);
127 
128 		my_free(tmp_file);
129 
130 		return ERROR;
131 		}
132 
133 	/* what attributes should be masked out? */
134 	/* NOTE: host/service/contact-specific values may be added in the future, but for now we only have global masks */
135 	process_host_attribute_mask = retained_process_host_attribute_mask;
136 	process_service_attribute_mask = retained_process_service_attribute_mask;
137 	host_attribute_mask = retained_host_attribute_mask;
138 	service_attribute_mask = retained_service_attribute_mask;
139 	contact_host_attribute_mask = retained_contact_host_attribute_mask;
140 	contact_service_attribute_mask = retained_contact_service_attribute_mask;
141 
142 	/* write version info to status file */
143 	fprintf(fp, "########################################\n");
144 	fprintf(fp, "#      NAGIOS STATE RETENTION FILE\n");
145 	fprintf(fp, "#\n");
146 	fprintf(fp, "# THIS FILE IS AUTOMATICALLY GENERATED\n");
147 	fprintf(fp, "# BY NAGIOS.  DO NOT MODIFY THIS FILE!\n");
148 	fprintf(fp, "########################################\n");
149 
150 	time(&current_time);
151 
152 	/* write file info */
153 	fprintf(fp, "info {\n");
154 	fprintf(fp, "created=%llu\n", (unsigned long long)current_time);
155 	fprintf(fp, "version=%s\n", PROGRAM_VERSION);
156 	fprintf(fp, "last_update_check=%llu\n", (unsigned long long)last_update_check);
157 	fprintf(fp, "update_available=%d\n", update_available);
158 	fprintf(fp, "update_uid=%lu\n", update_uid);
159 	fprintf(fp, "last_version=%s\n", (last_program_version == NULL) ? "" : last_program_version);
160 	fprintf(fp, "new_version=%s\n", (new_program_version == NULL) ? "" : new_program_version);
161 	fprintf(fp, "}\n");
162 
163 	/* save program state information */
164 	fprintf(fp, "program {\n");
165 	fprintf(fp, "modified_host_attributes=%lu\n", (modified_host_process_attributes & ~process_host_attribute_mask));
166 	fprintf(fp, "modified_service_attributes=%lu\n", (modified_service_process_attributes & ~process_service_attribute_mask));
167 	fprintf(fp, "enable_notifications=%d\n", enable_notifications);
168 	fprintf(fp, "active_service_checks_enabled=%d\n", execute_service_checks);
169 	fprintf(fp, "passive_service_checks_enabled=%d\n", accept_passive_service_checks);
170 	fprintf(fp, "active_host_checks_enabled=%d\n", execute_host_checks);
171 	fprintf(fp, "passive_host_checks_enabled=%d\n", accept_passive_host_checks);
172 	fprintf(fp, "enable_event_handlers=%d\n", enable_event_handlers);
173 	fprintf(fp, "obsess_over_services=%d\n", obsess_over_services);
174 	fprintf(fp, "obsess_over_hosts=%d\n", obsess_over_hosts);
175 	fprintf(fp, "check_service_freshness=%d\n", check_service_freshness);
176 	fprintf(fp, "check_host_freshness=%d\n", check_host_freshness);
177 	fprintf(fp, "enable_flap_detection=%d\n", enable_flap_detection);
178 	fprintf(fp, "process_performance_data=%d\n", process_performance_data);
179 	fprintf(fp, "global_host_event_handler=%s\n", (global_host_event_handler == NULL) ? "" : global_host_event_handler);
180 	fprintf(fp, "global_service_event_handler=%s\n", (global_service_event_handler == NULL) ? "" : global_service_event_handler);
181 	fprintf(fp, "next_comment_id=%lu\n", next_comment_id);
182 	fprintf(fp, "next_downtime_id=%lu\n", next_downtime_id);
183 	fprintf(fp, "next_event_id=%lu\n", next_event_id);
184 	fprintf(fp, "next_problem_id=%lu\n", next_problem_id);
185 	fprintf(fp, "next_notification_id=%lu\n", next_notification_id);
186 	fprintf(fp, "}\n");
187 
188 	/* save host state information */
189 	for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
190 
191 		fprintf(fp, "host {\n");
192 		fprintf(fp, "host_name=%s\n", temp_host->name);
193 		fprintf(fp, "modified_attributes=%lu\n", (temp_host->modified_attributes & ~host_attribute_mask));
194 		fprintf(fp, "check_command=%s\n", (temp_host->check_command == NULL) ? "" : temp_host->check_command);
195 		fprintf(fp, "check_period=%s\n", (temp_host->check_period == NULL) ? "" : temp_host->check_period);
196 		fprintf(fp, "notification_period=%s\n", (temp_host->notification_period == NULL) ? "" : temp_host->notification_period);
197 		fprintf(fp, "event_handler=%s\n", (temp_host->event_handler == NULL) ? "" : temp_host->event_handler);
198 		fprintf(fp, "has_been_checked=%d\n", temp_host->has_been_checked);
199 		fprintf(fp, "check_execution_time=%.3f\n", temp_host->execution_time);
200 		fprintf(fp, "check_latency=%.3f\n", temp_host->latency);
201 		fprintf(fp, "check_type=%d\n", temp_host->check_type);
202 		fprintf(fp, "current_state=%d\n", temp_host->current_state);
203 		fprintf(fp, "last_state=%d\n", temp_host->last_state);
204 		fprintf(fp, "last_hard_state=%d\n", temp_host->last_hard_state);
205 		fprintf(fp, "last_event_id=%lu\n", temp_host->last_event_id);
206 		fprintf(fp, "current_event_id=%lu\n", temp_host->current_event_id);
207 		fprintf(fp, "current_problem_id=%lu\n", temp_host->current_problem_id);
208 		fprintf(fp, "last_problem_id=%lu\n", temp_host->last_problem_id);
209 		fprintf(fp, "plugin_output=%s\n", (temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output);
210 		fprintf(fp, "long_plugin_output=%s\n", (temp_host->long_plugin_output == NULL) ? "" : temp_host->long_plugin_output);
211 		fprintf(fp, "performance_data=%s\n", (temp_host->perf_data == NULL) ? "" : temp_host->perf_data);
212 		fprintf(fp, "last_check=%llu\n", (unsigned long long)temp_host->last_check);
213 		fprintf(fp, "next_check=%llu\n", (unsigned long long)temp_host->next_check);
214 		fprintf(fp, "check_options=%d\n", temp_host->check_options);
215 		fprintf(fp, "current_attempt=%d\n", temp_host->current_attempt);
216 		fprintf(fp, "max_attempts=%d\n", temp_host->max_attempts);
217 		fprintf(fp, "check_interval=%f\n", temp_host->check_interval);
218 		fprintf(fp, "retry_interval=%f\n", temp_host->retry_interval);
219 		fprintf(fp, "state_type=%d\n", temp_host->state_type);
220 		fprintf(fp, "last_state_change=%llu\n", (unsigned long long)temp_host->last_state_change);
221 		fprintf(fp, "last_hard_state_change=%llu\n", (unsigned long long)temp_host->last_hard_state_change);
222 		fprintf(fp, "last_time_up=%llu\n", (unsigned long long)temp_host->last_time_up);
223 		fprintf(fp, "last_time_down=%llu\n", (unsigned long long)temp_host->last_time_down);
224 		fprintf(fp, "last_time_unreachable=%llu\n", (unsigned long long)temp_host->last_time_unreachable);
225 		fprintf(fp, "notified_on_down=%d\n", flag_isset(temp_host->notified_on, OPT_DOWN));
226 		fprintf(fp, "notified_on_unreachable=%d\n", flag_isset(temp_host->notified_on, OPT_UNREACHABLE));
227 		fprintf(fp, "last_notification=%llu\n", (unsigned long long)temp_host->last_notification);
228 		fprintf(fp, "current_notification_number=%d\n", temp_host->current_notification_number);
229 		fprintf(fp, "current_notification_id=%lu\n", temp_host->current_notification_id);
230 		fprintf(fp, "notifications_enabled=%d\n", temp_host->notifications_enabled);
231 		fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_host->problem_has_been_acknowledged);
232 		fprintf(fp, "acknowledgement_type=%d\n", temp_host->acknowledgement_type);
233 		fprintf(fp, "active_checks_enabled=%d\n", temp_host->checks_enabled);
234 		fprintf(fp, "passive_checks_enabled=%d\n", temp_host->accept_passive_checks);
235 		fprintf(fp, "event_handler_enabled=%d\n", temp_host->event_handler_enabled);
236 		fprintf(fp, "flap_detection_enabled=%d\n", temp_host->flap_detection_enabled);
237 		fprintf(fp, "process_performance_data=%d\n", temp_host->process_performance_data);
238 		fprintf(fp, "obsess=%d\n", temp_host->obsess);
239 		fprintf(fp, "is_flapping=%d\n", temp_host->is_flapping);
240 		fprintf(fp, "percent_state_change=%.2f\n", temp_host->percent_state_change);
241 		fprintf(fp, "check_flapping_recovery_notification=%d\n", temp_host->check_flapping_recovery_notification);
242 		fprintf(fp, "flapping_comment_id=%lu\n", temp_host->flapping_comment_id);
243 
244 		fprintf(fp, "state_history=");
245 		for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++)
246 			fprintf(fp, "%s%d", (x > 0) ? "," : "", temp_host->state_history[(x + temp_host->state_history_index) % MAX_STATE_HISTORY_ENTRIES]);
247 		fprintf(fp, "\n");
248 
249 		/* custom variables */
250 		for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
251 			if(temp_customvariablesmember->variable_name)
252 				fprintf(fp, "_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
253 			}
254 
255 		fprintf(fp, "}\n");
256 		}
257 
258 	/* save service state information */
259 	for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
260 
261 		fprintf(fp, "service {\n");
262 		fprintf(fp, "host_name=%s\n", temp_service->host_name);
263 		fprintf(fp, "service_description=%s\n", temp_service->description);
264 		fprintf(fp, "modified_attributes=%lu\n", (temp_service->modified_attributes & ~service_attribute_mask));
265 		fprintf(fp, "check_command=%s\n", (temp_service->check_command == NULL) ? "" : temp_service->check_command);
266 		fprintf(fp, "check_period=%s\n", (temp_service->check_period == NULL) ? "" : temp_service->check_period);
267 		fprintf(fp, "notification_period=%s\n", (temp_service->notification_period == NULL) ? "" : temp_service->notification_period);
268 		fprintf(fp, "event_handler=%s\n", (temp_service->event_handler == NULL) ? "" : temp_service->event_handler);
269 		fprintf(fp, "has_been_checked=%d\n", temp_service->has_been_checked);
270 		fprintf(fp, "check_execution_time=%.3f\n", temp_service->execution_time);
271 		fprintf(fp, "check_latency=%.3f\n", temp_service->latency);
272 		fprintf(fp, "check_type=%d\n", temp_service->check_type);
273 		fprintf(fp, "current_state=%d\n", temp_service->current_state);
274 		fprintf(fp, "last_state=%d\n", temp_service->last_state);
275 		fprintf(fp, "last_hard_state=%d\n", temp_service->last_hard_state);
276 		fprintf(fp, "last_event_id=%lu\n", temp_service->last_event_id);
277 		fprintf(fp, "current_event_id=%lu\n", temp_service->current_event_id);
278 		fprintf(fp, "current_problem_id=%lu\n", temp_service->current_problem_id);
279 		fprintf(fp, "last_problem_id=%lu\n", temp_service->last_problem_id);
280 		fprintf(fp, "current_attempt=%d\n", temp_service->current_attempt);
281 		fprintf(fp, "max_attempts=%d\n", temp_service->max_attempts);
282 		fprintf(fp, "check_interval=%f\n", temp_service->check_interval);
283 		fprintf(fp, "retry_interval=%f\n", temp_service->retry_interval);
284 		fprintf(fp, "state_type=%d\n", temp_service->state_type);
285 		fprintf(fp, "last_state_change=%llu\n", (unsigned long long)temp_service->last_state_change);
286 		fprintf(fp, "last_hard_state_change=%llu\n", (unsigned long long)temp_service->last_hard_state_change);
287 		fprintf(fp, "last_time_ok=%llu\n", (unsigned long long)temp_service->last_time_ok);
288 		fprintf(fp, "last_time_warning=%llu\n", (unsigned long long)temp_service->last_time_warning);
289 		fprintf(fp, "last_time_unknown=%llu\n", (unsigned long long)temp_service->last_time_unknown);
290 		fprintf(fp, "last_time_critical=%llu\n", (unsigned long long)temp_service->last_time_critical);
291 		fprintf(fp, "plugin_output=%s\n", (temp_service->plugin_output == NULL) ? "" : temp_service->plugin_output);
292 		fprintf(fp, "long_plugin_output=%s\n", (temp_service->long_plugin_output == NULL) ? "" : temp_service->long_plugin_output);
293 		fprintf(fp, "performance_data=%s\n", (temp_service->perf_data == NULL) ? "" : temp_service->perf_data);
294 		fprintf(fp, "last_check=%llu\n", (unsigned long long)temp_service->last_check);
295 		fprintf(fp, "next_check=%llu\n", (unsigned long long)temp_service->next_check);
296 		fprintf(fp, "check_options=%d\n", temp_service->check_options);
297 		fprintf(fp, "notified_on_unknown=%d\n", flag_isset(temp_service->notified_on, OPT_UNKNOWN));
298 		fprintf(fp, "notified_on_warning=%d\n", flag_isset(temp_service->notified_on, OPT_WARNING));
299 		fprintf(fp, "notified_on_critical=%d\n", flag_isset(temp_service->notified_on, OPT_CRITICAL));
300 		fprintf(fp, "current_notification_number=%d\n", temp_service->current_notification_number);
301 		fprintf(fp, "current_notification_id=%lu\n", temp_service->current_notification_id);
302 		fprintf(fp, "last_notification=%llu\n", (unsigned long long)temp_service->last_notification);
303 		fprintf(fp, "notifications_enabled=%d\n", temp_service->notifications_enabled);
304 		fprintf(fp, "active_checks_enabled=%d\n", temp_service->checks_enabled);
305 		fprintf(fp, "passive_checks_enabled=%d\n", temp_service->accept_passive_checks);
306 		fprintf(fp, "event_handler_enabled=%d\n", temp_service->event_handler_enabled);
307 		fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_service->problem_has_been_acknowledged);
308 		fprintf(fp, "acknowledgement_type=%d\n", temp_service->acknowledgement_type);
309 		fprintf(fp, "flap_detection_enabled=%d\n", temp_service->flap_detection_enabled);
310 		fprintf(fp, "process_performance_data=%d\n", temp_service->process_performance_data);
311 		fprintf(fp, "obsess=%d\n", temp_service->obsess);
312 		fprintf(fp, "is_flapping=%d\n", temp_service->is_flapping);
313 		fprintf(fp, "percent_state_change=%.2f\n", temp_service->percent_state_change);
314 		fprintf(fp, "check_flapping_recovery_notification=%d\n", temp_service->check_flapping_recovery_notification);
315 		fprintf(fp, "flapping_comment_id=%lu\n", temp_service->flapping_comment_id);
316 
317 		fprintf(fp, "state_history=");
318 		for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++)
319 			fprintf(fp, "%s%d", (x > 0) ? "," : "", temp_service->state_history[(x + temp_service->state_history_index) % MAX_STATE_HISTORY_ENTRIES]);
320 		fprintf(fp, "\n");
321 
322 		/* custom variables */
323 		for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
324 			if(temp_customvariablesmember->variable_name)
325 				fprintf(fp, "_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
326 			}
327 
328 		fprintf(fp, "}\n");
329 		}
330 
331 	/* save contact state information */
332 	for(temp_contact = contact_list; temp_contact != NULL; temp_contact = temp_contact->next) {
333 
334 		fprintf(fp, "contact {\n");
335 		fprintf(fp, "contact_name=%s\n", temp_contact->name);
336 		fprintf(fp, "modified_attributes=%lu\n", (temp_contact->modified_attributes & ~contact_attribute_mask));
337 		fprintf(fp, "modified_host_attributes=%lu\n", (temp_contact->modified_host_attributes & ~contact_host_attribute_mask));
338 		fprintf(fp, "modified_service_attributes=%lu\n", (temp_contact->modified_service_attributes & ~contact_service_attribute_mask));
339 		fprintf(fp, "host_notification_period=%s\n", (temp_contact->host_notification_period == NULL) ? "" : temp_contact->host_notification_period);
340 		fprintf(fp, "service_notification_period=%s\n", (temp_contact->service_notification_period == NULL) ? "" : temp_contact->service_notification_period);
341 		fprintf(fp, "last_host_notification=%llu\n", (unsigned long long)temp_contact->last_host_notification);
342 		fprintf(fp, "last_service_notification=%llu\n", (unsigned long long)temp_contact->last_service_notification);
343 		fprintf(fp, "host_notifications_enabled=%d\n", temp_contact->host_notifications_enabled);
344 		fprintf(fp, "service_notifications_enabled=%d\n", temp_contact->service_notifications_enabled);
345 
346 		/* custom variables */
347 		for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
348 			if(temp_customvariablesmember->variable_name)
349 				fprintf(fp, "_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value);
350 			}
351 
352 		fprintf(fp, "}\n");
353 		}
354 
355 	/* save all comments */
356 	for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) {
357 
358 		if(temp_comment->comment_type == HOST_COMMENT)
359 			fprintf(fp, "hostcomment {\n");
360 		else
361 			fprintf(fp, "servicecomment {\n");
362 		fprintf(fp, "host_name=%s\n", temp_comment->host_name);
363 		if(temp_comment->comment_type == SERVICE_COMMENT)
364 			fprintf(fp, "service_description=%s\n", temp_comment->service_description);
365 		fprintf(fp, "entry_type=%d\n", temp_comment->entry_type);
366 		fprintf(fp, "comment_id=%lu\n", temp_comment->comment_id);
367 		fprintf(fp, "source=%d\n", temp_comment->source);
368 		fprintf(fp, "persistent=%d\n", temp_comment->persistent);
369 		fprintf(fp, "entry_time=%llu\n", (unsigned long long)temp_comment->entry_time);
370 		fprintf(fp, "expires=%d\n", temp_comment->expires);
371 		fprintf(fp, "expire_time=%llu\n", (unsigned long long)temp_comment->expire_time);
372 		fprintf(fp, "author=%s\n", temp_comment->author);
373 		fprintf(fp, "comment_data=%s\n", temp_comment->comment_data);
374 		fprintf(fp, "}\n");
375 		}
376 
377 	/* save all downtime */
378 	for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) {
379 
380 		if(temp_downtime->type == HOST_DOWNTIME)
381 			fprintf(fp, "hostdowntime {\n");
382 		else
383 			fprintf(fp, "servicedowntime {\n");
384 		fprintf(fp, "host_name=%s\n", temp_downtime->host_name);
385 		if(temp_downtime->type == SERVICE_DOWNTIME)
386 			fprintf(fp, "service_description=%s\n", temp_downtime->service_description);
387 		fprintf(fp, "comment_id=%lu\n", temp_downtime->comment_id);
388 		fprintf(fp, "downtime_id=%lu\n", temp_downtime->downtime_id);
389 		fprintf(fp, "entry_time=%llu\n", (unsigned long long)temp_downtime->entry_time);
390 		fprintf(fp, "start_time=%llu\n", (unsigned long long)temp_downtime->start_time);
391 		fprintf(fp, "flex_downtime_start=%llu\n", (unsigned long long)temp_downtime->flex_downtime_start);
392 		fprintf(fp, "end_time=%llu\n", (unsigned long long)temp_downtime->end_time);
393 		fprintf(fp, "triggered_by=%lu\n", temp_downtime->triggered_by);
394 		fprintf(fp, "fixed=%d\n", temp_downtime->fixed);
395 		fprintf(fp, "duration=%lu\n", temp_downtime->duration);
396 		fprintf(fp, "is_in_effect=%d\n", temp_downtime->is_in_effect);
397 		fprintf(fp, "start_notification_sent=%d\n", temp_downtime->start_notification_sent);
398 		fprintf(fp, "author=%s\n", temp_downtime->author);
399 		fprintf(fp, "comment=%s\n", temp_downtime->comment);
400 		fprintf(fp, "}\n");
401 		}
402 
403 	fflush(fp);
404 	fsync(fd);
405 	result = fclose(fp);
406 
407 	/* save/close was successful */
408 	if(result == 0) {
409 
410 		result = OK;
411 
412 		/* move the temp file to the retention file (overwrite the old retention file) */
413 		if(my_rename(tmp_file, retention_file)) {
414 			unlink(tmp_file);
415 			logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to update retention file '%s': %s", retention_file, strerror(errno));
416 			result = ERROR;
417 			}
418 		}
419 
420 	/* a problem occurred saving the file */
421 	else {
422 
423 		result = ERROR;
424 
425 		/* remove temp file and log an error */
426 		unlink(tmp_file);
427 		logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to save retention file: %s", strerror(errno));
428 		}
429 
430 	/* free memory */
431 	my_free(tmp_file);
432 
433 	return result;
434 	}
435 
436 
437 
438 
439 /******************************************************************/
440 /***************** DEFAULT STATE INPUT FUNCTION *******************/
441 /******************************************************************/
442 
xrddefault_read_state_information(void)443 int xrddefault_read_state_information(void) {
444 	char *input = NULL;
445 	char *inputbuf = NULL;
446 	char *temp_ptr = NULL;
447 	mmapfile *thefile;
448 	char *host_name = NULL;
449 	char *service_description = NULL;
450 	char *contact_name = NULL;
451 	char *author = NULL;
452 	char *comment_data = NULL;
453 	int data_type = XRDDEFAULT_NO_DATA;
454 	int x = 0;
455 	host *temp_host = NULL;
456 	service *temp_service = NULL;
457 	contact *temp_contact = NULL;
458 	command *temp_command = NULL;
459 	timeperiod *temp_timeperiod = NULL;
460 	customvariablesmember *temp_customvariablesmember = NULL;
461 	char *customvarname = NULL;
462 	char *var = NULL;
463 	char *val = NULL;
464 	char *tempval = NULL;
465 	char *ch = NULL;
466 	unsigned long comment_id = 0;
467 	int persistent = FALSE;
468 	int expires = FALSE;
469 	time_t expire_time = 0L;
470 	int entry_type = USER_COMMENT;
471 	int source = COMMENTSOURCE_INTERNAL;
472 	time_t entry_time = 0L;
473 	time_t creation_time;
474 	time_t current_time;
475 	int scheduling_info_is_ok = FALSE;
476 	unsigned long downtime_id = 0;
477 	time_t start_time = 0L;
478 	time_t flex_downtime_start = ( time_t)0;
479 	time_t end_time = 0L;
480 	int fixed = FALSE;
481 	unsigned long triggered_by = 0;
482 	unsigned long duration = 0L;
483 	unsigned long host_attribute_mask = 0L;
484 	unsigned long service_attribute_mask = 0L;
485 	unsigned long contact_attribute_mask = 0L;
486 	unsigned long contact_host_attribute_mask = 0L;
487 	unsigned long contact_service_attribute_mask = 0L;
488 	unsigned long process_host_attribute_mask = 0L;
489 	unsigned long process_service_attribute_mask = 0L;
490 	int remove_comment = FALSE;
491 	int ack = FALSE;
492 	int was_flapping = FALSE;
493 	int allow_flapstart_notification = TRUE;
494 	struct timeval tv[2];
495 	double runtime[2];
496 	int found_directive = FALSE;
497 	int is_in_effect = FALSE;
498 	int start_notification_sent = FALSE;
499 
500 
501 	log_debug_info(DEBUGL_FUNCTIONS, 0, "xrddefault_read_state_information() start\n");
502 
503 	/* make sure we have what we need */
504 	if(retention_file == NULL) {
505 
506 		logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: We don't have a filename for retention data!\n");
507 
508 		return ERROR;
509 		}
510 
511 	if(test_scheduling == TRUE)
512 		gettimeofday(&tv[0], NULL);
513 
514 	/* open the retention file for reading */
515 	if((thefile = mmap_fopen(retention_file)) == NULL)
516 		return ERROR;
517 
518 	/* what attributes should be masked out? */
519 	/* NOTE: host/service/contact-specific values may be added in the future, but for now we only have global masks */
520 	process_host_attribute_mask = retained_process_host_attribute_mask;
521 	process_service_attribute_mask = retained_process_host_attribute_mask;
522 	host_attribute_mask = retained_host_attribute_mask;
523 	service_attribute_mask = retained_host_attribute_mask;
524 	contact_host_attribute_mask = retained_contact_host_attribute_mask;
525 	contact_service_attribute_mask = retained_contact_service_attribute_mask;
526 
527 	/* Big speedup when reading retention.dat in bulk */
528 	defer_downtime_sorting = 1;
529 	defer_comment_sorting = 1;
530 
531 	/* read all lines in the retention file */
532 	while(1) {
533 
534 		/* free memory */
535 		my_free(inputbuf);
536 
537 		/* read the next line */
538 		if((inputbuf = mmap_fgets(thefile)) == NULL)
539 			break;
540 
541 		input = inputbuf;
542 
543 		/* far better than strip()ing */
544 		if(input[0] == '\t')
545 			input++;
546 
547 		strip(input);
548 
549 		if(!strcmp(input, "service {"))
550 			data_type = XRDDEFAULT_SERVICESTATUS_DATA;
551 		else if(!strcmp(input, "host {"))
552 			data_type = XRDDEFAULT_HOSTSTATUS_DATA;
553 		else if(!strcmp(input, "contact {"))
554 			data_type = XRDDEFAULT_CONTACTSTATUS_DATA;
555 		else if(!strcmp(input, "hostcomment {"))
556 			data_type = XRDDEFAULT_HOSTCOMMENT_DATA;
557 		else if(!strcmp(input, "servicecomment {"))
558 			data_type = XRDDEFAULT_SERVICECOMMENT_DATA;
559 		else if(!strcmp(input, "hostdowntime {"))
560 			data_type = XRDDEFAULT_HOSTDOWNTIME_DATA;
561 		else if(!strcmp(input, "servicedowntime {"))
562 			data_type = XRDDEFAULT_SERVICEDOWNTIME_DATA;
563 		else if(!strcmp(input, "info {"))
564 			data_type = XRDDEFAULT_INFO_DATA;
565 		else if(!strcmp(input, "program {"))
566 			data_type = XRDDEFAULT_PROGRAMSTATUS_DATA;
567 
568 		else if(!strcmp(input, "}")) {
569 
570 			switch(data_type) {
571 
572 				case XRDDEFAULT_INFO_DATA:
573 					break;
574 
575 				case XRDDEFAULT_PROGRAMSTATUS_DATA:
576 
577 					/* adjust modified attributes if necessary */
578 					if(use_retained_program_state == FALSE) {
579 						modified_host_process_attributes = MODATTR_NONE;
580 						modified_service_process_attributes = MODATTR_NONE;
581 						}
582 					break;
583 
584 				case XRDDEFAULT_HOSTSTATUS_DATA:
585 
586 					if(temp_host != NULL) {
587 
588 						/* adjust modified attributes if necessary */
589 						if(temp_host->retain_nonstatus_information == FALSE)
590 							temp_host->modified_attributes = MODATTR_NONE;
591 
592 						/* adjust modified attributes if no custom variables have been changed */
593 						if(temp_host->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
594 							for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
595 								if(temp_customvariablesmember->has_been_modified == TRUE)
596 									break;
597 
598 								}
599 							if(temp_customvariablesmember == NULL)
600 								temp_host->modified_attributes -= MODATTR_CUSTOM_VARIABLE;
601 							}
602 
603 						/* calculate next possible notification time */
604 						if(temp_host->current_state != HOST_UP && temp_host->last_notification != (time_t)0)
605 							temp_host->next_notification = get_next_host_notification_time(temp_host, temp_host->last_notification);
606 
607 						/* ADDED 01/23/2009 adjust current check attempts if host in hard problem state (max attempts may have changed in config since restart) */
608 						if(temp_host->current_state != HOST_UP && temp_host->state_type == HARD_STATE)
609 							temp_host->current_attempt = temp_host->max_attempts;
610 
611 
612 						/* ADDED 02/20/08 assume same flapping state if large install tweaks enabled */
613 						if(use_large_installation_tweaks == TRUE) {
614 							temp_host->is_flapping = was_flapping;
615 							}
616 						/* else use normal startup flap detection logic */
617 						else {
618 							/* host was flapping before program started */
619 							/* 11/10/07 don't allow flapping notifications to go out */
620 							if(was_flapping == TRUE)
621 								allow_flapstart_notification = FALSE;
622 							else
623 								/* flapstart notifications are okay */
624 								allow_flapstart_notification = TRUE;
625 
626 							/* check for flapping */
627 							check_for_host_flapping(temp_host, FALSE, FALSE, allow_flapstart_notification);
628 
629 							/* host was flapping before and isn't now, so clear recovery check variable if host isn't flapping now */
630 							if(was_flapping == TRUE && temp_host->is_flapping == FALSE)
631 								temp_host->check_flapping_recovery_notification = FALSE;
632 							}
633 
634 						/* handle new vars added in 2.x */
635 						if(temp_host->last_hard_state_change == (time_t)0)
636 							temp_host->last_hard_state_change = temp_host->last_state_change;
637 
638 						/* update host status */
639 						update_host_status(temp_host, FALSE);
640 						}
641 
642 					/* reset vars */
643 					was_flapping = FALSE;
644 					allow_flapstart_notification = TRUE;
645 
646 					my_free(host_name);
647 					host_name = NULL;
648 					temp_host = NULL;
649 					break;
650 
651 				case XRDDEFAULT_SERVICESTATUS_DATA:
652 
653 					if(temp_service != NULL) {
654 
655 						/* adjust modified attributes if necessary */
656 						if(temp_service->retain_nonstatus_information == FALSE)
657 							temp_service->modified_attributes = MODATTR_NONE;
658 
659 						/* adjust modified attributes if no custom variables have been changed */
660 						if(temp_service->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
661 							for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
662 								if(temp_customvariablesmember->has_been_modified == TRUE)
663 									break;
664 
665 								}
666 							if(temp_customvariablesmember == NULL)
667 								temp_service->modified_attributes -= MODATTR_CUSTOM_VARIABLE;
668 							}
669 
670 						/* calculate next possible notification time */
671 						if(temp_service->current_state != STATE_OK && temp_service->last_notification != (time_t)0)
672 							temp_service->next_notification = get_next_service_notification_time(temp_service, temp_service->last_notification);
673 
674 						/* fix old vars */
675 						if(temp_service->has_been_checked == FALSE && temp_service->state_type == SOFT_STATE)
676 							temp_service->state_type = HARD_STATE;
677 
678 						/* ADDED 01/23/2009 adjust current check attempt if service is in hard problem state (max attempts may have changed in config since restart) */
679 						if(temp_service->current_state != STATE_OK && temp_service->state_type == HARD_STATE)
680 							temp_service->current_attempt = temp_service->max_attempts;
681 
682 
683 						/* ADDED 02/20/08 assume same flapping state if large install tweaks enabled */
684 						if(use_large_installation_tweaks == TRUE) {
685 							temp_service->is_flapping = was_flapping;
686 							}
687 						/* else use normal startup flap detection logic */
688 						else {
689 							/* service was flapping before program started */
690 							/* 11/10/07 don't allow flapping notifications to go out */
691 							if(was_flapping == TRUE)
692 								allow_flapstart_notification = FALSE;
693 							else
694 								/* flapstart notifications are okay */
695 								allow_flapstart_notification = TRUE;
696 
697 							/* check for flapping */
698 							check_for_service_flapping(temp_service, FALSE, allow_flapstart_notification);
699 
700 							/* service was flapping before and isn't now, so clear recovery check variable if service isn't flapping now */
701 							if(was_flapping == TRUE && temp_service->is_flapping == FALSE)
702 								temp_service->check_flapping_recovery_notification = FALSE;
703 							}
704 
705 						/* handle new vars added in 2.x */
706 						if(temp_service->last_hard_state_change == (time_t)0)
707 							temp_service->last_hard_state_change = temp_service->last_state_change;
708 
709 						/* update service status */
710 						update_service_status(temp_service, FALSE);
711 						}
712 
713 					/* reset vars */
714 					was_flapping = FALSE;
715 					allow_flapstart_notification = TRUE;
716 
717 					my_free(host_name);
718 					my_free(service_description);
719 					temp_service = NULL;
720 					break;
721 
722 				case XRDDEFAULT_CONTACTSTATUS_DATA:
723 
724 					if(temp_contact != NULL) {
725 
726 						/* adjust modified attributes if necessary */
727 						if(temp_contact->retain_nonstatus_information == FALSE)
728 							temp_contact->modified_attributes = MODATTR_NONE;
729 
730 						/* adjust modified attributes if no custom variables have been changed */
731 						if(temp_contact->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
732 							for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
733 								if(temp_customvariablesmember->has_been_modified == TRUE)
734 									break;
735 
736 								}
737 							if(temp_customvariablesmember == NULL)
738 								temp_contact->modified_attributes -= MODATTR_CUSTOM_VARIABLE;
739 							}
740 
741 						/* update contact status */
742 						update_contact_status(temp_contact, FALSE);
743 						}
744 
745 					my_free(contact_name);
746 					temp_contact = NULL;
747 					break;
748 
749 				case XRDDEFAULT_HOSTCOMMENT_DATA:
750 				case XRDDEFAULT_SERVICECOMMENT_DATA:
751 
752 					/* add the comment */
753 					add_comment((data_type == XRDDEFAULT_HOSTCOMMENT_DATA) ? HOST_COMMENT : SERVICE_COMMENT, entry_type, host_name, service_description, entry_time, author, comment_data, comment_id, persistent, expires, expire_time, source);
754 
755 					/* delete the comment if necessary */
756 					/* it seems a bit backwards to add and then immediately delete the comment, but its necessary to track comment deletions in the event broker */
757 					remove_comment = FALSE;
758 					/* host no longer exists */
759 					if((temp_host = find_host(host_name)) == NULL)
760 						remove_comment = TRUE;
761 					/* service no longer exists */
762 					else if(data_type == XRDDEFAULT_SERVICECOMMENT_DATA && (temp_service = find_service(host_name, service_description)) == NULL)
763 						remove_comment = TRUE;
764 					/* acknowledgement comments get deleted if they're not persistent and the original problem is no longer acknowledged */
765 					else if(entry_type == ACKNOWLEDGEMENT_COMMENT) {
766 						ack = FALSE;
767 						if(data_type == XRDDEFAULT_HOSTCOMMENT_DATA)
768 							ack = temp_host->problem_has_been_acknowledged;
769 						else
770 							ack = temp_service->problem_has_been_acknowledged;
771 						if(ack == FALSE && persistent == FALSE)
772 							remove_comment = TRUE;
773 						}
774 					/* non-persistent comments don't last past restarts UNLESS they're acks (see above) */
775 					else if(persistent == FALSE && (sigrestart == FALSE || entry_type == DOWNTIME_COMMENT))
776 						remove_comment = TRUE;
777 
778 					if(remove_comment == TRUE)
779 						delete_comment((data_type == XRDDEFAULT_HOSTCOMMENT_DATA) ? HOST_COMMENT : SERVICE_COMMENT, comment_id);
780 
781 					/* free temp memory */
782 					my_free(host_name);
783 					my_free(service_description);
784 					my_free(author);
785 					my_free(comment_data);
786 
787 					/* reset defaults */
788 					entry_type = USER_COMMENT;
789 					comment_id = 0;
790 					source = COMMENTSOURCE_INTERNAL;
791 					persistent = FALSE;
792 					entry_time = 0L;
793 					expires = FALSE;
794 					expire_time = 0L;
795 
796 					break;
797 
798 				case XRDDEFAULT_HOSTDOWNTIME_DATA:
799 				case XRDDEFAULT_SERVICEDOWNTIME_DATA:
800 
801 					/* add the downtime */
802 					if(data_type == XRDDEFAULT_HOSTDOWNTIME_DATA)
803 						add_host_downtime(host_name, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent);
804 					else
805 						add_service_downtime(host_name, service_description, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent);
806 
807 					/* must register the downtime with Nagios so it can schedule it, add comments, etc. */
808 					register_downtime((data_type == XRDDEFAULT_HOSTDOWNTIME_DATA) ? HOST_DOWNTIME : SERVICE_DOWNTIME, downtime_id);
809 
810 					/* free temp memory */
811 					my_free(host_name);
812 					my_free(service_description);
813 					my_free(author);
814 					my_free(comment_data);
815 
816 					/* reset defaults */
817 					downtime_id = 0;
818 					entry_time = 0L;
819 					start_time = 0L;
820 					flex_downtime_start = ( time_t)0;
821 					end_time = 0L;
822 					fixed = FALSE;
823 					triggered_by = 0;
824 					duration = 0L;
825 
826 					break;
827 
828 				default:
829 					break;
830 				}
831 
832 			data_type = XRDDEFAULT_NO_DATA;
833 			}
834 
835 		else if(data_type != XRDDEFAULT_NO_DATA) {
836 
837 			/* slightly faster than strtok () */
838 			var = input;
839 			if((val = strchr(input, '=')) == NULL)
840 				continue;
841 			val[0] = '\x0';
842 			val++;
843 
844 			found_directive = TRUE;
845 
846 			switch(data_type) {
847 
848 				case XRDDEFAULT_INFO_DATA:
849 					if(!strcmp(var, "created")) {
850 						creation_time = strtoul(val, NULL, 10);
851 						time(&current_time);
852 						if(current_time - creation_time < retention_scheduling_horizon)
853 							scheduling_info_is_ok = TRUE;
854 						else
855 							scheduling_info_is_ok = FALSE;
856 						last_program_stop = creation_time;
857 						}
858 					else if(!strcmp(var, "version")) {
859 						/* initialize last version in case we're reading a pre-3.1.0 retention file */
860 						if(last_program_version == NULL)
861 							last_program_version = (char *)strdup(val);
862 						}
863 					else if(!strcmp(var, "last_update_check"))
864 						last_update_check = strtoul(val, NULL, 10);
865 					else if(!strcmp(var, "update_available"))
866 						update_available = atoi(val);
867 					else if(!strcmp(var, "update_uid"))
868 						update_uid = strtoul(val, NULL, 10);
869 					else if(!strcmp(var, "last_version")) {
870 						if(last_program_version)
871 							my_free(last_program_version);
872 						last_program_version = (char *)strdup(val);
873 						}
874 					else if(!strcmp(var, "new_version"))
875 						new_program_version = (char *)strdup(val);
876 					break;
877 
878 				case XRDDEFAULT_PROGRAMSTATUS_DATA:
879 					if(!strcmp(var, "modified_host_attributes")) {
880 
881 						modified_host_process_attributes = strtoul(val, NULL, 10);
882 
883 						/* mask out attributes we don't want to retain */
884 						modified_host_process_attributes &= ~process_host_attribute_mask;
885 						}
886 					else if(!strcmp(var, "modified_service_attributes")) {
887 
888 						modified_service_process_attributes = strtoul(val, NULL, 10);
889 
890 						/* mask out attributes we don't want to retain */
891 						modified_service_process_attributes &= ~process_service_attribute_mask;
892 						}
893 					if(use_retained_program_state == TRUE) {
894 						if(!strcmp(var, "enable_notifications")) {
895 							if(modified_host_process_attributes & MODATTR_NOTIFICATIONS_ENABLED)
896 								enable_notifications = (atoi(val) > 0) ? TRUE : FALSE;
897 							}
898 						else if(!strcmp(var, "active_service_checks_enabled")) {
899 							if(modified_service_process_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
900 								execute_service_checks = (atoi(val) > 0) ? TRUE : FALSE;
901 							}
902 						else if(!strcmp(var, "passive_service_checks_enabled")) {
903 							if(modified_service_process_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
904 								accept_passive_service_checks = (atoi(val) > 0) ? TRUE : FALSE;
905 							}
906 						else if(!strcmp(var, "active_host_checks_enabled")) {
907 							if(modified_host_process_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
908 								execute_host_checks = (atoi(val) > 0) ? TRUE : FALSE;
909 							}
910 						else if(!strcmp(var, "passive_host_checks_enabled")) {
911 							if(modified_host_process_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
912 								accept_passive_host_checks = (atoi(val) > 0) ? TRUE : FALSE;
913 							}
914 						else if(!strcmp(var, "enable_event_handlers")) {
915 							if(modified_host_process_attributes & MODATTR_EVENT_HANDLER_ENABLED)
916 								enable_event_handlers = (atoi(val) > 0) ? TRUE : FALSE;
917 							}
918 						else if(!strcmp(var, "obsess_over_services")) {
919 							if(modified_service_process_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
920 								obsess_over_services = (atoi(val) > 0) ? TRUE : FALSE;
921 							}
922 						else if(!strcmp(var, "obsess_over_hosts")) {
923 							if(modified_host_process_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
924 								obsess_over_hosts = (atoi(val) > 0) ? TRUE : FALSE;
925 							}
926 						else if(!strcmp(var, "check_service_freshness")) {
927 							if(modified_service_process_attributes & MODATTR_FRESHNESS_CHECKS_ENABLED)
928 								check_service_freshness = (atoi(val) > 0) ? TRUE : FALSE;
929 							}
930 						else if(!strcmp(var, "check_host_freshness")) {
931 							if(modified_host_process_attributes & MODATTR_FRESHNESS_CHECKS_ENABLED)
932 								check_host_freshness = (atoi(val) > 0) ? TRUE : FALSE;
933 							}
934 						else if(!strcmp(var, "enable_flap_detection")) {
935 							if(modified_host_process_attributes & MODATTR_FLAP_DETECTION_ENABLED)
936 								enable_flap_detection = (atoi(val) > 0) ? TRUE : FALSE;
937 							}
938 						else if(!strcmp(var, "process_performance_data")) {
939 							if(modified_host_process_attributes & MODATTR_PERFORMANCE_DATA_ENABLED)
940 								process_performance_data = (atoi(val) > 0) ? TRUE : FALSE;
941 							}
942 						else if(!strcmp(var, "global_host_event_handler")) {
943 							if(modified_host_process_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
944 
945 								/* make sure the check command still exists... */
946 								tempval = (char *)strdup(val);
947 								temp_ptr = my_strtok(tempval, "!");
948 								temp_command = find_command(temp_ptr);
949 								temp_ptr = (char *)strdup(val);
950 								my_free(tempval);
951 
952 								if(temp_command != NULL && temp_ptr != NULL) {
953 									my_free(global_host_event_handler);
954 									global_host_event_handler = temp_ptr;
955 									}
956 								}
957 							}
958 						else if(!strcmp(var, "global_service_event_handler")) {
959 							if(modified_service_process_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
960 
961 								/* make sure the check command still exists... */
962 								tempval = (char *)strdup(val);
963 								temp_ptr = my_strtok(tempval, "!");
964 								temp_command = find_command(temp_ptr);
965 								temp_ptr = (char *)strdup(val);
966 								my_free(tempval);
967 
968 								if(temp_command != NULL && temp_ptr != NULL) {
969 									my_free(global_service_event_handler);
970 									global_service_event_handler = temp_ptr;
971 									}
972 								}
973 							}
974 						else if(!strcmp(var, "next_comment_id"))
975 							next_comment_id = strtoul(val, NULL, 10);
976 						else if(!strcmp(var, "next_downtime_id"))
977 							next_downtime_id = strtoul(val, NULL, 10);
978 						else if(!strcmp(var, "next_event_id"))
979 							next_event_id = strtoul(val, NULL, 10);
980 						else if(!strcmp(var, "next_problem_id"))
981 							next_problem_id = strtoul(val, NULL, 10);
982 						else if(!strcmp(var, "next_notification_id"))
983 							next_notification_id = strtoul(val, NULL, 10);
984 						}
985 					break;
986 
987 				case XRDDEFAULT_HOSTSTATUS_DATA:
988 
989 					if(temp_host == NULL) {
990 						if(!strcmp(var, "host_name")) {
991 							host_name = (char *)strdup(val);
992 							temp_host = find_host(host_name);
993 							}
994 						}
995 					else {
996 						if(!strcmp(var, "modified_attributes")) {
997 
998 							temp_host->modified_attributes = strtoul(val, NULL, 10);
999 
1000 							/* mask out attributes we don't want to retain */
1001 							temp_host->modified_attributes &= ~host_attribute_mask;
1002 
1003 							/* break out */
1004 							break;
1005 							}
1006 						if(temp_host->retain_status_information == TRUE) {
1007 							if(!strcmp(var, "has_been_checked"))
1008 								temp_host->has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
1009 							else if(!strcmp(var, "check_execution_time"))
1010 								temp_host->execution_time = strtod(val, NULL);
1011 							else if(!strcmp(var, "check_latency"))
1012 								temp_host->latency = strtod(val, NULL);
1013 							else if(!strcmp(var, "check_type"))
1014 								temp_host->check_type = atoi(val);
1015 							else if(!strcmp(var, "current_state"))
1016 								temp_host->current_state = atoi(val);
1017 							else if(!strcmp(var, "last_state"))
1018 								temp_host->last_state = atoi(val);
1019 							else if(!strcmp(var, "last_hard_state"))
1020 								temp_host->last_hard_state = atoi(val);
1021 							else if(!strcmp(var, "plugin_output")) {
1022 								my_free(temp_host->plugin_output);
1023 								temp_host->plugin_output = (char *)strdup(val);
1024 								}
1025 							else if(!strcmp(var, "long_plugin_output")) {
1026 								my_free(temp_host->long_plugin_output);
1027 								temp_host->long_plugin_output = (char *)strdup(val);
1028 								}
1029 							else if(!strcmp(var, "performance_data")) {
1030 								my_free(temp_host->perf_data);
1031 								temp_host->perf_data = (char *)strdup(val);
1032 								}
1033 							else if(!strcmp(var, "last_check"))
1034 								temp_host->last_check = strtoul(val, NULL, 10);
1035 							else if(!strcmp(var, "next_check")) {
1036 								if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
1037 									temp_host->next_check = strtoul(val, NULL, 10);
1038 								}
1039 							else if(!strcmp(var, "check_options")) {
1040 								if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
1041 									temp_host->check_options = atoi(val);
1042 								}
1043 							else if(!strcmp(var, "current_attempt"))
1044 								temp_host->current_attempt = atoi(val);
1045 							else if(!strcmp(var, "current_event_id"))
1046 								temp_host->current_event_id = strtoul(val, NULL, 10);
1047 							else if(!strcmp(var, "last_event_id"))
1048 								temp_host->last_event_id = strtoul(val, NULL, 10);
1049 							else if(!strcmp(var, "current_problem_id"))
1050 								temp_host->current_problem_id = strtoul(val, NULL, 10);
1051 							else if(!strcmp(var, "last_problem_id"))
1052 								temp_host->last_problem_id = strtoul(val, NULL, 10);
1053 							else if(!strcmp(var, "state_type"))
1054 								temp_host->state_type = atoi(val);
1055 							else if(!strcmp(var, "last_state_change"))
1056 								temp_host->last_state_change = strtoul(val, NULL, 10);
1057 							else if(!strcmp(var, "last_hard_state_change"))
1058 								temp_host->last_hard_state_change = strtoul(val, NULL, 10);
1059 							else if(!strcmp(var, "last_time_up"))
1060 								temp_host->last_time_up = strtoul(val, NULL, 10);
1061 							else if(!strcmp(var, "last_time_down"))
1062 								temp_host->last_time_down = strtoul(val, NULL, 10);
1063 							else if(!strcmp(var, "last_time_unreachable"))
1064 								temp_host->last_time_unreachable = strtoul(val, NULL, 10);
1065 							else if(!strcmp(var, "notified_on_down"))
1066 								temp_host->notified_on |= (atoi(val) > 0 ? OPT_DOWN : 0);
1067 							else if(!strcmp(var, "notified_on_unreachable"))
1068 								temp_host->notified_on |= (atoi(val) > 0 ? OPT_UNREACHABLE : 0);
1069 							else if(!strcmp(var, "last_notification"))
1070 								temp_host->last_notification = strtoul(val, NULL, 10);
1071 							else if(!strcmp(var, "current_notification_number"))
1072 								temp_host->current_notification_number = atoi(val);
1073 							else if(!strcmp(var, "current_notification_id"))
1074 								temp_host->current_notification_id = strtoul(val, NULL, 10);
1075 							else if(!strcmp(var, "is_flapping"))
1076 								was_flapping = atoi(val);
1077 							else if(!strcmp(var, "percent_state_change"))
1078 								temp_host->percent_state_change = strtod(val, NULL);
1079 							else if(!strcmp(var, "check_flapping_recovery_notification"))
1080 								temp_host->check_flapping_recovery_notification = atoi(val);
1081 							else if(!strcmp(var, "state_history")) {
1082 								temp_ptr = val;
1083 								for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++) {
1084 									if((ch = my_strsep(&temp_ptr, ",")) != NULL)
1085 										temp_host->state_history[x] = atoi(ch);
1086 									else
1087 										break;
1088 									}
1089 								temp_host->state_history_index = 0;
1090 								}
1091 							else if(!strcmp(var, "flapping_comment_id") && sigrestart == TRUE)
1092 								temp_host->flapping_comment_id = strtoul(val, NULL, 10);
1093 							else
1094 								found_directive = FALSE;
1095 							}
1096 						if(temp_host->retain_nonstatus_information == TRUE) {
1097 							/* null-op speeds up logic */
1098 							if(found_directive == TRUE);
1099 
1100 							else if(!strcmp(var, "problem_has_been_acknowledged"))
1101 								temp_host->problem_has_been_acknowledged = (atoi(val) > 0) ? TRUE : FALSE;
1102 							else if(!strcmp(var, "acknowledgement_type"))
1103 								temp_host->acknowledgement_type = atoi(val);
1104 							else if(!strcmp(var, "notifications_enabled")) {
1105 								if(temp_host->modified_attributes & MODATTR_NOTIFICATIONS_ENABLED)
1106 									temp_host->notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1107 								}
1108 							else if(!strcmp(var, "active_checks_enabled")) {
1109 								if(temp_host->modified_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
1110 									temp_host->checks_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1111 								}
1112 							else if(!strcmp(var, "passive_checks_enabled")) {
1113 								if(temp_host->modified_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
1114 									temp_host->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE;
1115 								}
1116 							else if(!strcmp(var, "event_handler_enabled")) {
1117 								if(temp_host->modified_attributes & MODATTR_EVENT_HANDLER_ENABLED)
1118 									temp_host->event_handler_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1119 								}
1120 							else if(!strcmp(var, "flap_detection_enabled")) {
1121 								if(temp_host->modified_attributes & MODATTR_FLAP_DETECTION_ENABLED)
1122 									temp_host->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1123 								}
1124 							else if(!strcmp(var, "process_performance_data")) {
1125 								if(temp_host->modified_attributes & MODATTR_PERFORMANCE_DATA_ENABLED)
1126 									temp_host->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE;
1127 								}
1128 							else if(!strcmp(var, "obsess_over_host") || !strcmp(var, "obsess")) {
1129 								if(temp_host->modified_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
1130 									temp_host->obsess = (atoi(val) > 0) ? TRUE : FALSE;
1131 								}
1132 							else if(!strcmp(var, "check_command")) {
1133 								if(temp_host->modified_attributes & MODATTR_CHECK_COMMAND) {
1134 
1135 									/* make sure the check command still exists... */
1136 									tempval = (char *)strdup(val);
1137 									temp_ptr = my_strtok(tempval, "!");
1138 									temp_command = find_command(temp_ptr);
1139 									temp_ptr = (char *)strdup(val);
1140 									my_free(tempval);
1141 
1142 									if(temp_command != NULL && temp_ptr != NULL) {
1143 										my_free(temp_host->check_command);
1144 										temp_host->check_command = temp_ptr;
1145 										}
1146 									else
1147 										temp_host->modified_attributes -= MODATTR_CHECK_COMMAND;
1148 									}
1149 								}
1150 							else if(!strcmp(var, "check_period")) {
1151 								if(temp_host->modified_attributes & MODATTR_CHECK_TIMEPERIOD) {
1152 
1153 									/* make sure the timeperiod still exists... */
1154 									temp_timeperiod = find_timeperiod(val);
1155 									temp_ptr = (char *)strdup(val);
1156 
1157 									if(temp_timeperiod != NULL && temp_ptr != NULL) {
1158 										my_free(temp_host->check_period);
1159 										temp_host->check_period = temp_ptr;
1160 										}
1161 									else
1162 										temp_host->modified_attributes -= MODATTR_CHECK_TIMEPERIOD;
1163 									}
1164 								}
1165 							else if(!strcmp(var, "notification_period")) {
1166 								if(temp_host->modified_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
1167 
1168 									/* make sure the timeperiod still exists... */
1169 									temp_timeperiod = find_timeperiod(val);
1170 									temp_ptr = (char *)strdup(val);
1171 
1172 									if(temp_timeperiod != NULL && temp_ptr != NULL) {
1173 										my_free(temp_host->notification_period);
1174 										temp_host->notification_period = temp_ptr;
1175 										}
1176 									else
1177 										temp_host->modified_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
1178 									}
1179 								}
1180 							else if(!strcmp(var, "event_handler")) {
1181 								if(temp_host->modified_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
1182 
1183 									/* make sure the check command still exists... */
1184 									tempval = (char *)strdup(val);
1185 									temp_ptr = my_strtok(tempval, "!");
1186 									temp_command = find_command(temp_ptr);
1187 									temp_ptr = (char *)strdup(val);
1188 									my_free(tempval);
1189 
1190 									if(temp_command != NULL && temp_ptr != NULL) {
1191 										my_free(temp_host->event_handler);
1192 										temp_host->event_handler = temp_ptr;
1193 										}
1194 									else
1195 										temp_host->modified_attributes -= MODATTR_EVENT_HANDLER_COMMAND;
1196 									}
1197 								}
1198 							else if(!strcmp(var, "check_interval")) {
1199 								if(temp_host->modified_attributes & MODATTR_NORMAL_CHECK_INTERVAL && strtod(val, NULL) >= 0)
1200 									temp_host->check_interval = strtod(val, NULL);
1201 								}
1202 							else if(!strcmp(var, "retry_interval")) {
1203 								if(temp_host->modified_attributes & MODATTR_RETRY_CHECK_INTERVAL && strtod(val, NULL) >= 0)
1204 									temp_host->retry_interval = strtod(val, NULL);
1205 								}
1206 							else if(!strcmp(var, "max_attempts")) {
1207 								if(temp_host->modified_attributes & MODATTR_MAX_CHECK_ATTEMPTS && atoi(val) >= 1) {
1208 
1209 									temp_host->max_attempts = atoi(val);
1210 
1211 									/* adjust current attempt number if in a hard state */
1212 									if(temp_host->state_type == HARD_STATE && temp_host->current_state != HOST_UP && temp_host->current_attempt > 1)
1213 										temp_host->current_attempt = temp_host->max_attempts;
1214 									}
1215 								}
1216 
1217 							/* custom variables */
1218 							else if(var[0] == '_') {
1219 
1220 								if(temp_host->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
1221 
1222 									/* get the variable name */
1223 									if((customvarname = (char *)strdup(var + 1))) {
1224 
1225 										for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
1226 											if(!strcmp(customvarname, temp_customvariablesmember->variable_name)) {
1227 												if((x = atoi(val)) > 0 && strlen(val) > 3) {
1228 													my_free(temp_customvariablesmember->variable_value);
1229 													temp_customvariablesmember->variable_value = (char *)strdup(val + 2);
1230 													temp_customvariablesmember->has_been_modified = (x > 0) ? TRUE : FALSE;
1231 													}
1232 												break;
1233 												}
1234 											}
1235 
1236 										/* free memory */
1237 										my_free(customvarname);
1238 										}
1239 									}
1240 
1241 								}
1242 							}
1243 
1244 						}
1245 
1246 					break;
1247 
1248 				case XRDDEFAULT_SERVICESTATUS_DATA:
1249 
1250 					if(temp_service == NULL) {
1251 						if(!strcmp(var, "host_name")) {
1252 							host_name = (char *)strdup(val);
1253 
1254 							/*temp_service=find_service(host_name,service_description);*/
1255 
1256 							/* break out */
1257 							break;
1258 							}
1259 						else if(!strcmp(var, "service_description")) {
1260 							service_description = (char *)strdup(val);
1261 							temp_service = find_service(host_name, service_description);
1262 
1263 							/* break out */
1264 							break;
1265 							}
1266 						}
1267 					else {
1268 						if(!strcmp(var, "modified_attributes")) {
1269 
1270 							temp_service->modified_attributes = strtoul(val, NULL, 10);
1271 
1272 							/* mask out attributes we don't want to retain */
1273 							temp_service->modified_attributes &= ~service_attribute_mask;
1274 							}
1275 						if(temp_service->retain_status_information == TRUE) {
1276 							if(!strcmp(var, "has_been_checked"))
1277 								temp_service->has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
1278 							else if(!strcmp(var, "check_execution_time"))
1279 								temp_service->execution_time = strtod(val, NULL);
1280 							else if(!strcmp(var, "check_latency"))
1281 								temp_service->latency = strtod(val, NULL);
1282 							else if(!strcmp(var, "check_type"))
1283 								temp_service->check_type = atoi(val);
1284 							else if(!strcmp(var, "current_state"))
1285 								temp_service->current_state = atoi(val);
1286 							else if(!strcmp(var, "last_state"))
1287 								temp_service->last_state = atoi(val);
1288 							else if(!strcmp(var, "last_hard_state"))
1289 								temp_service->last_hard_state = atoi(val);
1290 							else if(!strcmp(var, "current_attempt"))
1291 								temp_service->current_attempt = atoi(val);
1292 							else if(!strcmp(var, "current_event_id"))
1293 								temp_service->current_event_id = strtoul(val, NULL, 10);
1294 							else if(!strcmp(var, "last_event_id"))
1295 								temp_service->last_event_id = strtoul(val, NULL, 10);
1296 							else if(!strcmp(var, "current_problem_id"))
1297 								temp_service->current_problem_id = strtoul(val, NULL, 10);
1298 							else if(!strcmp(var, "last_problem_id"))
1299 								temp_service->last_problem_id = strtoul(val, NULL, 10);
1300 							else if(!strcmp(var, "state_type"))
1301 								temp_service->state_type = atoi(val);
1302 							else if(!strcmp(var, "last_state_change"))
1303 								temp_service->last_state_change = strtoul(val, NULL, 10);
1304 							else if(!strcmp(var, "last_hard_state_change"))
1305 								temp_service->last_hard_state_change = strtoul(val, NULL, 10);
1306 							else if(!strcmp(var, "last_time_ok"))
1307 								temp_service->last_time_ok = strtoul(val, NULL, 10);
1308 							else if(!strcmp(var, "last_time_warning"))
1309 								temp_service->last_time_warning = strtoul(val, NULL, 10);
1310 							else if(!strcmp(var, "last_time_unknown"))
1311 								temp_service->last_time_unknown = strtoul(val, NULL, 10);
1312 							else if(!strcmp(var, "last_time_critical"))
1313 								temp_service->last_time_critical = strtoul(val, NULL, 10);
1314 							else if(!strcmp(var, "plugin_output")) {
1315 								my_free(temp_service->plugin_output);
1316 								temp_service->plugin_output = (char *)strdup(val);
1317 								}
1318 							else if(!strcmp(var, "long_plugin_output")) {
1319 								my_free(temp_service->long_plugin_output);
1320 								temp_service->long_plugin_output = (char *)strdup(val);
1321 								}
1322 							else if(!strcmp(var, "performance_data")) {
1323 								my_free(temp_service->perf_data);
1324 								temp_service->perf_data = (char *)strdup(val);
1325 								}
1326 							else if(!strcmp(var, "last_check"))
1327 								temp_service->last_check = strtoul(val, NULL, 10);
1328 							else if(!strcmp(var, "next_check")) {
1329 								if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
1330 									temp_service->next_check = strtoul(val, NULL, 10);
1331 								}
1332 							else if(!strcmp(var, "check_options")) {
1333 								if(use_retained_scheduling_info == TRUE && scheduling_info_is_ok == TRUE)
1334 									temp_service->check_options = atoi(val);
1335 								}
1336 							else if(!strcmp(var, "notified_on_unknown"))
1337 								temp_service->notified_on |= ((atoi(val) > 0) ? OPT_UNKNOWN : 0);
1338 							else if(!strcmp(var, "notified_on_warning"))
1339 								temp_service->notified_on |= ((atoi(val) > 0) ? OPT_WARNING : 0);
1340 							else if(!strcmp(var, "notified_on_critical"))
1341 								temp_service->notified_on |= ((atoi(val) > 0) ? OPT_CRITICAL : 0);
1342 							else if(!strcmp(var, "current_notification_number"))
1343 								temp_service->current_notification_number = atoi(val);
1344 							else if(!strcmp(var, "current_notification_id"))
1345 								temp_service->current_notification_id = strtoul(val, NULL, 10);
1346 							else if(!strcmp(var, "last_notification"))
1347 								temp_service->last_notification = strtoul(val, NULL, 10);
1348 							else if(!strcmp(var, "is_flapping"))
1349 								was_flapping = atoi(val);
1350 							else if(!strcmp(var, "percent_state_change"))
1351 								temp_service->percent_state_change = strtod(val, NULL);
1352 							else if(!strcmp(var, "check_flapping_recovery_notification"))
1353 								temp_service->check_flapping_recovery_notification = atoi(val);
1354 							else if(!strcmp(var, "state_history")) {
1355 								temp_ptr = val;
1356 								for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++) {
1357 									if((ch = my_strsep(&temp_ptr, ",")) != NULL)
1358 										temp_service->state_history[x] = atoi(ch);
1359 									else
1360 										break;
1361 									}
1362 								temp_service->state_history_index = 0;
1363 								}
1364 							else if(!strcmp(var, "flapping_comment_id") && sigrestart == TRUE)
1365 								temp_service->flapping_comment_id = strtoul(val, NULL, 10);
1366 							else
1367 								found_directive = FALSE;
1368 							}
1369 						if(temp_service->retain_nonstatus_information == TRUE) {
1370 							/* null-op speeds up logic */
1371 							if(found_directive == TRUE);
1372 
1373 							else if(!strcmp(var, "problem_has_been_acknowledged"))
1374 								temp_service->problem_has_been_acknowledged = (atoi(val) > 0) ? TRUE : FALSE;
1375 							else if(!strcmp(var, "acknowledgement_type"))
1376 								temp_service->acknowledgement_type = atoi(val);
1377 							else if(!strcmp(var, "notifications_enabled")) {
1378 								if(temp_service->modified_attributes & MODATTR_NOTIFICATIONS_ENABLED)
1379 									temp_service->notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1380 								}
1381 							else if(!strcmp(var, "active_checks_enabled")) {
1382 								if(temp_service->modified_attributes & MODATTR_ACTIVE_CHECKS_ENABLED)
1383 									temp_service->checks_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1384 								}
1385 							else if(!strcmp(var, "passive_checks_enabled")) {
1386 								if(temp_service->modified_attributes & MODATTR_PASSIVE_CHECKS_ENABLED)
1387 									temp_service->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE;
1388 								}
1389 							else if(!strcmp(var, "event_handler_enabled")) {
1390 								if(temp_service->modified_attributes & MODATTR_EVENT_HANDLER_ENABLED)
1391 									temp_service->event_handler_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1392 								}
1393 							else if(!strcmp(var, "flap_detection_enabled")) {
1394 								if(temp_service->modified_attributes & MODATTR_FLAP_DETECTION_ENABLED)
1395 									temp_service->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1396 								}
1397 							else if(!strcmp(var, "process_performance_data")) {
1398 								if(temp_service->modified_attributes & MODATTR_PERFORMANCE_DATA_ENABLED)
1399 									temp_service->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE;
1400 								}
1401 							else if(!strcmp(var, "obsess_over_service") || !strcmp(var, "obsess")) {
1402 								if(temp_service->modified_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED)
1403 									temp_service->obsess = (atoi(val) > 0) ? TRUE : FALSE;
1404 								}
1405 							else if(!strcmp(var, "check_command")) {
1406 								if(temp_service->modified_attributes & MODATTR_CHECK_COMMAND) {
1407 
1408 									/* make sure the check command still exists... */
1409 									tempval = (char *)strdup(val);
1410 									temp_ptr = my_strtok(tempval, "!");
1411 									temp_command = find_command(temp_ptr);
1412 									temp_ptr = (char *)strdup(val);
1413 									my_free(tempval);
1414 
1415 									if(temp_command != NULL && temp_ptr != NULL) {
1416 										my_free(temp_service->check_command);
1417 										temp_service->check_command = temp_ptr;
1418 										}
1419 									else
1420 										temp_service->modified_attributes -= MODATTR_CHECK_COMMAND;
1421 									}
1422 								}
1423 							else if(!strcmp(var, "check_period")) {
1424 								if(temp_service->modified_attributes & MODATTR_CHECK_TIMEPERIOD) {
1425 
1426 									/* make sure the timeperiod still exists... */
1427 									temp_timeperiod = find_timeperiod(val);
1428 									temp_ptr = (char *)strdup(val);
1429 
1430 									if(temp_timeperiod != NULL && temp_ptr != NULL) {
1431 										my_free(temp_service->check_period);
1432 										temp_service->check_period = temp_ptr;
1433 										}
1434 									else
1435 										temp_service->modified_attributes -= MODATTR_CHECK_TIMEPERIOD;
1436 									}
1437 								}
1438 							else if(!strcmp(var, "notification_period")) {
1439 								if(temp_service->modified_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
1440 
1441 									/* make sure the timeperiod still exists... */
1442 									temp_timeperiod = find_timeperiod(val);
1443 									temp_ptr = (char *)strdup(val);
1444 
1445 									if(temp_timeperiod != NULL && temp_ptr != NULL) {
1446 										my_free(temp_service->notification_period);
1447 										temp_service->notification_period = temp_ptr;
1448 										}
1449 									else
1450 										temp_service->modified_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
1451 									}
1452 								}
1453 							else if(!strcmp(var, "event_handler")) {
1454 								if(temp_service->modified_attributes & MODATTR_EVENT_HANDLER_COMMAND) {
1455 
1456 									/* make sure the check command still exists... */
1457 									tempval = (char *)strdup(val);
1458 									temp_ptr = my_strtok(tempval, "!");
1459 									temp_command = find_command(temp_ptr);
1460 									temp_ptr = (char *)strdup(val);
1461 									my_free(tempval);
1462 
1463 									if(temp_command != NULL && temp_ptr != NULL) {
1464 										my_free(temp_service->event_handler);
1465 										temp_service->event_handler = temp_ptr;
1466 										}
1467 									else
1468 										temp_service->modified_attributes -= MODATTR_EVENT_HANDLER_COMMAND;
1469 									}
1470 								}
1471 							else if(!strcmp(var, "check_interval")) {
1472 								if(temp_service->modified_attributes & MODATTR_NORMAL_CHECK_INTERVAL && strtod(val, NULL) >= 0)
1473 									temp_service->check_interval = strtod(val, NULL);
1474 								}
1475 							else if(!strcmp(var, "retry_interval")) {
1476 								if(temp_service->modified_attributes & MODATTR_RETRY_CHECK_INTERVAL && strtod(val, NULL) >= 0)
1477 									temp_service->retry_interval = strtod(val, NULL);
1478 								}
1479 							else if(!strcmp(var, "max_attempts")) {
1480 								if(temp_service->modified_attributes & MODATTR_MAX_CHECK_ATTEMPTS && atoi(val) >= 1) {
1481 
1482 									temp_service->max_attempts = atoi(val);
1483 
1484 									/* adjust current attempt number if in a hard state */
1485 									if(temp_service->state_type == HARD_STATE && temp_service->current_state != STATE_OK && temp_service->current_attempt > 1)
1486 										temp_service->current_attempt = temp_service->max_attempts;
1487 									}
1488 								}
1489 
1490 							/* custom variables */
1491 							else if(var[0] == '_') {
1492 
1493 								if(temp_service->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
1494 
1495 									/* get the variable name */
1496 									if((customvarname = (char *)strdup(var + 1))) {
1497 
1498 										for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
1499 											if(!strcmp(customvarname, temp_customvariablesmember->variable_name)) {
1500 												if((x = atoi(val)) > 0 && strlen(val) > 3) {
1501 													my_free(temp_customvariablesmember->variable_value);
1502 													temp_customvariablesmember->variable_value = (char *)strdup(val + 2);
1503 													temp_customvariablesmember->has_been_modified = (x > 0) ? TRUE : FALSE;
1504 													}
1505 												break;
1506 												}
1507 											}
1508 
1509 										/* free memory */
1510 										my_free(customvarname);
1511 										}
1512 									}
1513 
1514 								}
1515 							}
1516 						}
1517 
1518 					break;
1519 
1520 				case XRDDEFAULT_CONTACTSTATUS_DATA:
1521 					if(temp_contact == NULL) {
1522 						if(!strcmp(var, "contact_name")) {
1523 							contact_name = (char *)strdup(val);
1524 							temp_contact = find_contact(contact_name);
1525 							}
1526 						}
1527 					else {
1528 						if(!strcmp(var, "modified_attributes")) {
1529 
1530 							temp_contact->modified_attributes = strtoul(val, NULL, 10);
1531 
1532 							/* mask out attributes we don't want to retain */
1533 							temp_contact->modified_attributes &= ~contact_attribute_mask;
1534 							}
1535 						else if(!strcmp(var, "modified_host_attributes")) {
1536 
1537 							temp_contact->modified_host_attributes = strtoul(val, NULL, 10);
1538 
1539 							/* mask out attributes we don't want to retain */
1540 							temp_contact->modified_host_attributes &= ~contact_host_attribute_mask;
1541 							}
1542 						else if(!strcmp(var, "modified_service_attributes")) {
1543 							temp_contact->modified_service_attributes = strtoul(val, NULL, 10);
1544 
1545 							/* mask out attributes we don't want to retain */
1546 							temp_contact->modified_service_attributes &= ~contact_service_attribute_mask;
1547 							}
1548 						else if(temp_contact->retain_status_information == TRUE) {
1549 							if(!strcmp(var, "last_host_notification"))
1550 								temp_contact->last_host_notification = strtoul(val, NULL, 10);
1551 							else if(!strcmp(var, "last_service_notification"))
1552 								temp_contact->last_service_notification = strtoul(val, NULL, 10);
1553 							else
1554 								found_directive = FALSE;
1555 							}
1556 						if(temp_contact->retain_nonstatus_information == TRUE) {
1557 							/* null-op speeds up logic */
1558 							if(found_directive == TRUE);
1559 
1560 							else if(!strcmp(var, "host_notification_period")) {
1561 								if(temp_contact->modified_host_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
1562 
1563 									/* make sure the timeperiod still exists... */
1564 									temp_timeperiod = find_timeperiod(val);
1565 									temp_ptr = (char *)strdup(val);
1566 
1567 									if(temp_timeperiod != NULL && temp_ptr != NULL) {
1568 										my_free(temp_contact->host_notification_period);
1569 										temp_contact->host_notification_period = temp_ptr;
1570 										}
1571 									else
1572 										temp_contact->modified_host_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
1573 									}
1574 								}
1575 							else if(!strcmp(var, "service_notification_period")) {
1576 								if(temp_contact->modified_service_attributes & MODATTR_NOTIFICATION_TIMEPERIOD) {
1577 
1578 									/* make sure the timeperiod still exists... */
1579 									temp_timeperiod = find_timeperiod(val);
1580 									temp_ptr = (char *)strdup(val);
1581 
1582 									if(temp_timeperiod != NULL && temp_ptr != NULL) {
1583 										my_free(temp_contact->service_notification_period);
1584 										temp_contact->service_notification_period = temp_ptr;
1585 										}
1586 									else
1587 										temp_contact->modified_service_attributes -= MODATTR_NOTIFICATION_TIMEPERIOD;
1588 									}
1589 								}
1590 							else if(!strcmp(var, "host_notifications_enabled")) {
1591 								if(temp_contact->modified_host_attributes & MODATTR_NOTIFICATIONS_ENABLED)
1592 									temp_contact->host_notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1593 								}
1594 							else if(!strcmp(var, "service_notifications_enabled")) {
1595 								if(temp_contact->modified_service_attributes & MODATTR_NOTIFICATIONS_ENABLED)
1596 									temp_contact->service_notifications_enabled = (atoi(val) > 0) ? TRUE : FALSE;
1597 								}
1598 							/* custom variables */
1599 							else if(var[0] == '_') {
1600 
1601 								if(temp_contact->modified_attributes & MODATTR_CUSTOM_VARIABLE) {
1602 
1603 									/* get the variable name */
1604 									if((customvarname = (char *)strdup(var + 1))) {
1605 
1606 										for(temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
1607 											if(!strcmp(customvarname, temp_customvariablesmember->variable_name)) {
1608 												if((x = atoi(val)) > 0 && strlen(val) > 3) {
1609 													my_free(temp_customvariablesmember->variable_value);
1610 													temp_customvariablesmember->variable_value = (char *)strdup(val + 2);
1611 													temp_customvariablesmember->has_been_modified = (x > 0) ? TRUE : FALSE;
1612 													}
1613 												break;
1614 												}
1615 											}
1616 
1617 										/* free memory */
1618 										my_free(customvarname);
1619 										}
1620 									}
1621 								}
1622 							}
1623 						}
1624 					break;
1625 
1626 				case XRDDEFAULT_HOSTCOMMENT_DATA:
1627 				case XRDDEFAULT_SERVICECOMMENT_DATA:
1628 					if(!strcmp(var, "host_name"))
1629 						host_name = (char *)strdup(val);
1630 					else if(!strcmp(var, "service_description"))
1631 						service_description = (char *)strdup(val);
1632 					else if(!strcmp(var, "entry_type"))
1633 						entry_type = atoi(val);
1634 					else if(!strcmp(var, "comment_id"))
1635 						comment_id = strtoul(val, NULL, 10);
1636 					else if(!strcmp(var, "source"))
1637 						source = atoi(val);
1638 					else if(!strcmp(var, "persistent"))
1639 						persistent = (atoi(val) > 0) ? TRUE : FALSE;
1640 					else if(!strcmp(var, "entry_time"))
1641 						entry_time = strtoul(val, NULL, 10);
1642 					else if(!strcmp(var, "expires"))
1643 						expires = (atoi(val) > 0) ? TRUE : FALSE;
1644 					else if(!strcmp(var, "expire_time"))
1645 						expire_time = strtoul(val, NULL, 10);
1646 					else if(!strcmp(var, "author"))
1647 						author = (char *)strdup(val);
1648 					else if(!strcmp(var, "comment_data"))
1649 						comment_data = (char *)strdup(val);
1650 					break;
1651 
1652 				case XRDDEFAULT_HOSTDOWNTIME_DATA:
1653 				case XRDDEFAULT_SERVICEDOWNTIME_DATA:
1654 					if(!strcmp(var, "host_name"))
1655 						host_name = (char *)strdup(val);
1656 					else if(!strcmp(var, "service_description"))
1657 						service_description = (char *)strdup(val);
1658 					else if(!strcmp(var, "downtime_id"))
1659 						downtime_id = strtoul(val, NULL, 10);
1660 					else if(!strcmp(var, "comment_id"))
1661 						comment_id = strtoul(val, NULL, 10);
1662 					else if(!strcmp(var, "entry_time"))
1663 						entry_time = strtoul(val, NULL, 10);
1664 					else if(!strcmp(var, "start_time"))
1665 						start_time = strtoul(val, NULL, 10);
1666 					else if(!strcmp(var, "flex_downtime_start"))
1667 						flex_downtime_start = strtoul(val, NULL, 10);
1668 					else if(!strcmp(var, "end_time"))
1669 						end_time = strtoul(val, NULL, 10);
1670 					else if(!strcmp(var, "fixed"))
1671 						fixed = (atoi(val) > 0) ? TRUE : FALSE;
1672 					else if(!strcmp(var, "triggered_by"))
1673 						triggered_by = strtoul(val, NULL, 10);
1674 					else if(!strcmp(var, "is_in_effect"))
1675 						is_in_effect = (atoi(val) > 0) ? TRUE : FALSE;
1676 					else if(!strcmp(var, "start_notification_sent"))
1677 						start_notification_sent = (atoi(val) > 0) ? TRUE : FALSE;
1678 					else if(!strcmp(var, "duration"))
1679 						duration = strtoul(val, NULL, 10);
1680 					else if(!strcmp(var, "author"))
1681 						author = (char *)strdup(val);
1682 					else if(!strcmp(var, "comment"))
1683 						comment_data = (char *)strdup(val);
1684 					break;
1685 
1686 				default:
1687 					break;
1688 				}
1689 			}
1690 		}
1691 
1692 	/* free memory and close the file */
1693 	my_free(inputbuf);
1694 	mmap_fclose(thefile);
1695 
1696 	if(sort_downtime() != OK)
1697 		return ERROR;
1698 	if(sort_comments() != OK)
1699 		return ERROR;
1700 
1701 	if(test_scheduling == TRUE)
1702 		gettimeofday(&tv[1], NULL);
1703 
1704 	if(test_scheduling == TRUE) {
1705 		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);
1706 
1707 		runtime[1] = (double)((double)(tv[1].tv_sec - tv[0].tv_sec) + (double)((tv[1].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0);
1708 
1709 		printf("RETENTION DATA TIMES\n");
1710 		printf("----------------------------------\n");
1711 		printf("Read and Process:     %.6lf sec\n", runtime[0]);
1712 		printf("                      ============\n");
1713 		printf("TOTAL:                %.6lf sec\n", runtime[1]);
1714 		printf("\n\n");
1715 		}
1716 
1717 	return OK;
1718 	}
1719