>From 973ae3a9c51e7d1ee5eb5acab8087c20b1900f5a Mon Sep 17 00:00:00 2001
From: Michael Friedrich <michael.friedrich@univie.ac.at>
Date: Sat, 30 Apr 2011 13:50:28 +0200
Subject: [PATCH 3/4] move thread safe macro function prototypes with suffix _r and restore old compatible prototypes again

the current source makes the macro logic thread safe.
within common/macros.c several function prototypes have
been changed and new nagios_macros* mac argument is
required. if a (neb) module uses such internal functions
and expected the old version, the empty macro object will
cause the core to run into SIGSEGV.

the proposed solution for backwards compatibility is to
rename the changed thread safe functions from *_macro()
to *_macro_r() and add the previous function prototypes
again. those make an internal call to macro_r() passing
&global_macros as an argument.
the core and cgi references have been replaced to use the
internal thread safe implementation.

this has been implemented and tested with mod_gearman and
mklivestatus, *do and merlin currently don't use the macro
logic in their respective neb module.

after a future release of Nagios, the default functions might
get deprecated and only the *_macro_r() announced as mandatory.
---
 base/checks.c                   |   36 +++---
 base/logging.c                  |   24 ++--
 base/notifications.c            |   20 ++--
 base/sehandlers.c               |   26 +++---
 base/utils.c                    |    8 +-
 cgi/config.c                    |    4 +-
 cgi/extinfo.c                   |    8 +-
 cgi/status.c                    |   14 ++--
 cgi/statusmap.c                 |    2 +-
 common/macros.c                 |  228 +++++++++++++++++++++++++++------------
 include/macros.h                |  104 ++++++++++++------
 t-tap/.gitignore                |    3 +
 t-tap/smallconfig/objects.cache |    2 +-
 t-tap/test-stubs.c              |   12 +-
 xdata/xpddefault.c              |   26 +++---
 15 files changed, 327 insertions(+), 190 deletions(-)

diff --git a/base/checks.c b/base/checks.c
index b0fc968..f39fd95 100644
--- a/base/checks.c
+++ b/base/checks.c
@@ -418,13 +418,13 @@ int run_async_service_check(service *svc, int check_options, double latency, int
 
 	/* grab the host and service macro variables */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, temp_host);
