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