1 /*****************************************************************************
2  *
3  * OBJECTS.C - Object addition and search functions 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 #include "../include/config.h"
24 #include "../include/common.h"
25 #include "../include/objects.h"
26 #include "../xdata/xodtemplate.h"
27 
28 #ifdef NSCGI
29 #include "../include/cgiutils.h"
30 #else
31 #include "../include/nagios.h"
32 #endif
33 
34 
35 
36 /*
37  * These get created in xdata/xodtemplate.c:xodtemplate_register_objects()
38  * Escalations are attached to the objects they belong to.
39  * Dependencies are attached to the dependent end of the object chain.
40  */
41 dkhash_table *object_hash_tables[NUM_OBJECT_SKIPLISTS];
42 
43 command *command_list = NULL;
44 timeperiod *timeperiod_list = NULL;
45 host *host_list = NULL;
46 service *service_list = NULL;
47 contact *contact_list = NULL;
48 hostgroup *hostgroup_list = NULL;
49 servicegroup *servicegroup_list = NULL;
50 contactgroup *contactgroup_list = NULL;
51 hostescalation *hostescalation_list = NULL;
52 serviceescalation *serviceescalation_list = NULL;
53 command **command_ary = NULL;
54 timeperiod **timeperiod_ary = NULL;
55 host **host_ary = NULL;
56 service **service_ary = NULL;
57 contact **contact_ary = NULL;
58 hostgroup **hostgroup_ary = NULL;
59 servicegroup **servicegroup_ary = NULL;
60 contactgroup **contactgroup_ary = NULL;
61 hostescalation **hostescalation_ary = NULL;
62 serviceescalation **serviceescalation_ary = NULL;
63 hostdependency **hostdependency_ary = NULL;
64 servicedependency **servicedependency_ary = NULL;
65 
66 #ifndef NSCGI
67 int __nagios_object_structure_version = CURRENT_OBJECT_STRUCTURE_VERSION;
68 
69 struct flag_map {
70 	int opt;
71 	int ch;
72 	const char *name;
73 };
74 
75 static const struct flag_map service_flag_map[] = {
76 	{ OPT_WARNING, 'w', "warning" },
77 	{ OPT_UNKNOWN, 'u', "unknown" },
78 	{ OPT_CRITICAL, 'c', "critical" },
79 	{ OPT_FLAPPING, 'f', "flapping" },
80 	{ OPT_DOWNTIME, 's', "downtime" },
81 	{ OPT_OK, 'o', "ok" },
82 	{ OPT_RECOVERY, 'r', "recovery" },
83 	{ OPT_PENDING, 'p', "pending" },
84 	{ OPT_NOTIFICATIONS, 'N', "notifications" },
85 	{ 0, 0, NULL },
86 };
87 
88 static const struct flag_map host_flag_map[] = {
89 	{ OPT_DOWN, 'd', "down" },
90 	{ OPT_UNREACHABLE, 'u', "unreachable" },
91 	{ OPT_FLAPPING, 'f', "flapping" },
92 	{ OPT_RECOVERY, 'r', "recovery" },
93 	{ OPT_DOWNTIME, 's', "downtime" },
94 	{ OPT_PENDING, 'p', "pending" },
95 	{ OPT_NOTIFICATIONS, 'N', "notifications" },
96 	{ 0, 0, NULL },
97 };
98 
opts2str(int opts,const struct flag_map * map,char ok_char)99 static const char *opts2str(int opts, const struct flag_map *map, char ok_char)
100 {
101 	int i, pos = 0;
102 	static char buf[16];
103 
104 	if(!opts)
105 		return "n";
106 
107 	if(opts == OPT_ALL)
108 		return "a";
109 
110 	if(flag_isset(opts, OPT_OK)) {
111 		flag_unset(opts, OPT_OK);
112 		buf[pos++] = ok_char;
113 		buf[pos++] = opts ? ',' : 0;
114 		}
115 
116 	for (i = 0; map[i].name; i++) {
117 		if(flag_isset(opts, map[i].opt)) {
118 			buf[pos++] = map[i].ch;
119 			flag_unset(opts, map[i].opt);
120 			if(!opts)
121 				break;
122 			buf[pos++] = ',';
123 		}
124 	}
125 	buf[pos++] = 0;
126 	return buf;
127 }
128 #endif
129 
host_services_value(host * h)130 unsigned int host_services_value(host *h) {
131 	servicesmember *sm;
132 	unsigned int ret = 0;
133 	for(sm = h->services; sm; sm = sm->next) {
134 		ret += sm->service_ptr->hourly_value;
135 		}
136 	return ret;
137 	}
138 
139 
140 #ifndef NSCGI
141 /* Host/Service dependencies are not visible in Nagios CGIs, so we exclude them */
cmp_sdep(const void * a_,const void * b_)142 static int cmp_sdep(const void *a_, const void *b_) {
143 	const servicedependency *a = *(servicedependency **)a_;
144 	const servicedependency *b = *(servicedependency **)b_;
145 	int ret;
146 	ret = a->master_service_ptr->id - b->master_service_ptr->id;
147 	return ret ? ret : (int)(a->dependent_service_ptr->id - b->dependent_service_ptr->id);
148 	}
149 
cmp_hdep(const void * a_,const void * b_)150 static int cmp_hdep(const void *a_, const void *b_) {
151 	const hostdependency *a = *(const hostdependency **)a_;
152 	const hostdependency *b = *(const hostdependency **)b_;
153 	int ret;
154 	ret = a->master_host_ptr->id - b->master_host_ptr->id;
155 	return ret ? ret : (int)(a->dependent_host_ptr->id - b->dependent_host_ptr->id);
156 	}
157 
cmp_serviceesc(const void * a_,const void * b_)158 static int cmp_serviceesc(const void *a_, const void *b_) {
159 	const serviceescalation *a = *(const serviceescalation **)a_;
160 	const serviceescalation *b = *(const serviceescalation **)b_;
161 	return a->service_ptr->id - b->service_ptr->id;
162 	}
163 
cmp_hostesc(const void * a_,const void * b_)164 static int cmp_hostesc(const void *a_, const void *b_) {
165 	const hostescalation *a = *(const hostescalation **)a_;
166 	const hostescalation *b = *(const hostescalation **)b_;
167 	return a->host_ptr->id - b->host_ptr->id;
168 	}
169 #endif
170 
post_process_object_config(void)171 static void post_process_object_config(void) {
172 	objectlist *list;
173 	unsigned int i, slot;
174 
175 	if(hostdependency_ary)
176 		free(hostdependency_ary);
177 	if(servicedependency_ary)
178 		free(servicedependency_ary);
179 
180 	hostdependency_ary = calloc(num_objects.hostdependencies, sizeof(void *));
181 	servicedependency_ary = calloc(num_objects.servicedependencies, sizeof(void *));
182 
183 	slot = 0;
184 	for(i = 0; slot < num_objects.servicedependencies && i < num_objects.services; i++) {
185 		service *s = service_ary[i];
186 		for(list = s->notify_deps; list; list = list->next)
187 			servicedependency_ary[slot++] = (servicedependency *)list->object_ptr;
188 		for(list = s->exec_deps; list; list = list->next)
189 			servicedependency_ary[slot++] = (servicedependency *)list->object_ptr;
190 	}
191 	timing_point("Done post-processing servicedependencies\n");
192 
193 	slot = 0;
194 	for(i = 0; slot < num_objects.hostdependencies && i < num_objects.hosts; i++) {
195 		host *h = host_ary[i];
196 		for(list = h->notify_deps; list; list = list->next)
197 			hostdependency_ary[slot++] = (hostdependency *)list->object_ptr;
198 		for(list = h->exec_deps; list; list = list->next)
199 			hostdependency_ary[slot++] = (hostdependency *)list->object_ptr;
200 	}
201 	timing_point("Done post-processing host dependencies\n");
202 
203 #ifndef NSCGI
204 	/* cgi's always get their objects in sorted order */
205 	if(servicedependency_ary)
206 		qsort(servicedependency_ary, num_objects.servicedependencies, sizeof(servicedependency *), cmp_sdep);
207 	if(hostdependency_ary)
208 		qsort(hostdependency_ary, num_objects.hostdependencies, sizeof(hostdependency *), cmp_hdep);
209 	if(hostescalation_ary)
210 		qsort(hostescalation_ary, num_objects.hostescalations, sizeof(hostescalation *), cmp_hostesc);
211 	if(serviceescalation_ary)
212 		qsort(serviceescalation_ary, num_objects.serviceescalations, sizeof(serviceescalation *), cmp_serviceesc);
213 	timing_point("Done post-sorting slave objects\n");
214 #endif
215 
216 	timeperiod_list = timeperiod_ary ? *timeperiod_ary : NULL;
217 	command_list = command_ary ? *command_ary : NULL;
218 	hostgroup_list = hostgroup_ary ? *hostgroup_ary : NULL;
219 	contactgroup_list = contactgroup_ary ? *contactgroup_ary : NULL;
220 	servicegroup_list = servicegroup_ary ? *servicegroup_ary : NULL;
221 	contact_list = contact_ary ? *contact_ary : NULL;
222 	host_list = host_ary ? *host_ary : NULL;
223 	service_list = service_ary ? *service_ary : NULL;
224 	hostescalation_list = hostescalation_ary ? *hostescalation_ary : NULL;
225 	serviceescalation_list = serviceescalation_ary ? *serviceescalation_ary : NULL;
226 }
227 
228 /* simple state-name helpers, nifty to have all over the place */
service_state_name(int state)229 const char *service_state_name(int state)
230 {
231 	switch (state) {
232 	case STATE_OK: return "OK";
233 	case STATE_WARNING: return "WARNING";
234 	case STATE_CRITICAL: return "CRITICAL";
235 	}
236 
237 	return "UNKNOWN";
238 }
239 
host_state_name(int state)240 const char *host_state_name(int state)
241 {
242 	switch (state) {
243 	case HOST_UP: return "UP";
244 	case HOST_DOWN: return "DOWN";
245 	case HOST_UNREACHABLE: return "UNREACHABLE";
246 	}
247 
248 	return "(unknown)";
249 }
250 
state_type_name(int state_type)251 const char *state_type_name(int state_type)
252 {
253 	return state_type == HARD_STATE ? "HARD" : "SOFT";
254 }
255 
check_type_name(int check_type)256 const char *check_type_name(int check_type)
257 {
258 	return check_type == CHECK_TYPE_PASSIVE ? "PASSIVE" : "ACTIVE";
259 }
260 
261 /******************************************************************/
262 /******* TOP-LEVEL HOST CONFIGURATION DATA INPUT FUNCTION *********/
263 /******************************************************************/
264 
265 
266 /* read all host configuration data from external source */
read_object_config_data(const char * main_config_file,int options)267 int read_object_config_data(const char *main_config_file, int options) {
268 	int result = OK;
269 
270 	/* reset object counts */
271 	memset(&num_objects, 0, sizeof(num_objects));
272 
273 	/* read in data from all text host config files (template-based) */
274 	result = xodtemplate_read_config_data(main_config_file, options);
275 	if(result != OK)
276 		return ERROR;
277 
278 	/* handle any remaining config mangling */
279 	post_process_object_config();
280 	timing_point("Done post-processing configuration\n");
281 
282 	return result;
283 	}
284 
285 
286 
287 /******************************************************************/
288 /******************** SKIPLIST FUNCTIONS **************************/
289 /******************************************************************/
290 
291 
skiplist_compare_text(const char * val1a,const char * val1b,const char * val2a,const char * val2b)292 int skiplist_compare_text(const char *val1a, const char *val1b, const char *val2a, const char *val2b) {
293 	int result = 0;
294 
295 	/* check first name */
296 	if(val1a == NULL && val2a == NULL)
297 		result = 0;
298 	else if(val1a == NULL)
299 		result = 1;
300 	else if(val2a == NULL)
301 		result = -1;
302 	else
303 		result = strcmp(val1a, val2a);
304 
305 	/* check second name if necessary */
306 	if(result == 0) {
307 		if(val1b == NULL && val2b == NULL)
308 			result = 0;
309 		else if(val1b == NULL)
310 			result = 1;
311 		else if(val2b == NULL)
312 			result = -1;
313 		else
314 			result = strcmp(val1b, val2b);
315 		}
316 
317 	return result;
318 	}
319 
320 
get_host_count(void)321 int get_host_count(void) {
322 	return num_objects.hosts;
323 	}
324 
325 
get_service_count(void)326 int get_service_count(void) {
327 	return num_objects.services;
328 	}
329 
330 
331 
332 
333 /******************************************************************/
334 /**************** OBJECT ADDITION FUNCTIONS ***********************/
335 /******************************************************************/
336 
create_object_table(const char * name,unsigned int elems,unsigned int size,void ** ptr)337 static int create_object_table(const char *name, unsigned int elems, unsigned int size, void **ptr)
338 {
339 	void *ret;
340 	if (!elems) {
341 		*ptr = NULL;
342 		return OK;
343 		}
344 	ret = calloc(elems, size);
345 	if (!ret) {
346 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to allocate %s table with %u elements\n", name, elems);
347 		return ERROR;
348 		}
349 	*ptr = ret;
350 	return OK;
351 }
352 
353 #define mktable(name, id) \
354 	create_object_table(#name, ocount[id], sizeof(name *), (void **)&name##_ary)
355 
356 /* ocount is an array with NUM_OBJECT_TYPES members */
create_object_tables(unsigned int * ocount)357 int create_object_tables(unsigned int *ocount)
358 {
359 	int i;
360 
361 	for (i = 0; i < NUM_HASHED_OBJECT_TYPES; i++) {
362 		const unsigned int hash_size = ocount[i];
363 		if (!hash_size)
364 			continue;
365 		object_hash_tables[i] = dkhash_create(hash_size);
366 		if (!object_hash_tables[i]) {
367 			logit(NSLOG_CONFIG_ERROR, TRUE, "Failed to create hash table with %u entries\n", hash_size);
368 		}
369 	}
370 
371 	/*
372 	 * errors here will always lead to an early exit, so there's no need
373 	 * to free() successful allocs when later ones fail
374 	 */
375 	if (mktable(timeperiod, TIMEPERIOD_SKIPLIST) != OK)
376 		return ERROR;
377 	if (mktable(command, COMMAND_SKIPLIST) != OK)
378 		return ERROR;
379 	if (mktable(host, HOST_SKIPLIST) != OK)
380 		return ERROR;
381 	if (mktable(service, SERVICE_SKIPLIST) != OK)
382 		return ERROR;
383 	if (mktable(contact, CONTACT_SKIPLIST) != OK)
384 		return ERROR;
385 	if (mktable(hostgroup, HOSTGROUP_SKIPLIST) != OK)
386 		return ERROR;
387 	if (mktable(servicegroup, SERVICEGROUP_SKIPLIST) != OK)
388 		return ERROR;
389 	if (mktable(contactgroup, CONTACTGROUP_SKIPLIST) != OK)
390 		return ERROR;
391 	if (mktable(hostescalation, HOSTESCALATION_SKIPLIST) != OK)
392 		return ERROR;
393 	if (mktable(hostdependency, HOSTDEPENDENCY_SKIPLIST) != OK)
394 		return ERROR;
395 	if (mktable(serviceescalation, SERVICEESCALATION_SKIPLIST) != OK)
396 		return ERROR;
397 	if (mktable(servicedependency, SERVICEDEPENDENCY_SKIPLIST) != OK)
398 		return ERROR;
399 
400 	return OK;
401 }
402 
403 
404 /* add a new timeperiod to the list in memory */
add_timeperiod(char * name,char * alias)405 timeperiod *add_timeperiod(char *name, char *alias) {
406 	timeperiod *new_timeperiod = NULL;
407 	int result = OK;
408 
409 	/* make sure we have the data we need */
410 	if((name == NULL || !strcmp(name, "")) || (alias == NULL || !strcmp(alias, ""))) {
411 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Name or alias for timeperiod is NULL\n");
412 		return NULL;
413 		}
414 
415 	new_timeperiod = calloc(1, sizeof(*new_timeperiod));
416 	if(!new_timeperiod)
417 		return NULL;
418 
419 	/* copy string vars */
420 	new_timeperiod->name = name;
421 	new_timeperiod->alias = alias ? alias : name;
422 
423 	/* add new timeperiod to hash table */
424 	if(result == OK) {
425 		result = dkhash_insert(object_hash_tables[TIMEPERIOD_SKIPLIST], new_timeperiod->name, NULL, new_timeperiod);
426 		switch(result) {
427 			case DKHASH_EDUPE:
428 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Timeperiod '%s' has already been defined\n", name);
429 				result = ERROR;
430 				break;
431 			case DKHASH_OK:
432 				result = OK;
433 				break;
434 			default:
435 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add timeperiod '%s' to hash table\n", name);
436 				result = ERROR;
437 				break;
438 			}
439 		}
440 
441 	/* handle errors */
442 	if(result == ERROR) {
443 		free(new_timeperiod);
444 		return NULL;
445 		}
446 
447 	new_timeperiod->id = num_objects.timeperiods++;
448 	if(new_timeperiod->id)
449 		timeperiod_ary[new_timeperiod->id - 1]->next = new_timeperiod;
450 	timeperiod_ary[new_timeperiod->id] = new_timeperiod;
451 	return new_timeperiod;
452 	}
453 
454 
455 
456 
457 /* adds a new exclusion to a timeperiod */
add_exclusion_to_timeperiod(timeperiod * period,char * name)458 timeperiodexclusion *add_exclusion_to_timeperiod(timeperiod *period, char *name) {
459 	timeperiodexclusion *new_timeperiodexclusion = NULL;
460 
461 	/* make sure we have enough data */
462 	if(period == NULL || name == NULL)
463 		return NULL;
464 
465 	if((new_timeperiodexclusion = (timeperiodexclusion *)malloc(sizeof(timeperiodexclusion))) == NULL)
466 		return NULL;
467 
468 	new_timeperiodexclusion->timeperiod_name = (char *)strdup(name);
469 
470 	new_timeperiodexclusion->next = period->exclusions;
471 	period->exclusions = new_timeperiodexclusion;
472 
473 	return new_timeperiodexclusion;
474 	}
475 
476 
477 
478 
479 /* add a new timerange to a timeperiod */
add_timerange_to_timeperiod(timeperiod * period,int day,unsigned long start_time,unsigned long end_time)480 timerange *add_timerange_to_timeperiod(timeperiod *period, int day, unsigned long start_time, unsigned long end_time) {
481 	timerange *prev = NULL, *tr, *new_timerange = NULL;
482 
483 	/* make sure we have the data we need */
484 	if(period == NULL)
485 		return NULL;
486 
487 	if(day < 0 || day > 6) {
488 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Day %d is not valid for timeperiod '%s'\n", day, period->name);
489 		return NULL;
490 		}
491 	if(start_time > 86400) {
492 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Start time %lu on day %d is not valid for timeperiod '%s'\n", start_time, day, period->name);
493 		return NULL;
494 		}
495 	if(end_time > 86400) {
496 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: End time %lu on day %d is not value for timeperiod '%s'\n", end_time, day, period->name);
497 		return NULL;
498 		}
499 
500 	/* allocate memory for the new time range */
501 	if((new_timerange = malloc(sizeof(timerange))) == NULL)
502 		return NULL;
503 
504 	new_timerange->range_start = start_time;
505 	new_timerange->range_end = end_time;
506 
507 	/* insertion-sort the new time range into the list for this day */
508 	if(!period->days[day] || period->days[day]->range_start > new_timerange->range_start) {
509 		new_timerange->next = period->days[day];
510 		period->days[day] = new_timerange;
511 		return new_timerange;
512 		}
513 
514 	for(tr = period->days[day]; tr; tr = tr->next) {
515 		if(new_timerange->range_start < tr->range_start) {
516 			new_timerange->next = tr;
517 			prev->next = new_timerange;
518 			break;
519 			}
520 		if(!tr->next) {
521 			tr->next = new_timerange;
522 			new_timerange->next = NULL;
523 			break;
524 			}
525 		prev = tr;
526 		}
527 
528 	return new_timerange;
529 	}
530 
531 
532 /* add a new exception to a timeperiod */
add_exception_to_timeperiod(timeperiod * period,int type,int syear,int smon,int smday,int swday,int swday_offset,int eyear,int emon,int emday,int ewday,int ewday_offset,int skip_interval)533 daterange *add_exception_to_timeperiod(timeperiod *period, int type, int syear, int smon, int smday, int swday, int swday_offset, int eyear, int emon, int emday, int ewday, int ewday_offset, int skip_interval) {
534 	daterange *new_daterange = NULL;
535 
536 	/* make sure we have the data we need */
537 	if(period == NULL)
538 		return NULL;
539 
540 	/* allocate memory for the date range range */
541 	if((new_daterange = malloc(sizeof(daterange))) == NULL)
542 		return NULL;
543 
544 	new_daterange->times = NULL;
545 	new_daterange->next = NULL;
546 
547 	new_daterange->type = type;
548 	new_daterange->syear = syear;
549 	new_daterange->smon = smon;
550 	new_daterange->smday = smday;
551 	new_daterange->swday = swday;
552 	new_daterange->swday_offset = swday_offset;
553 	new_daterange->eyear = eyear;
554 	new_daterange->emon = emon;
555 	new_daterange->emday = emday;
556 	new_daterange->ewday = ewday;
557 	new_daterange->ewday_offset = ewday_offset;
558 	new_daterange->skip_interval = skip_interval;
559 
560 	/* add the new date range to the head of the range list for this exception type */
561 	new_daterange->next = period->exceptions[type];
562 	period->exceptions[type] = new_daterange;
563 
564 	return new_daterange;
565 	}
566 
567 
568 
569 /* add a new timerange to a daterange */
add_timerange_to_daterange(daterange * drange,unsigned long start_time,unsigned long end_time)570 timerange *add_timerange_to_daterange(daterange *drange, unsigned long start_time, unsigned long end_time) {
571 	timerange *new_timerange = NULL;
572 
573 	/* make sure we have the data we need */
574 	if(drange == NULL)
575 		return NULL;
576 
577 	if(start_time > 86400) {
578 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Start time %lu is not valid for timeperiod\n", start_time);
579 		return NULL;
580 		}
581 	if(end_time > 86400) {
582 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: End time %lu is not value for timeperiod\n", end_time);
583 		return NULL;
584 		}
585 
586 	/* allocate memory for the new time range */
587 	if((new_timerange = malloc(sizeof(timerange))) == NULL)
588 		return NULL;
589 
590 	new_timerange->range_start = start_time;
591 	new_timerange->range_end = end_time;
592 
593 	/* add the new time range to the head of the range list for this date range */
594 	new_timerange->next = drange->times;
595 	drange->times = new_timerange;
596 
597 	return new_timerange;
598 	}
599 
600 
601 
602 /* add a new host definition */
add_host(char * name,char * display_name,char * alias,char * address,char * check_period,int initial_state,double check_interval,double retry_interval,int max_attempts,int notification_options,double notification_interval,double first_notification_delay,char * notification_period,int notifications_enabled,char * check_command,int checks_enabled,int accept_passive_checks,char * event_handler,int event_handler_enabled,int flap_detection_enabled,double low_flap_threshold,double high_flap_threshold,int flap_detection_options,int stalking_options,int process_perfdata,int check_freshness,int freshness_threshold,char * notes,char * notes_url,char * action_url,char * icon_image,char * icon_image_alt,char * vrml_image,char * statusmap_image,int x_2d,int y_2d,int have_2d_coords,double x_3d,double y_3d,double z_3d,int have_3d_coords,int should_be_drawn,int retain_status_information,int retain_nonstatus_information,int obsess,unsigned int hourly_value)603 host *add_host(char *name, char *display_name, char *alias, char *address, char *check_period, int initial_state, double check_interval, double retry_interval, int max_attempts, int notification_options, double notification_interval, double first_notification_delay, char *notification_period, int notifications_enabled, char *check_command, int checks_enabled, int accept_passive_checks, char *event_handler, int event_handler_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_options, int stalking_options, int process_perfdata, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, char *vrml_image, char *statusmap_image, int x_2d, int y_2d, int have_2d_coords, double x_3d, double y_3d, double z_3d, int have_3d_coords, int should_be_drawn, int retain_status_information, int retain_nonstatus_information, int obsess, unsigned int hourly_value) {
604 	host *new_host = NULL;
605 	timeperiod *check_tp = NULL, *notify_tp = NULL;
606 	int result = OK;
607 
608 	/* make sure we have the data we need */
609 	if(name == NULL || !strcmp(name, "")) {
610 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host name is NULL\n");
611 		return NULL;
612 		}
613 
614 	if(check_period && !(check_tp = find_timeperiod(check_period))) {
615 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate check_period '%s' for host '%s'!\n",
616 			  check_period, name);
617 		return NULL;
618 	}
619 	if(notification_period && !(notify_tp = find_timeperiod(notification_period))) {
620 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate notification_period '%s' for host '%s'!\n",
621 			  notification_period, name);
622 		return NULL;
623 	}
624 	/* check values */
625 	if(max_attempts <= 0) {
626 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid max_check_attempts value for host '%s'\n", name);
627 		return NULL;
628 		}
629 	if(check_interval < 0) {
630 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid check_interval value for host '%s'\n", name);
631 		return NULL;
632 		}
633 	if(notification_interval < 0) {
634 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid notification_interval value for host '%s'\n", name);
635 		return NULL;
636 		}
637 	if(first_notification_delay < 0) {
638 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid first_notification_delay value for host '%s'\n", name);
639 		return NULL;
640 		}
641 	if(freshness_threshold < 0) {
642 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid freshness_threshold value for host '%s'\n", name);
643 		return NULL;
644 		}
645 
646 	new_host = calloc(1, sizeof(*new_host));
647 
648 	/* assign string vars */
649 	new_host->name = name;
650 	new_host->display_name = display_name ? display_name : new_host->name;
651 	new_host->alias = alias ? alias : new_host->name;
652 	new_host->address = address ? address : new_host->name;
653 	new_host->check_period = check_tp ? (char *)strdup(check_tp->name) : NULL;
654 	new_host->notification_period = notify_tp ? (char *)strdup(notify_tp->name) : NULL;
655 	new_host->notification_period_ptr = notify_tp;
656 	new_host->check_period_ptr = check_tp;
657 	new_host->check_command = check_command;
658 	new_host->event_handler = event_handler;
659 	new_host->notes = notes;
660 	new_host->notes_url = notes_url;
661 	new_host->action_url = action_url;
662 	new_host->icon_image = icon_image;
663 	new_host->icon_image_alt = icon_image_alt;
664 	new_host->vrml_image = vrml_image;
665 	new_host->statusmap_image = statusmap_image;
666 
667 	/* duplicate non-string vars */
668 	new_host->hourly_value = hourly_value;
669 	new_host->max_attempts = max_attempts;
670 	new_host->check_interval = check_interval;
671 	new_host->retry_interval = retry_interval;
672 	new_host->notification_interval = notification_interval;
673 	new_host->first_notification_delay = first_notification_delay;
674 	new_host->notification_options = notification_options;
675 	new_host->flap_detection_enabled = (flap_detection_enabled > 0) ? TRUE : FALSE;
676 	new_host->low_flap_threshold = low_flap_threshold;
677 	new_host->high_flap_threshold = high_flap_threshold;
678 	new_host->flap_detection_options = flap_detection_options;
679 	new_host->stalking_options = stalking_options;
680 	new_host->process_performance_data = (process_perfdata > 0) ? TRUE : FALSE;
681 	new_host->check_freshness = (check_freshness > 0) ? TRUE : FALSE;
682 	new_host->freshness_threshold = freshness_threshold;
683 	new_host->checks_enabled = (checks_enabled > 0) ? TRUE : FALSE;
684 	new_host->accept_passive_checks = (accept_passive_checks > 0) ? TRUE : FALSE;
685 	new_host->event_handler_enabled = (event_handler_enabled > 0) ? TRUE : FALSE;
686 	new_host->x_2d = x_2d;
687 	new_host->y_2d = y_2d;
688 	new_host->have_2d_coords = (have_2d_coords > 0) ? TRUE : FALSE;
689 	new_host->x_3d = x_3d;
690 	new_host->y_3d = y_3d;
691 	new_host->z_3d = z_3d;
692 	new_host->have_3d_coords = (have_3d_coords > 0) ? TRUE : FALSE;
693 	new_host->should_be_drawn = (should_be_drawn > 0) ? TRUE : FALSE;
694 	new_host->obsess = (obsess > 0) ? TRUE : FALSE;
695 	new_host->retain_status_information = (retain_status_information > 0) ? TRUE : FALSE;
696 	new_host->retain_nonstatus_information = (retain_nonstatus_information > 0) ? TRUE : FALSE;
697 #ifdef NSCORE
698 	new_host->current_state = initial_state;
699 	new_host->last_state = initial_state;
700 	new_host->last_hard_state = initial_state;
701 	new_host->check_type = CHECK_TYPE_ACTIVE;
702 	new_host->should_be_scheduled = TRUE;
703 	new_host->current_attempt = (initial_state == HOST_UP) ? 1 : max_attempts;
704 	new_host->state_type = HARD_STATE;
705 	new_host->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
706 	new_host->notifications_enabled = (notifications_enabled > 0) ? TRUE : FALSE;
707 	new_host->check_options = CHECK_OPTION_NONE;
708 #endif
709 
710 	/* add new host to hash table */
711 	if(result == OK) {
712 		result = dkhash_insert(object_hash_tables[HOST_SKIPLIST], new_host->name, NULL, new_host);
713 		switch(result) {
714 			case DKHASH_EDUPE:
715 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host '%s' has already been defined\n", name);
716 				result = ERROR;
717 				break;
718 			case DKHASH_OK:
719 				result = OK;
720 				break;
721 			default:
722 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add host '%s' to hash table\n", name);
723 				result = ERROR;
724 				break;
725 			}
726 		}
727 
728 	/* handle errors */
729 	if(result == ERROR) {
730 		my_free(new_host);
731 		return NULL;
732 		}
733 
734 	new_host->id = num_objects.hosts++;
735 	host_ary[new_host->id] = new_host;
736 	if(new_host->id)
737 		host_ary[new_host->id - 1]->next = new_host;
738 	return new_host;
739 	}
740 
741 
742 
add_parent_host_to_host(host * hst,char * host_name)743 hostsmember *add_parent_host_to_host(host *hst, char *host_name) {
744 	hostsmember *new_hostsmember = NULL;
745 	int result = OK;
746 
747 	/* make sure we have the data we need */
748 	if(hst == NULL || host_name == NULL || !strcmp(host_name, "")) {
749 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host is NULL or parent host name is NULL\n");
750 		return NULL;
751 		}
752 
753 	/* a host cannot be a parent/child of itself */
754 	if(!strcmp(host_name, hst->name)) {
755 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host '%s' cannot be a child/parent of itself\n", hst->name);
756 		return NULL;
757 		}
758 
759 	/* allocate memory */
760 	if((new_hostsmember = (hostsmember *)calloc(1, sizeof(hostsmember))) == NULL)
761 		return NULL;
762 
763 	/* duplicate string vars */
764 	if((new_hostsmember->host_name = (char *)strdup(host_name)) == NULL)
765 		result = ERROR;
766 
767 	/* handle errors */
768 	if(result == ERROR) {
769 		my_free(new_hostsmember->host_name);
770 		my_free(new_hostsmember);
771 		return NULL;
772 		}
773 
774 	/* add the parent host entry to the host definition */
775 	new_hostsmember->next = hst->parent_hosts;
776 	hst->parent_hosts = new_hostsmember;
777 
778 	return new_hostsmember;
779 	}
780 
add_parent_service_to_service(service * svc,char * host_name,char * description)781 servicesmember *add_parent_service_to_service(service *svc, char *host_name, char *description) {
782 	servicesmember *sm;
783 
784 	if(!svc || !host_name || !description || !*host_name || !*description)
785 		return NULL;
786 
787 	if (strcmp(svc->host_name, host_name) == 0 && strcmp(svc->description, description) == 0) {
788 		logit(NSLOG_CONFIG_ERROR, TRUE,
789 				"Error: Host '%s' Service '%s' cannot be a child/parent of itself\n",
790 				svc->host_name, svc->description);
791 		return NULL;
792 	}
793 
794 	if((sm = calloc(1, sizeof(*sm))) == NULL)
795 		return NULL;
796 
797 	if ((sm->host_name = strdup(host_name)) == NULL || (sm->service_description = strdup(description)) == NULL) {
798 		/* there was an error copying (description is NULL now) */
799 		my_free(sm->host_name);
800 		free(sm);
801 		return NULL;
802 		}
803 
804 	sm->next = svc->parents;
805 	svc->parents = sm;
806 	return sm;
807 	}
808 
add_child_link_to_host(host * hst,host * child_ptr)809 hostsmember *add_child_link_to_host(host *hst, host *child_ptr) {
810 	hostsmember *new_hostsmember = NULL;
811 
812 	/* make sure we have the data we need */
813 	if(hst == NULL || child_ptr == NULL)
814 		return NULL;
815 
816 	/* allocate memory */
817 	if((new_hostsmember = (hostsmember *)malloc(sizeof(hostsmember))) == NULL)
818 		return NULL;
819 
820 	/* assign values */
821 	new_hostsmember->host_name = child_ptr->name;
822 	new_hostsmember->host_ptr = child_ptr;
823 
824 	/* add the child entry to the host definition */
825 	new_hostsmember->next = hst->child_hosts;
826 	hst->child_hosts = new_hostsmember;
827 
828 	return new_hostsmember;
829 	}
830 
831 
832 
add_service_link_to_host(host * hst,service * service_ptr)833 servicesmember *add_service_link_to_host(host *hst, service *service_ptr) {
834 	servicesmember *new_servicesmember = NULL;
835 
836 	/* make sure we have the data we need */
837 	if(hst == NULL || service_ptr == NULL)
838 		return NULL;
839 
840 	/* allocate memory */
841 	if((new_servicesmember = (servicesmember *)calloc(1, sizeof(servicesmember))) == NULL)
842 		return NULL;
843 
844 	/* assign values */
845 	new_servicesmember->host_name = service_ptr->host_name;
846 	new_servicesmember->service_description = service_ptr->description;
847 	new_servicesmember->service_ptr = service_ptr;
848 #ifndef NSCGI
849 	hst->total_services++;
850 #endif
851 
852 	/* add the child entry to the host definition */
853 	new_servicesmember->next = hst->services;
854 	hst->services = new_servicesmember;
855 
856 	return new_servicesmember;
857 	}
858 
859 
860 
add_child_link_to_service(service * svc,service * child_ptr)861 servicesmember *add_child_link_to_service(service *svc, service *child_ptr) {
862 	servicesmember *new_servicesmember = NULL;
863 
864 	/* make sure we have the data we need */
865 	if(svc == NULL || child_ptr == NULL)
866 		return NULL;
867 
868 	/* allocate memory */
869 	if((new_servicesmember = (servicesmember *)malloc(sizeof(servicesmember)))
870 			== NULL) return NULL;
871 
872 	/* assign values */
873 	new_servicesmember->host_name = child_ptr->host_name;
874 	new_servicesmember->service_description = child_ptr->description;
875 	new_servicesmember->service_ptr = child_ptr;
876 
877 	/* add the child entry to the host definition */
878 	new_servicesmember->next = svc->children;
879 	svc->children = new_servicesmember;
880 
881 	return new_servicesmember;
882 	}
883 
884 
885 
add_contactgroup_to_object(contactgroupsmember ** cg_list,const char * group_name)886 static contactgroupsmember *add_contactgroup_to_object(contactgroupsmember **cg_list, const char *group_name) {
887 	contactgroupsmember *cgm;
888 	contactgroup *cg;
889 
890 	if(!group_name || !*group_name) {
891 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n");
892 		return NULL;
893 		}
894 	if(!(cg = find_contactgroup(group_name))) {
895 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup '%s' is not defined anywhere\n", group_name);
896 		return NULL;
897 		}
898 	if(!(cgm = malloc(sizeof(*cgm)))) {
899 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for contactgroup\n");
900 		return NULL;
901 		}
902 	cgm->group_name = cg->group_name;
903 	cgm->group_ptr = cg;
904 	cgm->next = *cg_list;
905 	*cg_list = cgm;
906 
907 	return cgm;
908 	}
909 
910 
911 /* add a new contactgroup to a host */
add_contactgroup_to_host(host * hst,char * group_name)912 contactgroupsmember *add_contactgroup_to_host(host *hst, char *group_name) {
913 	return add_contactgroup_to_object(&hst->contact_groups, group_name);
914 	}
915 
916 
917 
918 /* adds a contact to a host */
add_contact_to_host(host * hst,char * contact_name)919 contactsmember *add_contact_to_host(host *hst, char *contact_name) {
920 
921 	return add_contact_to_object(&hst->contacts, contact_name);
922 	}
923 
924 
925 
926 /* adds a custom variable to a host */
add_custom_variable_to_host(host * hst,char * varname,char * varvalue)927 customvariablesmember *add_custom_variable_to_host(host *hst, char *varname, char *varvalue) {
928 
929 	return add_custom_variable_to_object(&hst->custom_variables, varname, varvalue);
930 	}
931 
932 
933 
934 /* add a new host group to the list in memory */
add_hostgroup(char * name,char * alias,char * notes,char * notes_url,char * action_url)935 hostgroup *add_hostgroup(char *name, char *alias, char *notes, char *notes_url, char *action_url) {
936 	hostgroup *new_hostgroup = NULL;
937 	int result = OK;
938 
939 	/* make sure we have the data we need */
940 	if(name == NULL || !strcmp(name, "")) {
941 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroup name is NULL\n");
942 		return NULL;
943 		}
944 
945 	new_hostgroup = calloc(1, sizeof(*new_hostgroup));
946 
947 	/* assign vars */
948 	new_hostgroup->group_name = name;
949 	new_hostgroup->alias = alias ? alias : name;
950 	new_hostgroup->notes = notes;
951 	new_hostgroup->notes_url = notes_url;
952 	new_hostgroup->action_url = action_url;
953 
954 	/* add new host group to hash table */
955 	if(result == OK) {
956 		result = dkhash_insert(object_hash_tables[HOSTGROUP_SKIPLIST], new_hostgroup->group_name, NULL, new_hostgroup);
957 		switch(result) {
958 			case DKHASH_EDUPE:
959 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroup '%s' has already been defined\n", name);
960 				result = ERROR;
961 				break;
962 			case DKHASH_OK:
963 				result = OK;
964 				break;
965 			default:
966 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add hostgroup '%s' to hash table\n", name);
967 				result = ERROR;
968 				break;
969 			}
970 		}
971 
972 	/* handle errors */
973 	if(result == ERROR) {
974 		free(new_hostgroup);
975 		return NULL;
976 		}
977 
978 	new_hostgroup->id = num_objects.hostgroups++;
979 	hostgroup_ary[new_hostgroup->id] = new_hostgroup;
980 	if(new_hostgroup->id)
981 		hostgroup_ary[new_hostgroup->id - 1]->next = new_hostgroup;
982 	return new_hostgroup;
983 	}
984 
985 
986 /* add a new host to a host group */
add_host_to_hostgroup(hostgroup * temp_hostgroup,char * host_name)987 hostsmember *add_host_to_hostgroup(hostgroup *temp_hostgroup, char *host_name) {
988 	hostsmember *new_member = NULL;
989 	hostsmember *last_member = NULL;
990 	hostsmember *temp_member = NULL;
991 	struct host *h;
992 
993 	/* make sure we have the data we need */
994 	if(temp_hostgroup == NULL || (host_name == NULL || !strcmp(host_name, ""))) {
995 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroup or group member is NULL\n");
996 		return NULL;
997 		}
998 	if (!(h = find_host(host_name))) {
999 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate host '%s' for hostgroup '%s'\n", host_name, temp_hostgroup->group_name);
1000 		return NULL;
1001 	}
1002 
1003 	/* allocate memory for a new member */
1004 	if((new_member = calloc(1, sizeof(hostsmember))) == NULL)
1005 		return NULL;
1006 
1007 	/* assign vars */
1008 	new_member->host_name = h->name;
1009 	new_member->host_ptr = h;
1010 
1011 	/* add (unsorted) link from the host to its group */
1012 	prepend_object_to_objectlist(&h->hostgroups_ptr, (void *)temp_hostgroup);
1013 
1014 	/* add the new member to the member list, sorted by host name */
1015 #ifndef NSCGI
1016 	if(use_large_installation_tweaks == TRUE) {
1017 		new_member->next = temp_hostgroup->members;
1018 		temp_hostgroup->members = new_member;
1019 		return new_member;
1020 		}
1021 #endif
1022 	last_member = temp_hostgroup->members;
1023 	for(temp_member = temp_hostgroup->members; temp_member != NULL; temp_member = temp_member->next) {
1024 		if(strcmp(new_member->host_name, temp_member->host_name) < 0) {
1025 			new_member->next = temp_member;
1026 			if(temp_member == temp_hostgroup->members)
1027 				temp_hostgroup->members = new_member;
1028 			else
1029 				last_member->next = new_member;
1030 			break;
1031 			}
1032 		else
1033 			last_member = temp_member;
1034 		}
1035 	if(temp_hostgroup->members == NULL) {
1036 		new_member->next = NULL;
1037 		temp_hostgroup->members = new_member;
1038 		}
1039 	else if(temp_member == NULL) {
1040 		new_member->next = NULL;
1041 		last_member->next = new_member;
1042 		}
1043 
1044 	return new_member;
1045 	}
1046 
1047 
1048 /* add a new service group to the list in memory */
add_servicegroup(char * name,char * alias,char * notes,char * notes_url,char * action_url)1049 servicegroup *add_servicegroup(char *name, char *alias, char *notes, char *notes_url, char *action_url) {
1050 	servicegroup *new_servicegroup = NULL;
1051 	int result = OK;
1052 
1053 	/* make sure we have the data we need */
1054 	if(name == NULL || !strcmp(name, "")) {
1055 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup name is NULL\n");
1056 		return NULL;
1057 		}
1058 
1059 	new_servicegroup = calloc(1, sizeof(*new_servicegroup));
1060 
1061 	/* duplicate vars */
1062 	new_servicegroup->group_name = name;
1063 	new_servicegroup->alias = alias ? alias : name;
1064 	new_servicegroup->notes = notes;
1065 	new_servicegroup->notes_url = notes_url;
1066 	new_servicegroup->action_url = action_url;
1067 
1068 	/* add new service group to hash table */
1069 	if(result == OK) {
1070 		result = dkhash_insert(object_hash_tables[SERVICEGROUP_SKIPLIST], new_servicegroup->group_name, NULL, new_servicegroup);
1071 		switch(result) {
1072 			case DKHASH_EDUPE:
1073 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup '%s' has already been defined\n", name);
1074 				result = ERROR;
1075 				break;
1076 			case DKHASH_OK:
1077 				result = OK;
1078 				break;
1079 			default:
1080 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add servicegroup '%s' to hash table\n", name);
1081 				result = ERROR;
1082 				break;
1083 			}
1084 		}
1085 
1086 	/* handle errors */
1087 	if(result == ERROR) {
1088 		my_free(new_servicegroup);
1089 		return NULL;
1090 		}
1091 
1092 	new_servicegroup->id = num_objects.servicegroups++;
1093 	servicegroup_ary[new_servicegroup->id] = new_servicegroup;
1094 	if(new_servicegroup->id)
1095 		servicegroup_ary[new_servicegroup->id - 1]->next = new_servicegroup;
1096 	return new_servicegroup;
1097 	}
1098 
1099 
1100 /* add a new service to a service group */
add_service_to_servicegroup(servicegroup * temp_servicegroup,char * host_name,char * svc_description)1101 servicesmember *add_service_to_servicegroup(servicegroup *temp_servicegroup, char *host_name, char *svc_description) {
1102 	servicesmember *new_member = NULL;
1103 	servicesmember *last_member = NULL;
1104 	servicesmember *temp_member = NULL;
1105 	struct service *svc;
1106 
1107 	/* make sure we have the data we need */
1108 	if(temp_servicegroup == NULL || (host_name == NULL || !strcmp(host_name, "")) || (svc_description == NULL || !strcmp(svc_description, ""))) {
1109 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup or group member is NULL\n");
1110 		return NULL;
1111 		}
1112 	if (!(svc = find_service(host_name, svc_description))) {
1113 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate service '%s' on host '%s' for servicegroup '%s'\n", svc_description, host_name, temp_servicegroup->group_name);
1114 		return NULL;
1115 		}
1116 
1117 	/* allocate memory for a new member */
1118 	if((new_member = calloc(1, sizeof(servicesmember))) == NULL)
1119 		return NULL;
1120 
1121 	/* assign vars */
1122 	new_member->host_name = svc->host_name;
1123 	new_member->service_description = svc->description;
1124 	new_member->service_ptr = svc;
1125 
1126 	/* add (unsorted) link from the service to its groups */
1127 	prepend_object_to_objectlist(&svc->servicegroups_ptr, temp_servicegroup);
1128 
1129 	/*
1130 	 * add new member to member list, sorted by host name then
1131 	 * service description, unless we're a large installation, in
1132 	 * which case insertion-sorting will take far too long
1133 	 */
1134 #ifndef NSCGI
1135 	if(use_large_installation_tweaks == TRUE) {
1136 		new_member->next = temp_servicegroup->members;
1137 		temp_servicegroup->members = new_member;
1138 		return new_member;
1139 		}
1140 #endif
1141 	last_member = temp_servicegroup->members;
1142 	for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
1143 
1144 		if(strcmp(new_member->host_name, temp_member->host_name) < 0) {
1145 			new_member->next = temp_member;
1146 			if(temp_member == temp_servicegroup->members)
1147 				temp_servicegroup->members = new_member;
1148 			else
1149 				last_member->next = new_member;
1150 			break;
1151 			}
1152 
1153 		else if(strcmp(new_member->host_name, temp_member->host_name) == 0 && strcmp(new_member->service_description, temp_member->service_description) < 0) {
1154 			new_member->next = temp_member;
1155 			if(temp_member == temp_servicegroup->members)
1156 				temp_servicegroup->members = new_member;
1157 			else
1158 				last_member->next = new_member;
1159 			break;
1160 			}
1161 
1162 		else
1163 			last_member = temp_member;
1164 		}
1165 	if(temp_servicegroup->members == NULL) {
1166 		new_member->next = NULL;
1167 		temp_servicegroup->members = new_member;
1168 		}
1169 	else if(temp_member == NULL) {
1170 		new_member->next = NULL;
1171 		last_member->next = new_member;
1172 		}
1173 
1174 	return new_member;
1175 	}
1176 
1177 
1178 /* add a new contact to the list in memory */
add_contact(char * name,char * alias,char * email,char * pager,char ** addresses,char * svc_notification_period,char * host_notification_period,int service_notification_options,int host_notification_options,int host_notifications_enabled,int service_notifications_enabled,int can_submit_commands,int retain_status_information,int retain_nonstatus_information,unsigned int minimum_value)1179 contact *add_contact(char *name, char *alias, char *email, char *pager, char **addresses, char *svc_notification_period, char *host_notification_period, int service_notification_options, int host_notification_options, int host_notifications_enabled, int service_notifications_enabled, int can_submit_commands, int retain_status_information, int retain_nonstatus_information, unsigned int minimum_value) {
1180 	contact *new_contact = NULL;
1181 	timeperiod *htp = NULL, *stp = NULL;
1182 	int x = 0;
1183 	int result = OK;
1184 
1185 	/* make sure we have the data we need */
1186 	if(name == NULL || !*name) {
1187 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n");
1188 		return NULL;
1189 		}
1190 	if(svc_notification_period && !(stp = find_timeperiod(svc_notification_period))) {
1191 		logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification period '%s' specified for contact '%s' is not defined anywhere!\n",
1192 			  svc_notification_period, name);
1193 		return NULL;
1194 		}
1195 	if(host_notification_period && !(htp = find_timeperiod(host_notification_period))) {
1196 		logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification period '%s' specified for contact '%s' is not defined anywhere!\n",
1197 			  host_notification_period, name);
1198 		return NULL;
1199 		}
1200 
1201 
1202 	new_contact = calloc(1, sizeof(*new_contact));
1203 	if(!new_contact)
1204 		return NULL;
1205 
1206 
1207 	new_contact->host_notification_period = htp ? (char *)strdup(htp->name) : NULL;
1208 	new_contact->service_notification_period = stp ? (char *)strdup(stp->name) : NULL;
1209 	new_contact->host_notification_period_ptr = htp;
1210 	new_contact->service_notification_period_ptr = stp;
1211 	new_contact->name = name;
1212 	new_contact->alias = alias ? alias : name;
1213 	new_contact->email = email;
1214 	new_contact->pager = pager;
1215 	if(addresses) {
1216 		for(x = 0; x < MAX_CONTACT_ADDRESSES; x++)
1217 			new_contact->address[x] = addresses[x];
1218 		}
1219 
1220 	new_contact->minimum_value = minimum_value;
1221 	new_contact->service_notification_options = service_notification_options;
1222 	new_contact->host_notification_options = host_notification_options;
1223 	new_contact->host_notifications_enabled = (host_notifications_enabled > 0) ? TRUE : FALSE;
1224 	new_contact->service_notifications_enabled = (service_notifications_enabled > 0) ? TRUE : FALSE;
1225 	new_contact->can_submit_commands = (can_submit_commands > 0) ? TRUE : FALSE;
1226 	new_contact->retain_status_information = (retain_status_information > 0) ? TRUE : FALSE;
1227 	new_contact->retain_nonstatus_information = (retain_nonstatus_information > 0) ? TRUE : FALSE;
1228 
1229 	/* add new contact to hash table */
1230 	if(result == OK) {
1231 		result = dkhash_insert(object_hash_tables[CONTACT_SKIPLIST], new_contact->name, NULL, new_contact);
1232 		switch(result) {
1233 			case DKHASH_EDUPE:
1234 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact '%s' has already been defined\n", name);
1235 				result = ERROR;
1236 				break;
1237 			case DKHASH_OK:
1238 				result = OK;
1239 				break;
1240 			default:
1241 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contact '%s' to hash table\n", name);
1242 				result = ERROR;
1243 				break;
1244 			}
1245 		}
1246 
1247 	/* handle errors */
1248 	if(result == ERROR) {
1249 		free(new_contact);
1250 		return NULL;
1251 		}
1252 
1253 	new_contact->id = num_objects.contacts++;
1254 	contact_ary[new_contact->id] = new_contact;
1255 	if(new_contact->id)
1256 		contact_ary[new_contact->id - 1]->next = new_contact;
1257 	return new_contact;
1258 	}
1259 
1260 
1261 
1262 /* adds a host notification command to a contact definition */
add_host_notification_command_to_contact(contact * cntct,char * command_name)1263 commandsmember *add_host_notification_command_to_contact(contact *cntct, char *command_name) {
1264 	commandsmember *new_commandsmember = NULL;
1265 	int result = OK;
1266 
1267 	/* make sure we have the data we need */
1268 	if(cntct == NULL || (command_name == NULL || !strcmp(command_name, ""))) {
1269 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact or host notification command is NULL\n");
1270 		return NULL;
1271 		}
1272 
1273 	/* allocate memory */
1274 	if((new_commandsmember = calloc(1, sizeof(commandsmember))) == NULL)
1275 		return NULL;
1276 
1277 	/* duplicate vars */
1278 	if((new_commandsmember->command = (char *)strdup(command_name)) == NULL)
1279 		result = ERROR;
1280 
1281 	/* handle errors */
1282 	if(result == ERROR) {
1283 		my_free(new_commandsmember->command);
1284 		my_free(new_commandsmember);
1285 		return NULL;
1286 		}
1287 
1288 	/* add the notification command */
1289 	new_commandsmember->next = cntct->host_notification_commands;
1290 	cntct->host_notification_commands = new_commandsmember;
1291 
1292 	return new_commandsmember;
1293 	}
1294 
1295 
1296 
1297 /* adds a service notification command to a contact definition */
add_service_notification_command_to_contact(contact * cntct,char * command_name)1298 commandsmember *add_service_notification_command_to_contact(contact *cntct, char *command_name) {
1299 	commandsmember *new_commandsmember = NULL;
1300 	int result = OK;
1301 
1302 	/* make sure we have the data we need */
1303 	if(cntct == NULL || (command_name == NULL || !strcmp(command_name, ""))) {
1304 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact or service notification command is NULL\n");
1305 		return NULL;
1306 		}
1307 
1308 	/* allocate memory */
1309 	if((new_commandsmember = calloc(1, sizeof(commandsmember))) == NULL)
1310 		return NULL;
1311 
1312 	/* duplicate vars */
1313 	if((new_commandsmember->command = (char *)strdup(command_name)) == NULL)
1314 		result = ERROR;
1315 
1316 	/* handle errors */
1317 	if(result == ERROR) {
1318 		my_free(new_commandsmember->command);
1319 		my_free(new_commandsmember);
1320 		return NULL;
1321 		}
1322 
1323 	/* add the notification command */
1324 	new_commandsmember->next = cntct->service_notification_commands;
1325 	cntct->service_notification_commands = new_commandsmember;
1326 
1327 	return new_commandsmember;
1328 	}
1329 
1330 
1331 
1332 /* adds a custom variable to a contact */
add_custom_variable_to_contact(contact * cntct,char * varname,char * varvalue)1333 customvariablesmember *add_custom_variable_to_contact(contact *cntct, char *varname, char *varvalue) {
1334 
1335 	return add_custom_variable_to_object(&cntct->custom_variables, varname, varvalue);
1336 	}
1337 
1338 
1339 
1340 /* add a new contact group to the list in memory */
add_contactgroup(char * name,char * alias)1341 contactgroup *add_contactgroup(char *name, char *alias) {
1342 	contactgroup *new_contactgroup = NULL;
1343 	int result = OK;
1344 
1345 	/* make sure we have the data we need */
1346 	if(name == NULL || !strcmp(name, "")) {
1347 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup name is NULL\n");
1348 		return NULL;
1349 		}
1350 
1351 	new_contactgroup = calloc(1, sizeof(*new_contactgroup));
1352 	if(!new_contactgroup)
1353 		return NULL;
1354 
1355 	/* assign vars */
1356 	new_contactgroup->group_name = name;
1357 	new_contactgroup->alias = alias ? alias : name;
1358 
1359 	/* add new contact group to hash table */
1360 	if(result == OK) {
1361 		result = dkhash_insert(object_hash_tables[CONTACTGROUP_SKIPLIST], new_contactgroup->group_name, NULL, new_contactgroup);
1362 		switch(result) {
1363 			case DKHASH_EDUPE:
1364 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup '%s' has already been defined\n", name);
1365 				result = ERROR;
1366 				break;
1367 			case DKHASH_OK:
1368 				result = OK;
1369 				break;
1370 			default:
1371 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contactgroup '%s' to hash table\n", name);
1372 				result = ERROR;
1373 				break;
1374 			}
1375 		}
1376 
1377 	/* handle errors */
1378 	if(result == ERROR) {
1379 		free(new_contactgroup);
1380 		return NULL;
1381 		}
1382 
1383 	new_contactgroup->id = num_objects.contactgroups++;
1384 	contactgroup_ary[new_contactgroup->id] = new_contactgroup;
1385 	if(new_contactgroup->id)
1386 		contactgroup_ary[new_contactgroup->id - 1]->next = new_contactgroup;
1387 	return new_contactgroup;
1388 	}
1389 
1390 
1391 
1392 /* add a new member to a contact group */
add_contact_to_contactgroup(contactgroup * grp,char * contact_name)1393 contactsmember *add_contact_to_contactgroup(contactgroup *grp, char *contact_name) {
1394 	contactsmember *new_contactsmember = NULL;
1395 	struct contact *c;
1396 
1397 	/* make sure we have the data we need */
1398 	if(grp == NULL || (contact_name == NULL || !strcmp(contact_name, ""))) {
1399 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup or contact name is NULL\n");
1400 		return NULL;
1401 		}
1402 
1403 	if (!(c = find_contact(contact_name))) {
1404 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate contact '%s' for contactgroup '%s'\n", contact_name, grp->group_name);
1405 		return NULL;
1406 		}
1407 
1408 	/* allocate memory for a new member */
1409 	if((new_contactsmember = calloc(1, sizeof(contactsmember))) == NULL)
1410 		return NULL;
1411 
1412 	/* assign vars */
1413 	new_contactsmember->contact_name = c->name;
1414 	new_contactsmember->contact_ptr = c;
1415 
1416 	/* add the new member to the head of the member list */
1417 	new_contactsmember->next = grp->members;
1418 	grp->members = new_contactsmember;
1419 
1420 	prepend_object_to_objectlist(&c->contactgroups_ptr, (void *)grp);
1421 
1422 	return new_contactsmember;
1423 	}
1424 
1425 
1426 
1427 /* add a new service to the list in memory */
add_service(char * host_name,char * description,char * display_name,char * check_period,int initial_state,int max_attempts,int parallelize,int accept_passive_checks,double check_interval,double retry_interval,double notification_interval,double first_notification_delay,char * notification_period,int notification_options,int notifications_enabled,int is_volatile,char * event_handler,int event_handler_enabled,char * check_command,int checks_enabled,int flap_detection_enabled,double low_flap_threshold,double high_flap_threshold,int flap_detection_options,int stalking_options,int process_perfdata,int check_freshness,int freshness_threshold,char * notes,char * notes_url,char * action_url,char * icon_image,char * icon_image_alt,int retain_status_information,int retain_nonstatus_information,int obsess,unsigned int hourly_value)1428 service *add_service(char *host_name, char *description, char *display_name, char *check_period, int initial_state, int max_attempts, int parallelize, int accept_passive_checks, double check_interval, double retry_interval, double notification_interval, double first_notification_delay, char *notification_period, int notification_options, int notifications_enabled, int is_volatile, char *event_handler, int event_handler_enabled, char *check_command, int checks_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_options, int stalking_options, int process_perfdata, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, int retain_status_information, int retain_nonstatus_information, int obsess, unsigned int hourly_value) {
1429 	host *h;
1430 	timeperiod *cp = NULL, *np = NULL;
1431 	service *new_service = NULL;
1432 	int result = OK;
1433 
1434 	/* make sure we have everything we need */
1435 	if(host_name == NULL || description == NULL || !*description || check_command == NULL || !*check_command) {
1436 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service description, host name, or check command is NULL\n");
1437 		return NULL;
1438 		}
1439 	if (!(h = find_host(host_name))) {
1440 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to locate host '%s' for service '%s'\n",
1441 			  host_name, description);
1442 		return NULL;
1443 		}
1444 	if(notification_period && !(np = find_timeperiod(notification_period))) {
1445 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: notification_period '%s' for service '%s' on host '%s' could not be found!\n",
1446 			  notification_period, description, host_name);
1447 		return NULL;
1448 		}
1449 	if(check_period && !(cp = find_timeperiod(check_period))) {
1450 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: check_period '%s' for service '%s' on host '%s' not found!\n",
1451 			  check_period, description, host_name);
1452 		return NULL;
1453 		}
1454 
1455 	/* check values */
1456 	if(max_attempts <= 0 || check_interval < 0 || retry_interval <= 0 || notification_interval < 0) {
1457 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid max_attempts, check_interval, retry_interval, or notification_interval value for service '%s' on host '%s'\n", description, host_name);
1458 		return NULL;
1459 		}
1460 
1461 	if(first_notification_delay < 0) {
1462 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid first_notification_delay value for service '%s' on host '%s'\n", description, host_name);
1463 		return NULL;
1464 		}
1465 
1466 	/* allocate memory */
1467 	new_service = calloc(1, sizeof(*new_service));
1468 	if(!new_service)
1469 		return NULL;
1470 
1471 	/* duplicate vars, but assign what we can */
1472 	new_service->notification_period_ptr = np;
1473 	new_service->check_period_ptr = cp;
1474 	new_service->host_ptr = h;
1475 	new_service->check_period = cp ? (char *)strdup(cp->name) : NULL;
1476 	new_service->notification_period = np ? (char *)strdup(np->name) : NULL;
1477 	new_service->host_name = h->name;
1478 	if((new_service->description = (char *)strdup(description)) == NULL)
1479 		result = ERROR;
1480 	if(display_name) {
1481 		if((new_service->display_name = (char *)strdup(display_name)) == NULL)
1482 			result = ERROR;
1483 		}
1484 	else {
1485 		new_service->display_name = new_service->description;
1486 		}
1487 	if((new_service->check_command = (char *)strdup(check_command)) == NULL)
1488 		result = ERROR;
1489 	if(event_handler) {
1490 		if((new_service->event_handler = (char *)strdup(event_handler)) == NULL)
1491 			result = ERROR;
1492 		}
1493 	if(notes) {
1494 		if((new_service->notes = (char *)strdup(notes)) == NULL)
1495 			result = ERROR;
1496 		}
1497 	if(notes_url) {
1498 		if((new_service->notes_url = (char *)strdup(notes_url)) == NULL)
1499 			result = ERROR;
1500 		}
1501 	if(action_url) {
1502 		if((new_service->action_url = (char *)strdup(action_url)) == NULL)
1503 			result = ERROR;
1504 		}
1505 	if(icon_image) {
1506 		if((new_service->icon_image = (char *)strdup(icon_image)) == NULL)
1507 			result = ERROR;
1508 		}
1509 	if(icon_image_alt) {
1510 		if((new_service->icon_image_alt = (char *)strdup(icon_image_alt)) == NULL)
1511 			result = ERROR;
1512 		}
1513 
1514 	new_service->hourly_value = hourly_value;
1515 	new_service->check_interval = check_interval;
1516 	new_service->retry_interval = retry_interval;
1517 	new_service->max_attempts = max_attempts;
1518 	new_service->parallelize = (parallelize > 0) ? TRUE : FALSE;
1519 	new_service->notification_interval = notification_interval;
1520 	new_service->first_notification_delay = first_notification_delay;
1521 	new_service->notification_options = notification_options;
1522 	new_service->is_volatile = (is_volatile > 0) ? TRUE : FALSE;
1523 	new_service->flap_detection_enabled = (flap_detection_enabled > 0) ? TRUE : FALSE;
1524 	new_service->low_flap_threshold = low_flap_threshold;
1525 	new_service->high_flap_threshold = high_flap_threshold;
1526 	new_service->flap_detection_options = flap_detection_options;
1527 	new_service->stalking_options = stalking_options;
1528 	new_service->process_performance_data = (process_perfdata > 0) ? TRUE : FALSE;
1529 	new_service->check_freshness = (check_freshness > 0) ? TRUE : FALSE;
1530 	new_service->freshness_threshold = freshness_threshold;
1531 	new_service->accept_passive_checks = (accept_passive_checks > 0) ? TRUE : FALSE;
1532 	new_service->event_handler_enabled = (event_handler_enabled > 0) ? TRUE : FALSE;
1533 	new_service->checks_enabled = (checks_enabled > 0) ? TRUE : FALSE;
1534 	new_service->retain_status_information = (retain_status_information > 0) ? TRUE : FALSE;
1535 	new_service->retain_nonstatus_information = (retain_nonstatus_information > 0) ? TRUE : FALSE;
1536 	new_service->notifications_enabled = (notifications_enabled > 0) ? TRUE : FALSE;
1537 	new_service->obsess = (obsess > 0) ? TRUE : FALSE;
1538 #ifdef NSCORE
1539 	new_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
1540 	new_service->check_type = CHECK_TYPE_ACTIVE;
1541 	new_service->current_attempt = (initial_state == STATE_OK) ? 1 : max_attempts;
1542 	new_service->current_state = initial_state;
1543 	new_service->last_state = initial_state;
1544 	new_service->last_hard_state = initial_state;
1545 	new_service->state_type = HARD_STATE;
1546 	new_service->should_be_scheduled = TRUE;
1547 	new_service->check_options = CHECK_OPTION_NONE;
1548 #endif
1549 
1550 	/* add new service to hash table */
1551 	if(result == OK) {
1552 		result = dkhash_insert(object_hash_tables[SERVICE_SKIPLIST], new_service->host_name, new_service->description, new_service);
1553 		switch(result) {
1554 			case DKHASH_EDUPE:
1555 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service '%s' on host '%s' has already been defined\n", description, host_name);
1556 				result = ERROR;
1557 				break;
1558 			case DKHASH_OK:
1559 				result = OK;
1560 				break;
1561 			default:
1562 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add service '%s' on host '%s' to hash table\n", description, host_name);
1563 				result = ERROR;
1564 				break;
1565 			}
1566 		}
1567 
1568 	/* handle errors */
1569 	if(result == ERROR) {
1570 #ifdef NSCORE
1571 		my_free(new_service->perf_data);
1572 		my_free(new_service->plugin_output);
1573 		my_free(new_service->long_plugin_output);
1574 #endif
1575 		my_free(new_service->event_handler);
1576 		my_free(new_service->check_command);
1577 		my_free(new_service->description);
1578 		if(display_name)
1579 			my_free(new_service->display_name);
1580 		return NULL;
1581 		}
1582 
1583 	add_service_link_to_host(h, new_service);
1584 
1585 	new_service->id = num_objects.services++;
1586 	service_ary[new_service->id] = new_service;
1587 	if(new_service->id)
1588 		service_ary[new_service->id - 1]->next = new_service;
1589 	return new_service;
1590 	}
1591 
1592 
1593 
1594 /* adds a contact group to a service */
add_contactgroup_to_service(service * svc,char * group_name)1595 contactgroupsmember *add_contactgroup_to_service(service *svc, char *group_name) {
1596 	return add_contactgroup_to_object(&svc->contact_groups, group_name);
1597 	}
1598 
1599 
1600 
1601 /* adds a contact to a service */
add_contact_to_service(service * svc,char * contact_name)1602 contactsmember *add_contact_to_service(service *svc, char *contact_name) {
1603 
1604 	return add_contact_to_object(&svc->contacts, contact_name);
1605 	}
1606 
1607 
1608 
1609 /* adds a custom variable to a service */
add_custom_variable_to_service(service * svc,char * varname,char * varvalue)1610 customvariablesmember *add_custom_variable_to_service(service *svc, char *varname, char *varvalue) {
1611 
1612 	return add_custom_variable_to_object(&svc->custom_variables, varname, varvalue);
1613 	}
1614 
1615 
1616 
1617 /* add a new command to the list in memory */
add_command(char * name,char * value)1618 command *add_command(char *name, char *value) {
1619 	command *new_command = NULL;
1620 	int result = OK;
1621 
1622 	/* make sure we have the data we need */
1623 	if((name == NULL || !strcmp(name, "")) || (value == NULL || !strcmp(value, ""))) {
1624 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Command name of command line is NULL\n");
1625 		return NULL;
1626 		}
1627 
1628 	/* allocate memory for the new command */
1629 	new_command = calloc(1, sizeof(*new_command));
1630 	if(!new_command)
1631 		return NULL;
1632 
1633 	/* assign vars */
1634 	new_command->name = name;
1635 	new_command->command_line = value;
1636 
1637 	/* add new command to hash table */
1638 	if(result == OK) {
1639 		result = dkhash_insert(object_hash_tables[COMMAND_SKIPLIST], new_command->name, NULL, new_command);
1640 		switch(result) {
1641 			case DKHASH_EDUPE:
1642 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Command '%s' has already been defined\n", name);
1643 				result = ERROR;
1644 				break;
1645 			case DKHASH_OK:
1646 				result = OK;
1647 				break;
1648 			default:
1649 				logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add command '%s' to hash table\n", name);
1650 				result = ERROR;
1651 				break;
1652 			}
1653 		}
1654 
1655 	/* handle errors */
1656 	if(result == ERROR) {
1657 		my_free(new_command);
1658 		return NULL;
1659 		}
1660 
1661 	new_command->id = num_objects.commands++;
1662 	command_ary[new_command->id] = new_command;
1663 	if(new_command->id)
1664 		command_ary[new_command->id - 1]->next = new_command;
1665 	return new_command;
1666 	}
1667 
1668 
1669 
1670 /* add a new service escalation to the list in memory */
add_serviceescalation(char * host_name,char * description,int first_notification,int last_notification,double notification_interval,char * escalation_period,int escalation_options)1671 serviceescalation *add_serviceescalation(char *host_name, char *description, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalation_options) {
1672 	serviceescalation *new_serviceescalation = NULL;
1673 	service *svc;
1674 	timeperiod *tp = NULL;
1675 
1676 	/* make sure we have the data we need */
1677 	if(host_name == NULL || !*host_name || description == NULL || !*description) {
1678 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service escalation host name or description is NULL\n");
1679 		return NULL;
1680 		}
1681 	if(!(svc = find_service(host_name, description))) {
1682 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service '%s' on host '%s' has an escalation but is not defined anywhere!\n",
1683 			  host_name, description);
1684 		return NULL;
1685 		}
1686 	if (escalation_period && !(tp = find_timeperiod(escalation_period))) {
1687 		logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!\n",
1688 			  escalation_period, description, host_name);
1689 		return NULL ;
1690 		}
1691 
1692 	new_serviceescalation = calloc(1, sizeof(*new_serviceescalation));
1693 	if(!new_serviceescalation)
1694 		return NULL;
1695 
1696 	if(add_object_to_objectlist(&svc->escalation_list, new_serviceescalation) != OK) {
1697 		logit(NSLOG_CONFIG_ERROR, TRUE, "Could not add escalation to service '%s' on host '%s'\n",
1698 			  svc->host_name, svc->description);
1699 		return NULL;
1700 		}
1701 
1702 	/* assign vars. object names are immutable, so no need to copy */
1703 	new_serviceescalation->host_name = svc->host_name;
1704 	new_serviceescalation->description = svc->description;
1705 	new_serviceescalation->service_ptr = svc;
1706 	new_serviceescalation->escalation_period_ptr = tp;
1707 	if(tp)
1708 		new_serviceescalation->escalation_period = (char *)strdup(tp->name);
1709 
1710 	new_serviceescalation->first_notification = first_notification;
1711 	new_serviceescalation->last_notification = last_notification;
1712 	new_serviceescalation->notification_interval = (notification_interval <= 0) ? 0 : notification_interval;
1713 	new_serviceescalation->escalation_options = escalation_options;
1714 
1715 	new_serviceescalation->id = num_objects.serviceescalations++;
1716 	serviceescalation_ary[new_serviceescalation->id] = new_serviceescalation;
1717 	return new_serviceescalation;
1718 	}
1719 
1720 
1721 
1722 /* adds a contact group to a service escalation */
add_contactgroup_to_serviceescalation(serviceescalation * se,char * group_name)1723 contactgroupsmember *add_contactgroup_to_serviceescalation(serviceescalation *se, char *group_name) {
1724 	return add_contactgroup_to_object(&se->contact_groups, group_name);
1725 	}
1726 
1727 
1728 
1729 /* adds a contact to a service escalation */
add_contact_to_serviceescalation(serviceescalation * se,char * contact_name)1730 contactsmember *add_contact_to_serviceescalation(serviceescalation *se, char *contact_name) {
1731 
1732 	return add_contact_to_object(&se->contacts, contact_name);
1733 	}
1734 
1735 
1736 
1737 /* adds a service dependency definition */
add_service_dependency(char * dependent_host_name,char * dependent_service_description,char * host_name,char * service_description,int dependency_type,int inherits_parent,int failure_options,char * dependency_period)1738 servicedependency *add_service_dependency(char *dependent_host_name, char *dependent_service_description, char *host_name, char *service_description, int dependency_type, int inherits_parent, int failure_options, char *dependency_period) {
1739 	servicedependency *new_servicedependency = NULL;
1740 	service *parent, *child;
1741 	timeperiod *tp = NULL;
1742 	int result;
1743 
1744 	/* make sure we have what we need */
1745 	parent = find_service(host_name, service_description);
1746 	if(!parent) {
1747 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Master service '%s' on host '%s' is not defined anywhere!\n",
1748 			  service_description, host_name);
1749 		return NULL;
1750 		}
1751 	child = find_service(dependent_host_name, dependent_service_description);
1752 	if(!child) {
1753 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Dependent service '%s' on host '%s' is not defined anywhere!\n",
1754 			 dependent_service_description, dependent_host_name);
1755 		return NULL;
1756 		}
1757 	if (dependency_period && !(tp = find_timeperiod(dependency_period))) {
1758 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate timeperiod '%s' for dependency from service '%s' on host '%s' to service '%s' on host '%s'\n",
1759 			  dependency_period, dependent_service_description, dependent_host_name, service_description, host_name);
1760 		return NULL;
1761 		}
1762 
1763 	/* allocate memory for a new service dependency entry */
1764 	if((new_servicedependency = calloc(1, sizeof(*new_servicedependency))) == NULL)
1765 		return NULL;
1766 
1767 	new_servicedependency->dependent_service_ptr = child;
1768 	new_servicedependency->master_service_ptr = parent;
1769 	new_servicedependency->dependency_period_ptr = tp;
1770 
1771 	/* assign vars. object names are immutable, so no need to copy */
1772 	new_servicedependency->dependent_host_name = child->host_name;
1773 	new_servicedependency->dependent_service_description = child->description;
1774 	new_servicedependency->host_name = parent->host_name;
1775 	new_servicedependency->service_description = parent->description;
1776 	if (tp)
1777 		new_servicedependency->dependency_period = (char *)strdup(tp->name);
1778 
1779 	new_servicedependency->dependency_type = (dependency_type == EXECUTION_DEPENDENCY) ? EXECUTION_DEPENDENCY : NOTIFICATION_DEPENDENCY;
1780 	new_servicedependency->inherits_parent = (inherits_parent > 0) ? TRUE : FALSE;
1781 	new_servicedependency->failure_options = failure_options;
1782 
1783 	/*
1784 	 * add new service dependency to its respective services.
1785 	 * Ordering doesn't matter here as we'll have to check them
1786 	 * all anyway. We avoid adding dupes though, since we can
1787 	 * apparently get zillion's and zillion's of them.
1788 	 */
1789 	if(dependency_type == NOTIFICATION_DEPENDENCY)
1790 		result = prepend_unique_object_to_objectlist(&child->notify_deps, new_servicedependency, sizeof(*new_servicedependency));
1791 	else
1792 		result = prepend_unique_object_to_objectlist(&child->exec_deps, new_servicedependency, sizeof(*new_servicedependency));
1793 
1794 	if(result != OK) {
1795 		free(new_servicedependency);
1796 		/* hack to avoid caller bombing out */
1797 		return result == OBJECTLIST_DUPE ? (void *)1 : NULL;
1798 		}
1799 
1800 	num_objects.servicedependencies++;
1801 	return new_servicedependency;
1802 	}
1803 
1804 
1805 /* adds a host dependency definition */
add_host_dependency(char * dependent_host_name,char * host_name,int dependency_type,int inherits_parent,int failure_options,char * dependency_period)1806 hostdependency *add_host_dependency(char *dependent_host_name, char *host_name, int dependency_type, int inherits_parent, int failure_options, char *dependency_period) {
1807 	hostdependency *new_hostdependency = NULL;
1808 	host *parent, *child;
1809 	timeperiod *tp = NULL;
1810 	int result;
1811 
1812 	/* make sure we have what we need */
1813 	parent = find_host(host_name);
1814 	if (!parent) {
1815 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Master host '%s' in hostdependency from '%s' to '%s' is not defined anywhere!\n",
1816 			  host_name, dependent_host_name, host_name);
1817 		return NULL;
1818 		}
1819 	child = find_host(dependent_host_name);
1820 	if (!child) {
1821 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Dependent host '%s' in hostdependency from '%s' to '%s' is not defined anywhere!\n",
1822 			  dependent_host_name, dependent_host_name, host_name);
1823 		return NULL;
1824 		}
1825 	if (dependency_period && !(tp = find_timeperiod(dependency_period))) {
1826 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to locate dependency_period '%s' for %s->%s host dependency\n",
1827 			  dependency_period, parent->name, child->name);
1828 		return NULL ;
1829 	}
1830 
1831 	if((new_hostdependency = calloc(1, sizeof(*new_hostdependency))) == NULL)
1832 		return NULL;
1833 
1834 	new_hostdependency->dependent_host_ptr = child;
1835 	new_hostdependency->master_host_ptr = parent;
1836 	new_hostdependency->dependency_period_ptr = tp;
1837 
1838 	/* assign vars. Objects are immutable, so no need to copy */
1839 	new_hostdependency->dependent_host_name = child->name;
1840 	new_hostdependency->host_name = parent->name;
1841 	if(tp)
1842 		new_hostdependency->dependency_period = (char *)strdup(tp->name);
1843 
1844 	new_hostdependency->dependency_type = (dependency_type == EXECUTION_DEPENDENCY) ? EXECUTION_DEPENDENCY : NOTIFICATION_DEPENDENCY;
1845 	new_hostdependency->inherits_parent = (inherits_parent > 0) ? TRUE : FALSE;
1846 	new_hostdependency->failure_options = failure_options;
1847 
1848 	if(dependency_type == NOTIFICATION_DEPENDENCY)
1849 		result = prepend_unique_object_to_objectlist(&child->notify_deps, new_hostdependency, sizeof(*new_hostdependency));
1850 	else
1851 		result = prepend_unique_object_to_objectlist(&child->exec_deps, new_hostdependency, sizeof(*new_hostdependency));
1852 
1853 	if(result != OK) {
1854 		free(new_hostdependency);
1855 		/* hack to avoid caller bombing out */
1856 		return result == OBJECTLIST_DUPE ? (void *)1 : NULL;
1857 		}
1858 
1859 	num_objects.hostdependencies++;
1860 	return new_hostdependency;
1861 	}
1862 
1863 
1864 
1865 /* add a new host escalation to the list in memory */
add_hostescalation(char * host_name,int first_notification,int last_notification,double notification_interval,char * escalation_period,int escalation_options)1866 hostescalation *add_hostescalation(char *host_name, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalation_options) {
1867 	hostescalation *new_hostescalation = NULL;
1868 	host *h;
1869 	timeperiod *tp = NULL;
1870 
1871 	/* make sure we have the data we need */
1872 	if(host_name == NULL || !*host_name) {
1873 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host escalation host name is NULL\n");
1874 		return NULL;
1875 		}
1876 	if (!(h = find_host(host_name))) {
1877 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host '%s' has an escalation, but is not defined anywhere!\n", host_name);
1878 		return NULL;
1879 		}
1880 	if (escalation_period && !(tp = find_timeperiod(escalation_period))) {
1881 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to locate timeperiod '%s' for hostescalation '%s'\n",
1882 			  escalation_period, host_name);
1883 		return NULL;
1884 		}
1885 
1886 	new_hostescalation = calloc(1, sizeof(*new_hostescalation));
1887 
1888 	/* add the escalation to its host */
1889 	if (add_object_to_objectlist(&h->escalation_list, new_hostescalation) != OK) {
1890 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add hostescalation to host '%s'\n", host_name);
1891 		free(new_hostescalation);
1892 		return NULL;
1893 		}
1894 
1895 	/* assign vars. Object names are immutable, so no need to copy */
1896 	new_hostescalation->host_name = h->name;
1897 	new_hostescalation->host_ptr = h;
1898 	new_hostescalation->escalation_period = tp ? (char *)strdup(tp->name) : NULL;
1899 	new_hostescalation->escalation_period_ptr = tp;
1900 	new_hostescalation->first_notification = first_notification;
1901 	new_hostescalation->last_notification = last_notification;
1902 	new_hostescalation->notification_interval = (notification_interval <= 0) ? 0 : notification_interval;
1903 	new_hostescalation->escalation_options = escalation_options;
1904 
1905 	new_hostescalation->id = num_objects.hostescalations++;
1906 	hostescalation_ary[new_hostescalation->id] = new_hostescalation;
1907 	return new_hostescalation;
1908 	}
1909 
1910 
1911 
1912 /* adds a contact group to a host escalation */
add_contactgroup_to_hostescalation(hostescalation * he,char * group_name)1913 contactgroupsmember *add_contactgroup_to_hostescalation(hostescalation *he, char *group_name) {
1914 	return add_contactgroup_to_object(&he->contact_groups, group_name);
1915 	}
1916 
1917 
1918 
1919 /* adds a contact to a host escalation */
add_contact_to_hostescalation(hostescalation * he,char * contact_name)1920 contactsmember *add_contact_to_hostescalation(hostescalation *he, char *contact_name) {
1921 
1922 	return add_contact_to_object(&he->contacts, contact_name);
1923 	}
1924 
1925 
1926 
1927 /* adds a contact to an object */
add_contact_to_object(contactsmember ** object_ptr,char * contactname)1928 contactsmember *add_contact_to_object(contactsmember **object_ptr, char *contactname) {
1929 	contactsmember *new_contactsmember = NULL;
1930 	contact *c;
1931 
1932 	/* make sure we have the data we need */
1933 	if(object_ptr == NULL) {
1934 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact object is NULL\n");
1935 		return NULL;
1936 		}
1937 
1938 	if(contactname == NULL || !*contactname) {
1939 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n");
1940 		return NULL;
1941 		}
1942 	if(!(c = find_contact(contactname))) {
1943 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact '%s' is not defined anywhere!\n", contactname);
1944 		return NULL;
1945 		}
1946 
1947 	/* allocate memory for a new member */
1948 	if((new_contactsmember = malloc(sizeof(contactsmember))) == NULL) {
1949 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for contact\n");
1950 		return NULL;
1951 		}
1952 	new_contactsmember->contact_name = c->name;
1953 
1954 	/* set initial values */
1955 	new_contactsmember->contact_ptr = c;
1956 
1957 	/* add the new contact to the head of the contact list */
1958 	new_contactsmember->next = *object_ptr;
1959 	*object_ptr = new_contactsmember;
1960 
1961 	return new_contactsmember;
1962 	}
1963 
1964 
1965 
1966 /* adds a custom variable to an object */
add_custom_variable_to_object(customvariablesmember ** object_ptr,char * varname,char * varvalue)1967 customvariablesmember *add_custom_variable_to_object(customvariablesmember **object_ptr, char *varname, char *varvalue) {
1968 	customvariablesmember *new_customvariablesmember = NULL;
1969 
1970 	/* make sure we have the data we need */
1971 	if(object_ptr == NULL) {
1972 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Custom variable object is NULL\n");
1973 		return NULL;
1974 		}
1975 
1976 	if(varname == NULL || !strcmp(varname, "")) {
1977 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Custom variable name is NULL\n");
1978 		return NULL;
1979 		}
1980 
1981 	/* allocate memory for a new member */
1982 	if((new_customvariablesmember = malloc(sizeof(customvariablesmember))) == NULL) {
1983 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for custom variable\n");
1984 		return NULL;
1985 		}
1986 	if((new_customvariablesmember->variable_name = (char *)strdup(varname)) == NULL) {
1987 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for custom variable name\n");
1988 		my_free(new_customvariablesmember);
1989 		return NULL;
1990 		}
1991 	if(varvalue) {
1992 		if((new_customvariablesmember->variable_value = (char *)strdup(varvalue)) == NULL) {
1993 			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for custom variable value\n");
1994 			my_free(new_customvariablesmember->variable_name);
1995 			my_free(new_customvariablesmember);
1996 			return NULL;
1997 			}
1998 		}
1999 	else
2000 		new_customvariablesmember->variable_value = NULL;
2001 
2002 	/* set initial values */
2003 	new_customvariablesmember->has_been_modified = FALSE;
2004 
2005 	/* add the new member to the head of the member list */
2006 	new_customvariablesmember->next = *object_ptr;
2007 	*object_ptr = new_customvariablesmember;
2008 
2009 	return new_customvariablesmember;
2010 	}
2011 
2012 
2013 
2014 
2015 /******************************************************************/
2016 /******************** OBJECT SEARCH FUNCTIONS *********************/
2017 /******************************************************************/
2018 
find_timeperiod(const char * name)2019 timeperiod *find_timeperiod(const char *name) {
2020 	return dkhash_get(object_hash_tables[TIMEPERIOD_SKIPLIST], name, NULL);
2021 	}
2022 
find_host(const char * name)2023 host *find_host(const char *name) {
2024 	return dkhash_get(object_hash_tables[HOST_SKIPLIST], name, NULL);
2025 	}
2026 
find_hostgroup(const char * name)2027 hostgroup *find_hostgroup(const char *name) {
2028 	return dkhash_get(object_hash_tables[HOSTGROUP_SKIPLIST], name, NULL);
2029 	}
2030 
find_servicegroup(const char * name)2031 servicegroup *find_servicegroup(const char *name) {
2032 	return dkhash_get(object_hash_tables[SERVICEGROUP_SKIPLIST], name, NULL);
2033 	}
2034 
find_contact(const char * name)2035 contact *find_contact(const char *name) {
2036 	return dkhash_get(object_hash_tables[CONTACT_SKIPLIST], name, NULL);
2037 	}
2038 
find_contactgroup(const char * name)2039 contactgroup *find_contactgroup(const char *name) {
2040 	return dkhash_get(object_hash_tables[CONTACTGROUP_SKIPLIST], name, NULL);
2041 	}
2042 
find_command(const char * name)2043 command *find_command(const char *name) {
2044 	return dkhash_get(object_hash_tables[COMMAND_SKIPLIST], name, NULL);
2045 	}
2046 
find_service(const char * host_name,const char * svc_desc)2047 service *find_service(const char *host_name, const char *svc_desc) {
2048 	return dkhash_get(object_hash_tables[SERVICE_SKIPLIST], host_name, svc_desc);
2049 	}
2050 
2051 
2052 
2053 /* adds a object to a list of objects */
add_object_to_objectlist(objectlist ** list,void * object_ptr)2054 int add_object_to_objectlist(objectlist **list, void *object_ptr) {
2055 	objectlist *temp_item = NULL;
2056 	objectlist *new_item = NULL;
2057 
2058 	if(list == NULL || object_ptr == NULL)
2059 		return ERROR;
2060 
2061 	/* skip this object if its already in the list */
2062 	for(temp_item = *list; temp_item; temp_item = temp_item->next) {
2063 		if(temp_item->object_ptr == object_ptr)
2064 			break;
2065 		}
2066 	if(temp_item)
2067 		return OK;
2068 
2069 	/* allocate memory for a new list item */
2070 	if((new_item = (objectlist *)malloc(sizeof(objectlist))) == NULL)
2071 		return ERROR;
2072 
2073 	/* initialize vars */
2074 	new_item->object_ptr = object_ptr;
2075 
2076 	/* add new item to head of list */
2077 	new_item->next = *list;
2078 	*list = new_item;
2079 
2080 	return OK;
2081 	}
2082 
2083 
2084 /* useful when we don't care if the object is unique or not */
prepend_object_to_objectlist(objectlist ** list,void * object_ptr)2085 int prepend_object_to_objectlist(objectlist **list, void *object_ptr)
2086 {
2087 	objectlist *item;
2088 	if(list == NULL || object_ptr == NULL)
2089 		return ERROR;
2090 	if((item = malloc(sizeof(*item))) == NULL)
2091 		return ERROR;
2092 	item->next = *list;
2093 	item->object_ptr = object_ptr;
2094 	*list = item;
2095 	return OK;
2096 	}
2097 
2098 /* useful for adding dependencies to master objects */
prepend_unique_object_to_objectlist(objectlist ** list,void * object_ptr,size_t size)2099 int prepend_unique_object_to_objectlist(objectlist **list, void *object_ptr, size_t size) {
2100 	objectlist *l;
2101 	if(list == NULL || object_ptr == NULL)
2102 		return ERROR;
2103 	for(l = *list; l; l = l->next) {
2104 		if(!memcmp(l->object_ptr, object_ptr, size))
2105 			return OBJECTLIST_DUPE;
2106 		}
2107 	return prepend_object_to_objectlist(list, object_ptr);
2108 }
2109 
2110 /* frees memory allocated to a temporary object list */
free_objectlist(objectlist ** temp_list)2111 int free_objectlist(objectlist **temp_list) {
2112 	objectlist *this_objectlist = NULL;
2113 	objectlist *next_objectlist = NULL;
2114 
2115 	if(temp_list == NULL)
2116 		return ERROR;
2117 
2118 	/* free memory allocated to object list */
2119 	for(this_objectlist = *temp_list; this_objectlist != NULL; this_objectlist = next_objectlist) {
2120 		next_objectlist = this_objectlist->next;
2121 		my_free(this_objectlist);
2122 		}
2123 
2124 	*temp_list = NULL;
2125 
2126 	return OK;
2127 	}
2128 
2129 
2130 
2131 /******************************************************************/
2132 /********************* OBJECT QUERY FUNCTIONS *********************/
2133 /******************************************************************/
2134 
2135 /* determines whether or not a specific host is an immediate child of another host */
is_host_immediate_child_of_host(host * parent_host,host * child_host)2136 int is_host_immediate_child_of_host(host *parent_host, host *child_host) {
2137 	hostsmember *temp_hostsmember = NULL;
2138 
2139 	/* not enough data */
2140 	if(child_host == NULL)
2141 		return FALSE;
2142 
2143 	/* root/top-level hosts */
2144 	if(parent_host == NULL) {
2145 		if(child_host->parent_hosts == NULL)
2146 			return TRUE;
2147 		}
2148 
2149 	/* mid-level/bottom hosts */
2150 	else {
2151 
2152 		for(temp_hostsmember = child_host->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
2153 			if(temp_hostsmember->host_ptr == parent_host)
2154 				return TRUE;
2155 			}
2156 		}
2157 
2158 	return FALSE;
2159 	}
2160 
2161 
2162 /* determines whether or not a specific host is an immediate parent of another host */
is_host_immediate_parent_of_host(host * child_host,host * parent_host)2163 int is_host_immediate_parent_of_host(host *child_host, host *parent_host) {
2164 
2165 	if(is_host_immediate_child_of_host(parent_host, child_host) == TRUE)
2166 		return TRUE;
2167 
2168 	return FALSE;
2169 	}
2170 
2171 #ifdef NSCGI
hostsmember_elements(hostsmember * list)2172 int hostsmember_elements(hostsmember *list)
2173 {
2174 	int elems = 0;
2175 	for (; list; list = list->next)
2176 		elems++;
2177 	return elems;
2178 }
2179 
2180 /* returns a count of the immediate children for a given host */
2181 /* NOTE: This function is only used by the CGIS */
number_of_immediate_child_hosts(host * hst)2182 int number_of_immediate_child_hosts(host *hst) {
2183 	int children = 0;
2184 	host *temp_host = NULL;
2185 
2186 	if(hst == NULL) {
2187 		for(temp_host = host_list; temp_host != NULL;
2188 				temp_host = temp_host->next) {
2189 			if(is_host_immediate_child_of_host(hst, temp_host) == TRUE)
2190 				children++;
2191 			}
2192 		return children;
2193 		}
2194 	else {
2195 		return hostsmember_elements(hst->child_hosts);
2196 		}
2197 	}
2198 
2199 
2200 /* get the number of immediate parent hosts for a given host */
2201 /* NOTE: This function is only used by the CGIS */
number_of_immediate_parent_hosts(host * hst)2202 int number_of_immediate_parent_hosts(host *hst) {
2203 	int parents = 0;
2204 	host *temp_host = NULL;
2205 
2206 	if(hst == NULL) {
2207 		for(temp_host = host_list; temp_host != NULL;
2208 				temp_host = temp_host->next) {
2209 			if(is_host_immediate_parent_of_host(hst, temp_host) == TRUE) {
2210 				parents++;
2211 				}
2212 			}
2213 		return parents;
2214 		}
2215 	else {
2216 		return hostsmember_elements(hst->parent_hosts);
2217 		}
2218 	}
2219 #endif
2220 
2221 /*  tests whether a host is a member of a particular hostgroup */
2222 /* NOTE: This function is only used by the CGIS */
is_host_member_of_hostgroup(hostgroup * group,host * hst)2223 int is_host_member_of_hostgroup(hostgroup *group, host *hst) {
2224 	hostsmember *temp_hostsmember = NULL;
2225 
2226 	if(group == NULL || hst == NULL)
2227 		return FALSE;
2228 
2229 	for(temp_hostsmember = group->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
2230 		if(temp_hostsmember->host_ptr == hst)
2231 			return TRUE;
2232 		}
2233 
2234 	return FALSE;
2235 	}
2236 
2237 
2238 /*  tests whether a host is a member of a particular servicegroup */
2239 /* NOTE: This function is only used by the CGIS */
is_host_member_of_servicegroup(servicegroup * group,host * hst)2240 int is_host_member_of_servicegroup(servicegroup *group, host *hst) {
2241 	servicesmember *temp_servicesmember = NULL;
2242 
2243 	if(group == NULL || hst == NULL)
2244 		return FALSE;
2245 
2246 	for(temp_servicesmember = group->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
2247 		if(temp_servicesmember->service_ptr != NULL && temp_servicesmember->service_ptr->host_ptr == hst)
2248 			return TRUE;
2249 		}
2250 
2251 	return FALSE;
2252 	}
2253 
2254 
2255 /*  tests whether a service is a member of a particular servicegroup */
2256 /* NOTE: This function is only used by the CGIS */
is_service_member_of_servicegroup(servicegroup * group,service * svc)2257 int is_service_member_of_servicegroup(servicegroup *group, service *svc) {
2258 	servicesmember *temp_servicesmember = NULL;
2259 
2260 	if(group == NULL || svc == NULL)
2261 		return FALSE;
2262 
2263 	for(temp_servicesmember = group->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
2264 		if(temp_servicesmember->service_ptr == svc)
2265 			return TRUE;
2266 		}
2267 
2268 	return FALSE;
2269 	}
2270 
2271 
2272 /*
2273  * tests whether a contact is a member of a particular contactgroup.
2274  * The mk-livestatus eventbroker module uses this, so it must hang
2275  * around until 4.0 to prevent api breakage.
2276  * The cgi's stopped using it quite long ago though, so we need only
2277  * compile it if we're building the core
2278  */
is_contact_member_of_contactgroup(contactgroup * group,contact * cntct)2279 int is_contact_member_of_contactgroup(contactgroup *group, contact *cntct) {
2280 	contactsmember *member;
2281 
2282 	if(!group || !cntct)
2283 		return FALSE;
2284 
2285 	/* search all contacts in this contact group */
2286 	for(member = group->members; member; member = member->next) {
2287 		if (member->contact_ptr == cntct)
2288 			return TRUE;
2289 		}
2290 
2291 	return FALSE;
2292 	}
2293 
2294 /*  tests whether a contact is a contact for a particular host */
is_contact_for_host(host * hst,contact * cntct)2295 int is_contact_for_host(host *hst, contact *cntct) {
2296 	contactsmember *temp_contactsmember = NULL;
2297 	contactgroupsmember *temp_contactgroupsmember = NULL;
2298 	contactgroup *temp_contactgroup = NULL;
2299 
2300 	if(hst == NULL || cntct == NULL) {
2301 		return FALSE;
2302 		}
2303 
2304 	/* search all individual contacts of this host */
2305 	for(temp_contactsmember = hst->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
2306 		if (temp_contactsmember->contact_ptr == cntct)
2307 			return TRUE;
2308 		}
2309 
2310 	/* search all contactgroups of this host */
2311 	for(temp_contactgroupsmember = hst->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
2312 		temp_contactgroup = temp_contactgroupsmember->group_ptr;
2313 		if(is_contact_member_of_contactgroup(temp_contactgroup, cntct))
2314 			return TRUE;
2315 		}
2316 
2317 	return FALSE;
2318 	}
2319 
2320 
2321 
2322 /*  tests whether a contactgroup is a contactgroup for a particular host */
is_contactgroup_for_host(host * hst,contactgroup * group)2323 int is_contactgroup_for_host(host *hst, contactgroup *group) {
2324 	contactgroupsmember *temp_contactgroupsmember = NULL;
2325 
2326 	if(hst == NULL || group == NULL) {
2327 		return FALSE;
2328 		}
2329 
2330 	/* search all contactgroups of this host */
2331 	for(temp_contactgroupsmember = hst->contact_groups;
2332 			temp_contactgroupsmember != NULL;
2333 			temp_contactgroupsmember = temp_contactgroupsmember->next) {
2334 		if(temp_contactgroupsmember->group_ptr == group) {
2335 			return TRUE;
2336 			}
2337 		}
2338 
2339 	return FALSE;
2340 	}
2341 
2342 
2343 
2344 /* tests whether a contact is an escalated contact for a particular host */
is_escalated_contact_for_host(host * hst,contact * cntct)2345 int is_escalated_contact_for_host(host *hst, contact *cntct) {
2346 	hostescalation *temp_hostescalation = NULL;
2347 	objectlist *list;
2348 
2349 	/* search all host escalations */
2350 	for(list = hst->escalation_list; list; list = list->next) {
2351 		temp_hostescalation = (hostescalation *)list->object_ptr;
2352 
2353 		if(is_contact_for_host_escalation(temp_hostescalation, cntct) == TRUE) {
2354 			return TRUE;
2355 			}
2356 		}
2357 
2358 	return FALSE;
2359 	}
2360 
2361 
2362 
2363 /* tests whether a contact is an contact for a particular host escalation */
is_contact_for_host_escalation(hostescalation * escalation,contact * cntct)2364 int is_contact_for_host_escalation(hostescalation *escalation, contact *cntct) {
2365 	contactsmember *temp_contactsmember = NULL;
2366 	contactgroupsmember *temp_contactgroupsmember = NULL;
2367 	contactgroup *temp_contactgroup = NULL;
2368 
2369 	if(escalation == NULL || cntct == NULL) {
2370 		return FALSE;
2371 		}
2372 
2373 	/* search all contacts of this host escalation */
2374 	for(temp_contactsmember = escalation->contacts;
2375 			temp_contactsmember != NULL;
2376 			temp_contactsmember = temp_contactsmember->next) {
2377 		if(temp_contactsmember->contact_ptr == cntct)
2378 			return TRUE;
2379 		}
2380 
2381 	/* search all contactgroups of this host escalation */
2382 	for(temp_contactgroupsmember = escalation->contact_groups;
2383 			temp_contactgroupsmember != NULL;
2384 			temp_contactgroupsmember = temp_contactgroupsmember->next) {
2385 		temp_contactgroup = temp_contactgroupsmember->group_ptr;
2386 		if(is_contact_member_of_contactgroup(temp_contactgroup, cntct))
2387 			return TRUE;
2388 		}
2389 
2390 	return FALSE;
2391 	}
2392 
2393 
2394 
2395 /*  tests whether a contactgroup is a contactgroup for a particular
2396 	host escalation */
is_contactgroup_for_host_escalation(hostescalation * escalation,contactgroup * group)2397 int is_contactgroup_for_host_escalation(hostescalation *escalation,
2398 		contactgroup *group) {
2399 	contactgroupsmember *temp_contactgroupsmember = NULL;
2400 
2401 	if(escalation == NULL || group == NULL) {
2402 		return FALSE;
2403 		}
2404 
2405 	/* search all contactgroups of this host escalation */
2406 	for(temp_contactgroupsmember = escalation->contact_groups;
2407 			temp_contactgroupsmember != NULL;
2408 			temp_contactgroupsmember = temp_contactgroupsmember->next) {
2409 		if(temp_contactgroupsmember->group_ptr == group) {
2410 			return TRUE;
2411 			}
2412 		}
2413 
2414 	return FALSE;
2415 	}
2416 
2417 
2418 
2419 /*  tests whether a contact is a contact for a particular service */
is_contact_for_service(service * svc,contact * cntct)2420 int is_contact_for_service(service *svc, contact *cntct) {
2421 	contactsmember *temp_contactsmember = NULL;
2422 	contactgroupsmember *temp_contactgroupsmember = NULL;
2423 	contactgroup *temp_contactgroup = NULL;
2424 
2425 	if(svc == NULL || cntct == NULL)
2426 		return FALSE;
2427 
2428 	/* search all individual contacts of this service */
2429 	for(temp_contactsmember = svc->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
2430 		if(temp_contactsmember->contact_ptr == cntct)
2431 			return TRUE;
2432 		}
2433 
2434 	/* search all contactgroups of this service */
2435 	for(temp_contactgroupsmember = svc->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
2436 		temp_contactgroup = temp_contactgroupsmember->group_ptr;
2437 		if(is_contact_member_of_contactgroup(temp_contactgroup, cntct))
2438 			return TRUE;
2439 
2440 		}
2441 
2442 	return FALSE;
2443 	}
2444 
2445 
2446 
2447 /*  tests whether a contactgroup is a contactgroup for a particular service */
is_contactgroup_for_service(service * svc,contactgroup * group)2448 int is_contactgroup_for_service(service *svc, contactgroup *group) {
2449 	contactgroupsmember *temp_contactgroupsmember = NULL;
2450 
2451 	if(svc == NULL || group == NULL)
2452 		return FALSE;
2453 
2454 	/* search all contactgroups of this service */
2455 	for(temp_contactgroupsmember = svc->contact_groups;
2456 			temp_contactgroupsmember != NULL;
2457 			temp_contactgroupsmember = temp_contactgroupsmember->next) {
2458 		if(temp_contactgroupsmember->group_ptr == group) {
2459 			return TRUE;
2460 			}
2461 		}
2462 
2463 	return FALSE;
2464 	}
2465 
2466 
2467 
2468 /* tests whether a contact is an escalated contact for a particular service */
is_escalated_contact_for_service(service * svc,contact * cntct)2469 int is_escalated_contact_for_service(service *svc, contact *cntct) {
2470 	serviceescalation *temp_serviceescalation = NULL;
2471 	objectlist *list;
2472 
2473 	/* search all the service escalations */
2474 	for(list = svc->escalation_list; list; list = list->next) {
2475 		temp_serviceescalation = (serviceescalation *)list->object_ptr;
2476 
2477 		if(is_contact_for_service_escalation(temp_serviceescalation,
2478 				cntct) == TRUE) {
2479 			return TRUE;
2480 			}
2481 		}
2482 
2483 	return FALSE;
2484 	}
2485 
2486 
2487 
2488 /* tests whether a contact is an contact for a particular service escalation */
is_contact_for_service_escalation(serviceescalation * escalation,contact * cntct)2489 int is_contact_for_service_escalation(serviceescalation *escalation,
2490 		contact *cntct) {
2491 	contactsmember *temp_contactsmember = NULL;
2492 	contactgroupsmember *temp_contactgroupsmember = NULL;
2493 	contactgroup *temp_contactgroup = NULL;
2494 
2495 	/* search all contacts of this service escalation */
2496 	for(temp_contactsmember = escalation->contacts;
2497 			temp_contactsmember != NULL;
2498 			temp_contactsmember = temp_contactsmember->next) {
2499 		if(temp_contactsmember->contact_ptr == cntct)
2500 			return TRUE;
2501 		}
2502 
2503 	/* search all contactgroups of this service escalation */
2504 	for(temp_contactgroupsmember =escalation->contact_groups;
2505 			temp_contactgroupsmember != NULL;
2506 			temp_contactgroupsmember = temp_contactgroupsmember->next) {
2507 		temp_contactgroup = temp_contactgroupsmember->group_ptr;
2508 		if(is_contact_member_of_contactgroup(temp_contactgroup, cntct))
2509 			return TRUE;
2510 		}
2511 
2512 	return FALSE;
2513 	}
2514 
2515 
2516 
2517 /*  tests whether a contactgroup is a contactgroup for a particular
2518 	service escalation */
is_contactgroup_for_service_escalation(serviceescalation * escalation,contactgroup * group)2519 int is_contactgroup_for_service_escalation(serviceescalation *escalation,
2520 		contactgroup *group) {
2521 	contactgroupsmember *temp_contactgroupsmember = NULL;
2522 
2523 	if(escalation == NULL || group == NULL) {
2524 		return FALSE;
2525 		}
2526 
2527 	/* search all contactgroups of this service escalation */
2528 	for(temp_contactgroupsmember = escalation->contact_groups;
2529 			temp_contactgroupsmember != NULL;
2530 			temp_contactgroupsmember = temp_contactgroupsmember->next) {
2531 		if(temp_contactgroupsmember->group_ptr == group) {
2532 			return TRUE;
2533 			}
2534 		}
2535 
2536 	return FALSE;
2537 	}
2538 
2539 
2540 
2541 /******************************************************************/
2542 /******************* OBJECT DELETION FUNCTIONS ********************/
2543 /******************************************************************/
2544 
2545 
2546 /* free all allocated memory for objects */
free_object_data(void)2547 int free_object_data(void) {
2548 	daterange *this_daterange = NULL;
2549 	daterange *next_daterange = NULL;
2550 	timerange *this_timerange = NULL;
2551 	timerange *next_timerange = NULL;
2552 	timeperiodexclusion *this_timeperiodexclusion = NULL;
2553 	timeperiodexclusion *next_timeperiodexclusion = NULL;
2554 	hostsmember *this_hostsmember = NULL;
2555 	hostsmember *next_hostsmember = NULL;
2556 	servicesmember *this_servicesmember = NULL;
2557 	servicesmember *next_servicesmember = NULL;
2558 	contactsmember *this_contactsmember = NULL;
2559 	contactsmember *next_contactsmember = NULL;
2560 	contactgroupsmember *this_contactgroupsmember = NULL;
2561 	contactgroupsmember *next_contactgroupsmember = NULL;
2562 	customvariablesmember *this_customvariablesmember = NULL;
2563 	customvariablesmember *next_customvariablesmember = NULL;
2564 	commandsmember *this_commandsmember = NULL;
2565 	commandsmember *next_commandsmember = NULL;
2566 	unsigned int i = 0, x = 0;
2567 
2568 
2569 	/*
2570 	 * kill off hash tables so lingering modules don't look stuff up
2571 	 * while we're busy removing it.
2572 	 */
2573 	for (i = 0; i < ARRAY_SIZE(object_hash_tables); i++) {
2574 		dkhash_table *t = object_hash_tables[i];
2575 		object_hash_tables[i] = NULL;
2576 		dkhash_destroy(t);
2577 	}
2578 
2579 	/**** free memory for the timeperiod list ****/
2580 	for (i = 0; i < num_objects.timeperiods; i++) {
2581 		timeperiod *this_timeperiod = timeperiod_ary[i];
2582 
2583 		/* free the exception time ranges contained in this timeperiod */
2584 		for(x = 0; x < DATERANGE_TYPES; x++) {
2585 
2586 			for(this_daterange = this_timeperiod->exceptions[x]; this_daterange != NULL; this_daterange = next_daterange) {
2587 				next_daterange = this_daterange->next;
2588 				for(this_timerange = this_daterange->times; this_timerange != NULL; this_timerange = next_timerange) {
2589 					next_timerange = this_timerange->next;
2590 					my_free(this_timerange);
2591 					}
2592 				my_free(this_daterange);
2593 				}
2594 			}
2595 
2596 		/* free the day time ranges contained in this timeperiod */
2597 		for(x = 0; x < 7; x++) {
2598 
2599 			for(this_timerange = this_timeperiod->days[x]; this_timerange != NULL; this_timerange = next_timerange) {
2600 				next_timerange = this_timerange->next;
2601 				my_free(this_timerange);
2602 				}
2603 			}
2604 
2605 		/* free exclusions */
2606 		for(this_timeperiodexclusion = this_timeperiod->exclusions; this_timeperiodexclusion != NULL; this_timeperiodexclusion = next_timeperiodexclusion) {
2607 			next_timeperiodexclusion = this_timeperiodexclusion->next;
2608 			my_free(this_timeperiodexclusion->timeperiod_name);
2609 			my_free(this_timeperiodexclusion);
2610 			}
2611 
2612 		if (this_timeperiod->alias != this_timeperiod->name)
2613 			my_free(this_timeperiod->alias);
2614 		my_free(this_timeperiod->name);
2615 		my_free(this_timeperiod);
2616 		}
2617 
2618 	/* reset pointers */
2619 	my_free(timeperiod_ary);
2620 
2621 
2622 	/**** free memory for the host list ****/
2623 	for (i = 0; i < num_objects.hosts; i++) {
2624 		host *this_host = host_ary[i];
2625 
2626 		/* free memory for parent hosts */
2627 		this_hostsmember = this_host->parent_hosts;
2628 		while(this_hostsmember != NULL) {
2629 			next_hostsmember = this_hostsmember->next;
2630 			my_free(this_hostsmember->host_name);
2631 			my_free(this_hostsmember);
2632 			this_hostsmember = next_hostsmember;
2633 			}
2634 
2635 		/* free memory for child host links */
2636 		this_hostsmember = this_host->child_hosts;
2637 		while(this_hostsmember != NULL) {
2638 			next_hostsmember = this_hostsmember->next;
2639 			my_free(this_hostsmember);
2640 			this_hostsmember = next_hostsmember;
2641 			}
2642 
2643 		/* free memory for service links */
2644 		this_servicesmember = this_host->services;
2645 		while(this_servicesmember != NULL) {
2646 			next_servicesmember = this_servicesmember->next;
2647 			my_free(this_servicesmember);
2648 			this_servicesmember = next_servicesmember;
2649 			}
2650 
2651 		/* free memory for contact groups */
2652 		this_contactgroupsmember = this_host->contact_groups;
2653 		while(this_contactgroupsmember != NULL) {
2654 			next_contactgroupsmember = this_contactgroupsmember->next;
2655 			my_free(this_contactgroupsmember);
2656 			this_contactgroupsmember = next_contactgroupsmember;
2657 			}
2658 
2659 		/* free memory for contacts */
2660 		this_contactsmember = this_host->contacts;
2661 		while(this_contactsmember != NULL) {
2662 			next_contactsmember = this_contactsmember->next;
2663 			my_free(this_contactsmember);
2664 			this_contactsmember = next_contactsmember;
2665 			}
2666 
2667 		/* free memory for custom variables */
2668 		this_customvariablesmember = this_host->custom_variables;
2669 		while(this_customvariablesmember != NULL) {
2670 			next_customvariablesmember = this_customvariablesmember->next;
2671 			my_free(this_customvariablesmember->variable_name);
2672 			my_free(this_customvariablesmember->variable_value);
2673 			my_free(this_customvariablesmember);
2674 			this_customvariablesmember = next_customvariablesmember;
2675 			}
2676 
2677 		if(this_host->display_name != this_host->name)
2678 			my_free(this_host->display_name);
2679 		if(this_host->alias != this_host->name)
2680 			my_free(this_host->alias);
2681 		if(this_host->address != this_host->name)
2682 			my_free(this_host->address);
2683 		my_free(this_host->name);
2684 		my_free(this_host->check_period);
2685 		my_free(this_host->notification_period);
2686 #ifdef NSCORE
2687 		my_free(this_host->plugin_output);
2688 		my_free(this_host->long_plugin_output);
2689 		my_free(this_host->perf_data);
2690 #endif
2691 		free_objectlist(&this_host->hostgroups_ptr);
2692 		free_objectlist(&this_host->notify_deps);
2693 		free_objectlist(&this_host->exec_deps);
2694 		free_objectlist(&this_host->escalation_list);
2695 		my_free(this_host->check_command);
2696 		my_free(this_host->event_handler);
2697 		my_free(this_host->notes);
2698 		my_free(this_host->notes_url);
2699 		my_free(this_host->action_url);
2700 		my_free(this_host->icon_image);
2701 		my_free(this_host->icon_image_alt);
2702 		my_free(this_host->vrml_image);
2703 		my_free(this_host->statusmap_image);
2704 		my_free(this_host);
2705 		}
2706 
2707 	/* reset pointers */
2708 	my_free(host_ary);
2709 
2710 
2711 	/**** free memory for the host group list ****/
2712 	for (i = 0; i < num_objects.hostgroups; i++) {
2713 		hostgroup *this_hostgroup = hostgroup_ary[i];
2714 
2715 		/* free memory for the group members */
2716 		this_hostsmember = this_hostgroup->members;
2717 		while(this_hostsmember != NULL) {
2718 			next_hostsmember = this_hostsmember->next;
2719 			my_free(this_hostsmember);
2720 			this_hostsmember = next_hostsmember;
2721 			}
2722 
2723 		if (this_hostgroup->alias != this_hostgroup->group_name)
2724 			my_free(this_hostgroup->alias);
2725 		my_free(this_hostgroup->group_name);
2726 		my_free(this_hostgroup->notes);
2727 		my_free(this_hostgroup->notes_url);
2728 		my_free(this_hostgroup->action_url);
2729 		my_free(this_hostgroup);
2730 		}
2731 
2732 	/* reset pointers */
2733 	my_free(hostgroup_ary);
2734 
2735 	/**** free memory for the service group list ****/
2736 	for (i = 0; i < num_objects.servicegroups; i++) {
2737 		servicegroup *this_servicegroup = servicegroup_ary[i];
2738 
2739 		/* free memory for the group members */
2740 		this_servicesmember = this_servicegroup->members;
2741 		while(this_servicesmember != NULL) {
2742 			next_servicesmember = this_servicesmember->next;
2743 			my_free(this_servicesmember);
2744 			this_servicesmember = next_servicesmember;
2745 			}
2746 
2747 		if (this_servicegroup->alias != this_servicegroup->group_name)
2748 			my_free(this_servicegroup->alias);
2749 		my_free(this_servicegroup->group_name);
2750 		my_free(this_servicegroup->notes);
2751 		my_free(this_servicegroup->notes_url);
2752 		my_free(this_servicegroup->action_url);
2753 		my_free(this_servicegroup);
2754 		}
2755 
2756 	/* reset pointers */
2757 	my_free(servicegroup_ary);
2758 
2759 	/**** free memory for the contact list ****/
2760 	for (i = 0; i < num_objects.contacts; i++) {
2761 		int j;
2762 		contact *this_contact = contact_ary[i];
2763 
2764 		/* free memory for the host notification commands */
2765 		this_commandsmember = this_contact->host_notification_commands;
2766 		while(this_commandsmember != NULL) {
2767 			next_commandsmember = this_commandsmember->next;
2768 			if(this_commandsmember->command != NULL)
2769 				my_free(this_commandsmember->command);
2770 			my_free(this_commandsmember);
2771 			this_commandsmember = next_commandsmember;
2772 			}
2773 
2774 		/* free memory for the service notification commands */
2775 		this_commandsmember = this_contact->service_notification_commands;
2776 		while(this_commandsmember != NULL) {
2777 			next_commandsmember = this_commandsmember->next;
2778 			if(this_commandsmember->command != NULL)
2779 				my_free(this_commandsmember->command);
2780 			my_free(this_commandsmember);
2781 			this_commandsmember = next_commandsmember;
2782 			}
2783 
2784 		/* free memory for custom variables */
2785 		this_customvariablesmember = this_contact->custom_variables;
2786 		while(this_customvariablesmember != NULL) {
2787 			next_customvariablesmember = this_customvariablesmember->next;
2788 			my_free(this_customvariablesmember->variable_name);
2789 			my_free(this_customvariablesmember->variable_value);
2790 			my_free(this_customvariablesmember);
2791 			this_customvariablesmember = next_customvariablesmember;
2792 			}
2793 
2794 		if (this_contact->alias != this_contact->name)
2795 			my_free(this_contact->alias);
2796 		my_free(this_contact->name);
2797 		my_free(this_contact->email);
2798 		my_free(this_contact->pager);
2799 		my_free(this_contact->host_notification_period);
2800 		my_free(this_contact->service_notification_period);
2801 		for(j = 0; j < MAX_CONTACT_ADDRESSES; j++)
2802 			my_free(this_contact->address[j]);
2803 
2804 		free_objectlist(&this_contact->contactgroups_ptr);
2805 		my_free(this_contact);
2806 		}
2807 
2808 	/* reset pointers */
2809 	my_free(contact_ary);
2810 
2811 
2812 	/**** free memory for the contact group list ****/
2813 	for (i = 0; i < num_objects.contactgroups; i++) {
2814 		contactgroup *this_contactgroup = contactgroup_ary[i];
2815 
2816 		/* free memory for the group members */
2817 		this_contactsmember = this_contactgroup->members;
2818 		while(this_contactsmember != NULL) {
2819 			next_contactsmember = this_contactsmember->next;
2820 			my_free(this_contactsmember);
2821 			this_contactsmember = next_contactsmember;
2822 			}
2823 
2824 		if (this_contactgroup->alias != this_contactgroup->group_name)
2825 			my_free(this_contactgroup->alias);
2826 		my_free(this_contactgroup->group_name);
2827 		my_free(this_contactgroup);
2828 		}
2829 
2830 	/* reset pointers */
2831 	my_free(contactgroup_ary);
2832 
2833 
2834 	/**** free memory for the service list ****/
2835 	for (i = 0; i < num_objects.services; i++) {
2836 		service *this_service = service_ary[i];
2837 
2838 		/* free memory for contact groups */
2839 		this_contactgroupsmember = this_service->contact_groups;
2840 		while(this_contactgroupsmember != NULL) {
2841 			next_contactgroupsmember = this_contactgroupsmember->next;
2842 			my_free(this_contactgroupsmember);
2843 			this_contactgroupsmember = next_contactgroupsmember;
2844 			}
2845 
2846 		/* free memory for contacts */
2847 		this_contactsmember = this_service->contacts;
2848 		while(this_contactsmember != NULL) {
2849 			next_contactsmember = this_contactsmember->next;
2850 			my_free(this_contactsmember);
2851 			this_contactsmember = next_contactsmember;
2852 			}
2853 
2854 		/* free memory for custom variables */
2855 		this_customvariablesmember = this_service->custom_variables;
2856 		while(this_customvariablesmember != NULL) {
2857 			next_customvariablesmember = this_customvariablesmember->next;
2858 			my_free(this_customvariablesmember->variable_name);
2859 			my_free(this_customvariablesmember->variable_value);
2860 			my_free(this_customvariablesmember);
2861 			this_customvariablesmember = next_customvariablesmember;
2862 			}
2863 
2864 		if(this_service->display_name != this_service->description)
2865 			my_free(this_service->display_name);
2866 		my_free(this_service->description);
2867 		my_free(this_service->check_command);
2868 		my_free(this_service->check_period);
2869 		my_free(this_service->notification_period);
2870 #ifdef NSCORE
2871 		my_free(this_service->plugin_output);
2872 		my_free(this_service->long_plugin_output);
2873 		my_free(this_service->perf_data);
2874 
2875 		my_free(this_service->event_handler_args);
2876 		my_free(this_service->check_command_args);
2877 #endif
2878 
2879 		free_objectlist(&this_service->servicegroups_ptr);
2880 		free_objectlist(&this_service->notify_deps);
2881 		free_objectlist(&this_service->exec_deps);
2882 		free_objectlist(&this_service->escalation_list);
2883 		my_free(this_service->event_handler);
2884 		my_free(this_service->notes);
2885 		my_free(this_service->notes_url);
2886 		my_free(this_service->action_url);
2887 		my_free(this_service->icon_image);
2888 		my_free(this_service->icon_image_alt);
2889 		my_free(this_service);
2890 		}
2891 
2892 	/* reset pointers */
2893 	my_free(service_ary);
2894 
2895 
2896 	/**** free command memory ****/
2897 	for (i = 0; i < num_objects.commands; i++) {
2898 		command *this_command = command_ary[i];
2899 		my_free(this_command->name);
2900 		my_free(this_command->command_line);
2901 		my_free(this_command);
2902 		}
2903 
2904 	/* reset pointers */
2905 	my_free(command_ary);
2906 
2907 
2908 	/**** free service escalation memory ****/
2909 	for (i = 0; i < num_objects.serviceescalations; i++) {
2910 		serviceescalation *this_serviceescalation = serviceescalation_ary[i];
2911 
2912 		/* free memory for the contact group members */
2913 		this_contactgroupsmember = this_serviceescalation->contact_groups;
2914 		while(this_contactgroupsmember != NULL) {
2915 			next_contactgroupsmember = this_contactgroupsmember->next;
2916 			my_free(this_contactgroupsmember);
2917 			this_contactgroupsmember = next_contactgroupsmember;
2918 			}
2919 
2920 		/* free memory for contacts */
2921 		this_contactsmember = this_serviceescalation->contacts;
2922 		while(this_contactsmember != NULL) {
2923 			next_contactsmember = this_contactsmember->next;
2924 			my_free(this_contactsmember);
2925 			this_contactsmember = next_contactsmember;
2926 			}
2927 		my_free(this_serviceescalation);
2928 		}
2929 
2930 	/* reset pointers */
2931 	my_free(serviceescalation_ary);
2932 
2933 
2934 	/**** free service dependency memory ****/
2935 	if (servicedependency_ary) {
2936 		for(i = 0; i < num_objects.servicedependencies; i++)
2937 			my_free(servicedependency_ary[i]);
2938 		my_free(servicedependency_ary);
2939 		}
2940 
2941 
2942 	/**** free host dependency memory ****/
2943 	if (hostdependency_ary) {
2944 		for(i = 0; i < num_objects.hostdependencies; i++)
2945 			my_free(hostdependency_ary[i]);
2946 		my_free(hostdependency_ary);
2947 		}
2948 
2949 
2950 	/**** free host escalation memory ****/
2951 	for (i = 0; i < num_objects.hostescalations; i++) {
2952 		hostescalation *this_hostescalation = hostescalation_ary[i];
2953 
2954 		/* free memory for the contact group members */
2955 		this_contactgroupsmember = this_hostescalation->contact_groups;
2956 		while(this_contactgroupsmember != NULL) {
2957 			next_contactgroupsmember = this_contactgroupsmember->next;
2958 			my_free(this_contactgroupsmember);
2959 			this_contactgroupsmember = next_contactgroupsmember;
2960 			}
2961 
2962 		/* free memory for contacts */
2963 		this_contactsmember = this_hostescalation->contacts;
2964 		while(this_contactsmember != NULL) {
2965 			next_contactsmember = this_contactsmember->next;
2966 			my_free(this_contactsmember);
2967 			this_contactsmember = next_contactsmember;
2968 			}
2969 		my_free(this_hostescalation);
2970 		}
2971 
2972 	/* reset pointers */
2973 	my_free(hostescalation_ary);
2974 
2975 	/* we no longer have any objects */
2976 	memset(&num_objects, 0, sizeof(num_objects));
2977 
2978 	return OK;
2979 	}
2980 
2981 
2982 
2983 /******************************************************************/
2984 /*********************** CACHE FUNCTIONS **************************/
2985 /******************************************************************/
2986 
2987 #ifndef NSCGI
timerange2str(const timerange * tr)2988 static const char *timerange2str(const timerange *tr)
2989 {
2990 	static char str[12];
2991 	int sh, sm, eh, em;
2992 
2993 	if(!tr)
2994 		return "";
2995 	sh = tr->range_start / 3600;
2996 	sm = (tr->range_start / 60) % 60;
2997 	eh = tr->range_end / 3600;
2998 	em = (tr->range_end / 60) % 60;
2999 	sprintf(str, "%02d:%02d-%02d:%02d", sh, sm, eh, em);
3000 	return str;
3001 }
3002 
fcache_contactlist(FILE * fp,const char * prefix,contactsmember * list)3003 void fcache_contactlist(FILE *fp, const char *prefix, contactsmember *list)
3004 {
3005 	if(list) {
3006 		contactsmember *l;
3007 		fprintf(fp, "%s", prefix);
3008 		for(l = list; l; l = l->next)
3009 			fprintf(fp, "%s%c", l->contact_name, l->next ? ',' : '\n');
3010 	}
3011 }
3012 
fcache_contactgrouplist(FILE * fp,const char * prefix,contactgroupsmember * list)3013 void fcache_contactgrouplist(FILE *fp, const char *prefix, contactgroupsmember *list)
3014 {
3015 	if(list) {
3016 		contactgroupsmember *l;
3017 		fprintf(fp, "%s", prefix);
3018 		for(l = list; l; l = l->next)
3019 			fprintf(fp, "%s%c", l->group_name, l->next ? ',' : '\n');
3020 	}
3021 }
3022 
fcache_hostlist(FILE * fp,const char * prefix,hostsmember * list)3023 void fcache_hostlist(FILE *fp, const char *prefix, hostsmember *list)
3024 {
3025 	if(list) {
3026 		hostsmember *l;
3027 		fprintf(fp, "%s", prefix);
3028 		for(l = list; l; l = l->next)
3029 			fprintf(fp, "%s%c", l->host_name, l->next ? ',' : '\n');
3030 	}
3031 }
3032 
fcache_customvars(FILE * fp,customvariablesmember * cvlist)3033 void fcache_customvars(FILE *fp, customvariablesmember *cvlist)
3034 {
3035 	if(cvlist) {
3036 		customvariablesmember *l;
3037 		for(l = cvlist; l; l = l->next)
3038 			fprintf(fp, "\t_%s\t%s\n", l->variable_name, (l->variable_value == NULL) ? XODTEMPLATE_NULL : l->variable_value);
3039 	}
3040 }
3041 
fcache_timeperiod(FILE * fp,timeperiod * temp_timeperiod)3042 void fcache_timeperiod(FILE *fp, timeperiod *temp_timeperiod)
3043 {
3044 	const char *days[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
3045 	const char *months[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};
3046 	daterange *temp_daterange;
3047 	timerange *tr;
3048 	register int x;
3049 
3050 	fprintf(fp, "define timeperiod {\n");
3051 	fprintf(fp, "\ttimeperiod_name\t%s\n", temp_timeperiod->name);
3052 	if(temp_timeperiod->alias)
3053 		fprintf(fp, "\talias\t%s\n", temp_timeperiod->alias);
3054 
3055 	if(temp_timeperiod->exclusions) {
3056 		timeperiodexclusion *exclude;
3057 		fprintf(fp, "\texclude\t");
3058 		for(exclude = temp_timeperiod->exclusions; exclude; exclude = exclude->next) {
3059 			fprintf(fp, "%s%c", exclude->timeperiod_name, exclude->next ? ',' : '\n');
3060 		}
3061 	}
3062 
3063 	for(x = 0; x < DATERANGE_TYPES; x++) {
3064 		for(temp_daterange = temp_timeperiod->exceptions[x]; temp_daterange != NULL; temp_daterange = temp_daterange->next) {
3065 
3066 			/* skip null entries */
3067 			if(temp_daterange->times == NULL)
3068 				continue;
3069 
3070 			switch(temp_daterange->type) {
3071 				case DATERANGE_CALENDAR_DATE:
3072 				fprintf(fp, "\t%d-%02d-%02d", temp_daterange->syear, temp_daterange->smon + 1, temp_daterange->smday);
3073 				if((temp_daterange->smday != temp_daterange->emday) || (temp_daterange->smon != temp_daterange->emon) || (temp_daterange->syear != temp_daterange->eyear))
3074 					fprintf(fp, " - %d-%02d-%02d", temp_daterange->eyear, temp_daterange->emon + 1, temp_daterange->emday);
3075 				if(temp_daterange->skip_interval > 1)
3076 					fprintf(fp, " / %d", temp_daterange->skip_interval);
3077 				break;
3078 			case DATERANGE_MONTH_DATE:
3079 				fprintf(fp, "\t%s %d", months[temp_daterange->smon], temp_daterange->smday);
3080 				if((temp_daterange->smon != temp_daterange->emon) || (temp_daterange->smday != temp_daterange->emday)) {
3081 					fprintf(fp, " - %s %d", months[temp_daterange->emon], temp_daterange->emday);
3082 					if(temp_daterange->skip_interval > 1)
3083 						fprintf(fp, " / %d", temp_daterange->skip_interval);
3084 				}
3085 				break;
3086 			case DATERANGE_MONTH_DAY:
3087 				fprintf(fp, "\tday %d", temp_daterange->smday);
3088 				if(temp_daterange->smday != temp_daterange->emday) {
3089 					fprintf(fp, " - %d", temp_daterange->emday);
3090 					if(temp_daterange->skip_interval > 1)
3091 						fprintf(fp, " / %d", temp_daterange->skip_interval);
3092 				}
3093 				break;
3094 			case DATERANGE_MONTH_WEEK_DAY:
3095 				fprintf(fp, "\t%s %d %s", days[temp_daterange->swday], temp_daterange->swday_offset, months[temp_daterange->smon]);
3096 				if((temp_daterange->smon != temp_daterange->emon) || (temp_daterange->swday != temp_daterange->ewday) || (temp_daterange->swday_offset != temp_daterange->ewday_offset)) {
3097 					fprintf(fp, " - %s %d %s", days[temp_daterange->ewday], temp_daterange->ewday_offset, months[temp_daterange->emon]);
3098 					if(temp_daterange->skip_interval > 1)
3099 						fprintf(fp, " / %d", temp_daterange->skip_interval);
3100 				}
3101 				break;
3102 			case DATERANGE_WEEK_DAY:
3103 				fprintf(fp, "\t%s %d", days[temp_daterange->swday], temp_daterange->swday_offset);
3104 				if((temp_daterange->swday != temp_daterange->ewday) || (temp_daterange->swday_offset != temp_daterange->ewday_offset)) {
3105 					fprintf(fp, " - %s %d", days[temp_daterange->ewday], temp_daterange->ewday_offset);
3106 					if(temp_daterange->skip_interval > 1)
3107 						fprintf(fp, " / %d", temp_daterange->skip_interval);
3108 				}
3109 				break;
3110 			default:
3111 				break;
3112 			}
3113 
3114 			fputc('\t', fp);
3115 			for(tr = temp_daterange->times; tr; tr = tr->next) {
3116 				fprintf(fp, "%s%c", timerange2str(tr), tr->next ? ',' : '\n');
3117 			}
3118 		}
3119 	}
3120 	for(x = 0; x < 7; x++) {
3121 		/* skip null entries */
3122 		if(temp_timeperiod->days[x] == NULL)
3123 			continue;
3124 
3125 		fprintf(fp, "\t%s\t", days[x]);
3126 		for(tr = temp_timeperiod->days[x]; tr; tr = tr->next) {
3127 			fprintf(fp, "%s%c", timerange2str(tr), tr->next ? ',' : '\n');
3128 		}
3129 	}
3130 	fprintf(fp, "\t}\n\n");
3131 }
3132 
fcache_command(FILE * fp,command * temp_command)3133 void fcache_command(FILE *fp, command *temp_command)
3134 {
3135 	fprintf(fp, "define command {\n\tcommand_name\t%s\n\tcommand_line\t%s\n\t}\n\n",
3136 		   temp_command->name, temp_command->command_line);
3137 }
3138 
fcache_contactgroup(FILE * fp,contactgroup * temp_contactgroup)3139 void fcache_contactgroup(FILE *fp, contactgroup *temp_contactgroup)
3140 {
3141 	fprintf(fp, "define contactgroup {\n");
3142 	fprintf(fp, "\tcontactgroup_name\t%s\n", temp_contactgroup->group_name);
3143 	if(temp_contactgroup->alias)
3144 		fprintf(fp, "\talias\t%s\n", temp_contactgroup->alias);
3145 	fcache_contactlist(fp, "\tmembers\t", temp_contactgroup->members);
3146 	fprintf(fp, "\t}\n\n");
3147 }
3148 
fcache_hostgroup(FILE * fp,hostgroup * temp_hostgroup)3149 void fcache_hostgroup(FILE *fp, hostgroup *temp_hostgroup)
3150 {
3151 	fprintf(fp, "define hostgroup {\n");
3152 	fprintf(fp, "\thostgroup_name\t%s\n", temp_hostgroup->group_name);
3153 	if(temp_hostgroup->alias)
3154 		fprintf(fp, "\talias\t%s\n", temp_hostgroup->alias);
3155 	if(temp_hostgroup->members) {
3156 		hostsmember *list;
3157 		fprintf(fp, "\tmembers\t");
3158 		for(list = temp_hostgroup->members; list; list = list->next)
3159 			fprintf(fp, "%s%c", list->host_name, list->next ? ',' : '\n');
3160 	}
3161 	if(temp_hostgroup->notes)
3162 		fprintf(fp, "\tnotes\t%s\n", temp_hostgroup->notes);
3163 	if(temp_hostgroup->notes_url)
3164 		fprintf(fp, "\tnotes_url\t%s\n", temp_hostgroup->notes_url);
3165 	if(temp_hostgroup->action_url)
3166 		fprintf(fp, "\taction_url\t%s\n", temp_hostgroup->action_url);
3167 	fprintf(fp, "\t}\n\n");
3168 }
3169 
fcache_servicegroup(FILE * fp,servicegroup * temp_servicegroup)3170 void fcache_servicegroup(FILE *fp, servicegroup *temp_servicegroup)
3171 {
3172 	fprintf(fp, "define servicegroup {\n");
3173 	fprintf(fp, "\tservicegroup_name\t%s\n", temp_servicegroup->group_name);
3174 	if(temp_servicegroup->alias)
3175 		fprintf(fp, "\talias\t%s\n", temp_servicegroup->alias);
3176 	if(temp_servicegroup->members) {
3177 		servicesmember *list;
3178 		fprintf(fp, "\tmembers\t");
3179 		for(list = temp_servicegroup->members; list; list = list->next) {
3180 			service *s = list->service_ptr;
3181 			fprintf(fp, "%s,%s%c", s->host_name, s->description, list->next ? ',' : '\n');
3182 		}
3183 	}
3184 	if(temp_servicegroup->notes)
3185 		fprintf(fp, "\tnotes\t%s\n", temp_servicegroup->notes);
3186 	if(temp_servicegroup->notes_url)
3187 		fprintf(fp, "\tnotes_url\t%s\n", temp_servicegroup->notes_url);
3188 	if(temp_servicegroup->action_url)
3189 		fprintf(fp, "\taction_url\t%s\n", temp_servicegroup->action_url);
3190 	fprintf(fp, "\t}\n\n");
3191 }
3192 
fcache_contact(FILE * fp,contact * temp_contact)3193 void fcache_contact(FILE *fp, contact *temp_contact)
3194 {
3195 	commandsmember *list;
3196 	int x;
3197 
3198 	fprintf(fp, "define contact {\n");
3199 	fprintf(fp, "\tcontact_name\t%s\n", temp_contact->name);
3200 	if(temp_contact->alias)
3201 		fprintf(fp, "\talias\t%s\n", temp_contact->alias);
3202 	if(temp_contact->service_notification_period)
3203 		fprintf(fp, "\tservice_notification_period\t%s\n", temp_contact->service_notification_period);
3204 	if(temp_contact->host_notification_period)
3205 		fprintf(fp, "\thost_notification_period\t%s\n", temp_contact->host_notification_period);
3206 	fprintf(fp, "\tservice_notification_options\t%s\n", opts2str(temp_contact->service_notification_options, service_flag_map, 'r'));
3207 	fprintf(fp, "\thost_notification_options\t%s\n", opts2str(temp_contact->host_notification_options, host_flag_map, 'r'));
3208 	if(temp_contact->service_notification_commands) {
3209 		fprintf(fp, "\tservice_notification_commands\t");
3210 		for(list = temp_contact->service_notification_commands; list; list = list->next) {
3211 			fprintf(fp, "%s%c", list->command, list->next ? ',' : '\n');
3212 		}
3213 	}
3214 	if(temp_contact->host_notification_commands) {
3215 		fprintf(fp, "\thost_notification_commands\t");
3216 		for(list = temp_contact->host_notification_commands; list; list = list->next) {
3217 			fprintf(fp, "%s%c", list->command, list->next ? ',' : '\n');
3218 		}
3219 	}
3220 	if(temp_contact->email)
3221 		fprintf(fp, "\temail\t%s\n", temp_contact->email);
3222 	if(temp_contact->pager)
3223 		fprintf(fp, "\tpager\t%s\n", temp_contact->pager);
3224 	for(x = 0; x < MAX_XODTEMPLATE_CONTACT_ADDRESSES; x++) {
3225 		if(temp_contact->address[x])
3226 			fprintf(fp, "\taddress%d\t%s\n", x + 1, temp_contact->address[x]);
3227 	}
3228 	fprintf(fp, "\tminimum_importance\t%u\n", temp_contact->minimum_value);
3229 	fprintf(fp, "\thost_notifications_enabled\t%d\n", temp_contact->host_notifications_enabled);
3230 	fprintf(fp, "\tservice_notifications_enabled\t%d\n", temp_contact->service_notifications_enabled);
3231 	fprintf(fp, "\tcan_submit_commands\t%d\n", temp_contact->can_submit_commands);
3232 	fprintf(fp, "\tretain_status_information\t%d\n", temp_contact->retain_status_information);
3233 	fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_contact->retain_nonstatus_information);
3234 
3235 	/* custom variables */
3236 	fcache_customvars(fp, temp_contact->custom_variables);
3237 	fprintf(fp, "\t}\n\n");
3238 }
3239 
fcache_host(FILE * fp,host * temp_host)3240 void fcache_host(FILE *fp, host *temp_host)
3241 {
3242 	fprintf(fp, "define host {\n");
3243 	fprintf(fp, "\thost_name\t%s\n", temp_host->name);
3244 	if(temp_host->display_name != temp_host->name)
3245 		fprintf(fp, "\tdisplay_name\t%s\n", temp_host->display_name);
3246 	if(temp_host->alias)
3247 		fprintf(fp, "\talias\t%s\n", temp_host->alias);
3248 	if(temp_host->address)
3249 		fprintf(fp, "\taddress\t%s\n", temp_host->address);
3250 	fcache_hostlist(fp, "\tparents\t", temp_host->parent_hosts);
3251 	if(temp_host->check_period)
3252 		fprintf(fp, "\tcheck_period\t%s\n", temp_host->check_period);
3253 	if(temp_host->check_command)
3254 		fprintf(fp, "\tcheck_command\t%s\n", temp_host->check_command);
3255 	if(temp_host->event_handler)
3256 		fprintf(fp, "\tevent_handler\t%s\n", temp_host->event_handler);
3257 	fcache_contactlist(fp, "\tcontacts\t", temp_host->contacts);
3258 	fcache_contactgrouplist(fp, "\tcontact_groups\t", temp_host->contact_groups);
3259 	if(temp_host->notification_period)
3260 		fprintf(fp, "\tnotification_period\t%s\n", temp_host->notification_period);
3261 	fprintf(fp, "\tinitial_state\t");
3262 	if(temp_host->initial_state == HOST_DOWN)
3263 		fprintf(fp, "d\n");
3264 	else if(temp_host->initial_state == HOST_UNREACHABLE)
3265 		fprintf(fp, "u\n");
3266 	else
3267 		fprintf(fp, "o\n");
3268 	fprintf(fp, "\timportance\t%u\n", temp_host->hourly_value);
3269 	fprintf(fp, "\tcheck_interval\t%f\n", temp_host->check_interval);
3270 	fprintf(fp, "\tretry_interval\t%f\n", temp_host->retry_interval);
3271 	fprintf(fp, "\tmax_check_attempts\t%d\n", temp_host->max_attempts);
3272 	fprintf(fp, "\tactive_checks_enabled\t%d\n", temp_host->checks_enabled);
3273 	fprintf(fp, "\tpassive_checks_enabled\t%d\n", temp_host->accept_passive_checks);
3274 	fprintf(fp, "\tobsess\t%d\n", temp_host->obsess);
3275 	fprintf(fp, "\tevent_handler_enabled\t%d\n", temp_host->event_handler_enabled);
3276 	fprintf(fp, "\tlow_flap_threshold\t%f\n", temp_host->low_flap_threshold);
3277 	fprintf(fp, "\thigh_flap_threshold\t%f\n", temp_host->high_flap_threshold);
3278 	fprintf(fp, "\tflap_detection_enabled\t%d\n", temp_host->flap_detection_enabled);
3279 	fprintf(fp, "\tflap_detection_options\t%s\n", opts2str(temp_host->flap_detection_options, host_flag_map, 'u'));
3280 	fprintf(fp, "\tfreshness_threshold\t%d\n", temp_host->freshness_threshold);
3281 	fprintf(fp, "\tcheck_freshness\t%d\n", temp_host->check_freshness);
3282 	fprintf(fp, "\tnotification_options\t%s\n", opts2str(temp_host->notification_options, host_flag_map, 'r'));
3283 	fprintf(fp, "\tnotifications_enabled\t%d\n", temp_host->notifications_enabled);
3284 	fprintf(fp, "\tnotification_interval\t%f\n", temp_host->notification_interval);
3285 	fprintf(fp, "\tfirst_notification_delay\t%f\n", temp_host->first_notification_delay);
3286 	fprintf(fp, "\tstalking_options\t%s\n", opts2str(temp_host->stalking_options, host_flag_map, 'u'));
3287 	fprintf(fp, "\tprocess_perf_data\t%d\n", temp_host->process_performance_data);
3288 	if(temp_host->icon_image)
3289 		fprintf(fp, "\ticon_image\t%s\n", temp_host->icon_image);
3290 	if(temp_host->icon_image_alt)
3291 		fprintf(fp, "\ticon_image_alt\t%s\n", temp_host->icon_image_alt);
3292 	if(temp_host->vrml_image)
3293 		fprintf(fp, "\tvrml_image\t%s\n", temp_host->vrml_image);
3294 	if(temp_host->statusmap_image)
3295 		fprintf(fp, "\tstatusmap_image\t%s\n", temp_host->statusmap_image);
3296 	if(temp_host->have_2d_coords == TRUE)
3297 		fprintf(fp, "\t2d_coords\t%d,%d\n", temp_host->x_2d, temp_host->y_2d);
3298 	if(temp_host->have_3d_coords == TRUE)
3299 		fprintf(fp, "\t3d_coords\t%f,%f,%f\n", temp_host->x_3d, temp_host->y_3d, temp_host->z_3d);
3300 	if(temp_host->notes)
3301 		fprintf(fp, "\tnotes\t%s\n", temp_host->notes);
3302 	if(temp_host->notes_url)
3303 		fprintf(fp, "\tnotes_url\t%s\n", temp_host->notes_url);
3304 	if(temp_host->action_url)
3305 		fprintf(fp, "\taction_url\t%s\n", temp_host->action_url);
3306 	fprintf(fp, "\tretain_status_information\t%d\n", temp_host->retain_status_information);
3307 	fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_host->retain_nonstatus_information);
3308 
3309 	/* custom variables */
3310 	fcache_customvars(fp, temp_host->custom_variables);
3311 	fprintf(fp, "\t}\n\n");
3312 }
3313 
fcache_service(FILE * fp,service * temp_service)3314 void fcache_service(FILE *fp, service *temp_service)
3315 {
3316 	fprintf(fp, "define service {\n");
3317 	fprintf(fp, "\thost_name\t%s\n", temp_service->host_name);
3318 	fprintf(fp, "\tservice_description\t%s\n", temp_service->description);
3319 	if(temp_service->display_name != temp_service->description)
3320 		fprintf(fp, "\tdisplay_name\t%s\n", temp_service->display_name);
3321 	if(temp_service->parents) {
3322 		fprintf(fp, "\tparents\t");
3323 		/* same-host, single-parent? */
3324 		if(!temp_service->parents->next && temp_service->parents->service_ptr->host_ptr == temp_service->host_ptr)
3325 			fprintf(fp, "%s\n", temp_service->parents->service_ptr->description);
3326 		else {
3327 			servicesmember *sm;
3328 			for(sm = temp_service->parents; sm; sm = sm->next) {
3329 				fprintf(fp, "%s,%s%c", sm->host_name, sm->service_description, sm->next ? ',' : '\n');
3330 			}
3331 		}
3332 	}
3333 	if(temp_service->check_period)
3334 		fprintf(fp, "\tcheck_period\t%s\n", temp_service->check_period);
3335 	if(temp_service->check_command)
3336 		fprintf(fp, "\tcheck_command\t%s\n", temp_service->check_command);
3337 	if(temp_service->event_handler)
3338 		fprintf(fp, "\tevent_handler\t%s\n", temp_service->event_handler);
3339 	fcache_contactlist(fp, "\tcontacts\t", temp_service->contacts);
3340 	fcache_contactgrouplist(fp, "\tcontact_groups\t", temp_service->contact_groups);
3341 	if(temp_service->notification_period)
3342 		fprintf(fp, "\tnotification_period\t%s\n", temp_service->notification_period);
3343 	fprintf(fp, "\tinitial_state\t");
3344 	if(temp_service->initial_state == STATE_WARNING)
3345 		fprintf(fp, "w\n");
3346 	else if(temp_service->initial_state == STATE_UNKNOWN)
3347 		fprintf(fp, "u\n");
3348 	else if(temp_service->initial_state == STATE_CRITICAL)
3349 		fprintf(fp, "c\n");
3350 	else
3351 		fprintf(fp, "o\n");
3352 	fprintf(fp, "\timportance\t%u\n", temp_service->hourly_value);
3353 	fprintf(fp, "\tcheck_interval\t%f\n", temp_service->check_interval);
3354 	fprintf(fp, "\tretry_interval\t%f\n", temp_service->retry_interval);
3355 	fprintf(fp, "\tmax_check_attempts\t%d\n", temp_service->max_attempts);
3356 	fprintf(fp, "\tis_volatile\t%d\n", temp_service->is_volatile);
3357 	fprintf(fp, "\tparallelize_check\t%d\n", temp_service->parallelize);
3358 	fprintf(fp, "\tactive_checks_enabled\t%d\n", temp_service->checks_enabled);
3359 	fprintf(fp, "\tpassive_checks_enabled\t%d\n", temp_service->accept_passive_checks);
3360 	fprintf(fp, "\tobsess\t%d\n", temp_service->obsess);
3361 	fprintf(fp, "\tevent_handler_enabled\t%d\n", temp_service->event_handler_enabled);
3362 	fprintf(fp, "\tlow_flap_threshold\t%f\n", temp_service->low_flap_threshold);
3363 	fprintf(fp, "\thigh_flap_threshold\t%f\n", temp_service->high_flap_threshold);
3364 	fprintf(fp, "\tflap_detection_enabled\t%d\n", temp_service->flap_detection_enabled);
3365 	fprintf(fp, "\tflap_detection_options\t%s\n", opts2str(temp_service->flap_detection_options, service_flag_map, 'o'));
3366 	fprintf(fp, "\tfreshness_threshold\t%d\n", temp_service->freshness_threshold);
3367 	fprintf(fp, "\tcheck_freshness\t%d\n", temp_service->check_freshness);
3368 	fprintf(fp, "\tnotification_options\t%s\n", opts2str(temp_service->notification_options, service_flag_map, 'r'));
3369 	fprintf(fp, "\tnotifications_enabled\t%d\n", temp_service->notifications_enabled);
3370 	fprintf(fp, "\tnotification_interval\t%f\n", temp_service->notification_interval);
3371 	fprintf(fp, "\tfirst_notification_delay\t%f\n", temp_service->first_notification_delay);
3372 	fprintf(fp, "\tstalking_options\t%s\n", opts2str(temp_service->stalking_options, service_flag_map, 'o'));
3373 	fprintf(fp, "\tprocess_perf_data\t%d\n", temp_service->process_performance_data);
3374 	if(temp_service->icon_image)
3375 		fprintf(fp, "\ticon_image\t%s\n", temp_service->icon_image);
3376 	if(temp_service->icon_image_alt)
3377 		fprintf(fp, "\ticon_image_alt\t%s\n", temp_service->icon_image_alt);
3378 	if(temp_service->notes)
3379 		fprintf(fp, "\tnotes\t%s\n", temp_service->notes);
3380 	if(temp_service->notes_url)
3381 		fprintf(fp, "\tnotes_url\t%s\n", temp_service->notes_url);
3382 	if(temp_service->action_url)
3383 		fprintf(fp, "\taction_url\t%s\n", temp_service->action_url);
3384 	fprintf(fp, "\tretain_status_information\t%d\n", temp_service->retain_status_information);
3385 	fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_service->retain_nonstatus_information);
3386 
3387 	/* custom variables */
3388 	fcache_customvars(fp, temp_service->custom_variables);
3389 	fprintf(fp, "\t}\n\n");
3390 }
3391 
fcache_servicedependency(FILE * fp,servicedependency * temp_servicedependency)3392 void fcache_servicedependency(FILE *fp, servicedependency *temp_servicedependency)
3393 {
3394 	fprintf(fp, "define servicedependency {\n");
3395 	fprintf(fp, "\thost_name\t%s\n", temp_servicedependency->host_name);
3396 	fprintf(fp, "\tservice_description\t%s\n", temp_servicedependency->service_description);
3397 	fprintf(fp, "\tdependent_host_name\t%s\n", temp_servicedependency->dependent_host_name);
3398 	fprintf(fp, "\tdependent_service_description\t%s\n", temp_servicedependency->dependent_service_description);
3399 	if(temp_servicedependency->dependency_period)
3400 		fprintf(fp, "\tdependency_period\t%s\n", temp_servicedependency->dependency_period);
3401 	fprintf(fp, "\tinherits_parent\t%d\n", temp_servicedependency->inherits_parent);
3402 	fprintf(fp, "\t%s_failure_options\t%s\n",
3403 	        temp_servicedependency->dependency_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution",
3404 	        opts2str(temp_servicedependency->failure_options, service_flag_map, 'o'));
3405 	fprintf(fp, "\t}\n\n");
3406 }
3407 
fcache_serviceescalation(FILE * fp,serviceescalation * temp_serviceescalation)3408 void fcache_serviceescalation(FILE *fp, serviceescalation *temp_serviceescalation)
3409 {
3410 	fprintf(fp, "define serviceescalation {\n");
3411 	fprintf(fp, "\thost_name\t%s\n", temp_serviceescalation->host_name);
3412 	fprintf(fp, "\tservice_description\t%s\n", temp_serviceescalation->description);
3413 	fprintf(fp, "\tfirst_notification\t%d\n", temp_serviceescalation->first_notification);
3414 	fprintf(fp, "\tlast_notification\t%d\n", temp_serviceescalation->last_notification);
3415 	fprintf(fp, "\tnotification_interval\t%f\n", temp_serviceescalation->notification_interval);
3416 	if(temp_serviceescalation->escalation_period)
3417 		fprintf(fp, "\tescalation_period\t%s\n", temp_serviceescalation->escalation_period);
3418 	fprintf(fp, "\tescalation_options\t%s\n", opts2str(temp_serviceescalation->escalation_options, service_flag_map, 'r'));
3419 
3420 	if(temp_serviceescalation->contacts) {
3421 		contactsmember *cl;
3422 		fprintf(fp, "\tcontacts\t");
3423 		for(cl = temp_serviceescalation->contacts; cl; cl = cl->next)
3424 			fprintf(fp, "%s%c", cl->contact_ptr->name, cl->next ? ',' : '\n');
3425 	}
3426 	if(temp_serviceescalation->contact_groups) {
3427 		contactgroupsmember *cgl;
3428 		fprintf(fp, "\tcontact_groups\t");
3429 		for (cgl = temp_serviceescalation->contact_groups; cgl; cgl = cgl->next)
3430 			fprintf(fp, "%s%c", cgl->group_name, cgl->next ? ',' : '\n');
3431 	}
3432 	fprintf(fp, "\t}\n\n");
3433 }
3434 
fcache_hostdependency(FILE * fp,hostdependency * temp_hostdependency)3435 void fcache_hostdependency(FILE *fp, hostdependency *temp_hostdependency)
3436 {
3437 	fprintf(fp, "define hostdependency {\n");
3438 	fprintf(fp, "\thost_name\t%s\n", temp_hostdependency->host_name);
3439 	fprintf(fp, "\tdependent_host_name\t%s\n", temp_hostdependency->dependent_host_name);
3440 	if(temp_hostdependency->dependency_period)
3441 		fprintf(fp, "\tdependency_period\t%s\n", temp_hostdependency->dependency_period);
3442 	fprintf(fp, "\tinherits_parent\t%d\n", temp_hostdependency->inherits_parent);
3443 	fprintf(fp, "\t%s_failure_options\t%s\n",
3444 			temp_hostdependency->dependency_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution",
3445 			opts2str(temp_hostdependency->failure_options, host_flag_map, 'o'));
3446 	fprintf(fp, "\t}\n\n");
3447 }
3448 
fcache_hostescalation(FILE * fp,hostescalation * temp_hostescalation)3449 void fcache_hostescalation(FILE *fp, hostescalation *temp_hostescalation)
3450 {
3451 	fprintf(fp, "define hostescalation {\n");
3452 	fprintf(fp, "\thost_name\t%s\n", temp_hostescalation->host_name);
3453 	fprintf(fp, "\tfirst_notification\t%d\n", temp_hostescalation->first_notification);
3454 	fprintf(fp, "\tlast_notification\t%d\n", temp_hostescalation->last_notification);
3455 	fprintf(fp, "\tnotification_interval\t%f\n", temp_hostescalation->notification_interval);
3456 	if(temp_hostescalation->escalation_period)
3457 		fprintf(fp, "\tescalation_period\t%s\n", temp_hostescalation->escalation_period);
3458 	fprintf(fp, "\tescalation_options\t%s\n", opts2str(temp_hostescalation->escalation_options, host_flag_map, 'r'));
3459 
3460 	fcache_contactlist(fp, "\tcontacts\t", temp_hostescalation->contacts);
3461 	fcache_contactgrouplist(fp, "\tcontact_groups\t", temp_hostescalation->contact_groups);
3462 	fprintf(fp, "\t}\n\n");
3463 }
3464 
3465 /* writes cached object definitions for use by web interface */
fcache_objects(char * cache_file)3466 int fcache_objects(char *cache_file) {
3467 	FILE *fp = NULL;
3468 	time_t current_time = 0L;
3469 	unsigned int i;
3470 
3471 	/* some people won't want to cache their objects */
3472 	if(!cache_file || !strcmp(cache_file, "/dev/null"))
3473 		return OK;
3474 
3475 	time(&current_time);
3476 
3477 	/* open the cache file for writing */
3478 	fp = fopen(cache_file, "w");
3479 	if(fp == NULL) {
3480 		logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Could not open object cache file '%s' for writing!\n", cache_file);
3481 		return ERROR;
3482 		}
3483 
3484 	/* write header to cache file */
3485 	fprintf(fp, "########################################\n");
3486 	fprintf(fp, "#       NAGIOS OBJECT CACHE FILE\n");
3487 	fprintf(fp, "#\n");
3488 	fprintf(fp, "# THIS FILE IS AUTOMATICALLY GENERATED\n");
3489 	fprintf(fp, "# BY NAGIOS.  DO NOT MODIFY THIS FILE!\n");
3490 	fprintf(fp, "#\n");
3491 	fprintf(fp, "# Created: %s", ctime(&current_time));
3492 	fprintf(fp, "########################################\n\n");
3493 
3494 
3495 	/* cache timeperiods */
3496 	for(i = 0; i < num_objects.timeperiods; i++)
3497 		fcache_timeperiod(fp, timeperiod_ary[i]);
3498 
3499 	/* cache commands */
3500 	for(i = 0; i < num_objects.commands; i++)
3501 		fcache_command(fp, command_ary[i]);
3502 
3503 	/* cache contactgroups */
3504 	for(i = 0; i < num_objects.contactgroups; i++)
3505 		fcache_contactgroup(fp, contactgroup_ary[i]);
3506 
3507 	/* cache hostgroups */
3508 	for(i = 0; i < num_objects.hostgroups; i++)
3509 		fcache_hostgroup(fp, hostgroup_ary[i]);
3510 
3511 	/* cache servicegroups */
3512 	for(i = 0; i < num_objects.servicegroups; i++)
3513 		fcache_servicegroup(fp, servicegroup_ary[i]);
3514 
3515 	/* cache contacts */
3516 	for(i = 0; i < num_objects.contacts; i++)
3517 		fcache_contact(fp, contact_ary[i]);
3518 
3519 	/* cache hosts */
3520 	for(i = 0; i < num_objects.hosts; i++)
3521 		fcache_host(fp, host_ary[i]);
3522 
3523 	/* cache services */
3524 	for(i = 0; i < num_objects.services; i++)
3525 		fcache_service(fp, service_ary[i]);
3526 
3527 	/* cache service dependencies */
3528 	for(i = 0; i < num_objects.servicedependencies; i++)
3529 		fcache_servicedependency(fp, servicedependency_ary[i]);
3530 
3531 	/* cache service escalations */
3532 	for(i = 0; i < num_objects.serviceescalations; i++)
3533 		fcache_serviceescalation(fp, serviceescalation_ary[i]);
3534 
3535 	/* cache host dependencies */
3536 	for(i = 0; i < num_objects.hostdependencies; i++)
3537 		fcache_hostdependency(fp, hostdependency_ary[i]);
3538 
3539 	/* cache host escalations */
3540 	for(i = 0; i < num_objects.hostescalations; i++)
3541 		fcache_hostescalation(fp, hostescalation_ary[i]);
3542 
3543 	fclose(fp);
3544 
3545 	return OK;
3546 	}
3547 #endif
3548