-	grab_service_macros(&mac, svc);
+	grab_host_macros_r(&mac, temp_host);
+	grab_service_macros_r(&mac, svc);
 
 	/* get the raw command line */
 	get_raw_command_line_r(&mac, svc->check_command_ptr,svc->service_check_command,&raw_command,0);
 	if(raw_command==NULL){
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		log_debug_info(DEBUGL_CHECKS,0,"Raw check command for service '%s' on host '%s' was NULL - aborting.\n",svc->description,svc->host_name);
 		if(preferred_time)
 			*preferred_time+=(svc->check_interval*interval_length);
@@ -435,7 +435,7 @@ int run_async_service_check(service *svc, int check_options, double latency, int
 	/* process any macros contained in the argument */
 	process_macros_r(&mac, raw_command,&processed_command,0);
 	if(processed_command==NULL){
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		log_debug_info(DEBUGL_CHECKS,0,"Processed check command for service '%s' on host '%s' was NULL - aborting.\n",svc->description,svc->host_name);
 		if(preferred_time)
 			*preferred_time+=(svc->check_interval*interval_length);
@@ -472,7 +472,7 @@ int run_async_service_check(service *svc, int check_options, double latency, int
 
 	/* neb module wants to override the service check - perhaps it will check the service itself */
 	if(neb_result==NEBERROR_CALLBACKOVERRIDE){
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		svc->latency=old_latency;
 		my_free(processed_command);
 		my_free(raw_command);
@@ -660,7 +660,7 @@ int run_async_service_check(service *svc, int check_options, double latency, int
 	else if(pid==0){
 
 		/* set environment variables */
-		set_all_macro_environment_vars(&mac, TRUE);
+		set_all_macro_environment_vars_r(&mac, TRUE);
 
 		/* ADDED 11/12/07 EG */
 		/* close external command file and shut down worker thread */
@@ -846,7 +846,7 @@ int run_async_service_check(service *svc, int check_options, double latency, int
 		/* NOTE: this code is never reached if large install tweaks are enabled... */
 
 		/* unset environment variables */
-		set_all_macro_environment_vars(&mac, FALSE);
+		set_all_macro_environment_vars_r(&mac, FALSE);
 
 		/* free allocated memory */
 		/* this needs to be done last, so we don't free memory for variables before they're used above */
@@ -859,7 +859,7 @@ int run_async_service_check(service *svc, int check_options, double latency, int
 
 	/* else the parent should wait for the first child to return... */
 	else if(pid>0){
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 
 		log_debug_info(DEBUGL_CHECKS,2,"Service check is executing in child process (pid=%lu)\n",(unsigned long)pid);
 
@@ -2680,7 +2680,7 @@ int execute_sync_host_check_3x(host *hst)
 
 	/* grab the host macros */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, hst);
+	grab_host_macros_r(&mac, hst);
 
 	/* high resolution start time for event broker */
 	gettimeofday(&start_time,NULL);
@@ -2691,14 +2691,14 @@ int execute_sync_host_check_3x(host *hst)
 	/* get the raw command line */
 	get_raw_command_line_r(&mac, hst->check_command_ptr,hst->host_check_command,&raw_command,0);
 	if(raw_command==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
 	/* process any macros contained in the argument */
 	process_macros_r(&mac, raw_command,&processed_command,0);
 	if(processed_command==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 			
@@ -2719,7 +2719,7 @@ int execute_sync_host_check_3x(host *hst)
 
 	/* run the host check command */
 	result=my_system_r(&mac, processed_command,host_check_timeout,&early_timeout,&exectime,&temp_plugin_output,MAX_PLUGIN_OUTPUT_LENGTH);
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	/* if the check timed out, report an error */
 	if(early_timeout==TRUE){
@@ -2948,12 +2948,12 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc
 
 	/* grab the host macro variables */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, hst);
+	grab_host_macros_r(&mac, hst);
 
 	/* get the raw command line */
 	get_raw_command_line_r(&mac, hst->check_command_ptr,hst->host_check_command,&raw_command,0);
 	if(raw_command==NULL){
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		log_debug_info(DEBUGL_CHECKS,0,"Raw check command for host '%s' was NULL - aborting.\n",hst->name);
 		return ERROR;
 		}
@@ -2961,7 +2961,7 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc
 	/* process any macros contained in the argument */
 	process_macros_r(&mac, raw_command,&processed_command,0);
 	if(processed_command==NULL){
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		log_debug_info(DEBUGL_CHECKS,0,"Processed check command for host '%s' was NULL - aborting.\n",hst->name);
 		return ERROR;
 		}
@@ -3069,7 +3069,7 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc
 	else if(pid==0){
 
 		/* set environment variables */
-		set_all_macro_environment_vars(&mac, TRUE);
+		set_all_macro_environment_vars_r(&mac, TRUE);
 
 		/* ADDED 11/12/07 EG */
 		/* close external command file and shut down worker thread */
@@ -3177,7 +3177,7 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc
 		/* NOTE: this code is never reached if large install tweaks are enabled... */
 
 		/* unset environment variables */
-		set_all_macro_environment_vars(&mac, FALSE);
+		set_all_macro_environment_vars_r(&mac, FALSE);
 
 		/* free allocated memory */
 		/* this needs to be done last, so we don't free memory for variables before they're used above */
@@ -3190,7 +3190,7 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc
 
 	/* else the parent should wait for the first child to return... */
 	else if(pid>0){
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 
 		log_debug_info(DEBUGL_CHECKS,2,"Host check is executing in child process (pid=%lu)\n",(unsigned long)pid);
 
diff --git a/base/logging.c b/base/logging.c
index d0fea2b..de52d9e 100644
--- a/base/logging.c
+++ b/base/logging.c
@@ -273,14 +273,14 @@ int log_service_event(service *svc)
 
 	/* grab service macros */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, temp_host);
-	grab_service_macros(&mac, svc);
+	grab_host_macros_r(&mac, temp_host);
+	grab_service_macros_r(&mac, svc);
 
 	/* XXX: replace the macro madness with some simple helpers instead */
 	asprintf(&temp_buffer,"SERVICE ALERT: %s;%s;$SERVICESTATE$;$SERVICESTATETYPE$;$SERVICEATTEMPT$;%s\n",svc->host_name,svc->description,(svc->plugin_output==NULL)?"":svc->plugin_output);
 	process_macros_r(&mac, temp_buffer,&processed_buffer,0);
-	clear_host_macros(&mac);
-	clear_service_macros(&mac);
+	clear_host_macros_r(&mac);
+	clear_service_macros_r(&mac);
 
 	write_to_all_logs(processed_buffer,log_options);
 
@@ -301,7 +301,7 @@ int log_host_event(host *hst)
 
 	/* grab the host macros */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, hst);
+	grab_host_macros_r(&mac, hst);
 
 	/* get the log options */
 	if(hst->current_state==HOST_DOWN)
@@ -317,7 +317,7 @@ int log_host_event(host *hst)
 
 	write_to_all_logs(processed_buffer,log_options);
 
-	clear_host_macros(&mac);
+	clear_host_macros_r(&mac);
 	my_free(temp_buffer);
 	my_free(processed_buffer);
 
@@ -341,7 +341,7 @@ int log_host_states(int type, time_t *timestamp)
 	for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
 
 		/* grab the host macros */
-		grab_host_macros(&mac, temp_host);
+		grab_host_macros_r(&mac, temp_host);
 
 		/* XXX: macro madness */
 		asprintf(&temp_buffer,"%s HOST STATE: %s;$HOSTSTATE$;$HOSTSTATETYPE$;$HOSTATTEMPT$;%s\n",(type==INITIAL_STATES)?"INITIAL":"CURRENT",temp_host->name,(temp_host->plugin_output==NULL)?"":temp_host->plugin_output);
@@ -349,7 +349,7 @@ int log_host_states(int type, time_t *timestamp)
 		
 		write_to_all_logs_with_timestamp(processed_buffer,NSLOG_INFO_MESSAGE,timestamp);
 
-		clear_host_macros(&mac);
+		clear_host_macros_r(&mac);
 
 		my_free(temp_buffer);
 		my_free(processed_buffer);
@@ -380,8 +380,8 @@ int log_service_states(int type, time_t *timestamp)
 			continue;
 
 		/* grab service macros */
-		grab_host_macros(&mac, temp_host);
-		grab_service_macros(&mac, temp_service);
+		grab_host_macros_r(&mac, temp_host);
+		grab_service_macros_r(&mac, temp_service);
 
 		/* XXX: macro madness */
 		asprintf(&temp_buffer,"%s SERVICE STATE: %s;%s;$SERVICESTATE$;$SERVICESTATETYPE$;$SERVICEATTEMPT$;%s\n",(type==INITIAL_STATES)?"INITIAL":"CURRENT",temp_service->host_name,temp_service->description,temp_service->plugin_output);
@@ -389,8 +389,8 @@ int log_service_states(int type, time_t *timestamp)
 
 		write_to_all_logs_with_timestamp(processed_buffer,NSLOG_INFO_MESSAGE,timestamp);
 
-		clear_host_macros(&mac);
-		clear_service_macros(&mac);
+		clear_host_macros_r(&mac);
+		clear_service_macros_r(&mac);
 
 		my_free(temp_buffer);
 		my_free(processed_buffer);
diff --git a/base/notifications.c b/base/notifications.c
index 8ca5aec..b9b4298 100644
--- a/base/notifications.c
+++ b/base/notifications.c
@@ -130,8 +130,8 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat
 	if(notification_list!=NULL){
 
 		/* grab the macro variables */
-		grab_host_macros(mac, temp_host);
-		grab_service_macros(mac, svc);
+		grab_host_macros_r(mac, temp_host);
+		grab_service_macros_r(mac, svc);
 
 		/* if this notification has an author, attempt to lookup the associated contact */
 		if(not_author!=NULL){
@@ -217,10 +217,10 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat
 		for(temp_notification=notification_list;temp_notification!=NULL;temp_notification=temp_notification->next){
 
 			/* grab the macro variables for this contact */
-			grab_contact_macros(mac, temp_notification->contact);
+			grab_contact_macros_r(mac, temp_notification->contact);
 
 			/* clear summary macros (they are customized for each contact) */
-			clear_summary_macros(mac);
+			clear_summary_macros_r(mac);
 
 			/* notify this contact */
 			result=notify_contact_of_service(mac, temp_notification->contact,svc,type,not_author,not_data,options,escalated);
@@ -234,7 +234,7 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat
 		free_notification_list();
 
 		/* clear summary macros so they will be regenerated without contact filters when needed next */
-		clear_summary_macros(mac);
+		clear_summary_macros_r(mac);
 
 		if(type==NOTIFICATION_NORMAL){
 
@@ -1033,7 +1033,7 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int
 
 	/* clear volatile macros */
 	mac = get_global_macros();
-	clear_volatile_macros(mac);
+	clear_volatile_macros_r(mac);
 
 	log_debug_info(DEBUGL_NOTIFICATIONS,0,"Notification viability test passed.\n");
 
@@ -1070,7 +1070,7 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int
 	if(notification_list!=NULL){
 
 		/* grab the macro variables */
-		grab_host_macros(mac, hst);
+		grab_host_macros_r(mac, hst);
 
 		/* if this notification has an author, attempt to lookup the associated contact */
 		if(not_author!=NULL){
@@ -1156,10 +1156,10 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int
 		for(temp_notification=notification_list;temp_notification!=NULL;temp_notification=temp_notification->next){
 
 			/* grab the macro variables for this contact */
-			grab_contact_macros(mac, temp_notification->contact);
+			grab_contact_macros_r(mac, temp_notification->contact);
 
 			/* clear summary macros (they are customized for each contact) */
-			clear_summary_macros(mac);
+			clear_summary_macros_r(mac);
 
 			/* notify this contact */
 			result=notify_contact_of_host(mac, temp_notification->contact,hst,type,not_author,not_data,options,escalated);
@@ -1173,7 +1173,7 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int
 		free_notification_list();
 
 		/* clear summary macros so they will be regenerated without contact filters when needednext */
-		clear_summary_macros(mac);
+		clear_summary_macros_r(mac);
 
 		if(type==NOTIFICATION_NORMAL){
 
diff --git a/base/sehandlers.c b/base/sehandlers.c
index f038953..5616f58 100644
--- a/base/sehandlers.c
+++ b/base/sehandlers.c
@@ -101,13 +101,13 @@ int obsessive_compulsive_service_check_processor(service *svc)
 
 	/* update service macros */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, temp_host);
-	grab_service_macros(&mac, svc);
+	grab_host_macros_r(&mac, temp_host);
+	grab_service_macros_r(&mac, svc);
 
 	/* get the raw command line */
 	get_raw_command_line_r(&mac, ocsp_command_ptr,ocsp_command,&raw_command,macro_options);
 	if(raw_command==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -116,7 +116,7 @@ int obsessive_compulsive_service_check_processor(service *svc)
 	/* process any macros in the raw command line */
 	process_macros_r(&mac, raw_command,&processed_command,macro_options);
 	if(processed_command==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -125,7 +125,7 @@ int obsessive_compulsive_service_check_processor(service *svc)
 	/* run the command */
 	my_system_r(&mac, processed_command,ocsp_timeout,&early_timeout,&exectime,NULL,0);
 
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	/* check to see if the command timed out */
 	if(early_timeout==TRUE)
@@ -167,12 +167,12 @@ int obsessive_compulsive_host_check_processor(host *hst)
 
 	/* update macros */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, hst);
+	grab_host_macros_r(&mac, hst);
 
 	/* get the raw command line */
 	get_raw_command_line_r(&mac, ochp_command_ptr,ochp_command,&raw_command,macro_options);
 	if(raw_command==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -181,7 +181,7 @@ int obsessive_compulsive_host_check_processor(host *hst)
 	/* process any macros in the raw command line */
 	process_macros_r(&mac, raw_command,&processed_command,macro_options);
 	if(processed_command==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -189,7 +189,7 @@ int obsessive_compulsive_host_check_processor(host *hst)
 
 	/* run the command */
 	my_system_r(&mac, processed_command,ochp_timeout,&early_timeout,&exectime,NULL,0);
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	/* check to see if the command timed out */
 	if(early_timeout==TRUE)
@@ -238,8 +238,8 @@ int handle_service_event(service *svc)
 
 	/* update service macros */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, temp_host);
-	grab_service_macros(&mac, svc);
+	grab_host_macros_r(&mac, temp_host);
+	grab_service_macros_r(&mac, svc);
 
 	/* run the global service event handler */
 	run_global_service_event_handler(&mac, svc);
@@ -247,7 +247,7 @@ int handle_service_event(service *svc)
 	/* run the event handler command if there is one */
 	if(svc->event_handler!=NULL)
 		run_service_event_handler(&mac, svc);
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	/* check for external commands - the event handler may have given us some directives... */
 	check_for_external_commands();
@@ -492,7 +492,7 @@ int handle_host_event(host *hst)
 
 	/* update host macros */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, hst);
+	grab_host_macros_r(&mac, hst);
 
 	/* run the global host event handler */
 	run_global_host_event_handler(&mac, hst);
diff --git a/base/utils.c b/base/utils.c
index 62fb993..1a62d85 100644
--- a/base/utils.c
+++ b/base/utils.c
@@ -433,7 +433,7 @@ int my_system_r(nagios_macros *mac, char *cmd,int timeout,int *early_timeout,dou
 		setpgid(0,0);
 
 		/* set environment variables */
-		set_all_macro_environment_vars(mac, TRUE);
+		set_all_macro_environment_vars_r(mac, TRUE);
 
 		/* ADDED 11/12/07 EG */
 		/* close external command file and shut down worker thread */
@@ -544,7 +544,7 @@ int my_system_r(nagios_macros *mac, char *cmd,int timeout,int *early_timeout,dou
 		alarm(0);
 		
 		/* clear environment variables */
-		set_all_macro_environment_vars(mac, FALSE);
+		set_all_macro_environment_vars_r(mac, FALSE);
 
 #ifndef DONT_USE_MEMORY_PERFORMANCE_TWEAKS
 		/* free allocated memory */
@@ -692,7 +692,7 @@ int get_raw_command_line_r(nagios_macros *mac, command *cmd_ptr, char *cmd, char
 	log_debug_info(DEBUGL_FUNCTIONS,0,"get_raw_command_line_r()\n");
 
 	/* clear the argv macros */
-	clear_argv_macros(mac);
+	clear_argv_macros_r(mac);
 
 	/* make sure we've got all the requirements */
 	if(cmd_ptr==NULL || full_command==NULL)
@@ -4224,7 +4224,7 @@ void free_memory(nagios_macros *mac)
 	 * macros when we get a reload or restart request through the
 	 * command pipe, or when we receive a SIGHUP.
 	 */
-	clear_volatile_macros(mac);
+	clear_volatile_macros_r(mac);
 
 	free_macrox_names();
 
diff --git a/cgi/config.c b/cgi/config.c
index 3cd9e32..29ab0db 100644
--- a/cgi/config.c
+++ b/cgi/config.c
@@ -518,7 +518,7 @@ void display_hosts(void){
 	for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next) if (((*to_expand)=='\0')||!strcmp(to_expand,temp_host->name)){
 
 		/* grab macros */
-		grab_host_macros(mac, temp_host);
+		grab_host_macros_r(mac, temp_host);
 
 		if(odd){
 			odd=0;
@@ -1260,7 +1260,7 @@ void display_services(void){
 		if (((*to_expand)=='\0')||(!strcmp(to_expand,temp_service->host_name))||(!strcmp(to_expand,temp_service->description))){
 
 		/* grab macros */
-		grab_service_macros(mac, temp_service);
+		grab_service_macros_r(mac, temp_service);
 
 		if(odd){
 			odd=0;
diff --git a/cgi/extinfo.c b/cgi/extinfo.c
index a84390d..4a2d684 100644
--- a/cgi/extinfo.c
+++ b/cgi/extinfo.c
@@ -231,11 +231,11 @@ int main(void){
 		if(display_type==DISPLAY_HOST_INFO || display_type==DISPLAY_SERVICE_INFO){
 
 			temp_host=find_host(host_name);
-			grab_host_macros(mac, temp_host);
+			grab_host_macros_r(mac, temp_host);
 
 			if(display_type==DISPLAY_SERVICE_INFO){
 				temp_service=find_service(host_name,service_desc);
-				grab_service_macros(mac, temp_service);
+				grab_service_macros_r(mac, temp_service);
 				}
 
 			/* write some Javascript helper functions */
@@ -259,13 +259,13 @@ int main(void){
 		/* find the hostgroup */
 		else if(display_type==DISPLAY_HOSTGROUP_INFO){
 			temp_hostgroup=find_hostgroup(hostgroup_name);
-			grab_hostgroup_macros(mac, temp_hostgroup);
+			grab_hostgroup_macros_r(mac, temp_hostgroup);
 			}
 
 		/* find the servicegroup */
 		else if(display_type==DISPLAY_SERVICEGROUP_INFO){
 			temp_servicegroup=find_servicegroup(servicegroup_name);
-			grab_servicegroup_macros(mac, temp_servicegroup);
+			grab_servicegroup_macros_r(mac, temp_servicegroup);
 			}
 
 		if((display_type==DISPLAY_HOST_INFO && temp_host!=NULL) || (display_type==DISPLAY_SERVICE_INFO && temp_host!=NULL && temp_service!=NULL) || (display_type==DISPLAY_HOSTGROUP_INFO && temp_hostgroup!=NULL) || (display_type==DISPLAY_SERVICEGROUP_INFO && temp_servicegroup!=NULL)){
diff --git a/cgi/status.c b/cgi/status.c
index ea99674..10cb643 100644
--- a/cgi/status.c
+++ b/cgi/status.c
@@ -1559,7 +1559,7 @@ void show_service_detail(void){
 			if(new_host==TRUE){
 
 				/* grab macros */
-				grab_host_macros(mac, temp_host);
+				grab_host_macros_r(mac, temp_host);
 
 				if(temp_hoststatus->status==HOST_DOWN){
 					if(temp_hoststatus->problem_has_been_acknowledged==TRUE)
@@ -1659,7 +1659,7 @@ void show_service_detail(void){
 			printf("</TD>\n");
 
 			/* grab macros */
-			grab_service_macros(mac, temp_service);
+			grab_service_macros_r(mac, temp_service);
 
 			/* service name column */
 			printf("<TD CLASS='status%s'>",status_bg_class);
@@ -2021,7 +2021,7 @@ void show_host_detail(void){
 		total_entries++;
 
 		/* grab macros */
-		grab_host_macros(mac, temp_host);
+		grab_host_macros_r(mac, temp_host);
 
 
 		if(display_type==DISPLAY_HOSTGROUPS){
@@ -3229,7 +3229,7 @@ void show_servicegroup_grid(servicegroup *temp_servicegroup){
 		printf("<TD CLASS='status%s'>",host_status_class);
 
 		/* grab macros */
-		grab_host_macros(mac, temp_host);
+		grab_host_macros_r(mac, temp_host);
 
 		printf("<A HREF='%s?type=%d&host=%s'>\n",EXTINFO_CGI,DISPLAY_HOST_INFO,url_encode(temp_host->name));
 		printf("<IMG SRC='%s%s' BORDER=0 WIDTH=%d HEIGHT=%d ALT='%s' TITLE='%s'>",url_images_path,DETAIL_ICON,STATUS_ICON_WIDTH,STATUS_ICON_HEIGHT,"View Extended Information For This Host","View Extended Information For This Host");
@@ -3482,7 +3482,7 @@ void show_servicegroup_hostgroup_member_overview(hoststatus *hststatus,int odd,v
 	temp_host=find_host(hststatus->host_name);
 
 	/* grab macros */
-	grab_host_macros(mac, temp_host);
+	grab_host_macros_r(mac, temp_host);
 
 	if(hststatus->status==HOST_PENDING){
 		strncpy(status,"PENDING",sizeof(status));
@@ -4352,7 +4352,7 @@ void show_hostgroup_grid(hostgroup *temp_hostgroup){
 			continue;
 
 		/* grab macros */
-		grab_host_macros(mac, temp_host);
+		grab_host_macros_r(mac, temp_host);
 
 		/* find the host status */
 		temp_hoststatus=find_hoststatus(temp_host->name);
@@ -4432,7 +4432,7 @@ void show_hostgroup_grid(hostgroup *temp_hostgroup){
 			        }
 
 			/* grab macros */
-			grab_service_macros(mac, temp_service);
+			grab_service_macros_r(mac, temp_service);
 
 			/* get the status of the service */
 			temp_servicestatus=find_servicestatus(temp_service->host_name,temp_service->description);
diff --git a/cgi/statusmap.c b/cgi/statusmap.c
index bb2d988..76be4eb 100644
--- a/cgi/statusmap.c
+++ b/cgi/statusmap.c
@@ -1934,7 +1934,7 @@ void write_host_popup_text(host *hst){
 	        }
 
 	/* grab macros */
-	grab_host_macros(mac, hst);
+	grab_host_macros_r(mac, hst);
 
 	/* strip nasty stuff from plugin output */
 	sanitize_plugin_output(temp_status->plugin_output);
diff --git a/common/macros.c b/common/macros.c
index a8da521..d19b4b1 100644
--- a/common/macros.c
+++ b/common/macros.c
@@ -157,7 +157,7 @@ int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffe
 			clean_options=0;
 
 			/* grab the macro value */
-			result=grab_macro_value(mac, temp_buffer,&selected_macro,&clean_options,&free_macro);
+			result=grab_macro_value_r(mac, temp_buffer,&selected_macro,&clean_options,&free_macro);
 			log_debug_info(DEBUGL_MACROS,2,"  Processed '%s', Clean Options: %d, Free: %d\n",temp_buffer,clean_options,free_macro);
 
 			/* an error occurred - we couldn't parse the macro, so continue on */
@@ -261,11 +261,11 @@ int process_macros(char *input_buffer, char **output_buffer, int options)
 /******************************************************************/
 
 /* grab macros that are specific to a particular host */
-int grab_host_macros(nagios_macros *mac, host *hst)
+int grab_host_macros_r(nagios_macros *mac, host *hst)
 {
 	/* clear host-related macros */
-	clear_host_macros(mac);
-	clear_hostgroup_macros(mac);
+	clear_host_macros_r(mac);
+	clear_hostgroup_macros_r(mac);
 
 	/* save pointer to host */
 	mac->host_ptr=hst;
@@ -283,12 +283,16 @@ int grab_host_macros(nagios_macros *mac, host *hst)
 	return OK;
 }
 
+int grab_host_macros(host *hst){
+        return grab_host_macros_r(&global_macros, hst);
+}
+
 
 /* grab hostgroup macros */
-int grab_hostgroup_macros(nagios_macros *mac, hostgroup *hg)
+int grab_hostgroup_macros_r(nagios_macros *mac, hostgroup *hg)
 {
 	/* clear hostgroup macros */
-	clear_hostgroup_macros(mac);
+	clear_hostgroup_macros_r(mac);
 
 	/* save the hostgroup pointer for later */
 	mac->hostgroup_ptr=hg;
@@ -299,14 +303,18 @@ int grab_hostgroup_macros(nagios_macros *mac, hostgroup *hg)
 	return OK;
 }
 
+int grab_hostgroup_macros(hostgroup *hg){
+        return grab_hostgroup_macros_r(&global_macros, hg);
+}
+
 
 /* grab macros that are specific to a particular service */
-int grab_service_macros(nagios_macros *mac, service *svc)
+int grab_service_macros_r(nagios_macros *mac, service *svc)
 {
 
 	/* clear service-related macros */
-	clear_service_macros(mac);
-	clear_servicegroup_macros(mac);
+	clear_service_macros_r(mac);
+	clear_servicegroup_macros_r(mac);
 
 	/* save pointer for later */
 	mac->service_ptr=svc;
@@ -324,13 +332,16 @@ int grab_service_macros(nagios_macros *mac, service *svc)
 	return OK;
 }
 
+int grab_service_macros(service *svc){
+	return grab_service_macros_r(&global_macros, svc);
+}
 
 
 /* grab macros that are specific to a particular servicegroup */
-int grab_servicegroup_macros(nagios_macros *mac, servicegroup *sg)
+int grab_servicegroup_macros_r(nagios_macros *mac, servicegroup *sg)
 {
 	/* clear servicegroup macros */
-	clear_servicegroup_macros(mac);
+	clear_servicegroup_macros_r(mac);
 
 	/* save the pointer for later */
 	mac->servicegroup_ptr=sg;
@@ -341,14 +352,17 @@ int grab_servicegroup_macros(nagios_macros *mac, servicegroup *sg)
 	return OK;
 }
 
+int grab_servicegroup_macros(servicegroup *sg){
+        return grab_servicegroup_macros_r(&global_macros, sg);
+}
 
 
 /* grab macros that are specific to a particular contact */
-int grab_contact_macros(nagios_macros *mac, contact *cntct)
+int grab_contact_macros_r(nagios_macros *mac, contact *cntct)
 {
 	/* clear contact-related macros */
-	clear_contact_macros(mac);
-	clear_contactgroup_macros(mac);
+	clear_contact_macros_r(mac);
+	clear_contactgroup_macros_r(mac);
 
 	/* save pointer to contact for later */
 	mac->contact_ptr=cntct;
@@ -366,6 +380,9 @@ int grab_contact_macros(nagios_macros *mac, contact *cntct)
 	return OK;
 }
 
+int grab_contact_macros(contact *cntct){
+        return grab_contact_macros_r(&global_macros, cntct);
+}
 
 
 /******************************************************************/
@@ -373,7 +390,7 @@ int grab_contact_macros(nagios_macros *mac, contact *cntct)
 /******************************************************************/
 
 /* this is the big one */
-int grab_macro_value(nagios_macros *mac, char *macro_buffer, char **output, int *clean_options, int *free_macro)
+int grab_macro_value_r(nagios_macros *mac, char *macro_buffer, char **output, int *clean_options, int *free_macro)
 {
 	char *buf=NULL;
 	char *ptr=NULL;
@@ -438,7 +455,7 @@ int grab_macro_value(nagios_macros *mac, char *macro_buffer, char **output, int
 			log_debug_info(DEBUGL_MACROS,2,"  macros[%d] (%s) match.\n",x,macro_x_names[x]);
 
 			/* get the macro value */
-			result=grab_macrox_value(mac, x,arg[0],arg[1],output,free_macro);
+			result=grab_macrox_value_r(mac, x,arg[0],arg[1],output,free_macro);
 
 			/* post-processing */
 			/* host/service output/perfdata and author/comment macros should get cleaned */
@@ -574,7 +591,7 @@ int grab_macro_value(nagios_macros *mac, char *macro_buffer, char **output, int
 	else if(macro_name[0]=='_'){
 
 		/* get the macro value */
-		result=grab_custom_macro_value(mac, macro_name,arg[0],arg[1],output);
+		result=grab_custom_macro_value_r(mac, macro_name,arg[0],arg[1],output);
 		}
 
 	/* no macro matched... */
@@ -588,10 +605,13 @@ int grab_macro_value(nagios_macros *mac, char *macro_buffer, char **output, int
 
 	return result;
 }
-	
+
+int grab_macro_value(char *macro_buffer, char **output, int *clean_options, int *free_macro){
+	return grab_macro_value_r(&global_macros, macro_buffer, output, clean_options, free_macro);
+}
 
 
-int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output, int *free_macro)
+int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output, int *free_macro)
 {
 	host *temp_host=NULL;
 	hostgroup *temp_hostgroup=NULL;
@@ -702,7 +722,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 				return ERROR;
 
 			/* get the host macro value */
-			result=grab_standard_host_macro(mac, macro_type,temp_host,output,free_macro);
+			result=grab_standard_host_macro_r(mac, macro_type,temp_host,output,free_macro);
 			}
 
 		/* a host macro with a hostgroup name and delimiter */
@@ -725,7 +745,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 #endif
 
 				/* get the macro value for this host */
-				grab_standard_host_macro(mac, macro_type,temp_host,&temp_buffer,&free_sub_macro);
+				grab_standard_host_macro_r(mac, macro_type,temp_host,&temp_buffer,&free_sub_macro);
 
 				if(temp_buffer==NULL)
 					continue;
@@ -769,7 +789,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 			}
 
 		/* get the hostgroup macro value */
-		result=grab_standard_hostgroup_macro(mac, macro_type,temp_hostgroup,output);
+		result=grab_standard_hostgroup_macro_r(mac, macro_type,temp_hostgroup,output);
 		break;
 
 		/******************/
@@ -823,7 +843,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 			if((temp_service=mac->service_ptr)==NULL)
 				return ERROR;
 
-			result=grab_standard_service_macro(mac, macro_type,temp_service,output,free_macro);
+			result=grab_standard_service_macro_r(mac, macro_type,temp_service,output,free_macro);
 			}
 
 		/* else and ondemand macro... */
@@ -838,7 +858,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 				if((temp_service=find_service(mac->host_ptr->name,arg2))){
 
 					/* get the service macro value */
-					result=grab_standard_service_macro(mac, macro_type,temp_service,output,free_macro);
+					result=grab_standard_service_macro_r(mac, macro_type,temp_service,output,free_macro);
 					}
 				}
 
@@ -846,7 +866,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 			else if((temp_service=find_service(arg1,arg2))){
 
 				/* get the service macro value */
-				result=grab_standard_service_macro(mac, macro_type,temp_service,output,free_macro);
+				result=grab_standard_service_macro_r(mac, macro_type,temp_service,output,free_macro);
 				}
 
 			/* else we have a service macro with a servicegroup name and a delimiter... */
@@ -869,7 +889,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 #endif
 
 					/* get the macro value for this service */
-					grab_standard_service_macro(mac, macro_type,temp_service,&temp_buffer,&free_sub_macro);
+					grab_standard_service_macro_r(mac, macro_type,temp_service,&temp_buffer,&free_sub_macro);
 
 					if(temp_buffer==NULL)
 						continue;
@@ -915,7 +935,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 			}
 
 		/* get the servicegroup macro value */
-		result=grab_standard_servicegroup_macro(mac, macro_type,temp_servicegroup,output);
+		result=grab_standard_servicegroup_macro_r(mac, macro_type,temp_servicegroup,output);
 		break;
 
 		/******************/
@@ -940,7 +960,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 				return ERROR;
 
 			/* get the contact macro value */
-			result=grab_standard_contact_macro(mac, macro_type,temp_contact,output);
+			result=grab_standard_contact_macro_r(mac, macro_type,temp_contact,output);
 			}
 
 		/* a contact macro with a contactgroup name and delimiter */
@@ -963,7 +983,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 #endif
 
 				/* get the macro value for this contact */
-				grab_standard_contact_macro(mac, macro_type,temp_contact,&temp_buffer);
+				grab_standard_contact_macro_r(mac, macro_type,temp_contact,&temp_buffer);
 
 				if(temp_buffer==NULL)
 					continue;
@@ -1034,7 +1054,7 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 	case MACRO_NEXTVALIDTIME:
 
 		/* calculate macros */
-		result=grab_datetime_macro(mac, macro_type,arg1,arg2,output);
+		result=grab_datetime_macro_r(mac, macro_type,arg1,arg2,output);
 		break;
 
 		/*****************/
@@ -1223,10 +1243,13 @@ int grab_macrox_value(nagios_macros *mac, int macro_type, char *arg1, char *arg2
 	return result;
 	}
 
+int grab_macrox_value(int macro_type, char *arg1, char *arg2, char **output, int *free_macro){
+        return grab_macrox_value_r(&global_macros, macro_type, arg1, arg2, output, free_macro);
+}
 
 
 /* calculates the value of a custom macro */
-int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, char *arg2, char **output){
+int grab_custom_macro_value_r(nagios_macros *mac, char *macro_name, char *arg1, char *arg2, char **output){
 	host *temp_host=NULL;
 	hostgroup *temp_hostgroup=NULL;
 	hostsmember *temp_hostsmember=NULL;
@@ -1260,7 +1283,7 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 				return ERROR;
 
 			/* get the host macro value */
-			result=grab_custom_object_macro(mac, macro_name+5,temp_host->custom_variables,output);
+			result=grab_custom_object_macro_r(mac, macro_name+5,temp_host->custom_variables,output);
 			}
 
 		/* a host macro with a hostgroup name and delimiter */
@@ -1282,7 +1305,7 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 #endif
 
 				/* get the macro value for this host */
-				grab_custom_macro_value(mac, macro_name,temp_host->name,NULL,&temp_buffer);
+				grab_custom_macro_value_r(mac, macro_name,temp_host->name,NULL,&temp_buffer);
 
 				if(temp_buffer==NULL)
 					continue;
@@ -1311,7 +1334,7 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 				return ERROR;
 
 			/* get the service macro value */
-			result=grab_custom_object_macro(mac, macro_name+8,temp_service->custom_variables,output);
+			result=grab_custom_object_macro_r(mac, macro_name+8,temp_service->custom_variables,output);
 			}
 
 		/* else and ondemand macro... */
@@ -1323,7 +1346,7 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 			if((temp_service=find_service((mac->host_ptr)?mac->host_ptr->name:NULL,arg2))){
 
 				/* get the service macro value */
-				result=grab_custom_object_macro(mac, macro_name+8,temp_service->custom_variables,output);
+				result=grab_custom_object_macro_r(mac, macro_name+8,temp_service->custom_variables,output);
 				}
 
 			/* else we have a service macro with a servicegroup name and a delimiter... */
@@ -1346,7 +1369,7 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 #endif
 
 					/* get the macro value for this service */
-					grab_custom_macro_value(mac, macro_name,temp_service->host_name,temp_service->description,&temp_buffer);
+					grab_custom_macro_value_r(mac, macro_name,temp_service->host_name,temp_service->description,&temp_buffer);
 
 					if(temp_buffer==NULL)
 						continue;
@@ -1383,7 +1406,7 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 				return ERROR;
 
 			/* get the contact macro value */
-			result=grab_custom_object_macro(mac, macro_name+8,temp_contact->custom_variables,output);
+			result=grab_custom_object_macro_r(mac, macro_name+8,temp_contact->custom_variables,output);
 			}
 
 		/* a contact macro with a contactgroup name and delimiter */
@@ -1406,7 +1429,7 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 #endif
 
 				/* get the macro value for this contact */
-				grab_custom_macro_value(mac, macro_name,temp_contact->name,NULL,&temp_buffer);
+				grab_custom_macro_value_r(mac, macro_name,temp_contact->name,NULL,&temp_buffer);
 
 				if(temp_buffer==NULL)
 					continue;
@@ -1431,10 +1454,13 @@ int grab_custom_macro_value(nagios_macros *mac, char *macro_name, char *arg1, ch
 	return result;
 	}
 
+int grab_custom_macro_value(char *macro_name, char *arg1, char *arg2, char **output){
+	return grab_custom_macro_value_r(&global_macros, macro_name, arg1, arg2, output);
+}
 
 
 /* calculates a date/time macro */
-int grab_datetime_macro(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output)
+int grab_datetime_macro_r(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output)
 {
 	time_t current_time=0L;
 	timeperiod *temp_timeperiod=NULL;
@@ -1526,10 +1552,13 @@ int grab_datetime_macro(nagios_macros *mac, int macro_type, char *arg1, char *ar
 	return OK;
 }
 
+int grab_datetime_macro(int macro_type, char *arg1, char *arg2, char **output){
+	return grab_datetime_macro_r(&global_macros, macro_type, arg1, arg2, output);
+}
 
 
 /* calculates a host macro */
-int grab_standard_host_macro(nagios_macros *mac, int macro_type, host *temp_host, char **output, int *free_macro)
+int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_host, char **output, int *free_macro)
 {
 	char *temp_buffer=NULL;
 #ifdef NSCORE
@@ -1814,10 +1843,13 @@ int grab_standard_host_macro(nagios_macros *mac, int macro_type, host *temp_host
 	return OK;
 }
 
+int grab_standard_host_macro(int macro_type, host *temp_host, char **output, int *free_macro){
+	return grab_standard_host_macro_r(&global_macros, macro_type, temp_host, output, free_macro);
+}
 
 
 /* computes a hostgroup macro */
-int grab_standard_hostgroup_macro(nagios_macros *mac, int macro_type, hostgroup *temp_hostgroup, char **output)
+int grab_standard_hostgroup_macro_r(nagios_macros *mac, int macro_type, hostgroup *temp_hostgroup, char **output)
 {
 	hostsmember *temp_hostsmember=NULL;
 	char *temp_buffer=NULL;
@@ -1907,10 +1939,13 @@ int grab_standard_hostgroup_macro(nagios_macros *mac, int macro_type, hostgroup
 	return OK;
 }
 
+int grab_standard_hostgroup_macro(int macro_type, hostgroup *temp_hostgroup, char **output){
+	return grab_standard_hostgroup_macro_r(&global_macros, macro_type, temp_hostgroup, output);
+}
 
 
 /* computes a service macro */
-int grab_standard_service_macro(nagios_macros *mac, int macro_type, service *temp_service, char **output, int *free_macro)
+int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *temp_service, char **output, int *free_macro)
 {
 	char *temp_buffer=NULL;
 #ifdef NSCORE
@@ -2144,10 +2179,13 @@ int grab_standard_service_macro(nagios_macros *mac, int macro_type, service *tem
 	return OK;
 }
 
+int grab_standard_service_macro(int macro_type, service *temp_service, char **output, int *free_macro){
+	return grab_standard_service_macro_r(&global_macros, macro_type, temp_service, output, free_macro);
+}
 
 
 /* computes a servicegroup macro */
-int grab_standard_servicegroup_macro(nagios_macros *mac, int macro_type, servicegroup *temp_servicegroup, char **output)
+int grab_standard_servicegroup_macro_r(nagios_macros *mac, int macro_type, servicegroup *temp_servicegroup, char **output)
 {
 	servicesmember *temp_servicesmember=NULL;
 	char *temp_buffer=NULL;
@@ -2236,10 +2274,13 @@ int grab_standard_servicegroup_macro(nagios_macros *mac, int macro_type, service
 	return OK;
 }
 
+int grab_standard_servicegroup_macro(int macro_type, servicegroup *temp_servicegroup, char **output){
+	return grab_standard_servicegroup_macro_r(&global_macros, macro_type, temp_servicegroup, output);
+}
 
 
 /* computes a contact macro */
-int grab_standard_contact_macro(nagios_macros *mac, int macro_type, contact *temp_contact, char **output)
+int grab_standard_contact_macro_r(nagios_macros *mac, int macro_type, contact *temp_contact, char **output)
 {
 #ifdef NSCORE
 	contactgroup *temp_contactgroup=NULL;
@@ -2294,6 +2335,9 @@ int grab_standard_contact_macro(nagios_macros *mac, int macro_type, contact *tem
 	return OK;
 	}
 
+int grab_standard_contact_macro(int macro_type, contact *temp_contact, char **output){
+	return grab_standard_contact_macro_r(&global_macros, macro_type, temp_contact, output);
+}
 
 
 /* computes a contact address macro */
@@ -2352,9 +2396,8 @@ int grab_standard_contactgroup_macro(int macro_type, contactgroup *temp_contactg
 }
 
 
-
 /* computes a custom object macro */
-int grab_custom_object_macro(nagios_macros *mac, char *macro_name, customvariablesmember *vars, char **output)
+int grab_custom_object_macro_r(nagios_macros *mac, char *macro_name, customvariablesmember *vars, char **output)
 {
 	customvariablesmember *temp_customvariablesmember=NULL;
 	int result=ERROR;
@@ -2379,6 +2422,9 @@ int grab_custom_object_macro(nagios_macros *mac, char *macro_name, customvariabl
 	return result;
 }
 
+int grab_custom_object_macro(char *macro_name, customvariablesmember *vars, char **output){
+	return grab_custom_object_macro_r(&global_macros, macro_name, vars, output);
+}
 
 
 /******************************************************************/
@@ -2507,7 +2553,7 @@ int init_macros(void)
 	 * from the command fifo. Otherwise a memset() would
 	 * have been better.
 	 */
-	clear_volatile_macros(&global_macros);
+	clear_volatile_macros_r(&global_macros);
 
 	/* backwards compatibility hack */
 	macro_x = global_macros.x;
@@ -2706,7 +2752,7 @@ int free_macrox_names(void){
 
 
 /* clear argv macros - used in commands */
-int clear_argv_macros(nagios_macros *mac)
+int clear_argv_macros_r(nagios_macros *mac)
 {
 	register int x=0;
 
@@ -2717,6 +2763,9 @@ int clear_argv_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_argv_macros(void){
+        return clear_argv_macros_r(&global_macros);
+}
 
 /*
  * copies non-volatile macros from global macro_x to **dest, which
@@ -2745,7 +2794,7 @@ void copy_constant_macros(char **dest)
 #undef cp_macro
 
 /* clear all macros that are not "constant" (i.e. they change throughout the course of monitoring) */
-int clear_volatile_macros(nagios_macros *mac)
+int clear_volatile_macros_r(nagios_macros *mac)
 {
 	customvariablesmember *this_customvariablesmember=NULL;
 	customvariablesmember *next_customvariablesmember=NULL;
@@ -2793,7 +2842,7 @@ int clear_volatile_macros(nagios_macros *mac)
 	my_free(mac->ondemand);
 
 	/* clear ARGx macros */
-	clear_argv_macros(mac);
+	clear_argv_macros_r(mac);
 
 	/* clear custom host variables */
 	for(this_customvariablesmember=mac->custom_host_vars;this_customvariablesmember!=NULL;this_customvariablesmember=next_customvariablesmember){
@@ -2826,9 +2875,13 @@ int clear_volatile_macros(nagios_macros *mac)
         }
 
 
+int clear_volatile_macros(void){
+	return clear_volatile_macros_r(&global_macros);
+}
+
 
 /* clear service macros */
-int clear_service_macros(nagios_macros *mac)
+int clear_service_macros_r(nagios_macros *mac)
 {
 	register int x;
 	customvariablesmember *this_customvariablesmember=NULL;
@@ -2894,9 +2947,13 @@ int clear_service_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_service_macros(void){
+        return clear_service_macros_r(&global_macros);
+}
+
 
 /* clear host macros */
-int clear_host_macros(nagios_macros *mac)
+int clear_host_macros_r(nagios_macros *mac)
 {
 	register int x;
 	customvariablesmember *this_customvariablesmember=NULL;
@@ -2967,9 +3024,13 @@ int clear_host_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_host_macros(void){
+        return clear_host_macros_r(&global_macros);
+}
+
 
 /* clear hostgroup macros */
-int clear_hostgroup_macros(nagios_macros *mac)
+int clear_hostgroup_macros_r(nagios_macros *mac)
 {
 	register int x;
 	
@@ -2994,9 +3055,13 @@ int clear_hostgroup_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_hostgroup_macros(void){
+        return clear_hostgroup_macros_r(&global_macros);
+}
+
 
 /* clear servicegroup macros */
-int clear_servicegroup_macros(nagios_macros *mac)
+int clear_servicegroup_macros_r(nagios_macros *mac)
 {
 	register int x;
 	
@@ -3021,9 +3086,13 @@ int clear_servicegroup_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_servicegroup_macros(void){
+        return clear_servicegroup_macros_r(&global_macros);
+}
+
 
 /* clear contact macros */
-int clear_contact_macros(nagios_macros *mac)
+int clear_contact_macros_r(nagios_macros *mac)
 {
 	register int x;
 	customvariablesmember *this_customvariablesmember=NULL;
@@ -3062,10 +3131,13 @@ int clear_contact_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_contact_macros(void){
+        return clear_contact_macros_r(&global_macros);
+}
 
 
 /* clear contactgroup macros */
-int clear_contactgroup_macros(nagios_macros *mac)
+int clear_contactgroup_macros_r(nagios_macros *mac)
 {
 	register int x;
 	
@@ -3087,10 +3159,13 @@ int clear_contactgroup_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_contactgroup_macros(void){
+        return clear_contactgroup_macros_r(&global_macros);
+}
 
 
 /* clear summary macros */
-int clear_summary_macros(nagios_macros *mac)
+int clear_summary_macros_r(nagios_macros *mac)
 {
 	register int x;
 
@@ -3100,6 +3175,9 @@ int clear_summary_macros(nagios_macros *mac)
 	return OK;
 }
 
+int clear_summary_macros(void){
+        return clear_summary_macros_r(&global_macros);
+}
 
 
 /******************************************************************/
@@ -3109,23 +3187,26 @@ int clear_summary_macros(nagios_macros *mac)
 #ifdef NSCORE
 
 /* sets or unsets all macro environment variables */
-int set_all_macro_environment_vars(nagios_macros *mac, int set)
+int set_all_macro_environment_vars_r(nagios_macros *mac, int set)
 {
 	if(enable_environment_macros==FALSE)
 		return ERROR;
 
-	set_macrox_environment_vars(mac, set);
-	set_argv_macro_environment_vars(mac, set);
-	set_custom_macro_environment_vars(mac, set);
-	set_contact_address_environment_vars(mac, set);
+	set_macrox_environment_vars_r(mac, set);
+	set_argv_macro_environment_vars_r(mac, set);
+	set_custom_macro_environment_vars_r(mac, set);
+	set_contact_address_environment_vars_r(mac, set);
 
 	return OK;
 }
 
+int set_all_macro_environment_vars(int set){
+	return set_all_macro_environment_vars_r(&global_macros, set);
+}
 
 
 /* sets or unsets macrox environment variables */
-int set_macrox_environment_vars(nagios_macros *mac, int set)
+int set_macrox_environment_vars_r(nagios_macros *mac, int set)
 {
 	register int x=0;
 	int free_macro=FALSE;
@@ -3147,7 +3228,7 @@ int set_macrox_environment_vars(nagios_macros *mac, int set)
 				generate_macro=FALSE;
 
 			if(mac->x[x]==NULL && generate_macro==TRUE)
-				grab_macrox_value(mac,x,NULL,NULL,&mac->x[x],&free_macro);
+				grab_macrox_value_r(mac,x,NULL,NULL,&mac->x[x],&free_macro);
 			}
 
 		/* set the value */
@@ -3157,10 +3238,13 @@ int set_macrox_environment_vars(nagios_macros *mac, int set)
 	return OK;
 }
 
+int set_macrox_environment_vars(int set){
+	return set_macrox_environment_vars_r(&global_macros, set);
+}
 
 
 /* sets or unsets argv macro environment variables */
-int set_argv_macro_environment_vars(nagios_macros *mac, int set)
+int set_argv_macro_environment_vars_r(nagios_macros *mac, int set)
 {
 	char *macro_name=NULL;
 	register int x=0;
@@ -3175,10 +3259,13 @@ int set_argv_macro_environment_vars(nagios_macros *mac, int set)
 	return OK;
 }
 
+int set_argv_macro_environment_vars(int set){
+	return set_argv_macro_environment_vars_r(&global_macros, set);
+}
 
 
 /* sets or unsets custom host/service/contact macro environment variables */
-int set_custom_macro_environment_vars(nagios_macros *mac, int set)
+int set_custom_macro_environment_vars_r(nagios_macros *mac, int set)
 {
 	customvariablesmember *temp_customvariablesmember=NULL;
 	host *temp_host=NULL;
@@ -3229,10 +3316,13 @@ int set_custom_macro_environment_vars(nagios_macros *mac, int set)
 	return OK;
 }
 
+int set_custom_macro_environment_vars(int set){
+	return set_custom_macro_environment_vars_r(&global_macros, set);
+}
 
 
 /* sets or unsets contact address environment variables */
-int set_contact_address_environment_vars(nagios_macros *mac, int set)
+int set_contact_address_environment_vars_r(nagios_macros *mac, int set)
 {
 	char *varname=NULL;
 	register int x;
@@ -3250,6 +3340,9 @@ int set_contact_address_environment_vars(nagios_macros *mac, int set)
 	return OK;
 }
 
+int set_contact_address_environment_vars(int set){
+	return set_contact_address_environment_vars_r(&global_macros, set);
+}
 
 
 /* sets or unsets a macro environment variable */
@@ -3273,4 +3366,5 @@ int set_macro_environment_var(char *name, char *value, int set)
 	return OK;
 }
 
+
 #endif
diff --git a/include/macros.h b/include/macros.h
index 0160535..b21eca5 100644
--- a/include/macros.h
+++ b/include/macros.h
@@ -246,11 +246,44 @@ char *clean_macro_chars(char *,int);
  * These functions updates **macros with the values from
  * their respective object type.
  */
-int grab_service_macros(nagios_macros *mac, service *);
-int grab_host_macros(nagios_macros *mac, host *);
-int grab_servicegroup_macros(nagios_macros *mac, servicegroup *);
-int grab_hostgroup_macros(nagios_macros *mac, hostgroup *);
-int grab_contact_macros(nagios_macros *mac, contact *);
+
+int grab_service_macros(service *);
+int grab_host_macros(host *);
+int grab_servicegroup_macros(servicegroup *);
+int grab_hostgroup_macros(hostgroup *);
+int grab_contact_macros(contact *);
+
+int grab_macro_value(char *,char **,int *,int *);
+int grab_macrox_value(int,char *,char *,char **,int *);
+int grab_custom_macro_value(char *,char *,char *,char **);
+int grab_datetime_macro(int,char *,char *,char **);
+int grab_standard_host_macro(int,host *,char **,int *);
+int grab_standard_hostgroup_macro(int,hostgroup *,char **);
+int grab_standard_service_macro(int,service *,char **,int *);
+int grab_standard_servicegroup_macro(int,servicegroup *,char **);
+int grab_standard_contact_macro(int,contact *,char **);
+int grab_contact_address_macro(int,contact *,char **);
+int grab_standard_contactgroup_macro(int,contactgroup *,char **);
+int grab_custom_object_macro(char *,customvariablesmember *,char **);
+
+/* thread-safe version of the above */
+int grab_service_macros_r(nagios_macros *mac, service *);
+int grab_host_macros_r(nagios_macros *mac, host *);
+int grab_servicegroup_macros_r(nagios_macros *mac, servicegroup *);
+int grab_hostgroup_macros_r(nagios_macros *mac, hostgroup *);
+int grab_contact_macros_r(nagios_macros *mac, contact *);
+
+int grab_macro_value_r(nagios_macros *mac, char *,char **,int *,int *);
+int grab_macrox_value_r(nagios_macros *mac, int,char *,char *,char **,int *);
+int grab_custom_macro_value_r(nagios_macros *mac, char *,char *,char *,char **);
+int grab_datetime_macro_r(nagios_macros *mac, int,char *,char *,char **);
+int grab_standard_host_macro_r(nagios_macros *mac, int,host *,char **,int *);
+int grab_standard_hostgroup_macro_r(nagios_macros *mac, int,hostgroup *,char **);
+int grab_standard_service_macro_r(nagios_macros *mac, int,service *,char **,int *);
+int grab_standard_servicegroup_macro_r(nagios_macros *mac, int,servicegroup *,char **);
+int grab_standard_contact_macro_r(nagios_macros *mac, int,contact *,char **);
+int grab_custom_object_macro_r(nagios_macros *mac, char *,customvariablesmember *,char **);
+
 
 char *get_url_encoded_string(char *);			/* URL encode a string */
 
@@ -260,37 +293,44 @@ int free_macrox_names(void);
 
 extern void copy_constant_macros(char **dest);
 
-int clear_argv_macros(nagios_macros *mac);
-int clear_volatile_macros(nagios_macros *mac);
-int clear_host_macros(nagios_macros *mac);
-int clear_service_macros(nagios_macros *mac);
-int clear_hostgroup_macros(nagios_macros *mac);
-int clear_servicegroup_macros(nagios_macros *mac);
-int clear_contact_macros(nagios_macros *mac);
-int clear_contactgroup_macros(nagios_macros *mac);
-int clear_summary_macros(nagios_macros *mac);
-
-int grab_macro_value(nagios_macros *mac, char *,char **,int *,int *);
-int grab_macrox_value(nagios_macros *mac, int,char *,char *,char **,int *);
-int grab_custom_macro_value(nagios_macros *mac, char *,char *,char *,char **);
-int grab_datetime_macro(nagios_macros *mac, int,char *,char *,char **);
-int grab_standard_host_macro(nagios_macros *mac, int,host *,char **,int *);
-int grab_standard_hostgroup_macro(nagios_macros *mac, int,hostgroup *,char **);
-int grab_standard_service_macro(nagios_macros *mac, int,service *,char **,int *);
-int grab_standard_servicegroup_macro(nagios_macros *mac, int,servicegroup *,char **);
-int grab_standard_contact_macro(nagios_macros *mac, int,contact *,char **);
-int grab_contact_address_macro(int,contact *,char **);
-int grab_standard_contactgroup_macro(int,contactgroup *,char **);
-int grab_custom_object_macro(nagios_macros *mac, char *,customvariablesmember *,char **);
+/* clear macros */
+int clear_argv_macros(void);
+int clear_volatile_macros(void);
+int clear_host_macros(void);
+int clear_service_macros(void);
+int clear_hostgroup_macros(void);
+int clear_servicegroup_macros(void);
+int clear_contact_macros(void);
+int clear_contactgroup_macros(void);
+int clear_summary_macros(void);
+
+/* thread-safe version of the above */
+int clear_argv_macros_r(nagios_macros *mac);
+int clear_volatile_macros_r(nagios_macros *mac);
+int clear_host_macros_r(nagios_macros *mac);
+int clear_service_macros_r(nagios_macros *mac);
+int clear_hostgroup_macros_r(nagios_macros *mac);
+int clear_servicegroup_macros_r(nagios_macros *mac);
+int clear_contact_macros_r(nagios_macros *mac);
+int clear_contactgroup_macros_r(nagios_macros *mac);
+int clear_summary_macros_r(nagios_macros *mac);
 
 
 #ifdef NSCORE
-int set_all_macro_environment_vars(nagios_macros *mac, int);
-int set_macrox_environment_vars(nagios_macros *mac, int);
-int set_argv_macro_environment_vars(nagios_macros *mac, int);
-int set_custom_macro_environment_vars(nagios_macros *mac, int);
-int set_contact_address_environment_vars(nagios_macros *mac, int);
+int set_all_macro_environment_vars(int);
+int set_macrox_environment_vars(int);
+int set_argv_macro_environment_vars(int);
+int set_custom_macro_environment_vars(int);
+int set_contact_address_environment_vars(int);
 int set_macro_environment_var(char *,char *,int);
+
+/* thread-safe version of the above */
+int set_all_macro_environment_vars_r(nagios_macros *mac, int);
+int set_macrox_environment_vars_r(nagios_macros *mac, int);
+int set_argv_macro_environment_vars_r(nagios_macros *mac, int);
+int set_custom_macro_environment_vars_r(nagios_macros *mac, int);
+int set_contact_address_environment_vars_r(nagios_macros *mac, int);
+
 #endif
 
 #endif
diff --git a/t-tap/.gitignore b/t-tap/.gitignore
index dd302ed..3c8db7f 100644
--- a/t-tap/.gitignore
+++ b/t-tap/.gitignore
@@ -4,4 +4,7 @@ test_checks
 test_nagios_config
 test_timeperiods
 test_xsddefault
+test_commands
+test_downtime
+test_strtoul
 *.dSYM
diff --git a/t-tap/smallconfig/objects.cache b/t-tap/smallconfig/objects.cache
index ddda905..7315960 100644
--- a/t-tap/smallconfig/objects.cache
+++ b/t-tap/smallconfig/objects.cache
@@ -4,7 +4,7 @@
 # THIS FILE IS AUTOMATICALLY GENERATED
 # BY NAGIOS.  DO NOT MODIFY THIS FILE!
 #
-# Created: Mon Mar 21 20:09:19 2011
+# Created: Sat Apr 30 13:46:36 2011
 ########################################
 
 define timeperiod {
diff --git a/t-tap/test-stubs.c b/t-tap/test-stubs.c
index d842bb2..3252fe4 100644
--- a/t-tap/test-stubs.c
+++ b/t-tap/test-stubs.c
@@ -117,15 +117,15 @@ int debug_level;
 int debug_verbosity;
 unsigned long max_debug_file_size;
 
-int grab_host_macros(nagios_macros *mac, host *hst) {}
+int grab_host_macros_r(nagios_macros *mac, host *hst) {}
 
-int grab_service_macros(nagios_macros *mac, service *svc) {}
+int grab_service_macros_r(nagios_macros *mac, service *svc) {}
 
 void broker_log_data(int a, int b, int c, char *d, unsigned long e, time_t f, struct timeval *g) {}
 
-int clear_volatile_macros(nagios_macros *mac) {}
-int clear_service_macros(nagios_macros *mac) {}
-int clear_host_macros(nagios_macros *mac) {}
+int clear_volatile_macros_r(nagios_macros *mac) {}
+int clear_service_macros_r(nagios_macros *mac) {}
+int clear_host_macros_r(nagios_macros *mac) {}
 
 int process_macros(char *a, char **b, int c) {}
 int process_macros_r(nagios_macros *mac, char *a, char **b, int c) {}
@@ -149,7 +149,7 @@ check_result    check_result_info;
 char *temp_path;
 int dbuf_init(dbuf *db, int chunk_size){}
 int update_check_stats(int check_type, time_t check_time){}
-int set_all_macro_environment_vars(nagios_macros *mac, int set){}
+int set_all_macro_environment_vars_r(nagios_macros *mac, int set){}
 int close_command_file(void){}
 void reset_sighandler(void){}
 void service_check_sighandler(int sig){}
diff --git a/xdata/xpddefault.c b/xdata/xpddefault.c
index 6d20a55..06cd3cb 100644
--- a/xdata/xpddefault.c
+++ b/xdata/xpddefault.c
@@ -398,20 +398,20 @@ int xpddefault_update_service_performance_data(service *svc)
 	 */
 	memset(&mac, 0, sizeof(mac));
 	hst = find_host(svc->host_name);
-	grab_host_macros(&mac, hst);
-	grab_service_macros(&mac, svc);
+	grab_host_macros_r(&mac, hst);
+	grab_service_macros_r(&mac, svc);
 
 	/* run the performance data command */
 	xpddefault_run_service_performance_data_command(&mac, svc);
 
 	/* get rid of used memory we won't need anymore */
-	clear_argv_macros(&mac);
+	clear_argv_macros_r(&mac);
 
 	/* update the performance data file */
 	xpddefault_update_service_performance_data_file(&mac, svc);
 
 	/* now free() it all */
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	return OK;
 }
@@ -437,19 +437,19 @@ int xpddefault_update_host_performance_data(host *hst)
 
 	/* set up macros and get to work */
 	memset(&mac, 0, sizeof(mac));
-	grab_host_macros(&mac, hst);
+	grab_host_macros_r(&mac, hst);
 
 	/* run the performance data command */
 	xpddefault_run_host_performance_data_command(&mac, hst);
 
 	/* no more commands to run, so we won't need this any more */
-	clear_argv_macros(&mac);
+	clear_argv_macros_r(&mac);
 
 	/* update the performance data file */
 	xpddefault_update_host_performance_data_file(&mac, hst);
 
 	/* free() all */
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	return OK;
 }
@@ -792,7 +792,7 @@ int xpddefault_process_host_perfdata_file(void)
 	/* get the raw command line */
 	get_raw_command_line_r(&mac, xpddefault_host_perfdata_file_processing_command_ptr,xpddefault_host_perfdata_file_processing_command,&raw_command_line,macro_options);
 	if(raw_command_line==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -801,7 +801,7 @@ int xpddefault_process_host_perfdata_file(void)
 	/* process any macros in the raw command line */
 	process_macros_r(&mac, raw_command_line,&processed_command_line,macro_options);
 	if(processed_command_line==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -813,7 +813,7 @@ int xpddefault_process_host_perfdata_file(void)
 
 	/* run the command */
 	my_system_r(&mac, processed_command_line,xpddefault_perfdata_timeout,&early_timeout,&exectime,NULL,0);
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	/* re-open and unlock the performance data file */
 	xpddefault_open_host_perfdata_file();
@@ -854,7 +854,7 @@ int xpddefault_process_service_perfdata_file(void){
 	/* get the raw command line */
 	get_raw_command_line_r(&mac, xpddefault_service_perfdata_file_processing_command_ptr,xpddefault_service_perfdata_file_processing_command,&raw_command_line,macro_options);
 	if(raw_command_line==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -863,7 +863,7 @@ int xpddefault_process_service_perfdata_file(void){
 	/* process any macros in the raw command line */
 	process_macros_r(&mac, raw_command_line,&processed_command_line,macro_options);
 	if(processed_command_line==NULL) {
-		clear_volatile_macros(&mac);
+		clear_volatile_macros_r(&mac);
 		return ERROR;
 	}
 
@@ -880,7 +880,7 @@ int xpddefault_process_service_perfdata_file(void){
 	xpddefault_open_service_perfdata_file();
 	pthread_mutex_unlock(&xpddefault_service_perfdata_fp_lock);
 
-	clear_volatile_macros(&mac);
+	clear_volatile_macros_r(&mac);
 
 	/* check to see if the command timed out */
 	if(early_timeout==TRUE)
-- 
1.7.1

