diff --git a/crm/admin/cibadmin.c b/crm/admin/cibadmin.c
index 560315c43b..15273b0978 100644
--- a/crm/admin/cibadmin.c
+++ b/crm/admin/cibadmin.c
@@ -1,564 +1,567 @@
-/* $Id: cibadmin.c,v 1.6 2004/09/14 05:54:42 andrew Exp $ */
+/* $Id: cibadmin.c,v 1.7 2004/09/17 13:03:09 andrew Exp $ */
 
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <sys/param.h>
 
 #include <crm/crm.h>
 
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <hb_api.h>
 #include <clplumbing/uids.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/ctrl.h>
 #include <crm/common/ipc.h>
 
 #include <crm/cib.h>
 
 #include <getopt.h>
 #include <ha_msg.h> /* someone complaining about _ha_msg_mod not being found */
 #include <crm/dmalloc_wrapper.h>
 
 
 GMainLoop *mainloop = NULL;
 const char *crm_system_name = "cibadmin";
 IPC_Channel *crmd_channel = NULL;
 char *admin_uuid = NULL;
 
 void usage(const char *cmd, int exit_status);
 ll_cluster_t *do_init(void);
 int do_work(ll_cluster_t * hb_cluster, const char *xml_text);
 
 gboolean admin_msg_callback(IPC_Channel * source_data, void *private_data);
 xmlNodePtr handleCibMod(const char *xml);
 
 
 gboolean BE_VERBOSE = FALSE;
 int expected_responses = 1;
 
 gboolean DO_HEALTH       = FALSE;
 
 const char *cib_action = NULL;
 xmlNodePtr msg_options = NULL;
 
 typedef struct str_list_s
 {
 		int num_items;
 		char *value;
 		struct str_list_s *next;
 } str_list_t;
 
 const char *verbose = XML_BOOLEAN_FALSE;
 char *id = NULL;
 char *this_msg_reference = NULL;
 char *obj_type = NULL;
 char *clear = NULL;
 char *status = NULL;
 char *migrate_from = NULL;
 char *migrate_res = NULL;
 char *subtype = NULL;
 char *reset = NULL;
 
 int operation_status = 0;
 const char *sys_to = NULL;;
 
 #define OPTARGS	"V?i:o:QDSUCEX:"
 
 int
 main(int argc, char **argv)
 {
 	int option_index = 0;
 	int argerr = 0;
 	int flag;
 	ll_cluster_t *hb_cluster = NULL;
 	int level = 0;
 	char *xml_text = NULL;
 	
 	static struct option long_options[] = {
 		/* Top-level Options */
 		{CRM_OP_ERASE,   0, 0, 'E'},
 		{CRM_OP_QUERY,   0, 0, 'Q'},
 		{CRM_OP_CREATE,  0, 0, 'C'},
 		{CRM_OP_REPLACE, 0, 0, 'R'},
 		{CRM_OP_STORE,   0, 0, 'S'},
 		{CRM_OP_UPDATE,  0, 0, 'U'},
 		{CRM_OP_DELETE,  0, 0, 'D'},
 		{"xml",          1, 0, 'X'},
 		{"verbose",      0, 0, 'V'},
 		{"help",         0, 0, '?'},
 		{"reference",    1, 0, 0},
 
 		/* common options */
 		{XML_ATTR_ID, 1, 0, 'i'},
 		{"obj_type", 1, 0, 'o'},
 
 		{0, 0, 0, 0}
 	};
 
 	if(argc < 2) {
 		usage(crm_system_name, LSB_EXIT_EINVAL);
 	}
 
 	/* Redirect messages from glib functions to our handler */
 	g_log_set_handler(NULL,
 			  G_LOG_LEVEL_ERROR      | G_LOG_LEVEL_CRITICAL
 			  | G_LOG_LEVEL_WARNING  | G_LOG_LEVEL_MESSAGE
 			  | G_LOG_LEVEL_INFO     | G_LOG_LEVEL_DEBUG
 			  | G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL,
 			  cl_glib_msg_handler, NULL);
 	/* and for good measure... */
 	g_log_set_always_fatal((GLogLevelFlags)0);    
 	
 	cl_log_set_entity(crm_system_name);
 	cl_log_set_facility(LOG_USER);
 
 	while (1) {
 		flag = getopt_long(argc, argv, OPTARGS,
 				   long_options, &option_index);
 		if (flag == -1)
 			break;
 
 		switch(flag) {
 			case 0:
 				printf("option %s",
 				       long_options[option_index].name);
 				if (optarg)
 					printf(" with arg %s", optarg);
 				printf("\n");
 			
 	if ((safe_str_eq(CRM_OP_ERASE,      long_options[option_index].name))
 	    || (safe_str_eq(CRM_OP_CREATE,  long_options[option_index].name))
 	    || (safe_str_eq(CRM_OP_UPDATE,  long_options[option_index].name))
 	    || (safe_str_eq(CRM_OP_DELETE,  long_options[option_index].name))
 	    || (safe_str_eq(CRM_OP_REPLACE, long_options[option_index].name))
 	    || (safe_str_eq(CRM_OP_STORE,   long_options[option_index].name))
 	    || (safe_str_eq(CRM_OP_QUERY,   long_options[option_index].name))){
 		cib_action = crm_strdup(long_options[option_index].name);
 					
 	} else if (safe_str_eq("reference", long_options[option_index].name)) {
 		this_msg_reference = crm_strdup(optarg);
 
 	} else {
 		printf("Long option (--%s) is not (yet?) properly supported\n",
 		       long_options[option_index].name);
 		++argerr;
 	}
 	break;
 			
 /* a sample test for multiple instance
    if (digit_optind != 0 && digit_optind != this_option_optind)
    printf ("digits occur in two different argv-elements.\n");
    digit_optind = this_option_optind;
    printf ("option %c\n", c);
 */
 				
 			case 'E':
 				cib_action = crm_strdup(CRM_OP_ERASE);
 				break;
 			case 'Q':
 				cib_action = crm_strdup(CRM_OP_QUERY);
 				break;
 			case 'U':
 				cib_action = crm_strdup(CRM_OP_UPDATE);
 				break;
 			case 'R':
 				cib_action = crm_strdup(CRM_OP_REPLACE);
 				break;
 			case 'S':
 				cib_action = crm_strdup(CRM_OP_STORE);
 				break;
 			case 'C':
 				cib_action = crm_strdup(CRM_OP_CREATE);
 				break;
 			case 'D':
 				cib_action = crm_strdup(CRM_OP_DELETE);
 				break;
 			case 'V':
 				level = get_crm_log_level();
 				BE_VERBOSE = TRUE;
 				verbose = XML_BOOLEAN_TRUE;
 				cl_log_enable_stderr(TRUE);
 				set_crm_log_level(level+1);
 				break;
 			case '?':
 				usage(crm_system_name, LSB_EXIT_OK);
 				break;
 			case 'i':
 				crm_verbose("Option %c => %s", flag, optarg);
 				id = crm_strdup(optarg);
 				break;
 			case 'o':
 				crm_verbose("Option %c => %s", flag, optarg);
 				obj_type = crm_strdup(optarg);
 				break;
 			case 'X':
 				xml_text = crm_strdup(optarg);
 				break;
 			default:
 				printf("Argument code 0%o (%c)"
 				       " is not (?yet?) supported\n",
 				       flag, flag);
 				++argerr;
 				break;
 		}
 	}
 
 	if (optind < argc) {
 		printf("non-option ARGV-elements: ");
 		while (optind < argc)
 			printf("%s ", argv[optind++]);
 		printf("\n");
 	}
 
 	if (optind > argc) {
 		++argerr;
 	}
 
 	if (argerr) {
 		usage(crm_system_name, LSB_EXIT_GENERIC);
 	}
 
 	hb_cluster = do_init();
 	if (hb_cluster != NULL) {
 		if (do_work(hb_cluster, xml_text) > 0) {
 			/* wait for the reply by creating a mainloop and running it until
 			 * the callbacks are invoked...
 			 */
 			mainloop = g_main_new(FALSE);
 			crm_info("%s waiting for reply from the local CRM",
 				 crm_system_name);
 
 			g_main_run(mainloop);
 			return_to_orig_privs();
 		} else {
 			crm_err("No message to send");
 			operation_status = -1;
 		}
 	} else {
 		crm_err("Init failed, could not perform requested operations");
 		operation_status = -2;
 	}
 
 	crm_debug("%s exiting normally", crm_system_name);
 	return operation_status;
 }
 
 xmlNodePtr
 handleCibMod(const char *xml)
 {
 	const char *attr_name = NULL;
 	const char *attr_value = NULL;
 	xmlNodePtr fragment = NULL;
 	xmlNodePtr cib_object = NULL;
 
 	if(xml == NULL) {
 		cib_object = file2xml(stdin);
 	} else {
 		cib_object = string2xml(xml);
 	}
 	
 	
 	if(cib_object == NULL) {
 		return NULL;
 	}
 	
 	attr_name = XML_ATTR_ID;
 	
 	attr_value = xmlGetProp(cib_object, attr_name);
 	if(attr_name == NULL || strlen(attr_name) == 0) {
 		crm_err("No value for %s specified.", attr_name);
 		return NULL;
 	}
 	
 	crm_trace("Object creation complete");
 
 	/* create the cib request */
 	fragment = create_cib_fragment(cib_object, NULL);
 
 	set_xml_property_copy(msg_options, XML_ATTR_OP, cib_action);
 
 	return fragment;
 }
 
 
 int
 do_work(ll_cluster_t * hb_cluster, const char *xml_text)
 {
 	/* construct the request */
 	xmlNodePtr msg_data = NULL;
 	const char *dest_node = NULL;
 	gboolean all_is_good = TRUE;
 	char *obj_type_parent = NULL;
 	
 	msg_options = create_xml_node(NULL, XML_TAG_OPTIONS);
 	set_xml_property_copy(msg_options, XML_ATTR_VERBOSE, verbose);
 	set_xml_property_copy(msg_options, XML_ATTR_TIMEOUT, "0");
 
 	if(strcmp(CRM_OP_QUERY, cib_action) == 0) {
 		crm_debug("Querying the CIB");
 		obj_type_parent = pluralSection(obj_type);
 		
 		crm_verbose("Querying the CIB for section: %s",
 			    obj_type_parent);
 		
 		set_xml_property_copy(msg_options, XML_ATTR_OP, CRM_OP_QUERY);
 
 		if(obj_type_parent != NULL) {
 			set_xml_property_copy(
 				msg_options,
 				XML_ATTR_FILTER_TYPE, obj_type_parent);
 		}
 		if(id != NULL) {
 			set_xml_property_copy(
 				msg_options, XML_ATTR_FILTER_ID, id);
 		}
 		
 		dest_node = status;
 		crm_verbose("CIB query creation %s",
 			    msg_data == NULL ? "failed." : "passed.");
 		
 		sys_to = CRM_SYSTEM_DCIB;
 		
 	} else if (strcmp(CRM_OP_ERASE, cib_action) == 0) {
 		set_xml_property_copy(msg_options,
 				      XML_ATTR_OP,
 				      CRM_OP_ERASE);
 		
 		dest_node = status;
 		crm_trace("CIB Erase op in progress");
 		
 		sys_to = CRM_SYSTEM_DCIB;
 		
 	} else if(cib_action != NULL) {
 		msg_data = handleCibMod(xml_text);
 		sys_to = CRM_SYSTEM_DCIB;
 		if(msg_data == NULL)
 			all_is_good = FALSE;
 		
 	} else {
 		crm_err("Unknown options");
 		all_is_good = FALSE;
 	}
 	
 	if(all_is_good == FALSE) {
 		crm_err("Creation of request failed.  No message to send");
 		return -1;
 	}
 
 /* send it */
 	if (crmd_channel == NULL) {
 		crm_err("The IPC connection is not valid, cannot send anything");
 		return -1;
 	}
 
 	if(sys_to == NULL) {
 		if (dest_node != NULL)
 			sys_to = CRM_SYSTEM_CRMD;
 		else
 			sys_to = CRM_SYSTEM_DC;				
 	}
 		
 	send_ipc_request(
 		crmd_channel, msg_options, msg_data,
 		dest_node, sys_to,
 		crm_system_name, admin_uuid, this_msg_reference);
 
 	return 1;
 
 }
 
 ll_cluster_t *
 do_init(void)
 {
 	int facility;
 	ll_cluster_t *hb_cluster = NULL;
 
 	/* docs say only do this once, but in their code they do it every time! */
 	xmlInitParser (); 
 
 	/* change the logging facility to the one used by heartbeat daemon */
 	hb_cluster = ll_cluster_new("heartbeat");
 	
 	crm_info("Switching to Heartbeat logger");
 	if (( facility =
 	      hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) {
 		cl_log_set_facility(facility);
 	}
 
-	admin_uuid = crm_malloc(sizeof(char) * 11);
-	snprintf(admin_uuid, 10, "%d", getpid());
-	admin_uuid[10] = '\0';
-
+	crm_malloc(admin_uuid, sizeof(char) * 11);
+	if(admin_uuid != NULL) {
+		snprintf(admin_uuid, 10, "%d", getpid());
+		admin_uuid[10] = '\0';
+	}
+	
 	crmd_channel =
 		init_client_ipc_comms(CRM_SYSTEM_CRMD,admin_msg_callback,NULL);
 
 	if(crmd_channel != NULL) {
 		send_hello_message(crmd_channel,
-				   admin_uuid,
-				   crm_system_name,
-				   "0",
-				   "1");
+				   admin_uuid, crm_system_name,
+				   "0", "1");
 
 		return hb_cluster;
 	} 
 	return NULL;
 }
 
 
 gboolean
 admin_msg_callback(IPC_Channel * server, void *private_data)
 {
 	int lpc = 0;
 	IPC_Message *msg = NULL;
 	gboolean hack_return_good = TRUE;
 	static int received_responses = 0;
 	char *filename;
 	int filename_len = 0;
 	const char *result = NULL;
 	xmlNodePtr options = NULL;
 	xmlNodePtr xml_root_node = NULL;
 	char *buffer = NULL;
 
-	
-
 	while (server->ch_status != IPC_DISCONNECT
 	       && server->ops->is_message_pending(server) == TRUE) {
 		if (server->ops->recv(server, &msg) != IPC_OK) {
 			perror("Receive failure:");
 			return !hack_return_good;
 		}
 
 		if (msg == NULL) {
 			crm_trace("No message this time");
 			continue;
 		}
 
 		lpc++;
 		buffer =(char *) msg->msg_body;
 		crm_verbose("Got xml [text=%s]", buffer);
 
 		xml_root_node = find_xml_in_ipcmessage(msg, TRUE);
 
 		if (xml_root_node == NULL) {
 			crm_info(
 			       "XML in IPC message was not valid... "
 			       "discarding.");
 			continue;
 		} else if (validate_crm_message(xml_root_node,
 					 crm_system_name,
 					 admin_uuid,
 					 "response") == FALSE) {
 			crm_info(
 			       "Message was not a CRM response. Discarding.");
 			continue;
 		}
 
 		options = find_xml_node(xml_root_node, XML_TAG_OPTIONS);
 		
 		result = xmlGetProp(options, XML_ATTR_RESULT);
 		if(result == NULL || strcmp(result, "ok") == 0) {
 			result = "pass";
 		} else {
 			result = "fail";
 		}
 		
 		received_responses++;
 		crm_xml_devel(xml_root_node, cib_action);
 
+		dump_xml_formatted(xml_root_node);
+		fprintf(stderr, "%s", crm_str(buffer));
+		crm_free(buffer);
+
 		if (this_msg_reference != NULL) {
 			/* in testing mode... */
 			/* 31 = "test-_.xml" + an_int_as_string + '\0' */
 			filename_len = 31 + strlen(this_msg_reference);
 
-			filename = crm_malloc(sizeof(char) * filename_len);
-			sprintf(filename, "%s-%s_%d.xml",
-				result,
-				this_msg_reference,
-				received_responses);
-			
-			filename[filename_len - 1] = '\0';
-			if (xmlSaveFormatFile(
-				    filename, xml_root_node->doc, 1) < 0) {
-				crm_crit("Could not save response %s_%s_%d.xml",
-					 this_msg_reference,
-					 result,
-					 received_responses);
+			crm_malloc(filename, sizeof(char) * filename_len);
+			if(filename != NULL) {
+				sprintf(filename, "%s-%s_%d.xml",
+					result, this_msg_reference,
+					received_responses);
+				
+				filename[filename_len - 1] = '\0';
+				if (xmlSaveFormatFile(
+					    filename, xml_root_node->doc, 1) < 0) {
+					crm_crit("Could not save response to"
+						 " %s_%s_%d.xml",
+						 this_msg_reference,
+						 result, received_responses);
+				}
 			}
 		}
 	}
 
 	if (server->ch_status == IPC_DISCONNECT) {
 		crm_info("admin_msg_callback: received HUP");
 		return !hack_return_good;
 	}
 
 	if (received_responses >= expected_responses) {
 		crm_info(
 		       "Recieved expected number (%d) of messages from Heartbeat."
 		       "  Exiting normally.", expected_responses);
 		g_main_quit(mainloop);
 		return !hack_return_good;
 	}
 	return hack_return_good;
 }
 
 
 void
 usage(const char *cmd, int exit_status)
 {
 	FILE *stream;
 
 	stream = exit_status ? stderr : stdout;
 
 	fprintf(stream, "usage: %s [-?Vio] command\n"
 		"\twhere necessary, XML data will be expected using -X"
 		" or on STDIN if -X isnt specified\n", cmd);
 
 	fprintf(stream, "Options\n");
 	fprintf(stream, "\t--%s (-%c) <id>\tid of the object being operated on\n",
 		XML_ATTR_ID, 'i');
 	fprintf(stream, "\t--%s (-%c) <type>\tobject type being operated on\n",
 		"obj_type", 'o');
 	fprintf(stream, "\t--%s (-%c)\tturn on debug info."
 		"  additional instance increase verbosity\n", "verbose", 'V');
 	fprintf(stream, "\t--%s (-%c)\tthis help message\n", "help", '?');
 	fprintf(stream, "\nCommands\n");
 	fprintf(stream, "\t--%s (-%c)\t\n", CRM_OP_ERASE, 'E');
 	fprintf(stream, "\t--%s (-%c)\t\n", CRM_OP_QUERY, 'Q');
 	fprintf(stream, "\t--%s (-%c)\t\n", CRM_OP_CREATE, 'C');
 	fprintf(stream, "\t--%s (-%c)\t\n", CRM_OP_REPLACE, 'R');
 	fprintf(stream, "\t--%s (-%c)\t\n", CRM_OP_STORE, 'S');
 	fprintf(stream, "\t--%s (-%c)\t\n", CRM_OP_UPDATE, 'U');
 	fprintf(stream, "\t--%s (-%c)\t\n", CRM_OP_DELETE, 'D');
 	fprintf(stream, "\nXML data\n");
 	fprintf(stream, "\t--%s (-%c) <string>\t\n", "xml", 'X');
 
 	fflush(stream);
 
 	exit(exit_status);
 }
diff --git a/crm/admin/crmadmin.c b/crm/admin/crmadmin.c
index ab254f9df5..b60e422af7 100644
--- a/crm/admin/crmadmin.c
+++ b/crm/admin/crmadmin.c
@@ -1,775 +1,778 @@
-/* $Id: crmadmin.c,v 1.6 2004/09/14 05:54:42 andrew Exp $ */
+/* $Id: crmadmin.c,v 1.7 2004/09/17 13:03:09 andrew Exp $ */
 
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <sys/param.h>
 
 #include <crm/crm.h>
 
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
 
 #include <hb_api.h>
 #include <clplumbing/uids.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/ctrl.h>
 #include <crm/common/ipc.h>
 
 #include <crm/cib.h>
 
 #include <getopt.h>
 #include <crm/dmalloc_wrapper.h>
 
 GMainLoop *mainloop = NULL;
 IPC_Channel *crmd_channel = NULL;
 char *admin_uuid = NULL;
 
 void usage(const char *cmd, int exit_status);
 ll_cluster_t *do_init(void);
 int do_work(ll_cluster_t * hb_cluster);
 
 gboolean admin_msg_callback(IPC_Channel * source_data, void *private_data);
 char *pluralSection(const char *a_section);
 xmlNodePtr handleCibMod(void);
 int do_find_resource(const char *rsc, xmlNodePtr xml_node);
 int do_find_resource_list(xmlNodePtr xml_node);
 int do_find_node_list(xmlNodePtr xml_node);
 
 enum debug {
 	debug_none,
 	debug_dec,
 	debug_inc
 };
 
 gboolean BE_VERBOSE = FALSE;
 int expected_responses = 1;
 
 gboolean DO_HEALTH        = FALSE;
 gboolean DO_RESET         = FALSE;
 gboolean DO_RESOURCE      = FALSE;
 gboolean DO_ELECT_DC      = FALSE;
 gboolean DO_WHOIS_DC      = FALSE;
 gboolean DO_NODE_LIST     = FALSE;
 gboolean BE_SILENT        = FALSE;
 gboolean DO_RESOURCE_LIST = FALSE;
 enum debug DO_DEBUG       = debug_none;
 
 xmlNodePtr msg_options = NULL;
 
 const char *verbose = XML_BOOLEAN_FALSE;
 char *id = NULL;
 char *this_msg_reference = NULL;
 char *disconnect = NULL;
 char *dest_node  = NULL;
 char *rsc_name   = NULL;
 
 int operation_status = 0;
 const char *sys_to = NULL;;
 const char *crm_system_name = "crmadmin";
 
 #define OPTARGS	"V?K:S:HE:DW:d:i:RNs"
 
 int
 main(int argc, char **argv)
 {
 	int option_index = 0;
 	int argerr = 0;
 	int flag;
 	ll_cluster_t *hb_cluster = NULL;
 	int level = 0;
 
 	static struct option long_options[] = {
 		/* Top-level Options */
 		{"verbose", 0, 0, 'V'},
 		{"help", 0, 0, '?'},
 		{"silent", 0, 0, 's'},
 		{"reference", 1, 0, 0},
 
 		/* daemon options */
 		{"kill", 1, 0, 'K'},  /* stop a node */
 		{"crm_debug_inc", 1, 0, 'i'},
 		{"crm_debug_dec", 1, 0, 'd'},
 		{"status", 1, 0, 'S'},
 		{"health", 0, 0, 'H'},
 		{"election", 0, 0, 'E'},
 		{"dc_lookup", 0, 0, 'D'},
 		{"resources", 0, 0, 'R'},
 		{"nodes", 0, 0, 'N'},
 		{"whereis", 1, 0, 'W'},
 
 		{0, 0, 0, 0}
 	};
 
 	/* Redirect messages from glib functions to our handler */
 	g_log_set_handler(NULL,
 			  G_LOG_LEVEL_ERROR      | G_LOG_LEVEL_CRITICAL
 			  | G_LOG_LEVEL_WARNING  | G_LOG_LEVEL_MESSAGE
 			  | G_LOG_LEVEL_INFO     | G_LOG_LEVEL_DEBUG
 			  | G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL,
 			  cl_glib_msg_handler, NULL);
 	/* and for good measure... */
 	g_log_set_always_fatal((GLogLevelFlags)0);    
 	
 	crm_system_name = basename(argv[0]);
 	cl_log_set_entity(crm_system_name);
 	cl_log_set_facility(LOG_USER);
 
 	if(argc < 2) {
 		usage(crm_system_name, LSB_EXIT_EINVAL);
 	}
 	
 	while (1) {
 		flag = getopt_long(argc, argv, OPTARGS,
 				   long_options, &option_index);
 		if (flag == -1)
 			break;
 
 		switch(flag) {
 			case 0:
 				printf("option %s", long_options[option_index].name);
 				if (optarg)
 					printf(" with arg %s", optarg);
 				printf("\n");
 			
 				if (strcmp("reference",
 					   long_options[option_index].name) == 0) {
 					this_msg_reference =
 						crm_strdup(optarg);
 
 				} else {
 					printf( "?? Long option (--%s) is not yet properly supported ??\n",
 						long_options[option_index].name);
 					++argerr;
 				}
 				break;
 			
 /* a sample test for multiple instance
    if (digit_optind != 0 && digit_optind != this_option_optind)
    printf ("digits occur in two different argv-elements.\n");
    digit_optind = this_option_optind;
    printf ("option %c\n", c);
 */
 			
 			case 'V':
 				level = get_crm_log_level();
 				BE_VERBOSE = TRUE;
 				verbose = XML_BOOLEAN_TRUE;
 				cl_log_enable_stderr(TRUE);
 				set_crm_log_level(level+1);
 				break;
 			case '?':
 				usage(crm_system_name, LSB_EXIT_OK);
 				break;
 			case 'D':
 				DO_WHOIS_DC = TRUE;
 				break;
 			case 'W':
 				DO_RESOURCE = TRUE;
 				crm_verbose("Option %c => %s", flag, optarg);
 				rsc_name = crm_strdup(optarg);
 				break;
 			case 'K':
 				DO_RESET = TRUE;
 				crm_verbose("Option %c => %s", flag, optarg);
 				dest_node = crm_strdup(optarg);
 				break;
 			case 's':
 				BE_SILENT = TRUE;
 				break;
 			case 'i':
 				DO_DEBUG = debug_inc;
 				crm_verbose("Option %c => %s", flag, optarg);
 				dest_node = crm_strdup(optarg);
 				break;
 			case 'd':
 				DO_DEBUG = debug_dec;
 				crm_verbose("Option %c => %s", flag, optarg);
 				dest_node = crm_strdup(optarg);
 				break;
 			case 'S':
 				DO_HEALTH = TRUE;
 				crm_verbose("Option %c => %s", flag, optarg);
 				dest_node = crm_strdup(optarg);
 				break;
 			case 'E':
 				DO_ELECT_DC = TRUE;
 				break;
 			case 'N':
 				DO_NODE_LIST = TRUE;
 				break;
 			case 'R':
 				DO_RESOURCE_LIST = TRUE;
 				break;
 			case 'H':
 				DO_HEALTH = TRUE;
 				break;
 			default:
 				printf("Argument code 0%o (%c) is not (?yet?) supported\n", flag, flag);
 				++argerr;
 				break;
 		}
 	}
 
 	if (optind < argc) {
 		printf("non-option ARGV-elements: ");
 		while (optind < argc)
 			printf("%s ", argv[optind++]);
 		printf("\n");
 	}
 
 	if (optind > argc) {
 		++argerr;
 	}
 
 	if (argerr) {
 		usage(crm_system_name, LSB_EXIT_GENERIC);
 	}
 
 	hb_cluster = do_init();
 	if (hb_cluster != NULL) {
 		int res = do_work(hb_cluster);
 		if (res > 0) {
 			/* wait for the reply by creating a mainloop and running it until
 			 * the callbacks are invoked...
 			 */
 			mainloop = g_main_new(FALSE);
 			crm_verbose("%s waiting for reply from the local CRM",
 				 crm_system_name);
 
 			g_main_run(mainloop);
 			return_to_orig_privs();
 			
 		} else if(res == 0) {
 			crm_verbose("%s: no reply expected",
 				 crm_system_name);
 			
 		} else {
 			crm_err("No message to send");
 			operation_status = -1;
 		}
 	} else {
 		crm_err("Init failed, could not perform requested operations");
 		operation_status = -2;
 	}
 
 	crm_verbose("%s exiting normally", crm_system_name);
 	return operation_status;
 }
 
 
 
 int
 do_work(ll_cluster_t * hb_cluster)
 {
 	int ret = 1;
 	/* construct the request */
 	xmlNodePtr msg_data = NULL;
 	gboolean all_is_good = TRUE;
 	
 	msg_options = create_xml_node(NULL, XML_TAG_OPTIONS);
 	set_xml_property_copy(msg_options, XML_ATTR_VERBOSE, verbose);
 	set_xml_property_copy(msg_options, XML_ATTR_TIMEOUT, "0");
 
 	if (DO_HEALTH == TRUE) {
 		crm_verbose("Querying the system");
 		
 		sys_to = CRM_SYSTEM_DC;
 		
 		if (dest_node != NULL) {
 			sys_to = CRM_SYSTEM_CRMD;
 			if (BE_VERBOSE) {
 				expected_responses = -1;/* wait until timeout instead */
 			}
 			
 			set_xml_property_copy(
 				msg_options, XML_ATTR_OP, CRM_OP_PING);
 			
 			set_xml_property_copy(
 				msg_options, XML_ATTR_TIMEOUT, "0");
 
 		} else {
 			crm_info("Cluster-wide health not available yet");
 			all_is_good = FALSE;
 		}
 		
 	} else if(DO_ELECT_DC) {
 		/* tell the local node to initiate an election */
 
 		sys_to = CRM_SYSTEM_CRMD;
 
 		set_xml_property_copy(
 			msg_options, XML_ATTR_OP, CRM_OP_VOTE);
 		
 		set_xml_property_copy(
 			msg_options, XML_ATTR_TIMEOUT, "0");
 		
 		dest_node = NULL;
 
 		ret = 0; /* no return message */
 		
 	} else if(DO_WHOIS_DC) {
 		sys_to = CRM_SYSTEM_DC;
 
 		set_xml_property_copy(
 			msg_options, XML_ATTR_OP, CRM_OP_PING);
 			
 		set_xml_property_copy(
 			msg_options, XML_ATTR_TIMEOUT, "0");
 
 		dest_node = NULL;
 		
 		
 	} else if(DO_RESOURCE) {
 		set_xml_property_copy(msg_options, XML_ATTR_OP, CRM_OP_QUERY);
 		set_xml_property_copy(
 			msg_options, XML_ATTR_FILTER_TYPE, XML_CIB_TAG_STATUS);
 		
 		sys_to = CRM_SYSTEM_CIB;
 
 	} else if(DO_RESOURCE_LIST) {
 		set_xml_property_copy(msg_options, XML_ATTR_OP, CRM_OP_QUERY);
 		set_xml_property_copy(
 			msg_options, XML_ATTR_FILTER_TYPE, XML_CIB_TAG_RESOURCES);
 		
 		sys_to = CRM_SYSTEM_CIB;
 
 	} else if(DO_NODE_LIST) {
 		set_xml_property_copy(msg_options, XML_ATTR_OP, CRM_OP_QUERY);
 		set_xml_property_copy(
 			msg_options, XML_ATTR_FILTER_TYPE, XML_CIB_TAG_NODES);
 		
 		sys_to = CRM_SYSTEM_CIB;
 
 	} else if(DO_RESET) {
 		/* tell dest_node to initiate the shutdown proceedure
 		 *
 		 * if dest_node is NULL, the request will be sent to the
 		 *   local node
 		 */
 		sys_to = CRM_SYSTEM_CRMD;
 
 		set_xml_property_copy(
 			msg_options, XML_ATTR_OP, "init_shutdown");
 		
 		set_xml_property_copy(
 			msg_options, XML_ATTR_TIMEOUT, "0");
 		
 		ret = 0; /* no return message */
 		
 	} else if(DO_DEBUG == debug_inc) {
 		/* tell dest_node to increase its debug level
 		 *
 		 * if dest_node is NULL, the request will be sent to the
 		 *   local node
 		 */
 		sys_to = CRM_SYSTEM_CRMD;
 
 		set_xml_property_copy(msg_options, XML_ATTR_OP, "debug_inc");
 		set_xml_property_copy(msg_options, XML_ATTR_TIMEOUT, "0");
 		
 		ret = 0; /* no return message */
 		
 	} else if(DO_DEBUG == debug_dec) {
 		/* tell dest_node to increase its debug level
 		 *
 		 * if dest_node is NULL, the request will be sent to the
 		 *   local node
 		 */
 		sys_to = CRM_SYSTEM_CRMD;
 
 		set_xml_property_copy(msg_options, XML_ATTR_OP, "debug_dec");
 		set_xml_property_copy(msg_options, XML_ATTR_TIMEOUT, "0");
 		
 		ret = 0; /* no return message */
 		
 	} else {
 		crm_err("Unknown options");
 		all_is_good = FALSE;
 	}
 	
 
 	if(all_is_good == FALSE) {
 		crm_err("Creation of request failed.  No message to send");
 		return -1;
 	}
 
 /* send it */
 	if (crmd_channel == NULL) {
 		crm_err("The IPC connection is not valid, cannot send anything");
 		return -1;
 	}
 
 	if(sys_to == NULL) {
 		if (dest_node != NULL)
 			sys_to = CRM_SYSTEM_CRMD;
 		else
 			sys_to = CRM_SYSTEM_DC;				
 	}
 		
 	send_ipc_request(crmd_channel,
 			 msg_options,
 			 msg_data,
 			 dest_node, sys_to,
 			 crm_system_name,
 			 admin_uuid,
 			 this_msg_reference);
 
 	return ret;
 
 }
 
 
 ll_cluster_t *
 do_init(void)
 {
 	int facility;
 	ll_cluster_t *hb_cluster = NULL;
 
 	/* docs say only do this once, but in their code they do it every time! */
 	xmlInitParser (); 
 
 	/* change the logging facility to the one used by heartbeat daemon */
 	hb_cluster = ll_cluster_new("heartbeat");
 	
 	crm_verbose("Switching to Heartbeat logger");
 	if (( facility =
 	      hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) {
 		cl_log_set_facility(facility);
 	}
 
-	admin_uuid = crm_malloc(sizeof(char) * 11);
-	snprintf(admin_uuid, 10, "%d", getpid());
-	admin_uuid[10] = '\0';
-
+	crm_malloc(admin_uuid, sizeof(char) * 11);
+	if(admin_uuid != NULL) {
+		snprintf(admin_uuid, 10, "%d", getpid());
+		admin_uuid[10] = '\0';
+	}
+	
 	crmd_channel = init_client_ipc_comms(
 		CRM_SYSTEM_CRMD, admin_msg_callback, NULL);
 
 	if(crmd_channel != NULL) {
 		send_hello_message(
 			crmd_channel, admin_uuid, crm_system_name,"0", "1");
 
 		return hb_cluster;
 	} 
 	return NULL;
 }
 
 gboolean
 admin_msg_callback(IPC_Channel * server, void *private_data)
 {
 	int lpc = 0;
 	IPC_Message *msg = NULL;
 	gboolean hack_return_good = TRUE;
 	static int received_responses = 0;
 	char *filename;
 	int filename_len = 0;
 	const char *result = NULL;
 	xmlNodePtr options = NULL;
 	xmlNodePtr xml_root_node = NULL;
 	char *buffer = NULL;
 
 	while (server->ch_status != IPC_DISCONNECT
 	       && server->ops->is_message_pending(server) == TRUE) {
 		if (server->ops->recv(server, &msg) != IPC_OK) {
 			perror("Receive failure:");
 			return !hack_return_good;
 		}
 
 		if (msg == NULL) {
 			crm_trace("No message this time");
 			continue;
 		}
 
 		lpc++;
 		buffer =(char *) msg->msg_body;
 		crm_verbose("Got xml [text=%s]", buffer);
 
 		xml_root_node = find_xml_in_ipcmessage(msg, TRUE);
 
 		if (xml_root_node == NULL) {
 			crm_info(
 			       "XML in IPC message was not valid... "
 			       "discarding.");
 			continue;
 		} else if (validate_crm_message(xml_root_node,
 					 crm_system_name,
 					 admin_uuid,
 					 "response") == FALSE) {
 			crm_info(
 			       "Message was not a CRM response. Discarding.");
 			continue;
 		}
 
 		options = find_xml_node(xml_root_node, XML_TAG_OPTIONS);
 		
 		result = xmlGetProp(options, XML_ATTR_RESULT);
 		if(result == NULL || strcmp(result, "ok") == 0) {
 			result = "pass";
 		} else {
 			result = "fail";
 		}
 		
 		received_responses++;
 
 		if(DO_HEALTH) {
 			xmlNodePtr ping = find_xml_node(
 				xml_root_node, XML_CRM_TAG_PING);
 
 			const char *state = xmlGetProp(ping, "crmd_state");
 
 			printf("Status of %s@%s: %s (%s)\n",
 			       xmlGetProp(ping, XML_PING_ATTR_SYSFROM),
 			       xmlGetProp(xml_root_node, XML_ATTR_HOSTFROM),
 			       state,
 			       xmlGetProp(ping, XML_PING_ATTR_STATUS));
 			
 			if(BE_SILENT && state != NULL) {
 				fprintf(stderr, "%s\n", state);
 			}
 			
 		} else if(DO_RESOURCE) {
 			do_find_resource(rsc_name, xml_root_node);
 			
 		} else if(DO_RESOURCE_LIST) {
 			do_find_resource_list(xml_root_node);
 
 		} else if(DO_NODE_LIST) {
 			do_find_node_list(xml_root_node);
 
 		} else if(DO_WHOIS_DC) {
 			const char *dc = xmlGetProp(
 				xml_root_node, XML_ATTR_HOSTFROM);
 			
 			printf("Designated Controller is: %s\n", dc);
 			if(BE_SILENT && dc != NULL) {
 				fprintf(stderr, "%s\n", dc);
 			}
 		}
 		
 		if (this_msg_reference != NULL) {
 			/* in testing mode... */
 			/* 31 = "test-_.xml" + an_int_as_string + '\0' */
 			filename_len = 31 + strlen(this_msg_reference);
 
-			filename = crm_malloc(sizeof(char) * filename_len);
-			sprintf(filename, "%s-%s_%d.xml",
-				result,
-				this_msg_reference,
-				received_responses);
-			
-			filename[filename_len - 1] = '\0';
-			if (xmlSaveFormatFile(filename,
-					      xml_root_node->doc, 1) < 0) {
-				crm_crit("Could not save response %s_%s_%d.xml",
-					 this_msg_reference,
-					 result,
-					 received_responses);
+			crm_malloc(filename, sizeof(char) * filename_len);
+			if(filename != NULL) {
+				sprintf(filename, "%s-%s_%d.xml",
+					result, this_msg_reference,
+					received_responses);
+				
+				filename[filename_len - 1] = '\0';
+				if (xmlSaveFormatFile(
+					    filename, xml_root_node->doc, 1) < 0) {
+					crm_crit("Could not save response to"
+						 " %s_%s_%d.xml",
+						 this_msg_reference,
+						 result, received_responses);
+				}
 			}
 		}
 	}
 
 	if (server->ch_status == IPC_DISCONNECT) {
 		crm_verbose("admin_msg_callback: received HUP");
 		return !hack_return_good;
 	}
 
 	if (received_responses >= expected_responses) {
 		crm_verbose(
 		       "Recieved expected number (%d) of messages from Heartbeat."
 		       "  Exiting normally.", expected_responses);
 		g_main_quit(mainloop);
 		return !hack_return_good;
 	}
 	return hack_return_good;
 }
 
 int
 do_find_resource(const char *rsc, xmlNodePtr xml_node)
 {
 	int found = 0;
 	const char *path[] = {
 		XML_TAG_FRAGMENT,
 		XML_TAG_CIB,
 		XML_CIB_TAG_STATUS,
 		XML_CIB_TAG_STATE
 	};
 	const char *path2[] = {
 		XML_CIB_TAG_LRM,
 		XML_LRM_TAG_RESOURCES,
 		XML_LRM_TAG_RESOURCE
 	};
 	xmlNodePtr nodestates = find_xml_node_nested(
 		xml_node, path, DIMOF(path));
 
 	while(nodestates != NULL) {
 		xmlNodePtr rscstates = find_xml_node_nested(
 			nodestates, path2, DIMOF(path2));
 		nodestates = nodestates->next;
 
 		
 		while(rscstates != NULL) {
 			const char *id = xmlGetProp(rscstates,XML_ATTR_ID);
 			const char *target =
 				xmlGetProp(rscstates,XML_LRM_ATTR_TARGET);
 			const char *last_op =
 				xmlGetProp(rscstates,XML_LRM_ATTR_LASTOP);
 			const char *op_code =
 				xmlGetProp(rscstates,XML_LRM_ATTR_OPSTATUS);
 
 			rscstates = rscstates->next;
 			
 			crm_debug("checking %s:%s for %s", target, id, rsc);
 
 			if(safe_str_eq("stop", last_op)) {
 				crm_debug("resource %s is stopped on: %s\n",
 					  rsc, target);
 				
 			} else if(safe_str_eq(last_op, "start")
 				  && safe_str_neq(op_code, "0")) {
 				crm_debug("resource %s is failed on: %s\n",
 					  rsc, target);				
 			} else if(safe_str_eq(rsc, id)){
 				printf("resource %s is running on: %s\n",
 				       rsc, target);
 				if(BE_SILENT) {
 					fprintf(stderr, "%s ", target);
 				}
 				found++;
 			}
 		}
 		if(BE_SILENT) {
 			fprintf(stderr, "\n");
 		}
 	}
 	if(found == 0) {
 		printf("resource %s is NOT running\n", rsc);
 	}
 					
 	return found;
 }
 
 int
 do_find_resource_list(xmlNodePtr xml_node)
 {
 	int found = 0;
 	const char *path[] = {
 		XML_TAG_FRAGMENT,
 		XML_TAG_CIB,
 		XML_CIB_TAG_RESOURCES,
 		XML_CIB_TAG_RESOURCE
 	};
 	xmlNodePtr rscs = find_xml_node_nested(
 		xml_node, path, DIMOF(path));
 
 	while(rscs != NULL) {
 		printf("%s resource: %s (%s)\n",
 		       xmlGetProp(rscs, "class"),
 		       xmlGetProp(rscs, XML_ATTR_ID),
 		       xmlGetProp(rscs, XML_ATTR_TYPE));
 
 		rscs = rscs->next;
 
 		found++;
 	}
 	if(found == 0) {
 		printf("NO resources configured\n");
 	}
 					
 	return found;
 }
 
 int
 do_find_node_list(xmlNodePtr xml_node)
 {
 	int found = 0;
 	const char *path[] = {
 		XML_TAG_FRAGMENT,
 		XML_TAG_CIB,
 		XML_CIB_TAG_NODES,
 		XML_CIB_TAG_NODE
 	};
 	xmlNodePtr nodes = find_xml_node_nested(
 		xml_node, path, DIMOF(path));
 
 	while(nodes != NULL) {
 		printf("%s node: %s (%s)\n",
 		       xmlGetProp(nodes, XML_ATTR_TYPE),
 		       xmlGetProp(nodes, XML_ATTR_UNAME),
 		       xmlGetProp(nodes, XML_ATTR_ID));
 
 		nodes = nodes->next;
 
 		found++;
 	}
 	if(found == 0) {
 		printf("NO nodes configured\n");
 	}
 					
 	return found;
 }
 
 
 void
 usage(const char *cmd, int exit_status)
 {
 	FILE *stream;
 
 	stream = exit_status ? stderr : stdout;
 
 	fprintf(stream, "usage: %s [-?vs] [command] [command args]\n", cmd);
 
 	fprintf(stream, "Options\n");
 	fprintf(stream, "\t--%s (-%c)\t: "
 		"turn on debug info. additional instances increase verbosity\n",
 		"verbose", 'V');
 	fprintf(stream, "\t--%s (-%c)\t: be very very quiet\n", "silent", 's');
 	fprintf(stream, "\t--%s (-%c)\t: this help message\n", "help", '?');
 	fprintf(stream, "\nCommands\n");
 	fprintf(stream, "\t--%s (-%c) <node>\t: "
 		"increment the CRMd debug level on <node>\n", "debug_inc",'i');
 	fprintf(stream, "\t--%s (-%c) <node>\t: "
 		"decrement the CRMd debug level on <node>\n", "debug_dec",'d');
 	fprintf(stream, "\t--%s (-%c) <node>\t: "
 		"shutdown the CRMd on <node>\n", "kill", 'K');
 	fprintf(stream, "\t--%s (-%c) <node>\t: "
 		"request the status of <node>\n", "status", 'S');
 	fprintf(stream, "\t--%s (-%c)\t\t: "
 		"request the status of all nodes\n", "health", 'H');
 	fprintf(stream, "\t--%s (-%c) <node>\t: "
 		"initiate an election from <node>\n", "election", 'E');
 	fprintf(stream, "\t--%s (-%c)\t: "
 		"request the uname of the DC\n", "dc_lookup", 'D');
 	fprintf(stream, "\t--%s (-%c)\t\t: "
 		"request the uname of all member nodes\n", "nodes", 'N');
 	fprintf(stream, "\t--%s (-%c)\t: "
 		"request the names of all resources\n", "resources", 'R');
 	fprintf(stream, "\t--%s (-%c) <rsc>\t: "
 		"request the location of <rsc>\n", "whereis", 'W');
 /*	fprintf(stream, "\t--%s (-%c)\t\n", "disconnect", 'D'); */
 	fflush(stream);
 
 	exit(exit_status);
 }
diff --git a/crm/cib/messages.c b/crm/cib/messages.c
index 5dac290c00..3fda740555 100644
--- a/crm/cib/messages.c
+++ b/crm/cib/messages.c
@@ -1,459 +1,462 @@
-/* $Id: messages.c,v 1.1 2004/09/15 09:16:55 andrew Exp $ */
+/* $Id: messages.c,v 1.2 2004/09/17 13:03:09 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <clplumbing/cl_log.h>
 
 #include <time.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/msg.h>
 #include <crm/common/xml.h>
 
 #include <cibio.h>
 #include <cibmessages.h>
 #include <cibprimatives.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 FILE *msg_cib_strm = NULL;
 
 enum cib_result updateList(xmlNodePtr local_cib,
 			   xmlNodePtr update_command,
 			   xmlNodePtr failed,
 			   int operation,
 			   const char *section);
 
 xmlNodePtr createCibFragmentAnswer(const char *section, xmlNodePtr failed);
 
 gboolean replace_section(const char *section,
 			 xmlNodePtr tmpCib,
 			 xmlNodePtr command);
 
 gboolean check_generation(xmlNodePtr newCib, xmlNodePtr oldCib);
 
 gboolean update_results(xmlNodePtr failed,
 				 xmlNodePtr target,
 				 int operation,
 				 int return_code);
 
 xmlNodePtr
 cib_process_request(const char *op,
 		    const xmlNodePtr options,
 		    const xmlNodePtr fragment,
 		    enum cib_result *result)
 {
 	const char *verbose        = NULL;
 	const char *section        = NULL;
 	const char *id             = NULL;
 	const char *output_section = NULL;
 	xmlNodePtr failed          = NULL;
 	xmlNodePtr cib_answer      = NULL;
 
 	gboolean update_the_cib = FALSE;
 	int cib_update_op = CIB_OP_NONE;
 	xmlNodePtr tmpCib;
 	char *new_value = NULL;
 	char *old_value = NULL;
 	int int_value = -1;
 	
 	*result = CIBRES_OK;
 	verbose = xmlGetProp(options, XML_ATTR_VERBOSE);
 	section = xmlGetProp(options, XML_ATTR_FILTER_TYPE);
 	id      = xmlGetProp(options, XML_ATTR_FILTER_ID);
 	failed  = create_xml_node(NULL, XML_TAG_FAILED);
 
 #ifdef MSG_LOG
 	if(msg_cib_strm == NULL) {
 		msg_cib_strm = fopen(DEVEL_DIR"/cib.log", "w");
 	}
 	fprintf(msg_cib_strm, "\n====================\n");
 	fprintf(msg_cib_strm, "[Input %s]\t%s\n", op, dump_xml_formatted(fragment));
 	fflush(msg_cib_strm);
 #endif
 
 	crm_debug("[cib] Processing \"%s\" event", op);
 	
 	if(op == NULL) {
 		*result = CIBRES_FAILED;
 		crm_err("No operation specified\n");
 		
 	} else if(strcmp("noop", op) == 0) {
 		;
 		
 	} else if(strcmp(CRM_OP_QUIT, op) == 0) {
 		crm_warn(
 		       "The CRMd has asked us to exit... complying");
 		exit(0);
 		
 	} else if (strcmp(CRM_OP_PING, op) == 0) {
 		cib_answer =
 			createPingAnswerFragment(CRM_SYSTEM_CIB, "ok");
 		
 	} else if (strcmp(CRM_OP_BUMP, op) == 0) {
 		tmpCib = get_cib_copy();
 		crm_verbose("Handling a %s for section=%s of the cib",
 			   CRM_OP_BUMP, section);
 		
 		/* modify the timestamp */
 		set_node_tstamp(tmpCib);
-		old_value =
-			xmlGetProp(get_the_CIB(), XML_ATTR_GENERATION);
+		old_value = xmlGetProp(get_the_CIB(), XML_ATTR_GENERATION);
 		
 		if(old_value != NULL) {
-			new_value = (char*)crm_malloc(128*(sizeof(char)));
-			int_value = atoi(old_value);
-			sprintf(new_value, "%d", ++int_value);
+			crm_malloc(new_value, 128*(sizeof(char)));
+			if(new_value != NULL) {
+				int_value = atoi(old_value);
+				sprintf(new_value, "%d", ++int_value);
+			}
+			
 		} else {
 			new_value = crm_strdup("0");
 		}
 
 		crm_debug("Generation %d(%s)->%s",
-		       int_value, old_value, new_value);
+			  int_value, crm_str(old_value), crm_str(new_value));
 		
 		set_xml_property_copy(tmpCib, XML_ATTR_GENERATION, new_value);
 		crm_free(new_value);
 		
 		if(activateCibXml(tmpCib, CIB_FILENAME) >= 0) {
 			verbose = XML_BOOLEAN_TRUE; 
 		} else {
 			*result = CIBRES_FAILED;
 		}
 		
 	} else if (strcmp("query", op) == 0) {
 		crm_verbose("Handling a query for section=%s of the cib",
 			   section);
 
 		/* grab the whole section by forcing a pick-up of
 		 * the relevant section before returning
 		 */
 		verbose = XML_BOOLEAN_TRUE;
 		
 	} else if (strcmp(CRM_OP_ERASE, op) == 0) {
 
 		crm_err("Op %s is not currently supported", op);
 		*result = CIBRES_FAILED_NOTSUPPORTED;
 
 	} else if (strcmp(CRM_OP_CREATE, op) == 0) {
 		update_the_cib = TRUE;
 		cib_update_op = CIB_OP_ADD;
 		
 	} else if (strcmp(CRM_OP_UPDATE, op) == 0
 		   || strcmp(CRM_OP_WELCOME, op) == 0
 		   || strcmp(CRM_OP_SHUTDOWN_REQ, op) == 0) {
 		update_the_cib = TRUE;
 		cib_update_op = CIB_OP_MODIFY;
 		
 	} else if (strcmp(CRM_OP_DELETE, op) == 0) {
 		update_the_cib = TRUE;
 		cib_update_op = CIB_OP_DELETE;
 
 	} else if (strcmp(CRM_OP_REPLACE, op) == 0) {
 		crm_verbose("Replacing section=%s of the cib", section);
 
 		if (section == NULL
 		    || strlen(section) == 0
 		    || strcmp("all", section) == 0) {
 			tmpCib = copy_xml_node_recursive(
 				find_xml_node(fragment, XML_TAG_CIB));
 
 		} else {
 			tmpCib = copy_xml_node_recursive(get_the_CIB());
 			replace_section(section, tmpCib, fragment);
 		}
 
 		/*if(check_generation(cib_updates, tmpCib) == FALSE)
 			*result = "discarded old update";
 			else */
 		if (activateCibXml(tmpCib, CIB_FILENAME) < 0)
 			*result = CIBRES_FAILED;
 	} else {
 		*result = CIBRES_FAILED_NOTSUPPORTED;
 		crm_err("Action [%s] is not supported by the CIB", op);
 	}
     
 	if (update_the_cib) {
 		tmpCib = copy_xml_node_recursive(get_the_CIB());
 
 		crm_verbose("Updating section=%s of the cib (op=%s)",
 			   section, op);
 
 			/* should we be doing this? */
 			/* do logging */
 			
 			/* make changes to a temp copy then activate */
 		if(section == NULL) {
 			crm_err("No section specified in %s",
 			       XML_ATTR_FILTER_TYPE);
 			*result = CIBRES_FAILED_NOSECTION;
 
 		} else if(strcmp("all", section) == 0) {
 			/* order is no longer important here */
 			updateList(tmpCib, fragment, failed, cib_update_op,
 				   XML_CIB_TAG_NODES);
 			updateList(tmpCib, fragment, failed, cib_update_op,
 				   XML_CIB_TAG_RESOURCES);
 			updateList(tmpCib, fragment, failed, cib_update_op,
 				   XML_CIB_TAG_CONSTRAINTS);
 			updateList(tmpCib, fragment, failed, cib_update_op,
 				   XML_CIB_TAG_STATUS);
 		} else {
 			*result = updateList(tmpCib, fragment, failed,
 					     cib_update_op, section);
 		}
 
 		crm_trace("Activating temporary CIB");
 
 		fprintf(msg_cib_strm, "[Activating CIB (%s - %s)]\t%s\n", op,
 			cib_error2string(*result),
 			dump_xml_formatted(tmpCib));
 		/* if(check_generation(cib_updates, tmpCib) == FALSE) */
 /* 			status = "discarded old update"; */
 /* 		else  */
 		if (activateCibXml(tmpCib, CIB_FILENAME) < 0) {
 			*result = CIBRES_FAILED_ACTIVATION;
 			
 		} else if (failed->children != NULL) {
 			*result = CIBRES_FAILED;
 
 		}
 		fprintf(msg_cib_strm, "[New CIB (%s - %s)]\t%s\n", op,
 			cib_error2string(*result),
 			dump_xml_formatted(get_the_CIB()));
 		fflush(msg_cib_strm);
 		
 		crm_verbose("CIB update status: %d", *result);
 	}
 	
 	output_section = section;
 	
 	if (failed->children != NULL || *result != CIBRES_OK) {
 		cib_answer = createCibFragmentAnswer(NULL /*"all"*/, failed);
 	
 	} else if (verbose != NULL && strcmp(XML_BOOLEAN_TRUE, verbose) == 0) {
 		cib_answer = createCibFragmentAnswer(output_section, failed);
 
 	}
 
 	free_xml(failed);
 
 #ifdef MSG_LOG
 	fprintf(msg_cib_strm, "[Reply (%s:%s)]\t%s\n",
 		op, cib_error2string(*result),
 		dump_xml_formatted(cib_answer));
 	fflush(msg_cib_strm);
 #endif
 
 	return cib_answer;
 }
 
 gboolean
 replace_section(const char *section, xmlNodePtr tmpCib, xmlNodePtr fragment)
 {
 	xmlNodePtr parent = NULL,
 		cib_updates = NULL,
 		new_section = NULL,
 		old_section = NULL;
 	
 	cib_updates = find_xml_node(fragment, XML_TAG_CIB);
 
 	/* find the old and new versions of the section */
 	new_section = get_object_root(section, cib_updates);
 	old_section = get_object_root(section, tmpCib);
 
 	if(old_section == NULL) {
 		crm_err("The CIB is corrupt, cannot replace missing section %s",
 		       section);
 		return FALSE;
 
 	} else if(new_section == NULL) {
 		crm_err("The CIB is corrupt, cannot set section %s to nothing",
 		       section);
 		return FALSE;
 	}
 
 	parent = old_section->parent;
 	
 	/* unlink and free the old one */
 	unlink_xml_node(old_section);
 	free_xml(old_section);
 
 	/* add the new copy */
 	add_node_copy(parent, new_section);
 	
 	return TRUE;
 }
 
 
 
 enum cib_result
 updateList(xmlNodePtr local_cib, xmlNodePtr update_fragment, xmlNodePtr failed,
 	   int operation, const char *section)
 {
 	xmlNodePtr this_section = get_object_root(section, local_cib);
 	xmlNodePtr cib_updates  = NULL;
 	xmlNodePtr xml_section  = NULL;
 
 	cib_updates  = find_xml_node(update_fragment, XML_TAG_CIB);
 	xml_section  = get_object_root(section, cib_updates);
 	
 	if (section == NULL || xml_section == NULL) {
 		crm_err("Section %s not found in message."
-		       "  CIB update is corrupt, ignoring.", section);
+			"  CIB update is corrupt, ignoring.",
+			crm_str(section));
 		return CIBRES_FAILED_NOSECTION;
 	}
 
 	if(CIB_OP_NONE > operation > CIB_OP_MAX) {
-		crm_err("Invalid operation on section %s", section);
+		crm_err("Invalid operation on section %s", crm_str(section));
 		return CIBRES_FAILED;
 	}
 
 	set_node_tstamp(this_section);
 
 	xml_child_iter(
 		xml_section, a_child, NULL,
 
 		crm_debug("%s to section %s with <%s id=%s>",
 			  cib_op2string(operation), section, a_child->name, xmlGetProp(a_child, "id"));
 
 		if(operation == CIB_OP_DELETE) {
 			update_results(
 				failed, a_child, operation,
 				delete_cib_object(this_section, a_child));
 
 		} else if(operation == CIB_OP_MODIFY) {
 
 			update_results(
 				failed, a_child, operation,
 				update_cib_object(this_section, a_child, FALSE));
 				       
 		} else {
 			update_results(
 				failed, a_child, operation,
 				add_cib_object(this_section, a_child));
 		} 
 
 		);
 
 	if (failed->children != NULL) {
 		return CIBRES_FAILED;
 	} else {
 		return CIBRES_OK;
 	}
 }
 
 xmlNodePtr
 createCibFragmentAnswer(const char *section, xmlNodePtr failed)
 {
 	xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT);
 	
 	set_xml_property_copy(fragment, XML_ATTR_SECTION, section);
 
 	if (section == NULL
 		   || strlen(section) == 0
 		   || strcmp("all", section) == 0) {
 		add_node_copy(fragment, get_the_CIB());
 		
 	} else {
 		xmlNodePtr cib = create_xml_node(fragment, XML_TAG_CIB);
 		add_node_copy(cib, get_object_root(section, get_the_CIB()));
 		copy_in_properties(cib, get_the_CIB());
 		
 	}
 
 	if (failed != NULL && failed->children != NULL) {
 		add_node_copy(fragment, failed);
 	}
 		
 	return fragment;
 }
 
 
 gboolean
 check_generation(xmlNodePtr newCib, xmlNodePtr oldCib)
 {
 	char *new_value = xmlGetProp(newCib, XML_ATTR_GENERATION);
 	char *old_value = xmlGetProp(oldCib, XML_ATTR_GENERATION);
 	int int_new_value = -1;
 	int int_old_value = -1;
 	if(old_value != NULL) int_old_value = atoi(old_value);
 	if(new_value != NULL) int_new_value = atoi(new_value);
 	
 	if(int_new_value >= int_old_value) {
 		return TRUE;
 	} else {
 		crm_err("Generation from update (%d) is older than %d",
 		       int_new_value, int_old_value);
 	}
 	
 	return FALSE;
 }
  
 gboolean
 update_results(xmlNodePtr failed,
 			xmlNodePtr target,
 			int operation,
 			int return_code)
 {
 	gboolean was_error = FALSE;
 	const char *error_msg = NULL;
 	const char *operation_msg = NULL;
 	xmlNodePtr xml_node;
 	
 	operation_msg = cib_op2string(operation);
     
 	if (return_code != CIBRES_OK) {
 		error_msg = cib_error2string(return_code);
 
 		xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB);
 
 		was_error = TRUE;
 				
 		set_xml_property_copy(
 			xml_node, XML_FAILCIB_ATTR_ID, ID(target));
 
 		set_xml_property_copy(
 			xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target));
 
 		set_xml_property_copy(
 			xml_node, XML_FAILCIB_ATTR_OP, operation_msg);
 	
 		set_xml_property_copy(
 			xml_node, XML_FAILCIB_ATTR_REASON, error_msg);
 
 		crm_debug("Action %s failed: %s (cde=%d)",
 			  operation_msg, error_msg, return_code);
 	
 	} else {
 		crm_debug("CIB %s passed", operation_msg);
 	}
 
 	return was_error;
 }
 
diff --git a/crm/common/ipc.c b/crm/common/ipc.c
index bd4fbfcf45..42a4265227 100644
--- a/crm/common/ipc.c
+++ b/crm/common/ipc.c
@@ -1,376 +1,380 @@
-/* $Id: ipc.c,v 1.7 2004/09/14 05:54:43 andrew Exp $ */
+/* $Id: ipc.c,v 1.8 2004/09/17 13:03:09 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 
 #include <clplumbing/ipc.h>
 #include <clplumbing/Gmain_timeout.h>
 #include <clplumbing/cl_log.h>
 #include <clplumbing/cl_signal.h>
 #include <clplumbing/lsb_exitcodes.h>
 #include <clplumbing/uids.h>
 #include <clplumbing/realtime.h>
 #include <clplumbing/GSource.h>
 #include <clplumbing/cl_poll.h>
 
 
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/xpath.h>
 
 #include <crm/common/ipc.h>
 #include <crm/msg_xml.h>
 
 
 #include <crm/dmalloc_wrapper.h>
 
 IPC_Message *create_simple_message(char *text, IPC_Channel *ch);
 gboolean send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg);
 
 
 gboolean 
 send_xmlipc_message(IPC_Channel *ipc_client, xmlNodePtr msg)
 {
 	int log_level = LOG_DEBUG;
 	char *xml_message = NULL;
 	IPC_Message *cib_dump = NULL;
 	gboolean res;
 	
 
 	xml_message = dump_xml_unformatted(msg);
 	
 	cib_dump = create_simple_message(xml_message, ipc_client);
 	res = send_ipc_message(ipc_client, cib_dump);
 	crm_free(xml_message);
 
 	if(res == FALSE) {
 		log_level = LOG_ERR;
 	}
 	
 	do_crm_log(log_level, __FUNCTION__,
 	       "Sending IPC message (ref=%s) to %s@%s %s.",
 	       xmlGetProp(msg, XML_ATTR_REFERENCE), 
 	       xmlGetProp(msg, XML_ATTR_SYSTO),
 	       xmlGetProp(msg, XML_ATTR_HOSTTO),
 	       res?"succeeded":"failed");
 	
 	return res;
 }
 
 
 gboolean 
 send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg)
 {
 	int lpc = 0;
 	gboolean all_is_good = TRUE;
-	
 
 	if (msg == NULL) {
 		crm_err("cant send NULL message");
 		all_is_good = FALSE;
 	}
 	else if (msg->msg_len <= 0) {
 		crm_err("cant send 0 sized message");
 		all_is_good = FALSE;
 	}
 	else if (msg->msg_len > MAXDATASIZE) {
 		crm_err("cant send msg... too big");
 		all_is_good = FALSE;
 	}
-    
-	crm_trace("Sending message: %s", (char*)msg->msg_body); 
+	
+	crm_trace("Sending message: %s", crm_str(msg->msg_body)); 
 	crm_verbose("Message is%s valid to send", all_is_good?"":" not");
 
 	if (ipc_client == NULL) {
 		all_is_good = FALSE;
 	}
 	crm_verbose("IPC Client is%s set.", all_is_good?"":" not");
 	if (all_is_good) {		
 		while(lpc++ < MAX_IPC_FAIL
 		      && ipc_client->ops->send(ipc_client, msg) == IPC_FAIL)
 		{
 			crm_err("ipc channel blocked");
 			cl_shortsleep();
 		}
 	}
 	
 	if (lpc == MAX_IPC_FAIL) {
 		crm_err("Could not send IPC, message.  Channel is dead.");
 		all_is_good = FALSE;
 	}
 
 	return all_is_good;
 }
 
 IPC_Message *
 create_simple_message(char *text, IPC_Channel *ch)
 {
 	/*    char	       str[256]; */
 	IPC_Message        *ack_msg = NULL;
 
 	
-	if (text == NULL) return NULL;
-
-	ack_msg = (IPC_Message *)crm_malloc(sizeof(IPC_Message));
-    
-	ack_msg->msg_private = NULL;
-	ack_msg->msg_done    = NULL;
-	ack_msg->msg_body    = text;
-	ack_msg->msg_ch      = ch;
+	if (text == NULL) {
+		return NULL;
+	}
+	crm_malloc(ack_msg, sizeof(IPC_Message));
 
-	ack_msg->msg_len = strlen(text)+1;
-    
+	if(ack_msg != NULL) {
+		ack_msg->msg_private = NULL;
+		ack_msg->msg_done    = NULL;
+		ack_msg->msg_body    = text;
+		ack_msg->msg_ch      = ch;
+		
+		ack_msg->msg_len = strlen(text)+1;
+	}
+	
 	return ack_msg;
 }
 
 
 xmlNodePtr
 find_xml_in_ipcmessage(IPC_Message *msg, gboolean do_free)
 {
 	char *buffer = NULL;
 	xmlDocPtr doc;
 	xmlNodePtr root;
 
 	
 	if (msg == NULL) {
 		crm_trace("IPC Message was empty...");
 		return NULL;
 	}
 
 	buffer = (char*)msg->msg_body;
 	doc = xmlParseMemory(buffer, strlen(buffer));
 
 	if (do_free) msg->msg_done(msg);
 
 	if (doc == NULL) {
 		crm_info("IPC Message did not contain an XML buffer...");
 		return NULL;
 	}
 
 	root = xmlDocGetRootElement(doc);
 	if (root == NULL) {
 		crm_info("Root node was NULL.");
 		return NULL;
 	}
 	return root;
 }
 
 
 
 void
 default_ipc_input_destroy(gpointer user_data)
 {
 	
 	return;
 }
 
 
 IPC_Channel *
 init_client_ipc_comms(const char *child,
 		      gboolean (*dispatch)(IPC_Channel* source_data
 					   ,gpointer    user_data),
 		      crmd_client_t *client_data)
 {
 	IPC_Channel *ch;
 	GHashTable * attrs;
 	GCHSource *the_source = NULL;
 	void *callback_data = client_data;
 	static char 	path[] = IPC_PATH_ATTR;
 	char *commpath = NULL;
 	int local_socket_len = 2; /* 2 = '/' + '\0' */
 
 	
 	local_socket_len += strlen(child);
 	local_socket_len += strlen(WORKING_DIR);
 
-	commpath = (char*)crm_malloc(sizeof(char)*local_socket_len);
-	sprintf(commpath, WORKING_DIR "/%s", child);
-	commpath[local_socket_len - 1] = '\0';
-    
-	crm_debug("Attempting to talk on: %s", commpath);
-
+	crm_malloc(commpath, sizeof(char)*local_socket_len);
+	if(commpath != NULL) {
+		sprintf(commpath, WORKING_DIR "/%s", child);
+		commpath[local_socket_len - 1] = '\0';
+		crm_debug("Attempting to talk on: %s", commpath);
+	}
+	
 	attrs = g_hash_table_new(g_str_hash,g_str_equal);
 	g_hash_table_insert(attrs, path, commpath);
 
 	ch = ipc_channel_constructor(IPC_ANYTYPE, attrs);
 	g_hash_table_destroy(attrs);
 
 	if (ch == NULL) {
 		crm_crit("Could not access channel on: %s", commpath);
+		return NULL;
 		
 	} else if (ch->ops->initiate_connection(ch) != IPC_OK) {
 		crm_crit("Could not init comms on: %s", commpath);
 		return NULL;
 	}
 
 	if(callback_data == NULL) {
 		callback_data = ch;
 	}
 	
 	ch->ops->set_recv_qlen(ch, 100);
 	ch->ops->set_send_qlen(ch, 100);
 
 	the_source = G_main_add_IPC_Channel(
 		G_PRIORITY_LOW, ch, FALSE, dispatch, callback_data, 
 		default_ipc_input_destroy);
 
 	crm_debug("Processing of %s complete", commpath);
 
 	return ch;
 }
 
 
 /*
  * This method adds a copy of xml_response_data
  */
 gboolean
 send_ipc_request(IPC_Channel *ipc_channel,
 		 xmlNodePtr msg_options, xmlNodePtr msg_data, 
 		 const char *host_to, const char *sys_to,
 		 const char *sys_from, const char *uuid_from,
 		 const char *crm_msg_reference)
 {
 	gboolean was_sent = FALSE;
 	xmlNodePtr request = NULL;
 	
 
 	request = create_request(msg_options, msg_data,
 				 host_to, sys_to,
 				 sys_from, uuid_from,
 				 crm_msg_reference);
 
 	was_sent = send_xmlipc_message(ipc_channel, request);
 
 	free_xml(request);
 
 	return was_sent;
 }
 
 
 /*
  * This method adds a copy of xml_response_data
  */
 gboolean
 send_ipc_reply(IPC_Channel *ipc_channel,
 	       xmlNodePtr xml_request,
 	       xmlNodePtr xml_response_data)
 {
 	gboolean was_sent = FALSE;
 	xmlNodePtr reply;
 	
 
 	reply = create_reply(xml_request, xml_response_data);
 
 	if (reply != NULL) {
 		was_sent = send_xmlipc_message(ipc_channel, reply);
 		free_xml(reply);
 	}
 	return was_sent;
 }
 
 
 gboolean
 subsystem_input_dispatch(IPC_Channel *sender, void *user_data)
 {
 	int lpc = 0;
 	char *buffer = NULL;
 	IPC_Message *msg = NULL;
 	gboolean all_is_well = TRUE;
 	xmlNodePtr root_xml_node = NULL;
 	const char *sys_to;
 	const char *type;
 
 	while(sender->ops->is_message_pending(sender)) {
 		if (sender->ch_status == IPC_DISCONNECT) {
 			/* The message which was pending for us is that
 			 * the IPC status is now IPC_DISCONNECT */
 			break;
 		}
 		if (sender->ops->recv(sender, &msg) != IPC_OK) {
 			perror("Receive failure:");
 			return !all_is_well;
 		}
 		if (msg == NULL) {
 			crm_err("No message this time");
 			continue;
 		}
 
 		lpc++;
 
 		buffer = (char*)msg->msg_body;
 		root_xml_node = string2xml(buffer);
 
 		sys_to= xmlGetProp(root_xml_node, XML_ATTR_SYSTO);
 		type  = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE);
 		if (root_xml_node == NULL) {
 			crm_err("Root node was NULL!!");
 
 		} else if(sys_to == NULL) {
 			crm_err("Value of %s was NULL!!",
 			       XML_ATTR_SYSTO);
 			
 		} else if(type == NULL) {
 			crm_err("Value of %s was NULL!!",
 			       XML_ATTR_MSGTYPE);
 			
 		} else {
 			gboolean (*process_function)
 				(xmlNodePtr msg, IPC_Channel *sender) = NULL;
 			process_function = user_data;
 			
 			if(process_function(root_xml_node, sender) == FALSE) {
 				crm_warn("Received a message destined for %s"
 					 " by mistake", sys_to);
 			}
 			
 		}
 
 		free_xml(root_xml_node);
 		root_xml_node = NULL;
 		
 		msg->msg_done(msg);
 		msg = NULL;
 	}
 
 	/* clean up after a break */
 	if(msg != NULL)
 		msg->msg_done(msg);
 
 	if(root_xml_node != NULL)
 		free_xml(root_xml_node);
 
 	crm_verbose("Processed %d messages", lpc);
 	if (sender->ch_status == IPC_DISCONNECT) {
 		crm_err("The server has left us: Shutting down...NOW");
 
 		exit(1); /* shutdown properly later */
 		
 		return !all_is_well;
 	}
 	return all_is_well;
 }
diff --git a/crm/common/msg.c b/crm/common/msg.c
index e2d051b1ee..355e7a4dc5 100644
--- a/crm/common/msg.c
+++ b/crm/common/msg.c
@@ -1,397 +1,399 @@
-/* $Id: msg.c,v 1.6 2004/08/29 03:01:12 msoffen Exp $ */
+/* $Id: msg.c,v 1.7 2004/09/17 13:03:09 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <string.h>
 
 #include <stdlib.h>
 
 #include <clplumbing/cl_log.h>
 
 #include <time.h> 
 
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/common/msg.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 xmlNodePtr
 create_common_message(xmlNodePtr original_request,
 		      xmlNodePtr xml_response_data);
 
 
 xmlNodePtr
 createPingAnswerFragment(const char *from, const char *status)
 {
 	xmlNodePtr ping = NULL;
 	
 	
 	ping = create_xml_node(NULL, XML_CRM_TAG_PING);
 	
 	set_xml_property_copy(ping, XML_PING_ATTR_STATUS, status);
 	set_xml_property_copy(ping, XML_PING_ATTR_SYSFROM, from);
 
 	return ping;
 }
 
 xmlNodePtr
 createPingRequest(const char *crm_msg_reference, const char *to)
 {
 	xmlNodePtr root_xml_node = NULL;
 	int sub_type_len;
 	int msg_type_len;
 	char *sub_type_target;
 	char *msg_type_target;
 
 	
 	
 	/* 2 = "_" + '\0' */
 	sub_type_len = strlen(to) + strlen(XML_ATTR_REQUEST) + 2; 
-	sub_type_target =
-		(char*)crm_malloc(sizeof(char)*(sub_type_len));
+	crm_malloc(sub_type_target, sizeof(char)*(sub_type_len));
 
-	sprintf(sub_type_target, "%s_%s", to, XML_ATTR_REQUEST);
+	if(sub_type_target != NULL) {
+		sprintf(sub_type_target, "%s_%s", to, XML_ATTR_REQUEST);
+	}
 	root_xml_node   = create_xml_node(NULL, sub_type_target);
-	set_xml_property_copy(root_xml_node,
-			      XML_ATTR_REFERENCE,
-			      crm_msg_reference);
+	set_xml_property_copy(
+		root_xml_node, XML_ATTR_REFERENCE, crm_msg_reference);
     
 	msg_type_len = strlen(to) + 10 + 1; /* + "_operation" + '\0' */
-	msg_type_target =
-		(char*)crm_malloc(sizeof(char)*(msg_type_len));
-	sprintf(msg_type_target, "%s_operation", to);
+	crm_malloc(msg_type_target, sizeof(char)*(msg_type_len));
+	if(msg_type_target != NULL) {
+		sprintf(msg_type_target, "%s_operation", to);
+	}
+	
 	set_xml_property_copy(root_xml_node, msg_type_target, CRM_OP_PING);
 	crm_free(msg_type_target);
 
 	return root_xml_node;
 }
 
 
 
 xmlNodePtr
 validate_crm_message(xmlNodePtr root_xml_node,
 		     const char *sys,
 		     const char *uuid,
 		     const char *msg_type)
 {
 	const char *from = NULL;
 	const char *to = NULL;
 	const char *type = NULL;
 	const char *crm_msg_reference = NULL;
 	xmlNodePtr action = NULL;
 	const char *true_sys;
 	
 	
 	if (root_xml_node == NULL) {
 		return NULL;
 	}
 
 	from = xmlGetProp(root_xml_node, XML_ATTR_SYSFROM);
 	to   = xmlGetProp(root_xml_node, XML_ATTR_SYSTO);
 	type = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE);
 	
 	crm_msg_reference = xmlGetProp(root_xml_node,
 				       XML_ATTR_REFERENCE);
 /*
 	crm_debug("Recieved XML message with (version=%s)",
 	       xmlGetProp(root_xml_node, XML_ATTR_VERSION));
 	crm_debug("Recieved XML message with (from=%s)", from);
 	crm_debug("Recieved XML message with (to=%s)"  , to);
 	crm_debug("Recieved XML message with (type=%s)", type);
 	crm_debug("Recieved XML message with (ref=%s)" ,
 	       crm_msg_reference);
 */
 	action = root_xml_node;
 	true_sys = sys;
 
 	if (uuid != NULL) true_sys = generate_hash_key(sys, uuid);
 
 	if (to == NULL) {
 		crm_info("No sub-system defined.");
 		action = NULL;
 	} else if (true_sys != NULL && strcmp(to, true_sys) != 0) {
 		crm_debug("The message is not for this sub-system (%s != %s).",
 			  to, true_sys);
 		action = NULL;
 	}
     
 	if (type == NULL) {
 		crm_info("No message type defined.");
 		return NULL;
 	} else if (msg_type != NULL && strcmp(msg_type, type) != 0) {
 		crm_info("Expecting a (%s) message but received a (%s).",
 		       msg_type, type);
 		action = NULL;
 	}
 
 	if (crm_msg_reference == NULL) {
 		crm_info("No message crm_msg_reference defined.");
 		action = NULL;
 	}
 /*
  	if(action != NULL) 
 		crm_debug(
 		       "XML is valid and node with message type (%s) found.",
 		       type);
 	crm_debug("Returning node (%s)", xmlGetNodePath(action));
 */
 	
 	return action;
 }
 
 
 void
 send_hello_message(IPC_Channel *ipc_client,
 		   const char *uuid,
 		   const char *client_name,
 		   const char *major_version,
 		   const char *minor_version)
 {
 	xmlNodePtr hello_node = NULL;
 	
 	
 	if (uuid == NULL || strlen(uuid) == 0
 	    || client_name == NULL || strlen(client_name) == 0
 	    || major_version == NULL || strlen(major_version) == 0
 	    || minor_version == NULL || strlen(minor_version) == 0) {
 		crm_err("Missing fields, Hello message will not be valid.");
 		return;
 	}
 
 	hello_node = create_xml_node(NULL, XML_TAG_OPTIONS);
 	set_xml_property_copy(hello_node, "major_version", major_version);
 	set_xml_property_copy(hello_node, "minor_version", minor_version);
 	set_xml_property_copy(hello_node, "client_name",   client_name);
 	set_xml_property_copy(hello_node, "client_uuid",   uuid);
 	set_xml_property_copy(hello_node, XML_ATTR_OP,     CRM_OP_HELLO);
 
 
 	send_ipc_request(ipc_client,
 			 hello_node, NULL, 
 			 NULL, NULL,
 			 client_name, uuid,
 			 NULL);
 
 	free_xml(hello_node);
 }
 
 
 gboolean
 process_hello_message(xmlNodePtr hello,
 		      char **uuid,
 		      char **client_name,
 		      char **major_version,
 		      char **minor_version)
 {
 	xmlNodePtr opts = NULL;
 	const char *op = NULL;
 	const char *local_uuid;
 	const char *local_client_name;
 	const char *local_major_version;
 	const char *local_minor_version;
 
 	
 	*uuid = NULL;
 	*client_name = NULL;
 	*major_version = NULL;
 	*minor_version = NULL;
 
 	opts = find_xml_node(hello, XML_TAG_OPTIONS);
 	
 	op = xmlGetProp(opts, XML_ATTR_OP);
 	local_uuid = xmlGetProp(opts, "client_uuid");
 	local_client_name = xmlGetProp(opts, "client_name");
 	local_major_version = xmlGetProp(opts, "major_version");
 	local_minor_version = xmlGetProp(opts, "minor_version");
 
 	if (op == NULL || strcmp(CRM_OP_HELLO, op) != 0) {
 		return FALSE;
 
 	} else if (local_uuid == NULL || strlen(local_uuid) == 0) {
 		crm_err("Hello message was not valid (field %s not found)",
 		       "uuid");
 		return FALSE;
 
 	} else if (local_client_name==NULL || strlen(local_client_name)==0){
 		crm_err("Hello message was not valid (field %s not found)",
 			"client name");
 		return FALSE;
 
 	} else if(local_major_version == NULL
 		  || strlen(local_major_version) == 0){
 		crm_err("Hello message was not valid (field %s not found)",
 			"major version");
 		return FALSE;
 
 	} else if (local_minor_version == NULL
 		   || strlen(local_minor_version) == 0){
 		crm_err("Hello message was not valid (field %s not found)",
 			"minor version");
 		return FALSE;
 	}
     
 	*uuid          = crm_strdup(local_uuid);
 	*client_name   = crm_strdup(local_client_name);
 	*major_version = crm_strdup(local_major_version);
 	*minor_version = crm_strdup(local_minor_version);
 
 	return TRUE;
 }
 
 xmlNodePtr
 create_request(xmlNodePtr msg_options, xmlNodePtr msg_data,
 	       const char *host_to, const char *sys_to,
 	       const char *sys_from, const char *uuid_from,
 	       const char *crm_msg_reference)
 {
 	const char *true_from = sys_from;
 	xmlNodePtr request;
 
 	
 
 	if (uuid_from != NULL)
 		true_from = generate_hash_key(sys_from, uuid_from);
 	/* else make sure we are internal */
 	else {
 		if (strcmp(CRM_SYSTEM_LRMD, sys_from) != 0
 		    && strcmp(CRM_SYSTEM_PENGINE, sys_from) != 0
 		    && strcmp(CRM_SYSTEM_TENGINE, sys_from) != 0
 		    && strcmp(CRM_SYSTEM_DC, sys_from) != 0
 		    && strcmp(CRM_SYSTEM_CRMD, sys_from) != 0) {
 			crm_err("only internal systems can leave"
 				" uuid_from blank");
 			return FALSE;
 		}
 	}
 
 	if (crm_msg_reference == NULL) {
 		crm_msg_reference =
 			generateReference(
 				xmlGetProp(msg_options,XML_ATTR_OP),sys_from);
 	}
 	
 	/* host_from will get set for us if necessary by CRMd when routed */
 	request = create_xml_node(NULL, XML_MSG_TAG);
 
 	set_node_tstamp(request);
 
 	set_xml_property_copy(request, XML_ATTR_VERSION, CRM_VERSION);
 	set_xml_property_copy(request, XML_ATTR_MSGTYPE, XML_ATTR_REQUEST);
 	set_xml_property_copy(request, XML_ATTR_SYSTO,   sys_to);
 	set_xml_property_copy(request, XML_ATTR_SYSFROM, true_from);
 	set_xml_property_copy(request, XML_ATTR_REFERENCE, crm_msg_reference);
 	if(host_to != NULL && strlen(host_to) > 0)
 		set_xml_property_copy(request, XML_ATTR_HOSTTO,  host_to);
 
 	if (msg_options != NULL) {
 		add_node_copy(request, msg_options);
 	}
 
 	if (msg_data != NULL) {
 		add_node_copy(request, msg_data);
 	}
 
 	return request;
 }
 
 /*
  * This method adds a copy of xml_response_data
  */
 xmlNodePtr
 create_reply(xmlNodePtr original_request,
 	     xmlNodePtr xml_response_data)
 {
 	const char *host_from = NULL;
 	const char *sys_from  = NULL;
 	const char *sys_to    = NULL;
 	xmlNodePtr reply;
 	
 	
 	host_from = xmlGetProp(original_request, XML_ATTR_HOSTFROM);
 	sys_from  = xmlGetProp(original_request, XML_ATTR_SYSFROM);
 	sys_to  = xmlGetProp(original_request, XML_ATTR_SYSTO);
 
 	reply = create_common_message(original_request, xml_response_data);
 	
 	set_xml_property_copy(reply, XML_ATTR_MSGTYPE, XML_ATTR_RESPONSE);
 	
 	/* since this is a reply, we reverse the from and to */
 
 	/* HOSTTO will be ignored if it is to the DC anyway. */
 	if(host_from != NULL && strlen(host_from) > 0)
 		set_xml_property_copy(reply, XML_ATTR_HOSTTO,   host_from);
 
 	set_xml_property_copy(reply, XML_ATTR_SYSTO,    sys_from);
 	set_xml_property_copy(reply, XML_ATTR_SYSFROM,  sys_to);
 
 	return reply;
 }
 
 xmlNodePtr
 create_common_message(xmlNodePtr original_request,
 		      xmlNodePtr xml_response_data)
 {
 	const char *crm_msg_reference = NULL;
 	const char *type      = NULL;
 	const char *operation = NULL;
 	xmlNodePtr options = NULL;
 	xmlNodePtr new_message;
 	
 	
 	crm_msg_reference = xmlGetProp(original_request,
 				       XML_ATTR_REFERENCE);
 	type      = xmlGetProp(original_request, XML_ATTR_MSGTYPE);
 	operation = xmlGetProp(original_request, XML_ATTR_OP);
 	
 	if (type == NULL) {
 		crm_err("Cannot create new_message,"
 			" no message type in original message");
 		return NULL;
 #if 0
 	} else if (strcmp(XML_ATTR_REQUEST, type) != 0) {
 		crm_err("Cannot create new_message,"
 			" original message was not a request");
 		return NULL;
 #endif
 	}
 	new_message = create_xml_node(NULL, XML_MSG_TAG);
 
 	set_node_tstamp(new_message);
 
 	set_xml_property_copy(new_message, XML_ATTR_VERSION, CRM_VERSION);
 	set_xml_property_copy(new_message, XML_ATTR_OP, operation);
 
 	set_xml_property_copy(new_message,
 			      XML_ATTR_REFERENCE,
 			      crm_msg_reference);
     
 	if (xml_response_data != NULL) {
 		add_node_copy(new_message, xml_response_data);
 	}
     
 	options = find_xml_node(original_request, XML_TAG_OPTIONS);
 	if (options != NULL) {
 		add_node_copy(new_message, options);
 	}
 
 	return new_message;
 }
diff --git a/crm/common/utils.c b/crm/common/utils.c
index 5a65b850bc..86aa4dcf22 100644
--- a/crm/common/utils.c
+++ b/crm/common/utils.c
@@ -1,372 +1,394 @@
-/* $Id: utils.c,v 1.15 2004/09/15 20:16:48 andrew Exp $ */
+/* $Id: utils.c,v 1.16 2004/09/17 13:03:09 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <string.h>
 
 #include <stdlib.h>
 
 
 #include <clplumbing/cl_log.h>
 #include <clplumbing/cl_signal.h>
 
 #include <time.h> 
 
 #include <clplumbing/Gmain_timeout.h>
 
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/util.h>
 #include <crm/dmalloc_wrapper.h>
 
 #define MAXLINE 512
 
 static uint ref_counter = 0;
 
 const char *
 generateReference(const char *custom1, const char *custom2)
 {
 
 	const char *local_cust1 = custom1;
 	const char *local_cust2 = custom2;
 	int reference_len = 4;
 	char *since_epoch = NULL;
 
 	
 	
 	reference_len += 20; /* too big */
 	reference_len += 40; /* too big */
 	
 	if(local_cust1 == NULL) local_cust1 = "_empty_";
 	reference_len += strlen(local_cust1);
 	
 	if(local_cust2 == NULL) local_cust2 = "_empty_";
 	reference_len += strlen(local_cust2);
 	
-	since_epoch = (char*)crm_malloc(reference_len*(sizeof(char)));
-	
-	sprintf(since_epoch, "%s-%s-%ld-%u",
-		local_cust1, local_cust2,
-		(unsigned long)time(NULL), ref_counter++);
+	crm_malloc(since_epoch, reference_len*(sizeof(char)));
+
+	if(since_epoch != NULL) {
+		sprintf(since_epoch, "%s-%s-%ld-%u",
+			local_cust1, local_cust2,
+			(unsigned long)time(NULL), ref_counter++);
+	}
 
 	return since_epoch;
 }
 
 gboolean
 decodeNVpair(const char *srcstring, char separator, char **name, char **value)
 {
 	int lpc = 0;
 	int len = 0;
 	const char *temp = NULL;
 
 	crm_verbose("Attempting to decode: [%s]", srcstring);
 	if (srcstring != NULL) {
 		len = strlen(srcstring);
 		while(lpc <= len) {
 			if (srcstring[lpc] == separator
 			    || srcstring[lpc] == '\0') {
-				*name = (char*)crm_malloc(sizeof(char)*lpc+1);
+				crm_malloc(*name, sizeof(char)*lpc+1);
+				if(*name == NULL) {
+					break; /* and return FALSE */
+				}
 				strncpy(*name, srcstring, lpc);
 				(*name)[lpc] = '\0';
 
-/* this sucks but as the strtok manpage says.. it *is* a bug */
-				len = len-lpc;
-				len--;
-				if(len > 0) {
-					*value = (char*)crm_malloc(
-						sizeof(char)*len+1);
+/* this sucks but as the strtok manpage says..
+ * it *is* a bug
+ */
+				len = len-lpc; len--;
+				if(len <= 0) {
+					*value = NULL;
+				} else {
+
+					crm_malloc(*value, sizeof(char)*len+1);
+					if(*value == NULL) {
+						crm_free(*name);
+						break; /* and return FALSE */
+					}
 					temp = srcstring+lpc+1;
 					strncpy(*value, temp, len);
 					(*value)[len] = '\0';
-				} else {
-					*value = NULL;
 				}
 
 				return TRUE;
 			}
 			lpc++;
 		}
 	}
 
 	*name = NULL;
 	*value = NULL;
     
 	return FALSE;
 }
 
 char *
 generate_hash_key(const char *crm_msg_reference, const char *sys)
 {
 	int ref_len = strlen(sys?sys:"none") + strlen(crm_msg_reference) + 2;
-	char *hash_key = (char*)crm_malloc(sizeof(char)*(ref_len));
+	char *hash_key = NULL;
+	crm_malloc(hash_key, sizeof(char)*(ref_len));
 
-	
-	sprintf(hash_key, "%s_%s", sys?sys:"none", crm_msg_reference);
-	hash_key[ref_len-1] = '\0';
-	crm_debug("created hash key: (%s)", hash_key);
+	if(hash_key != NULL) {
+		sprintf(hash_key, "%s_%s", sys?sys:"none", crm_msg_reference);
+		hash_key[ref_len-1] = '\0';
+		crm_debug("created hash key: (%s)", hash_key);
+	}
 	return hash_key;
 }
 
 char *
 generate_hash_value(const char *src_node, const char *src_subsys)
 {
 	int ref_len;
 	char *hash_value;
-
 	
 	if (src_node == NULL || src_subsys == NULL) {
 		return NULL;
 	}
     
 	if (strcmp(CRM_SYSTEM_DC, src_subsys) == 0) {
 		hash_value = crm_strdup(src_subsys);
 		if (!hash_value) {
 			crm_err("memory allocation failed in "
 			       "generate_hash_value()\n");
 			return NULL;
 		}
 		return hash_value;
 	}
     
 	ref_len = strlen(src_subsys) + strlen(src_node) + 2;
-	hash_value = (char*)crm_malloc(sizeof(char)*(ref_len));
+	crm_malloc(hash_value, sizeof(char)*(ref_len));
 	if (!hash_value) {
 		crm_err("memory allocation failed in "
 		       "generate_hash_value()\n");
 		return NULL;
 	}
 
 	snprintf(hash_value, ref_len-1, "%s_%s", src_node, src_subsys);
 	hash_value[ref_len-1] = '\0';/* make sure it is null terminated */
 
 	crm_info("created hash value: (%s)", hash_value);
 	return hash_value;
 }
 
 gboolean
 decode_hash_value(gpointer value, char **node, char **subsys)
 {
 	char *char_value = (char*)value;
 	int value_len = strlen(char_value);
 
-	crm_info("Decoding hash value: (%s:%d)",
-	       char_value,
-	       value_len);
+	crm_info("Decoding hash value: (%s:%d)", char_value, value_len);
     	
 	if (strcmp(CRM_SYSTEM_DC, (char*)value) == 0) {
 		*node = NULL;
 		*subsys = (char*)crm_strdup(char_value);
-		if (!*subsys) {
+		if (*subsys == NULL) {
 			crm_err("memory allocation failed in "
 			       "decode_hash_value()\n");
 			return FALSE;
 		}
-		crm_info("Decoded value: (%s:%d)", *subsys, 
-		       (int)strlen(*subsys));
+		crm_info("Decoded value: (%s:%d)", *subsys,
+			 (int)strlen(*subsys));
 		return TRUE;
-	}
-	else if (char_value != NULL) {
+		
+	} else if (char_value != NULL) {
 		if (decodeNVpair(char_value, '_', node, subsys)) {
 			return TRUE;
 		} else {
 			*node = NULL;
 			*subsys = NULL;
 			return FALSE;
 		}
 	}
 	return FALSE;
 }
 
 
 char *
 crm_itoa(int an_int)
 {
 	int len = 32;
-	char *buffer = crm_malloc(sizeof(char)*(len+1));
-	snprintf(buffer, len, "%d", an_int);
-
+	char *buffer = NULL;
+	
+	crm_malloc(buffer, sizeof(char)*(len+1));
+	if(buffer != NULL) {
+		snprintf(buffer, len, "%d", an_int);
+	}
+	
 	return buffer;
 }
 
 unsigned int crm_log_level = LOG_INFO;
 
 /* returns the old value */
 unsigned int
 set_crm_log_level(unsigned int level)
 {
 	unsigned int old = crm_log_level;
 
 	while(crm_log_level < level) {
 		alter_debug(DEBUG_INC);
 	}
 	while(crm_log_level > level) {
 		alter_debug(DEBUG_DEC);
 	}
 	
 	return old;
 }
 
 unsigned int
 get_crm_log_level(void)
 {
 	return crm_log_level;
 }
 
 void
 do_crm_log(int log_level, const char *function, const char *fmt, ...)
 {
 	int log_as = log_level;
 	gboolean do_log = FALSE;
 	if(log_level < LOG_INFO) {
 		do_log = TRUE;
 
 	} else if(log_level <= crm_log_level) {
 		do_log = TRUE;
 		if(log_level != LOG_INFO) {
 			log_as = LOG_DEBUG;
 		}
 	}
 
 	if(do_log) {
 		va_list ap;
 		char	buf[MAXLINE];
 		int	nbytes;
 		
 		memset(buf, EOS, sizeof(buf)-1);
 		/*			buf[MAXLINE-1] = EOS; */
 		va_start(ap, fmt);
 		nbytes=vsnprintf(buf, sizeof(buf)-1, fmt, ap);
 		va_end(ap);
 		
 		if(function == NULL) {
 			cl_log(log_as, "[%d] %s", log_level, buf);
 		} else {
 			cl_log(log_as, "(%s [%d]) %s", function,log_level,buf);
 		}
 	}
 }
 
 int
 compare_version(const char *version1, const char *version2)
 {
 	int lpc = 0;
 	char *step1 = NULL, *step2 = NULL;
 	char *rest1 = NULL, *rest2 = NULL;
 
-	if(version1 != NULL) rest1 = crm_strdup(version1);
-	if(version2 != NULL) rest2 = crm_strdup(version2);
-
+	if(version1 != NULL) {
+		rest1 = crm_strdup(version1);
+	} else {
+		version1 = "<null>";
+	}
+	if(version2 != NULL) {
+		rest2 = crm_strdup(version2);
+	} else {
+		version2 = "<null>";
+	}
+	
 	while(1) {
 		int cmp = 0;
 		int step1_i = 0;
 		int step2_i = 0;
 		char *tmp1 = NULL, *tmp2 = NULL;
 		
 		decodeNVpair(rest1, '.', &step1, &tmp1);
 		decodeNVpair(rest2, '.', &step2, &tmp2);
 
 		if(step1 != NULL) {
 			step1_i = atoi(step1);
 		}
 		if(step2 != NULL) {
 			step2_i = atoi(step2);
 		}
 
 		if(step1_i < step2_i){
 			cmp = -1;
 		} else if (step1_i > step2_i){
 			cmp = 1;
 		}
 
 		crm_trace("compare[%d (%d)]: %d(%s)  %d(%s)",
 			  lpc++, cmp,
-			  step1_i, step1, step2_i, step2);
+			  step1_i, crm_str(step1),
+			  step2_i, crm_str(step2));
 
 		crm_free(rest1);
 		crm_free(rest2);
 
 		rest1 = tmp1;
 		rest2 = tmp2;
 
 		if(step1 == NULL && step2 == NULL) {
 			break;
 		}
 
 		crm_free(step1);
 		crm_free(step2);
 		
 		if(cmp < 0) {
 			crm_verbose("%s < %s", version1, version2);
 			return -1;
 			
 		} else if(cmp > 0) {
 			crm_verbose("%s > %s", version1, version2);
 			return 1;
 		}
 	}
 	crm_verbose("%s == %s", version1, version2);
 	return 0;
 }
 
 gboolean do_stderr = FALSE;
 
 void
 alter_debug(int nsig) 
 {
 	CL_SIGNAL(DEBUG_INC, alter_debug);
 	CL_SIGNAL(DEBUG_DEC, alter_debug);
 	
 	switch(nsig) {
 		case DEBUG_INC:
 			if(do_stderr == FALSE && crm_log_level == LOG_INFO) {
 				do_stderr = TRUE;
 				cl_log_enable_stderr(do_stderr);
 				break;
 			}
 
 			crm_log_level++;
 			fprintf(stderr,
 				"Upped log level to %d\n", crm_log_level);
 			cl_log(LOG_INFO,
 			       "Upped log level to %d\n", crm_log_level);
 			break;
 
 		case DEBUG_DEC:
 			if(do_stderr && crm_log_level == LOG_INFO) {
 				do_stderr = FALSE;
 				cl_log_enable_stderr(do_stderr);
 				break;
 			}
 
 			crm_log_level--;
 			fprintf(stderr,
 				"Reduced log level to %d\n", crm_log_level);
 			cl_log(LOG_INFO,
 			       "Reduced log level to %d\n", crm_log_level);
 			break;	
 
 		default:
 			fprintf(stderr, "Unknown signal %d\n", nsig);
 			cl_log(LOG_ERR, "Unknown signal %d\n", nsig);
 			break;	
 	}
 }
diff --git a/crm/common/xml.c b/crm/common/xml.c
index 439f3ec3df..af60dd4fba 100644
--- a/crm/common/xml.c
+++ b/crm/common/xml.c
@@ -1,705 +1,708 @@
-/* $Id: xml.c,v 1.12 2004/09/14 05:54:43 andrew Exp $ */
+/* $Id: xml.c,v 1.13 2004/09/17 13:03:09 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <time.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <libxml/tree.h>
 #include <clplumbing/ipc.h>
 #include <clplumbing/cl_log.h> 
 
 #include <crm/crm.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/dmalloc_wrapper.h>
 
 void dump_array(int log_level, const char *message,
 		const char **array, int depth);
 
 
 xmlNodePtr
 find_xml_node(xmlNodePtr root, const char * search_path)
 {
 	if(search_path == NULL) {
 		crm_warn("Will never find <NULL>");
 		return NULL;
 	}
 	
 	xml_child_iter(
 		root, a_child, search_path,
 		crm_trace("returning node (%s).", xmlGetNodePath(a_child));
 		crm_trace("contents\t%s", dump_xml_formatted(a_child));
 		crm_trace("found in\t%s", dump_xml_formatted(root));
 		return a_child;
 		);
 
 	crm_warn("Could not find %s in %s.", search_path, xmlGetNodePath(root));
 	return NULL;
 }
 
 xmlNodePtr
 find_xml_node_nested(xmlNodePtr root, const char **search_path, int len)
 {
 	int	j;
 	gboolean is_found = TRUE;
 	xmlNodePtr match =  NULL;
 	xmlNodePtr lastMatch = root;
 	
 	if(search_path == NULL || search_path[0] == NULL) {
 		crm_warn("Will never find NULL");
 		return NULL;
 	}
 	
 	dump_array(LOG_TRACE, "Looking for.", search_path, len);
 
 	for (j=0; j < len; ++j) {
 		if (search_path[j] == NULL) {
 /* a NULL also means stop searching */
 			break;
 		}
 
 		match = find_xml_node(lastMatch, search_path[j]);
 		if(match == NULL) {
 			is_found = FALSE;
 			break;
 		} else {
 			lastMatch = match;
 		}
 	}
 
 	if (is_found) {
 		crm_trace("returning node (%s).",
 			   xmlGetNodePath(lastMatch));
 
 		crm_trace("found\t%s", dump_xml_formatted(lastMatch));
 		crm_trace("in \t%s", dump_xml_formatted(root));
 		
 		return lastMatch;
 	}
 
 	dump_array(LOG_WARNING,
 		   "Could not find the full path to the node you specified.",
 		   search_path, len);
 
 	crm_warn("Closest point was node (%s) starting from %s.",
 	       xmlGetNodePath(lastMatch), root?root->name:NULL);
 
 	return NULL;
     
 }
 
 
 const char *
 get_xml_attr(xmlNodePtr parent,
 	     const char *node_name, const char *attr_name,
 	     gboolean error)
 {
 
 	if(node_name == NULL) {
 		/* get it from the current node */
 		return get_xml_attr_nested(parent, NULL, 0, attr_name, error);
 	}
 	return get_xml_attr_nested(parent, &node_name, 1, attr_name, error);
 
 }
 
 
 const char *
 get_xml_attr_nested(xmlNodePtr parent,
 		    const char **node_path, int length,
 		    const char *attr_name, gboolean error)
 {
 	const char *attr_value = NULL;
 	xmlNodePtr attr_parent = NULL;
 
 	if(parent == NULL) {
 		crm_err("Can not find attribute %s in NULL parent",
 		       attr_name);
 		return NULL;
 	} 
 
 	if(attr_name == NULL || strlen(attr_name) == 0) {
 		crm_err("Can not find attribute with no name in %s",
 		       xmlGetNodePath(parent));
 		return NULL;
 	}
 	
 	if(length == 0) {
 		attr_parent = parent;
 		
 	} else {
 		attr_parent = find_xml_node_nested(parent, node_path, length);
 		if(attr_parent == NULL && error) {
 			crm_err("No node at the path you specified.");
 			return NULL;
 		}
 	}
 	
 	attr_value = xmlGetProp(attr_parent, attr_name);
 	if((attr_value == NULL || strlen(attr_value) == 0) && error) {
 		crm_err(
 		       "No value present for %s at %s",
 		       attr_name, xmlGetNodePath(attr_parent));
 		return NULL;
 	}
 	
 	return attr_value;
 }
 
 xmlNodePtr
 set_xml_attr(
 	xmlNodePtr parent,
 	const char *node_name, const char *attr_name, const char *attr_value,
 	gboolean create)
 {
 	xmlNodePtr node = parent;
 	xmlAttrPtr result = NULL;
 	
 	if(node_name != NULL) {
 		crm_trace("Setting %s=%s at [%s [%s]]",
 			  attr_name, attr_value,
 			  xmlGetNodePath(parent), node_name);
 		node = find_xml_node(parent, node_name);
 		if(node == NULL && create) {
 			node = create_xml_node(parent, node_name);
 			if(parent == NULL) {
 				parent = node;
 			}
 		}
 	}
 
 	if(node == NULL) {
 		crm_warn("Can not set attribute on NULL node");
 		return NULL;
 	} 
 
 	result = set_xml_property_copy(node, attr_name, attr_value);
 	if(result == NULL) {
 		crm_warn("Could not set %s=%s at %s (found in %s)",
 			 attr_name, attr_value,
 			 xmlGetNodePath(node), xmlGetNodePath(parent));
 	}
 
 	return parent;
 }
 
 xmlNodePtr
 find_entity(xmlNodePtr parent,
 	    const char *node_name,
 	    const char *id,
 	    gboolean siblings)
 {
 	while(parent != NULL) {
 		xml_child_iter(
 			parent, a_child, node_name,
 			if(id == NULL 
 			   || safe_str_eq(id,xmlGetProp(a_child,XML_ATTR_ID))){
 				crm_debug("returning node (%s).", 
 					  xmlGetNodePath(a_child));
 				return a_child;
 			}
 			);
 		if(siblings) {
 			parent = parent->next;
 		} else {
 			break;
 		}
 	}
 	crm_warn("node <%s id=%s> not found in %s.",
 		 node_name, id, xmlGetNodePath(parent));
 	return NULL;
 }
 
 
 void
 copy_in_properties(xmlNodePtr target, xmlNodePtr src)
 {
 	if(src == NULL) {
 		crm_err("No node to copy properties from");
 	} else if (src->properties == NULL) {
 		crm_info("No properties to copy");
 	} else if (target == NULL) {
 		crm_err("No node to copy properties into");
 	} else {
 #ifndef USE_BUGGY_LIBXML
 		xmlAttrPtr prop_iter = NULL;
 		
 		prop_iter = src->properties;
 		while(prop_iter != NULL) {
 			const char *local_prop_name = prop_iter->name;
 			const char *local_prop_value =
 				xmlGetProp(src, local_prop_name);
 			
 			set_xml_property_copy(target,
 					      local_prop_name,
 					      local_prop_value);
 			
 			prop_iter = prop_iter->next;
 		}
 #else
 		xmlCopyPropList(target, src->properties);
 #endif
 	}
 	
 	return;
 }
 
 xmlNodePtr
 add_node_copy(xmlNodePtr new_parent, xmlNodePtr xml_node)
 {
 	xmlNodePtr node_copy = NULL;
 
 	if(xml_node != NULL && new_parent != NULL) {
 		node_copy = copy_xml_node_recursive(xml_node);
 		xmlAddChild(new_parent, node_copy);
 
 	} else if(xml_node == NULL) {
 		crm_err("Could not add copy of NULL node");
 
 	} else {
 		crm_err("Could not add copy of node to NULL parent");
 	}
 	
 	return node_copy;
 }
 
 xmlAttrPtr
 set_xml_property_copy(xmlNodePtr node,
 		      const xmlChar *name,
 		      const xmlChar *value)
 {
 	const char *parent_name = NULL;
 	const char *local_name = NULL;
 	const char *local_value = NULL;
 
 	xmlAttrPtr ret_value = NULL;
 	
 
 	if(node != NULL) {
 		parent_name = node->name;
 	}
-
 	
-	crm_trace("[%s] Setting %s to %s", parent_name, name, value);
+	crm_trace("[%s] Setting %s to %s",crm_str(parent_name), name, value);
+
 	if (name == NULL || strlen(name) <= 0) {
 		ret_value = NULL;
 		
-	} else if(node == NULL) {
+	} else if(node == NULL || parent_name == NULL) {
 		ret_value = NULL;
 		
 	} else if (value == NULL || strlen(value) <= 0) {
 		ret_value = NULL;
 		xmlUnsetProp(node, local_name);
 		
 	} else {
 		local_value = crm_strdup(value);
 		local_name = crm_strdup(name);
 		ret_value = xmlSetProp(node, local_name, local_value);
 	}
 	
 	return ret_value;
 }
 
 xmlNodePtr
 create_xml_node(xmlNodePtr parent, const char *name)
 {
 	const char *local_name = NULL;
 	const char *parent_name = NULL;
 	xmlNodePtr ret_value = NULL;
 	
 
 	if (name == NULL || strlen(name) < 1) {
 		ret_value = NULL;
 	} else {
 		local_name = crm_strdup(name);
 
 		if(parent == NULL) 
 			ret_value = xmlNewNode(NULL, local_name);
 		else {
 			parent_name = parent->name;
 			ret_value =
 				xmlNewChild(parent, NULL, local_name, NULL);
 		}
 	}
 
 	crm_trace("Created node [%s [%s]]", parent_name, local_name);
 	return ret_value;
 }
 
 void
 unlink_xml_node(xmlNodePtr node)
 {
 	xmlUnlinkNode(node);
 	/* this helps us with frees and really should be being done by
 	 * the library call
 	 */
 	node->doc = NULL;
 }
 
 void
 free_xml(xmlNodePtr a_node)
 {
 	
         if(a_node == NULL) {
-	  ; /*  nothing to do */
+		; /*  nothing to do */
 	} else if (a_node->doc != NULL) {
-	  xmlFreeDoc(a_node->doc);
+		xmlFreeDoc(a_node->doc);
 	} else {
-	  /* make sure the node is unlinked first */
-	  xmlUnlinkNode(a_node);
-	  xmlFreeNode(a_node);
+		/* make sure the node is unlinked first */
+		xmlUnlinkNode(a_node);
+		xmlFreeNode(a_node);
 	}
 	
 	return;
 }
 
 void
 set_node_tstamp(xmlNodePtr a_node)
 {
-	char *since_epoch = (char*)crm_malloc(128*(sizeof(char)));
+	char *since_epoch = NULL;
 	
-	sprintf(since_epoch, "%ld", (unsigned long)time(NULL));
-	set_xml_property_copy(a_node, XML_ATTR_TSTAMP, since_epoch);
-	crm_free(since_epoch);
+	crm_malloc(since_epoch, 128*(sizeof(char)));
+	if(since_epoch != NULL) {
+		sprintf(since_epoch, "%ld", (unsigned long)time(NULL));
+		set_xml_property_copy(a_node, XML_ATTR_TSTAMP, since_epoch);
+		crm_free(since_epoch);
+	}
 }
 
 xmlNodePtr
 copy_xml_node_recursive(xmlNodePtr src_node)
 {
 #if XML_TRACE
 	const char *local_name = NULL;
 	xmlNodePtr local_node = NULL, local_child = NULL;
 	xmlAttrPtr prop_iter = NULL;
 
 	if(src_node != NULL && src_node->name != NULL) {
 		local_node = create_xml_node(NULL, src_node->name);
 
 		prop_iter = src_node->properties;
 		while(prop_iter != NULL) {
 			const char *local_prop_name = prop_iter->name;
 			const char *local_prop_value =
 				xmlGetProp(src_node, local_prop_name);
 
 			set_xml_property_copy(local_node,
 					      local_prop_name,
 					      local_prop_value);
 			
 			prop_iter = prop_iter->next;
 			
 		}
 
 		xml_child_iter(
 			node_iter, src_node, NULL,
 
 			local_child = copy_xml_node_recursive(node_iter);
 			if(local_child != NULL) {
 				xmlAddChild(local_node, local_child);
 				crm_trace("Copied node [%s [%s]", local_name, local_child->name);
 			} 				
 			);
 
 		crm_trace("Returning [%s]", local_node->name);
 		return local_node;
 	}
 
 	crm_trace("Returning null");
 	return NULL;
 #else
 	return xmlCopyNode(src_node, 1);
 #endif
 }
 
 
 xmlNodePtr
 string2xml(const char *input)
 {
 	char ch = 0;
 	int lpc = 0, input_len = strlen(input);
 	gboolean more = TRUE;
 	gboolean inTag = FALSE;
 	xmlNodePtr xml_object = NULL;
 	const char *the_xml;
 	xmlDocPtr doc;
 
 	xmlBufferPtr xml_buffer = xmlBufferCreate();
 	
 	for(lpc = 0; (lpc < input_len) && more; lpc++) {
 		ch = input[lpc];
 		switch(ch) {
 			case EOF: 
 			case 0:
 				ch = 0;
 				more = FALSE; 
 				xmlBufferAdd(xml_buffer, &ch, 1);
 				break;
 			case '>':
 			case '<':
 				inTag = TRUE;
 				if(ch == '>') inTag = FALSE;
 				xmlBufferAdd(xml_buffer, &ch, 1);
 				break;
 			case '\n':
 			case '\t':
 			case ' ':
 				ch = ' ';
 				if(inTag) {
 					xmlBufferAdd(xml_buffer, &ch, 1);
 				} 
 				break;
 			default:
 				xmlBufferAdd(xml_buffer, &ch, 1);
 				break;
 		}
 	}
 
 	
 	xmlInitParser();
 	the_xml = xmlBufferContent(xml_buffer);
 	doc = xmlParseMemory(the_xml, strlen(the_xml));
 	xmlCleanupParser();
 
 	if (doc == NULL) {
 		crm_err("Malformed XML [xml=%s]", the_xml);
 		xmlBufferFree(xml_buffer);
 		return NULL;
 	}
 
 	xmlBufferFree(xml_buffer);
 	xml_object = xmlDocGetRootElement(doc);
 
 	return xml_object;
 }
 
 xmlNodePtr
 file2xml(FILE *input)
 {
 	char ch = 0;
 	gboolean more = TRUE;
 	gboolean inTag = FALSE;
 	xmlNodePtr xml_object = NULL;
 	xmlBufferPtr xml_buffer = xmlBufferCreate();
 	const char *the_xml;
 	xmlDocPtr doc;
 
 	if(input == NULL) {
 		crm_err("File pointer was NULL");
 		return NULL;
 	}
 	
 	while (more) {
 		ch = fgetc(input);
 /* 		crm_debug("Got [%c]", ch); */
 		switch(ch) {
 			case EOF: 
 			case 0:
 				ch = 0;
 				more = FALSE; 
 				xmlBufferAdd(xml_buffer, &ch, 1);
 				break;
 			case '>':
 			case '<':
 				inTag = TRUE;
 				if(ch == '>') inTag = FALSE;
 				xmlBufferAdd(xml_buffer, &ch, 1);
 				break;
 			case '\n':
 			case '\t':
 			case ' ':
 				ch = ' ';
 				if(inTag) {
 					xmlBufferAdd(xml_buffer, &ch, 1);
 				} 
 				break;
 			default:
 				xmlBufferAdd(xml_buffer, &ch, 1);
 				break;
 		}
 	}
 
 	xmlInitParser();
 	the_xml = xmlBufferContent(xml_buffer);
 	doc = xmlParseMemory(the_xml, strlen(the_xml));
 	xmlCleanupParser();
 	
 	if (doc == NULL) {
 		crm_err("Malformed XML [xml=%s]", the_xml);
 		xmlBufferFree(xml_buffer);
 		return NULL;
 	}
 	xmlBufferFree(xml_buffer);
 	xml_object = xmlDocGetRootElement(doc);
 
 	crm_xml_devel(xml_object, "Created fragment");
 
 	return xml_object;
 }
 
 void
 dump_array(int log_level, const char *message, const char **array, int depth)
 {
 	int j;
 	
 	if(message != NULL) {
 		do_crm_log(log_level, __FUNCTION__,  "%s", message);
 	}
 
 	do_crm_log(log_level, __FUNCTION__,  "Contents of the array:");
 	if(array == NULL || array[0] == NULL || depth == 0) {
 		do_crm_log(log_level, __FUNCTION__,  "\t<empty>");
+		return;
 	}
 	
 	for (j=0; j < depth && array[j] != NULL; j++) {
 		if (array[j] == NULL) break;
 		do_crm_log(log_level, __FUNCTION__,  "\t--> (%s).", array[j]);
 	}
 }
 
 int
 write_xml_file(xmlNodePtr xml_node, const char *filename) 
 {
 	int res = 0;
 	xmlDocPtr foo = NULL;
 	char now_str[26];
 	time_t now;
 
 	crm_debug("Writing XML out to %s", filename);
 	
 	if (xml_node == NULL) {
 		return -1;
 		
 	} else if (xml_node->doc == NULL) {
 		crm_trace("Creating doc pointer for %s", xml_node->name);
 		foo = xmlNewDoc("1.0");
 		xmlDocSetRootElement(foo, xml_node);
 		xmlSetTreeDoc(xml_node, foo);
 	}
 
 	now = time(NULL);
 	ctime_r(&now, now_str);
 	set_xml_property_copy(xml_node, "last_written",now_str);
 
 	/* save it.
 	 * set arg 3 to 0 to disable line breaks,1 to enable
 	 * res == num bytes saved
 	 */
 	res = xmlSaveFormatFile(filename, xml_node->doc, 1);
 	
 	/* for some reason, reading back after saving with
 	 * line-breaks doesnt go real well 
 	 */
 	crm_debug("Saved %d bytes to the Cib as XML", res);
 
 	return res;
 }
 
 char *
 dump_xml_formatted(xmlNodePtr an_xml_node) {
 	int len = 0;
 	xmlChar *buffer = NULL;
 	xmlDocPtr foo = NULL;
 
 	xmlNodePtr xml_node = copy_xml_node_recursive(an_xml_node);
 	
 	if (xml_node == NULL) {
 		return NULL;
 		
 	} else {
 	  // reset the doc pointer
 		crm_trace("Creating doc pointer for %s", xml_node->name);
 		foo = xmlNewDoc("1.0");
 		xmlDocSetRootElement(foo, xml_node);
 		xmlSetTreeDoc(xml_node, foo);
 		crm_trace("Doc pointer set for %s", xml_node->name);
 	}
 
 	crm_trace("Initializing Parser");
 	xmlInitParser();
 	crm_trace("Dumping data");
 	xmlDocDumpFormatMemory(xml_node->doc, &buffer, &len,1);
 	crm_trace("Cleaning up parser");
 	xmlCleanupParser();
 	
 	free_xml(xml_node);
 
 	return buffer;
 }
 
 void
 print_xml_formatted (int log_level, const char *function,
 		     xmlNodePtr msg, const char *text)
 {
 	char *msg_buffer;
 
 	if(msg == NULL) {
 		do_crm_log(log_level, function, "%s: %s",
-			   text==NULL?"<null>":text, "<null>");
+			   crm_str(text), "<null>");
 		return;
 	}
 	
 	msg_buffer = dump_xml_formatted(msg);
 	do_crm_log(log_level, function, "%s: %s",
-		   text==NULL?"<null>":text,
-		   msg_buffer==NULL?"<null>":msg_buffer);
+		   crm_str(text), crm_str(msg_buffer));
 	crm_free(msg_buffer);
 
 	return;
 }
 
 char *
 dump_xml_unformatted(xmlNodePtr an_xml_node) {
 	int len = 0;
 	xmlBufferPtr xml_buffer;
 	xmlChar *buffer = NULL;
 
 	if (an_xml_node == NULL) {
 		return NULL;
 	}
 
 	crm_trace("Initializing Parser");
 	xmlInitParser();
 	crm_trace("Dumping data");
 	
 	xml_buffer = xmlBufferCreate();
 	len = xmlNodeDump(xml_buffer, an_xml_node->doc, an_xml_node, 0, 0);
 	
 	if(len < 0) {
 		crm_err("Error dumping xml");
 		xmlBufferFree(xml_buffer);
 		return NULL;
 	}
 	
 	buffer = (xmlChar*)crm_strdup(xmlBufferContent(xml_buffer)); 
 	xmlBufferFree(xml_buffer);
 
 	if (!buffer) {
 		crm_err("memory allocation failed");
 	}
 
 	crm_trace("Cleaning up parser");
 	xmlCleanupParser();
 
 	return buffer;
 }
diff --git a/crm/crmd/callbacks.c b/crm/crmd/callbacks.c
index c89aa78fbf..1eb82fb222 100644
--- a/crm/crmd/callbacks.c
+++ b/crm/crmd/callbacks.c
@@ -1,402 +1,401 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <string.h>
 #include <crmd_fsa.h>
 #include <libxml/tree.h>
 
 #include <heartbeat.h>
 
 #include <hb_api.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 #include <crm/cib.h>
 
 #include <crmd.h>
 #include <crmd_messages.h>
 #include <crmd_callbacks.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 FILE *msg_in_strm = NULL;
 FILE *msg_ipc_strm = NULL;
 
 xmlNodePtr find_xml_in_hamessage(const struct ha_msg* msg);
 gboolean crmd_ha_input_dispatch(int fd, gpointer user_data);
 void crmd_ha_input_destroy(gpointer user_data);
 
 void
 crmd_ha_input_callback(const struct ha_msg* msg, void* private_data)
 {
 	const char *from = ha_msg_value(msg, F_ORIG);
 	const char *to = NULL;
 	xmlNodePtr root_xml_node;
 
 	
 
 #ifdef MSG_LOG
 	if(msg_in_strm == NULL) {
 		msg_in_strm = fopen(DEVEL_DIR"/inbound.log", "w");
 	}
 #endif
 
 	if(safe_str_eq(from, fsa_our_uname)) {
 #ifdef MSG_LOG
 		fprintf(msg_in_strm,
 			"Discarded message [F_SEQ=%s] from ourselves.\n",
 			ha_msg_value(msg, F_SEQ));
 		fflush(msg_in_strm);
 #endif
 		return;
 	} else if(from == NULL) {
 		crm_err("Value of %s was NULL", F_ORIG);
 	}
 	
 #ifdef MSG_LOG
-	fprintf(msg_in_strm, "[%s (%s:%s)]\t%s\n",
-		from,
+	fprintf(msg_in_strm, "[%s (%s:%s)]\t%s\n", crm_str(from),
 		ha_msg_value(msg, F_SEQ),
 		ha_msg_value(msg, F_TYPE),
 		ha_msg_value(msg, "xml")
 		);
 	fflush(msg_in_strm);
 #endif
 
 	root_xml_node = find_xml_in_hamessage(msg);
 	to = xmlGetProp(root_xml_node, XML_ATTR_HOSTTO);
 	
 	if(to != NULL && strlen(to) > 0 && strcmp(to, fsa_our_uname) != 0) {
 #ifdef MSG_LOG
 		fprintf(msg_in_strm,
 			"Discarding message [F_SEQ=%s] for someone else.",
 			ha_msg_value(msg, F_SEQ));
 #endif
 		return;
 	}
 
 	set_xml_property_copy(root_xml_node, XML_ATTR_HOSTFROM, from);
 	s_crmd_fsa(C_HA_MESSAGE, I_ROUTER, root_xml_node);
 
 	free_xml(root_xml_node);
 
 	return;
 }
 
 /*
  * Apparently returning TRUE means "stay connected, keep doing stuff".
  * Returning FALSE means "we're all done, close the connection"
  */
 gboolean
 crmd_ipc_input_callback(IPC_Channel *client, gpointer user_data)
 {
 	int lpc = 0;
 	char *buffer = NULL;
 	IPC_Message *msg = NULL;
 	gboolean hack_return_good = TRUE;
 	xmlNodePtr root_xml_node;
 	crmd_client_t *curr_client = (crmd_client_t*)user_data;
 
 	
 	crm_verbose("Processing IPC message from %s",
 		   curr_client->table_key);
 
 #ifdef MSG_LOG
 	if(msg_ipc_strm == NULL) {
 		msg_ipc_strm = fopen(DEVEL_DIR"/inbound.ipc.log", "w");
 	}
 #endif
 
 
 	while(client->ops->is_message_pending(client)) {
 		if (client->ch_status == IPC_DISCONNECT) {
 			/* The message which was pending for us is that
 			 * the IPC status is now IPC_DISCONNECT */
 			break;
 		}
 		if (client->ops->recv(client, &msg) != IPC_OK) {
 			perror("Receive failure:");
 #ifdef MSG_LOG
 			fprintf(msg_ipc_strm, "[%s] [receive failure]\n",
 				curr_client->table_key);
 			fflush(msg_in_strm);
 #endif
 			return !hack_return_good;
 		}
 		if (msg == NULL) {
 #ifdef MSG_LOG
 			fprintf(msg_ipc_strm, "[%s] [__nothing__]\n",
 				curr_client->table_key);
 			fflush(msg_in_strm);
 #endif
 			crm_err("No message this time");
 			continue;
 		}
 
 		lpc++;
 		buffer = (char*)msg->msg_body;
 		crm_verbose("Processing xml from %s [text=%s]\n",
 			   curr_client->table_key, buffer);
 	
 #ifdef MSG_LOG
 		fprintf(msg_ipc_strm, "[%s] [text=%s]\n",
 			curr_client->table_key, buffer);
 		fflush(msg_in_strm);
 #endif
 
 		root_xml_node = find_xml_in_ipcmessage(msg, FALSE);
 	
 		if (root_xml_node != NULL) {
 			if (crmd_authorize_message(
 				    root_xml_node, msg, curr_client)) {
 				s_crmd_fsa(
 					C_IPC_MESSAGE,I_ROUTER,root_xml_node);
 			}
 
 		} else {
 			crm_info("IPC Message was not valid... discarding.");
 		}
 		free_xml(root_xml_node);
 		msg->msg_done(msg);
 		
 		msg = NULL;
 		buffer = NULL;
 		root_xml_node = NULL;
 	}
 
 	crm_verbose("Processed %d messages", lpc);
     
 	if (client->ch_status == IPC_DISCONNECT)
 	{
 		crm_info("received HUP from %s",
 			 curr_client->table_key);
 		if (curr_client != NULL) {
 			struct crm_subsystem_s *the_subsystem = NULL;
 			
 			if (curr_client->sub_sys == NULL) {
 				crm_warn("Client hadn't registered with us yet");
 
 			} else if (strcmp(CRM_SYSTEM_PENGINE,
 					  curr_client->sub_sys) == 0) {
 				the_subsystem = pe_subsystem;
 
 			} else if (strcmp(CRM_SYSTEM_TENGINE,
 					  curr_client->sub_sys) == 0) {
 				the_subsystem = te_subsystem;
 
 			} else if (strcmp(CRM_SYSTEM_CIB,
 					  curr_client->sub_sys) == 0){
 				the_subsystem = cib_subsystem;
 			}
 			
 			if(the_subsystem != NULL) {
 				cleanup_subsystem(the_subsystem);
 			} /* else that was a transient client */
 			
 			if (curr_client->table_key != NULL) {
 				/*
 				 * Key is destroyed below:
 				 *	curr_client->table_key
 				 * Value is cleaned up by:
 				 *	G_main_del_IPC_Channel
 				 */
 				g_hash_table_remove(
 					ipc_clients, curr_client->table_key);
 			}
 
 
 			if(curr_client->client_source != NULL) {
 				gboolean det = G_main_del_IPC_Channel(
 					curr_client->client_source);
 			
 				crm_verbose("crm_client was %s detached",
 					   det?"successfully":"not");
 			}
 			
 			crm_free(curr_client->table_key);
 			crm_free(curr_client->sub_sys);
 			crm_free(curr_client->uuid);
 			crm_free(curr_client);
 		}
 		return !hack_return_good;
 	}
     
 	return hack_return_good;
 }
 
 
 void
 lrm_op_callback (lrm_op_t* op)
 {
 	s_crmd_fsa(C_LRM_OP_CALLBACK, I_LRM_EVENT, op);
 }
 
 void
 crmd_client_status_callback(const char * node, const char * client,
 		 const char * status, void * private)
 {
 	const char    *join = NULL;
 	const char   *extra = NULL;
 	xmlNodePtr   update = NULL;
 	xmlNodePtr fragment = NULL;
 	xmlNodePtr msg_options = NULL;
 	xmlNodePtr request = NULL;
 
 	if(safe_str_eq(status, JOINSTATUS)){
 		status = ONLINESTATUS;
 		extra  = XML_CIB_ATTR_CLEAR_SHUTDOWN;
 
 	} else if(safe_str_eq(status, LEAVESTATUS)){
 		status = OFFLINESTATUS;
 		join   = CRMD_JOINSTATE_DOWN;
 		extra  = XML_CIB_ATTR_CLEAR_SHUTDOWN;
 	}
 	
 	crm_notice("Status update: Client %s/%s now has status [%s]\n",
 		   node, client, status);
 
 	if(AM_I_DC) {
 		update = create_node_state(node, node, NULL, status, join);
 
 		if(extra != NULL) {
 			set_xml_property_copy(update, extra, XML_BOOLEAN_TRUE);
 		}
 		
 		fragment = create_cib_fragment(update, NULL);
 /*		store_request(NULL, fragment, */
 /*			      CRM_OP_UPDATE, CRM_SYSTEM_DCIB); */
 
 		msg_options = set_xml_attr(
 			NULL, XML_TAG_OPTIONS, XML_ATTR_OP, CRM_OP_UPDATE, TRUE);
 		
 /*		crm_verbose("Storing op=%s message for later processing", operation); */
 		
 		request = create_request(
 			msg_options, fragment, NULL, CRM_SYSTEM_DCIB, CRM_SYSTEM_DC, NULL, NULL);
 
 		free_xml(fragment);
 		free_xml(update);
 
 /*		s_crmd_fsa(C_CRMD_STATUS_CALLBACK, I_NULL, NULL); */
 		s_crmd_fsa(C_CRMD_STATUS_CALLBACK, I_CIB_OP, request);
 		
 	} else {
 		crm_err("Got client status callback in non-DC mode");
 	}
 }
 
 
 xmlNodePtr
 find_xml_in_hamessage(const struct ha_msg* msg)
 {
 	const char *xml;
    	xmlDocPtr doc;
 	xmlNodePtr root;
 
 	
 	if (msg == NULL) {
 		crm_info("**** ha_crm_msg_callback called on a NULL message");
 		return NULL;
 	}
 
 #if 0
 	crm_debug("[F_TYPE=%s]", ha_msg_value(msg, F_TYPE));
 	crm_debug("[F_ORIG=%s]", ha_msg_value(msg, F_ORIG));
 	crm_debug("[F_TO=%s]", ha_msg_value(msg, F_TO));
 	crm_debug("[F_COMMENT=%s]", ha_msg_value(msg, F_COMMENT));
 	crm_debug("[F_XML=%s]", ha_msg_value(msg, "xml"));
 /*    crm_debug("[F_=%s]", ha_msg_value(ha_msg, F_)); */
 #endif
 	
 	if (strcmp("CRM", ha_msg_value(msg, F_TYPE)) != 0) {
 		crm_info("Received a (%s) message by mistake.",
 		       ha_msg_value(msg, F_TYPE));
 		return NULL;
 	}
 	xml = ha_msg_value(msg, "xml");
 	if (xml == NULL) {
 		crm_info("No XML attached to this message.");
 		return NULL;
 	}
 	doc = xmlParseMemory(xml, strlen(xml));
 	if (doc == NULL) {
 		crm_info("XML Buffer was not valid.");
 		return NULL;
 	}
 
 	root = xmlDocGetRootElement(doc);
 	if (root == NULL) {
 		crm_info("Root node was NULL.");
 		return NULL;
 	}
 	return root;
 }
 
 gboolean lrm_dispatch(int fd, gpointer user_data)
 {
 	ll_lrm_t *lrm = (ll_lrm_t*)user_data;
 	lrm->lrm_ops->rcvmsg(lrm, FALSE);
 	return TRUE;
 }
 
 #define MAX_EMPTY_CALLBACKS 20
 int empty_callbacks = 0;
 
 gboolean
 crmd_ha_input_dispatch(int fd, gpointer user_data)
 {
 	int lpc = 0;
 	ll_cluster_t *hb_cluster = (ll_cluster_t*)user_data;
     
 	while(hb_cluster->llc_ops->msgready(hb_cluster)) {
 		lpc++;
 		empty_callbacks = 0;
 		/* invoke the callbacks but dont block */
 		hb_cluster->llc_ops->rcvmsg(hb_cluster, 0);
 	}
 
 	if(lpc == 0) {
 		/* hey what happened?? */
 		crm_warn("We were called but no message was ready."
 		       "  Likely the connection to Heartbeat failed,"
 			" check the logs.");
 
 		if(empty_callbacks++ > MAX_EMPTY_CALLBACKS) {
 			crm_err("%d empty callbacks received..."
 				" considering heartbeat dead",
 				MAX_EMPTY_CALLBACKS);
 
 			/* s_crmd_fsa(C_HA_DISCONNECT, I_ERROR, NULL); */
 
 			return FALSE;
 		}
 	}
 	
     
 	return TRUE;
 }
 
 void
 crmd_ha_input_destroy(gpointer user_data)
 {
 	crm_crit("Heartbeat has left us");
 	/* this is always an error */
 	/* feed this back into the FSA */
 	s_crmd_fsa(C_HA_DISCONNECT, I_ERROR, NULL);
 }
diff --git a/crm/crmd/ccm.c b/crm/crmd/ccm.c
index 758115f2b5..cd52e8191e 100644
--- a/crm/crmd/ccm.c
+++ b/crm/crmd/ccm.c
@@ -1,566 +1,580 @@
-/* $Id: ccm.c,v 1.33 2004/08/30 03:17:38 msoffen Exp $ */
+/* $Id: ccm.c,v 1.34 2004/09/17 13:03:09 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 /* put these first so that uuid_t is defined without conflicts */
 #include <portability.h>
 #include <ocf/oc_event.h>
 #include <ocf/oc_membership.h>
 
 #include <clplumbing/GSource.h>
 #include <string.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crmd_messages.h>
 #include <crmd_fsa.h>
 #include <fsa_proto.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 void oc_ev_special(const oc_ev_t *, oc_ev_class_t , int );
 
 int register_with_ccm(ll_cluster_t *hb_cluster);
 
 void msg_ccm_join(const struct ha_msg *msg, void *foo);
 
 void crmd_ccm_input_callback(oc_ed_t event,
 			     void *cookie,
 			     size_t size,
 			     const void *data);
 
 void ccm_event_detail(const oc_ev_membership_t *oc, oc_ed_t event);
 gboolean ccm_dispatch(int fd, gpointer user_data);
 
 gboolean ghash_node_clfree(gpointer key, gpointer value, gpointer user_data);
 void ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data);
 
 #define CCM_EVENT_DETAIL 1
 oc_ev_t *fsa_ev_token;
 
 /*	 A_CCM_CONNECT	*/
 enum crmd_fsa_input
 do_ccm_control(long long action,
 		enum crmd_fsa_cause cause,
 		enum crmd_fsa_state cur_state,
 		enum crmd_fsa_input current_input,
 		void *data)
 {
 	int      ret;
  	int	 fsa_ev_fd; 
     
 	
 
 	if(action & A_CCM_DISCONNECT){
 		oc_ev_unregister(fsa_ev_token);
 
 	}
 
 	if(action & A_CCM_CONNECT) {
 		
 		crm_info("Registering with CCM");
 		oc_ev_register(&fsa_ev_token);
 		
 		crm_info("Setting up CCM callbacks");
 		oc_ev_set_callback(fsa_ev_token, OC_EV_MEMB_CLASS,
 				   crmd_ccm_input_callback,
 				   NULL);
 
 		oc_ev_special(fsa_ev_token, OC_EV_MEMB_CLASS, 0/*don't care*/);
 		
 		crm_info("Activating CCM token");
 		ret = oc_ev_activate(fsa_ev_token, &fsa_ev_fd);
 		if (ret){
 			crm_info("CCM Activation failed... unregistering");
 			oc_ev_unregister(fsa_ev_token);
 			return(I_FAIL);
 		}
 		crm_info("CCM Activation passed... all set to go!");
 
 /* GFDSource* */
 		G_main_add_fd(G_PRIORITY_LOW, fsa_ev_fd, FALSE, ccm_dispatch,
 			      fsa_ev_token,
 			      default_ipc_input_destroy);
 		
 	}
 
 	if(action & ~(A_CCM_CONNECT|A_CCM_DISCONNECT)) {
 		crm_err("Unexpected action %s in %s",
 		       fsa_action2string(action), __FUNCTION__);
 	}
 	
 	return I_NULL;
 }
 
 
 /*	 A_CCM_EVENT	*/
 enum crmd_fsa_input
 do_ccm_event(long long action,
 	     enum crmd_fsa_cause cause,
 	     enum crmd_fsa_state cur_state,
 	     enum crmd_fsa_input current_input,
 	     void *data)
 {
 	enum crmd_fsa_input return_input = I_NULL;
 	const oc_ev_membership_t *oc = ((struct ccm_data *)data)->oc;
 	oc_ed_t event = *((struct ccm_data *)data)->event;
 
 	
 
 	crm_info("event=%s", 
 	       event==OC_EV_MS_NEW_MEMBERSHIP?"NEW MEMBERSHIP":
 	       event==OC_EV_MS_NOT_PRIMARY?"NOT PRIMARY":
 	       event==OC_EV_MS_PRIMARY_RESTORED?"PRIMARY RESTORED":
 	       event==OC_EV_MS_EVICTED?"EVICTED":
 	       "NO QUORUM MEMBERSHIP");
 	
 	if(CCM_EVENT_DETAIL) {
 		ccm_event_detail(oc, event);
 	}
 
 	if (OC_EV_MS_EVICTED == event) {
 		/* get out... NOW! */
 		return_input = I_SHUTDOWN;
 
 	}
 	
 	if(return_input == I_SHUTDOWN) {
 		; /* ignore everything, the new DC will handle it */
 	} else {
 		/* My understanding is that we will never get both
 		 * node leaving *and* node joining callbacks at the
 		 * same time.
 		 *
 		 * This logic would need to change if this is not
 		 * the case
 		 */
 
 		if(oc->m_n_out !=0) {
 			return_input = I_NODE_LEFT;
 
 		} else if(oc->m_n_in !=0) {
 			/* delay the I_NODE_JOIN until they acknowledge our
 			 * DC status and send us their CIB
 			 */
 			return_input = I_NULL;
 		} else {
 			crm_warn("So why are we here?  What CCM event happened?");
 		}
 	}
 
 	return return_input;
 }
 
 /*	 A_CCM_UPDATE_CACHE	*/
 /*
  * Take the opportunity to update the node status in the CIB as well
  *  (but only if we are the DC)
  */
 enum crmd_fsa_input
 do_ccm_update_cache(long long action,
 		    enum crmd_fsa_cause cause,
 		    enum crmd_fsa_state cur_state,
 		    enum crmd_fsa_input current_input,
 		    void *data)
 {
 	enum crmd_fsa_input next_input = I_NULL;
 	int lpc, offset;
 	GHashTable *members = NULL;
 	oc_ed_t event = *((struct ccm_data *)data)->event;
 	const oc_ev_membership_t *oc = ((struct ccm_data *)data)->oc;
 
-	oc_node_list_t *tmp = NULL, *membership_copy = (oc_node_list_t *)
-		crm_malloc(sizeof(oc_node_list_t));
-
-	
+	oc_node_list_t *tmp = NULL, *membership_copy = NULL;
+	crm_malloc(membership_copy, sizeof(oc_node_list_t));
 
 	crm_info("Updating CCM cache after a \"%s\" event.", 
 	       event==OC_EV_MS_NEW_MEMBERSHIP?"NEW MEMBERSHIP":
 	       event==OC_EV_MS_NOT_PRIMARY?"NOT PRIMARY":
 	       event==OC_EV_MS_PRIMARY_RESTORED?"PRIMARY RESTORED":
 	       event==OC_EV_MS_EVICTED?"EVICTED":
 	       "NO QUORUM MEMBERSHIP");
 
+	if(membership_copy == NULL) {
+		crm_crit("Couldnt create membership copy - out of memory");
+		return I_ERROR;
+	}
+	
 	/*--*-- All Member Nodes --*--*/
 	offset = oc->m_memb_idx;
 	membership_copy->members_size = oc->m_n_member;
 
 	if(membership_copy->members_size > 0) {
 		membership_copy->members =
 			g_hash_table_new(g_str_hash, g_str_equal);
 		members = membership_copy->members;
 		
 		for(lpc=0; lpc < membership_copy->members_size; lpc++) {
-			oc_node_t *member = (oc_node_t *)
-				crm_malloc(sizeof(oc_node_t));
+			oc_node_t *member = NULL;
+			crm_malloc(member, sizeof(oc_node_t));
 			
+			if(member == NULL) {
+				continue;
+			}
+
 			member->node_id =
 				oc->m_array[offset+lpc].node_id;
 			
 			member->node_born_on =
 				oc->m_array[offset+lpc].node_born_on;
 			
 			member->node_uname =
 				crm_strdup(oc->m_array[offset+lpc].node_uname);
 
 			g_hash_table_insert(members, member->node_uname, member);	
 		}
 		
 	} else {
 		membership_copy->members = NULL;
 	}
 	
 	/*--*-- New Member Nodes --*--*/
 	offset = oc->m_in_idx;
 	membership_copy->new_members_size = oc->m_n_in;
 
 	if(membership_copy->new_members_size > 0) {
 		membership_copy->new_members =
 			g_hash_table_new(g_str_hash, g_str_equal);
 		members = membership_copy->new_members;
 		
 		for(lpc=0; lpc < membership_copy->new_members_size; lpc++) {
-			oc_node_t *member = (oc_node_t *)
-				crm_malloc(sizeof(oc_node_t));
+			oc_node_t *member = NULL;
+			crm_malloc(member, sizeof(oc_node_t));
+
+			if(member == NULL) {
+				continue;
+			}
 			
 			member->node_id =
 				oc->m_array[offset+lpc].node_id;
 			
 			member->node_born_on =
 				oc->m_array[offset+lpc].node_born_on;
 
 			member->node_uname =
 				crm_strdup(oc->m_array[offset+lpc].node_uname);
 
 			g_hash_table_insert(members, member->node_uname, member);
 		}
 
 	} else {
 		membership_copy->new_members = NULL;
 	}
 	
 	/*--*-- Recently Dead Member Nodes --*--*/
 	offset = oc->m_out_idx;
 	membership_copy->dead_members_size = oc->m_n_out;
 	if(membership_copy->dead_members_size > 0) {
 		membership_copy->dead_members =
 			g_hash_table_new(g_str_hash, g_str_equal);
 
 		members = membership_copy->dead_members;
 
 		for(lpc=0; lpc < membership_copy->dead_members_size; lpc++) {
-			oc_node_t *member = (oc_node_t *)
-				crm_malloc(sizeof(oc_node_t));
+			oc_node_t *member = NULL;
+			crm_malloc(member, sizeof(oc_node_t));
+
+			if(member == NULL) {
+				continue;
+			}
 			
 			member->node_id =
 				oc->m_array[offset+lpc].node_id;
 			
 			member->node_born_on =
 				oc->m_array[offset+lpc].node_born_on;
 			
 			member->node_uname =
 				crm_strdup(oc->m_array[offset+lpc].node_uname);
 
 			g_hash_table_insert(members, member->node_uname, member);
 		}
 
 	} else {
 		membership_copy->dead_members = NULL;
 	}
 
 	tmp = fsa_membership_copy;
 	fsa_membership_copy = membership_copy;
 
 	if(AM_I_DC) {
 		/* should be sufficient for only the DC to do this */
 		free_xml(do_update_cib_nodes(NULL, FALSE));
 	}
 	
 	/* Free the old copy */
 	if(tmp != NULL) {
 		if(tmp->members != NULL)
 			g_hash_table_foreach_remove(
 				tmp->members, ghash_node_clfree, NULL);
 		if(tmp->new_members != NULL)
 			g_hash_table_foreach_remove(
 				tmp->new_members, ghash_node_clfree, NULL);
 		if(tmp->dead_members != NULL)
 			g_hash_table_foreach_remove(
 				tmp->dead_members, ghash_node_clfree, NULL);
 		crm_free(tmp);
 	}
 	
 	return next_input;
 }
 
 void
 ccm_event_detail(const oc_ev_membership_t *oc, oc_ed_t event)
 {
 	int member_id = -1;
 	gboolean member = FALSE;
 	int lpc;
 	int node_list_size;
 
 	crm_info("trans=%d, nodes=%d, new=%d, lost=%d n_idx=%d, "
 	       "new_idx=%d, old_idx=%d",
 	       oc->m_instance,
 	       oc->m_n_member,
 	       oc->m_n_in,
 	       oc->m_n_out,
 	       oc->m_memb_idx,
 	       oc->m_in_idx,
 	       oc->m_out_idx);
 	
 	crm_info("NODES IN THE PRIMARY MEMBERSHIP");
 	
 	node_list_size = oc->m_n_member;
 	for(lpc=0; lpc<node_list_size; lpc++) {
 		crm_info("\t%s [nodeid=%d, born=%d]",
 		       oc->m_array[oc->m_memb_idx+lpc].node_uname,
 		       oc->m_array[oc->m_memb_idx+lpc].node_id,
 		       oc->m_array[oc->m_memb_idx+lpc].node_born_on);
 
 		crm_verbose("%s ? %s", fsa_our_uname,
 			  oc->m_array[oc->m_memb_idx+lpc].node_uname);
 		if(safe_str_eq(fsa_our_uname,
 			       oc->m_array[oc->m_memb_idx+lpc].node_uname)) {
 			member = TRUE;
 			member_id = oc->m_array[oc->m_memb_idx+lpc].node_id;
 		}
 	}
 	
 	if (member == FALSE) {
 		crm_warn("MY NODE IS NOT IN CCM THE MEMBERSHIP LIST");
 	} else {
 		crm_info("MY NODE ID IS %d", member_id);
 	}
 	
 	
 	crm_info("NEW MEMBERS");
 	if (oc->m_n_in==0) 
 		crm_info("\tNONE");
 	
 	for(lpc=0; lpc<oc->m_n_in; lpc++) {
 		crm_info("\t%s [nodeid=%d, born=%d]",
 		       oc->m_array[oc->m_in_idx+lpc].node_uname,
 		       oc->m_array[oc->m_in_idx+lpc].node_id,
 		       oc->m_array[oc->m_in_idx+lpc].node_born_on);
 	}
 	
 	crm_info("MEMBERS LOST");
 	if (oc->m_n_out==0) 
 		crm_info("\tNONE");
 	
 	for(lpc=0; lpc<oc->m_n_out; lpc++) {
 		crm_info("\t%s [nodeid=%d, born=%d]",
 		       oc->m_array[oc->m_out_idx+lpc].node_uname,
 		       oc->m_array[oc->m_out_idx+lpc].node_id,
 		       oc->m_array[oc->m_out_idx+lpc].node_born_on);
 		if(fsa_our_uname != NULL
 		   && strcmp(fsa_our_uname,
 			     oc->m_array[oc->m_memb_idx+lpc].node_uname)) {
 			crm_err("We're not part of the cluster anymore");
 		}
 	}
 	
 	crm_info("-----------------------");
 	
 }
 
 int
 register_with_ccm(ll_cluster_t *hb_cluster)
 {
 	return 0;
 }
 
 gboolean ccm_dispatch(int fd, gpointer user_data)
 {
 	oc_ev_t *ccm_token = (oc_ev_t*)user_data;
 	oc_ev_handle_event(ccm_token);
 	return TRUE;
 }
 
 
 void 
 crmd_ccm_input_callback(oc_ed_t event,
 			void *cookie,
 			size_t size,
 			const void *data)
 {
 	struct ccm_data *event_data = NULL;
 	
-	
-
 	if(data != NULL) {
-		event_data = (struct ccm_data *)
-			crm_malloc(sizeof(struct ccm_data));
-		
-		event_data->event = &event;
-		event_data->oc = (const oc_ev_membership_t *)data;
-		
-		s_crmd_fsa(C_CCM_CALLBACK, I_CCM_EVENT, (void*)event_data);
-		
-		event_data->event = NULL;
-		event_data->oc = NULL;
+		crm_malloc(event_data, sizeof(struct ccm_data));
 
-		crm_free(event_data);
+		if(event_data != NULL) {
+			event_data->event = &event;
+			event_data->oc = (const oc_ev_membership_t *)data;
+			
+			s_crmd_fsa(C_CCM_CALLBACK, I_CCM_EVENT, (void*)event_data);
+			
+			event_data->event = NULL;
+			event_data->oc = NULL;
+
+			crm_free(event_data);
+		}
 
 	} else {
 		crm_info("CCM Callback with NULL data... "
 		       "I dont /think/ this is bad");
 	}
 	
 	oc_ev_callback_done(cookie);
 	
 	return;
 }
 
 void 
 msg_ccm_join(const struct ha_msg *msg, void *foo)
 {
 	
 	crm_verbose("\n###### Recieved ccm_join message...");
 	if (msg != NULL)
 	{
 		crm_verbose("[type=%s]",
 			    ha_msg_value(msg, F_TYPE));
 		crm_verbose("[orig=%s]",
 			    ha_msg_value(msg, F_ORIG));
 		crm_verbose("[to=%s]",
 			    ha_msg_value(msg, F_TO));
 		crm_verbose("[status=%s]",
 			    ha_msg_value(msg, F_STATUS));
 		crm_verbose("[info=%s]",
 			    ha_msg_value(msg, F_COMMENT));
 		crm_verbose("[rsc_hold=%s]",
 			    ha_msg_value(msg, F_RESOURCES));
 		crm_verbose("[stable=%s]",
 			    ha_msg_value(msg, F_ISSTABLE));
 		crm_verbose("[rtype=%s]",
 			    ha_msg_value(msg, F_RTYPE));
 		crm_verbose("[ts=%s]",
 			    ha_msg_value(msg, F_TIME));
 		crm_verbose("[seq=%s]",
 			    ha_msg_value(msg, F_SEQ));
 		crm_verbose("[generation=%s]",
 			    ha_msg_value(msg, F_HBGENERATION));
 		/*      crm_verbose("[=%s]", ha_msg_value(msg, F_)); */
 	}
 	return;
 }
 
 struct update_data_s
 {
 		xmlNodePtr updates;
 		const char *state;
 		const char *join;
 };
 
 xmlNodePtr
 do_update_cib_nodes(xmlNodePtr updates, gboolean overwrite)
 {
 	
 	struct update_data_s update_data;
 	update_data.updates = updates;
 	
 	update_data.state = XML_BOOLEAN_NO;
 	update_data.join  = CRMD_JOINSTATE_DOWN;
 	if(fsa_membership_copy->dead_members != NULL) {
 		g_hash_table_foreach(fsa_membership_copy->dead_members,
 				     ghash_update_cib_node, &update_data);
 	}
 	
 	update_data.state = XML_BOOLEAN_YES;
 	update_data.join  = NULL;
 	if(overwrite) {
 		update_data.join = CRMD_JOINSTATE_PENDING;
 	}
 	
 	if(fsa_membership_copy->members != NULL) {
 		g_hash_table_foreach(fsa_membership_copy->members,
 				     ghash_update_cib_node, &update_data);
 	}
 
 	/* this is most likely overkill...
 	 *
 	 * make *sure* that the join status of nodes entering the ccm list
 	 *  is reset
 	 *
 	update_data.join = CRMD_JOINSTATE_PENDING;
 	if(fsa_membership_copy->new_members != NULL) {
 		g_hash_table_foreach(fsa_membership_copy->new_members,
 				     ghash_update_cib_node, &update_data);
 	}
 */
 	if(update_data.updates != NULL) {
 		xmlNodePtr fragment =
 			create_cib_fragment(update_data.updates, NULL);
 
 		invoke_local_cib(NULL, fragment, CRM_OP_UPDATE);
 		
 		free_xml(fragment);
 	}
 
 	/* so it can be freed */
 	return update_data.updates;
 
 }
 
 void
 ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data)
 {
 	xmlNodePtr tmp1 = NULL;
 	const char *node_uname = (const char*)key;
 	struct update_data_s* data = (struct update_data_s*)user_data;
 	const char *state = data->join;
 
 	crm_verbose("%s processing %s (%s)",
 		  __FUNCTION__, node_uname, data->state);
 
 	if(state != NULL
 	   && safe_str_eq(fsa_our_uname, node_uname)) {
 		/* the DC is always a member */
 		state = CRMD_JOINSTATE_MEMBER;
 	} 
 
 	tmp1 = create_node_state(node_uname, node_uname,
 				 data->state, NULL, state);
 
 	if(data->updates == NULL) {
 		crm_verbose("Creating first update");
 		data->updates = tmp1;
 	} else {
 		xmlAddNextSibling(data->updates, tmp1);
 	}
 
 }
 
 gboolean
 ghash_node_clfree(gpointer key, gpointer value, gpointer user_data)
 {
 	/* value->node_uname is free'd as "key" */
 	if(key != NULL) {
 		crm_free(key);
 	}
 	if(value != NULL) {
 		crm_free(value);
 	}
 	return TRUE;
 }
diff --git a/crm/crmd/control.c b/crm/crmd/control.c
index 84fd3e26fd..6a5775bc14 100644
--- a/crm/crmd/control.c
+++ b/crm/crmd/control.c
@@ -1,555 +1,579 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <sys/param.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ctrl.h>
 
 #include <crmd.h>
 #include <crmd_fsa.h>
 #include <fsa_proto.h>
 #include <crmd_messages.h>
 #include <crmd_callbacks.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 extern gboolean crmd_ha_input_dispatch(int fd, gpointer user_data);
 extern void crmd_ha_input_destroy(gpointer user_data);
 
 void crm_shutdown(int nsig);
 
 IPC_WaitConnection *wait_channel_init(char daemonsocket[]);
 
 int init_server_ipc_comms(
 	const char *child,
 	gboolean (*channel_client_connect)(IPC_Channel *newclient,
 					   gpointer user_data),
 	void (*channel_input_destroy)(gpointer user_data));
 
 
 gboolean
 register_with_ha(ll_cluster_t *hb_cluster, const char *client_name,
 		 gboolean (*dispatch_method)(int fd, gpointer user_data),
 		 void (*message_callback)(const struct ha_msg* msg,
 					  void* private_data),
 		 GDestroyNotify cleanup_method);
 
 GHashTable   *ipc_clients = NULL;
 
 /*	 A_HA_CONNECT	*/
 enum crmd_fsa_input
 do_ha_control(long long action,
 	       enum crmd_fsa_cause cause,
 	       enum crmd_fsa_state cur_state,
 	       enum crmd_fsa_input current_input,
 	       void *data)
 {
 	gboolean registered = FALSE;
 	
 	
 
 	if(action & A_HA_DISCONNECT) {
 		if(fsa_cluster_conn != NULL) {
 			fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn);
 		}
 		
 	}
 	
 	if(action & A_HA_CONNECT) {
 		if(fsa_cluster_conn == NULL)
 			fsa_cluster_conn = ll_cluster_new("heartbeat");
 
 		/* make sure we are disconnected first */
 		fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn);
 		
 		registered = register_with_ha(fsa_cluster_conn,
 					      crm_system_name,
 					      crmd_ha_input_dispatch,
 					      crmd_ha_input_callback,
 					      crmd_ha_input_destroy);
 		
 		if(registered == FALSE) {
 			return I_FAIL;
 		}
 	} 
 	
 	if(action & ~(A_HA_CONNECT|A_HA_DISCONNECT)) {
 		crm_err("Unexpected action %s in %s",
 		       fsa_action2string(action), __FUNCTION__);
 	}
 	
 	
 	return I_NULL;
 }
 
 /*	 A_SHUTDOWN	*/
 enum crmd_fsa_input
 do_shutdown(long long action,
 	    enum crmd_fsa_cause cause,
 	    enum crmd_fsa_state cur_state,
 	    enum crmd_fsa_input current_input,
 	    void *data)
 {
 	enum crmd_fsa_input next_input = I_NULL;
 	enum crmd_fsa_input tmp = I_NULL;
 	
 	
 
 	/* last attempt to shut these down */
 	if(is_set(fsa_input_register, R_PE_CONNECTED)) {
 		crm_warn("Last attempt to shutdown the PolicyEngine");
 		tmp = do_pe_control(A_PE_STOP, cause, cur_state,
 				    current_input, data);
 		if(tmp != I_NULL) {
 			next_input = I_ERROR;
 			crm_err("Failed to shutdown the PolicyEngine");
 		}
 	}
 
 	if(is_set(fsa_input_register, R_TE_CONNECTED)) {
 		crm_warn("Last attempt to shutdown the Transitioner");
 		tmp = do_pe_control(A_TE_STOP, cause, cur_state,
 				    current_input, data);
 		if(tmp != I_NULL) {
 			next_input = I_ERROR;
 			crm_err("Failed to shutdown the Transitioner");
 		}
 		
 	}
 
 	/* TODO: shutdown all remaining resources? */
 	
 	return next_input;
 }
 
 /*	 A_SHUTDOWN_REQ	*/
 enum crmd_fsa_input
 do_shutdown_req(long long action,
 	    enum crmd_fsa_cause cause,
 	    enum crmd_fsa_state cur_state,
 	    enum crmd_fsa_input current_input,
 	    void *data)
 {
 	enum crmd_fsa_input next_input = I_NULL;
 	
 
 	if(send_request(NULL, NULL, CRM_OP_SHUTDOWN_REQ,
 			NULL, CRM_SYSTEM_DC, NULL) == FALSE){
 		next_input = I_ERROR;
 	}
 
 	return next_input;
 }
 
 /*	 A_EXIT_0, A_EXIT_1	*/
 enum crmd_fsa_input
 do_exit(long long action,
 	enum crmd_fsa_cause cause,
 	enum crmd_fsa_state cur_state,
 	enum crmd_fsa_input current_input,
 	void *data)
 {
 	
 
 	crm_err("Action %s (%.16llx) not supported\n",
 		fsa_action2string(action), action);
 
 	if(action & A_EXIT_0) {
 		g_main_quit(crmd_mainloop);
 	} else {
 		exit(1);
 	}
 	
 	return I_NULL;
 }
 
 
 /*	 A_STARTUP	*/
 enum crmd_fsa_input
 do_startup(long long action,
 	   enum crmd_fsa_cause cause,
 	   enum crmd_fsa_state cur_state,
 	   enum crmd_fsa_input current_input,
 	   void *data)
 {
 	int facility;
 	int was_error = 0;
 	int interval = 1; /* seconds between DC heartbeats */
 
 	fsa_input_register = 0; /* zero out the regester */
 	
 	crm_info("Register PID");
 	register_pid(PID_FILE, FALSE, crm_shutdown);
 	
 	ipc_clients = g_hash_table_new(&g_str_hash, &g_str_equal);
 	
 	/* change the logging facility to the one used by heartbeat daemon */
 	fsa_cluster_conn = ll_cluster_new("heartbeat");
 	
 	crm_info("Switching to Heartbeat logger");
 	if ((facility =
 	     fsa_cluster_conn->llc_ops->get_logfacility(
 		     fsa_cluster_conn)) > 0) {
 		cl_log_set_facility(facility);
 	}
 	
 	crm_verbose("Facility: %d", facility);
 	
 	if(was_error == 0) {
 		crm_info("Init server comms");
 		was_error = init_server_ipc_comms(
 			CRM_SYSTEM_CRMD, crmd_client_connect,
 			default_ipc_input_destroy);
 	}	
 
 	/* set up the timers */
-	dc_heartbeat     = (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
-	integration_timer= (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
-	election_trigger = (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
-	election_timeout = (fsa_timer_t *)crm_malloc(sizeof(fsa_timer_t));
-	shutdown_escalation_timmer = (fsa_timer_t *)
-		crm_malloc(sizeof(fsa_timer_t));
-
+	crm_malloc(dc_heartbeat, sizeof(fsa_timer_t));
+	crm_malloc(integration_timer, sizeof(fsa_timer_t));
+	crm_malloc(election_trigger, sizeof(fsa_timer_t));
+	crm_malloc(election_timeout, sizeof(fsa_timer_t));
+	crm_malloc(shutdown_escalation_timmer, sizeof(fsa_timer_t));
 
 	interval = interval * 1000;
-	
-	election_trigger->source_id = -1;
-	election_trigger->period_ms = -1;
-	election_trigger->fsa_input = I_DC_TIMEOUT;
-	election_trigger->callback = timer_popped;
-
-	dc_heartbeat->source_id = -1;
-	dc_heartbeat->period_ms = -1;
-	dc_heartbeat->fsa_input = I_NULL;
-	dc_heartbeat->callback = do_dc_heartbeat;
-		
-	election_timeout->source_id = -1;
-	election_timeout->period_ms = -1;
-	election_timeout->fsa_input = I_ELECTION_DC;
-	election_timeout->callback = timer_popped;
 
-	integration_timer->source_id = -1;
-	integration_timer->period_ms = -1;
-	integration_timer->fsa_input = I_INTEGRATION_TIMEOUT;
-	integration_timer->callback = timer_popped;
+	if(election_trigger != NULL) {
+		election_trigger->source_id = -1;
+		election_trigger->period_ms = -1;
+		election_trigger->fsa_input = I_DC_TIMEOUT;
+		election_trigger->callback = timer_popped;
+	} else {
+		was_error = TRUE;
+	}
+	
+	if(dc_heartbeat != NULL) {
+		dc_heartbeat->source_id = -1;
+		dc_heartbeat->period_ms = -1;
+		dc_heartbeat->fsa_input = I_NULL;
+		dc_heartbeat->callback = do_dc_heartbeat;
+	} else {
+		was_error = TRUE;
+	}
+	
+	if(election_timeout != NULL) {
+		election_timeout->source_id = -1;
+		election_timeout->period_ms = -1;
+		election_timeout->fsa_input = I_ELECTION_DC;
+		election_timeout->callback = timer_popped;
+	} else {
+		was_error = TRUE;
+	}
+	
+	if(integration_timer != NULL) {
+		integration_timer->source_id = -1;
+		integration_timer->period_ms = -1;
+		integration_timer->fsa_input = I_INTEGRATION_TIMEOUT;
+		integration_timer->callback = timer_popped;
+	} else {
+		was_error = TRUE;
+	}
 	
-	shutdown_escalation_timmer->source_id = -1;
-	shutdown_escalation_timmer->period_ms = -1;
-	shutdown_escalation_timmer->fsa_input = I_TERMINATE;
-	shutdown_escalation_timmer->callback = timer_popped;
+	if(shutdown_escalation_timmer != NULL) {
+		shutdown_escalation_timmer->source_id = -1;
+		shutdown_escalation_timmer->period_ms = -1;
+		shutdown_escalation_timmer->fsa_input = I_TERMINATE;
+		shutdown_escalation_timmer->callback = timer_popped;
+	} else {
+		was_error = TRUE;
+	}
 	
 	/* set up the sub systems */
-	cib_subsystem = (struct crm_subsystem_s*)
-		crm_malloc(sizeof(struct crm_subsystem_s));
-	
-	cib_subsystem->pid = 0;	
-	cib_subsystem->respawn = 1;	
-	cib_subsystem->path = crm_strdup(BIN_DIR);
-	cib_subsystem->name = crm_strdup(CRM_SYSTEM_CIB);
-	cib_subsystem->command = BIN_DIR"/cib";
-	cib_subsystem->flag = R_CIB_CONNECTED;	
-
-	te_subsystem = (struct crm_subsystem_s*)
-		crm_malloc(sizeof(struct crm_subsystem_s));
-	
-	te_subsystem->pid = 0;	
-	te_subsystem->respawn = 1;	
-	te_subsystem->path = crm_strdup(BIN_DIR);
-	te_subsystem->name = crm_strdup(CRM_SYSTEM_TENGINE);
-	te_subsystem->command = BIN_DIR"/tengine";
-	te_subsystem->flag = R_TE_CONNECTED;	
-
-	pe_subsystem = (struct crm_subsystem_s*)
-		crm_malloc(sizeof(struct crm_subsystem_s));
-	
-	pe_subsystem->pid = 0;	
-	pe_subsystem->respawn = 1;	
-	pe_subsystem->path = crm_strdup(BIN_DIR);
-	pe_subsystem->name = crm_strdup(CRM_SYSTEM_PENGINE);
-	pe_subsystem->command = BIN_DIR"/pengine";
-	pe_subsystem->flag = R_PE_CONNECTED;	
-
+	crm_malloc(cib_subsystem, sizeof(struct crm_subsystem_s));
+	crm_malloc(te_subsystem,  sizeof(struct crm_subsystem_s));
+	crm_malloc(pe_subsystem,  sizeof(struct crm_subsystem_s));
+
+	if(cib_subsystem != NULL) {
+		cib_subsystem->pid = 0;	
+		cib_subsystem->respawn = 1;	
+		cib_subsystem->path = crm_strdup(BIN_DIR);
+		cib_subsystem->name = crm_strdup(CRM_SYSTEM_CIB);
+		cib_subsystem->command = BIN_DIR"/cib";
+		cib_subsystem->flag = R_CIB_CONNECTED;	
+	} else {
+		was_error = TRUE;
+	}
+	
+	if(te_subsystem != NULL) {
+		te_subsystem->pid = 0;	
+		te_subsystem->respawn = 1;	
+		te_subsystem->path = crm_strdup(BIN_DIR);
+		te_subsystem->name = crm_strdup(CRM_SYSTEM_TENGINE);
+		te_subsystem->command = BIN_DIR"/tengine";
+		te_subsystem->flag = R_TE_CONNECTED;	
+	} else {
+		was_error = TRUE;
+	}
+	
+	if(pe_subsystem != NULL) {
+		pe_subsystem->pid = 0;	
+		pe_subsystem->respawn = 1;	
+		pe_subsystem->path = crm_strdup(BIN_DIR);
+		pe_subsystem->name = crm_strdup(CRM_SYSTEM_PENGINE);
+		pe_subsystem->command = BIN_DIR"/pengine";
+		pe_subsystem->flag = R_PE_CONNECTED;	
+	} else {
+		was_error = TRUE;
+	}
 
 	if(was_error)
 		return I_FAIL;
 	
 	return I_NULL;
 }
 
 
 /*	 A_STOP	*/
 enum crmd_fsa_input
 do_stop(long long action,
 	enum crmd_fsa_cause cause,
 	enum crmd_fsa_state cur_state,
 	enum crmd_fsa_input current_input,
 	void *data)
 {
 	
 
 	crm_err("Action %s (%.16llx) not supported\n",
 	       fsa_action2string(action), action);
 
 	return I_NULL;
 }
 
 /*	 A_STARTED	*/
 enum crmd_fsa_input
 do_started(long long action,
 	   enum crmd_fsa_cause cause,
 	   enum crmd_fsa_state cur_state,
 	   enum crmd_fsa_input current_input,
 	   void *data)
 {
 	
 
 	clear_bit_inplace(&fsa_input_register, R_STARTING);
 	
 	return I_NULL;
 }
 
 /*	 A_RECOVER	*/
 enum crmd_fsa_input
 do_recover(long long action,
 	   enum crmd_fsa_cause cause,
 	   enum crmd_fsa_state cur_state,
 	   enum crmd_fsa_input current_input,
 	   void *data)
 {
 	
 
 	crm_err("Action %s (%.16llx) not supported\n",
 	       fsa_action2string(action), action);
 
 	return I_SHUTDOWN;
 }
 
 /*	 A_READCONFIG	*/
 enum crmd_fsa_input
 do_read_config(long long action,
 	       enum crmd_fsa_cause cause,
 	       enum crmd_fsa_state cur_state,
 	       enum crmd_fsa_input current_input,
 	       void *data)
 {
 	xmlNodePtr cib_copy = get_cib_copy();
 	xmlNodePtr config   = get_object_root(XML_CIB_TAG_CRMCONFIG, cib_copy);
 
 	xml_child_iter(
 		config, iter, XML_CIB_TAG_NVPAIR,
 
 		const char *name  = xmlGetProp(iter, XML_NVPAIR_ATTR_NAME);
 		const char *value = xmlGetProp(iter, XML_NVPAIR_ATTR_VALUE);
 
 		if(name == NULL || value == NULL) {
 			xml_iter_continue(iter);
 			continue;
 			
 		} else if(safe_str_eq(name, "dc_heartbeat")) {
 			dc_heartbeat->period_ms = atoi(value);
 			
 		} else if(safe_str_eq(name, "dc_deadtime")) {
 			election_trigger->period_ms = atoi(value);
 
 		} else if(safe_str_eq(name, "shutdown_escalation")) {
 			shutdown_escalation_timmer->period_ms = atoi(value);
 
 		}
 		);
 	
 	
 	if(dc_heartbeat->period_ms < 1) {
 		/* sensible default */
 		dc_heartbeat->period_ms = 1000;
 		
 	}
 	if(election_trigger->period_ms < 1) {
 		/* sensible default */
 		election_trigger->period_ms = dc_heartbeat->period_ms * 4;
 		
 	}
 	if(shutdown_escalation_timmer->period_ms < 1) {
 		/* sensible default */
 		shutdown_escalation_timmer->period_ms
 			= election_trigger->period_ms * 3 *10;/* 10 for testing */
 	}
 	
 	election_timeout->period_ms  = dc_heartbeat->period_ms * 6;
 	integration_timer->period_ms = dc_heartbeat->period_ms * 6;
 
 	return I_NULL;
 }
 
 
 void
 crm_shutdown(int nsig)
 {
 	CL_SIGNAL(nsig, crm_shutdown);
     
 	if (crmd_mainloop != NULL && g_main_is_running(crmd_mainloop)) {
 
 		if(is_set(fsa_input_register, R_SHUTDOWN)) {
 			crm_err("Escalating the shutdown");
 			s_crmd_fsa(C_SHUTDOWN, I_ERROR, NULL);
 
 		} else {
 			set_bit_inplace(&fsa_input_register, R_SHUTDOWN);
 
 			if(is_set(fsa_input_register, R_SHUTDOWN)) {
 				/* cant rely on this... */
 				startTimer(shutdown_escalation_timmer);
 				
 				s_crmd_fsa(C_SHUTDOWN, I_SHUTDOWN, NULL);
 			} else {
 				crm_err("Could not set R_SHUTDOWN");
 				exit(LSB_EXIT_ENOTSUPPORTED);
 			}
 		}
 	} else {
 		crm_info("exit from shutdown");
 		exit(LSB_EXIT_OK);
 	    
 	}
 	return;
 }
 
 
 IPC_WaitConnection *
 wait_channel_init(char daemonsocket[])
 {
 	IPC_WaitConnection *wait_ch;
 	mode_t mask;
 	char path[] = IPC_PATH_ATTR;
 	GHashTable * attrs;
 
 	
 	attrs = g_hash_table_new(g_str_hash,g_str_equal);
 	g_hash_table_insert(attrs, path, daemonsocket);
     
 	mask = umask(0);
 	wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs);
 	if (wait_ch == NULL) {
 		cl_perror("Can't create wait channel of type %s",
 			  IPC_ANYTYPE);
 		exit(1);
 	}
 	mask = umask(mask);
     
 	g_hash_table_destroy(attrs);
     
 	return wait_ch;
 }
 
 int
 init_server_ipc_comms(
 	const char *child,
 	gboolean (*channel_client_connect)(IPC_Channel *newclient,
 					   gpointer user_data),
 	void (*channel_input_destroy)(gpointer user_data))
 {
 	/* the clients wait channel is the other source of events.
 	 * This source delivers the clients connection events.
 	 * listen to this source at a relatively lower priority.
 	 */
     
 	char    commpath[SOCKET_LEN];
 	IPC_WaitConnection *wait_ch;
 
 	
 	sprintf(commpath, WORKING_DIR "/%s", child);
 
 	wait_ch = wait_channel_init(commpath);
 
 	if (wait_ch == NULL) return 1;
 	G_main_add_IPC_WaitConnection(G_PRIORITY_LOW,
 				      wait_ch,
 				      NULL,
 				      FALSE,
 				      channel_client_connect,
 				      wait_ch, /* user data passed to ?? */
 				      channel_input_destroy);
 
 	crm_debug("Listening on: %s", commpath);
 
 	return 0;
 }
 
 #define safe_val3(def, t,u,v)       (t?t->u?t->u->v:def:def)
 
 gboolean
 register_with_ha(ll_cluster_t *hb_cluster, const char *client_name,
 		 gboolean (*dispatch_method)(int fd, gpointer user_data),
 		 void (*message_callback)(const struct ha_msg* msg,
 					  void* private_data),
 		 GDestroyNotify cleanup_method)
 {
 	if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) {
 	  crm_crit("cluster errmsg function unavailable");
 	}
 	crm_info("Signing in with Heartbeat");
 	if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) {
 		crm_err("Cannot sign on with heartbeat");
 		if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) {
 			crm_crit("cluster errmsg function unavailable");
 		} else {
 			crm_err("REASON: %s",
 				hb_cluster->llc_ops->errmsg(hb_cluster));
 		}
 		return FALSE;
 	}
   
 	crm_debug("Be informed of CRM messages");
 	if (hb_cluster->llc_ops->set_msg_callback(hb_cluster,
 						  "CRM",
 						  message_callback,
 						  hb_cluster)
 	    !=HA_OK){
 		crm_err("Cannot set CRM message callback");
 		if(safe_val3(NULL, hb_cluster, llc_ops, errmsg) == NULL) {
 			crm_crit("cluster errmsg function unavailable");
 		} else {
 			crm_err("REASON: %s",
 				hb_cluster->llc_ops->errmsg(hb_cluster));
 		}
 		return FALSE;
 	}
 	
 	G_main_add_fd(G_PRIORITY_HIGH, 
 		      hb_cluster->llc_ops->inputfd(hb_cluster),
 		      FALSE, 
 		      dispatch_method, 
 		      hb_cluster,  /* usrdata  */
 		      cleanup_method);
 
 	crm_debug("Finding our node name");
 	if ((fsa_our_uname =
 	     hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) {
 		crm_err("get_mynodeid() failed");
 		return FALSE;
 	}
 	crm_info("FSA Hostname: %s", fsa_our_uname);
 
 	return TRUE;
     
 }
diff --git a/crm/crmd/fsa.c b/crm/crmd/fsa.c
index 1c93b18bc0..8c5b449dd8 100644
--- a/crm/crmd/fsa.c
+++ b/crm/crmd/fsa.c
@@ -1,690 +1,690 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <clplumbing/Gmain_timeout.h>
 
 #include <crmd_messages.h>
 #include <crmd_fsa.h>
 #include <fsa_proto.h>
 #include <fsa_matrix.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 extern GHashTable *joined_nodes;
 
 long long
 do_state_transition(long long actions,
 		    enum crmd_fsa_cause cause,
 		    enum crmd_fsa_state cur_state,
 		    enum crmd_fsa_state next_state,
 		    enum crmd_fsa_input current_input,
 		    void *data);
 
 long long clear_flags(long long actions,
 			     enum crmd_fsa_cause cause,
 			     enum crmd_fsa_state cur_state,
 			     enum crmd_fsa_input cur_input);
 
 void dump_rsc_info(void);
 
 #ifdef DOT_FSA_ACTIONS
 # ifdef FSA_TRACE
 #  define IF_FSA_ACTION(x,y)						\
      if(is_set(actions,x)) {						\
 	crm_verbose("Invoking action %s (%.16llx)",			\
 		fsa_action2string(x), x);				\
 	last_action = x;						\
 	actions = clear_bit(actions, x);				\
 	next_input = y(x, cause, cur_state, last_input, data);		\
 	if( (x & O_DC_TICKLE) == 0 && next_input != I_DC_HEARTBEAT )	\
 		fprintf(dot_strm,					\
 			"\t// %s:\t%s\t(data? %p)\t(result=%s)\n",	\
 			fsa_input2string(cur_input),			\
 			fsa_action2string(x),				\
 			data,						\
 			fsa_input2string(next_input));			\
 	fflush(dot_strm);						\
 	crm_verbose("Result of action %s was %s",			\
 		fsa_action2string(x), fsa_input2string(next_input));	\
      }
 # else
 #  define IF_FSA_ACTION(x,y)						\
      if(is_set(actions,x)) {						\
 	last_action = x;						\
 	actions = clear_bit(actions, x);				\
 	next_input = y(x, cause, cur_state, last_input, data);		\
 	if( (x & O_DC_TICKLE) == 0 && next_input != I_DC_HEARTBEAT )	\
 		fprintf(dot_strm,					\
 			"\t// %s:\t%s\t(data? %p)\t(result=%s)\n",	\
 			fsa_input2string(cur_input),			\
 			fsa_action2string(x),				\
 			data,						\
 			fsa_input2string(next_input));			\
 	fflush(dot_strm);						\
      }
 # endif
 #else
 # ifdef FSA_TRACE
 #  define IF_FSA_ACTION(x,y)						\
      if(is_set(actions,x)) {						\
 	crm_verbose("Invoking action %s (%.16llx)",			\
 		fsa_action2string(x), x);				\
 	last_action = x;						\
 	actions = clear_bit(actions, x);				\
 	next_input = y(x, cause, cur_state, last_input, data);		\
 	crm_verbose("Result of action %s was %s",			\
 		fsa_action2string(x), fsa_input2string(next_input));	\
      }
 # else
 #  define IF_FSA_ACTION(x,y)						\
      if(is_set(actions,x)) {						\
 	last_action = x;						\
 	actions = clear_bit(actions, x);				\
 	next_input = y(x, cause, cur_state, last_input, data);		\
      }
 # endif
 #endif
 
-#define ELSEIF_FSA_ACTION(x,y) else IF_FSA_ACTION(x,y)
+/* #define ELSEIF_FSA_ACTION(x,y) else IF_FSA_ACTION(x,y) */
 
 const char *dot_intro = "digraph \"g\" {\n"
 "	size = \"30,30\"\n"
 "	graph [\n"
 "		fontsize = \"12\"\n"
 "		fontname = \"Times-Roman\"\n"
 "		fontcolor = \"black\"\n"
 "		bb = \"0,0,398.922306,478.927856\"\n"
 "		color = \"black\"\n"
 "	]\n"
 "	node [\n"
 "		fontsize = \"12\"\n"
 "		fontname = \"Times-Roman\"\n"
 "		fontcolor = \"black\"\n"
 "		shape = \"ellipse\"\n"
 "		color = \"black\"\n"
 "	]\n"
 "	edge [\n"
 "		fontsize = \"12\"\n"
 "		fontname = \"Times-Roman\"\n"
 "		fontcolor = \"black\"\n"
 "		color = \"black\"\n"
 "	]\n"
 "// special nodes\n"
 "	\"S_PENDING\" \n"
 "	[\n"
 "	 color = \"blue\"\n"
 "	 fontcolor = \"blue\"\n"
 "	 ]\n"
 "	\"S_TERMINATE\" \n"
 "	[\n"
 "	 color = \"red\"\n"
 "	 fontcolor = \"red\"\n"
 "	 ]\n"
 "\n"
 "// DC only nodes\n"
 "	\"S_RECOVERY_DC\" [ fontcolor = \"green\" ]\n"
 "	\"S_INTEGRATION\" [ fontcolor = \"green\" ]\n"
 "	\"S_POLICY_ENGINE\" [ fontcolor = \"green\" ]\n"
 "	\"S_TRANSITION_ENGINE\" [ fontcolor = \"green\" ]\n"
 "	\"S_RELEASE_DC\" [ fontcolor = \"green\" ]\n"
 "	\"S_IDLE\" [ fontcolor = \"green\" ]\n";
 
 
 static FILE *dot_strm = NULL;
 
 enum crmd_fsa_state fsa_state;
 oc_node_list_t *fsa_membership_copy;
 ll_cluster_t   *fsa_cluster_conn;
 ll_lrm_t       *fsa_lrm_conn;
 long long       fsa_input_register;
 long long       fsa_actions = A_NOTHING;
 const char     *fsa_our_uname;
 const char     *fsa_our_dc;
 
 fsa_timer_t *election_trigger = NULL;		/*  */
 fsa_timer_t *election_timeout = NULL;		/*  */
-fsa_timer_t *shutdown_escalation_timmer = NULL;	/*  */
+fsa_timer_t *shutdown_escalation_timmer = NULL; /*  */
 fsa_timer_t *integration_timer = NULL;
 fsa_timer_t *dc_heartbeat = NULL;
 
 enum crmd_fsa_state
 s_crmd_fsa(enum crmd_fsa_cause cause,
 	   enum crmd_fsa_input initial_input,
 	   void *data)
 {
 	long long actions = fsa_actions;
 	long long new_actions = A_NOTHING;
 	long long last_action = A_NOTHING;
 	enum crmd_fsa_input last_input = initial_input;
 	enum crmd_fsa_input cur_input;
 	enum crmd_fsa_input next_input;
 	enum crmd_fsa_state last_state, cur_state, next_state, starting_state;
 	
 	
 
 	starting_state = fsa_state;
 	cur_input  = initial_input;
 	next_input = initial_input;
 	
 	last_state = starting_state;
 	cur_state  = starting_state;
 	next_state = starting_state;
 
 #ifdef FSA_TRACE
 	crm_verbose("FSA invoked with Cause: %s\tState: %s, Input: %s",
 		   fsa_cause2string(cause),
 		   fsa_state2string(cur_state),
 		   fsa_input2string(cur_input));
 #endif
 
 #ifdef DOT_FSA_ACTIONS
 	if(dot_strm == NULL) {
 		dot_strm = fopen(DEVEL_DIR"/live.dot", "w");
 		fprintf(dot_strm, "%s", dot_intro);
 	}
 	fprintf(dot_strm,
 		"\t// FSA invoked: Cause=%s\tState=%s\tInput=%s\n",
 		   fsa_cause2string(cause),
 		   fsa_state2string(cur_state),
 		   fsa_input2string(cur_input));
 
 	fflush(dot_strm);
 #endif
 	/*
 	 * Process actions in order of priority but do only one
 	 * action at a time to avoid complicating the ordering.
 	 *
 	 * Actions may result in a new I_ event, these are added to
 	 * (not replace) existing actions before the next iteration.
 	 *
 	 */
 	while(next_input != I_NULL || actions != A_NOTHING || is_message()) {
 
 		if(next_input == I_WAIT_FOR_EVENT) {
 			/* we may be waiting for an a-sync task to "happen"
 			 * and until it does, we cant do anything else
 			 *
 			 * Re-add the last action
 			 */
 
 			actions |= last_action;
 					
 			crm_info("Wait until something else happens");
 			break;
 		}
 
 #ifdef FSA_TRACE
 		crm_verbose("FSA while loop:\tState: %s, Input: %s",
 			   fsa_state2string(cur_state),
 			   fsa_input2string(cur_input));
 #endif
 		
 		/* update input variables */
 		cur_input = next_input;
 		if(cur_input != I_NULL) {
 			last_input = cur_input;
 		}
 
 		/* get the next batch of actions */
 		new_actions = crmd_fsa_actions[cur_input][cur_state];
 		if(new_actions != A_NOTHING) {
 #ifdef FSA_TRACE
 			crm_verbose("Adding actions %.16llx", new_actions);
 #endif
 			actions |= new_actions;
 		}
 
 		/* logging : *before* the state is changed */
 		IF_FSA_ACTION(A_ERROR, do_log)
-		ELSEIF_FSA_ACTION(A_WARN, do_log)
-		ELSEIF_FSA_ACTION(A_LOG,  do_log)
+		else IF_FSA_ACTION(A_WARN, do_log)
+		else IF_FSA_ACTION(A_LOG,  do_log)
 
 		/* update state variables */
 		next_state  = crmd_fsa_state[cur_input][cur_state];
 		last_state  = cur_state;
 		cur_state   = next_state;
 		fsa_state   = next_state;
 
 		/* start doing things... */
 
 
 		/*
 		 * Hook for change of state.
 		 * Allows actions to be added or removed when entering a state
 		 */
 		if(last_state != cur_state){
 			actions = do_state_transition(actions, cause,
 						      last_state, cur_state,
 						      last_input, data);
 		}
 
 		/* this is always run, some inputs/states may make various
 		 * actions irrelevant/invalid
 		 */
 		actions = clear_flags(actions, cause, cur_state, cur_input);
 
 		/* regular action processing in order of action priority
 		 *
 		 * Make sure all actions that connect to required systems
 		 * are performed first
 		 */
 		if(actions == A_NOTHING) {
 
 			crm_info("Nothing to do");
 			next_input = I_NULL;
 		
 /*			// check registers, see if anything is pending
 			if(is_set(fsa_input_register, R_SHUTDOWN)) {
 				crm_verbose("(Re-)invoking shutdown");
 				next_input = I_SHUTDOWN;
 			} else if(is_set(fsa_input_register, R_INVOKE_PE)) {
 				crm_verbose("Invoke the PE somehow");
 			}
 */
 		}
 	
 	
 		/* get out of here NOW! before anything worse happens */
-	ELSEIF_FSA_ACTION(A_EXIT_1,	do_exit)
+	else IF_FSA_ACTION(A_EXIT_1,	do_exit)
 		
-		ELSEIF_FSA_ACTION(A_STARTUP,	do_startup)
+		else IF_FSA_ACTION(A_STARTUP,	do_startup)
 		
-		ELSEIF_FSA_ACTION(A_CIB_START,  do_cib_control)
-		ELSEIF_FSA_ACTION(A_READCONFIG,	do_read_config)
-		ELSEIF_FSA_ACTION(A_HA_CONNECT, do_ha_control)
-		ELSEIF_FSA_ACTION(A_LRM_CONNECT,do_lrm_control)
-		ELSEIF_FSA_ACTION(A_CCM_CONNECT,do_ccm_control)
+		else IF_FSA_ACTION(A_CIB_START,  do_cib_control)
+		else IF_FSA_ACTION(A_READCONFIG,	do_read_config)
+		else IF_FSA_ACTION(A_HA_CONNECT, do_ha_control)
+		else IF_FSA_ACTION(A_LRM_CONNECT,do_lrm_control)
+		else IF_FSA_ACTION(A_CCM_CONNECT,do_ccm_control)
 		
 		/* sub-system start */
-		ELSEIF_FSA_ACTION(A_TE_START,	do_te_control)
-		ELSEIF_FSA_ACTION(A_PE_START,	do_pe_control)
+		else IF_FSA_ACTION(A_TE_START,	do_te_control)
+		else IF_FSA_ACTION(A_PE_START,	do_pe_control)
 		
 		/* sub-system restart
 		 */
-		ELSEIF_FSA_ACTION(O_CIB_RESTART,do_cib_control)
-		ELSEIF_FSA_ACTION(O_PE_RESTART, do_pe_control)
-		ELSEIF_FSA_ACTION(O_TE_RESTART, do_te_control)
+		else IF_FSA_ACTION(O_CIB_RESTART,do_cib_control)
+		else IF_FSA_ACTION(O_PE_RESTART, do_pe_control)
+		else IF_FSA_ACTION(O_TE_RESTART, do_te_control)
 		
-		ELSEIF_FSA_ACTION(A_STARTED,	do_started)
+		else IF_FSA_ACTION(A_STARTED,	do_started)
 		
 		/* DC Timer */
-		ELSEIF_FSA_ACTION(O_DC_TIMER_RESTART,	do_dc_timer_control)
-		ELSEIF_FSA_ACTION(A_DC_TIMER_STOP,	do_dc_timer_control)
-		ELSEIF_FSA_ACTION(A_DC_TIMER_START,	do_dc_timer_control)
+		else IF_FSA_ACTION(O_DC_TIMER_RESTART,	do_dc_timer_control)
+		else IF_FSA_ACTION(A_DC_TIMER_STOP,	do_dc_timer_control)
+		else IF_FSA_ACTION(A_DC_TIMER_START,	do_dc_timer_control)
 		
 		/*
 		 * Highest priority actions
 		 */
 
 		/* the order of these is finiky...
 		 * the status section seems to dissappear after the BUMPGEN!!!
 		 * Yet BUMPGEN is non-destructive
 		 */
-		ELSEIF_FSA_ACTION(A_TE_COPYTO,		do_te_copyto)
-		ELSEIF_FSA_ACTION(A_CIB_BUMPGEN,	do_cib_invoke)
-
-		ELSEIF_FSA_ACTION(A_MSG_ROUTE,		do_msg_route)
-		ELSEIF_FSA_ACTION(A_RECOVER,		do_recover)
-		ELSEIF_FSA_ACTION(A_UPDATE_NODESTATUS,	do_update_node_status)
-		ELSEIF_FSA_ACTION(A_JOIN_ACK,		do_ack_welcome)
-		ELSEIF_FSA_ACTION(A_SHUTDOWN_REQ,	do_shutdown_req)
-		ELSEIF_FSA_ACTION(A_ELECTION_VOTE,	do_election_vote)
-		ELSEIF_FSA_ACTION(A_ELECT_TIMER_STOP,	do_election_timer_ctrl)
-		ELSEIF_FSA_ACTION(A_ELECT_TIMER_START,	do_election_timer_ctrl)
-		ELSEIF_FSA_ACTION(A_ELECTION_COUNT,	do_election_count_vote)
-		ELSEIF_FSA_ACTION(A_ELECTION_TIMEOUT,	do_election_timer_ctrl)
+		else IF_FSA_ACTION(A_TE_COPYTO,		do_te_copyto)
+		else IF_FSA_ACTION(A_CIB_BUMPGEN,	do_cib_invoke)
+
+		else IF_FSA_ACTION(A_MSG_ROUTE,		do_msg_route)
+		else IF_FSA_ACTION(A_RECOVER,		do_recover)
+		else IF_FSA_ACTION(A_UPDATE_NODESTATUS,	do_update_node_status)
+		else IF_FSA_ACTION(A_JOIN_ACK,		do_ack_welcome)
+		else IF_FSA_ACTION(A_SHUTDOWN_REQ,	do_shutdown_req)
+		else IF_FSA_ACTION(A_ELECTION_VOTE,	do_election_vote)
+		else IF_FSA_ACTION(A_ELECT_TIMER_STOP,	do_election_timer_ctrl)
+		else IF_FSA_ACTION(A_ELECT_TIMER_START,	do_election_timer_ctrl)
+		else IF_FSA_ACTION(A_ELECTION_COUNT,	do_election_count_vote)
+		else IF_FSA_ACTION(A_ELECTION_TIMEOUT,	do_election_timer_ctrl)
 		
 		/*
 		 * "Get this over with" actions
 		 */
-		ELSEIF_FSA_ACTION(A_MSG_STORE,		do_msg_store)
+		else IF_FSA_ACTION(A_MSG_STORE,		do_msg_store)
 		
 		/*
 		 * High priority actions
 		 * Update the cache first
 		 */
-		ELSEIF_FSA_ACTION(A_CCM_UPDATE_CACHE,	do_ccm_update_cache)
-		ELSEIF_FSA_ACTION(A_CCM_EVENT,		do_ccm_event)
+		else IF_FSA_ACTION(A_CCM_UPDATE_CACHE,	do_ccm_update_cache)
+		else IF_FSA_ACTION(A_CCM_EVENT,		do_ccm_event)
 		
 		/*
 		 * Medium priority actions
 		 */
-		ELSEIF_FSA_ACTION(A_DC_TAKEOVER,	do_dc_takeover)
-		ELSEIF_FSA_ACTION(A_DC_RELEASE,		do_dc_release)
-		ELSEIF_FSA_ACTION(A_JOIN_WELCOME_ALL,	do_send_welcome_all)
-		ELSEIF_FSA_ACTION(A_JOIN_WELCOME,	do_send_welcome)
-		ELSEIF_FSA_ACTION(A_JOIN_PROCESS_ACK,	do_process_welcome_ack)
+		else IF_FSA_ACTION(A_DC_TAKEOVER,	do_dc_takeover)
+		else IF_FSA_ACTION(A_DC_RELEASE,		do_dc_release)
+		else IF_FSA_ACTION(A_JOIN_WELCOME_ALL,	do_send_welcome_all)
+		else IF_FSA_ACTION(A_JOIN_WELCOME,	do_send_welcome)
+		else IF_FSA_ACTION(A_JOIN_PROCESS_ACK,	do_process_welcome_ack)
 		
 		/*
 		 * Low(er) priority actions
 		 * Make sure the CIB is always updated before invoking the
 		 * PE, and the PE before the TE
 		 */
-		ELSEIF_FSA_ACTION(A_CIB_INVOKE_LOCAL,	do_cib_invoke)
-		ELSEIF_FSA_ACTION(A_CIB_INVOKE,		do_cib_invoke)
-		ELSEIF_FSA_ACTION(A_LRM_INVOKE,		do_lrm_invoke)
-		ELSEIF_FSA_ACTION(A_LRM_EVENT,		do_lrm_event)
-		ELSEIF_FSA_ACTION(A_TE_CANCEL,		do_te_invoke)
-		ELSEIF_FSA_ACTION(A_PE_INVOKE,		do_pe_invoke)
-		ELSEIF_FSA_ACTION(A_TE_INVOKE,		do_te_invoke)
-		ELSEIF_FSA_ACTION(A_ANNOUNCE,		do_announce)
+		else IF_FSA_ACTION(A_CIB_INVOKE_LOCAL,	do_cib_invoke)
+		else IF_FSA_ACTION(A_CIB_INVOKE,		do_cib_invoke)
+		else IF_FSA_ACTION(A_LRM_INVOKE,		do_lrm_invoke)
+		else IF_FSA_ACTION(A_LRM_EVENT,		do_lrm_event)
+		else IF_FSA_ACTION(A_TE_CANCEL,		do_te_invoke)
+		else IF_FSA_ACTION(A_PE_INVOKE,		do_pe_invoke)
+		else IF_FSA_ACTION(A_TE_INVOKE,		do_te_invoke)
+		else IF_FSA_ACTION(A_ANNOUNCE,		do_announce)
 		
 		/* sub-system stop */
-		ELSEIF_FSA_ACTION(A_PE_STOP,		do_pe_control)
-		ELSEIF_FSA_ACTION(A_TE_STOP,		do_te_control)
-		ELSEIF_FSA_ACTION(A_DC_RELEASED,	do_dc_release)
-
-		ELSEIF_FSA_ACTION(A_HA_DISCONNECT,	do_ha_control)
-		ELSEIF_FSA_ACTION(A_CCM_DISCONNECT,	do_ccm_control)
-		ELSEIF_FSA_ACTION(A_LRM_DISCONNECT,	do_lrm_control)
-		ELSEIF_FSA_ACTION(A_CIB_STOP,		do_cib_control)		
+		else IF_FSA_ACTION(A_PE_STOP,		do_pe_control)
+		else IF_FSA_ACTION(A_TE_STOP,		do_te_control)
+		else IF_FSA_ACTION(A_DC_RELEASED,	do_dc_release)
+
+		else IF_FSA_ACTION(A_HA_DISCONNECT,	do_ha_control)
+		else IF_FSA_ACTION(A_CCM_DISCONNECT,	do_ccm_control)
+		else IF_FSA_ACTION(A_LRM_DISCONNECT,	do_lrm_control)
+		else IF_FSA_ACTION(A_CIB_STOP,		do_cib_control)		
 		/* time to go now... */
 		
 		/* Some of these can probably be consolidated */
-		ELSEIF_FSA_ACTION(A_SHUTDOWN,   do_shutdown)
-		ELSEIF_FSA_ACTION(A_STOP,	do_stop)
+		else IF_FSA_ACTION(A_SHUTDOWN,   do_shutdown)
+		else IF_FSA_ACTION(A_STOP,	do_stop)
 		
 		/* exit gracefully */
-		ELSEIF_FSA_ACTION(A_EXIT_0,	do_exit)
+		else IF_FSA_ACTION(A_EXIT_0,	do_exit)
 
-/*		ELSEIF_FSA_ACTION(A_, do_) */
+/*		else IF_FSA_ACTION(A_, do_) */
 		
 		else if((actions & A_MSG_PROCESS) != 0
 			|| is_message()) {
 			xmlNodePtr stored_msg = NULL;
 			crm_verbose("Checking messages... %d",
 				  g_list_length(fsa_message_queue));
 			
 			stored_msg = get_message();
 			
 			if(is_message() == FALSE) {
 				actions = clear_bit(actions, A_MSG_PROCESS);
 			}
 			
 			if(stored_msg == NULL) {
 				crm_err("Invalid stored message");
 				continue;
 			}
 
 			/*
 			 * This is where we should clean up old messages
 			 * The problem is that we dont always know the
 			 * type of the data (and therefore the correct way
 			 * to free it).  A wrapper is probably required.
 			 */
 			data = stored_msg;
 
 #ifdef DOT_FSA_ACTIONS
 			fprintf(dot_strm,
 				"\t// %s:\t%s\t(data? %s)",	
 				fsa_input2string(cur_input),
 				fsa_action2string(A_MSG_PROCESS),
 				stored_msg==NULL?XML_BOOLEAN_NO:XML_BOOLEAN_YES);
 			fflush(dot_strm);
 #endif
 #ifdef FSA_TRACE
 			crm_verbose("Invoking action %s (%.16llx)",
 				   fsa_action2string(A_MSG_PROCESS),
 				   A_MSG_PROCESS);
 #endif
 
 /*#ifdef FSA_TRACE*/
 			crm_xml_devel(stored_msg,"FSA processing message");
 /*#endif*/
 
 			next_input = handle_message(stored_msg);
 
 #ifdef DOT_FSA_ACTIONS
 			fprintf(dot_strm, "\t(result=%s)\n",
 				fsa_input2string(next_input));
 #endif
 #ifdef FSA_TRACE
 			crm_verbose("Result of action %s was %s",
 				   fsa_action2string(A_MSG_PROCESS),
 				   fsa_input2string(next_input));
 #endif
 			
 			/* Error checking and reporting */
 		} else if(cur_input != I_NULL && is_set(actions, A_NOTHING)) {
 			crm_warn(
 			       "No action specified for input,state (%s,%s)",
 			       fsa_input2string(cur_input),
 			       fsa_state2string(cur_state));
 			
 			next_input = I_NULL;
 			
 		} else if(cur_input == I_NULL && is_set(actions, A_NOTHING)) {
 #ifdef FSA_TRACE
 			crm_info("Nothing left to do");
 #endif			
 		} else {
 			crm_err("Action %s (0x%llx) not supported ",
 			       fsa_action2string(actions), actions);
 			next_input = I_ERROR;
 		}
 
 		if(is_message()) {
 			actions |= A_MSG_PROCESS;
 		}
 	}
 	
 #ifdef FSA_TRACE
 	crm_verbose("################# Exiting the FSA (%s) ##################",
 		  fsa_state2string(fsa_state));
 #endif
 
 #ifdef DOT_FSA_ACTIONS
 	fprintf(dot_strm,			
 		"\t// ### Exiting the FSA (%s)\n",
 		fsa_state2string(fsa_state));
 	fflush(dot_strm);
 #endif
 
 	/* cleanup inputs? */
 	fsa_actions = actions;
 	
 	return fsa_state;
 }
 
 
 
 
 long long 
 do_state_transition(long long actions,
 		    enum crmd_fsa_cause cause,
 		    enum crmd_fsa_state cur_state,
 		    enum crmd_fsa_state next_state,
 		    enum crmd_fsa_input current_input,
 		    void *data)
 {
 	gboolean clear_recovery_bit = TRUE;
 	long long tmp = actions;
 	const char *state_from = fsa_state2string(cur_state);
 	const char *state_to   = fsa_state2string(next_state);
 	const char *input      = fsa_input2string(current_input);
 	
 	time_t now = time(NULL);
 
 	if(cur_state == next_state) {
 		crm_err("%s called in state %s with no transtion",
 		       __FUNCTION__, state_from);
 		return A_NOTHING;
 	}
 	
 	
 /*	if(current_input != I_NULL */
 /*	   && (current_input != I_DC_HEARTBEAT || cur_state != S_NOT_DC)){ */
 		
 	fprintf(dot_strm,
 		"\t\"%s\" -> \"%s\" [ label =\"%s\" ] // %s",
 		state_from, state_to, input,
 		asctime(localtime(&now)));
 	fflush(dot_strm);
 	/*}*/
 
 	crm_info("State transition \"%s\" -> \"%s\" [ cause =\"%s\" %s ]",
 		 state_from, state_to, input, asctime(localtime(&now)));
 
 	switch(next_state) {
 		case S_PENDING:
 			break;
 		case S_NOT_DC:
 			if(is_set(fsa_input_register, R_SHUTDOWN)){
 				crm_info("(Re)Issuing shutdown request now"
 					 " that we have a new DC");
 				tmp = set_bit(tmp, A_SHUTDOWN_REQ);
 			}
 			break;
 		case S_RECOVERY_DC:
 		case S_RECOVERY:
 			clear_recovery_bit = FALSE;
 			break;
 		case S_POLICY_ENGINE:
 			if(g_hash_table_size(joined_nodes)
 			   != fsa_membership_copy->members_size) {
 				crm_warn("Only %d (of %d) cluster nodes are"
 					 " eligable to run resources.",
 					 1+g_hash_table_size(joined_nodes),
 					 fsa_membership_copy->members_size);
 			} else {
 				crm_info("All %d clusters nodes are"
 					 " eligable to run resources.",
 					 fsa_membership_copy->members_size);
 			}
 			break;
 			
 		case S_IDLE:
 			dump_rsc_info();
 			/* keep going */
 		default:
 			break;
 	}
 
 	if(clear_recovery_bit && next_state != S_PENDING) {
 		tmp = clear_bit(tmp, A_RECOVER);
 	} else if(clear_recovery_bit == FALSE) {
 		tmp = set_bit(tmp, A_RECOVER);
 	}
 	
 	if(tmp != actions) {
 		crm_info("Action b4    %.16llx ", actions);
 		crm_info("Action after %.16llx ", tmp);
 		actions = tmp;
 	}
 
 	return actions;
 }
 
 long long
 clear_flags(long long actions,
 	    enum crmd_fsa_cause cause,
 	    enum crmd_fsa_state cur_state,
 	    enum crmd_fsa_input cur_input)
 {
 
 	if(is_set(fsa_input_register, R_SHUTDOWN)){
 		clear_bit_inplace(&actions, A_DC_TIMER_START);
 	}
 	
 
 	switch(cur_state) {
 		case S_IDLE:
 			break;
 		case S_ELECTION:
 			break;
 		case S_INTEGRATION:
 			break;
 		case S_NOT_DC:
 			break;
 		case S_POLICY_ENGINE:
 			break;
 		case S_RECOVERY:
 			break;
 		case S_RECOVERY_DC:
 			break;
 		case S_RELEASE_DC:
 			break;
 		case S_PENDING:
 			break;
 		case S_STOPPING:
 			break;
 		case S_TERMINATE:
 			break;
 		case S_TRANSITION_ENGINE:
 			break;
 		case S_ILLEGAL:
 			break;
 	}
 	return actions;
 }
 
 void
 dump_rsc_info(void)
 {
 	xmlNodePtr local_cib = get_cib_copy();
 	xmlNodePtr root      = get_object_root(XML_CIB_TAG_STATUS, local_cib);
 	xmlNodePtr resources = NULL;
 	const char *rsc_id    = NULL;
 	const char *node_id   = NULL;
 	const char *rsc_state = NULL;
 	const char *op_status = NULL;
 	const char *last_rc   = NULL;
 	const char *last_op   = NULL;
 
 	
 	const char *path[] = {
 		XML_CIB_TAG_LRM,
 		XML_LRM_TAG_RESOURCES
 	};
 
 	xml_child_iter(
 		root, node, XML_CIB_TAG_STATE,
 		
 		resources = find_xml_node_nested(node, path, DIMOF(path));
 
 		xml_child_iter(
 			resources, rsc, XML_LRM_TAG_RESOURCE,
 
 			rsc_id    = xmlGetProp(rsc, XML_ATTR_ID);
 			node_id   = xmlGetProp(rsc, XML_LRM_ATTR_TARGET);
 			rsc_state = xmlGetProp(rsc, XML_LRM_ATTR_RSCSTATE);
 			op_status = xmlGetProp(rsc, XML_LRM_ATTR_OPSTATUS);
 			last_rc   = xmlGetProp(rsc, XML_LRM_ATTR_RC);
 			last_op   = xmlGetProp(rsc, XML_LRM_ATTR_LASTOP);
 			
 /* 			if(safe_str_eq(rsc_state, "stopped")) { */
 /* 				continue; */
 /* 			} */
 			
 			crm_info("Resource state: %s %s "
 				 "[%s (rc=%s) after %s] on %s",
 				 rsc_id, rsc_state,
 				 op_status, last_rc, last_op, node_id);
 			);
 		);
 }
diff --git a/crm/crmd/join.c b/crm/crmd/join.c
index e57ebfe495..47451a68fe 100644
--- a/crm/crmd/join.c
+++ b/crm/crmd/join.c
@@ -1,405 +1,406 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <portability.h>
 
 #include <heartbeat.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 
 #include <crmd_fsa.h>
 #include <crmd_messages.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 GHashTable *joined_nodes = NULL;
 
 /*	 A_JOIN_WELCOME	*/
 enum crmd_fsa_input
 do_send_welcome(long long action,
 		enum crmd_fsa_cause cause,
 		enum crmd_fsa_state cur_state,
 		enum crmd_fsa_input current_input,
 		void *data)
 {
 	xmlNodePtr update = NULL;
 	xmlNodePtr welcome = NULL;
 	xmlNodePtr tmp1 = NULL;
 	xmlNodePtr tmp2 = NULL;
 	const char *join_to = NULL;
 
 	if(action & A_JOIN_WELCOME && data == NULL) {
 		crm_err("Attempt to send welcome message "
 			 "without a message to reply to!");
 		return I_NULL;
 /*		return do_send_welcome_all( */
 /*			A_JOIN_WELCOME_ALL,cause,cur_state,current_input,data); */
 		
 	} else if(action & A_JOIN_WELCOME) {
 		welcome = (xmlNodePtr)data;
 
 		join_to = xmlGetProp(welcome, XML_ATTR_HOSTFROM);
 		if(join_to != NULL) {
 			stopTimer(integration_timer);
 
 			/* update node status */
 			crm_debug("Updating node state to %s for %s",
 				  CRMD_JOINSTATE_PENDING, join_to);
 			
 			update = create_node_state(
 				join_to, join_to,
 				NULL, NULL, CRMD_JOINSTATE_PENDING);
 
 			tmp1 = create_cib_fragment(update, NULL);
 			invoke_local_cib(NULL, tmp1, CRM_OP_UPDATE);
 			free_xml(tmp1);	
 			
 			/* Make sure they have the *whole* CIB */
 			crm_debug("Sending complete CIB to %s", join_to);
 			
 			tmp1 = get_cib_copy();
 			tmp2 = create_cib_fragment(tmp1, NULL);
 			
 			send_request(NULL, tmp2, CRM_OP_REPLACE,
 				     join_to, CRM_SYSTEM_CRMD, NULL);
 			
 			free_xml(tmp1);	
 			free_xml(tmp2);
 
 			/* send the welcome */
 			crm_debug("Sending %s to %s", CRM_OP_WELCOME, join_to);
 			
 			send_request(NULL, NULL, CRM_OP_WELCOME,
 				     join_to, CRM_SYSTEM_CRMD, NULL);
 
 			free_xml(update);
 			
 			/* if this client is sick, we shouldnt wait forever */
 			crm_debug("Restarting the integration timer");
 			startTimer(integration_timer);
 
 		} else {
 			crm_err("No recipient for welcome message");
 		}
 		
 		return I_NULL;
 
 	}
 	return I_ERROR;
 }
 
 /*	 A_JOIN_WELCOME_ALL	*/
 
 enum crmd_fsa_input
 do_send_welcome_all(long long action,
 		    enum crmd_fsa_cause cause,
 		    enum crmd_fsa_state cur_state,
 		    enum crmd_fsa_input current_input,
 		    void *data)
 {
 	
 
 	/* reset everyones status back to down or in_ccm in the CIB */
 	xmlNodePtr update     = NULL;
 	xmlNodePtr cib_copy   = get_cib_copy();
 	xmlNodePtr tmp1       = get_object_root(XML_CIB_TAG_STATUS, cib_copy);
 	xmlNodePtr tmp2       = NULL;
 
 	/* Give everyone a chance to join before invoking the PolicyEngine */
 	stopTimer(integration_timer);
 	startTimer(integration_timer);
 	
 	if(joined_nodes != NULL) {
 		g_hash_table_destroy(joined_nodes);
 		joined_nodes = g_hash_table_new(&g_str_hash, &g_str_equal);
 	}
 
 	/* catch any nodes that are active in the CIB but not in the CCM list*/
 	xml_child_iter(
 		tmp1, node_entry, XML_CIB_TAG_STATE,
 
 		const char *node_id = xmlGetProp(node_entry, XML_ATTR_UNAME);
 		gpointer a_node = g_hash_table_lookup(
 				fsa_membership_copy->members, node_id);
 
 		if(a_node != NULL || (safe_str_eq(fsa_our_uname, node_id))) {
 			/* handled by do_update_cib_node() */
 			xml_iter_continue(node_entry);
 		}
 
 		tmp2 = create_node_state(
 			node_id, node_id,
 			XML_BOOLEAN_NO, NULL, CRMD_JOINSTATE_DOWN);
 
 		if(update == NULL) {
 			update = tmp2;
 		} else {
 			update = xmlAddSibling(update, tmp2);
 		}
 		);
 
 	/* now process the CCM data */
 	free_xml(do_update_cib_nodes(update, TRUE));
 	free_xml(cib_copy);
 
 	/* Make sure everyone has the *whole* CIB */
 	tmp1 = get_cib_copy();
 	tmp2 = create_cib_fragment(tmp1, NULL);
 	
 	send_request(NULL, tmp2, CRM_OP_REPLACE,
 		     NULL, CRM_SYSTEM_CRMD, NULL);
 	
 	free_xml(tmp1);	
 	free_xml(tmp2);
 	
 	/* Avoid ordered message delays caused when the CRMd proc
 	 * isnt running yet (ie. send as a broadcast msg which are never
 	 * sent ordered.
 	 */
 	send_request(NULL, NULL, CRM_OP_WELCOME,
 		     NULL, CRM_SYSTEM_CRMD, NULL);	
 
 /* No point hanging around in S_INTEGRATION if we're the only ones here! */
 	if(joined_nodes == NULL) {
 		if(fsa_membership_copy->members_size == 1) {
 			/* we're the only ones in here */
 			crm_info("Not expecting any join acks");
 			return I_SUCCESS;
 		}
 		
 	} else if(g_hash_table_size(joined_nodes)
 		  >= (fsa_membership_copy->members_size -1)) {
 		crm_info("That was the last outstanding join ack");
 		return I_SUCCESS;
 	}
 
 	/* dont waste time by invoking the pe yet; */
 	crm_debug("Still waiting on %d outstanding join acks",
 		  fsa_membership_copy->members_size
 		  - g_hash_table_size(joined_nodes) - 1);
 	
 	return I_NULL;
 }
 
 
 /*	 A_JOIN_ACK	*/
 enum crmd_fsa_input
 do_ack_welcome(long long action,
 	    enum crmd_fsa_cause cause,
 	    enum crmd_fsa_state cur_state,
 	    enum crmd_fsa_input current_input,
 	    void *data)
 {
 	xmlNodePtr welcome = (xmlNodePtr)data;
 	xmlNodePtr cib_copy;
 	xmlNodePtr tmp1;
 	xmlNodePtr tmp2;
 
 	
 	
 #if 0
 	if(we are sick) {
 		log error ;
 		return I_NULL;
 	} 
 #endif
 	fsa_our_dc = xmlGetProp(welcome, XML_ATTR_HOSTFROM);
 	
 	if(fsa_our_dc == NULL) {
 		crm_err("Failed to determin our DC");
 		return I_FAIL;
 	}
 	
 	/* send our status section to the DC */
 	cib_copy = get_cib_copy();
 	tmp1 = get_object_root(XML_CIB_TAG_STATUS, cib_copy);
 	if(tmp1 != NULL) {
 		tmp2 = create_cib_fragment(tmp1->children, NULL);
 		
 		send_ha_reply(fsa_cluster_conn, welcome, tmp2);
 
 		free_xml(tmp2);
 	}
 	
 	free_xml(cib_copy);
 	
 	return I_NULL;
 }
 
 /*	 A_ANNOUNCE	*/
 enum crmd_fsa_input
 do_announce(long long action,
 	    enum crmd_fsa_cause cause,
 	    enum crmd_fsa_state cur_state,
 	    enum crmd_fsa_input current_input,
 	    void *data)
 {
 	xmlNodePtr msg = (xmlNodePtr)data;
 	
 	
 	/* Once we hear from the DC, we can stop the timer
 	 *
 	 * This timer was started either on startup or when a node
 	 * left the CCM list
 	 */
 
 	/* dont announce if we're in one of these states */
 	switch(cur_state) {
 		case S_RECOVERY:
 		case S_RECOVERY_DC:
 		case S_RELEASE_DC:
 		case S_TERMINATE:
 			crm_warn("Do not announce ourselves in state %s",
 				 fsa_state2string(cur_state));
 			return I_NULL;
 			break;
 		default:
 			break;
 	}
 
 	if(AM_I_OPERATIONAL) {
 		const char *from = xmlGetProp(msg, XML_ATTR_HOSTFROM);
 
 		if(from == NULL) {
 			crm_err("Failed to origin of ping message");
 			return I_FAIL;
 		}
 		
 		send_request(NULL, NULL, CRM_OP_ANNOUNCE,
 			     from, CRM_SYSTEM_DC, NULL);
 	} else {
 		/* Delay announce until we have finished local startup */
 		crm_warn("Delaying announce until local startup is complete");
 		return I_NULL;
 	}
 	
 	return I_NULL;
 }
 
 
 /*	 A_JOIN_PROCESS_ACK	*/
 enum crmd_fsa_input
 do_process_welcome_ack(long long action,
 		    enum crmd_fsa_cause cause,
 		    enum crmd_fsa_state cur_state,
 		    enum crmd_fsa_input current_input,
 		    void *data)
 {
 	xmlNodePtr tmp1;
 	xmlNodePtr tmp2;
 	xmlNodePtr cib_fragment;
 	xmlNodePtr msg_cib;
 	xmlNodePtr join_ack = (xmlNodePtr)data;
 
 	gboolean is_a_member  = FALSE;
 	const char *join_from = xmlGetProp(join_ack, XML_ATTR_HOSTFROM);
 	const char *ref       = xmlGetProp(join_ack, XML_ATTR_REFERENCE);
 
 	uuid_t uuid_raw;
 	char *uuid_calc = NULL;
 
 	gpointer join_node =
 		g_hash_table_lookup(fsa_membership_copy->members, join_from);
 
 	if(join_node != NULL) {
 		is_a_member = TRUE;
 	}
 	
 	cib_fragment = find_xml_node(join_ack, XML_TAG_FRAGMENT);
 
 	crm_debug("Welcoming node %s after ACK (ref %s)",
 	       join_from, ref);
 	
 	if(is_a_member == FALSE) {
 		crm_err("Node %s is not known to us (ref %s)",
 		       join_from, ref);
 
 		/* make sure any information from this node is discarded,
 		 * it is invalid
 		 */
 		free_xml(cib_fragment);
 		return I_FAIL;
 	}
 	
 	/* add them to our list of CRMD_STATE_ACTIVE nodes
 	   TODO: still used?
 	   TODO: check its not already there
 	*/
 	g_hash_table_insert(joined_nodes, strdup(join_from),strdup(join_from));
 
 	if(cib_fragment == NULL) {
 		crm_err("No status information was part of the"
 			" Welcome ACK from %s",
 			join_from);
 		return I_NULL;
 	}
 
 	create_node_entry(join_from, join_from, "member");
 
-	uuid_calc = (char*)crm_malloc(sizeof(char)*50);
-	
-	if(fsa_cluster_conn->llc_ops->get_uuid_by_name(
-		   fsa_cluster_conn, join_from, uuid_raw) == HA_FAIL) {
-		crm_err("Could not calculate UUID for %s", join_from);
-		crm_free(uuid_calc);
-		uuid_calc = crm_strdup(join_from);
-
-	} else {
-		uuid_unparse(uuid_raw, uuid_calc);
+	crm_malloc(uuid_calc, sizeof(char)*50);
+	if(uuid_calc != NULL) {
+		if(fsa_cluster_conn->llc_ops->get_uuid_by_name(
+			   fsa_cluster_conn, join_from, uuid_raw) == HA_FAIL) {
+			crm_err("Could not calculate UUID for %s", join_from);
+			crm_free(uuid_calc);
+			uuid_calc = crm_strdup(join_from);
+			
+		} else {
+			uuid_unparse(uuid_raw, uuid_calc);
+		}
 	}
-
+	
 	/* Make changes so that exp_state=active for this node when the update
 	 *  is processed by A_CIB_INVOKE
 	 */
 	msg_cib = find_xml_node(cib_fragment, XML_TAG_CIB);
 	tmp1 = get_object_root(XML_CIB_TAG_STATUS, msg_cib);
 	tmp2 = find_entity(tmp1, XML_CIB_TAG_STATE, uuid_calc, FALSE);
 
 	if(tmp2 == NULL) {
 		crm_err("Status entry for %s not found in update, adding",
 			join_from);
 		
 		tmp2 = create_xml_node(tmp1, XML_CIB_TAG_STATE);
 		set_xml_property_copy(tmp2, XML_ATTR_UUID,  uuid_calc);
 		set_xml_property_copy(tmp2, XML_ATTR_UNAME, join_from);
 	}
-	
+
 	crm_free(uuid_calc);	
 
 	/* make sure these values are correct in the CIB */
 	set_xml_property_copy(
 		tmp2, XML_CIB_ATTR_EXPSTATE, CRMD_STATE_ACTIVE);
 	set_xml_property_copy(
 		tmp2, XML_CIB_ATTR_JOINSTATE,CRMD_JOINSTATE_MEMBER);
 
 /* No point hanging around in S_INTEGRATION if we're the only ones here! */
 	if(g_hash_table_size(joined_nodes)
 		  >= (fsa_membership_copy->members_size -1)) {
 		crm_info("That was the last outstanding join ack");
 		return I_SUCCESS;
 	}
 
 	/* dont waste time by invoking the pe yet; */
 	crm_debug("Still waiting on %d outstanding join acks",
 		  fsa_membership_copy->members_size
 		  - g_hash_table_size(joined_nodes) - 1);
 	
 	return I_CIB_OP;
 }
diff --git a/crm/crmd/lrm.c b/crm/crmd/lrm.c
index 50d77a679f..f91ceb1343 100644
--- a/crm/crmd/lrm.c
+++ b/crm/crmd/lrm.c
@@ -1,762 +1,771 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <crmd_fsa.h>
 
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include <unistd.h>			/* for access */
 #include <clplumbing/cl_signal.h>
 
 #include <errno.h>
 
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 
 #include <crmd.h>
 #include <crmd_messages.h>
 #include <crmd_callbacks.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 xmlNodePtr do_lrm_query(gboolean);
 
 gboolean build_suppported_RAs(
 	xmlNodePtr metadata_list, xmlNodePtr xml_agent_list);
 
 gboolean build_active_RAs(xmlNodePtr rsc_list);
 
 void do_update_resource(lrm_rsc_t *rsc, lrm_op_t *op);
 
 enum crmd_fsa_input do_lrm_rsc_op(
 	lrm_rsc_t *rsc, char *rid, const char *operation, xmlNodePtr msg);
 
 enum crmd_fsa_input do_fake_lrm_op(gpointer data);
 
 GHashTable *xml2list(xmlNodePtr parent, const char **attr_path, int depth);
 GHashTable *monitors = NULL;
 
 const char *rsc_path[] = 
 {
 	"msg_data",
 	"rsc_op",
 	"resource",
 	"instance_attributes",
 	"rsc_parameters"
 };
 
 
 /*	 A_LRM_CONNECT	*/
 enum crmd_fsa_input
 do_lrm_control(long long action,
 	       enum crmd_fsa_cause cause,
 	       enum crmd_fsa_state cur_state,
 	       enum crmd_fsa_input current_input,
 	       void *data)
 {
 	enum crmd_fsa_input failed = I_FAIL;
 	int ret = HA_OK;
 
 	if(action & A_LRM_DISCONNECT) {
 		fsa_lrm_conn->lrm_ops->signoff(fsa_lrm_conn);
 
 		/* TODO: Clean up the hashtable */
 		
 	}
 
 	if(action & A_LRM_CONNECT) {
 	
 		crm_trace("LRM: connect...");
 
 		monitors = g_hash_table_new(g_str_hash, g_str_equal);
 
 		fsa_lrm_conn = ll_lrm_new(XML_CIB_TAG_LRM);	
 		if(NULL == fsa_lrm_conn) {
 			return failed;
 		}
 		
 		crm_trace("LRM: sigon...");
 		ret = fsa_lrm_conn->lrm_ops->signon(
 			fsa_lrm_conn, CRM_SYSTEM_CRMD);
 		
 		if(ret != HA_OK) {
 			crm_err("Failed to sign on to the LRM");
 			return failed;
 		}
 		
 		crm_trace("LRM: set_lrm_callback...");
 		ret = fsa_lrm_conn->lrm_ops->set_lrm_callback(
 			fsa_lrm_conn, lrm_op_callback);
 		
 		if(ret != HA_OK) {
 			crm_err("Failed to set LRM callbacks");
 			return failed;
 		}
 
 		/* TODO: create a destroy handler that causes
 		 * some recovery to happen
 		 */
 		G_main_add_fd(G_PRIORITY_LOW,
 			      fsa_lrm_conn->lrm_ops->inputfd(fsa_lrm_conn),
 			      FALSE,
 			      lrm_dispatch, fsa_lrm_conn,
 			      default_ipc_input_destroy);
 
 	}	
 
 	if(action & ~(A_LRM_CONNECT|A_LRM_DISCONNECT)) {
 		crm_err("Unexpected action %s in %s",
 		       fsa_action2string(action), __FUNCTION__);
 	}
 		
 	
 	return I_NULL;
 }
 
 
 
 gboolean
 build_suppported_RAs(xmlNodePtr metadata_list, xmlNodePtr xml_agent_list)
 {
 	int lpc = 0, llpc = 0;
 	GList *types            = NULL;
 	GList *classes          = NULL;
 	const char *version     = NULL;
 	const char *ra_data     = NULL;
 /*	GHashTable *metadata    = NULL; */
 	xmlNodePtr xml_agent    = NULL;
 	xmlNodePtr xml_metadata = NULL;
 	xmlNodePtr tmp          = NULL;
 
 	classes = fsa_lrm_conn->lrm_ops->get_rsc_class_supported(fsa_lrm_conn);
 
 	slist_iter(
 		class, char, classes, lpc,
 
 		types = fsa_lrm_conn->lrm_ops->get_rsc_type_supported(
 			fsa_lrm_conn, class);
 
 /*		metadata = fsa_lrm_conn->lrm_ops->get_all_type_metadatas(
 			fsa_lrm_conn, class);
 */	
 		slist_iter(
 			type, char, types, llpc,
 			
 			version = "1";
 
 			xml_agent = create_xml_node(
 				xml_agent_list, "lrm_agent");
 			
 			set_xml_property_copy(xml_agent, "class",       class);
 			set_xml_property_copy(xml_agent, XML_ATTR_TYPE, type);
 
 /*			ra_data = g_hashtable_lookup(metadata, type); */
 			if(ra_data != NULL) {
 				xml_metadata = create_xml_node(
 					xml_metadata, "agent_metadata");
 				set_xml_property_copy(
 					xml_metadata, "class",       class);
 				set_xml_property_copy(
 					xml_metadata, XML_ATTR_TYPE, type);
 
 				tmp = string2xml(ra_data);
 				if(tmp != NULL) {
 					xmlAddChild(xml_metadata, tmp);
 				}
 				/* extract version */
 			}
 			
 			set_xml_property_copy(xml_agent, "version",     version);
 
 			)
 		g_list_free(types);
 		);
 
 	g_list_free(classes);
 
 	return TRUE;
 }
 
 
 gboolean
 build_active_RAs(xmlNodePtr rsc_list)
 {
 	int lpc = 0, llpc = 0;
 
 	GList *op_list  = NULL;
 	GList *lrm_list = NULL;
 	gboolean found_op = FALSE;
 		
 
 	state_flag_t cur_state = 0;
 	const char *this_op    = NULL;
 	char *tmp = NULL;
 	
 	lrm_list = fsa_lrm_conn->lrm_ops->get_all_rscs(fsa_lrm_conn);
 
 	slist_iter(
 		rid, char, lrm_list, lpc,
 
 /* 		GHashTable* 	params; */
 
 		lrm_rsc_t *the_rsc =
 			fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid);
 
 		
 		xmlNodePtr xml_rsc = create_xml_node(
 			rsc_list, XML_LRM_TAG_RESOURCE);
 
 		crm_info("Processing lrm_rsc_t entry %s", rid);
 		
 		if(the_rsc == NULL) {
 			crm_err("NULL resource returned from the LRM");
 			continue;
 		}
 
 		set_xml_property_copy(xml_rsc, XML_ATTR_ID, the_rsc->id);
 		set_xml_property_copy(
 			xml_rsc, XML_LRM_ATTR_TARGET, fsa_our_uname);
 
 		op_list = the_rsc->ops->get_cur_state(the_rsc, &cur_state);
 
 		crm_verbose("\tcurrent state:%s\n",
 			    cur_state==LRM_RSC_IDLE?"Idle":"Busy");
 
 		slist_iter(
 			op, lrm_op_t, op_list, llpc,
 
 			this_op = op->op_type;
 
 			crm_debug("Processing op %s for %s (status=%d, rc=%d)", 
 				  op->op_type, the_rsc->id, op->op_status, op->rc);
 			
 			if(op->rc != 0
 			   || safe_str_neq(this_op, CRMD_RSCSTATE_MON)){
 				set_xml_property_copy(
 					xml_rsc,
 					XML_LRM_ATTR_RSCSTATE,
 					op->user_data);
 		
 				set_xml_property_copy(
 					xml_rsc, XML_LRM_ATTR_LASTOP, this_op);
 	
 				tmp = crm_itoa(op->rc);
 				set_xml_property_copy(
 					xml_rsc, XML_LRM_ATTR_RC, tmp);
 				crm_free(tmp);
 
 				tmp = crm_itoa(op->op_status);
 				set_xml_property_copy(
 					xml_rsc, XML_LRM_ATTR_OPSTATUS, tmp);
 				crm_free(tmp);
 				
 				/* we only want the last one */
 				found_op = TRUE;
 				break;
 
 			} else {
 				set_xml_property_copy(
 					xml_rsc,
 					XML_LRM_ATTR_RSCSTATE,
 					CRMD_RSCSTATE_START_OK);
 		
 				set_xml_property_copy(
 					xml_rsc,
 					XML_LRM_ATTR_LASTOP,
 					CRMD_RSCSTATE_START);
 	
 				tmp = crm_itoa(op->rc);
 				set_xml_property_copy(
 					xml_rsc, XML_LRM_ATTR_RC, tmp);
 				crm_free(tmp);
 
 				set_xml_property_copy(
 					xml_rsc, XML_LRM_ATTR_OPSTATUS, "0");
 
 				/* we only want the last one */
 				found_op = TRUE;
 				break;
 			}
 			);
 		if(found_op == FALSE) {
 			crm_err("Could not properly determin last op"
 				" for %s from %d entries", the_rsc->id,
 				g_list_length(op_list));
 		}
 
 		g_list_free(op_list);
 		);
 
 	g_list_free(lrm_list);
 
 	return TRUE;
 }
 
 xmlNodePtr
 do_lrm_query(gboolean is_replace)
 {
 	xmlNodePtr xml_result= NULL;
 	xmlNodePtr xml_state = create_xml_node(NULL, XML_CIB_TAG_STATE);
 	xmlNodePtr xml_data  = create_xml_node(xml_state, XML_CIB_TAG_LRM);
 	xmlNodePtr rsc_list  = create_xml_node(xml_data,XML_LRM_TAG_RESOURCES);
 	xmlNodePtr xml_agent_list = create_xml_node(xml_data, "lrm_agents");
 	xmlNodePtr xml_metadata_list = create_xml_node(xml_data, "metatdata");
 
 	/* Build a list of supported agents and metadata */
 	build_suppported_RAs(xml_metadata_list, xml_agent_list);
 	
 	/* Build a list of active (not always running) resources */
 	build_active_RAs(rsc_list);
 
 #ifndef USE_FAKE_LRM
 	if(is_replace) {
 		set_xml_property_copy(xml_state, "replace", XML_CIB_TAG_LRM);
 	}
 #else
 	if(is_replace) {
 		set_xml_property_copy(xml_data, "replace", "lrm_agents");
 	}
 #endif
 
 	set_uuid(xml_state, XML_ATTR_UUID, fsa_our_uname);
 
 	set_xml_property_copy(xml_state, XML_ATTR_UNAME, fsa_our_uname);
 	xml_result = create_cib_fragment(xml_state, NULL);
 	
 	return xml_result;
 }
 
 /*	A_UPDATE_NODESTATUS */
 enum crmd_fsa_input
 do_update_node_status(long long action,
 		      enum crmd_fsa_cause cause,
 		      enum crmd_fsa_state cur_state,
 		      enum crmd_fsa_input current_input,
 		      void *data)
 {
 	xmlNodePtr update = NULL;
 
 	if(action & A_UPDATE_NODESTATUS) {
 
 		update = do_lrm_query(TRUE);
 
 		/* this only happens locally.  the updates are pushed out
 		 * as part of the join process
 		 */
 		invoke_local_cib(NULL, update, CRM_OP_UPDATE);
 
 		free_xml(update);
 
 		return I_NULL;
 	}
 
 	return I_ERROR;
 }
 
 
 /*	 A_LRM_INVOKE	*/
 enum crmd_fsa_input
 do_lrm_invoke(long long action,
 	      enum crmd_fsa_cause cause,
 	      enum crmd_fsa_state cur_state,
 	      enum crmd_fsa_input current_input,
 	      void *data)
 {
 	enum crmd_fsa_input next_input = I_NULL;
 	xmlNodePtr msg;
 	const char *operation = NULL;
 	char rid[64];
 	const char *id_from_cib = NULL;
 	const char *crm_op = NULL;
 	lrm_rsc_t *rsc = NULL;
 
 #ifdef USE_FAKE_LRM
 	return do_fake_lrm_op(data);
 #endif
 	
 	msg = (xmlNodePtr)data;
 		
 	operation = get_xml_attr_nested(
 		msg, rsc_path, DIMOF(rsc_path) -3, XML_LRM_ATTR_TASK, TRUE);
 
 /*	xmlNodePtr tmp = find_xml_node_nested(msg, rsc_path, DIMOF(rsc_path) -3); */
 /*	operation = xmlGetProp(tmp, XML_LRM_ATTR_TASK); */
 
 	if(operation == NULL) {
 		crm_err("No value for %s in message at level %d.",
 			XML_LRM_ATTR_TASK, DIMOF(rsc_path) -3);
 		return I_NULL;
 	}
 	
 	id_from_cib = get_xml_attr_nested(
 		msg, rsc_path, DIMOF(rsc_path) -2, XML_ATTR_ID, TRUE);
 
 	if(id_from_cib == NULL) {
 		crm_err("No value for %s in message at level %d.",
 			XML_ATTR_ID, DIMOF(rsc_path) -2);
 		return I_NULL;
 	}
 	
 	/* only the first 16 chars are used by the LRM */
 	strncpy(rid, id_from_cib, 64);
 	rid[63] = 0;
 	
 	crm_op = get_xml_attr(msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE);
 	
 	rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid);
 	
 	if(crm_op != NULL && safe_str_eq(crm_op, "lrm_query")) {
 		xmlNodePtr data, reply;
 
 		data = do_lrm_query(FALSE);
 		reply = create_reply(msg, data);
 
 		relay_message(reply, TRUE);
 
 		free_xml(data);
 		free_xml(reply);
 
 	} else if(operation != NULL) {
 		next_input = do_lrm_rsc_op(rsc, rid, operation, msg);
 		
 	} else {
 		next_input = I_ERROR;
 	}
 
 	return next_input;
 }
 
 
 enum crmd_fsa_input
 do_lrm_rsc_op(
 	lrm_rsc_t *rsc, char *rid, const char *operation, xmlNodePtr msg)
 {
 	lrm_op_t* op = NULL;
 	int monitor_call_id = 0;
 
 	if(rsc == NULL) {
 		/* add it to the list */
 		crm_verbose("adding rsc %s before operation", rid);
 		fsa_lrm_conn->lrm_ops->add_rsc(
 			fsa_lrm_conn, rid,
 			get_xml_attr_nested(
 				msg, rsc_path, DIMOF(rsc_path) -2,
 				"class", TRUE),
 			get_xml_attr_nested(
 				msg, rsc_path, DIMOF(rsc_path) -2,
 				XML_ATTR_TYPE, TRUE),
 			NULL,NULL);
 		
 		rsc = fsa_lrm_conn->lrm_ops->get_rsc(
 			fsa_lrm_conn, rid);
 	}
 	
 	if(rsc == NULL) {
 		crm_err("Could not add resource to LRM");
 		return I_FAIL;
 	}
 
 	/* now do the op */
 	crm_info("Performing op %s on %s", operation, rid);
 	op = g_new(lrm_op_t, 1);
 	op->op_type   = g_strdup(operation);
 	op->params    = xml2list(msg, rsc_path, DIMOF(rsc_path));
 	op->timeout   = 0;
 	op->interval  = 0;
 	op->user_data = NULL;
 	op->target_rc = EVERYTIME;
 
 	if(safe_str_eq(CRMD_RSCSTATE_START, operation)) {
 		op->user_data = crm_strdup(CRMD_RSCSTATE_START_OK);
 	} else if(safe_str_eq(CRMD_RSCSTATE_STOP, operation)) {
 		op->user_data = crm_strdup(CRMD_RSCSTATE_STOP_OK);
 	} else {
 		crm_warn("Using status \"complete\" for op \"%s\""
 			 "... this is still in the experimental stage.",
 			operation);
 		op->user_data = crm_strdup(CRMD_RSCSTATE_GENERIC_OK);
 	}	
 	
 	rsc->ops->perform_op(rsc, op);
 
 	if(safe_str_eq(operation, CRMD_RSCSTATE_START)) {
 		/* initiate the monitor action */
 		op = g_new(lrm_op_t, 1);
 		op->op_type   = g_strdup(CRMD_RSCSTATE_MON);
 		op->params    = NULL;
 		op->user_data = crm_strdup(CRMD_RSCSTATE_MON_OK);
 		op->timeout   = 0;
 		op->interval  = 9000;
 		op->target_rc = CHANGED;
 		monitor_call_id = rsc->ops->perform_op(rsc, op);
 		if (monitor_call_id < 0) {
 			g_hash_table_insert(
 				monitors, strdup(rsc->id), GINT_TO_POINTER(monitor_call_id));
 		}
 		
 	} else if(safe_str_eq(operation, CRMD_RSCSTATE_STOP)) {
 		gpointer foo = g_hash_table_lookup(monitors, rsc->id);
 		int monitor_call_id = GPOINTER_TO_INT(foo);
 		
 		if(monitor_call_id > 0) {
 			crm_info("Stopping status op for %s", rsc->id);
 			rsc->ops->stop_op(rsc, monitor_call_id);
 			g_hash_table_remove(monitors, rsc->id);
 			/* TODO: Clean up key */
 			
 		} else {
 			crm_err("No monitor operation found for %s", rsc->id);
 		}
 	}
 	
 
 	return I_NULL;
 }
 
 GHashTable *
 xml2list(xmlNodePtr parent, const char**attr_path, int depth)
 {
 	xmlNodePtr node_iter = NULL;
 
 	GHashTable   *nvpair_hash =
 		g_hash_table_new(&g_str_hash, &g_str_equal);
 
 	xmlNodePtr nvpair_list =
 		find_xml_node_nested(parent, attr_path, depth);
 	
 	while(nvpair_list != NULL){
 		node_iter = nvpair_list->children;
 		while(node_iter != NULL) {
 			
 			const char *key   = xmlGetProp(
 				node_iter, XML_NVPAIR_ATTR_NAME);
 			const char *value = xmlGetProp(
 				node_iter, XML_NVPAIR_ATTR_VALUE);
 			
 			crm_verbose("Added %s=%s", key, value);
 			
 			g_hash_table_insert (nvpair_hash,
 					     crm_strdup(key),
 					     crm_strdup(value));
 			
 			node_iter = node_iter->next;
 		}
 		nvpair_list=nvpair_list->next;
 	}
 	
 	return nvpair_hash;
 }
 
 
 void
 do_update_resource(lrm_rsc_t *rsc, lrm_op_t* op)
 {
 /*
   <status>
   <nodes_status id=uname>
   <lrm>
   <lrm_resources>
   <lrm_resource id=>
   </...>
 */
 	xmlNodePtr update, iter;
 	char *tmp = NULL;
 	xmlNodePtr fragment;
 	int len = 0;
 	char *fail_state = NULL;
+
+
+	if(op == NULL || rsc == NULL) {
+		crm_err("Either resouce or op was not specified");
+		return;
+	}
 	
 	update = create_xml_node(NULL, XML_CIB_TAG_STATE);
 	set_uuid(update, XML_ATTR_UUID, fsa_our_uname);
 	set_xml_property_copy(update,  XML_ATTR_UNAME, fsa_our_uname);
 
 	iter = create_xml_node(update, XML_CIB_TAG_LRM);
 	iter = create_xml_node(iter,   XML_LRM_TAG_RESOURCES);
 	iter = create_xml_node(iter,   "lrm_resource");
 	
 	set_xml_property_copy(iter, XML_ATTR_ID, rsc->id);
 	set_xml_property_copy(iter, XML_LRM_ATTR_LASTOP, op->op_type);
 
 	len = strlen(op->op_type);
 	len += strlen("_failed_");
-	fail_state = (char*)crm_malloc(sizeof(char)*len);
-	sprintf(fail_state, "%s_failed", op->op_type);
+	crm_malloc(fail_state, sizeof(char)*len);
+	if(fail_state != NULL) {
+		sprintf(fail_state, "%s_failed", op->op_type);
+	}
 	
 	switch(op->op_status) {
 		case LRM_OP_CANCELLED:
 			break;
 		case LRM_OP_ERROR:
 		case LRM_OP_TIMEOUT:
 		case LRM_OP_NOTSUPPORTED:
 			crm_err("An LRM operation failed"
 					" or was aborted");
 			set_xml_property_copy(
 				iter, XML_LRM_ATTR_RSCSTATE, fail_state);
 			break;
 		case LRM_OP_DONE:
 			set_xml_property_copy(
-				iter, XML_LRM_ATTR_RSCSTATE, (const char*)op->user_data);
+				iter, XML_LRM_ATTR_RSCSTATE,
+				(const char*)op->user_data);
 			break;
 	}
 
 	crm_free(fail_state);
 	
 	tmp = crm_itoa(op->rc);
 	set_xml_property_copy(iter, XML_LRM_ATTR_RC, tmp);
 	crm_free(tmp);
 
 	tmp = crm_itoa(op->op_status);
 	set_xml_property_copy(iter, XML_LRM_ATTR_OPSTATUS, tmp);
 	crm_free(tmp);
 
 	set_xml_property_copy(iter, XML_LRM_ATTR_TARGET, fsa_our_uname);
 	
 	fragment = create_cib_fragment(update, NULL);
 
 	send_request(NULL, fragment, CRM_OP_UPDATE,
 		     fsa_our_dc, CRM_SYSTEM_DCIB, NULL);
 	
 	free_xml(fragment);
 	free_xml(update);
 }
 
 enum crmd_fsa_input
 do_lrm_event(long long action,
 	     enum crmd_fsa_cause cause,
 	     enum crmd_fsa_state cur_state,
 	     enum crmd_fsa_input cur_input,
 	     void *data)
 {
 	
 	if(cause == C_LRM_OP_CALLBACK) {
 		lrm_op_t* op = (lrm_op_t*)data;
 		lrm_rsc_t* rsc = op->rsc;
 
 		switch(op->op_status) {
 			case LRM_OP_ERROR:
 			case LRM_OP_CANCELLED:
 			case LRM_OP_TIMEOUT:
 			case LRM_OP_NOTSUPPORTED:
 				crm_err("An LRM operation failed"
 					" or was aborted");
-				/* keep going */
+				/* fall through */
 			case LRM_OP_DONE:
 				do_update_resource(rsc, op);
 
 
 				break;
 		}
 		
 	} else {
 
 		return I_FAIL;
 	}
 	
 	return I_NULL;
 }
 
 enum crmd_fsa_input
 do_fake_lrm_op(gpointer data)
 {
 	xmlNodePtr msg          = NULL;
 	const char *crm_op      = NULL;
 	const char *operation   = NULL;
 	const char *id_from_cib = NULL;
 	long int op_code = 0;
 	const char *op_status = NULL;
 	xmlNodePtr update = NULL;
 	xmlNodePtr state = NULL;
 	xmlNodePtr iter = NULL;
 	char *op_code_s = NULL;
 
 	
 	if(data == NULL) {
 		return I_ERROR;
 	}
 	
 	msg = (xmlNodePtr)data;
 	
 	operation = get_xml_attr_nested(
 		msg, rsc_path, DIMOF(rsc_path) -3, XML_LRM_ATTR_TASK, TRUE);
 	
 	id_from_cib = get_xml_attr_nested(
 		msg, rsc_path, DIMOF(rsc_path) -2, XML_ATTR_ID, TRUE);
 	
 	crm_op = get_xml_attr(msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE);
 
 	if(safe_str_eq(crm_op, "rsc_op")) {
 
 		state = create_xml_node(NULL, XML_CIB_TAG_STATE);
 		iter = create_xml_node(state, XML_CIB_TAG_LRM);
 
 		crm_info("Performing %s on %s", operation, id_from_cib);
 
 		/* so we can identify where to do the update */
 		set_uuid(state, XML_ATTR_UUID, fsa_our_uname);
 
 		iter = create_xml_node(iter, XML_LRM_TAG_RESOURCES);
 		iter = create_xml_node(iter, "lrm_resource");
 
 		set_xml_property_copy(iter, XML_ATTR_ID, id_from_cib);
 		set_xml_property_copy(iter, XML_LRM_ATTR_LASTOP, operation);
 
 
 #if 0
 		/* introduce a 10% chance of an action failing */
 		op_code = random();
 #endif
 		if((op_code % 10) == 1) {
 			op_code = 1;
 		} else {
 			op_code = 0;
 		}
 		op_code_s = crm_itoa(op_code);
 
 		if(op_code) {
 			/* fail */
 			if(safe_str_eq(operation, "start")){
 				op_status = "stopped";
 			} else {
 				op_status = "started";
 			}
 		} else {
 			/* pass */
 			if(safe_str_eq(operation, "start")){
 				op_status = "started";
 			} else {
 				op_status = "stopped";
 			}
 		}
 		
 		set_xml_property_copy(iter, XML_LRM_ATTR_RSCSTATE,op_status);
 		set_xml_property_copy(iter, XML_LRM_ATTR_OPSTATUS, op_code_s);
 		set_xml_property_copy(
 			iter, XML_LRM_ATTR_TARGET, fsa_our_uname);
 
 		crm_free(op_code_s);
 		
 		update = create_cib_fragment(state, NULL);
 		
 		send_request(NULL, update, CRM_OP_UPDATE,
 			     fsa_our_dc, CRM_SYSTEM_DCIB, NULL);
 	}
 	
 	return I_NULL;
 }
diff --git a/crm/crmd/messages.c b/crm/crmd/messages.c
index 8c3f3689ab..495477a81f 100644
--- a/crm/crmd/messages.c
+++ b/crm/crmd/messages.c
@@ -1,930 +1,939 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <string.h>
 #include <crmd_fsa.h>
 #include <libxml/tree.h>
 
 
 #include <hb_api.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 #include <crm/cib.h>
 
 #include <crmd.h>
 #include <crmd_messages.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 FILE *msg_out_strm = NULL;
 FILE *router_strm = NULL;
 
 GListPtr fsa_message_queue = NULL;
 
 extern void crm_shutdown(int nsig);
 
 gboolean relay_message(
 	xmlNodePtr xml_relay_message, gboolean originated_locally);
 
 
 gboolean send_ha_reply(
 	ll_cluster_t *hb_cluster,
 	xmlNodePtr xml_request, xmlNodePtr xml_response_data);
 
 gboolean send_xmlha_message(ll_cluster_t *hb_fd, xmlNodePtr root);
 
 #ifdef MSG_LOG
 
 #    define ROUTER_RESULT(x) char *msg_text = dump_xml_formatted(xml_relay_message);\
 	if(router_strm == NULL) {					\
 		router_strm = fopen(DEVEL_DIR"/router.log", "w");       \
 	}								\
 	fprintf(router_strm, "[%d RESULT (%s)]\t%s\t%s\n",		\
 		AM_I_DC,						\
 		xmlGetProp(xml_relay_message, XML_ATTR_REFERENCE),	\
 		x, msg_text);						\
 	fflush(router_strm);						\
 	crm_free(msg_text);						\
 	crm_xml_devel(xml_relay_message, x);
 #else
 #    define ROUTER_RESULT(x)	crm_xml_devel(xml_relay_message, x);
 #endif
 
 
 
 /* returns the current head of the FIFO queue */
 GListPtr
 put_message(xmlNodePtr new_message)
 {
 	int old_len = g_list_length(fsa_message_queue);
 
 	/* make sure to free it properly later */
 	fsa_message_queue = g_list_append(fsa_message_queue,
 					   copy_xml_node_recursive(new_message));
 
 	crm_verbose("Queue len: %d -> %d", old_len,
 		  g_list_length(fsa_message_queue));
 
 	
 	if(old_len == g_list_length(fsa_message_queue)){
 		crm_err("Couldnt add message to the queue");
 	}
 	
 	return fsa_message_queue;
 }
 
 /* returns the next message */
 xmlNodePtr
 get_message(void)
 {
 	xmlNodePtr message = g_list_nth_data(fsa_message_queue, 0);
 	fsa_message_queue = g_list_remove(fsa_message_queue, message);
 	return message;
 }
 
 /* returns the current head of the FIFO queue */
 gboolean
 is_message(void)
 {
 	return (g_list_length(fsa_message_queue) > 0);
 }
 
 
 /*	 A_MSG_STORE	*/
 enum crmd_fsa_input
 do_msg_store(long long action,
 	     enum crmd_fsa_cause cause,
 	     enum crmd_fsa_state cur_state,
 	     enum crmd_fsa_input current_input,
 	     void *data)
 {
 /*	xmlNodePtr new_message = (xmlNodePtr)data; */
 	
 
 /*	put_message(new_message); */
 
 	return I_NULL;
 }
 
 
 /*	A_MSG_ROUTE	*/
 enum crmd_fsa_input
 do_msg_route(long long action,
 	     enum crmd_fsa_cause cause,
 	     enum crmd_fsa_state cur_state,
 	     enum crmd_fsa_input current_input,
 	     void *data)
 {
 	enum crmd_fsa_input result = I_NULL;
 	xmlNodePtr xml_message = (xmlNodePtr)data;
 	gboolean routed = FALSE, defer = TRUE, do_process = TRUE;
 
 	
 
 #if 0
 /*	if(cause == C_IPC_MESSAGE) { */
 		if (crmd_authorize_message(root_xml_node,
 					   msg,
 					   curr_client) == FALSE) {
 			crm_debug("Message not authorized\t%s",
 				  dump_xml_formatted(root_xml_node, FALSE));
 			do_process = FALSE;
 		}
 /*	} */
 #endif
 	if(do_process) {
 		/* try passing the buck first */
 		routed = relay_message(xml_message, cause==C_IPC_MESSAGE);
 
 		if(routed == FALSE) {
 
 			defer = TRUE;
 			/* calculate defer */
 			result = handle_message(xml_message);
 			switch(result) {
 				case I_NULL:
 					defer = FALSE;
 					break;
 				case I_DC_HEARTBEAT:
 					defer = FALSE;
 					break;
 					
 					/* what else should go here? */
 				default:
 					crm_trace("Defering local processing of message");
 
 					put_message(xml_message);
 					result = I_REQUEST;
 					break;
 			}
 		} 
 	}
 	
 	return result;
 }
 
 /*
  * This method adds a copy of xml_response_data
  */
 gboolean
 send_request(xmlNodePtr msg_options, xmlNodePtr msg_data,
 	     const char *operation, const char *host_to, const char *sys_to,
 	     char **msg_reference)
 {
 	xmlNodePtr local_options = NULL;
 	gboolean was_sent = FALSE;
 	xmlNodePtr request = NULL;
 
 
 	if(msg_options == NULL) {
 		local_options = create_xml_node(NULL, XML_TAG_OPTIONS);
 		msg_options = local_options;
 	}
 
 	set_xml_property_copy(msg_options, XML_ATTR_OP, operation);
 	
 	request = create_request(
 		msg_options, msg_data, host_to, sys_to,
 		AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD,
 		NULL, NULL);
 
 /*	crm_xml_devel(request, "Final request..."); */
 
 	if(msg_reference != NULL) {
 		*msg_reference = crm_strdup(xmlGetProp(request, XML_ATTR_REFERENCE));
 	}
 	
 	was_sent = relay_message(request, TRUE);
 
 	if(was_sent == FALSE) {
 		put_message(request);
 	}
 	
 	free_xml(request);
 	free_xml(local_options);
 
 	return was_sent;
 }
 
 /*
  * This method adds a copy of xml_response_data
  */
 gboolean
 store_request(xmlNodePtr msg_options, xmlNodePtr msg_data,
 	      const char *operation, const char *sys_to)
 {
 	xmlNodePtr request = NULL;
 	
 
 	msg_options = set_xml_attr(msg_options, XML_TAG_OPTIONS,
 				   XML_ATTR_OP, operation, TRUE);
 
 	crm_verbose("Storing op=%s message for later processing", operation);
 	
 	request = create_request(msg_options,
 				 msg_data,
 				 NULL,
 				 sys_to,
 				 AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD,
 				 NULL,
 				 NULL);
 
 	put_message(request);
 	free_xml(request);
 	
 	return TRUE;
 }
 
 gboolean
 relay_message(xmlNodePtr xml_relay_message, gboolean originated_locally)
 {
 	int is_for_dc	= 0;
 	int is_for_dcib	= 0;
 	int is_for_crm	= 0;
 	int is_for_cib	= 0;
 	int is_local    = 0;
 	gboolean processing_complete = TRUE;
 	const char *host_to = xmlGetProp(xml_relay_message,XML_ATTR_HOSTTO);
 	const char *sys_to  = xmlGetProp(xml_relay_message,XML_ATTR_SYSTO);
 
 	crm_debug("Routing message %s",
 		  xmlGetProp(xml_relay_message, XML_ATTR_REFERENCE));
 	
 	if(xml_relay_message == NULL) {
 		crm_err("Cannot route empty message");
 		return TRUE;
 	}
 
 	if(strcmp(CRM_OP_HELLO, xml_relay_message->name) == 0) {
 		/* quietly ignore */
 		return TRUE;
 	}
 
 	if(strcmp(XML_MSG_TAG, xml_relay_message->name) != 0) {
 		crm_xml_err(xml_relay_message,
 			    "Bad message type, should be crm_message");
 		return TRUE;
 	}
 	
 	if(sys_to == NULL) {
 		crm_xml_err(xml_relay_message,
 			    "Message did not have any value for sys_to");
 		return TRUE;
 	}
 	
 	is_for_dc   = (strcmp(CRM_SYSTEM_DC,   sys_to) == 0);
 	is_for_dcib = (strcmp(CRM_SYSTEM_DCIB, sys_to) == 0);
 	is_for_cib  = (strcmp(CRM_SYSTEM_CIB,  sys_to) == 0);
 	is_for_crm  = (strcmp(CRM_SYSTEM_CRMD, sys_to) == 0);
 	
 	is_local = 0;
 	if(host_to == NULL || strlen(host_to) == 0) {
 		if(is_for_dc) {
 			is_local = 0;
 
 		} else if(is_for_crm && originated_locally) {
 			is_local = 0;
 
 		} else {
 			is_local = 1;
 		}
 		
 	} else if(strcmp(fsa_our_uname, host_to) == 0) {
 		is_local=1;
 	}
 
 	crm_trace("is_local    %d", is_local);
 	crm_trace("is_for_dcib %d", is_for_dcib);
 	crm_trace("is_for_dc   %d", is_for_dc);
 	crm_trace("is_for_crm  %d", is_for_crm);
 	crm_trace("AM_I_DC     %d", AM_I_DC);
-	crm_trace("sys_to      %s", sys_to);
-	crm_trace("host_to     %s", host_to);
+	crm_trace("sys_to      %s", crm_str(sys_to));
+	crm_trace("host_to     %s", crm_str(host_to));
 	
 	if(is_for_dc || is_for_dcib) {
 		if(AM_I_DC) {
 			ROUTER_RESULT("Message result: DC/CRMd process");
 			processing_complete = FALSE; /* more to be done by caller */
 
 		} else if(originated_locally) {
 			ROUTER_RESULT("Message result: External relay to DC");
 			send_msg_via_ha(xml_relay_message, NULL);
 
 		} else {
 			ROUTER_RESULT("Message result: Discard, not DC");
 			/* discard */
 		}
 		
 	} else if(is_local && (is_for_crm || is_for_cib)) {
 		ROUTER_RESULT("Message result: CRMd process");
 		processing_complete = FALSE; /* more to be done by caller */
 
 	} else if(is_local) {
 		ROUTER_RESULT("Message result: Local relay");
 		send_msg_via_ipc(xml_relay_message, sys_to);
 		
 	} else {
 		ROUTER_RESULT("Message result: External relay");
 		send_msg_via_ha(xml_relay_message, host_to);
 	}
 	
 	return processing_complete;
 }
 
 gboolean
 crmd_authorize_message(
 	xmlNodePtr root_xml_node,
 	IPC_Message *client_msg, crmd_client_t *curr_client)
 {
 	/* check the best case first */
 	const char *sys_from   = xmlGetProp(root_xml_node,
 					    XML_ATTR_SYSFROM);
 	char *uuid = NULL;
 	char *client_name = NULL;
 	char *major_version = NULL;
 	char *minor_version = NULL;
 	const char *filtered_from;
 	gpointer table_key = NULL;
 	gboolean result;
 	struct crm_subsystem_s *the_subsystem = NULL;
 	gboolean can_reply = FALSE; /* no-one has registered with this id */
 
 	const char *op = get_xml_attr(
 		root_xml_node, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE);
 	
 	
 
 	if (safe_str_neq(CRM_OP_HELLO, op)) {
 
 		if(sys_from == NULL) {
 			crm_warn("Message [%s] was had no value for %s... discarding",
 				 xmlGetProp(root_xml_node, XML_ATTR_REFERENCE),
 				XML_ATTR_SYSFROM);
 			return FALSE;
 		}
 		
 		filtered_from = sys_from;
 
 		/* The CIB can have two names on the DC */
 		if(strcmp(sys_from, CRM_SYSTEM_DCIB) == 0)
 			filtered_from = CRM_SYSTEM_CIB;
 		
 		if (g_hash_table_lookup (ipc_clients, filtered_from) != NULL) {
 			can_reply = TRUE;  /* reply can be routed */
 		}
 		
 		crm_verbose("Message reply can%s be routed from %s.",
 			   can_reply?"":" not", sys_from);
 
 		if(can_reply == FALSE) {
 			crm_warn("Message [%s] not authorized",
 				 xmlGetProp(root_xml_node, XML_ATTR_REFERENCE));
 		}
 		
 		return can_reply;
 	}
 	
 	crm_debug("received client join msg: %s",
 		 (char*)client_msg->msg_body);
 
 	result = process_hello_message(root_xml_node,
 				       &uuid,
 				       &client_name,
 				       &major_version,
 				       &minor_version);
 
 	if (result == TRUE) {
 		/* check version */
 		int mav = atoi(major_version);
 		int miv = atoi(minor_version);
 		if (mav < 0 || miv < 0) {
 			crm_err("Client version (%d:%d) is not acceptable",
 				mav, miv);
 			result = FALSE;
 		}
 		crm_free(major_version);
 		crm_free(minor_version);
 	}
 
 	if (result == TRUE) {
 		/* if we already have one of those clients
 		 * only applies to te, pe etc.  not admin clients
 		 */
 
 		
 		if (client_name == NULL) {
 			crm_warn("Client had not registered with us yet");
 
 		} else if (strcmp(CRM_SYSTEM_PENGINE, client_name) == 0) {
 			the_subsystem = pe_subsystem;
 			
 		} else if (strcmp(CRM_SYSTEM_TENGINE, client_name) == 0) {
 			the_subsystem = te_subsystem;
 			
 		} else if (strcmp(CRM_SYSTEM_CIB, client_name) == 0) {
 			the_subsystem = cib_subsystem;
 		}
 
 		if (the_subsystem != NULL) {
 			/* do we already have one? */
 			result =(fsa_input_register & the_subsystem->flag)==0;
 			if(result) {
 				the_subsystem->ipc =
 					curr_client->client_channel;
 
 			} /* else we didnt ask for the client to start */
 
 		} else if(client_name != NULL && uuid != NULL) {
 			table_key = (gpointer)
 				generate_hash_key(client_name, uuid);
 		} else {
 			result = FALSE;
 			crm_err("Bad client details (client_name=%s, uuid=%s)",
-			       client_name, uuid);
+				crm_str(client_name), uuid);
 		}
 	}
 	
 	if(result == TRUE && table_key == NULL) {
 		table_key = (gpointer)crm_strdup(client_name);
 	}
 	
 	if (result == TRUE) {
 		crm_info("Accepted client %s", (char*)table_key);
 
 		curr_client->table_key = table_key;
 		curr_client->sub_sys = crm_strdup(client_name);
 		curr_client->uuid = crm_strdup(uuid);
 	
 		g_hash_table_insert (ipc_clients,
 				     table_key,
 				     curr_client->client_channel);
 
 		send_hello_message(curr_client->client_channel,
 				   "n/a", CRM_SYSTEM_CRMD,
 				   "0", "1");
 
 		crm_debug("Updated client list with %s",
 		       (char*)table_key);
 		
 		if(the_subsystem != NULL) {
 			set_bit_inplace(&fsa_input_register,
 					the_subsystem->flag);
 		}
 		
 		s_crmd_fsa(C_SUBSYSTEM_CONNECT, I_NULL, NULL);
 
 	} else {
 		crm_err("Rejected client logon request");
 		curr_client->client_channel->ch_status = IPC_DISC_PENDING;
 	}
 	
 	if(uuid != NULL) crm_free(uuid);
 	if(client_name != NULL) crm_free(client_name);
 
 	/* hello messages should never be processed further */
 	return FALSE;
 }
 
 enum crmd_fsa_input
 handle_message(xmlNodePtr stored_msg)
 {
 	xmlNodePtr wrapper = NULL;
 	enum crmd_fsa_input next_input = I_NULL;
 
 	const char *sys_to   = get_xml_attr(
 		stored_msg, NULL, XML_ATTR_SYSTO,     TRUE);
 
 	const char *sys_from = get_xml_attr(
 		stored_msg, NULL, XML_ATTR_SYSFROM,   TRUE);
 
 	const char *host_from= get_xml_attr(
 		stored_msg, NULL, XML_ATTR_HOSTFROM,  FALSE);
 
 	const char *msg_ref  = get_xml_attr(
 		stored_msg, NULL, XML_ATTR_REFERENCE, TRUE);
 
 	const char *type     = get_xml_attr(
 		stored_msg, NULL, XML_ATTR_MSGTYPE,   TRUE);
 	
 	const char *op       = get_xml_attr(
 		stored_msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE);
 
 /*	crm_xml_devel(stored_msg, "Processing message"); */
 
 	crm_verbose("Received %s %s in state %s",
 		    op, type, fsa_state2string(fsa_state));
 	
 	if(type == NULL || op == NULL) {
 		crm_err("Ignoring message (type=%s), (op=%s)",
 		       type, op);
 		crm_xml_devel(stored_msg, "Bad message");
 		
 	} else if(strcmp(type, XML_ATTR_REQUEST) == 0){
 		if(strcmp(op, CRM_OP_HBEAT) == 0) {
 			next_input = I_DC_HEARTBEAT;
 
 		} else if(strcmp(op, CRM_OP_VOTE) == 0) {
 			next_input = I_ELECTION;
 				
 		} else if(AM_I_DC && strcmp(op, CRM_OP_TEABORT) == 0) {
-			next_input = I_PE_CALC;
+			if(fsa_state != S_INTEGRATION) {
+				next_input = I_PE_CALC;
+
+			} else {	
+				crm_debug("Ignoring %s in state %s."
+					"  Waiting for the integration to"
+					" complete first.",
+					op, fsa_state2string(fsa_state));
+			}
+			
 				
 		} else if(AM_I_DC
 			  && strcmp(op, CRM_OP_TECOMPLETE) == 0) {
 			if(fsa_state == S_TRANSITION_ENGINE) {
 				next_input = I_SUCCESS;
 /* silently ignore? probably means the TE is signaling OK too early
 			} else {
 				crm_warn(
 				       "Op %s is only valid in state %s (%s)",
 				       op,
 				       fsa_state2string(S_TRANSITION_ENGINE),
 				       fsa_state2string(fsa_state));
 */
 			}	
 				
 		} else if(strcmp(op, CRM_OP_WELCOME) == 0) {
 			next_input = I_WELCOME;
 				
 		} else if(strcmp(op, "init_shutdown") == 0) {
 
 			crm_warn("This method of shutting down is somewhat untested");
 			crm_shutdown(SIGTERM);
 			/*next_input = I_SHUTDOWN; */
 			next_input = I_NULL;
 				
 		} else if(strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
 
 			/* create cib fragment and add to message */
 
 			/* handle here to avoid potential version issues
 			 *   where the shutdown message/proceedure may have
 			 *   been changed in later versions.
 			 *
 			 * This way the DC is always in control of the shutdown
 			 */
 
 			xmlNodePtr frag = NULL;
 			time_t now = time(NULL);
 			char *now_s = crm_itoa((int)now);
 			xmlNodePtr node_state =
 				create_xml_node(NULL, XML_CIB_TAG_STATE);
 
 			crm_info("Creating shutdown request for %s",host_from);
 			
 			set_uuid(node_state, XML_ATTR_UUID, host_from);
 			set_xml_property_copy(
 				node_state, XML_ATTR_UNAME, host_from);
 			set_xml_property_copy(
 				node_state, XML_CIB_ATTR_SHUTDOWN,  now_s);
 			set_xml_property_copy(
 				node_state,
 				XML_CIB_ATTR_EXPSTATE,
 				CRMD_STATE_INACTIVE);
 
 			frag = create_cib_fragment(node_state, NULL);
 			xmlAddChild(stored_msg, frag);
 
 			free_xml(node_state);
 			crm_free(now_s);
 			
 			next_input = I_CIB_OP;
 				
 		} else if(strcmp(op, CRM_OP_SHUTDOWN) == 0) {
 			next_input = I_TERMINATE;
 			
 		} else if(strcmp(op, "debug_inc") == 0) {
 			int level = get_crm_log_level();
 			set_crm_log_level(level+1);
 			crm_info("Debug set to %d (was %d)",
 				 get_crm_log_level(), level);
 
 		} else if(strcmp(op, "debug_dec") == 0) {
 			int level = get_crm_log_level();
 			set_crm_log_level(level-1);
 			crm_info("Debug set to %d (was %d)",
 				 get_crm_log_level(), level);
 			
 		} else if(strcmp(op, CRM_OP_ANNOUNCE) == 0) {
 			next_input = I_NODE_JOIN;
 			
 		} else if(strcmp(op, CRM_OP_REPLACE) == 0
 			|| strcmp(op, CRM_OP_QUERY) == 0
 			|| strcmp(op, CRM_OP_ERASE) == 0) {
 			next_input = I_CIB_OP;
 			fprintf(router_strm, "Message result: CIB Op\n");
 
 		} else if(AM_I_DC
 			  && (strcmp(op, CRM_OP_CREATE) == 0
 			      || strcmp(op, CRM_OP_UPDATE) == 0
 			      || strcmp(op, CRM_OP_DELETE) == 0)) {
 			/* updates should only be performed on the DC */
 			next_input = I_CIB_OP;
 				
 		} else if(strcmp(op, CRM_OP_PING) == 0) {
 			/* eventually do some stuff to figure out
 			 * if we /are/ ok
 			 */
 			xmlNodePtr ping =
 				createPingAnswerFragment(sys_to, "ok");
 
 			set_xml_property_copy(ping, "crmd_state",
 					      fsa_state2string(fsa_state));
 
 			wrapper = create_reply(stored_msg, ping);
 
 			relay_message(wrapper, TRUE);
 			free_xml(wrapper);
 				
 		} else {
 			crm_err("Unexpected request (op=%s) sent to the %s",
 				op, AM_I_DC?"DC":"CRMd");
 		}
 		
 	} else if(strcmp(type, XML_ATTR_RESPONSE) == 0) {
 
 		if(strcmp(op, CRM_OP_WELCOME) == 0) {
 			next_input = I_WELCOME_ACK;
 				
 		} else if(AM_I_DC
 			  && strcmp(op, CRM_OP_PECALC) == 0) {
 
 			if(fsa_state == S_POLICY_ENGINE
 			   && safe_str_eq(msg_ref, fsa_pe_ref)) {
 				next_input = I_SUCCESS;
 			} else if(fsa_state != S_POLICY_ENGINE) {
 				crm_err("Reply to %s is only valid in state %s",
 					op, fsa_state2string(S_POLICY_ENGINE));
 				
 			} else {
 				crm_verbose("Skipping superceeded reply from %s",
 					  sys_from);
 			}
 			
 		} else if(strcmp(op, CRM_OP_VOTE) == 0
 			  || strcmp(op, CRM_OP_HBEAT) == 0
 			  || strcmp(op, CRM_OP_WELCOME) == 0
 			  || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0
 			  || strcmp(op, CRM_OP_SHUTDOWN) == 0
 			  || strcmp(op, CRM_OP_ANNOUNCE) == 0) {
 			next_input = I_NULL;
 			
 		} else if(strcmp(op, CRM_OP_CREATE) == 0
 			  || strcmp(op, CRM_OP_UPDATE) == 0
 			  || strcmp(op, CRM_OP_DELETE) == 0
 			  || strcmp(op, CRM_OP_REPLACE) == 0
 			  || strcmp(op, CRM_OP_ERASE) == 0) {
 			
 			/* perhaps we should do somethign with these replies,
 			 * especially check that the actions passed
 			 */
 /* 			fprintf(router_strm, "Message result: CIB Reply\n"); */
 
 		} else {
 			crm_err("Unexpected response (op=%s) sent to the %s",
 				op, AM_I_DC?"DC":"CRMd");
 			next_input = I_NULL;
 		}
 	} else {
 		crm_err("Unexpected message type %s", type);
 			
 	}
 
 /* 	crm_verbose("%s: Next input is %s", __FUNCTION__, */
 /* 		   fsa_input2string(next_input)); */
 	
 		
 	return next_input;
 		
 }
 
 gboolean
 send_xmlha_message(ll_cluster_t *hb_fd, xmlNodePtr root)
 {
 	int xml_len          = -1;
 	int send_result      = -1;
 	char *xml_text       = NULL;
 	const char *host_to  = NULL;
 	const char *sys_to   = NULL;
 	struct ha_msg *msg   = NULL;
 	gboolean all_is_good = TRUE;
 	gboolean broadcast   = FALSE;
 	int log_level        = LOG_DEBUG;
 
 	xmlNodePtr opts = find_xml_node(root, XML_TAG_OPTIONS);
 	const char *op  = xmlGetProp(opts, XML_ATTR_OP);
 
 #ifdef MSG_LOG
 	char *msg_text = NULL;
 #endif
 
 	
     
 	if (root == NULL) {
 		crm_err("Attempt to send NULL Message via HA failed.");
 		all_is_good = FALSE;
 	}
 
 	host_to = xmlGetProp(root, XML_ATTR_HOSTTO);
 	sys_to = xmlGetProp(root, XML_ATTR_SYSTO);
 	
 	if (all_is_good) {
 		msg = ha_msg_new(4); 
 		ha_msg_add(msg, F_TYPE, "CRM");
 		ha_msg_add(msg, F_COMMENT, "A CRM xml message");
 		xml_text = dump_xml_unformatted(root);
 		xml_len = strlen(xml_text);
 		
 		if (xml_text == NULL || xml_len <= 0) {
 			crm_err(
 			       "Failed sending an invalid XML Message via HA");
 			all_is_good = FALSE;
 			crm_xml_devel(root, "Bad message was");
 			
 		} else {
 			if(ha_msg_add(msg, "xml", xml_text) == HA_FAIL) {
 				crm_err("Could not add xml to HA message");
 				all_is_good = FALSE;
 			}
 		}
 	}
 
 	if (all_is_good) {
 		if (sys_to == NULL || strlen(sys_to) == 0)
 		{
 			crm_err("You did not specify a destination sub-system"
 				" for this message.");
 			all_is_good = FALSE;
 		}
 	}
 
 
 	/* There are a number of messages may not need to be ordered.
 	 * At a later point perhaps we should detect them and send them
 	 *  as unordered messages.
 	 */
 	if (all_is_good) {
 		if (host_to == NULL
 		    || strlen(host_to) == 0) {
 			broadcast = TRUE;
 			send_result=hb_fd->llc_ops->sendclustermsg(hb_fd, msg);
 		}
 		else {
 			send_result = hb_fd->llc_ops->send_ordered_nodemsg(
 				hb_fd, msg, host_to);
 		}
 		
 		if(send_result != HA_OK)
 			all_is_good = FALSE;
 	}
 	
 	if(all_is_good == FALSE) {
 		log_level = LOG_ERR;
 	}
 
 	if(log_level == LOG_ERR
 	   || (safe_str_neq(op, CRM_OP_HBEAT))) {
 		do_crm_log(log_level, __FUNCTION__, 
-		       "Sending %s HA message (ref=%s, len=%d) to %s@%s %s.",
-		       broadcast?"broadcast":"directed",
-		       xmlGetProp(root, XML_ATTR_REFERENCE), xml_len,
-		       sys_to, host_to==NULL?"<all>":host_to,
-		       all_is_good?"succeeded":"failed");
+			   "Sending %sHA message (ref=%s,len=%d) to %s@%s %s.",
+			   broadcast?"broadcast ":"directed ",
+			   xmlGetProp(root, XML_ATTR_REFERENCE), xml_len,
+			   sys_to, host_to==NULL?"<all>":host_to,
+			   all_is_good?"succeeded":"failed");
 	}
 	
 #ifdef MSG_LOG
 	msg_text = dump_xml_formatted(root);
 	if(msg_out_strm == NULL) {
 		msg_out_strm = fopen(DEVEL_DIR"/outbound.log", "w");
 	}
 	fprintf(msg_out_strm, "[%s HA (%s:%d)]\t%s\n",
 		all_is_good?"succeeded":"failed",
 		xmlGetProp(root, XML_ATTR_REFERENCE),
 		send_result,
 		msg_text);
 	
 	fflush(msg_out_strm);
 	crm_free(msg_text);
 	if(msg != NULL) {
 		ha_msg_del(msg);
 	}
 #endif
 		
 	return all_is_good;
 }
 		    
 
 
 /* required?  or just send to self an let relay_message do its thing? */
 /*
  * This method adds a copy of xml_response_data
  */
 gboolean
 send_ha_reply(ll_cluster_t *hb_cluster,
 	      xmlNodePtr xml_request,
 	      xmlNodePtr xml_response_data)
 {
 	gboolean was_sent = FALSE;
 	xmlNodePtr reply;
 
 	
 	was_sent = FALSE;
 	reply = create_reply(xml_request, xml_response_data);
 	if (reply != NULL) {
 		was_sent = send_xmlha_message(hb_cluster, reply);
 		free_xml(reply);
 	}
 	return was_sent;
 }
 
 
 void
 send_msg_via_ha(xmlNodePtr action, const char *dest_node)
 {
 	
 	if (action == NULL) return;
 
 	if (validate_crm_message(action, NULL, NULL, NULL) == NULL)
 	{
 		crm_err("Relay message to (%s) via HA was invalid, ignoring",
 			dest_node);
 		return;
 	}
 /*	crm_verbose("Relaying message to (%s) via HA", dest_node); */
 	set_xml_property_copy(action, XML_ATTR_HOSTTO, dest_node);
 
 	send_xmlha_message(fsa_cluster_conn, action);
 	return;
 }
 
 
 void
 send_msg_via_ipc(xmlNodePtr action, const char *sys)
 {
 	IPC_Channel *client_channel;
 	enum crmd_fsa_input next_input;
 
 	crm_trace("relaying msg to sub_sys=%s via IPC", sys);
 
 	client_channel =
 		(IPC_Channel*)g_hash_table_lookup (ipc_clients, sys);
 
 	if(xmlGetProp(action, XML_ATTR_HOSTFROM) == NULL) {
 		set_xml_property_copy(
 			action, XML_ATTR_HOSTFROM, fsa_our_uname);
 	}
 	
 	if (client_channel != NULL) {
 		crm_debug("Sending message via channel %s.", sys);
 		
 		send_xmlipc_message(client_channel, action);
 		
 	} else if(sys != NULL && strcmp(sys, CRM_SYSTEM_CIB) == 0) {
 		crm_err("Sub-system (%s) has been incorporated into the CRMd.",
 			sys);
 		crm_xml_devel(action, "Change the way we handle");
 		relay_message(process_cib_message(action, TRUE), TRUE);
 		
 	} else if(sys != NULL && strcmp(sys, CRM_SYSTEM_LRMD) == 0) {
 
 #ifdef FSA_TRACE
 		crm_verbose("Invoking action %s (%.16llx)",
 			    fsa_action2string(A_LRM_INVOKE),
 			    A_LRM_INVOKE);
 #endif
 
 		next_input =
 			do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE,
 				      fsa_state, I_MESSAGE, action);
 
 		/* todo: feed this back in for anything != I_NULL */
 		
 #ifdef FSA_TRACE
 		crm_verbose("Result of action %s was %s",
 			    fsa_action2string(A_LRM_INVOKE),
 			    fsa_input2string(next_input));
 #endif
 		
 	} else {
 		crm_err("Unknown Sub-system (%s)... discarding message.",
 			sys);
 	}    
 	return;
 }	
diff --git a/crm/crmd/subsystems.c b/crm/crmd/subsystems.c
index f6c4a6ffb1..c62645cd73 100644
--- a/crm/crmd/subsystems.c
+++ b/crm/crmd/subsystems.c
@@ -1,642 +1,641 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <crmd_fsa.h>
 
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include <unistd.h>			/* for access */
 #include <clplumbing/cl_signal.h>
 #include <clplumbing/realtime.h>
 #include <sys/types.h>	/* for calls to open */
 #include <sys/stat.h>	/* for calls to open */
 #include <fcntl.h>	/* for calls to open */
 #include <pwd.h>	/* for getpwuid */
 #include <grp.h>	/* for initgroups */
 
 #include <sys/time.h>	/* for getrlimit */
 #include <sys/resource.h>/* for getrlimit */
 
 #include <errno.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crmd_messages.h>
 #include <crmd_callbacks.h>
 
 #include <crm/cib.h>
 #include <crmd.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 #define CLIENT_EXIT_WAIT 10
 
 static gboolean stop_subsystem (struct crm_subsystem_s *centry);
 static gboolean start_subsystem(struct crm_subsystem_s *centry);
 
 struct crm_subsystem_s *cib_subsystem = NULL;
 struct crm_subsystem_s *te_subsystem  = NULL;
 struct crm_subsystem_s *pe_subsystem  = NULL;
 
 
 /*	 A_CIB_STOP, A_CIB_START, A_CIB_RESTART,	*/
 enum crmd_fsa_input
 do_cib_control(long long action,
 	       enum crmd_fsa_cause cause,
 	       enum crmd_fsa_state cur_state,
 	       enum crmd_fsa_input current_input,
 	       void *data)
 {
 	enum crmd_fsa_input result = I_NULL;
 	struct crm_subsystem_s *this_subsys = cib_subsystem;
 	
 	long long stop_actions = A_CIB_STOP;
 	long long start_actions = A_CIB_START;
 
 	
 	
 	if(action & stop_actions) {
 		/* dont do anything, its embedded now */
 	}
 
 	if(action & start_actions) {
 
 		if(cur_state != S_STOPPING) {
 			if(startCib(CIB_FILENAME) == FALSE)
 				result = I_FAIL;
 
 		} else {
 			crm_info("Ignoring request to start %s after shutdown",
 				 this_subsys->command);
 		}
 	}
 	
 	return result;
 }
 
 
 /*	 A_CIB_INVOKE, A_CIB_BUMPGEN, A_UPDATE_NODESTATUS	*/
 enum crmd_fsa_input
 do_cib_invoke(long long action,
 	      enum crmd_fsa_cause cause,
 	      enum crmd_fsa_state cur_state,
 	      enum crmd_fsa_input current_input,
 	      void *data)
 {
 	xmlNodePtr cib_msg = NULL;
 	xmlNodePtr answer = NULL;
 	xmlNodePtr new_options = NULL;
 	const char *section = NULL;
 	enum crmd_fsa_input result = I_NULL;
 
 	if(data != NULL) {
 		cib_msg = (xmlNodePtr)data;
 	}
 	
 	
 	if(action & A_CIB_INVOKE || action & A_CIB_INVOKE_LOCAL) {
 /*		gboolean is_update   = FALSE; */
 		xmlNodePtr options   = find_xml_node(cib_msg, XML_TAG_OPTIONS);
 		const char *sys_from = xmlGetProp(cib_msg, XML_ATTR_SYSFROM);
 		const char *op       = xmlGetProp(options, XML_ATTR_OP);
 		
 		crm_xml_devel(cib_msg, "[CIB b4]");
 		if(cib_msg == NULL) {
 			crm_err("No message for CIB command");
 			return I_NULL; /* I_ERROR */
 
 		} else if(op == NULL) {
 			crm_xml_devel(cib_msg, "Invalid CIB Message");
 			return I_NULL; /* I_ERROR */
 
 		}
 
 		set_xml_property_copy(cib_msg, XML_ATTR_SYSTO, "cib");
 		answer = process_cib_message(cib_msg, TRUE);
 
 		if(action & A_CIB_INVOKE) {
 
 			if(AM_I_DC == FALSE) {
 				if(relay_message(answer, TRUE) == FALSE) {
 					crm_err("Confused what to do with cib result");
 					crm_xml_devel(answer, "Couldnt route: ");
 					result = I_ERROR;
 				}
 				
 			} else if(strcmp(op, CRM_OP_CREATE) == 0
 			   || strcmp(op, CRM_OP_UPDATE) == 0
 			   || strcmp(op, CRM_OP_DELETE) == 0
 			   || strcmp(op, CRM_OP_REPLACE) == 0
 			   || strcmp(op, CRM_OP_WELCOME) == 0
 			   || strcmp(op, CRM_OP_SHUTDOWN_REQ) == 0) {
 				result = I_CIB_UPDATE;	
 				
 			} else if(strcmp(op, CRM_OP_ERASE) == 0) {
 				/* regenerate everyone's state and our node entry */
 				result = I_ELECTION_DC;	
 			}
 			
 			/* the TENGINE will get CC'd by other means. */
 			if(AM_I_DC
 			   && sys_from != NULL
 			   && safe_str_neq(sys_from, CRM_SYSTEM_TENGINE) 
 			   && safe_str_neq(sys_from, CRM_SYSTEM_CRMD)
 			   && safe_str_neq(sys_from, CRM_SYSTEM_DC)
 			   && relay_message(answer, TRUE) == FALSE) {
 				crm_err("Confused what to do with cib result");
 				crm_xml_devel(answer, "Couldnt route: ");
 				result = I_ERROR;
 				
 			}
 			
 /* 		} else { */
 /* 			put_message(answer); */
 /* 			return I_REQUEST; */
 			
 		}
 
 		crm_xml_devel(cib_msg, "[CIB after]");
 		return result;
 
 	} else if(action & A_CIB_BUMPGEN) {
 /*		xmlNodePtr options   = find_xml_node(cib_msg, XML_TAG_OPTIONS); */
 /*		const char *op       = xmlGetProp(options, XML_ATTR_OP); */
 
 		if(AM_I_DC == FALSE) {
 			return I_NULL;
 		}
 
  		/* check if the response was ok before next bit */
 
 /*		if(safe_str_neq(op, CRM_OP_WELCOME)) { */
 			/* set the section so that we dont always send the
 			 * whole thing
 			 */
 		section = get_xml_attr(
 			cib_msg, XML_TAG_OPTIONS,
 			XML_ATTR_FILTER_TYPE, FALSE);
 /*		} */
 		
 		if(section != NULL) {
 			new_options = set_xml_attr(
 				NULL, XML_TAG_OPTIONS, XML_ATTR_FILTER_TYPE,
 				section, TRUE);
 		}
 		
 		answer = process_cib_request(
 			CRM_OP_BUMP, new_options, NULL);
 
 		free_xml(new_options);
 
 		if(answer == NULL) {
 			crm_err("Result of BUMP in %s was NULL",
 			       __FUNCTION__);
 			return I_FAIL;
 		}
 
 		send_request(NULL, answer, CRM_OP_REPLACE,
 			     NULL, CRM_SYSTEM_CRMD, NULL);
 		
 		free_xml(answer);
 
 	} else {
 		crm_err("Unexpected action %s in %s",
 		       fsa_action2string(action), __FUNCTION__);
 	}
 	
 	
 	return I_NULL;
 }
 
 
 /*	 A_PE_START, A_PE_STOP, A_TE_RESTART	*/
 enum crmd_fsa_input
 do_pe_control(long long action,
 	      enum crmd_fsa_cause cause,
 	      enum crmd_fsa_state cur_state,
 	      enum crmd_fsa_input current_input,
 	      void *data)
 {
 	enum crmd_fsa_input result = I_NULL;
 	struct crm_subsystem_s *this_subsys = pe_subsystem;
 
 	long long stop_actions = A_PE_STOP;
 	long long start_actions = A_PE_START;
 	
 	
 
 	if(action & stop_actions) {
 		if(stop_subsystem(this_subsys) == FALSE)
 			result = I_FAIL;
 		else  if(this_subsys->pid > 0){
 			int lpc = CLIENT_EXIT_WAIT;
 			int pid_status = -1;
 			while(lpc-- > 0
 			      && this_subsys->pid > 0
 			      && CL_PID_EXISTS(this_subsys->pid)) {
 
 				sleep(1);
 				waitpid(this_subsys->pid, &pid_status, WNOHANG);
 			}
 			
 			if(CL_PID_EXISTS(this_subsys->pid)) {
 				crm_err("Process %s is still active with pid=%d",
 				       this_subsys->command, this_subsys->pid);
 				result = I_FAIL;
 			} 
 		}
 
 		cleanup_subsystem(this_subsys);
 	}
 
 	if(action & start_actions) {
 
 		if(cur_state != S_STOPPING) {
 			if(start_subsystem(this_subsys) == FALSE) {
 				result = I_FAIL;
 				cleanup_subsystem(this_subsys);
 			}
 		} else {
 			crm_info("Ignoring request to start %s while shutting down",
 			       this_subsys->command);
 		}
 	}
 	
 	return result;
 }
 
 char *fsa_pe_ref = NULL;
 
 /*	 A_PE_INVOKE	*/
 enum crmd_fsa_input
 do_pe_invoke(long long action,
 	     enum crmd_fsa_cause cause,
 	     enum crmd_fsa_state cur_state,
 	     enum crmd_fsa_input current_input,
 	     void *data)
 {
 	xmlNodePtr local_cib = NULL;
 
 	stopTimer(integration_timer);
 
 	if(is_set(fsa_input_register, R_PE_CONNECTED) == FALSE){
 		
 		crm_info("Waiting for the PE to connect");
 		return I_WAIT_FOR_EVENT;
 		
 	}
 	
 	local_cib = get_cib_copy();
 
 	crm_verbose("Invoking %s with %p", CRM_SYSTEM_PENGINE, local_cib);
 
 	if(fsa_pe_ref) {
 		crm_free(fsa_pe_ref);
 		fsa_pe_ref = NULL;
 	}
 
 	send_request(NULL, local_cib, CRM_OP_PECALC,
 		     NULL, CRM_SYSTEM_PENGINE, &fsa_pe_ref);
 
 	return I_NULL;
 }
 
 /*	 A_TE_START, A_TE_STOP, A_TE_RESTART	*/
 enum crmd_fsa_input
 do_te_control(long long action,
 	      enum crmd_fsa_cause cause,
 	      enum crmd_fsa_state cur_state,
 	      enum crmd_fsa_input current_input,
 	      void *data)
 {
 	enum crmd_fsa_input result = I_NULL;
 	struct crm_subsystem_s *this_subsys = te_subsystem;
 	
 	long long stop_actions = A_TE_STOP;
 	long long start_actions = A_TE_START;
 	int lpc, pid_status;
 	
 /* 		if(action & stop_actions && cur_state != S_STOPPING */
 /* 		   && is_set(fsa_input_register, R_TE_PEND)) { */
 /* 			result = I_WAIT_FOR_EVENT; */
 /* 			return result; */
 /* 		} */
 	
 	if(action & stop_actions) {
 		if(stop_subsystem(this_subsys) == FALSE)
 			result = I_FAIL;
 		else if(this_subsys->pid > 0){
 			lpc = CLIENT_EXIT_WAIT;
 			pid_status = -1;
 			while(lpc-- > 0
 			      && this_subsys->pid > 0
 			      && CL_PID_EXISTS(this_subsys->pid)) {
 
 				sleep(1);
 				waitpid(this_subsys->pid, &pid_status, WNOHANG);
 			}
 			
 			if(CL_PID_EXISTS(this_subsys->pid)) {
 				crm_err("Process %s is still active with pid=%d",
 				       this_subsys->command, this_subsys->pid);
 				result = I_FAIL;
 			} 
 		}
 
 		cleanup_subsystem(this_subsys);
 	}
 
 	if(action & start_actions) {
 
 		if(cur_state != S_STOPPING) {
 			if(start_subsystem(this_subsys) == FALSE) {
 				result = I_FAIL;
 				cleanup_subsystem(this_subsys);
 			}
 		} else {
 			crm_info("Ignoring request to start %s while shutting down",
 				 this_subsys->command);
 		}
 	}
 
 	return result;
 }
 
 static xmlNodePtr te_last_input = NULL;
 static xmlNodePtr te_lastcc = NULL;
 
 /*	 A_TE_COPYTO	*/
 enum crmd_fsa_input
 do_te_copyto(long long action,
 	     enum crmd_fsa_cause cause,
 	     enum crmd_fsa_state cur_state,
 	     enum crmd_fsa_input current_input,
 	     void *data)
 {
 	xmlNodePtr message  = NULL;
 	xmlNodePtr opts     = NULL;
 	const char *true_op = NULL;
 	
 	
 
 	if(data != NULL) {
 		crm_xml_devel(data, "[TE imput]");
 		message  = copy_xml_node_recursive((xmlNodePtr)data);
 		opts  = find_xml_node(message, XML_TAG_OPTIONS);
 		true_op = xmlGetProp(opts, XML_ATTR_OP);
 		
 		set_xml_property_copy(opts, XML_ATTR_OP, CRM_OP_EVENTCC);
 		set_xml_property_copy(opts, XML_ATTR_TRUEOP, true_op);
 
 		set_xml_property_copy(
 			message, XML_ATTR_SYSTO, CRM_SYSTEM_TENGINE);
 	}
 
 	if(is_set(fsa_input_register, R_TE_CONNECTED) == FALSE){
 		crm_info("Waiting for the TE to connect");
 		if(data != NULL) {
 			free_xml(te_lastcc);
 			te_lastcc = message;
 		}
 		return I_WAIT_FOR_EVENT;
 
 	}
 
 	if(message == NULL) {
 		message = te_lastcc;
 		te_lastcc = NULL;
 		
 	} else {
 		free_xml(te_lastcc);
 	}
 	
 	relay_message(message, FALSE);
 
 	/* only free it if it was a local copy */
 	if(data == NULL) {
 		free_xml(message);
 	}
 	
 	return I_NULL;
 }
 
 
 /*	 A_TE_INVOKE, A_TE_CANCEL	*/
 enum crmd_fsa_input
 do_te_invoke(long long action,
 	     enum crmd_fsa_cause cause,
 	     enum crmd_fsa_state cur_state,
 	     enum crmd_fsa_input current_input,
 	     void *data)
 {
 	xmlNodePtr graph = NULL;
 	xmlNodePtr msg = (xmlNodePtr)data;
 	
 
 	if(is_set(fsa_input_register, R_TE_CONNECTED) == FALSE){
 		crm_info("Waiting for the TE to connect");
 		if(data != NULL) {
 			free_xml(te_last_input);
 			te_last_input = copy_xml_node_recursive(msg);
 		}
 		return I_WAIT_FOR_EVENT;
 
 	}
 
 	if(msg == NULL) {
 		msg = te_last_input;
 		te_last_input = NULL;
 		
 	} else {
 		free_xml(te_last_input);
 	}
 	
 	if(action & A_TE_INVOKE) {
 		graph = find_xml_node(msg, "transition_graph");
 		if(graph == NULL) {
 			return I_FAIL;
 		}
 	
 		send_request(NULL, graph, CRM_OP_TRANSITION,
 			     NULL, CRM_SYSTEM_TENGINE, NULL);
 	} else {
 		send_request(NULL, graph, CRM_OP_ABORT,
 			     NULL, CRM_SYSTEM_TENGINE, NULL);
 	}
 
 	/* only free it if it was a local copy */
 	if(data == NULL) {
 		free_xml(msg);
 	}
 	
 	return I_NULL;
 }
 
 gboolean
 crmd_client_connect(IPC_Channel *client_channel, gpointer user_data)
 {
 	
 
 	if (client_channel == NULL) {
 		crm_err("Channel was NULL");
 	} else if (client_channel->ch_status == IPC_DISCONNECT) {
 		crm_err("Channel was disconnected");
 	} else {
-		crmd_client_t *blank_client =
-			(crmd_client_t *)crm_malloc(sizeof(crmd_client_t));
+		crmd_client_t *blank_client = NULL;
+		crm_malloc(blank_client, sizeof(crmd_client_t));
 	
 		if (blank_client == NULL) {
-			crm_err("Could not allocate memory for a blank crmd_client_t");
 			return FALSE;
 		}
 		client_channel->ops->set_recv_qlen(client_channel, 100);
 		client_channel->ops->set_send_qlen(client_channel, 100);
 	
 		blank_client->client_channel = client_channel;
 		blank_client->sub_sys   = NULL;
 		blank_client->uuid      = NULL;
 		blank_client->table_key = NULL;
 	
 		blank_client->client_source =
 			G_main_add_IPC_Channel(G_PRIORITY_LOW,
 					       client_channel,
 					       FALSE, 
 					       crmd_ipc_input_callback,
 					       blank_client,
 					       default_ipc_input_destroy);
 	}
     
 	return TRUE;
 }
 
 static gboolean
 stop_subsystem(struct crm_subsystem_s*	centry)
 {
 	crm_info("Stopping sub-system \"%s\"", centry->name);
 	if (centry->pid <= 0) {
 		crm_err("OOPS! client %s not running yet",
 			centry->command);
 
 	} else {
 		crm_info("Sending quit message to %s.", centry->name);
 		send_request(NULL, NULL, CRM_OP_QUIT, NULL, centry->name, NULL);
 
 	}
 	
 	return TRUE;
 }
 
 
 static gboolean
 start_subsystem(struct crm_subsystem_s*	centry)
 {
 	pid_t			pid;
 	struct stat buf;
 	int s_res;
 
 	crm_info("Starting sub-system \"%s\"", centry->command);
 
 	if (centry->pid > 0) {
 		crm_err("OOPS! client %s already running as pid %d"
 		       ,	centry->command, (int) centry->pid);
 	}
 
 	/*
 	 * We need to ensure that the exec will succeed before
 	 * we bother forking.  We don't want to respawn something that
 	 * won't exec in the first place.
 	 */
 
 	if (access(centry->path, F_OK|X_OK) != 0) {
 		cl_perror("Cannot (access) exec %s", centry->path);
 		return FALSE;
 	}
 
 	s_res = stat(centry->command, &buf);
 	if(s_res != 0) {
 		cl_perror("Cannot (stat) exec %s", centry->command);
 		return FALSE;
 	}
 	
 
 	/* We need to fork so we can make child procs not real time */
 	switch(pid=fork()) {
 
 		case -1:
 			crm_err("start_a_child_client: Cannot fork.");
 			return FALSE;
 
 		default:	/* Parent */
 			centry->pid = pid;
 			return TRUE;
 
 		case 0:		/* Child */
 			break;
 	}
 
 	/* Child process:  start the managed child */
 	cl_make_normaltime();
 	setpgid(0,0);
 
 	/* Limit peak resource usage, maximize success chances */
 	if (centry->shortrcount > 0) {
 		alarm(0);
 		sleep(1);
 	}
 
 	crm_info("Executing \"%s\" (pid %d)",
 	       centry->command, (int) getpid());
 
 	if(CL_SIGINTERRUPT(SIGALRM, 0) < 0) {
 		cl_perror("Cannot set interrupt for child process %s",
 			  centry->command);
 	}else{
 		const char *	devnull = "/dev/null";
 		unsigned int	j;
 		struct rlimit		oflimits;
 		CL_SIGNAL(SIGCHLD, SIG_DFL);
 		alarm(0);
 		CL_IGNORE_SIG(SIGALRM);
 
 		/* A precautionary measure */
 		getrlimit(RLIMIT_NOFILE, &oflimits);
 		for (j=0; j < oflimits.rlim_cur; ++j) {
 			close(j);
 		}
 		(void)devnull;
 		
 		(void)open(devnull, O_RDONLY);	/* Stdin:  fd 0 */
 		(void)open(devnull, O_WRONLY);	/* Stdout: fd 1 */
 		(void)open(devnull, O_WRONLY);	/* Stderr: fd 2 */
 
 		(void)execl("/bin/sh", "sh", "-c", centry->command, (const char *)NULL);
 
 		/* Should not happen */
 		cl_perror("Cannot exec %s", centry->command);
 	}
 	/* Suppress respawning */
 	exit(100);
 
 	/* never reached */
 	return TRUE;
 }
 
 
 
diff --git a/crm/crmd/utils.c b/crm/crmd/utils.c
index 9d4085221a..fcc7eee7e4 100644
--- a/crm/crmd/utils.c
+++ b/crm/crmd/utils.c
@@ -1,711 +1,716 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crmd_fsa.h>
 
 #include <clplumbing/Gmain_timeout.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <signal.h>
 
 #include <heartbeat.h>
 
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 
 gboolean
 timer_popped(gpointer data)
 {
 	fsa_timer_t *timer = (fsa_timer_t *)data;
 
 	crm_info("#!!#!!# Timer %s just popped!",
 	       fsa_input2string(timer->fsa_input));
 	
 	stopTimer(timer); /* dont make it go off again */
 
 	s_crmd_fsa(C_TIMER_POPPED, timer->fsa_input, NULL);
 	
 	return TRUE;
 }
 
 gboolean
 startTimer(fsa_timer_t *timer)
 {
 	if(((int)timer->source_id) < 0
 		&& timer->period_ms > 0) {
 		timer->source_id =
 			Gmain_timeout_add(timer->period_ms,
 					  timer->callback,
 					  (void*)timer);
 /*
 		crm_verbose("#!!#!!# Started %s timer (%d)",
 			   fsa_input2string(timer->fsa_input),
 			   timer->source_id);
 */
 	} else if(timer->period_ms < 0) {
 		crm_err("Tried to start timer %s with -ve period",
 			fsa_input2string(timer->fsa_input));
 		
 	} else {
 		crm_info("#!!#!!# Timer %s already running (%d)",
 		       fsa_input2string(timer->fsa_input),
 		       timer->source_id);
 		return FALSE;		
 	}
 	return TRUE;
 }
 
 
 gboolean
 stopTimer(fsa_timer_t *timer)
 {
 	if(((int)timer->source_id) > 0) {
 /*
 		crm_verbose("#!!#!!# Stopping %s timer (%d)",
 			   fsa_input2string(timer->fsa_input),
 			   timer->source_id);
 */
 		g_source_remove(timer->source_id);
 		timer->source_id = -2;
 
 	} else {
 		crm_info("#!!#!!# Timer %s already stopped (%d)",
 		       fsa_input2string(timer->fsa_input),
 		       timer->source_id);
 		return FALSE;
 	}
 	return TRUE;
 }
 
 
 long long
 toggle_bit(long long action_list, long long action)
 {
 	crm_trace("Toggling bit %.16llx", action);
 	action_list ^= action;
 	crm_trace("Result %.16llx", action_list & action);
 	return action_list;
 }
 
 long long
 clear_bit(long long action_list, long long action)
 {
 	crm_trace("Clearing bit\t%.16llx", action);
 
 	/* ensure its set */
 	action_list |= action;
 
 	/* then toggle */
 	action_list = action_list ^ action;
 
 	return action_list;
 }
 
 long long
 set_bit(long long action_list, long long action)
 {
 	crm_trace("Adding bit\t%.16llx", action);
 	action_list |= action;
 	return action_list;
 }
 
 void
 toggle_bit_inplace(long long *action_list, long long action)
 {
 	*action_list = toggle_bit(*action_list, action);
 }
 
 void
 clear_bit_inplace(long long *action_list, long long action)
 {
 	*action_list = clear_bit(*action_list, action);
 }
 
 void
 set_bit_inplace(long long *action_list, long long action)
 {
 	*action_list = set_bit(*action_list, action);
 }
 
 
 
 gboolean
 is_set(long long action_list, long long action)
 {
 /*	crm_verbose("Checking bit\t%.16llx", action); */
 	return ((action_list & action) == action);
 }
 
 
 
 const char *
 fsa_input2string(enum crmd_fsa_input input)
 {
 	const char *inputAsText = NULL;
 	
 	switch(input){
 		case I_NULL:
 			inputAsText = "I_NULL";
 			break;
 		case I_CCM_EVENT:
 			inputAsText = "I_CCM_EVENT";
 			break;
 		case I_CIB_OP:
 			inputAsText = "I_CIB_OP";
 			break;
 		case I_CIB_UPDATE:
 			inputAsText = "I_CIB_UPDATE";
 			break;
 		case I_DC_TIMEOUT:
 			inputAsText = "I_DC_TIMEOUT";
 			break;
 		case I_ELECTION:
 			inputAsText = "I_ELECTION";
 			break;
 		case I_PE_CALC:
 			inputAsText = "I_PE_CALC";
 			break;
 		case I_RELEASE_DC:
 			inputAsText = "I_RELEASE_DC";
 			break;
 		case I_ELECTION_DC:
 			inputAsText = "I_ELECTION_DC";
 			break;
 		case I_ERROR:
 			inputAsText = "I_ERROR";
 			break;
 		case I_FAIL:
 			inputAsText = "I_FAIL";
 			break;
 		case I_INTEGRATION_TIMEOUT:
 			inputAsText = "I_INTEGRATION_TIMEOUT";
 			break;
 		case I_NODE_JOIN:
 			inputAsText = "I_NODE_JOIN";
 			break;
 		case I_NODE_LEFT:
 			inputAsText = "I_NODE_LEFT";
 			break;
 		case I_NOT_DC:
 			inputAsText = "I_NOT_DC";
 			break;
 		case I_RECOVERED:
 			inputAsText = "I_RECOVERED";
 			break;
 		case I_RELEASE_FAIL:
 			inputAsText = "I_RELEASE_FAIL";
 			break;
 		case I_RELEASE_SUCCESS:
 			inputAsText = "I_RELEASE_SUCCESS";
 			break;
 		case I_RESTART:
 			inputAsText = "I_RESTART";
 			break;
 		case I_REQUEST:
 			inputAsText = "I_REQUEST";
 			break;
 		case I_ROUTER:
 			inputAsText = "I_ROUTER";
 			break;
 		case I_SHUTDOWN:
 			inputAsText = "I_SHUTDOWN";
 			break;
 		case I_STARTUP:
 			inputAsText = "I_STARTUP";
 			break;
 		case I_SUCCESS:
 			inputAsText = "I_SUCCESS";
 			break;
 		case I_TERMINATE:
 			inputAsText = "I_TERMINATE";
 			break;
 		case I_WELCOME:
 			inputAsText = "I_WELCOME";
 			break;
 		case I_WELCOME_ACK:
 			inputAsText = "I_WELCOME_ACK";
 			break;
 		case I_DC_HEARTBEAT:
 			inputAsText = "I_DC_HEARTBEAT";
 			break;
 		case I_WAIT_FOR_EVENT:
 			inputAsText = "I_WAIT_FOR_EVENT";
 			break;
 		case I_LRM_EVENT:
 			inputAsText = "I_LRM_EVENT";
 			break;
 		case I_ILLEGAL:
 			inputAsText = "I_ILLEGAL";
 			break;
 	}
 
 	if(inputAsText == NULL) {
 		crm_err("Input %d is unknown", input);
 		inputAsText = "<UNKNOWN_INPUT>";
 	}
 	
 	return inputAsText;
 }
 
 const char *
 fsa_state2string(enum crmd_fsa_state state)
 {
 	const char *stateAsText = NULL;
 	
 	switch(state){
 		case S_IDLE:
 			stateAsText = "S_IDLE";
 			break;
 		case S_ELECTION:
 			stateAsText = "S_ELECTION";
 			break;
 		case S_INTEGRATION:
 			stateAsText = "S_INTEGRATION";
 			break;
 		case S_NOT_DC:
 			stateAsText = "S_NOT_DC";
 			break;
 		case S_POLICY_ENGINE:
 			stateAsText = "S_POLICY_ENGINE";
 			break;
 		case S_RECOVERY:
 			stateAsText = "S_RECOVERY";
 			break;
 		case S_RECOVERY_DC:
 			stateAsText = "S_RECOVERY_DC";
 			break;
 		case S_RELEASE_DC:
 			stateAsText = "S_RELEASE_DC";
 			break;
 		case S_PENDING:
 			stateAsText = "S_PENDING";
 			break;
 		case S_STOPPING:
 			stateAsText = "S_STOPPING";
 			break;
 		case S_TERMINATE:
 			stateAsText = "S_TERMINATE";
 			break;
 		case S_TRANSITION_ENGINE:
 			stateAsText = "S_TRANSITION_ENGINE";
 			break;
 		case S_ILLEGAL:
 			stateAsText = "S_ILLEGAL";
 			break;
 	}
 
 	if(stateAsText == NULL) {
 		crm_err("State %d is unknown", state);
 		stateAsText = "<UNKNOWN_STATE>";
 	}
 	
 	return stateAsText;
 }
 
 const char *
 fsa_cause2string(enum crmd_fsa_cause cause)
 {
 	const char *causeAsText = NULL;
 	
 	switch(cause){
 		case C_UNKNOWN:
 			causeAsText = "C_UNKNOWN";
 			break;
 		case C_STARTUP:
 			causeAsText = "C_STARTUP";
 			break;
 		case C_IPC_MESSAGE:
 			causeAsText = "C_IPC_MESSAGE";
 			break;
 		case C_HA_MESSAGE:
 			causeAsText = "C_HA_MESSAGE";
 			break;
 		case C_CCM_CALLBACK:
 			causeAsText = "C_CCM_CALLBACK";
 			break;
 		case C_TIMER_POPPED:
 			causeAsText = "C_TIMER_POPPED";
 			break;
 		case C_SHUTDOWN:
 			causeAsText = "C_SHUTDOWN";
 			break;
 		case C_HEARTBEAT_FAILED:
 			causeAsText = "C_HEARTBEAT_FAILED";
 			break;
 		case C_SUBSYSTEM_CONNECT:
 			causeAsText = "C_SUBSYSTEM_CONNECT";
 			break;
 		case C_LRM_OP_CALLBACK:
 			causeAsText = "C_LRM_OP_CALLBACK";
 			break;
 		case C_LRM_MONITOR_CALLBACK:
 			causeAsText = "C_LRM_MONITOR_CALLBACK";
 			break;
 		case C_CRMD_STATUS_CALLBACK:
 			causeAsText = "C_CRMD_STATUS_CALLBACK";
 			break;
 		case C_HA_DISCONNECT:
 			causeAsText = "C_HA_DISCONNECT";
 			break;
 		case C_ILLEGAL:
 			causeAsText = "C_ILLEGAL";
 			break;
 	}
 
 	if(causeAsText == NULL) {
 		crm_err("Cause %d is unknown", cause);
 		causeAsText = "<UNKNOWN_CAUSE>";
 	}
 	
 	return causeAsText;
 }
 
 const char *
 fsa_action2string(long long action)
 {
 	const char *actionAsText = NULL;
 	
 	switch(action){
 
 		case A_NOTHING:
 			actionAsText = "A_NOTHING";
 			break;
 		case A_READCONFIG:
 			actionAsText = "A_READCONFIG";
 			break;
 		case O_SHUTDOWN:
 			actionAsText = "O_SHUTDOWN";
 			break;
 		case O_RELEASE:
 			actionAsText = "O_RELEASE";
 			break;
 		case A_STARTUP:
 			actionAsText = "A_STARTUP";
 			break;
 		case A_STARTED:
 			actionAsText = "A_STARTED";
 			break;
 		case A_HA_CONNECT:
 			actionAsText = "A_HA_CONNECT";
 			break;
 		case A_HA_DISCONNECT:
 			actionAsText = "A_HA_DISCONNECT";
 			break;
 		case A_LRM_CONNECT:
 			actionAsText = "A_LRM_CONNECT";
 			break;
 		case A_LRM_EVENT:
 			actionAsText = "A_LRM_EVENT";
 			break;
 		case A_LRM_INVOKE:
 			actionAsText = "A_LRM_INVOKE";
 			break;
 		case A_LRM_DISCONNECT:
 			actionAsText = "A_LRM_DISCONNECT";
 			break;
 		case O_DC_TIMER_RESTART:
 			actionAsText = "O_DC_TIMER_RESTART";
 			break;
 		case A_DC_TIMER_STOP:
 			actionAsText = "A_DC_TIMER_STOP";
 			break;
 		case A_DC_TIMER_START:
 			actionAsText = "A_DC_TIMER_START";
 			break;
 		case A_ELECTION_COUNT:
 			actionAsText = "A_ELECTION_COUNT";
 			break;
 		case A_ELECTION_TIMEOUT:
 			actionAsText = "A_ELECTION_TIMEOUT";
 			break;
 		case A_ELECT_TIMER_START:
 			actionAsText = "A_ELECT_TIMER_START";
 			break;
 		case A_ELECT_TIMER_STOP:
 			actionAsText = "A_ELECT_TIMER_STOP";
 			break;
 		case A_ELECTION_VOTE:
 			actionAsText = "A_ELECTION_VOTE";
 			break;
 		case A_ANNOUNCE:
 			actionAsText = "A_ANNOUNCE";
 			break;
 		case A_JOIN_ACK:
 			actionAsText = "A_JOIN_ACK";
 			break;
 		case A_JOIN_WELCOME:
 			actionAsText = "A_JOIN_WELCOME";
 			break;
 		case A_JOIN_WELCOME_ALL:
 			actionAsText = "A_JOIN_WELCOME_ALL";
 			break;
 		case A_JOIN_PROCESS_ACK:
 			actionAsText = "A_JOIN_PROCESS_ACK";
 			break;
 		case A_MSG_PROCESS:
 			actionAsText = "A_MSG_PROCESS";
 			break;
 		case A_MSG_ROUTE:
 			actionAsText = "A_MSG_ROUTE";
 			break;
 		case A_MSG_STORE:
 			actionAsText = "A_MSG_STORE";
 			break;
 		case A_RECOVER:
 			actionAsText = "A_RECOVER";
 			break;
 		case A_DC_RELEASE:
 			actionAsText = "A_DC_RELEASE";
 			break;
 		case A_DC_RELEASED:
 			actionAsText = "A_DC_RELEASED";
 			break;
 		case A_DC_TAKEOVER:
 			actionAsText = "A_DC_TAKEOVER";
 			break;
 		case A_SHUTDOWN:
 			actionAsText = "A_SHUTDOWN";
 			break;
 		case A_SHUTDOWN_REQ:
 			actionAsText = "A_SHUTDOWN_REQ";
 			break;
 		case A_STOP:
 			actionAsText = "A_STOP  ";
 			break;
 		case A_EXIT_0:
 			actionAsText = "A_EXIT_0";
 			break;
 		case A_EXIT_1:
 			actionAsText = "A_EXIT_1";
 			break;
 		case A_CCM_CONNECT:
 			actionAsText = "A_CCM_CONNECT";
 			break;
 		case A_CCM_DISCONNECT:
 			actionAsText = "A_CCM_DISCONNECT";
 			break;
 		case A_CCM_EVENT:
 			actionAsText = "A_CCM_EVENT";
 			break;
 		case A_CCM_UPDATE_CACHE:
 			actionAsText = "A_CCM_UPDATE_CACHE";
 			break;
 		case A_CIB_BUMPGEN:
 			actionAsText = "A_CIB_BUMPGEN";
 			break;
 		case A_CIB_INVOKE:
 			actionAsText = "A_CIB_INVOKE";
 			break;
 		case O_CIB_RESTART:
 			actionAsText = "O_CIB_RESTART";
 			break;
 		case A_CIB_START:
 			actionAsText = "A_CIB_START";
 			break;
 		case A_CIB_STOP:
 			actionAsText = "A_CIB_STOP";
 			break;
 		case A_TE_INVOKE:
 			actionAsText = "A_TE_INVOKE";
 			break;
 		case O_TE_RESTART:
 			actionAsText = "O_TE_RESTART";
 			break;
 		case A_TE_START:
 			actionAsText = "A_TE_START";
 			break;
 		case A_TE_STOP:
 			actionAsText = "A_TE_STOP";
 			break;
 		case A_TE_CANCEL:
 			actionAsText = "A_TE_CANCEL";
 			break;
 		case A_TE_COPYTO:
 			actionAsText = "A_TE_COPYTO";
 			break;
 		case A_PE_INVOKE:
 			actionAsText = "A_PE_INVOKE";
 			break;
 		case O_PE_RESTART:
 			actionAsText = "O_PE_RESTART";
 			break;
 		case A_PE_START:
 			actionAsText = "A_PE_START";
 			break;
 		case A_PE_STOP:
 			actionAsText = "A_PE_STOP";
 			break;
 		case A_NODE_BLOCK:
 			actionAsText = "A_NODE_BLOCK";
 			break;
 		case A_UPDATE_NODESTATUS:
 			actionAsText = "A_UPDATE_NODESTATUS";
 			break;
 		case A_LOG:
 			actionAsText = "A_LOG   ";
 			break;
 		case A_ERROR:
 			actionAsText = "A_ERROR ";
 			break;
 		case A_WARN:
 			actionAsText = "A_WARN  ";
 			break;
 	}
 
 	if(actionAsText == NULL) {
 		crm_err("Action %.16llx is unknown", action);
 		actionAsText = "<UNKNOWN_ACTION>";
 	}
 	
 	return actionAsText;
 }
 
 
 void
 cleanup_subsystem(struct crm_subsystem_s *the_subsystem)
 {
 	int pid_status = -1;
 	the_subsystem->ipc = NULL;
 	clear_bit_inplace(&fsa_input_register,
 			  the_subsystem->flag);
 
 	/* Forcing client to die */
 	kill(the_subsystem->pid, -9);
 	
 	/* cleanup the ps entry */
 	waitpid(the_subsystem->pid, &pid_status, WNOHANG);
 	the_subsystem->pid = -1;
 }
 
 enum crmd_fsa_input
 invoke_local_cib(xmlNodePtr msg_options,
 		 xmlNodePtr msg_data,
 		 const char *operation)
 {
 	enum crmd_fsa_input result = I_NULL;
 	xmlNodePtr request = NULL;
 	
 
 	msg_options = set_xml_attr(msg_options, XML_TAG_OPTIONS,
 				   XML_ATTR_OP, operation, TRUE);
 
 	request = create_request(msg_options,
 				 msg_data,
 				 NULL,
 				 CRM_SYSTEM_CIB,
 				 AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD,
 				 NULL,
 				 NULL);
 
 	result = do_cib_invoke(A_CIB_INVOKE_LOCAL,
 			       C_UNKNOWN,
 			       fsa_state,
 			       I_CIB_OP,
 			       request);
 
 	free_xml(request);
 	
 	return result;
 }
 
 void
 create_node_entry(const char *uuid, const char *uname, const char *type)
 {
 	
 	/* make sure a node entry exists for the new node
 	 *
 	 * this will add anyone except the first ever node in the cluster
 	 *   since it will also be the DC which doesnt go through the
 	 *   join process (with itself).  We can include a special case
 	 *   later if desired.
 	 */
 	xmlNodePtr tmp2 = NULL;
 	xmlNodePtr tmp1 = create_xml_node(NULL, XML_CIB_TAG_NODE);
 
 	crm_debug("Creating node entry for %s", uname);
 	set_uuid(tmp1, XML_ATTR_UUID, uname);
 	
 	set_xml_property_copy(tmp1, XML_ATTR_UNAME, uname);
 	set_xml_property_copy(tmp1, XML_ATTR_TYPE, type);
 	
 	tmp2 = create_cib_fragment(tmp1, NULL);
 
 	/* do not forward this to the TE */
 	invoke_local_cib(NULL, tmp2, CRM_OP_UPDATE);
 	
 	free_xml(tmp2);
 	free_xml(tmp1);
 	
 }
 
 xmlNodePtr
 create_node_state(const char *uuid,
 		  const char *uname,
 		  const char *ccm_state,
 		  const char *crmd_state,
 		  const char *join_state)
 {
 	xmlNodePtr node_state = create_xml_node(NULL, XML_CIB_TAG_STATE);
 
 	crm_debug("Creating node state entry for %s", uname);
 	set_uuid(node_state, XML_ATTR_UUID, uname);
 	set_xml_property_copy(node_state, XML_ATTR_UNAME, uname);
 
 	if(ccm_state != NULL) {
 		set_xml_property_copy(node_state, XML_CIB_ATTR_INCCM,     ccm_state);
 	}
 
 	if(crmd_state != NULL) {
 		set_xml_property_copy(node_state, XML_CIB_ATTR_CRMDSTATE,     crmd_state);
 	}
 
 	if(join_state != NULL) {
 		set_xml_property_copy(node_state, XML_CIB_ATTR_JOINSTATE,     join_state);
 	}
 
 	crm_xml_devel(node_state, "created");
 
 	return node_state;
 }
 
 
 void
 set_uuid(xmlNodePtr node, const char *attr, const char *uname) 
 {
 	uuid_t uuid_raw;
-	char *uuid_calc = (char*)crm_malloc(sizeof(char)*50);
+	char *uuid_calc = NULL;
 	
-	if(fsa_cluster_conn->llc_ops->get_uuid_by_name(
-		   fsa_cluster_conn, uname, uuid_raw) == HA_FAIL) {
-		crm_err("Could not calculate UUID for %s", uname);
-		crm_free(uuid_calc);
-		uuid_calc = crm_strdup(uname);
-
-	} else {
-		uuid_unparse(uuid_raw, uuid_calc);
+	crm_malloc(uuid_calc, sizeof(char)*50);
+
+	if(uuid_calc != NULL) {
+		if(fsa_cluster_conn->llc_ops->get_uuid_by_name(
+			   fsa_cluster_conn, uname, uuid_raw) == HA_FAIL) {
+			crm_err("Could not calculate UUID for %s", uname);
+			crm_free(uuid_calc);
+			uuid_calc = crm_strdup(uname);
+			
+		} else {
+			uuid_unparse(uuid_raw, uuid_calc);
+		}
+		
+		set_xml_property_copy(node, attr, uuid_calc);
 	}
 	
-	set_xml_property_copy(node, attr, uuid_calc);
 	crm_free(uuid_calc);
 }
diff --git a/crm/pengine/color.c b/crm/pengine/color.c
index 632c80e6f9..158dcf2c5e 100644
--- a/crm/pengine/color.c
+++ b/crm/pengine/color.c
@@ -1,621 +1,621 @@
-/* $Id: color.c,v 1.16 2004/09/14 05:54:43 andrew Exp $ */
+/* $Id: color.c,v 1.17 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <glib.h>
 #include <libxml/tree.h>
 
 #include <pengine.h>
 #include <pe_utils.h>
 
 color_t *no_color = NULL;
 
 color_t *add_color(resource_t *rh_resource, color_t *color);
 
 gboolean has_agent(node_t *a_node, lrm_agent_t *agent);
 
 gboolean update_node_weight(rsc_to_node_t *cons,const char *id,GListPtr nodes);
 
 gboolean rsc_preproc(
 	resource_t *lh_resource, GListPtr *colors, GListPtr resources);
 
 gboolean rsc_postproc(
 	resource_t *lh_resource, GListPtr *colors, GListPtr resources);
 
 gboolean strict_postproc(rsc_to_rsc_t *constraint,
 			 GListPtr *colors,
 			 GListPtr resources);
 
 gboolean strict_preproc(rsc_to_rsc_t *constraint,
 			GListPtr *colors,
 			GListPtr resources);
 
 gboolean is_active(rsc_to_node_t *cons);
 
 gboolean choose_color(resource_t *lh_resource);
 
 gboolean assign_color(resource_t *rsc, color_t *color);
 
 gboolean 
 apply_node_constraints(GListPtr constraints, GListPtr nodes)
 {
 	int lpc = 0;
 	int llpc = 0;
 	resource_t *rsc_lh = NULL;
 	GListPtr or_list = NULL;
 
 	crm_verbose("Applying constraints...");
 	slist_iter(
 		cons, rsc_to_node_t, constraints, lpc,
 		crm_debug_action(print_rsc_to_node("Applying", cons, FALSE));
 		/* take "lifetime" into account */
 		if(cons == NULL) {
 			crm_err("Constraint (%d) is NULL", lpc);
 			continue;
 			
 		} else if(is_active(cons) == FALSE) {
 			crm_info("Constraint (%d) is not active", lpc);
 			/* warning */
 			continue;
 		}
     
 		rsc_lh = cons->rsc_lh;
 		if(rsc_lh == NULL) {
 			crm_err("LHS of rsc_to_node (%s) is NULL", cons->id);
 			continue;
 		}
 
 		cons->rsc_lh->node_cons =
 			g_list_append(cons->rsc_lh->node_cons, cons);
 
 		if(cons->node_list_rh == NULL) {
-			crm_err("RHS of rsc_to_node (%s) is NULL", cons->id);
+			crm_err("RHS of constraint %s is NULL", cons->id);
 			continue;
 		}
 		crm_debug_action(print_resource("before update", rsc_lh,TRUE));
 
 		llpc = 0;
 		or_list = node_list_or(
 			rsc_lh->allowed_nodes, cons->node_list_rh, FALSE);
 		
 		pe_free_shallow(rsc_lh->allowed_nodes);
 		rsc_lh->allowed_nodes = or_list;
 		slist_iter(node_rh, node_t, cons->node_list_rh, llpc,
 			   update_node_weight(cons, node_rh->details->uname,
 					      rsc_lh->allowed_nodes));
 
 		crm_debug_action(print_resource("after update", rsc_lh, TRUE));
 		);
 	
 	return TRUE;
 	
 }
 
 gboolean
 apply_agent_constraints(GListPtr resources)
 {
 	int lpc;
 	int lpc2;
 	slist_iter(
 		rsc, resource_t, resources, lpc,
 
 		crm_trace("Applying RA restrictions to %s", rsc->id);
 		slist_iter(
 			node, node_t, rsc->allowed_nodes, lpc2,
 			
 			crm_trace("Checking if %s supports %s/%s (%s)",
 				  node->details->uname,
 				  rsc->agent->class, rsc->agent->type,
 				  rsc->agent->version);
 
 			if(has_agent(node, rsc->agent) == FALSE) {
 				/* remove node from contention */
 				crm_trace("Marking node %s unavailable for %s",
 					  node->details->uname, rsc->id);
 				node->weight = -1.0;
 				node->fixed = TRUE;
 			}
 			if(node->fixed && node->weight < 0) {
 				/* the structure of the list will have changed
 				 * lpc2-- might be sufficient
 				 */
 				crm_debug("Removing node %s from %s",
 					  node->details->uname, rsc->id);
 
 				lpc2 = -1;
 				rsc->allowed_nodes = g_list_remove(
 					rsc->allowed_nodes, node);
 				crm_free(node);
 			}
 			
 			)
 		);
 	crm_trace("Finished applying RA restrictions");
 	return TRUE;
 }
 
 gboolean
 has_agent(node_t *a_node, lrm_agent_t *an_agent)
 {
 	int lpc;
 	if(a_node == NULL || an_agent == NULL || an_agent->type == NULL) {
 		crm_warn("Invalid inputs");
 		return FALSE;
 	}
 	
 	crm_devel("Checking %d agents on %s",
 		  g_list_length(a_node->details->agents),
 		  a_node->details->uname);
 
 	slist_iter(
 		agent, lrm_agent_t, a_node->details->agents, lpc,
 
 		crm_trace("Checking against  %s/%s (%s)",
 			  agent->class, agent->type, agent->version);
 
 		if(safe_str_eq(an_agent->type, agent->type)){
 			if(an_agent->class == NULL) {
 				return TRUE;
 				
 			} else if(safe_str_eq(an_agent->class, agent->class)) {
 				if(compare_version(
 					   an_agent->version, agent->version)
 				   <= 0) {
 					return TRUE;
 				}
 			}
 		}
 		);
 	
 	crm_verbose("%s doesnt support version %s of %s/%s",
 		    a_node->details->uname, an_agent->version,
 		    an_agent->class, an_agent->type);
 	
 	return FALSE;
 }
 
 gboolean
 is_active(rsc_to_node_t *cons)
 {
 	/* todo: check constraint lifetime */
 	return TRUE;
 }
 
 
 gboolean
 strict_preproc(rsc_to_rsc_t *constraint, GListPtr *colors, GListPtr resources)
 {
 	resource_t *lh_resource = constraint->rsc_lh;
 	resource_t *rh_resource = constraint->rsc_rh;
 
 	color_t *local_color = NULL;
 	
 	float max_pri = lh_resource->effective_priority;
 
 	switch(constraint->strength) {
 		case pecs_ignore:
 			break;
 		case pecs_startstop:
 			break;
 		case pecs_must:
 			if(max_pri < rh_resource->effective_priority) {
 				max_pri = rh_resource->effective_priority;
 			}
 			lh_resource->effective_priority = max_pri;
 			rh_resource->effective_priority = max_pri;
 			break;
 			
 		case pecs_must_not:
 			if(constraint->variant != same_node) {
 				break;
 			} else if(constraint->rsc_rh->provisional) {
 				break;
 			} else if(local_color != NULL) {
 				lh_resource->candidate_colors = g_list_remove(
 					lh_resource->candidate_colors, local_color);
 				
 				crm_debug_action(
 					print_color(
 						"Removed",local_color,FALSE));
 				
 				crm_free(local_color);
 			}
 			break;
 	}
 	return TRUE;
 }
 
 gboolean
 strict_postproc(rsc_to_rsc_t *constraint, GListPtr *colors, GListPtr resources)
 {
 	print_rsc_to_rsc("Post processing", constraint, FALSE);
 
 	switch(constraint->strength) {
 		case pecs_ignore:
 		case pecs_startstop:
 			break;
 
 		case pecs_must:
 			if(constraint->rsc_lh->runnable == FALSE) {
 				crm_warn("Resource %s must run on the same"
 					 " node as %s (cons %s), but %s is not"
 					 " runnable.",
 					 constraint->rsc_rh->id,
 					 constraint->rsc_lh->id,
 					 constraint->id,
 					 constraint->rsc_lh->id);
 				constraint->rsc_rh->runnable = FALSE;
 
 			} else if(constraint->variant != same_node) {
 				break;
 
 			} else if(constraint->rsc_rh->provisional == TRUE) {
 
 
 				resource_t *rh_resource = constraint->rsc_rh;
 				assign_color(rh_resource, constraint->rsc_lh->color);
 				color_resource(rh_resource, colors, resources);
 				
 			} else if(constraint->rsc_rh->provisional == FALSE
 				  && constraint->rsc_rh->color->id !=
 				  constraint->rsc_lh->color->id) {
 				crm_err("Resource %s must run on the same"
 					" node as %s (cons %s), but %s is already"
 					" assigned to another color.",
 					constraint->rsc_rh->id,
 					constraint->rsc_lh->id,
 					constraint->id,
 					constraint->rsc_lh->id);
 				constraint->rsc_lh->runnable = FALSE;
 				return FALSE;
 			}
 			break;
 			
 		case pecs_must_not:
 			if(constraint->rsc_rh->provisional == FALSE
 			   && constraint->rsc_rh->color->id ==
 			      constraint->rsc_lh->color->id) {
 				crm_err("Resource %s must run on the same"
 					" node as %s (cons %s), but %s is already"
 					" assigned to another color.",
 					constraint->rsc_rh->id,
 					 constraint->rsc_lh->id,
 					constraint->id,
 					constraint->rsc_lh->id);
 				constraint->rsc_lh->runnable = FALSE;
 				return FALSE;
 			}
 			break;
 	}
 	return TRUE;
 }
 
 color_t *
 add_color(resource_t *resource, color_t *color)
 {
 					
 	color_t *local_color = NULL;
 
 	if(color == NULL) {
 		crm_err("Cannot add NULL color");
 		return NULL;
 	}
 	
 	local_color = find_color(resource->candidate_colors, color);
 
 	if(local_color == NULL) {
 		crm_debug("Adding color %d", color->id);
 		
 		local_color = copy_color(color);
 		resource->candidate_colors =
 			g_list_append(resource->candidate_colors, local_color);
 
 	} else {
 		crm_debug("Color %d already present", color->id);
 	}
 
 	return local_color;
 }
 
 gboolean
 choose_color(resource_t *lh_resource)
 {
 	int lpc = 0;
 	GListPtr sorted_colors = NULL;
 
 	if(lh_resource->runnable == FALSE) {
 		assign_color(lh_resource, no_color);
 	}
 
 	if(lh_resource->provisional == FALSE) {
 		return !lh_resource->provisional;
 	}
 	
 	sorted_colors = g_list_sort(
 		lh_resource->candidate_colors, sort_color_weight);
 	
 	lh_resource->candidate_colors = sorted_colors;
 	
 	crm_verbose("Choose a color from %d possibilities",
 		    g_list_length(sorted_colors));
 	
 	slist_iter(
 		this_color, color_t, lh_resource->candidate_colors, lpc,
 		GListPtr intersection = NULL;
 		GListPtr minus = NULL;
 		int len = 0;
 
 		if(this_color == NULL) {
 			crm_err("color was NULL");
 			continue;
 			
 		} else if(lh_resource->effective_priority
 		   < this_color->details->highest_priority) {
 
 			minus = node_list_minus(
 				this_color->details->candidate_nodes, 
 				lh_resource->allowed_nodes, TRUE);
 
 			len = g_list_length(minus);
 			pe_free_shallow(minus);
 			
 			if(len > 0) {
 				assign_color(lh_resource, this_color);
 				break;
 			}
 			
 		} else {
 			intersection = node_list_and(
 				this_color->details->candidate_nodes, 
 				lh_resource->allowed_nodes, TRUE);
 
 			len = g_list_length(intersection);
 			pe_free_shallow(intersection);
 			
 			if(len != 0) {
 				assign_color(lh_resource, this_color);
 				break;
 			}
 		}
 		);
 
 	return !lh_resource->provisional;
 }
 
 gboolean
 rsc_preproc(resource_t *lh_resource, GListPtr *colors, GListPtr resources)
 {
 	int lpc = 0;
 	slist_iter(
 		constraint, rsc_to_rsc_t, lh_resource->rsc_cons, lpc,
 
 		crm_debug_action(
 			print_rsc_to_rsc(
 				"Processing constraint",constraint,FALSE));
 		
 		if(constraint->rsc_rh == NULL) {
 			crm_err("rsc_rh was NULL for %s", constraint->id);
 			continue;
 		}		
 
 		strict_preproc(constraint, colors, resources);
 		);
 	
 	return TRUE;
 }
 
 gboolean
 rsc_postproc(resource_t *lh_resource, GListPtr *colors, GListPtr resources)
 {
 	int lpc = 0;
 	slist_iter(
 		constraint, rsc_to_rsc_t, lh_resource->rsc_cons, lpc,
 		strict_postproc(constraint, colors, resources);
 		);
 	
 	return TRUE;
 }
 
 void
 color_resource(resource_t *lh_resource, GListPtr *colors, GListPtr resources)
 {
 	color_t *new_color = NULL;
 
 	crm_debug_action(print_resource("Coloring", lh_resource, FALSE));
 	
 	if(lh_resource->provisional == FALSE) {
 		/* already processed this resource */
 		return;
 	}
 	
 	lh_resource->rsc_cons = g_list_sort(
 		lh_resource->rsc_cons, sort_cons_strength);
 
 	crm_debug_action(
 		print_resource("Pre-processing", lh_resource, FALSE));
 
 	/*------ Pre-processing */
 	rsc_preproc(lh_resource, colors, resources);
 	
 	/* avoid looping through lists when we know this resource
 	 * cant be started
 	 */
 	if( choose_color(lh_resource) ) {
 		crm_verbose("Colored resource %s with color %d",
 			    lh_resource->id, lh_resource->color->id);
 		
 	} else if(lh_resource->allowed_nodes != NULL) {
 		/* filter out nodes with a negative weight */
 		filter_nodes(lh_resource);
 		new_color = create_color(colors, lh_resource, NULL);
 		assign_color(lh_resource, new_color);
 	}
 	
 	if(lh_resource->color == NULL) {
 		crm_err("Could not color resource %s", lh_resource->id);
 		print_resource("ERROR: No color", lh_resource, FALSE);
 		assign_color(lh_resource, no_color);
 	}
 
 	lh_resource->provisional = FALSE;
 
 	crm_debug_action(
 		print_resource("Post-processing", lh_resource, FALSE));
 
 	/*------ Post-processing */
 	rsc_postproc(lh_resource, colors, resources);
 	
 	crm_debug_action(print_resource("Colored", lh_resource, FALSE));
 }
 
 
 gboolean
 update_node_weight(rsc_to_node_t *cons, const char *id, GListPtr nodes)
 {
 	node_t *node_rh = pe_find_node(cons->rsc_lh->allowed_nodes, id);
 
 	if(node_rh == NULL) {
 		crm_err("Node not found - cant update");
 		return FALSE;
 	}
 
 	if(node_rh->fixed) {
 		/* warning */
 		crm_warn("Constraint %s is irrelevant as the"
 			 " weight of node %s is fixed as %f.",
 			 cons->id,
 			 node_rh->details->uname,
 			 node_rh->weight);
 		return TRUE;
 	}
 	
 	crm_verbose("Constraint %s (%s): node %s weight %f.",
 		    cons->id,
 		    cons->can?"can":"cannot",
 		    node_rh->details->uname,
 		    node_rh->weight);
 
 	if(cons->can == FALSE) {
 		node_rh->weight = -1;
 	} else {
 		node_rh->weight += cons->weight;
 	}
 
 	if(node_rh->weight < 0) {
 		node_rh->fixed = TRUE;
 	}
 
 	crm_debug_action(print_node("Updated", node_rh, FALSE));
 
 	return TRUE;
 }
 
 gboolean
 assign_color(resource_t *rsc, color_t *color) 
 {
 	color_t *local_color = add_color(rsc, color);
 	GListPtr intersection = NULL;
 	GListPtr old_list = NULL;
 
 	
 	rsc->color = local_color;
 	rsc->provisional = FALSE;
 
 	if(local_color != NULL) {
 		local_color->details->allocated_resources =
 			g_list_append(
 				local_color->details->allocated_resources,rsc);
 
 			intersection = node_list_and(
 				local_color->details->candidate_nodes, 
 				rsc->allowed_nodes, TRUE);
 			   
 			old_list =
 				local_color->details->candidate_nodes;
 				
 			pe_free_shallow(old_list);
 			
 			local_color->details->candidate_nodes = intersection;
 				
 		return TRUE;
 	}
 	return FALSE;
 }
 
 
 gboolean
 process_colored_constraints(resource_t *rsc) 
 {
 	int lpc = 0;
 	color_t *other_c = NULL;
 	node_t *other_n = NULL;
 
 
 	if(rsc == NULL) {
 		crm_err("No constraints for NULL resource");
 		return FALSE;
 	} else {
 		crm_debug("Processing constraints from %s", rsc->id);
 	}
 	
 	slist_iter(
 		constraint, rsc_to_rsc_t, rsc->rsc_cons, lpc,
 		
 		if(constraint->variant != same_node) {
 			continue;
 		}
 		
 		/* remove the node from the other color */
 		other_c = constraint->rsc_rh->color;
 		other_n = pe_find_node(
 			other_c->details->candidate_nodes,
 			safe_val6(NULL, rsc, color, details,
 				  chosen_node, details, uname));
 		
 		if(other_c == NULL) {
 			crm_err("No color associated with %s",
 				constraint->id);
 			continue;
 		} else if(other_n == NULL) {
 			crm_err("No node associated with rsc/color %s/%d",
 				rsc->id, rsc->color->id);
 			continue;
 		}
 		
 		switch(constraint->strength) {
 			case pecs_must_not:
 				other_c->details->candidate_nodes =
 					g_list_remove(
 						other_c->details->candidate_nodes,
 						other_n);
 				
 				crm_free(other_n);
 				break;
 			default:
 				break;
 		}
 		);
 	return TRUE;
 }
 
diff --git a/crm/pengine/pengine.c b/crm/pengine/pengine.c
index 1839e2f2a5..1018c80cf7 100755
--- a/crm/pengine/pengine.c
+++ b/crm/pengine/pengine.c
@@ -1,249 +1,251 @@
-/* $Id: pengine.c,v 1.44 2004/09/14 05:54:43 andrew Exp $ */
+/* $Id: pengine.c,v 1.45 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <glib.h>
 #include <libxml/tree.h>
 
 #include <pengine.h>
 #include <pe_utils.h>
 FILE *pemsg_strm = NULL;
 
 xmlNodePtr do_calculations(xmlNodePtr cib_object);
 
 gboolean
 process_pe_message(xmlNodePtr msg, IPC_Channel *sender)
 {
 	char *msg_buffer = NULL;
 	const char *sys_to = NULL;
 	const char *op = get_xml_attr (msg, XML_TAG_OPTIONS,
 				       XML_ATTR_OP, TRUE);
 
 	const char *ref = xmlGetProp(msg, XML_ATTR_REFERENCE);
 
 	if(safe_str_eq(xmlGetProp(msg, XML_ATTR_MSGTYPE), XML_ATTR_REQUEST)) {
 		crm_info(
 		       "Message was a response not a request."
 		       "  Discarding");
 	}
 
 	crm_verbose("Processing %s op (ref=%s)...", op, ref);
 
 	if(pemsg_strm == NULL) {
 		pemsg_strm = fopen(DEVEL_DIR"/pe.log", "w");
 	}
 
 	msg_buffer = dump_xml_formatted(msg);
 	fprintf(pemsg_strm, "%s: %s\n", "[in ]", msg_buffer);
 	fflush(pemsg_strm);
 	crm_free(msg_buffer);
 	
 	sys_to = xmlGetProp(msg, XML_ATTR_SYSTO);
 
 	if(op == NULL){
 		/* error */
 
 	} else if(strcmp(op, CRM_OP_HELLO) == 0) {
 		/* ignore */
 		
 	} else if(sys_to == NULL || strcmp(sys_to, CRM_SYSTEM_PENGINE) != 0) {
-		crm_verbose("Bad sys-to %s", sys_to);
+		crm_verbose("Bad sys-to %s", crm_str(sys_to));
 		return FALSE;
 		
 	} else if(strcmp(op, CRM_OP_PECALC) == 0) {
 		xmlNodePtr input_cib = find_xml_node(msg, XML_TAG_CIB);
 		xmlNodePtr output = do_calculations(input_cib);
 		msg_buffer = dump_xml_formatted(output);
 		fprintf(pemsg_strm, "%s: %s\n", "[out ]", msg_buffer);
 		fflush(pemsg_strm);
 		crm_free(msg_buffer);
 		if (send_ipc_reply(sender, msg, output) ==FALSE) {
 
 			crm_warn("Answer could not be sent");
 		}
 		free_xml(output);
 
 	} else if(strcmp(op, CRM_OP_QUIT) == 0) {
 		crm_err("Received quit message, terminating");
 		exit(0);
 	}
 	
 	return TRUE;
 }
 
 xmlNodePtr
 do_calculations(xmlNodePtr cib_object)
 {
 	int lpc, lpc2;
 	
 	GListPtr resources = NULL;
 	GListPtr nodes = NULL;
 	GListPtr node_constraints = NULL;
 	GListPtr actions = NULL;
 	GListPtr action_constraints = NULL;
 	GListPtr stonith_list = NULL;
 	GListPtr shutdown_list = NULL;
 
 	GListPtr colors = NULL;
 	GListPtr action_sets = NULL;
 
 	xmlNodePtr graph = NULL;
 
 /*	pe_debug_on(); */
 	
 	crm_verbose("=#=#=#=#= Stage 0 =#=#=#=#=");
 		  
 	stage0(cib_object,
 	       &resources,
 	       &nodes,  &node_constraints,
 	       &actions,  &action_constraints,
 	       &stonith_list, &shutdown_list);
 
 	crm_verbose("=#=#=#=#= Stage 1 =#=#=#=#=");
 	stage1(node_constraints, nodes, resources);
 
 	crm_verbose("=#=#=#=#= Stage 2 =#=#=#=#=");
 	stage2(resources, nodes, &colors);
 
 	crm_verbose("========= Nodes =========");
 	crm_debug_action(
 		slist_iter(node, node_t, nodes, lpc,
 			   print_node(NULL, node, TRUE)
 			)
 		);
 		
 	crm_verbose("========= Resources =========");
 	crm_debug_action(
 		slist_iter(resource, resource_t, resources, lpc,
 			   print_resource(NULL, resource, TRUE)
 			)
 		);  
   
 	crm_verbose("=#=#=#=#= Stage 3 =#=#=#=#=");
 	stage3(colors);
 
 	crm_verbose("=#=#=#=#= Stage 4 =#=#=#=#=");
 	stage4(colors);
 	crm_verbose("========= Colors =========");
 	crm_debug_action(
 		slist_iter(color, color_t, colors, lpc,
 		   print_color(NULL, color, FALSE)
 			)
 		);
 
 	crm_verbose("=#=#=#=#= Stage 5 =#=#=#=#=");
 	stage5(resources);
 
 	crm_verbose("=#=#=#=#= Stage 6 =#=#=#=#=");
 	stage6(&actions, &action_constraints, nodes, resources);
 
 	crm_verbose("========= Action List =========");
 	crm_debug_action(
 		slist_iter(action, action_t, actions, lpc,
 			   print_action(NULL, action, TRUE)
 			)
 		);
 	
 	crm_verbose("=#=#=#=#= Stage 7 =#=#=#=#=");
 	stage7(resources, actions, action_constraints, &action_sets);
 	
 	crm_verbose("=#=#=#=#= Summary =#=#=#=#=");
 	summary(resources);
 
 	crm_verbose("========= Action Sets =========");
 
 	crm_verbose("\t========= Set %d (Un-runnable) =========", -1);
 	crm_debug_action(
 		slist_iter(action, action_t, actions, lpc,
 			   if(action->optional == FALSE
 			      && action->runnable == FALSE) {
 				   print_action("\t", action, TRUE);
 			   }
 			)
 		);
 
 	crm_debug_action(
 		slist_iter(action_set, GList, action_sets, lpc,
 			   crm_verbose("\t========= Set %d =========", lpc);
 			   slist_iter(action, action_t, action_set, lpc2,
 				      print_action("\t", action, TRUE);
 				   )
 			)
 		);
 
 	
 	crm_verbose("========= Stonith List =========");
 	crm_debug_action(
 		slist_iter(node, node_t, stonith_list, lpc,
 			   print_node(NULL, node, FALSE);
 			)
 		);
   
 	crm_verbose("========= Shutdown List =========");
 	crm_debug_action(
 		slist_iter(node, node_t, shutdown_list, lpc,
 			   print_node(NULL, node, FALSE);
 			)
 		);
 
 	crm_verbose("=#=#=#=#= Stage 8 =#=#=#=#=");
 	stage8(actions, &graph);
 
 	crm_verbose("=#=#=#=#= Cleanup =#=#=#=#=");
 
 	crm_verbose("deleting node cons");
 	while(node_constraints) {
 		pe_free_rsc_to_node((rsc_to_node_t*)node_constraints->data);
 		node_constraints = node_constraints->next;
 	}
-	g_list_free(node_constraints);
+	if(node_constraints != NULL) {
+		g_list_free(node_constraints);
+	}
 
 	crm_verbose("deleting order cons");
 	pe_free_shallow(action_constraints);
 
 	crm_verbose("deleting action sets");
 
 	slist_iter(action_set, GList, action_sets, lpc,
 		   pe_free_shallow_adv(action_set, FALSE);
 		);
 	pe_free_shallow_adv(action_sets, FALSE);
 	
 	crm_verbose("deleting actions");
 	pe_free_actions(actions);
 
 	crm_verbose("deleting resources");
 	pe_free_resources(resources); 
 	
 	crm_verbose("deleting colors");
 	pe_free_colors(colors);
 
 	crm_verbose("deleting nodes");
 	pe_free_nodes(nodes);
 	
 	g_list_free(shutdown_list);
 	g_list_free(stonith_list);
 
 	return graph;
 }
diff --git a/crm/pengine/ptest.c b/crm/pengine/ptest.c
index c137989bea..77d5a61bf8 100644
--- a/crm/pengine/ptest.c
+++ b/crm/pengine/ptest.c
@@ -1,274 +1,276 @@
-/* $Id: ptest.c,v 1.33 2004/09/14 05:54:43 andrew Exp $ */
+/* $Id: ptest.c,v 1.34 2004/09/17 13:03:10 andrew Exp $ */
 
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <portability.h>
 #include <crm/crm.h>
 
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/common/xml.h>
 #include <crm/common/util.h>
 #include <crm/msg_xml.h>
 
 #include <crm/cib.h>
 
 #define OPTARGS	"V?i:o:D:C:S:HA:U:M:I:EWRFt:m:a:d:w:c:r:p:s:"
 
 #include <getopt.h>
 #include <glib.h>
 #include <pengine.h>
 #include <pe_utils.h>
 
 
 int
 main(int argc, char **argv)
 {
 	xmlNodePtr cib_object = NULL;
 	int lpc = 0;
 	int argerr = 0;
 	int flag;
 		
 	GListPtr resources = NULL;
 	GListPtr nodes = NULL;
 	GListPtr node_constraints = NULL;
 	GListPtr actions = NULL;
 	GListPtr action_constraints = NULL;
 	GListPtr stonith_list = NULL;
 	GListPtr shutdown_list = NULL;
 	GListPtr colors = NULL;
 	GListPtr action_sets = NULL;
 	xmlNodePtr graph = NULL;
 	char *msg_buffer = NULL;
 
 	cl_log_set_entity("ptest");
 	cl_log_set_facility(LOG_USER);
 	
 	while (1) {
 		int option_index = 0;
 		static struct option long_options[] = {
 			/* Top-level Options */
 			{"help", 0, 0, 0},
       
 			{0, 0, 0, 0}
 		};
     
 		flag = getopt_long(argc, argv, OPTARGS,
 				   long_options, &option_index);
 		if (flag == -1)
 			break;
     
 		switch(flag) {
 			case 0:
 				printf("option %s", long_options[option_index].name);
 				if (optarg)
 					printf(" with arg %s", optarg);
 				printf("\n");
     
 				break;
       
 			case 'V':
 				alter_debug(DEBUG_INC);
 				break;
 			default:
 				printf("?? getopt returned character code 0%o ??\n", flag);
 				++argerr;
 				break;
 		}
 	}
   
 	if (optind < argc) {
 		printf("non-option ARGV-elements: ");
 		while (optind < argc)
 			printf("%s ", argv[optind++]);
 		printf("\n");
 	}
   
 	if (optind > argc) {
 		++argerr;
 	}
   
 	if (argerr) {
 		crm_err("%d errors in option parsing", argerr);
 	}
   
 	crm_info("=#=#=#=#= Getting XML =#=#=#=#=");
   
 	cib_object = file2xml(stdin);
   
 	crm_info("=#=#=#=#= Stage 0 =#=#=#=#=");
 
 
 #ifdef MCHECK
 	mtrace();
 #endif
 
 	stage0(cib_object,
 	       &resources,
 	       &nodes,  &node_constraints,
 	       &actions,  &action_constraints,
 	       &stonith_list, &shutdown_list);
 	
 	crm_debug("========= Nodes =========");
 	slist_iter(node, node_t, nodes, lpc,
 		   print_node(NULL, node, TRUE));
 
 	crm_debug("========= Resources =========");
 	slist_iter(resource, resource_t, resources, lpc,
 		   print_resource(NULL, resource, TRUE));    
 
 	crm_debug("========= Constraints =========");
 	slist_iter(constraint, rsc_to_node_t, node_constraints, lpc,
 		   print_rsc_to_node(NULL, constraint, FALSE));
     
 	crm_debug("=#=#=#=#= Stage 1 =#=#=#=#=");
 	stage1(node_constraints, nodes, resources);
 
 	crm_debug("========= Nodes =========");
 	slist_iter(node, node_t, nodes, lpc,
 		   print_node(NULL, node, TRUE));
 
 	crm_debug("========= Resources =========");
 	slist_iter(resource, resource_t, resources, lpc,
 		   print_resource(NULL, resource, TRUE));
 
 	crm_debug("=#=#=#=#= Stage 2 =#=#=#=#=");
 /*	pe_debug_on(); */
 	stage2(resources, nodes, &colors);
 /*	pe_debug_off(); */
 
 	crm_debug("========= Nodes =========");
 	slist_iter(node, node_t, nodes, lpc,
 		   print_node(NULL, node, TRUE));
 
 	crm_debug("========= Resources =========");
 	slist_iter(resource, resource_t, resources, lpc,
 		   print_resource(NULL, resource, TRUE));  
   
 	crm_debug("========= Colors =========");
 	slist_iter(color, color_t, colors, lpc,
 		   print_color(NULL, color, FALSE));
   
 	crm_debug("=#=#=#=#= Stage 3 =#=#=#=#=");
 	stage3(colors);
 	crm_debug("========= Colors =========");
 	slist_iter(color, color_t, colors, lpc,
 		   print_color(NULL, color, FALSE));
 
 	crm_debug("=#=#=#=#= Stage 4 =#=#=#=#=");
 	stage4(colors);
 	crm_debug("========= Colors =========");
 	slist_iter(color, color_t, colors, lpc,
 		   print_color(NULL, color, FALSE));
 
 	crm_debug("=#=#=#=#= Summary =#=#=#=#=");
 	summary(resources);
 	crm_debug("========= Action List =========");
 	slist_iter(action, action_t, actions, lpc,
 		   print_action(NULL, action, FALSE));
 	
 	crm_debug("=#=#=#=#= Stage 5 =#=#=#=#=");
 	stage5(resources);
 
 	crm_debug("=#=#=#=#= Stage 6 =#=#=#=#=");
 	stage6(&actions, &action_constraints, nodes, resources);
 
 	crm_debug("========= Action List =========");
 	slist_iter(action, action_t, actions, lpc,
 		   print_action(NULL, action, TRUE));
 	
 	crm_debug("=#=#=#=#= Stage 7 =#=#=#=#=");
 	stage7(resources, actions, action_constraints, &action_sets);
 
 	crm_debug("=#=#=#=#= Summary =#=#=#=#=");
 	summary(resources);
 
 	crm_debug("========= All Actions =========");
 	slist_iter(action, action_t, actions, lpc,
 		   print_action("\t", action, TRUE);
 		);
 
 	crm_debug("========= Stonith List =========");
 	slist_iter(node, node_t, stonith_list, lpc,
 		   print_node(NULL, node, FALSE));
   
 	crm_debug("========= Shutdown List =========");
 	slist_iter(node, node_t, shutdown_list, lpc,
 		   print_node(NULL, node, FALSE));
 
 	crm_debug("=#=#=#=#= Stage 8 =#=#=#=#=");
 	stage8(actions, &graph);
 
 
 	crm_verbose("deleting node cons");
 	while(node_constraints) {
 		pe_free_rsc_to_node((rsc_to_node_t*)node_constraints->data);
 		node_constraints = node_constraints->next;
 	}
-	g_list_free(node_constraints);
+	if(node_constraints != NULL) {
+		g_list_free(node_constraints);
+	}
 	
 	crm_verbose("deleting order cons");
 	pe_free_shallow(action_constraints);
 
 	crm_verbose("deleting action sets");
 	slist_iter(action_set, GList, action_sets, lpc,
 		   pe_free_shallow_adv(action_set, FALSE);
 		);
 	pe_free_shallow_adv(action_sets, FALSE);
 	
 	crm_verbose("deleting actions");
 	pe_free_actions(actions);
 
 /*	GListPtr action_sets = NULL; */
 
 	crm_verbose("deleting resources");
 	pe_free_resources(resources); 
 	
 	crm_verbose("deleting colors");
 	pe_free_colors(colors);
 
 	crm_free(no_color->details);
 	crm_free(no_color);
 	
 	crm_verbose("deleting nodes");
 	pe_free_nodes(nodes);
 	
 	g_list_free(shutdown_list);
 	g_list_free(stonith_list);
 
 #ifdef MCHECK
 	muntrace();
 #endif
 
 	msg_buffer = dump_xml_formatted(graph);
 	fprintf(stdout, "%s\n", msg_buffer);
 	fflush(stdout);
 	crm_free(msg_buffer);
 
 	free_xml(graph);
 	free_xml(cib_object);
 
 	return 0;
 }
diff --git a/crm/pengine/stages.c b/crm/pengine/stages.c
index 9b24d0728a..ae0754b4c5 100644
--- a/crm/pengine/stages.c
+++ b/crm/pengine/stages.c
@@ -1,605 +1,598 @@
-/* $Id: stages.c,v 1.19 2004/09/14 05:54:43 andrew Exp $ */
+/* $Id: stages.c,v 1.20 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <glib.h>
 #include <libxml/tree.h>
 
 #include <pengine.h>
 #include <pe_utils.h>
 
 node_t *choose_fencer(action_t *stonith, node_t *node, GListPtr resources);
 
 /*
  * Unpack everything
  * At the end you'll have:
  *  - A list of nodes
  *  - A list of resources (each with any dependancies on other resources)
  *  - A list of constraints between resources and nodes
  *  - A list of constraints between start/stop actions
  *  - A list of nodes that need to be stonith'd
  *  - A list of nodes that need to be shutdown
  *  - A list of the possible stop/start actions (without dependancies)
  */
 gboolean
 stage0(xmlNodePtr cib,
        GListPtr *resources,
        GListPtr *nodes, GListPtr *node_constraints,
        GListPtr *actions, GListPtr *action_constraints,
        GListPtr *stonith_list, GListPtr *shutdown_list)
 {
 /*	int lpc; */
 	xmlNodePtr cib_nodes       = get_object_root(
 		XML_CIB_TAG_NODES,       cib);
 	xmlNodePtr cib_status      = get_object_root(
 		XML_CIB_TAG_STATUS,      cib);
 	xmlNodePtr cib_resources   = get_object_root(
 		XML_CIB_TAG_RESOURCES,   cib);
 	xmlNodePtr cib_constraints = get_object_root(
 		XML_CIB_TAG_CONSTRAINTS, cib);
 	xmlNodePtr config          = get_object_root(
 		XML_CIB_TAG_CRMCONFIG,   cib);
 	xmlNodePtr agent_defaults  = NULL;
 	/*get_object_root(XML_CIB_TAG_RA_DEFAULTS, cib); */
 
 	/* reset remaining global variables */
 	max_valid_nodes = 0;
 	order_id = 1;
 	action_id = 1;
 
 	unpack_config(config);
 	
 	unpack_global_defaults(agent_defaults);
 	
 	unpack_nodes(cib_nodes, nodes);
 
 	unpack_resources(cib_resources,
 			 resources, actions, action_constraints, *nodes);
 
 	unpack_status(cib_status,
 		      *nodes, *resources, actions, node_constraints);
 
 	unpack_constraints(cib_constraints,
 			   *nodes, *resources,
 			   node_constraints, action_constraints);
 
 	return TRUE;
 }
 
 /*
  * Count how many valid nodes we have (so we know the maximum number of
  *  colors we can resolve).
  *
  * Apply node constraints (ie. filter the "allowed_nodes" part of resources
  */
 gboolean
 stage1(GListPtr node_constraints, GListPtr nodes, GListPtr resources)
 {
 	int lpc = 0;
 	
 	slist_iter(
 		node, node_t, nodes, lpc,
 		if(node == NULL) {
 			/* error */
 		} else if(node->weight >= 0.0 /* global weight */
 			  && node->details->online
 			  && node->details->type == node_member) {
 			max_valid_nodes++;
 		}	
 		);
 
 	apply_node_constraints(node_constraints, nodes);
 
 	/* will also filter -ve "final" weighted nodes from resources'
 	 *   allowed lists while we are there
 	 */
 	apply_agent_constraints(resources);
 
 	return TRUE;
 } 
 
 
 
 /*
  * Choose a color for all resources from highest priority and XML_STRENGTH_VAL_MUST
  *  dependancies to lowest, creating new colors as necessary (returned
  *  as "colors").
  *
  * Some nodes may be colored as a "no_color" meaning that it was unresolvable
  *  given the current node stati and constraints.
  */
 gboolean
 stage2(GListPtr sorted_rscs, GListPtr sorted_nodes, GListPtr *colors)
 {
 	int lpc;
 
 	crm_trace("setup");
 	
 	if(no_color != NULL) {
 		crm_free(no_color->details);
 		crm_free(no_color);
 	}
 	
 	crm_trace("create \"no color\"");
 	no_color = create_color(NULL, NULL, NULL);
 	
 	/* Take (next) highest resource */
 	slist_iter(
 		lh_resource, resource_t, sorted_rscs, lpc,
 		/* if resource.provisional == FALSE, repeat  */
 		if(lh_resource->provisional == FALSE) {
 			/* already processed this resource */
 			continue;
 		}
 		color_resource(lh_resource, colors, sorted_rscs);
 		/* next resource */
 		);
 	
 	return TRUE;
 }
 
 /*
  * not sure if this is a good idea or not, but eventually we might like
  *  to utilize as many nodes as possible... and this might be a convienient
  *  hook
  */
 gboolean
 stage3(GListPtr colors)
 {
 	/* not sure if this is a good idea or not */
 	if(g_list_length(colors) > max_valid_nodes) {
 		/* we need to consolidate some */
 	} else if(g_list_length(colors) < max_valid_nodes) {
 		/* we can create a few more */
 	}
 	return TRUE;
 }
 
 /*
  * Choose a node for each (if possible) color
  */
 gboolean
 stage4(GListPtr colors)
 {
 	int lpc = 0, lpc2 = 0;
 
 	slist_iter(
 		color, color_t, colors, lpc,
 
 		crm_debug("assigning node to color %d", color->id);
 		
 		if(color == NULL) {
 			crm_err("NULL color detected");
 			continue;
 			
 		} else if(color->details->pending == FALSE) {
 			continue;
 		}
 		
 		choose_node_from_list(color);
 
 		crm_debug("assigned %s to color %d",
 			  safe_val5(NULL, color, details, chosen_node, details, uname),
 			  color->id);
 
 		slist_iter(
 			rsc, resource_t, color->details->allocated_resources, lpc2,
 
 			process_colored_constraints(rsc);
 			
 			);
 		);
 	crm_verbose("done");
 	return TRUE;
 	
 }
 
 
 /*
  * Attach nodes to the actions that need to be taken
  *
  * Mark actions XML_LRM_ATTR_OPTIONAL if possible (Ie. if the start and stop are
  *  for the same node)
  *
  * Mark unrunnable actions
  */
 gboolean
 stage5(GListPtr resources)
 {
 	int lpc = 0;
 	int lpc2 = 0;
 	node_t *start_node = NULL;
 	node_t *stop_node = NULL;
 	node_t *default_node = NULL;
 
 	crm_verbose("filling in the nodes to perform the actions on");
 	slist_iter(
 		rsc, resource_t, resources, lpc,
 
 		crm_debug_action(print_resource("Processing", rsc, FALSE));
 		
 		default_node = NULL;
 		start_node = safe_val4(
 			NULL, rsc, color, details, chosen_node);
 		stop_node = safe_val(NULL, rsc, cur_node);
 		if(stop_node == NULL && start_node == NULL) {
 			/* it is not and will not run */
 			default_node = NULL;
 
 		} else if(stop_node == NULL) {
 			/* it is not running yet, all actions must take place
 			 * on the new node and if they fail, they fail
 			 */
 			default_node = start_node;
 			rsc->start->optional = FALSE;
 			crm_info("Starting resource %s (%s)",
 				  safe_val(NULL, rsc, id),
 				  safe_val3(NULL,start_node,details,uname));
 
 
 		} else if(start_node == NULL) {
 			/* it is being stopped, all actions must take place
 			 * on the existing node and if they fail, they fail
 			 */
 			default_node = stop_node;
 			rsc->stop->optional  = FALSE;
 			crm_warn("Stop resource %s (%s)",
 				  safe_val(NULL, rsc, id),
 				  safe_val3(NULL, stop_node, details,uname));
 
 		} else if(safe_str_eq(
 			   safe_val3(NULL, stop_node, details, uname),
 			   safe_val3(NULL, start_node, details, uname))) {
 
 			/* its not moving so choose either copy */
 			default_node = start_node;
 			crm_verbose("No change (possible restart)"
 				    " for Resource %s (%s)",
 				    safe_val(NULL, rsc, id),
 				    safe_val3(
 					    NULL,default_node,details,uname));
 
 			
 		} else {
 			/* the resource is moving...
 			 *
 			 * the action was scheduled based on its current
 			 * location and or state, actions other than start
 			 * and stop *must* be run at the existing location
 			 * (ie. stop_node)
 			 *
 			 */
 
 			default_node = stop_node;
 			rsc->stop->optional  = FALSE;
 			rsc->start->optional = FALSE;
 			
 			crm_debug("Move resource %s (%s -> %s)",
 				  safe_val(NULL, rsc, id),
 				  safe_val3(NULL, stop_node,details,uname),
 				  safe_val3(NULL, start_node,details,uname));
 		}
 		
 		
 		slist_iter(
 			action, action_t, rsc->actions, lpc2,
 
 			switch(action->task) {
 				case start_rsc:
 					action->node = start_node;
 					break;
 				case stop_rsc:
 					action->node = stop_node;
 					break;
 				default:
 					action->node = default_node;
 					break;
 			}
 
 			if(action->node == NULL) {
 				action->runnable = FALSE;
 			}
 			
 			);
 		);
 	
 	return TRUE;
 }
 
 /*
  * Create dependacies for stonith and shutdown operations
  */
 gboolean
 stage6(GListPtr *actions, GListPtr *action_constraints,
        GListPtr nodes, GListPtr resources)
 {
 
 	int lpc = 0;
 	action_t *down_node = NULL;
 	action_t *stonith_node = NULL;
 
 	slist_iter(
 		node, node_t, nodes, lpc,
 		if(node->details->shutdown) {
 			crm_warn("Scheduling Node %s for shutdown",
 				 node->details->uname);
 			
 			down_node = action_new(NULL,shutdown_crm);
 			down_node->node     = node;
 			down_node->runnable = TRUE;
 			down_node->optional = FALSE;
 			
 			*actions = g_list_append(*actions, down_node);
 			
 			shutdown_constraints(
 				node, down_node, action_constraints);
 			
 		}
 
 		if(node->details->unclean) {
 			crm_warn("Scheduling Node %s for STONITH",
 				 node->details->uname);
 
 			stonith_node = action_new(NULL,stonith_op);
 			stonith_node->runnable = TRUE;
 			stonith_node->optional = FALSE;
 			choose_fencer(
 				stonith_node, node, resources);
 
 			set_xml_property_copy(stonith_node->args,
 					      "target", node->details->uname);
 			
 			if(stonith_node->node == NULL) {
 				/*stonith_node->runnable = FALSE; */
 			}
 			
 			if(down_node != NULL) {
 				down_node->failure_is_fatal = FALSE;
 			}
 			
 			*actions = g_list_append(*actions, stonith_node);
 			
 			stonith_constraints(node, stonith_node, down_node,
 					    action_constraints);
 		}
 		);
 
 
 	return TRUE;
 }
 
 /*
  * Determin the sets of independant actions and the correct order for the
  *  actions in each set.
  *
  * Mark dependancies of un-runnable actions un-runnable
  *
  */
 gboolean
 stage7(GListPtr resources, GListPtr actions, GListPtr action_constraints,
 	GListPtr *action_sets)
 {
 	int lpc;
 	action_wrapper_t *wrapper = NULL;
 	GListPtr list = NULL;
 
-// compress(action1, action2)
-
-	
-/*
-	for(lpc = 0; lpc < g_list_length(action_constraints);  lpc++) {
-		order_constraint_t *order = (order_constraint_t*)
-			g_list_nth_data(action_constraints, lpc);
-*/
 	slist_iter(
 		order, order_constraint_t, action_constraints, lpc,
 			
 		crm_verbose("%d Processing %d -> %d",
 		       order->id,
 		       order->lh_action->id,
 		       order->rh_action->id);
 
 		crm_debug_action(
 			print_action("LH (stage7)", order->lh_action, FALSE));
 		crm_debug_action(
 			print_action("RH (stage7)", order->rh_action, FALSE));
 
-		wrapper = (action_wrapper_t*)
-			crm_malloc(sizeof(action_wrapper_t));
-		wrapper->action = order->rh_action;
-		wrapper->strength = order->strength;
-
-		list = order->lh_action->actions_after;
-		list = g_list_append(list, wrapper);
-		order->lh_action->actions_after = list;
-
-		wrapper = (action_wrapper_t*)
-			crm_malloc(sizeof(action_wrapper_t));
-		wrapper->action = order->lh_action;
-		wrapper->strength = order->strength;
-
-		list = order->rh_action->actions_before;
-		list = g_list_append(list, wrapper);
-		order->rh_action->actions_before = list;
+		crm_malloc(wrapper, sizeof(action_wrapper_t));
+		if(wrapper != NULL) {
+			wrapper->action = order->rh_action;
+			wrapper->strength = order->strength;
+			
+			list = order->lh_action->actions_after;
+			list = g_list_append(list, wrapper);
+			order->lh_action->actions_after = list;
+		}
+		
+		crm_malloc(wrapper, sizeof(action_wrapper_t));
+		if(wrapper != NULL) {
+			wrapper->action = order->lh_action;
+			wrapper->strength = order->strength;
+			
+			list = order->rh_action->actions_before;
+			list = g_list_append(list, wrapper);
+			order->rh_action->actions_before = list;
+		}
 		);
-/*	} */
 
 	update_action_states(actions);
 
 	return TRUE;
 }
 
 /*
  * Create a dependancy graph to send to the transitioner (via the CRMd)
  */
 gboolean
 stage8(GListPtr actions, xmlNodePtr *graph)
 {
 	int lpc = 0;
 	int lpc2 = 0;
 
 	xmlNodePtr syn = NULL;
 	xmlNodePtr set = NULL;
 	xmlNodePtr in  = NULL;
 	xmlNodePtr input = NULL;
 	xmlNodePtr xml_action = NULL;
 	
 	*graph = create_xml_node(NULL, "transition_graph");
 	
 /* errors...
 	slist_iter(action, action_t, action_list, lpc,
 		   if(action->optional == FALSE && action->runnable == FALSE) {
 			   print_action("Ignoring", action, TRUE);
 		   }
 		);
 */
 	slist_iter(
 		action, action_t, actions, lpc,
 
 		if(action->optional) {
 			continue;
 		} else if(action->runnable == FALSE) {
 			continue;
 		}
 		
 		syn    = create_xml_node(*graph, "synapse");
 		set    = create_xml_node(syn, "action_set");
 		in     = create_xml_node(syn, "inputs");
 		
 		xml_action = action2xml(action);
 		xmlAddChild(set, xml_action);
 
 		slist_iter(
 			wrapper,action_wrapper_t,action->actions_before,lpc2,
 
 			switch(wrapper->strength) {
 				case pecs_must_not:
 				case pecs_ignore:
 					/* ignore both */
 					break;
 				case pecs_startstop:
 					if(wrapper->action->runnable == FALSE){
 						break;
 					}
 					/* keep going */
 				case pecs_must:
 					input = create_xml_node(in, "trigger");
 					
 					xml_action=action2xml(wrapper->action);
 					xmlAddChild(input, xml_action);
 					break;
 			}
 			
 			);
 
 		);
 
 	crm_xml_devel(*graph, "created action list");
 	
 	return TRUE;
 }
 
 /*
  * Print a nice human readable high-level summary of what we're going to do 
  */
 gboolean
 summary(GListPtr resources)
 {
 	int lpc = 0;
 	const char *rsc_id      = NULL;
 	const char *node_id     = NULL;
 	const char *new_node_id = NULL;
 	
 	slist_iter(
 		rsc, resource_t, resources, lpc,
 		rsc_id = safe_val(NULL, rsc, id);
 		node_id = safe_val4(NULL, rsc, cur_node, details, uname);
 		new_node_id = safe_val6(
 			NULL, rsc, color, details, chosen_node, details, uname);
 
 		if(rsc->runnable == FALSE) {
 			crm_err("Resource %s was not runnable", rsc_id);
 			if(node_id != NULL) {
 				crm_warn("Stopping Resource (%s) on node %s",
 					 rsc_id, node_id);
 			}
 
 		} else if(safe_val4(NULL, rsc, color, details, chosen_node) == NULL) {
 			crm_err("Could not allocate Resource %s", rsc_id);
 			crm_debug_action(
 				print_resource("Could not allocate",rsc,TRUE));
 			if(node_id != NULL) {
 				
 				crm_warn("Stopping Resource (%s) on node %s",
 					 rsc_id, node_id);
 			}
 			
 		} else if(safe_str_eq(node_id, new_node_id)){
 			crm_debug("No change for Resource %s (%s)",
 				  rsc_id,
 				  safe_val4(NULL, rsc, cur_node, details, uname));
 			
 		} else if(node_id == NULL) {
 			crm_info("Starting Resource %s on %s",
 				 rsc_id, new_node_id);
 			
 		} else {
 			crm_info("Moving Resource %s from %s to %s",
 				 rsc_id, node_id, new_node_id);
 		}
 		);
 	
 	
 	return TRUE;
 }
 
 gboolean
 choose_node_from_list(color_t *color)
 {
 	/*
 	  1. Sort by weight
 	  2. color.chosen_node = highest wieghted node 
 	  3. remove color.chosen_node from all other colors
 	*/
 	GListPtr nodes = color->details->candidate_nodes;
 	nodes = g_list_sort(nodes, sort_node_weight);
 	color->details->chosen_node =
 		node_copy((node_t*)g_list_nth_data(nodes, 0));
 	color->details->pending = FALSE;
 
 	if(color->details->chosen_node == NULL) {
 		crm_err("Could not allocate a node for color %d",
 			color->id);
 		return FALSE;
 	}
 	
 	return TRUE;
 }
 
 node_t *
 choose_fencer(action_t *stonith, node_t *a_node, GListPtr resources)
 {
 	return NULL;
 }
diff --git a/crm/pengine/unpack.c b/crm/pengine/unpack.c
index aef9ce695f..8e77742092 100644
--- a/crm/pengine/unpack.c
+++ b/crm/pengine/unpack.c
@@ -1,1273 +1,1305 @@
-/* $Id: unpack.c,v 1.27 2004/09/15 20:24:53 andrew Exp $ */
+/* $Id: unpack.c,v 1.28 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <portability.h>
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <lrm/lrm_api.h>
 
 #include <glib.h>
 #include <libxml/tree.h>
 
 #include <heartbeat.h> /* for ONLINESTATUS */
 
 #include <pengine.h>
 #include <pe_utils.h>
 
 int      max_valid_nodes = 0;
 int      order_id        = 1;
 GListPtr agent_defaults  = NULL;
 gboolean stonith_enabled = FALSE;
 
 GListPtr match_attrs(const char *attr, const char *op, const char *value,
 		     const char *type, GListPtr node_list);
 
 gboolean unpack_rsc_to_attr(xmlNodePtr xml_obj,
 			    GListPtr rsc_list,
 			    GListPtr node_list,
 			    GListPtr *node_constraints);
 
 gboolean unpack_rsc_to_node(xmlNodePtr xml_obj,
 			    GListPtr rsc_list,
 			    GListPtr node_list,
 			    GListPtr *node_constraints);
 
 gboolean unpack_rsc_order(
 	xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr *action_constraints);
 
 gboolean unpack_rsc_dependancy(
 	xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr *action_constraints);
 
 gboolean unpack_rsc_location(
 	xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr node_list,
 	GListPtr *action_constraints);
 
 gboolean unpack_lrm_rsc_state(
 	node_t *node, xmlNodePtr lrm_state,
 	GListPtr rsc_list, GListPtr nodes,
 	GListPtr *actions, GListPtr *node_constraints);
 
 gboolean add_node_attrs(xmlNodePtr attrs, node_t *node);
 
 gboolean unpack_healthy_resource(GListPtr *node_constraints, GListPtr *actions,
 	xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node);
 
 gboolean unpack_failed_resource(GListPtr *node_constraints, GListPtr *actions,
 	xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node);
 
 gboolean determine_online_status(xmlNodePtr node_state, node_t *this_node);
 
 gboolean unpack_lrm_agents(node_t *node, xmlNodePtr agent_list);
 
 gboolean is_node_unclean(xmlNodePtr node_state);
 
 gboolean rsc2rsc_new(const char *id, enum con_strength strength, enum rsc_con_type type,
 		     resource_t *rsc_lh, resource_t *rsc_rh);
 
 gboolean create_ordering(
 	const char *id, enum con_strength strength,
 	resource_t *rsc_lh, resource_t *rsc_rh, GListPtr *action_constraints);
 
 rsc_to_node_t *rsc2node_new(
 	const char *id, resource_t *rsc,
 	double weight, gboolean can_run, node_t *node,
 	GListPtr *node_constraints);
 
 const char *get_agent_param(resource_t *rsc, const char *param);
 
 const char *get_agent_param_rsc(resource_t *rsc, const char *param);
 
 const void *get_agent_param_metadata(resource_t *rsc, const char *param);
 
 const char *get_agent_param_global(resource_t *rsc, const char *param);
 
 const char *param_value(xmlNodePtr parent, const char *name);
 
 gboolean
 unpack_config(xmlNodePtr config)
 {
 	const char *value = NULL;
 	
 	value = param_value(config, "failed_nodes");
 
 	crm_debug("config %p", config);
 	crm_debug("value %p", value);
 
 	if(safe_str_eq(value, "stonith")) {
 		crm_debug("Enabling STONITH of failed nodes");
 		stonith_enabled = TRUE;
 	} else {
 		stonith_enabled = FALSE;
 	}
 	
 	return TRUE;
 }
 
 const char *
 param_value(xmlNodePtr parent, const char *name) 
 {
 	xmlNodePtr a_default = find_entity(
 		parent, XML_CIB_TAG_NVPAIR, name, FALSE);
 
 	return xmlGetProp(a_default, XML_NVPAIR_ATTR_VALUE);
 }
 
 const char *
 get_agent_param(resource_t *rsc, const char *param)
 {
 	const char *value = NULL;
 
 	if(param == NULL) {
 		return NULL;
 	}
 	
 	value = get_agent_param_rsc(rsc, param);
 	if(value == NULL) {
 		value = get_agent_param_metadata(rsc, param);
 	}
 	if(value == NULL) {
 		value = get_agent_param_global(rsc, param);
 	}
 	
 	return value;
 }
 
 const char *
 get_agent_param_rsc(resource_t *rsc, const char *param)
 {
 	xmlNodePtr xml_rsc = rsc->xml;
 	return xmlGetProp(xml_rsc, param);
 }
 
 const void *
 get_agent_param_metadata(resource_t *rsc, const char *param)
 {
 	return NULL;
 }
 
 const char *
 get_agent_param_global(resource_t *rsc, const char *param)
 {
 	const char * value = NULL;/*g_hashtable_lookup(agent_global_defaults, param); */
 	if(value == NULL) {
 		crm_err("No global value default for %s", param);
 	}
 	return value;
 }
 
 gboolean
 unpack_global_defaults(xmlNodePtr defaults)
 {
 	return TRUE;
 }
 
 
 gboolean
 unpack_nodes(xmlNodePtr xml_nodes, GListPtr *nodes)
 {
 	node_t *new_node   = NULL;
 	xmlNodePtr attrs   = NULL;
 	const char *id     = NULL;
 	const char *uname  = NULL;
 	const char *type   = NULL;
 
 	crm_verbose("Begining unpack...");
 	xml_child_iter(
 		xml_nodes, xml_obj, XML_CIB_TAG_NODE,
 
 		attrs   = xml_obj->children;
 		id     = xmlGetProp(xml_obj, XML_ATTR_ID);
 		uname  = xmlGetProp(xml_obj, XML_ATTR_UNAME);
 		type   = xmlGetProp(xml_obj, XML_ATTR_TYPE);
 
-		crm_verbose("Processing node %s", id);
+		crm_verbose("Processing node %s/%s", uname, id);
 
 		if(attrs != NULL) {
 			attrs = attrs->children;
 		}
 		
 		if(id == NULL) {
 			crm_err("Must specify id tag in <node>");
 			xml_iter_continue(xml_obj);
 		}
 		if(type == NULL) {
 			crm_err("Must specify type tag in <node>");
 			xml_iter_continue(xml_obj);
 		}
-		new_node  = crm_malloc(sizeof(node_t));
+		crm_malloc(new_node, sizeof(node_t));
+		if(new_node == NULL) {
+			return FALSE;
+		}
+		
 		new_node->weight  = 1.0;
 		new_node->fixed   = FALSE;
-		new_node->details = (struct node_shared_s*)
-			crm_malloc(sizeof(struct node_shared_s));
+		crm_malloc(new_node->details,
+			   sizeof(struct node_shared_s));
+
+		if(new_node->details == NULL) {
+			crm_free(new_node);
+			return FALSE;
+		}
+
+		crm_verbose("Creaing node for entry %s/%s", uname, id);
 		new_node->details->id		= id;
 		new_node->details->uname	= uname;
 		new_node->details->type		= node_ping;
 		new_node->details->online	= FALSE;
 		new_node->details->unclean	= FALSE;
 		new_node->details->shutdown	= FALSE;
 		new_node->details->running_rsc	= NULL;
 		new_node->details->agents	= NULL;
-		new_node->details->attrs	= g_hash_table_new(
+		new_node->details->attrs        = g_hash_table_new(
 			g_str_hash, g_str_equal);
-
+		
 		if(safe_str_eq(type, "member")) {
 			new_node->details->type = node_member;
 		}
 
 		add_node_attrs(attrs, new_node);
 		*nodes = g_list_append(*nodes, new_node);    
-
 		crm_verbose("Done with node %s", xmlGetProp(xml_obj, "uname"));
 
 		crm_debug_action(print_node("Added", new_node, FALSE));
 		);
   
 	*nodes = g_list_sort(*nodes, sort_node_weight);
 
 	return TRUE;
 }
 
 gboolean 
 unpack_resources(xmlNodePtr xml_resources,
 		 GListPtr *resources,
 		 GListPtr *actions,
 		 GListPtr *action_cons,
 		 GListPtr all_nodes)
 {
 	crm_verbose("Begining unpack...");
 	xml_child_iter(
 		xml_resources, xml_obj, XML_CIB_TAG_RESOURCE,
 		action_t *action_stop  = NULL;
 		action_t *action_start = NULL;
 		const char *id         = xmlGetProp(xml_obj, XML_ATTR_ID);
 		const char *stopfail   = xmlGetProp(xml_obj, "on_stopfail");
 		const char *restart    = xmlGetProp(xml_obj, "restart_type");
 
 		const char *max_instances      = xmlGetProp(
 			xml_obj, "max_instances");
 		const char *max_node_instances = xmlGetProp(
 			xml_obj, "max_node_instances");
 		const char *max_masters      = xmlGetProp(
 			xml_obj, "max_masters");
 		const char *max_node_masters = xmlGetProp(
 			xml_obj, "max_node_masters");
 
 		const char *version    = xmlGetProp(xml_obj, XML_ATTR_VERSION);
 		resource_t *new_rsc = NULL;
 		const char *priority   = xmlGetProp(
 			xml_obj, XML_CIB_ATTR_PRIORITY);
 
 		crm_verbose("Processing resource...");
 		
 		if(id == NULL) {
 			crm_err("Must specify id tag in <resource>");
 			xml_iter_continue(xml_obj);
 		}
-		new_rsc = crm_malloc(sizeof(resource_t));
+		crm_malloc(new_rsc, sizeof(resource_t));
+
+		if(new_rsc == NULL) {
+			return FALSE;
+		}
+		
 		new_rsc->id		= id;
 		new_rsc->xml		= xml_obj;
-		new_rsc->agent		= crm_malloc(sizeof(lrm_agent_t));
+		crm_malloc(new_rsc->agent, sizeof(lrm_agent_t));
 		new_rsc->agent->class	= xmlGetProp(xml_obj, "class");
 		new_rsc->agent->type	= xmlGetProp(xml_obj, "type");
 		new_rsc->agent->version	= version?version:"0.0";
 
 		new_rsc->priority	    = atoi(priority?priority:"0"); 
 		new_rsc->effective_priority = new_rsc->priority;
 
 		new_rsc->max_instances	    = atoi(
 			max_instances?max_instances:"1"); 
 		new_rsc->max_node_instances = atoi(
 			max_node_instances?max_node_instances:"1"); 
 		new_rsc->max_masters	    = atoi(
 			max_masters?max_masters:"0"); 
 		new_rsc->max_node_masters   = atoi(
 			max_node_masters?max_node_masters:"0"); 
 
 		new_rsc->candidate_colors   = NULL;
 		new_rsc->actions            = NULL;
 		new_rsc->color		= NULL; 
 		new_rsc->runnable	= TRUE; 
 		new_rsc->provisional	= TRUE; 
 		new_rsc->allowed_nodes	= NULL;
 		new_rsc->rsc_cons	= NULL; 
 		new_rsc->node_cons	= NULL; 
 		new_rsc->cur_node	= NULL;
 		
 		if(safe_str_eq(stopfail, "ignore")) {
 			new_rsc->stopfail_type = pesf_ignore;
 		} else if(safe_str_eq(stopfail, "stonith")) {
 			new_rsc->stopfail_type = pesf_stonith;
 		} else {
 			new_rsc->stopfail_type = pesf_block;
 		}
 
 		if(safe_str_eq(restart, "restart")) {
 			new_rsc->restart_type = pe_restart_restart;
 		} else if(safe_str_eq(restart, "recover")) {
 			new_rsc->restart_type = pe_restart_recover;
 		} else {
 			new_rsc->restart_type = pe_restart_ignore;
 		}
 
 		action_stop    = action_new(new_rsc, stop_rsc);
 		*actions       = g_list_append(*actions, action_stop);
 		new_rsc->stop  = action_stop;
 		new_rsc->actions =
 			g_list_append(new_rsc->actions, action_stop);
 
 		action_start   = action_new(new_rsc, start_rsc);
 		*actions       = g_list_append(*actions, action_start);
 		new_rsc->start = action_start;
 		new_rsc->actions =
 			g_list_append(new_rsc->actions, action_start);
 
 		order_new(action_stop,action_start,pecs_startstop,action_cons);
 
 		*resources = g_list_append(*resources, new_rsc);
 	
 		crm_debug_action(print_resource("Added", new_rsc, FALSE));
 		);
 	
 	*resources = g_list_sort(*resources, sort_rsc_priority);
 
 	return TRUE;
 }
 
 
 
 gboolean 
 unpack_constraints(xmlNodePtr xml_constraints,
 		   GListPtr nodes, GListPtr resources,
 		   GListPtr *node_constraints,
 		   GListPtr *action_constraints)
 {
 	crm_verbose("Begining unpack...");
 	xml_child_iter(
 		xml_constraints, xml_obj, NULL,
 
 		const char *id = xmlGetProp(xml_obj, XML_ATTR_ID);
 		if(id == NULL) {
 			crm_err("Constraint <%s...> must have an id",
 				xml_obj->name);
 			xml_iter_continue(xml_obj);
 		}
 
 		crm_verbose("Processing constraint %s %s", xml_obj->name,id);
 		if(safe_str_eq("rsc_order", xml_obj->name)) {
 			unpack_rsc_order(
 				xml_obj, resources, action_constraints);
 
 		} else if(safe_str_eq("rsc_dependancy", xml_obj->name)) {
 			unpack_rsc_dependancy(
 				xml_obj, resources, action_constraints);
 
 		} else if(safe_str_eq("rsc_location", xml_obj->name)) {
 			unpack_rsc_location(
 				xml_obj, resources, nodes, node_constraints);
 
 		} else {
 			crm_err("Unsupported constraint type: %s",
 				xml_obj->name);
 		}
 		);
 
 	return TRUE;
 }
 
 rsc_to_node_t *
 rsc2node_new(const char *id, resource_t *rsc,
 	     double weight, gboolean can, node_t *node,
 	     GListPtr *node_constraints)
 {
 	rsc_to_node_t *new_con = NULL;
 
 	if(rsc == NULL || id == NULL) {
-		crm_err("Invalid constraint %s for rsc=%p)", id, rsc);
+		crm_err("Invalid constraint %s for rsc=%p", id, rsc);
 		return NULL;
 	}
 
-	new_con = (rsc_to_node_t*)crm_malloc(sizeof(rsc_to_node_t));
-	
-	new_con->id           = id;
-	new_con->rsc_lh       = rsc;
-	new_con->node_list_rh = NULL;
-	new_con->can          = can;
-
-	if(can) {
-		new_con->weight = weight;
-	} else {
-		new_con->weight = -1;
-	}
-	
-	if(node != NULL) {
-		new_con->node_list_rh = g_list_append(NULL, node);
+	crm_malloc(new_con, sizeof(rsc_to_node_t));
+	if(new_con != NULL) {
+		new_con->id           = id;
+		new_con->rsc_lh       = rsc;
+		new_con->node_list_rh = NULL;
+		new_con->can          = can;
+		
+		if(can) {
+			new_con->weight = weight;
+		} else {
+			new_con->weight = -1;
+		}
+		
+		if(node != NULL) {
+			new_con->node_list_rh = g_list_append(NULL, node);
+		}
+		
+		*node_constraints = g_list_append(*node_constraints, new_con);
 	}
 	
-	*node_constraints = g_list_append(*node_constraints, new_con);
-
 	return new_con;
 }
 
 
 
 
 /* remove nodes that are down, stopping */
 /* create +ve rsc_to_node constraints between resources and the nodes they are running on */
 /* anything else? */
 gboolean
 unpack_status(xmlNodePtr status,
 	      GListPtr nodes, GListPtr rsc_list,
 	      GListPtr *actions, GListPtr *node_constraints)
 {
 	const char *uname     = NULL;
 
 	xmlNodePtr lrm_rsc    = NULL;
 	xmlNodePtr lrm_agents = NULL;
 	xmlNodePtr attrs      = NULL;
 	node_t    *this_node  = NULL;
 	
 	crm_verbose("Begining unpack");
 	xml_child_iter(
 		status, node_state, XML_CIB_TAG_STATE,
 
 /*		id         = xmlGetProp(node_state, XML_ATTR_ID); */
 		uname      = xmlGetProp(node_state,    XML_ATTR_UNAME);
 		attrs      = find_xml_node(node_state, "attributes");
 		lrm_rsc    = find_xml_node(node_state, XML_CIB_TAG_LRM);
 		lrm_agents = find_xml_node(lrm_rsc,    "lrm_agents");
 		lrm_rsc    = find_xml_node(lrm_rsc,    XML_LRM_TAG_RESOURCES);
 		lrm_rsc    = find_xml_node(lrm_rsc,    "lrm_resource");
 
 		crm_verbose("Processing node %s", uname);
 		this_node = pe_find_node(nodes, uname);
 
 		if(uname == NULL) {
 			/* error */
 			xml_iter_continue(node_state);
 
 		} else if(this_node == NULL) {
 			crm_err("Node %s in status section no longer exists",
 				uname);
 			xml_iter_continue(node_state);
 		}
 		
 		crm_verbose("Adding runtime node attrs");
 		add_node_attrs(attrs, this_node);
 
 		crm_verbose("determining node state");
 		determine_online_status(node_state, this_node);
 
 		crm_verbose("Processing lrm resource entries");
 		unpack_lrm_rsc_state(this_node, lrm_rsc, rsc_list, nodes,
 				     actions, node_constraints);
 
 		crm_verbose("Processing lrm agents");
 		unpack_lrm_agents(this_node, lrm_agents);
 
 		);
 
 	return TRUE;
 	
 }
 
 gboolean
 determine_online_status(xmlNodePtr node_state, node_t *this_node)
 {
 	const char *uname      = xmlGetProp(node_state,XML_ATTR_UNAME);
 	const char *state      = xmlGetProp(node_state,XML_NODE_ATTR_STATE);
 	const char *exp_state  = xmlGetProp(node_state,XML_CIB_ATTR_EXPSTATE);
 	const char *join_state = xmlGetProp(node_state,XML_CIB_ATTR_JOINSTATE);
 	const char *crm_state  = xmlGetProp(node_state,XML_CIB_ATTR_CRMDSTATE);
 	const char *ccm_state  = xmlGetProp(node_state,XML_CIB_ATTR_INCCM);
 	const char *shutdown   = xmlGetProp(node_state,XML_CIB_ATTR_SHUTDOWN);
 	const char *unclean    = NULL;/*xmlGetProp(node_state,XML_CIB_ATTR_STONITH); */
 	
 	if(safe_str_eq(join_state, CRMD_JOINSTATE_MEMBER)
 	   && safe_str_eq(ccm_state, XML_BOOLEAN_YES)
 	   && safe_str_eq(crm_state, ONLINESTATUS)
 	   && shutdown == NULL) {
 		this_node->details->online = TRUE;
 
 	} else {
 		crm_verbose("remove");
 		/* remove node from contention */
 		this_node->weight = -1;
 		this_node->fixed = TRUE;
 
 		crm_verbose("state %s, expected %s, shutdown %s",
 			    state, exp_state, shutdown);
 
 		if(unclean != NULL) {
 			this_node->details->unclean = TRUE;
 				
 		} else if(shutdown != NULL) {
 			this_node->details->shutdown = TRUE;
 
 		} else if(is_node_unclean(node_state)) {
 			/* report and or take remedial action */
 			this_node->details->unclean = TRUE;
 		}
 
 		if(this_node->details->unclean) {
 			crm_verbose("Node %s is due for STONITH", uname);
 		}
 
 		if(this_node->details->shutdown) {
 			crm_verbose("Node %s is due for shutdown", uname);
 		}
 	}
 	return TRUE;
 }
 
 gboolean
 is_node_unclean(xmlNodePtr node_state)
 {
 	const char *state      = xmlGetProp(node_state,XML_NODE_ATTR_STATE);
 	const char *exp_state  = xmlGetProp(node_state,XML_CIB_ATTR_EXPSTATE);
 	const char *join_state = xmlGetProp(node_state,XML_CIB_ATTR_JOINSTATE);
 	const char *crm_state  = xmlGetProp(node_state,XML_CIB_ATTR_CRMDSTATE);
 	const char *ccm_state  = xmlGetProp(node_state,XML_CIB_ATTR_INCCM);
 
 	if(safe_str_eq(exp_state, CRMD_STATE_INACTIVE)) {
 		return FALSE;
 
 	/* do an actual calculation once STONITH is available */
 
 	/* } else if(...) { */
 	}
 
 	/* for now... */
 	if(0) {
 		state = NULL;
 		join_state = NULL;
 		crm_state = NULL;
 		ccm_state = NULL;
 	}
 	
 	return FALSE;
 }
 
 gboolean
 unpack_lrm_agents(node_t *node, xmlNodePtr agent_list)
 {
 	/* if the agent is not listed, remove the node from
 	 * the resource's list of allowed_nodes
 	 */
 	lrm_agent_t *agent   = NULL;
 	const char *version  = NULL;
 
 	if(agent_list == NULL) {
 		return FALSE;
 	}
 
 	xml_child_iter(
 		agent_list, xml_agent, XML_LRM_TAG_AGENT,
 
-		agent = (lrm_agent_t*)crm_malloc(sizeof(lrm_agent_t));
-		agent->class = xmlGetProp(xml_agent, "class");
-		agent->type  = xmlGetProp(xml_agent, "type");
-		version      = xmlGetProp(xml_agent, "version");
-
+		crm_malloc(agent, sizeof(lrm_agent_t));
+		if(agent == NULL) {
+			continue;
+		}
+		
+		agent->class   = xmlGetProp(xml_agent, "class");
+		agent->type    = xmlGetProp(xml_agent, "type");
+		version        = xmlGetProp(xml_agent, "version");
 		agent->version = version?version:"0.0";
 
 		crm_trace("Adding agent %s/%s v%s to node %s",
 			  agent->class,
 			  agent->type,
 			  agent->version,
 			  node->details->uname);
 			  
 		node->details->agents = g_list_append(
 			node->details->agents, agent);
 		);
 	
 	return TRUE;
 }
 
 
 gboolean
 unpack_lrm_rsc_state(node_t *node, xmlNodePtr lrm_rsc,
 		     GListPtr rsc_list, GListPtr nodes,
 		     GListPtr *actions, GListPtr *node_constraints)
 {
 	xmlNodePtr rsc_entry  = NULL;
 	
 	const char *rsc_id    = NULL;
 	const char *node_id   = NULL;
 	const char *rsc_state = NULL;
 	const char *op_status = NULL;
 	const char *last_rc   = NULL;
 	const char *last_op   = NULL;
 	resource_t *rsc_lh    = NULL;
 	op_status_t  action_status_i = LRM_OP_ERROR;
 	xmlNodePtr stonith_list = NULL;
 
 	while(lrm_rsc != NULL) {
 		rsc_entry = lrm_rsc;
 		lrm_rsc   = lrm_rsc->next;
 		
 		rsc_id    = xmlGetProp(rsc_entry, XML_ATTR_ID);
 		node_id   = xmlGetProp(rsc_entry, XML_LRM_ATTR_TARGET);
 		rsc_state = xmlGetProp(rsc_entry, XML_LRM_ATTR_RSCSTATE);
 		op_status = xmlGetProp(rsc_entry, XML_LRM_ATTR_OPSTATUS);
 		last_rc   = xmlGetProp(rsc_entry, XML_LRM_ATTR_RC);
 		last_op   = xmlGetProp(rsc_entry, XML_LRM_ATTR_LASTOP);
 		
 		rsc_lh    = pe_find_resource(rsc_list, rsc_id);
 
 		crm_verbose("[%s] Processing %s on %s (%s)",
 			    rsc_entry->name, rsc_id, node_id, rsc_state);
 
 		if(rsc_lh == NULL) {
 			crm_err("Could not find a match for resource"
 				" %s in %s's status section",
 				rsc_id, node_id);
 			continue;
 		} else if(op_status == NULL) {
 			crm_err("Invalid resource status entry for %s in %s",
 				rsc_id, node_id);
 			continue;
 		}
 
 		xml_child_iter(
 			stonith_list, rsc_entry, "can_fence",
 
 			node_t *node = pe_find_node(
 				nodes, xmlGetProp(stonith_list, "id"));
 
 			rsc_lh->fencable_nodes = g_list_append(
 				rsc_lh->fencable_nodes, node_copy(node));
 			);
 		
 		action_status_i = atoi(op_status);
 
 		if(action_status_i == -1) {
 			/*
 			 * TODO: this needs more thought
 			 * Some cases:
 			 * - PE reinvoked with pending action that will succeed
 			 * - PE reinvoked with pending action that will fail
 			 * - After DC election
 			 * - After startup
 			 *
 			 * pending start - required start
 			 * pending stop  - required stop
 			 * pending <any> on unavailable node - stonith
 			 *
 			 * For now this should do
 			 */
 			if(safe_str_eq(last_op, "stop")) {
 				/* map this to a timeout so it is re-issued */
 				action_status_i = LRM_OP_TIMEOUT;
 			} else {
 				/* map this to a "done" so it is not marked
 				 * as failed, then make sure it is re-issued
 				 */
 				action_status_i = LRM_OP_DONE;
 				rsc_lh->start->optional = FALSE;
 			}
 		}
 
 		switch(action_status_i) {
 			case LRM_OP_DONE:
 				unpack_healthy_resource(
 					node_constraints, actions,
 					rsc_entry, rsc_lh,node);
 				break;
 			case LRM_OP_ERROR:
 			case LRM_OP_TIMEOUT:
 			case LRM_OP_NOTSUPPORTED:
 				unpack_failed_resource(
 					node_constraints, actions, 
 					rsc_entry, rsc_lh,node);
 				break;
 			case LRM_OP_CANCELLED:
 				/* do nothing?? */
 				crm_warn("Dont know what to do for cancelled ops yet");
 				break;
 		}
 	}
 	return TRUE;
 }
 
 gboolean
 unpack_failed_resource(GListPtr *node_constraints, GListPtr *actions,
 		       xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node)
 {
 	const char *last_op  = xmlGetProp(rsc_entry, "last_op");
 
 	crm_debug("Unpacking failed action %s on %s", last_op, rsc_lh->id);
 	
 	if(safe_str_neq(last_op, "stop")) {
 		/* not running */
 		/* do not run the resource here again */
 		rsc2node_new("dont_run_generate",
 			     rsc_lh, -1.0, FALSE, node, node_constraints);
 
 		/* schedule a stop here just in case? */
 		action_new(rsc_lh, stop_rsc);
 		
 		return TRUE;
 		
 	} 
 
 	switch(rsc_lh->stopfail_type) {
 		case pesf_stonith:
 			/* remedial action:
 			 *   shutdown (so all other resources are
 			 *   stopped gracefully) and then STONITH node
 			 */
 			
 			if(stonith_enabled == FALSE) {
 				crm_err("STONITH is not enabled in this cluster but is required for resource %s after a failed stop", rsc_lh->id);
 				rsc_lh->start->runnable = FALSE;
 				break;
 			}
 			
 			/* treat it as if it is still running */
 			rsc_lh->cur_node = node;
 			node->details->running_rsc = g_list_append(
 				node->details->running_rsc, rsc_lh);
 			
 			if(node->details->online) {
 				node->details->shutdown = TRUE;
 			}
 			node->details->unclean  = TRUE;
 			break;
 			
 		case pesf_block:
 			crm_warn("SHARED RESOURCE %s WILL REMAIN BLOCKED"
 				 " UNTIL CLEANED UP MANUALLY ON NODE %s",
 				 rsc_lh->id, node->details->uname);
 			rsc_lh->start->runnable = FALSE;
 			break;
 			
 		case pesf_ignore:
 			crm_warn("SHARED RESOURCE %s IS NOT PROTECTED",
 				 rsc_lh->id);
 			/* do not run the resource here again */
 			rsc2node_new(
 				"dont_run_generate",
 				rsc_lh, -1.0, FALSE, node, node_constraints);
 
 			break;
 	}
 		
 	return TRUE;
 }
 
 gboolean
 unpack_healthy_resource(GListPtr *node_constraints, GListPtr *actions,
 			xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node)
 {
 	const char *last_op  = xmlGetProp(rsc_entry, "last_op");
 
 	crm_debug("Unpacking healthy action %s on %s", last_op, rsc_lh->id);
 
 	if(safe_str_neq(last_op, "stop")) {
 
 		if(rsc_lh->cur_node != NULL) {
 			crm_err("Resource %s running on multiple nodes %s, %s",
 				rsc_lh->id,
 				rsc_lh->cur_node->details->uname,
 				node->details->uname);
 			/* TODO: some recovery action!! */
 			/* like force a stop on the second node? */
 			return FALSE;
 			
 		} else {
 			/* create the link between this node and the rsc */
 			crm_verbose("Setting cur_node = %s for rsc = %s",
 				    node->details->uname, rsc_lh->id);
 			
 			rsc_lh->cur_node = node;
 			node->details->running_rsc = g_list_append(
 				node->details->running_rsc, rsc_lh);
 		}
 	}
 
 	return TRUE;
 }
 
 gboolean
 rsc2rsc_new(const char *id, enum con_strength strength, enum rsc_con_type type,
 	    resource_t *rsc_lh, resource_t *rsc_rh)
 {
 	rsc_to_rsc_t *new_con      = NULL;
 	rsc_to_rsc_t *inverted_con = NULL;
 
 	if(rsc_lh == NULL || rsc_rh == NULL){
 		/* error */
 		return FALSE;
 	}
 
-	new_con      = crm_malloc(sizeof(rsc_to_rsc_t));
-
-	new_con->id       = id;
-	new_con->rsc_lh   = rsc_lh;
-	new_con->rsc_rh   = rsc_rh;
-	new_con->strength = strength;
-	new_con->variant  = type;
-	
-	inverted_con = invert_constraint(new_con);
-
-	rsc_lh->rsc_cons = g_list_insert_sorted(
-		rsc_lh->rsc_cons, new_con, sort_cons_strength);
+	crm_malloc(new_con, sizeof(rsc_to_rsc_t));
+	if(new_con != NULL) {
+		new_con->id       = id;
+		new_con->rsc_lh   = rsc_lh;
+		new_con->rsc_rh   = rsc_rh;
+		new_con->strength = strength;
+		new_con->variant  = type;
+		
+		inverted_con = invert_constraint(new_con);
+		
+		rsc_lh->rsc_cons = g_list_insert_sorted(
+			rsc_lh->rsc_cons, new_con, sort_cons_strength);
+		
+		rsc_rh->rsc_cons = g_list_insert_sorted(
+			rsc_rh->rsc_cons, inverted_con, sort_cons_strength);
+	} else {
+		return FALSE;
+	}
 	
-	rsc_rh->rsc_cons = g_list_insert_sorted(
-		rsc_rh->rsc_cons, inverted_con, sort_cons_strength);
-
 	return TRUE;
 }
 
 gboolean
 order_new(action_t *before, action_t *after, enum con_strength strength,
 	  GListPtr *action_constraints)
 {
 	order_constraint_t *order = NULL;
 
 	if(before == NULL || after == NULL || action_constraints == NULL){
 		crm_err("Invalid inputs b=%p, a=%p l=%p",
 			before, after, action_constraints);
 		return FALSE;
 	}
 
-	order = (order_constraint_t*)crm_malloc(sizeof(order_constraint_t));
-	
-	order->id        = order_id++;
-	order->strength  = strength;
-	order->lh_action = before;
-	order->rh_action = after;
-	
-	*action_constraints = g_list_append(*action_constraints, order);
+	crm_malloc(order, sizeof(order_constraint_t));
 
+	if(order != NULL) {
+		order->id        = order_id++;
+		order->strength  = strength;
+		order->lh_action = before;
+		order->rh_action = after;
+		
+		*action_constraints = g_list_append(
+			*action_constraints, order);
+	}
+	
 	return TRUE;
 }
 
 gboolean
 unpack_rsc_dependancy(xmlNodePtr xml_obj,
 		  GListPtr rsc_list,
 		  GListPtr *action_constraints)
 {
 	enum con_strength strength_e = pecs_ignore;
 
 	const char *id_lh    = xmlGetProp(xml_obj, "from");
 	const char *id       = xmlGetProp(xml_obj, XML_ATTR_ID);
 	const char *id_rh    = xmlGetProp(xml_obj, "to");
 	const char *type = xmlGetProp(xml_obj, XML_ATTR_TYPE);
 
 	resource_t *rsc_lh   = pe_find_resource(rsc_list, id_lh);
 	resource_t *rsc_rh   = pe_find_resource(rsc_list, id_rh);
  
 #if 1
 	/* relates to the ifdef below */
 	action_t *before, *after;
 #endif
 	if(rsc_lh == NULL) {
 		crm_err("No resource (con=%s, rsc=%s)", id, id_lh);
 		return FALSE;
 	} else if(rsc_rh == NULL) {
 		crm_err("No resource (con=%s, rsc=%s)", id, id_rh);
 		return FALSE;
 	}
 	
 	if(safe_str_eq(type, XML_STRENGTH_VAL_MUST)) {
 		strength_e = pecs_must;
 		
 	} else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULD)) {
 		crm_err("Type %s is no longer supported", type);
 		strength_e = pecs_must;
 		
 	} else if(safe_str_eq(type, XML_STRENGTH_VAL_SHOULDNOT)) {
 		crm_err("Type %s is no longer supported", type);
 		strength_e = pecs_must_not;
 		
 	} else if(safe_str_eq(type, XML_STRENGTH_VAL_MUSTNOT)) {
 		strength_e = pecs_must_not;
 
 	} else {
 		crm_err("Unknown value for %s: %s", "type", type);
 		return FALSE;
 	}
 
 	/* make sure the lower priority resource stops before
 	 *  the higher is started, otherwise they may be both running
 	 *  on the same node when the higher is replacing the lower
 	 */
 	if(rsc_lh->priority >= rsc_rh->priority) {
 		before = rsc_rh->stop;
 		after  = rsc_lh->start;
 	} else {
 		before = rsc_lh->stop;
 		after  = rsc_rh->start;
 	}
 	
 	order_new(before, after, strength_e, action_constraints);
 
 	/* make sure the lower priority resource starts after
 	 *  the higher is started
 	 */
 	if(rsc_lh->priority < rsc_rh->priority) {
 		before = rsc_rh->start;
 		after  = rsc_lh->start;
 	} else {
 		before = rsc_lh->start;
 		after  = rsc_rh->start;
 	}
 	order_new(before, after, strength_e,action_constraints);
 	
 	return rsc2rsc_new(id, strength_e, same_node, rsc_lh, rsc_rh);
 }
 
 gboolean
 unpack_rsc_order(xmlNodePtr xml_obj,
 		  GListPtr rsc_list,
 		  GListPtr *action_constraints)
 {
 	enum con_strength strength_e = pecs_ignore;
 
 	const char *id       = xmlGetProp(xml_obj, XML_ATTR_ID);
 	const char *id_lh    = xmlGetProp(xml_obj, "from");
 	const char *id_rh    = xmlGetProp(xml_obj, "to");
 	const char *type     = xmlGetProp(xml_obj, XML_ATTR_TYPE);
 
 	resource_t *rsc_lh   = pe_find_resource(rsc_list, id_lh);
 	resource_t *rsc_rh   = pe_find_resource(rsc_list, id_rh);
 
 	if(xml_obj == NULL) {
 		crm_err("No constraint object to process.");
 		return FALSE;
 
 	} else if(id == NULL) {
 		crm_err("%s constraint must have an id", xml_obj->name);
 		return FALSE;
 		
 	} else if(rsc_lh == NULL || rsc_rh == NULL) {
 		crm_err("Constraint %s needs two sides lh: %p rh: %p"
 			" (NULL indicates missing side)",
 			id, rsc_lh, rsc_rh);
 		return FALSE;
 	
 	} else if(safe_str_eq(type, "after")) {
 		rsc2rsc_new(id, strength_e, start_after, rsc_lh, rsc_rh);
 		order_new(rsc_rh->stop, rsc_lh->stop, pecs_must,
 			  action_constraints);
 		order_new(rsc_lh->start, rsc_rh->start, pecs_must,
 			  action_constraints);
 	} else {
 		rsc2rsc_new(id, strength_e, start_before, rsc_lh, rsc_rh);
 		order_new(rsc_lh->stop, rsc_rh->stop, pecs_must,
 			  action_constraints);
 		order_new(rsc_rh->start, rsc_lh->start, pecs_must,
 			  action_constraints);
 	}
 	return TRUE;
 }
 
 
 /* do NOT free the nodes returned here */
 GListPtr
 match_attrs(const char *attr, const char *op, const char *value,
 	    const char *type, GListPtr node_list)
 {
 	int lpc = 0, lpc2 = 0;
 	GListPtr result = NULL;
 	
 	if(attr == NULL || op == NULL) {
 		crm_err("Invlaid attribute or operation in expression"
-			" (\'%s\' \'%s\' \'%s\')", attr, op, value);
+			" (\'%s\' \'%s\' \'%s\')",
+			crm_str(attr), crm_str(op), crm_str(value));
 		return NULL;
 	}
 	
 
 	slist_iter(
 		node, node_t, node_list, lpc,
 		gboolean accept = FALSE;
 		
 		int cmp = 0;
 		const char *h_val = (const char*)g_hash_table_lookup(
 			node->details->attrs, attr);
 
 		if(value != NULL && h_val != NULL) {
 			if(type == NULL || (safe_str_eq(type, "string"))) {
 				cmp = strcmp(h_val, value);
 
 			} else if(safe_str_eq(type, "number")) {
 				float h_val_f = atof(h_val);
 				float value_f = atof(value);
 
 				if(h_val_f < value_f) {
 					cmp = -1;
 				} else if(h_val_f > value_f)  {
 					cmp = 1;
 				} else {
 					cmp = 0;
 				}
 				
 			} else if(safe_str_eq(type, "version")) {
 				cmp = compare_version(h_val, value);
 
 			}
 			
 		} else if(value == NULL && h_val == NULL) {
 			cmp = 0;
 		} else if(value == NULL) {
 			cmp = 1;
 		} else {
 			cmp = -1;
 		}
 		
 		if(safe_str_eq(op, "exists")) {
 			if(h_val != NULL) accept = TRUE;	
 
 		} else if(safe_str_eq(op, "notexists")) {
 			if(h_val == NULL) accept = TRUE;
 
 		} else if(safe_str_eq(op, "running")) {
 			GListPtr rsc_list = node->details->running_rsc;
 			slist_iter(
 				rsc, resource_t, rsc_list, lpc2,
 				if(safe_str_eq(rsc->id, attr)) {
 					accept = TRUE;
 				}
 				);
 
 		} else if(safe_str_eq(op, "not_running")) {
 			GListPtr rsc_list = node->details->running_rsc;
 			accept = TRUE;
 			slist_iter(
 				rsc, resource_t, rsc_list, lpc2,
 				if(safe_str_eq(rsc->id, attr)) {
 					accept = FALSE;
 					break;
 				}
 				);
 
 		} else if(safe_str_eq(op, "eq")) {
 			if((h_val == value) || cmp == 0)
 				accept = TRUE;
 
 		} else if(safe_str_eq(op, "ne")) {
 			if((h_val == NULL && value != NULL)
 			   || (h_val != NULL && value == NULL)
 			   || cmp != 0)
 				accept = TRUE;
 
 		} else if(value == NULL || h_val == NULL) {
 			/* the comparision is meaningless from this point on */
 			accept = FALSE;
 			
 		} else if(safe_str_eq(op, "lt")) {
 			if(cmp < 0) accept = TRUE;
 			
 		} else if(safe_str_eq(op, "lte")) {
 			if(cmp <= 0) accept = TRUE;
 			
 		} else if(safe_str_eq(op, "gt")) {
 			if(cmp > 0) accept = TRUE;
 			
 		} else if(safe_str_eq(op, "gte")) {
 			if(cmp >= 0) accept = TRUE;
 			
 		}
 		
 		if(accept) {
 			crm_trace("node %s matched", node->details->uname);
 			result = g_list_append(result, node);
 		} else {
 			crm_trace("node %s did not match", node->details->uname);
 		}		   
 		);
 	
 	return result;
 }
 
 gboolean
 add_node_attrs(xmlNodePtr attrs, node_t *node)
 {
 	const char *name  = NULL;
 	const char *value = NULL;
 	
 	while(attrs != NULL){
 		name  = xmlGetProp(attrs, XML_NVPAIR_ATTR_NAME);
 		value = xmlGetProp(attrs, XML_NVPAIR_ATTR_VALUE);
 			
 		if(name != NULL
 		   && value != NULL
 		   && safe_val(NULL, node, details) != NULL) {
 			crm_verbose("Adding %s => %s", name, value);
 
 			/* this is frustrating... no way to pass in const
 			 *  keys or values yet docs say:
 			 *   Note: If keys and/or values are dynamically
 			 *   allocated, you should free them first.
 			 */
 			g_hash_table_insert(node->details->attrs,
 					    crm_strdup(name),
 					    crm_strdup(value));
 		}
 		attrs = attrs->next;
 	}	
  	g_hash_table_insert(node->details->attrs,
 			    crm_strdup("uname"),
 			    crm_strdup(node->details->uname));
  	g_hash_table_insert(node->details->attrs,
 			    crm_strdup("id"),
 			    crm_strdup(node->details->id));
 	return TRUE;
 }
 
 
 
 gboolean
-unpack_rsc_location(xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr node_list,
-		    GListPtr *node_constraints)
+unpack_rsc_location(
+	xmlNodePtr xml_obj,
+	GListPtr rsc_list, GListPtr node_list, GListPtr *node_constraints)
 {
 /*
 
   <constraints>
      <rsc_location rsc="Filesystem-whatever-1" timestamp="..." lifetime="...">
      	<rule score="+50.0" result="can">
 <!ATTLIST node_expression
 	  id         CDATA #REQUIRED
 	  attribute  CDATA #REQUIRED
 	  operation  (lt|gt|lte|gte|eq|ne|exists|notexists)
 	  value      CDATA #IMPLIED
 	  type	     (integer|string|version)    'string'>
 
 	</rule>
      	<rule score="+500.0">
        		<node_expression match="cpu:50GHz" />
 	</rule>
      	<rule result="cannot">
        		<node_expression not_match="san"/>
 	</rule>
 ...
 
    Translation:
 
    Further translation:
        
 */
 	gboolean were_rules = FALSE;
 	const char *id_lh   = xmlGetProp(xml_obj, "rsc");
 	const char *id      = xmlGetProp(xml_obj, XML_ATTR_ID);
 	resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
 
 	if(rsc_lh == NULL) {
 		crm_err("No resource (con=%s, rsc=%s)",
 		       id, id_lh);
 		return FALSE;
 	}
 			
 	xml_child_iter(
 		xml_obj, rule, "rule",
 
 		gboolean first_expr = TRUE;
 		gboolean can_run    = FALSE;
 		gboolean do_and     = TRUE;
 
 		const char *rule_id = xmlGetProp(rule, XML_ATTR_ID);
 		const char *score   = xmlGetProp(rule, "score");
 		const char *result  = xmlGetProp(rule, "result");
 		const char *boolean = xmlGetProp(rule, "boolean_op");
 		GListPtr match_L    = NULL;
 		GListPtr old_list   = NULL;
 		float score_f       = atof(score?score:"0.0");
 
 		rsc_to_node_t *new_con = NULL;
 
 		were_rules = TRUE;
 		
 		if(safe_str_eq(boolean, "or")) {
 			do_and = FALSE;
 		}
 
 		if(result == NULL || (safe_str_eq(result, "can"))) {
 			can_run = TRUE;
 		}
 
 		new_con = rsc2node_new(rule_id, rsc_lh, score_f,
 				       can_run, NULL, node_constraints);
 
 		if(new_con == NULL) {
-			crm_err("couldnt create constraint %s", rule_id);
 			continue;
 		}
 		
-		/* feels like a hack */
-		if(rule->children == NULL && can_run) {
-			new_con->node_list_rh = node_list_dup(node_list,FALSE);
-		}
-
+		gboolean rule_has_expressions = FALSE;
 		xml_child_iter(
 			rule, expr, "expression",
 
 			const char *attr  = xmlGetProp(expr, "attribute");
 			const char *op    = xmlGetProp(expr, "operation");
 			const char *value = xmlGetProp(expr, "value");
 			const char *type  = xmlGetProp(expr, "type");
-
+			
+			rule_has_expressions = TRUE;
 			crm_trace("processing expression: %s",
 				  xmlGetProp(expr, "id"));
 
 			match_L = match_attrs(
 				attr, op, value, type, node_list);
 			
 			if(first_expr) {
 				new_con->node_list_rh =	node_list_dup(
 					match_L, FALSE);
 				first_expr = FALSE;
 				xml_iter_continue(expr);
 			}
 
 			old_list = new_con->node_list_rh;
 
 			if(do_and) {
 				crm_trace("do_and");
 				
 				new_con->node_list_rh = node_list_and(
 					old_list, match_L, FALSE);
 			} else {
 				crm_trace("do_or");
 				
 				new_con->node_list_rh = node_list_or(
 					old_list, match_L, FALSE);
 			}
 			pe_free_shallow_adv(match_L,  FALSE);
 			pe_free_shallow_adv(old_list, TRUE);
 			);
+
+		if(rule_has_expressions == FALSE) {
+			/* feels like a hack */
+			crm_debug("Rule %s had no expressions,"
+				  " adding all nodes", xmlGetProp(rule, "id"));
+			
+			new_con->node_list_rh = node_list_dup(node_list,FALSE);
+		}
 		
 		if(new_con->node_list_rh == NULL) {
 			crm_warn("No matching nodes for constraint/rule %s/%s",
 				 id, xmlGetProp(rule, "id"));
 		}
+		
 		crm_debug_action(print_rsc_to_node("Added", new_con, FALSE));
 		);
 
 	if(were_rules == FALSE) {
 		crm_err("no rules for constraint %s", id);
 	}
 
 	
 	return TRUE;
 }
 
diff --git a/crm/pengine/utils.c b/crm/pengine/utils.c
index 135a2c2330..37b43efafb 100644
--- a/crm/pengine/utils.c
+++ b/crm/pengine/utils.c
@@ -1,1053 +1,1091 @@
-/* $Id: utils.c,v 1.40 2004/09/14 05:54:43 andrew Exp $ */
+/* $Id: utils.c,v 1.41 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <portability.h>
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/util.h>
 
 #include <glib.h>
 
 #include <pengine.h>
 #include <pe_utils.h>
 
 int action_id = 1;
 
 void print_str_str(gpointer key, gpointer value, gpointer user_data);
 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
 gboolean node_merge_weights(node_t *node, node_t *with);
 
 /* only for rsc_to_rsc constraints */
 rsc_to_rsc_t *
 invert_constraint(rsc_to_rsc_t *constraint) 
 {
 	rsc_to_rsc_t *inverted_con = NULL;
 
 	crm_verbose("Inverting constraint");
-	inverted_con = crm_malloc(sizeof(rsc_to_rsc_t));
+	if(constraint == NULL) {
+		crm_err("Cannot invert NULL constraint");
+		return NULL;
+	}
 
+	crm_malloc(inverted_con, sizeof(rsc_to_rsc_t));
+
+	if(inverted_con == NULL) {
+		return NULL;
+	}
+	
 	inverted_con->id = crm_strdup(constraint->id);
 	inverted_con->strength = constraint->strength;
 
 	/* swap the direction */
 	inverted_con->rsc_lh = constraint->rsc_rh;
 	inverted_con->rsc_rh = constraint->rsc_lh;
 
 	switch(constraint->variant) {
 		case same_node:
 			inverted_con->variant = same_node;
 			break;
 		case start_before:
 			inverted_con->variant = start_after;
 			break;
 		case start_after:
 			inverted_con->variant = start_before;
 			break;
 	}
 	
 	crm_debug_action(
 		print_rsc_to_rsc("Inverted constraint", inverted_con, FALSE));
 	
 	return inverted_con;
 }
 
 
 /* are the contents of list1 and list2 equal 
  * nodes with weight < 0 are ignored if filter == TRUE
  *
  * slow but linear
  *
  */
 gboolean
 node_list_eq(GListPtr list1, GListPtr list2, gboolean filter)
 {
 	int lpc;
 	
 	node_t *other_node;
 
 	GListPtr lhs = list1;
 	GListPtr rhs = list2;
 	
 	slist_iter(
 		node, node_t, lhs, lpc,
 
 		if(node == NULL || (filter && node->weight < 0)) {
 			continue;
 		}
 
 		other_node = (node_t*)
 			pe_find_node(rhs, node->details->uname);
 
 		if(other_node == NULL || other_node->weight < 0) {
 			return FALSE;
 		}
 		);
 	
 	lhs = list2;
 	rhs = list1;
 
 	slist_iter(
 		node, node_t, lhs, lpc,
 
 		if(node == NULL || (filter && node->weight < 0)) {
 			continue;
 		}
 
 		other_node = (node_t*)
 			pe_find_node(rhs, node->details->uname);
 
 		if(other_node == NULL || other_node->weight < 0) {
 			return FALSE;
 		}
 		);
   
 	return TRUE;
 }
 
 /* the intersection of list1 and list2 
  */
 GListPtr
 node_list_and(GListPtr list1, GListPtr list2, gboolean filter)
 {
 	GListPtr result = NULL;
 	int lpc = 0;
 
 	for(lpc = 0; lpc < g_list_length(list1); lpc++) {
 		node_t *node = (node_t*)g_list_nth_data(list1, lpc);
 		node_t *new_node = node_copy(node);
 		node_t *other_node = pe_find_node(list2, node->details->uname);
 
 		if(node_merge_weights(new_node, other_node) == FALSE) {
 			crm_free(new_node);
 
 		} else if(filter && new_node->weight < 0) {
 			crm_free(new_node);
 
 		} else {
 			result = g_list_append(result, new_node);
 		}
 	}
 
 	return result;
 }
 
 
 gboolean
 node_merge_weights(node_t *node, node_t *with)
 {
 	if(node == NULL || with == NULL) {
 		return FALSE;
 	} else if(node->weight < 0 || with->weight < 0) {
 		node->weight = -1;
 	} else if(node->weight < with->weight) {
 		node->weight = with->weight;
 	}
 	return TRUE;
 }
 
 
 /* list1 - list2 */
 GListPtr
 node_list_minus(GListPtr list1, GListPtr list2, gboolean filter)
 {
 	GListPtr result = NULL;
 	int lpc = 0;
 
 	slist_iter(
 		node, node_t, list1, lpc,
 		node_t *other_node = pe_find_node(list2, node->details->uname);
 		node_t *new_node = NULL;
 		
 		if(node == NULL || other_node != NULL
 		   || (filter && node->weight < 0)) {
 			continue;
 			
 		}
 		new_node = node_copy(node);
 		result = g_list_append(result, new_node);
 		);
   
 	crm_verbose("Minus result len: %d", g_list_length(result));
 
 	return result;
 }
 
 /* list1 + list2 - (intersection of list1 and list2) */
 GListPtr
 node_list_xor(GListPtr list1, GListPtr list2, gboolean filter)
 {
 	GListPtr result = NULL;
 	int lpc = 0;
 	
 	slist_iter(
 		node, node_t, list1, lpc,
 		node_t *new_node = NULL;
 		node_t *other_node = (node_t*)
 			pe_find_node(list2, node->details->uname);
 
 		if(node == NULL || other_node != NULL
 		   || (filter && node->weight < 0)) {
 			continue;
 		}
 		new_node = node_copy(node);
 		result = g_list_append(result, new_node);
 		);
 	
  
 	slist_iter(
 		node, node_t, list2, lpc,
 		node_t *new_node = NULL;
 		node_t *other_node = (node_t*)
 			pe_find_node(list1, node->details->uname);
 
 		if(node == NULL || other_node != NULL
 		   || (filter && node->weight < 0)) {
 			continue;
 		}
 		new_node = node_copy(node);
 		result = g_list_append(result, new_node);
 		);
   
 	crm_verbose("Xor result len: %d", g_list_length(result));
 	return result;
 }
 
 GListPtr
 node_list_or(GListPtr list1, GListPtr list2, gboolean filter)
 {
 	node_t *other_node = NULL;
 	GListPtr result = NULL;
 	int lpc = 0;
 
 	result = node_list_dup(list1, filter);
 
 	slist_iter(
 		node, node_t, list2, lpc,
 
 		if(node == NULL) {
 			continue;
 		}
 
 		other_node = (node_t*)pe_find_node(
 			result, node->details->uname);
 		
 		if(other_node != NULL) {
 			node_merge_weights(other_node, node);
 
 			if(filter && node->weight < 0) {
 				/* TODO: remove and free other_node */
 			}
 			
 		} else if(filter && node->weight < 0) {
 				  
 		} else {
 			node_t *new_node = node_copy(node);
 			result = g_list_append(result, new_node);
 		}
 		);
 
 	return result;
 }
 
 GListPtr 
 node_list_dup(GListPtr list1, gboolean filter)
 {
 	GListPtr result = NULL;
 	int lpc = 0;
 	slist_iter(
 		this_node, node_t, list1, lpc,
 		node_t *new_node = NULL;
 		if(filter && this_node->weight < 0) {
 			continue;
 		}
 		
 		new_node = node_copy(this_node);
 		if(new_node != NULL) {
 			result = g_list_append(result, new_node);
 		}
 		);
 
 	return result;
 }
 
 node_t *
 node_copy(node_t *this_node) 
 {
 	node_t *new_node  = NULL;
 
 	if(this_node == NULL) {
-		print_node("Failed copy of", this_node, TRUE);
+		crm_err("Failed copy of <null> node.");
 		return NULL;
 	}
-	new_node  = (node_t*)crm_malloc(sizeof(node_t));
-	crm_trace("copying %p (%s) to %p", this_node, this_node->details->uname, new_node);
+	crm_malloc(new_node, sizeof(node_t));
+
+	if(new_node == NULL) {
+		return NULL;
+	}
+	
+	crm_trace("Copying %p (%s) to %p",
+		  this_node, this_node->details->uname, new_node);
 	new_node->weight  = this_node->weight; 
 	new_node->fixed   = this_node->fixed;
 	new_node->details = this_node->details; 
 	
 	return new_node;
 }
 
 static int color_id = 0;
 
 /*
  * Create a new color with the contents of "nodes" as the list of
  *  possible nodes that resources with this color can be run on.
  *
  * Typically, when creating a color you will provide the node list from
  *  the resource you will first assign the color to.
  *
  * If "colors" != NULL, it will be added to that list
  * If "resources" != NULL, it will be added to every provisional resource
  *  in that list
  */
 color_t *
 create_color(GListPtr *colors, resource_t *resource, GListPtr resources)
 {
 	color_t *new_color = NULL;
 	
 	crm_trace("Creating color");
-	new_color = crm_malloc(sizeof(color_t));
+	crm_malloc(new_color, sizeof(color_t));
+	if(new_color == NULL) {
+		return NULL;
+	}
+	
 	new_color->id           = color_id++;
 	new_color->local_weight = 1.0;
 	
 	crm_trace("Creating color details");
-	new_color->details = crm_malloc(sizeof(struct color_shared_s));
+	crm_malloc(new_color->details, sizeof(struct color_shared_s));
+
+	if(new_color->details == NULL) {
+		crm_free(new_color);
+		return NULL;
+	}
+		
 	new_color->details->id                  = new_color->id;
 	new_color->details->highest_priority    = -1;
 	new_color->details->chosen_node         = NULL;
 	new_color->details->candidate_nodes     = NULL;
 	new_color->details->allocated_resources = NULL;
 	new_color->details->pending             = TRUE;
-
+	
 	if(resource != NULL) {
 		crm_trace("populating node list");
 		new_color->details->highest_priority = resource->priority;
 		new_color->details->candidate_nodes  =
 			node_list_dup(resource->allowed_nodes, TRUE);
 	}
 	
 	crm_debug_action(print_color("Created color", new_color, TRUE));
 
 	if(colors != NULL) {
 		*colors = g_list_append(*colors, new_color);      
 	}
 	
 	return new_color;
 }
 
 color_t *
 copy_color(color_t *a_color) 
 {
 	color_t *color_copy = NULL;
 
 	if(a_color == NULL) {
 		crm_err("Cannot copy NULL");
 		return NULL;
 	}
 	
-	color_copy = (color_t *)crm_malloc(sizeof(color_t));
-	color_copy->id      = a_color->id;
-	color_copy->details = a_color->details;
-	color_copy->local_weight = 1.0;
-	
+	crm_malloc(color_copy, sizeof(color_t));
+	if(color_copy != NULL) {
+		color_copy->id      = a_color->id;
+		color_copy->details = a_color->details;
+		color_copy->local_weight = 1.0;
+	}
 	return color_copy;
 }
 
 
 
 /*
  * Remove any nodes with a -ve weight
  */
 gboolean
 filter_nodes(resource_t *rsc)
 {
 	int lpc2 = 0;
 	crm_debug_action(print_resource("Filtering nodes for", rsc, FALSE));
 	slist_iter(
 		node, node_t, rsc->allowed_nodes, lpc2,
 		if(node == NULL) {
 			crm_err("Invalid NULL node");
 			
 		} else if(node->weight < 0.0
 			  || node->details->online == FALSE
 			  || node->details->type == node_ping) {
 			crm_debug_action(print_node("Removing", node, FALSE));
 			rsc->allowed_nodes =
 				g_list_remove(rsc->allowed_nodes,node);
 			crm_free(node);
 			lpc2 = -1; /* restart the loop */
 		}
 		);
 
 	return TRUE;
 }
 
 resource_t *
 pe_find_resource(GListPtr rsc_list, const char *id_rh)
 {
 	int lpc = 0;
 	resource_t *rsc = NULL;
 
 	for(lpc = 0; lpc < g_list_length(rsc_list); lpc++) {
 		rsc = g_list_nth_data(rsc_list, lpc);
 		if(rsc != NULL && safe_str_eq(rsc->id, id_rh)){
 			return rsc;
 		}
 	}
 	/* error */
 	return NULL;
 }
 
 
 node_t *
 pe_find_node(GListPtr nodes, const char *uname)
 {
 	int lpc = 0;
 	node_t *node = NULL;
   
 	for(lpc = 0; lpc < g_list_length(nodes); lpc++) {
 		node = g_list_nth_data(nodes, lpc);
 		if(node != NULL && safe_str_eq(node->details->uname, uname)) {
 			return node;
 		}
 	}
 	/* error */
 	return NULL;
 }
 
 node_t *
 pe_find_node_id(GListPtr nodes, const char *id)
 {
 	int lpc = 0;
 	node_t *node = NULL;
   
 	for(lpc = 0; lpc < g_list_length(nodes); lpc++) {
 		node = g_list_nth_data(nodes, lpc);
 		if(safe_str_eq(node->details->id, id)) {
 			return node;
 		}
 	}
 	/* error */
 	return NULL;
 }
 
 gint gslist_color_compare(gconstpointer a, gconstpointer b);
 color_t *
 find_color(GListPtr candidate_colors, color_t *other_color)
 {
 	GListPtr tmp = g_list_find_custom(candidate_colors, other_color,
 					    gslist_color_compare);
 	if(tmp != NULL) {
 		return (color_t *)tmp->data;
 	}
 	return NULL;
 }
 
 
 gint gslist_color_compare(gconstpointer a, gconstpointer b)
 {
 	const color_t *color_a = (const color_t*)a;
 	const color_t *color_b = (const color_t*)b;
 
 /*	crm_trace("%d vs. %d", a?color_a->id:-2, b?color_b->id:-2); */
 	if(a == b) {
 		return 0;
 	} else if(a == NULL || b == NULL) {
 		return 1;
 	} else if(color_a->id == color_b->id) {
 		return 0;
 	}
 	return 1;
 }
 
 
 
 gint sort_rsc_priority(gconstpointer a, gconstpointer b)
 {
 	const resource_t *resource1 = (const resource_t*)a;
 	const resource_t *resource2 = (const resource_t*)b;
 
 	if(a == NULL) return 1;
 	if(b == NULL) return -1;
   
 	if(resource1->priority > resource2->priority)
 		return -1;
 
 	if(resource1->priority < resource2->priority)
 		return 1;
 
 	return 0;
 }
 
 gint sort_cons_strength(gconstpointer a, gconstpointer b)
 {
 	const rsc_to_rsc_t *rsc_constraint1 = (const rsc_to_rsc_t*)a;
 	const rsc_to_rsc_t *rsc_constraint2 = (const rsc_to_rsc_t*)b;
 
 	if(a == NULL) return 1;
 	if(b == NULL) return -1;
   
 	if(rsc_constraint1->strength > rsc_constraint2->strength)
 		return 1;
 
 	if(rsc_constraint1->strength < rsc_constraint2->strength)
 		return -1;
 	return 0;
 }
 
 gint sort_color_weight(gconstpointer a, gconstpointer b)
 {
 	const color_t *color1 = (const color_t*)a;
 	const color_t *color2 = (const color_t*)b;
 
 	if(a == NULL) return 1;
 	if(b == NULL) return -1;
   
 	if(color1->local_weight > color2->local_weight)
 		return -1;
 
 	if(color1->local_weight < color2->local_weight)
 		return 1;
 
 	return 0;
 }
 
 gint sort_node_weight(gconstpointer a, gconstpointer b)
 {
 	const node_t *node1 = (const node_t*)a;
 	const node_t *node2 = (const node_t*)b;
 
 	if(a == NULL) return 1;
 	if(b == NULL) return -1;
 	
 	if(node1->weight > node2->weight)
 		return -1;
 
 	if(node1->weight < node2->weight)
 		return 1;
   
 
 	return 0;
 }
 
 action_t *
 action_new(resource_t *rsc, enum action_tasks task)
 {
-	action_t *action = (action_t*)crm_malloc(sizeof(action_t));
-	action->id   = action_id++;
-	action->rsc  = rsc;
-	action->task = task;
-	action->node = NULL; /* fill node in later */
-	action->actions_before   = NULL;
-	action->actions_after    = NULL;
-	action->failure_is_fatal = TRUE;
-	action->discard    = FALSE;
-	action->runnable   = TRUE;
-	action->processed  = FALSE;
-	action->optional   = TRUE;
-	action->seen_count = 0;
-	action->timeout = 0;
-	action->args = create_xml_node(NULL, "args");
+	action_t *action = NULL;
 	
+	crm_malloc(action, sizeof(action_t));
+	if(action != NULL) {
+		action->id   = action_id++;
+		action->rsc  = rsc;
+		action->task = task;
+		action->node = NULL; /* fill node in later */
+		action->actions_before   = NULL;
+		action->actions_after    = NULL;
+		action->failure_is_fatal = TRUE;
+		action->discard    = FALSE;
+		action->runnable   = TRUE;
+		action->processed  = FALSE;
+		action->optional   = TRUE;
+		action->seen_count = 0;
+		action->timeout = 0;
+		action->args = create_xml_node(NULL, "args");
+	}
 	return action;
 }
 
 const char *
 contype2text(enum con_type type)
 {
 	const char *result = "<unknown>";
 	switch(type)
 	{
 		case type_none:
 			result = "none";
 			break;
 		case rsc_to_rsc:
 			result = "rsc_to_rsc";
 			break;
 		case rsc_to_node:
 			result = "rsc_to_node";
 			break;
 		case rsc_to_attr:
 			result = "rsc_to_attr";
 			break;
 		case base_weight:
 			result = "base_weight";
 			break;
 	}
 	return result;
 }
 
 const char *
 strength2text(enum con_strength strength)
 {
 	const char *result = "<unknown>";
 	switch(strength)
 	{
 		case pecs_ignore:
 			result = "ignore";
 			break;
 		case pecs_must:
 			result = XML_STRENGTH_VAL_MUST;
 			break;
 		case pecs_must_not:
 			result = XML_STRENGTH_VAL_MUSTNOT;
 			break;
 		case pecs_startstop:
 			result = "start/stop";
 			break;
 	}
 	return result;
 }
 
 
 
 const char *
 task2text(enum action_tasks task)
 {
 	const char *result = "<unknown>";
 	switch(task)
 	{
 		case no_action:
 			result = "no_action";
 			break;
 		case stop_rsc:
 			result = "stop";
 			break;
 		case start_rsc:
 			result = "start";
 			break;
 		case shutdown_crm:
 			result = "shutdown_crm";
 			break;
 		case stonith_op:
 			result = "stonith";
 			break;
 	}
 	
 	return result;
 }
 
 
 void
 print_node(const char *pre_text, node_t *node, gboolean details)
 { 
 	if(node == NULL) {
 		crm_debug("%s%s: <NULL>",
 		       pre_text==NULL?"":pre_text,
 		       pre_text==NULL?"":": ");
 		return;
 	}
 
 	crm_debug("%s%s%sNode %s: (weight=%f, fixed=%s)",
 	       pre_text==NULL?"":pre_text,
 	       pre_text==NULL?"":": ",
 	       node->details==NULL?"error ":node->details->online?"":"Unavailable/Unclean ",
 	       node->details->uname, 
 	       node->weight,
 	       node->fixed?"True":"False"); 
 
 	if(details && node->details != NULL) {
 		char *mutable = crm_strdup("\t\t");
 		crm_debug("\t\t===Node Attributes");
 		g_hash_table_foreach(node->details->attrs,
 				     print_str_str, mutable);
 		crm_free(mutable);
 	}
 
 	if(details) {
 		int lpc = 0;
 		crm_debug("\t\t===Node Attributes");
 		slist_iter(
 			rsc, resource_t, node->details->running_rsc, lpc,
 			print_resource("\t\t", rsc, FALSE);
 			);
 	}
 	
 }
 
 /*
  * Used by the HashTable for-loop
  */
 void print_str_str(gpointer key, gpointer value, gpointer user_data)
 {
 	crm_debug("%s%s %s ==> %s",
 	       user_data==NULL?"":(char*)user_data,
 	       user_data==NULL?"":": ",
 	       (char*)key,
 	       (char*)value);
 }
 
 void
 print_color_details(const char *pre_text,
 		    struct color_shared_s *color,
 		    gboolean details)
 { 
 	if(color == NULL) {
 		crm_debug("%s%s: <NULL>",
 		       pre_text==NULL?"":pre_text,
 		       pre_text==NULL?"":": ");
 		return;
 	}
 	crm_debug("%s%sColor %d: node=%s (from %d candidates)",
 	       pre_text==NULL?"":pre_text,
 	       pre_text==NULL?"":": ",
 	       color->id, 
 	       color->chosen_node==NULL?"<unset>":color->chosen_node->details->uname,
 	       g_list_length(color->candidate_nodes)); 
 	if(details) {
 		int lpc = 0;
 		slist_iter(node, node_t, color->candidate_nodes, lpc,
 			   print_node("\t", node, FALSE));
 	}
 }
 
 void
 print_color(const char *pre_text, color_t *color, gboolean details)
 { 
 	if(color == NULL) {
 		crm_debug("%s%s: <NULL>",
 		       pre_text==NULL?"":pre_text,
 		       pre_text==NULL?"":": ");
 		return;
 	}
 	crm_debug("%s%sColor %d: (weight=%f, node=%s, possible=%d)",
 	       pre_text==NULL?"":pre_text,
 	       pre_text==NULL?"":": ",
 	       color->id, 
 	       color->local_weight,
 		  safe_val5("<unset>",color,details,chosen_node,details,uname),
 	       g_list_length(color->details->candidate_nodes)); 
 	if(details) {
 		print_color_details("\t", color->details, details);
 	}
 }
 
 void
 print_rsc_to_node(const char *pre_text, rsc_to_node_t *cons, gboolean details)
 { 
 	int lpc = 0;
 	if(cons == NULL) {
 		crm_debug("%s%s: <NULL>",
 		       pre_text==NULL?"":pre_text,
 		       pre_text==NULL?"":": ");
 		return;
 	}
 	crm_debug("%s%s%s Constraint %s (%p) - %d nodes:",
 	       pre_text==NULL?"":pre_text,
 	       pre_text==NULL?"":": ",
 	       "rsc_to_node",
 		  cons->id, cons,
 		  g_list_length(cons->node_list_rh));
 
 	if(details == FALSE) {
 		crm_debug("\t%s %s run (score=%f : node placement rule)",
 			  safe_val3(NULL, cons, rsc_lh, id), 
 			  cons->can?"Can":"Cannot",
 			  cons->weight);
 
 		slist_iter(
 			node, node_t, cons->node_list_rh, lpc,
 			print_node("\t\t-->", node, FALSE)
 			);
 	}
 }
 
 void
 print_rsc_to_rsc(const char *pre_text, rsc_to_rsc_t *cons, gboolean details)
 { 
 	if(cons == NULL) {
 		crm_debug("%s%s: <NULL>",
 		       pre_text==NULL?"":pre_text,
 		       pre_text==NULL?"":": ");
 		return;
 	}
 	crm_debug("%s%s%s Constraint %s (%p):",
 	       pre_text==NULL?"":pre_text,
 	       pre_text==NULL?"":": ",
 	       "rsc_to_rsc", cons->id, cons);
 
 	if(details == FALSE) {
 
 		crm_debug("\t%s --> %s, %s",
 			  safe_val3(NULL, cons, rsc_lh, id), 
 			  safe_val3(NULL, cons, rsc_rh, id), 
 			  strength2text(cons->strength));
 	}
 } 
 
 void
 print_resource(const char *pre_text, resource_t *rsc, gboolean details)
 { 
 	if(rsc == NULL) {
 		crm_debug("%s%s: <NULL>",
 		       pre_text==NULL?"":pre_text,
 		       pre_text==NULL?"":": ");
 		return;
 	}
 	crm_debug("%s%s%s%sResource %s: (priority=%f, color=%d, now=%s)",
 	       pre_text==NULL?"":pre_text,
 	       pre_text==NULL?"":": ",
 	       rsc->provisional?"Provisional ":"",
 	       rsc->runnable?"":"(Non-Startable) ",
 	       rsc->id,
 	       (double)rsc->priority,
 	       safe_val3(-1, rsc, color, id),
 	       safe_val4(NULL, rsc, cur_node, details, uname));
 
 	crm_debug("\t%d candidate colors, %d allowed nodes, %d rsc_cons and %d node_cons",
 	       g_list_length(rsc->candidate_colors),
 	       g_list_length(rsc->allowed_nodes),
 	       g_list_length(rsc->rsc_cons),
 	       g_list_length(rsc->node_cons));
 	
 	if(details) {
 		int lpc = 0;
 		crm_debug("\t=== Actions");
 		print_action("\tStop: ", rsc->stop, FALSE);
 		print_action("\tStart: ", rsc->start, FALSE);
 		
 		crm_debug("\t=== Colors");
 		slist_iter(
 			color, color_t, rsc->candidate_colors, lpc,
 			print_color("\t", color, FALSE)
 			);
 		crm_debug("\t=== Allowed Nodes");
 		slist_iter(
 			node, node_t, rsc->allowed_nodes, lpc,
 			print_node("\t", node, FALSE);
 			);
 	}
 }
 
 
 
 void
 print_action(const char *pre_text, action_t *action, gboolean details)
 { 
 	if(action == NULL) {
 		crm_debug("%s%s: <NULL>",
 		       pre_text==NULL?"":pre_text,
 		       pre_text==NULL?"":": ");
 		return;
 	}
 
 	switch(action->task) {
 		case stonith_op:
 		case shutdown_crm:
 			crm_debug("%s%s%sAction %d: %s @ %s",
 			       pre_text==NULL?"":pre_text,
 			       pre_text==NULL?"":": ",
 			       action->discard?"Discarded ":action->optional?"Optional ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
 			       action->id,
 			       task2text(action->task),
 			       safe_val4(NULL, action, node, details, uname));
 			break;
 		default:
 			crm_debug("%s%s%sAction %d: %s %s @ %s",
 			       pre_text==NULL?"":pre_text,
 			       pre_text==NULL?"":": ",
 			       action->optional?"Optional ":action->runnable?action->processed?"":"(Provisional) ":"!!Non-Startable!! ",
 			       action->id,
 			       task2text(action->task),
 			       safe_val3(NULL, action, rsc, id),
 			       safe_val4(NULL, action, node, details, uname));
 			
 			break;
 	}
 
 	if(details) {
 		int lpc = 0;
 #if 1
 		crm_debug("\t\t====== Preceeding Actions");
 		slist_iter(
 			other, action_wrapper_t, action->actions_before, lpc,
 			print_action("\t\t", other->action, FALSE);
 			);
 		crm_debug("\t\t====== Subsequent Actions");
 		slist_iter(
 			other, action_wrapper_t, action->actions_after, lpc,
 			print_action("\t\t", other->action, FALSE);
 			);		
 #else
 		crm_debug("\t\t====== Subsequent Actions");
 		slist_iter(
 			other, action_wrapper_t, action->actions_after, lpc,
 			print_action("\t\t", other->action, FALSE);
 			);		
 #endif
 		crm_debug("\t\t====== End");
 
 	} else {
 		crm_debug("\t\t(seen=%d, before=%d, after=%d)",
 		       action->seen_count,
 		       g_list_length(action->actions_before),
 		       g_list_length(action->actions_after));
 	}
 }
 
 
 void
 pe_free_nodes(GListPtr nodes)
 {
 	while(nodes != NULL) {
 		GListPtr list_item = nodes;
 		node_t *node = (node_t*)list_item->data;
 		struct node_shared_s *details = node->details;
 		nodes = nodes->next;
 
 		crm_trace("deleting node");
 		crm_trace("%s is being deleted", details->uname);
 		print_node("delete", node, FALSE);
 		
 		if(details != NULL) {
 			if(details->attrs != NULL) {
 				g_hash_table_foreach_remove(details->attrs,
 							    ghash_free_str_str,
 							    NULL);
 
 				g_hash_table_destroy(details->attrs);
 			}
 			
 		}
 		
 	}
-	g_list_free(nodes);
+	if(nodes != NULL) {
+		g_list_free(nodes);
+	}
 }
 
 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data)
 {
 	crm_free(key);
 	crm_free(value);
 	return TRUE;
 }
 
 
 void
 pe_free_colors(GListPtr colors)
 {
 	while(colors != NULL) {
 		GListPtr list_item = colors;
 		color_t *color = (color_t *)list_item->data;
 		struct color_shared_s *details = color->details;
 		colors = colors->next;
 		
 		if(details != NULL) {
 			pe_free_shallow(details->candidate_nodes);
 			pe_free_shallow_adv(details->allocated_resources, FALSE);
 			crm_free(details->chosen_node);
 			crm_free(details);
 		}
 		crm_free(color);
 	}
-	g_list_free(colors);
+	if(colors != NULL) {
+		g_list_free(colors);
+	}
 }
 
 void
 pe_free_shallow(GListPtr alist)
 {
 	pe_free_shallow_adv(alist, TRUE);
 }
 
 void
 pe_free_shallow_adv(GListPtr alist, gboolean with_data)
 {
 	GListPtr item;
 	GListPtr item_next = alist;
 	while(item_next != NULL) {
 		item = item_next;
 		item_next = item_next->next;
 		
 		if(with_data) {
 /*			crm_trace("freeing %p", item->data); */
 			crm_free(item->data);
 		}
 		
 		item->data = NULL;
 		item->next = NULL;
 		g_list_free(item);
 	}
 }
 
 void
 pe_free_resources(GListPtr resources)
 { 
 	volatile GListPtr list_item = NULL;
 	resource_t *rsc = NULL;
 	
 	while(resources != NULL) {
 		list_item = resources;
 		rsc = (resource_t *)list_item->data;
 		resources = resources->next;
 
 		pe_free_shallow_adv(rsc->candidate_colors, TRUE);
 		pe_free_shallow(rsc->allowed_nodes);
 
 		while(rsc->rsc_cons) {
 			pe_free_rsc_to_rsc((rsc_to_rsc_t*)rsc->rsc_cons->data);
 			rsc->rsc_cons = rsc->rsc_cons->next;
 		}
-		g_list_free(rsc->rsc_cons);
+		if(rsc->rsc_cons != NULL) {
+			g_list_free(rsc->rsc_cons);
+		}
 		crm_free(rsc);
 	}
-	g_list_free(resources);
-	
+	if(resources != NULL) {
+		g_list_free(resources);
+	}
 }
 
 
 void
 pe_free_actions(GListPtr actions) 
 {
 	while(actions != NULL) {
 		GListPtr list_item = actions;
 		action_t *action = (action_t *)list_item->data;
 		actions = actions->next;
 
-		pe_free_shallow(action->actions_before); /* action_warpper_t* */
+		pe_free_shallow(action->actions_before);/* action_warpper_t* */
 		pe_free_shallow(action->actions_after); /* action_warpper_t* */
 		action->actions_before = NULL;
 		action->actions_after  = NULL;
 		free_xml(action->args);
 		crm_free(action);
 	}
-	g_list_free(actions);
+	if(actions != NULL) {
+		g_list_free(actions);
+	}
 }
 
 
 
 void
 pe_free_rsc_to_rsc(rsc_to_rsc_t *cons)
 { 
 	if(cons != NULL) {
 		crm_free(cons);
 	}
 }
 
 void
 pe_free_rsc_to_node(rsc_to_node_t *cons)
 {
 	if(cons != NULL) {
 
 		/* right now we dont make copies so this isnt required */
 /*		pe_free_shallow(cons->node_list_rh); */ /* node_t* */
 		crm_free(cons);
 	}
 }
 
diff --git a/crm/tengine/unpack.c b/crm/tengine/unpack.c
index a03ae76ee4..de8aa00a80 100644
--- a/crm/tengine/unpack.c
+++ b/crm/tengine/unpack.c
@@ -1,438 +1,441 @@
-/* $Id: unpack.c,v 1.2 2004/09/15 20:23:18 andrew Exp $ */
+/* $Id: unpack.c,v 1.3 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/msg.h>
 #include <crm/common/xml.h>
 #include <tengine.h>
 #include <heartbeat.h>
 #include <clplumbing/Gmain_timeout.h>
 #include <lrm/lrm_api.h>
 #include <sys/stat.h>
 
 gboolean process_te_message(xmlNodePtr msg, IPC_Channel *sender);
 action_t* unpack_action(xmlNodePtr xml_action);
 xmlNodePtr create_shutdown_event(const char *node, int op_status);
 
 gboolean
 unpack_graph(xmlNodePtr xml_graph)
 {
 /*
 <transition_graph>
   <synapse>
     <action_set>
       <rsc_op id="2"
 	... 
     <inputs>
       <rsc_op id="2"
 	... 
 */
 	int num_synapses = 0;
 	int num_actions = 0;
 
 	xml_child_iter(
 		xml_graph, synapse, "synapse",
 
-		synapse_t *new_synapse = (synapse_t*)
-			crm_malloc(sizeof(synapse_t));
+		synapse_t *new_synapse = NULL;
+		crm_malloc(new_synapse, sizeof(synapse_t));
 		new_synapse->id       = num_synapses++;
 		new_synapse->complete = FALSE;
 		new_synapse->actions  = NULL;
 		new_synapse->inputs   = NULL;
 		
 		graph = g_list_append(graph, new_synapse);
 
 		xml_child_iter(
 			synapse, actions, "action_set",
 
 			xml_child_iter(
 				actions, action, NULL,
 				
 				action_t *new_action = unpack_action(action);
 				num_actions++;
 				
 				if(new_action == NULL) {
 					action = action->next;
 					break;
 				}
 				new_synapse->actions = g_list_append(
 					new_synapse->actions,
 					new_action);
 				);
 			
 			);
 
 		xml_child_iter(
 			synapse, inputs, "inputs",
 
 			xml_child_iter(
 				inputs, trigger, NULL,
 
 				xml_child_iter(
 					trigger, input, NULL,
 
 					action_t *new_input =
 						unpack_action(input);
 
 					if(new_input == NULL) {
 						input = input->next;
 						break;
 					}
 					
 					new_synapse->inputs = g_list_append(
 						new_synapse->inputs,
 						new_input);
 					);
 				);
 			);
 		);
 
 	crm_info("Unpacked %d actions in %d synapses",
 		 num_actions, num_synapses);
 
 	if(num_actions > 0) {
 		return TRUE;
 	} else {
 		/* indicate to caller that there's nothing to do */
 		return FALSE;
 	}
 	
 }
 
 action_t*
 unpack_action(xmlNodePtr xml_action) 
 {
 	const char *tmp        = xmlGetProp(xml_action, "id");
 	action_t   *action     = NULL;
 	xmlNodePtr action_copy = NULL;
 
 	if(tmp == NULL) {
 		crm_err("Actions must have an id!");
 		crm_xml_devel(xml_action, "Action with missing id");
 		return NULL;
 	}
 	
 	action_copy = copy_xml_node_recursive(xml_action);
-	action = crm_malloc(sizeof(action_t));
-
+	crm_malloc(action, sizeof(action_t));
+	if(action == NULL) {
+		return NULL;
+	}
+	
 	action->id       = atoi(tmp);
 	action->timeout  = 0;
 	action->timer_id = -1;
 	action->invoked  = FALSE;
 	action->complete = FALSE;
 	action->can_fail = FALSE;
 	action->type     = action_type_rsc;
- 	action->xml      = action_copy;
+	action->xml      = action_copy;
 	
 	if(safe_str_eq(action_copy->name, "rsc_op")) {
 		action->type = action_type_rsc;
 
 	} else if(safe_str_eq(action_copy->name, "pseudo_event")) {
 		action->type = action_type_pseudo;
 
 	} else if(safe_str_eq(action_copy->name, "crm_event")) {
 		action->type = action_type_crm;
 
 	}
 
 	tmp = xmlGetProp(action_copy, "timeout");
 	if(tmp != NULL) {
 		action->timeout = atoi(tmp);
 	}
 
 	tmp = xmlGetProp(action_copy, "can_fail");
 	if(safe_str_eq(tmp, "true")) {
 		action->can_fail = TRUE;
 	}
 
 	return action;
 }
 
 
 gboolean
 extract_event(xmlNodePtr msg)
 {
 	gboolean abort      = FALSE;
 	xmlNodePtr iter     = NULL;
 	xmlNodePtr cib      = NULL;
 	const char *section = NULL;
 	const char *event_node   = NULL;
 
 /*
 [cib fragment]
 ...
 <status>
    <node_state id="node1" state=CRMD_STATE_ACTIVE exp_state="active">
      <lrm>
        <lrm_resources>
 	 <rsc_state id="" rsc_id="rsc4" node_id="node1" rsc_state="stopped"/>
 */
 
 	crm_trace("Extracting event");
 	
 	iter = find_xml_node(msg, XML_TAG_FRAGMENT);
 	section = xmlGetProp(iter, XML_ATTR_SECTION);
 
 	if(safe_str_eq(section, XML_CIB_TAG_CRMCONFIG)) {
 		/* ignore - for the moment */
 		crm_debug("Ignoring changes to the %s section",
 			  XML_CIB_TAG_CRMCONFIG);
 		return TRUE;
 		
 	} else if(safe_str_neq(section, XML_CIB_TAG_STATUS)) {
 		/* these too are never expected	 */
 		crm_debug("Ignoring changes outside the %s section",
 			  XML_CIB_TAG_STATUS);
 		return FALSE;
 	}
 	
 	cib = find_xml_node(iter, XML_TAG_CIB);
 	iter = get_object_root(XML_CIB_TAG_STATUS, cib);
 	if(iter != NULL) {
 		iter = iter->children;
 	} else {
 		crm_xml_warn(cib, XML_CIB_TAG_STATUS " section missing?");
 	}
 	
 	
 	while(abort == FALSE && iter != NULL) {
 		xmlNodePtr node_state = iter;
 		xmlNodePtr child = iter->children;
 		const char *state = xmlGetProp(
 			node_state, XML_CIB_ATTR_CRMDSTATE);
 		iter = iter->next;
 
 		crm_xml_devel(node_state,"Processing");
 		
 		if(xmlGetProp(node_state, XML_CIB_ATTR_SHUTDOWN) != NULL) {
 			crm_trace("Aborting on %s attribute",
 				  XML_CIB_ATTR_SHUTDOWN);
 			abort = TRUE;
 			
 		} else if(xmlGetProp(node_state, XML_CIB_ATTR_STONITH) != NULL) {
 			/* node marked for STONITH
 			 *   possibly by us when a shutdown timmed out
 			 */
 			crm_trace("Checking for STONITH");
 			event_node = xmlGetProp(node_state, XML_ATTR_UNAME);
 
 			xmlNodePtr shutdown = create_shutdown_event(
 				event_node, LRM_OP_TIMEOUT);
 
 			process_graph_event(shutdown);
 
 			free_xml(shutdown);
 			
 		} else if(state != NULL && child == NULL) {
 			/* simple node state update...
 			 *   possibly from a shutdown we requested
 			 */
 			crm_trace("Processing simple state update");
 			if(safe_str_neq(state, OFFLINESTATUS)) {
 				/* always recompute */
 				abort = TRUE;
 				continue;
 			}
 			
 			event_node = xmlGetProp(node_state, XML_ATTR_UNAME);
 			xmlNodePtr shutdown = create_shutdown_event(
 				event_node, LRM_OP_DONE);
 
 			process_graph_event(shutdown);
 
 			free_xml(shutdown);
 
 		} else if(state == NULL && child != NULL) {
 			/* LRM resource update...
 			 */
 			crm_trace("Processing LRM resource update");
 			child = find_xml_node(node_state, XML_CIB_TAG_LRM);
 			child = find_xml_node(child, XML_LRM_TAG_RESOURCES);
 
 			if(child != NULL) {
 				child = child->children;
 			} else {
 				abort = TRUE;
 			}
 			
 			event_node = xmlGetProp(node_state, XML_ATTR_UNAME);
 			while(abort == FALSE && child != NULL) {
 				process_graph_event(child);
 				child = child->next;
 			}	
 		} else if(state != NULL && child != NULL) {
 			/* this is a complex event and could not be completely
 			 * due to any request we made
 			 */
 			crm_trace("Aborting on complex update");
 			abort = TRUE;
 			
 		} else {
 			/* ignore */
 			crm_err("Ignoring message");
 		}
 	}
 	
 	return !abort;
 }
 
 gboolean
 process_te_message(xmlNodePtr msg, IPC_Channel *sender)
 {
 	xmlNodePtr graph = NULL;
 	const char *sys_to = xmlGetProp(msg, XML_ATTR_SYSTO);
 	const char *ref    = xmlGetProp(msg, XML_ATTR_REFERENCE);
 	const char *op     = get_xml_attr(
 		msg, XML_TAG_OPTIONS, XML_ATTR_OP, FALSE);
 
 
 	crm_debug("Recieved %s (%s) message", op, ref);
 	
 #ifdef MSG_LOG
 
 	struct stat buf;
 	if(stat(DEVEL_DIR, &buf) != 0) {
 		cl_perror("Stat of %s failed... exiting", DEVEL_DIR);
 		exit(100);
 	}
 	
 	if(msg_te_strm == NULL) {
 		msg_te_strm = fopen(DEVEL_DIR"/te.log", "w");
 	}
 	char *xml = dump_xml_formatted(msg);
 	fprintf(msg_te_strm, "[Input %s]\t%s\n",
 		op, xml);
 	fflush(msg_te_strm);
 	crm_free(xml);
 #endif
 
 	if(safe_str_eq(xmlGetProp(msg, XML_ATTR_MSGTYPE), XML_ATTR_RESPONSE)
 	   && safe_str_neq(op, CRM_OP_EVENTCC)) {
 #ifdef MSG_LOG
 	fprintf(msg_te_strm, "[Result ]\tDiscarded\n");
 	fflush(msg_te_strm);
 #endif
 		crm_info("Message was a response not a request.  Discarding");
 		return TRUE;
 	}
 
 	crm_debug("Processing %s (%s) message", op, ref);
 	
 	if(op == NULL){
 		/* error */
 	} else if(strcmp(op, CRM_OP_HELLO) == 0) {
 		/* ignore */
 
 	} else if(sys_to == NULL || strcmp(sys_to, CRM_SYSTEM_TENGINE) != 0) {
-		crm_verbose("Bad sys-to %s", sys_to);
+		crm_verbose("Bad sys-to %s", crm_str(sys_to));
 		return FALSE;
 		
 	} else if(strcmp(op, CRM_OP_TRANSITION) == 0) {
 
 		crm_trace("Initializing graph...");
 		initialize_graph();
 
 		graph = find_xml_node(msg, "transition_graph");
 		crm_trace("Unpacking graph...");
 		unpack_graph(graph);
 		crm_trace("Initiating transition...");
 
 		in_transition = TRUE;
 
 		if(initiate_transition() == FALSE) {
 			/* nothing to be done.. means we're done. */
 			crm_info("No actions to be taken..."
 			       " transition compelte.");
 		}
 		crm_trace("Processing complete...");
 		
 	} else if(strcmp(op, CRM_OP_ABORT) == 0) {
 		initialize_graph();
 
 	} else if(strcmp(op, CRM_OP_QUIT) == 0) {
 		crm_err("Received quit message, terminating");
 		exit(0);
 		
 	} else if(in_transition == FALSE) {
 		crm_info("Received event_cc while not in a transition..."
 			 "  Poking the Policy Engine");
 		send_abort("Initiate a transition", NULL);
 		
 	} else if(strcmp(op, CRM_OP_EVENTCC) == 0) {
 		const char *true_op = get_xml_attr (msg, XML_TAG_OPTIONS,
 						    XML_ATTR_TRUEOP, TRUE);
 		crm_trace("Processing %s...", CRM_OP_EVENTCC);
 		if(true_op == NULL) {
 			crm_err(
 			       "Illegal update,"
 			       " the original operation must be specified");
 			send_abort("Illegal update", msg);
 			
 		} else if(strcmp(true_op, CRM_OP_CREATE) == 0
 		   || strcmp(true_op, CRM_OP_DELETE) == 0
 		   || strcmp(true_op, CRM_OP_REPLACE) == 0
 		   || strcmp(true_op, CRM_OP_WELCOME) == 0
 		   || strcmp(true_op, CRM_OP_SHUTDOWN_REQ) == 0
 		   || strcmp(true_op, CRM_OP_ERASE) == 0) {
 
 			/* these are always unexpected, trigger the PE */
 			send_abort("Config update", msg);
 			
 		} else if(strcmp(true_op, CRM_OP_UPDATE) == 0) {
 			/* this may not be un-expected */
 //			if(
 			extract_event(msg);
 			//== FALSE){
 //				send_abort(msg);
 //			}
 			
 		} else {
 			crm_err(
 			       "Did not expect copy of action %s", op);
 		}
 		
 	}
 
 	crm_debug("finished processing message");
 	print_state(FALSE);
 	
 	return TRUE;
 }
 		
 
 xmlNodePtr
 create_shutdown_event(const char *node, int op_status)
 {
 	xmlNodePtr event = create_xml_node(NULL, XML_CIB_TAG_STATE);
 	char *code = crm_itoa(op_status);
 
 	set_xml_property_copy(event, XML_LRM_ATTR_TARGET, node);
 //	event_rsc    = set_xml_property_copy(event, XML_ATTR_ID);
 	set_xml_property_copy(event, XML_LRM_ATTR_RC, "0");
 	set_xml_property_copy(
 		event, XML_LRM_ATTR_LASTOP, XML_CIB_ATTR_SHUTDOWN);
 	set_xml_property_copy(
 		event, XML_LRM_ATTR_RSCSTATE, CRMD_RSCSTATE_GENERIC_OK);
 	set_xml_property_copy(event, XML_LRM_ATTR_OPSTATUS, code);
 	
 	crm_free(code);
 	return event;
 }
diff --git a/crm/tengine/utils.c b/crm/tengine/utils.c
index 94c854e292..6b7fd5e865 100644
--- a/crm/tengine/utils.c
+++ b/crm/tengine/utils.c
@@ -1,373 +1,373 @@
-/* $Id: utils.c,v 1.2 2004/09/15 20:22:33 andrew Exp $ */
+/* $Id: utils.c,v 1.3 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <sys/param.h>
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/msg.h>
 #include <crm/common/xml.h>
 #include <tengine.h>
 #include <heartbeat.h>
 #include <clplumbing/Gmain_timeout.h>
 #include <lrm/lrm_api.h>
 
 extern int global_transition_timer;
 FILE *msg_te_strm = NULL;
 
 void print_input(const char *prefix, action_t *input, gboolean to_file);
 void print_action(const char *prefix, action_t *action, gboolean to_file);
 
 void
 send_abort(const char *text, xmlNodePtr msg)
 {	
 	xmlNodePtr options = create_xml_node(NULL, XML_TAG_OPTIONS);
 
 	crm_info("Sending \"abort\" message... details follow");
 	crm_xml_info(msg, text);
 	
 #ifdef MSG_LOG
 	fprintf(msg_te_strm, "[Result ]\tTransition aborted\n");
 	fflush(msg_te_strm);
 #endif
 #ifdef TESTING
 	print_state(TRUE);
 	g_main_quit(mainloop);
 	return;
 #endif	
 	set_xml_property_copy(options, XML_ATTR_OP, CRM_OP_TEABORT);
 	
 	send_ipc_request(crm_ch, options, NULL,
 			 NULL, CRM_SYSTEM_DC, CRM_SYSTEM_TENGINE,
 			 NULL, NULL);
 	
 	free_xml(options);
 }
 
 void
 send_success(const char *text)
 {	
 	xmlNodePtr options = create_xml_node(NULL, XML_TAG_OPTIONS);
 
 	if(in_transition == FALSE) {
 		crm_warn("Not in transition, not sending message");
 		return;
 	}
 	in_transition = FALSE;
 
 	crm_info("Sending \"complete\" message: %s", text);
 
 #ifdef MSG_LOG
 	if(msg_te_strm != NULL) {
 		fprintf(msg_te_strm, "[Result ]\tTransition complete\n");
 		fflush(msg_te_strm);
 	}
 #endif
 #ifdef TESTING
 	print_state(TRUE);
 	g_main_quit(mainloop);
 	return;
 #endif
 	
 	set_xml_property_copy(options, XML_ATTR_OP, CRM_OP_TECOMPLETE);
 	
 	send_ipc_request(crm_ch, options, NULL,
 			 NULL, CRM_SYSTEM_DC, CRM_SYSTEM_TENGINE,
 			 NULL, NULL);
 	
 	free_xml(options);
 }
 
 void
 print_state(gboolean to_file)
 {
 	int lpc = 0;
 	int lpc2 = 0;
 	FILE *output = msg_te_strm;
 #ifdef TESTING
 	output = stderr;
 #endif
 	if(to_file) {
 		fprintf(output, "Start Transitioner state\n");
 	}
 	crm_debug("#!!#!!# Start Transitioner state");
 	if(graph == NULL) {
 		crm_debug("\tEmpty transition graph");
 		crm_debug("#!!#!!# End Transitioner state");
 		if(to_file) {
 			fprintf(output,
 				"\tEmpty transition graph\n"
 				"End Transitioner state\n");
 		}
 		return;
 	}
 
 	slist_iter(
 		synapse, synapse_t, graph, lpc,
 
 		crm_debug("Synapse %d %s",
 			  synapse->id,
 			  synapse->complete?"has completed":"is pending");
 		
 		if(to_file) {
 			fprintf(output, "Synapse %d %s\n",
 				synapse->id,
 				synapse->complete?"has completed":"is pending");
 		}
 		if(synapse->complete == FALSE) {
 			slist_iter(
 				input, action_t, synapse->inputs, lpc2,
 				
 				print_input("\t", input, to_file);
 				
 				);
 		}
 		
 		slist_iter(
 			action, action_t, synapse->actions, lpc2,
 
 			print_action("\t", action, to_file);
 
 			);
 		);
 	
 	crm_debug("#!!#!!# End Transitioner state");	
 	if(to_file) {
 		fprintf(output, "End Transitioner state\n");
 	}
 }
 
 void
 print_input(const char *prefix, action_t *input, gboolean to_file) 
 {
 	FILE *output = msg_te_strm;
 #ifdef TESTING
 	output = stderr;
 #endif
 	crm_debug("%s[Input %d] %s (%d)",
 		  prefix,
 		  input->id,
 		  input->complete?"Satisfied":"Pending",
 		  input->type);
 
 	crm_xml_trace(input->xml, "\t  Raw input");
 
 	if(to_file) {
 		fprintf(output,
 			"%s[Input %d] %s (%d)\n",
 			prefix,
 			input->id,
 			input->complete?"Satisfied":"Pending",
 			input->type);
 		
 		fflush(msg_te_strm);
 	}
 	
 }
 
 void
 print_action(const char *prefix, action_t *action, gboolean to_file) 
 {
 	FILE *output = msg_te_strm;
 #ifdef TESTING
 	output = stderr;
 #endif
 	crm_debug("%s[Action %d] %s (%d - %s fail)",
 		  prefix,
 		  action->id,
 		  action->complete?"Completed":
 			action->invoked?"In-flight":"Pending",
 		  action->type,
 		  action->can_fail?"can":"cannot");
 
 	crm_debug("%s  timeout=%d, timer=%d",
 		  prefix,
 		  action->timeout,
 		  action->timer_id);
 
 	crm_xml_trace(action->xml, "\t  Raw action");
 
 	if(to_file) {
 		fprintf(output,
 			"%s[Action %d] %s (%d - %s fail)\n",
 			prefix,
 			action->id,
 			action->complete?"Completed":
 			action->invoked?"In-flight":"Pending",
 			action->type,
 			action->can_fail?"can":"cannot");
 	
 		fflush(msg_te_strm);
 	}		  
 }
 
 gboolean
 timer_callback(gpointer data)
 {
 	if(data == NULL) {
 		/* global timeout - abort the transition */
 		crm_info("Transition timeout reached..."
 			 " marking transition complete.");
 		crm_warn("Some actions may not have been executed.");
 
 		if(global_transition_timer > 0) {
 			crm_devel("Stopping transition timer");
 			g_source_remove(global_transition_timer);
 			global_transition_timer = -1;
 		}
 		
 		send_success("timeout");
 		
 		return TRUE;
 		
 	} else {
 		/* fail the action
 		 * - which may or may not abort the transition
 		 */
 		action_t *action = (action_t*)data;
 		if(action->timer_id > 0) {
 			g_source_remove(action->timer_id);
 		}
 		action->timer_id = -1;
 
 		return do_update_cib(action->xml, LRM_OP_TIMEOUT);	
 	}
 }
 
 gboolean
 do_update_cib(xmlNodePtr xml_action, int status)
 {
 	char *code;
 	char since_epoch[64];
 	xmlNodePtr fragment = NULL;
 	xmlNodePtr options  = NULL;
 	xmlNodePtr state    = NULL;
 	xmlNodePtr rsc      = NULL;
 
 	const char *sys_to = CRM_SYSTEM_DCIB;
 	const char *task   = xmlGetProp(xml_action, XML_LRM_ATTR_TASK);
 	const char *rsc_id = xmlGetProp(xml_action, XML_LRM_ATTR_RSCID);
 	const char *target = xmlGetProp(xml_action, XML_LRM_ATTR_TARGET);
 	const char *target_uuid =
 		xmlGetProp(xml_action, XML_LRM_ATTR_TARGET_UUID);
 	
 	if(status == LRM_OP_TIMEOUT) {
 		if(xmlGetProp(xml_action, XML_LRM_ATTR_RSCID) != NULL) {
 			crm_warn("%s: %s %s on %s timed out",
 				 xml_action->name, task, rsc_id, target);
 		} else {
 			crm_warn("%s: %s on %s timed out",
 				 xml_action->name, task, target);
 		}
 	}
 	
 /*
   update the CIB
 
 <node_state id="hadev">
       <lrm>
         <lrm_resources>
           <lrm_resource id="rsc2" last_op="start" op_code="0" target="hadev"/>
 */
 
 	fragment = NULL;
 	options  = create_xml_node(NULL, XML_TAG_OPTIONS);
 	state    = create_xml_node(NULL, XML_CIB_TAG_STATE);
 
 #ifdef TESTING
 
 	/* turn the "pending" notification into a "op completed" notification
 	 *  when testing... exercises more code this way.
 	 */
 	if(status == -1) {
 		status = 0;
 	}
 	sys_to = CRM_SYSTEM_TENGINE;
 	set_xml_property_copy(options, XML_ATTR_OP,     CRM_OP_EVENTCC);
 	set_xml_property_copy(options, XML_ATTR_TRUEOP, CRM_OP_UPDATE);
 #else
 	set_xml_property_copy(options, XML_ATTR_OP,    CRM_OP_UPDATE);
 #endif
 	set_xml_property_copy(state,   XML_ATTR_UUID,  target_uuid);
 	set_xml_property_copy(state,   XML_ATTR_UNAME, target);
 	
 	if(status != -1 && (safe_str_eq(task, "shutdown_crm"))) {
 		sprintf(since_epoch, "%ld", (unsigned long)time(NULL));
 		set_xml_property_copy(rsc, "stonith", since_epoch);
 		
 	} else {
 		code = crm_itoa(status);
 		
 		rsc = create_xml_node(state, "lrm");
 		rsc = create_xml_node(rsc,   "lrm_resources");
 		rsc = create_xml_node(rsc,   "lrm_resource");
 		
 		set_xml_property_copy(rsc, XML_ATTR_ID,         rsc_id);
 		set_xml_property_copy(rsc, XML_LRM_ATTR_TARGET, target);
 		set_xml_property_copy(
 			rsc, XML_LRM_ATTR_TARGET_UUID, target_uuid);
 
 		if(safe_str_eq(CRMD_RSCSTATE_START, task)) {
 			set_xml_property_copy(
 				rsc, XML_LRM_ATTR_RSCSTATE,
 				CRMD_RSCSTATE_START_PENDING);
 
 		} else if(safe_str_eq(CRMD_RSCSTATE_STOP, task)) {
 			set_xml_property_copy(
 				rsc, XML_LRM_ATTR_RSCSTATE,
 				CRMD_RSCSTATE_STOP_PENDING);
 
 		} else {
-			crm_warn("Using status \"pending\" for op \"%s\""
-				 "... this is still in the experimental stage.",
-				 task);
+			crm_warn("Using status \"pending\" for op \"%s\"..."
+				 " this is still in the experimental stage.",
+				 crm_str(task));
 			set_xml_property_copy(
 				rsc, XML_LRM_ATTR_RSCSTATE,
 				CRMD_RSCSTATE_GENERIC_PENDING);
 		}
 		
 		set_xml_property_copy(rsc, XML_LRM_ATTR_OPSTATUS, code);
 		set_xml_property_copy(rsc, XML_LRM_ATTR_RC, code);
 		set_xml_property_copy(rsc, XML_LRM_ATTR_LASTOP, task);
 
 		crm_free(code);
 	}
 
 	fragment = create_cib_fragment(state, NULL);
 	
 #ifdef MSG_LOG
 	fprintf(msg_te_strm,
 		"[Result ]\tUpdate CIB with \"%s\" (%s): %s %s on %s\n",
 		status<0?"new action":"timeout",
 		xml_action->name, task, rsc_id, target);
 	fprintf(msg_te_strm, "[Sent ]\t%s\n",
 		dump_xml_formatted(fragment));
 	fflush(msg_te_strm);
 #endif
 	
 	send_ipc_request(crm_ch, options, fragment,
 			 NULL, sys_to, CRM_SYSTEM_TENGINE,
 			 NULL, NULL);
 	
 	free_xml(fragment);
 	free_xml(options);
 	free_xml(state);
 	
 	return TRUE;
 }
 		
diff --git a/crm/test/1node.sh b/crm/test/1node.sh
index 2682e87f47..fa919e06f9 100644
--- a/crm/test/1node.sh
+++ b/crm/test/1node.sh
@@ -1,94 +1,94 @@
 #!/bin/bash
 #
 # Copyright (C) 2004 Andrew Beekhof  <andrew@beekhof.net>
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
 # of the License, or (at your option) any later version.
 # 
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #
 
 . helper.sh
 #. @libdir@/heartbeat/crmtest/helper.sh
 
 CRM_ERR_SHUTDOWN=1
 
 # make *sure* theres nothing left over from last time
 # stop all running HAs
 do_cmd remote_cmd $INIT_USER $test_node_1 $HALIB_DIR/heartbeat "-k" "2>&1 >/dev/null"
 do_cmd remote_cmd $INIT_USER $test_node_2 $HALIB_DIR/heartbeat "-k" "2>&1 >/dev/null"
 
 # be *very* sure everything has stopped
 do_cmd remote_cmd $INIT_USER $test_node_1 "killall -q9 heartbeat ccm lrmd crmd"
 do_cmd remote_cmd $INIT_USER $test_node_2 "killall -q9 heartbeat ccm lrmd crmd"
 
 # make *sure* theres nothing left over from last time
 do_cmd remote_cmd $INIT_USER $test_node_1 "rm -f $HAVAR_DIR/crm/cib*.xml"
 do_cmd remote_cmd $INIT_USER $test_node_2 "rm -f $HAVAR_DIR/crm/cib*.xml"
 
 do_cmd remote_cmd $INIT_USER $test_node_1 $HALIB_DIR/heartbeat -M "2>&1 >/dev/null" &
 
 # start HA anew
 do_cmd echo "wait for HA to start"
 do_cmd ./testutils.pl --search -a -m 1500 -s "${test_node_1} ccm(.*): info: Hostname: ${test_node_1}" -s "${test_node_1} heartbeat(.*) info: Starting(.*)lrmd" -e "${test_node_1} heartbeat(.*)Client(.*) respawning too fast"
 cts_assert "Startup of Heartbeat on ${test_node_1} failed."
 
 do_cmd remote_cmd $CRMD_USER $test_node_1 $HALIB_DIR/crmd -VVVV "2>&1 >/dev/null" &
 
 do_cmd echo "wait for CRMd to start"
 do_cmd ./testutils.pl --search  -a -m 1500 -s "${test_node_1} crmd(.*): info:(.*)FSA Hostname: ${test_node_1}"
 cts_assert "CRMd startup on ${test_node_1} failed."
 
 do_cmd wait_for_state S_IDLE 30 $test_node_1 
 cts_assert "S_IDLE not reached on $test_node_1 (startup)!"
 
 # Create the CIB for this test and wait for all transitions to complete
 #do_cmd make_node $test_node_1 $test_node_1
 args="<nvpair name=\"1\" value=\"${ip_rsc_1}\"/>"
 do_cmd make_resource $test_node_1 rsc1 heartbeat IPaddr - - $args
 args="<nvpair name=\"1\" value=\"${ip_rsc_2}\"/>"
 do_cmd make_resource $test_node_1 rsc2 heartbeat IPaddr - - $args
 do_cmd make_constraint $test_node_1 rsc1 can
 do_cmd make_constraint $test_node_1 rsc2 can
-do_cmd wait_for_state S_IDLE 10 $test_node_1 
+do_cmd wait_for_state S_IDLE 30 $test_node_1 
 cts_assert "S_IDLE not reached on $test_node_1 after CIB create"
 
 do_cmd is_running rsc1 $test_node_1
 cts_assert "rsc1 NOT running"
 
 do_cmd is_running rsc2 $test_node_1
 cts_assert "rsc2 NOT running"
 
 do_cmd is_dc $test_node_1
 cts_assert "$test_node_1 is supposed to be the DC"
 
 do_cmd is_running rsc1 $test_node_1 x$test_node_1
 cts_assert_false "rsc1 IS running on x$test_node_1"
 
 do_cmd is_running rsc1 $test_node_1 $test_node_1
 cts_assert "rsc1 NOT running on $test_node_1"
 
 do_cmd is_running rsc2 $test_node_1 $test_node_1
 cts_assert "rsc2 NOT running on $test_node_1"
 
 # shutdown
 do_cmd remote_cmd $CRMD_USER $test_node_1 $HALIB_DIR/crmadmin -K $test_node_1
 do_cmd wait_for_state S_PENDING 30 $test_node_1 
 cts_assert "S_PENDING not reached on $test_node_1!"
 
 # escalate the shutdown
 do_cmd remote_cmd $CRMD_USER $test_node_1 $HALIB_DIR/crmadmin -K $test_node_1
 
 # just in case
 do_cmd remote_cmd $CRMD_USER $test_node_1 killall -9q crmd
 
 echo "test: PASSED"
diff --git a/crm/test/2node.sh b/crm/test/2node.sh
index 91d667f2e3..ef7c947b07 100644
--- a/crm/test/2node.sh
+++ b/crm/test/2node.sh
@@ -1,185 +1,185 @@
 #!/bin/bash
 #
 # Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
 # of the License, or (at your option) any later version.
 # 
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #
 
 . helper.sh
 
 CRM_ERR_SHUTDOWN=0
 
 
 
 # stop all running HAs
 do_cmd remote_cmd $INIT_USER $test_node_1 $HALIB_DIR/heartbeat "-k" "2>&1 >/dev/null"
 do_cmd remote_cmd $INIT_USER $test_node_2 $HALIB_DIR/heartbeat "-k" "2>&1 >/dev/null"
 
 # be *very* sure everything has stopped
 do_cmd remote_cmd $INIT_USER $test_node_1 "killall -q9 heartbeat ccm lrmd crmd"
 do_cmd remote_cmd $INIT_USER $test_node_2 "killall -q9 heartbeat ccm lrmd crmd"
 
 # make *sure* theres nothing left over from last time
 do_cmd remote_cmd $INIT_USER $test_node_1 "rm -f $HAVAR_DIR/crm/cib*.xml"
 do_cmd remote_cmd $INIT_USER $test_node_2 "rm -f $HAVAR_DIR/crm/cib*.xml"
 
 do_cmd remote_cmd $INIT_USER $test_node_1 $HALIB_DIR/heartbeat -M "2>&1 >/dev/null" &
 
 do_cmd echo "wait for HA to start"
 do_cmd ./testutils.pl --search -a -m 1500 -s "${test_node_1} ccm(.*): info: Hostname: ${test_node_1}" -s "${test_node_1} heartbeat(.*) info: Starting(.*)lrmd" -e "${test_node_1} heartbeat(.*)Client(.*) respawning too fast"
 cts_assert "Startup of Heartbeat on ${test_node_1} failed."
 
 do_cmd remote_cmd $CRMD_USER $test_node_1 $HALIB_DIR/crmd -VVVV "2>&1 >/dev/null" &
 
 do_cmd echo "wait for CRMd to start"
 do_cmd ./testutils.pl --search  -a -m 1500 -s "${test_node_1} crmd(.*): info:(.*)FSA Hostname: ${test_node_1}"
 cts_assert "CRMd startup on ${test_node_1} failed."
 
 do_cmd wait_for_state S_IDLE 30 $test_node_1 
 cts_assert "S_IDLE not reached on $test_node_1 (startup)!"
 
 # Erase the contents of the CIB and wait for things to settle down
 #do_cmd remote_cmd $CRMD_USER $test_node_1 $HALIB_DIR/cibadmin -E 
 #do_cmd wait_for_state S_IDLE 10 $test_node_1 
 #cts_assert "S_IDLE not reached on $test_node_1 after CIB erase"
 
 # Create the CIB for this test and wait for all transitions to complete
 #do_cmd make_node $test_node_1 $test_node_1
 #do_cmd make_node $test_node_1 $test_node_2
 args="<nvpair name=\"1\" value=\"${ip_rsc_1}\"/>"
 do_cmd make_resource $test_node_1 rsc1 heartbeat IPaddr - - $args
 args="<nvpair name=\"1\" value=\"${ip_rsc_2}\"/>"
 do_cmd make_resource $test_node_1 rsc2 heartbeat IPaddr - - $args
 
 #do_cmd make_constraint $test_node_1 rsc1 can
 uuid1=`uuidgen`
 uuid2=`uuidgen`
 uuid3=`uuidgen`
 rsc=rsc1
     
 node_xml="'<rsc_location id=\"${uuid1}\" rsc=\"${rsc}\">
         <rule id=\"${uuid2}\" result=\"can\"/>
 	<rule id=\"${uuid3}\" score=\"1000\" boolean_op=\"or\">
 	  <expression attribute=\"uname\" operation=\"eq\" value=\"${test_node_1}\"/>
 	</rule>
       </rsc_location>'"
 do_cmd make_constraint_adv $test_node_1 $node_xml
 
 #do_cmd make_constraint $test_node_1 rsc2 can
 uuid1=`uuidgen`
 uuid2=`uuidgen`
 uuid3=`uuidgen`
 rsc=rsc2
     
 node_xml="'<rsc_location id=\"${uuid1}\" rsc=\"${rsc}\">
 	        <rule id=\"${uuid2}\" result=\"can\"/>
 		<rule id=\"${uuid3}\" score=\"1000\" boolean_op=\"or\">
 		   <expression attribute=\"uname\" operation=\"eq\" value=\"${test_node_2}\"/>
 		</rule>
 	   </rsc_location>'"
 do_cmd make_constraint_adv $test_node_1 $node_xml
 
-do_cmd wait_for_state S_IDLE 10 $test_node_1 
+do_cmd wait_for_state S_IDLE 30 $test_node_1 
 cts_assert "S_IDLE not reached on $test_node_1 (CIB create)!"
 
 do_cmd is_running rsc1 $test_node_1
 cts_assert "rsc1 NOT running"
 
 do_cmd is_running rsc2 $test_node_1
 cts_assert "rsc2 NOT running"
 
 do_cmd is_dc $test_node_1
 cts_assert "$test_node_1 is supposed to be the DC"
 
 do_cmd is_running rsc1 $test_node_1 x$test_node_1
 cts_assert_false "rsc1 IS running on x$test_node_1"
 
 do_cmd is_running rsc1 $test_node_1 $test_node_1
 cts_assert "rsc1 NOT running on $test_node_1"
 
 do_cmd is_running rsc2 $test_node_1 $test_node_1
 cts_assert "rsc2 NOT running on $test_node_1"
 
 do_cmd remote_cmd $INIT_USER $test_node_2 $HALIB_DIR/heartbeat -M "2>&1 >/dev/null" &
 do_cmd echo "wait for HA to start on $test_node_2"
 do_cmd ./testutils.pl --search -a -m 1500 -s "${test_node_2} ccm(.*) Hostname: ${test_node_2}" -s "${test_node_2} heartbeat(.*): info: Starting (.*)lrmd" -e "${test_node_2} heartbeat(.*) Client (.*) respawning too fast"
 cts_assert "Startup of Heartbeat on ${test_node_2} failed."
 
 do_cmd remote_cmd $CRMD_USER $test_node_2 $HALIB_DIR/crmd  "-VVVV" "2>&1 >/dev/null" &
 
 #do_cmd wait_for_state S_INTEGRATION 30 $test_node_1 
 #cts_assert "S_INTEGRATION not reached on $test_node_1 (new node)!"
 do_cmd echo "wait for CRMd to start on $test_node_2"
 do_cmd ./testutils.pl --search -a -m 1500  -s "${test_node_2} crmd(.*)FSA Hostname: ${test_node_2}" -s "${test_node_2} crmd(.*) Performing op start(.*) on rsc2"
 cts_assert "CRMd startup on ${test_node_2} failed."
 
 #do_cmd echo "wait for transition to complete"
 #do_cmd ./testutils.pl --search $logfile '"${test_node_2} crmd(.*)erforming op start(.*) on rsc2"' 1 1500
 #cts_assert "Transition of rsc2 to ${test_node_2} failed."
 
 do_cmd wait_for_state S_NOT_DC 30 $test_node_2 
 cts_assert "S_NOT_DC not reached on $test_node_2 (startup - 2)!"
 
 do_cmd wait_for_state S_IDLE 30 $test_node_1 
 cts_assert "S_IDLE not reached on $test_node_1 (startup - 2)!"
 
 do_cmd is_running rsc1 $test_node_1
 cts_assert "rsc1 NOT running"
 
 do_cmd is_running rsc2 $test_node_1
 cts_assert "rsc2 NOT running"
 
 do_cmd is_running rsc1 $test_node_1 $test_node_1
 cts_assert "rsc1 NOT running on $test_node_1"
 
 do_cmd is_running rsc2 $test_node_1 $test_node_2
 cts_assert "rsc2 NOT running on $test_node_2"
 
 do_cmd remote_cmd $CRMD_USER $test_node_1 $HALIB_DIR/crmadmin -K $test_node_1 &
 
 do_cmd echo "Looking for transition messages"
 do_cmd ./testutils.pl --search -a -m 1500 -s "${test_node_2} crmd(.*) State transition (.*) -> \"S_ELECTION\"" -s "${test_node_1} crmd(.*) State transition (.*) -> \"S_NOT_DC\"" -s "${test_node_1} crmd(.*)State transition (.*) -> \"S_STOPPING\""
 cts_assert "Shutdown of ${test_node_1} followed by stability on ${test_node_2} failed."
 
 do_cmd wait_for_state S_IDLE 60 $test_node_2 
 cts_assert "S_IDLE not reached on $test_node_2!"
 
 do_cmd is_running rsc1 $test_node_2
 cts_assert "rsc1 NOT running"
 
 do_cmd is_running rsc2 $test_node_2
 cts_assert "rsc2 NOT running"
 
 do_cmd is_running rsc1 $test_node_2 $test_node_1
 cts_assert_false "rsc1 IS running on $test_node_1"
 
 do_cmd is_running rsc2 $test_node_2 $test_node_2
 cts_assert "rsc2 NOT running on $test_node_2"
 
 do_cmd remote_cmd $CRMD_USER $test_node_2 $HALIB_DIR/crmadmin -K $test_node_2
 
 do_cmd wait_for_state S_PENDING 30 $test_node_2 
 cts_assert "S_PENDING not reached on $test_node_2!"
 
 # escalate the shutdown
 do_cmd remote_cmd $CRMD_USER $test_node_2 $HALIB_DIR/crmadmin -K $test_node_2 &
 
 do_cmd ./testutils.pl --search -a -m 1500 -s "${test_node_2} crmd(.*)State transition \"S_PENDING\" -> \"S_STOPPING\""
 cts_assert "Shutdown of ${test_node_2} failed."
 
 # just in case
 do_cmd remote_cmd $CRMD_USER $test_node_2 killall -9 crmd
 
 echo "test: PASSED"
diff --git a/crm/test/testutils.pl b/crm/test/testutils.pl
index dd164742fa..64359da2be 100755
--- a/crm/test/testutils.pl
+++ b/crm/test/testutils.pl
@@ -1,157 +1,157 @@
 #!/usr/bin/perl
 
  # Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  # 
  # This program is free software; you can redistribute it and/or
  # modify it under the terms of the GNU General Public
  # License as published by the Free Software Foundation; either
  # version 2.1 of the License, or (at your option) any later version.
  # 
  # This software is distributed in the hope that it will be useful,
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  # General Public License for more details.
  # 
  # You should have received a copy of the GNU General Public
  # License along with this library; if not, write to the Free Software
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  #
 
 $in_exp=0;
 $in_err_exp=0;
 $match_all=0;
 $max_lines=0;
 $log_file="/var/log/messages";
 
 @search_for = ();
 @errors     = ();
 
 while ( $_ = @ARGV[0], /^-/ ) {
     shift;
     if ( /^--search/ ) {
 	$do_search = 1 ;
 
     } elsif ( /^-m/ ) {
 	$max_lines = $ARGV[0];
 	shift;
 
     } elsif ( /^-l/ ) {
 	$log_file = $ARGV[0];
 	shift;
 
     } elsif (  /^-a/ ) {
 	$match_all = 1;
 
     } elsif ( /^-s/ ) {
 	$this_exp="";
 	while( @ARGV ) {
 	    last if $ARGV[0] =~ /^-/;
 	    $this_exp=$this_exp." ".$ARGV[0];
 	    shift;
 	}
 	$this_exp=substr($this_exp, 1);
 	print STDOUT "Found search expression: _${this_exp}_\n";
 	push @search_for, $this_exp;
 
     } elsif ( /^-e/ ) {
 	$this_exp="";
 	while( @ARGV ) {
 	    last if $ARGV[0] =~ /^-/;
 	    $this_exp=$this_exp." ".$ARGV[0];
 	    shift;
 	}
 	$this_exp=substr($this_exp, 1);
 	print STDOUT "Found error expression: _${this_exp}_\n";
 	push @errors, $this_exp;
     } else {
 	print STDOUT "huh? $_\n";
     }
 }
 
 if( $do_search eq 1 ) {
     $rc=string_search();
     print STDOUT "Search returned: $rc\n";
     exit $rc;
 }
 
 sub remote_command() {
     my ($user, $host, @command) = @_;
 
     my $args = "";
 
     foreach $arg ( @command ) {
 	$args = $args." ".$arg;
     }
 
     print STDOUT "Running \'".$args."\' as ".$user."@".$host."\n";
     $rc = system "/usr/bin/ssh", "-l", $user, $host, $args;
     return $rc;
 }
 
 
 sub string_search() {
 
     my %results    = {};
     my $num_lines  = 0;
 
-    print STDOUT "Starting search...\n";
+    print STDOUT "Starting search in $log_file...\n";
     open(LOG, $log_file);
 
     seek LOG, 0, 2;
 
     for(;;)
     {
-	print STDOUT "Checking $log_file for more data...\n";
+#	print STDOUT "Checking $log_file for more data...\n";
 	for($curpos = tell LOG; $_ = <LOG>; $curpos = tell LOG) 
 	{
 	    my $lpc = 0;
 	    $line = $_;
 	    $num_lines = $num_lines + 1;
 	    
 #	    print STDOUT "Checking line[".$num_lines."]: ".$line;
 	    
 	    if($max_lines > 0 && $num_lines > $max_lines) {
 		return -1000;
 	    }
 	    
 	    foreach $regex (@search_for) {
 		$lpc = $lpc +1;
 		if ( $line =~ /$regex/ ) {
-		    print STDOUT "Found match for (".$regex."): ".$line;
+		    print STDOUT "Found match for (".$regex."): \n\t".$line;
 		    if($match_all eq "0") {
 			return $lpc; 
 		    } else {
 			if( $results{$regex} ne "" ) {
 			    $results{$regex} = $results{$regex} + 1;
 			} else {
 			    $results{$regex} = 1;
 			}
 			$found = scalar(keys %results)-1;
 			print STDOUT "Found ".$found." keys of ".scalar(@search_for)."\n";
 			if(scalar(@search_for) < scalar(keys %results)) {
 			    
 			    foreach $key (sort keys %results) {
 				print STDOUT "Found key \'".$key."\' ".$results{$key}." times.\n" if $results{$key} ne "";
 			    }
 			    return 0;
 			}
 		    }
 		}
 	    }
 	    
 	    $lpc = 0;
 	    foreach $regex ( @errors ) {
 		$lpc = $lpc +1;
 		if ( $line =~ /$regex/ ) {
 		    print STDOUT "Found ERROR match for (".$regex."): ".$line;
 		    return 0-$lpc;
 		}
 	    }
 	}
 	sleep 3;
 	seek LOG, $curpos, 0;
     }
 #    print STDOUT "No more lines\n";
     return -2000;
 }
 
diff --git a/include/crm/crm.h b/include/crm/crm.h
index 4fa3bcd60d..84b56bcbb5 100644
--- a/include/crm/crm.h
+++ b/include/crm/crm.h
@@ -1,176 +1,179 @@
-/* $Id: crm.h,v 1.23 2004/09/15 20:19:23 andrew Exp $ */
+/* $Id: crm.h,v 1.24 2004/09/17 13:03:10 andrew Exp $ */
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #ifndef CRM__H
 #define CRM__H
 
 #include <stdlib.h>
 #include <ha_config.h>
 #include <glib.h>
 
 #include <string.h>
 #include <clplumbing/cl_log.h>
 #include <clplumbing/cl_malloc.h>
 #ifdef MCHECK
 #include <mcheck.h>
 #endif
 #include <crm/common/util.h>
 
 /* Clean these up at some point, some probably should be runtime options */
 #define WORKING_DIR	HA_VARLIBDIR"/heartbeat/crm"
 #define BIN_DIR		"/usr/lib/heartbeat"
 #define MAXDATASIZE	65535 /* ipc comms */
 #define SOCKET_LEN	1024
 #define APPNAME_LEN	256
 #define LOG_DIR		"/var/log"
 #define MAX_IPC_FAIL	5
 #define CIB_FILENAME	WORKING_DIR"/cib.xml"
 #define CIB_BACKUP	WORKING_DIR"/cib_backup.xml"
 
 #define DEVEL_CIB_COPY   1
 #define DEVEL_DIR	"/tmp/crm"
 
 #define CRM_VERSION	"0.6"
 
 #define MSG_LOG			1
 #define DOT_FSA_ACTIONS		1
 #define DOT_ALL_FSA_INPUTS	1
 #define FSA_TRACE		1
 /* #define USE_FAKE_LRM		1 */
 
 /* Sub-systems */
 #define CRM_SYSTEM_DC		"dc"
 #define CRM_SYSTEM_DCIB		"dcib" /*  The master CIB */
 #define CRM_SYSTEM_CIB		"cib"
 #define CRM_SYSTEM_CRMD		"crmd"
 #define CRM_SYSTEM_LRMD		"lrmd"
 #define CRM_SYSTEM_PENGINE	"pengine"
 #define CRM_SYSTEM_TENGINE	"tengine"
 
 /* Valid operations */
 #define CRM_OP_BUMP		"bump"
 #define CRM_OP_QUERY		"query"
 #define CRM_OP_CREATE		"create"
 #define CRM_OP_UPDATE		"update"
 #define CRM_OP_DELETE		"delete"
 #define CRM_OP_ERASE		"erase"
 #define CRM_OP_STORE		"store"
 #define CRM_OP_REPLACE		"replace"
 #define CRM_OP_FORWARD		"forward"
 #define CRM_OP_JOINACK		"join_ack"
 #define CRM_OP_WELCOME		"welcome"
 #define CRM_OP_PING		"ping"
 #define CRM_OP_VOTE		"vote"
 #define CRM_OP_HELLO		"hello"
 #define CRM_OP_ANNOUNCE		"announce"
 #define CRM_OP_HBEAT		"dc_beat"
 #define CRM_OP_PECALC		"pe_calc"
 #define CRM_OP_ABORT		"abort"
 #define CRM_OP_QUIT		"quit"
 #define CRM_OP_SHUTDOWN 	"shutdown_crm"
 #define CRM_OP_EVENTCC		"event_cc"
 #define CRM_OP_TEABORT		"te_abort"
 #define CRM_OP_TRANSITION	"transition"
 #define CRM_OP_TECOMPLETE	"te_complete"
 #define CRM_OP_SHUTDOWN_REQ	"req_shutdown"
 
 #define CRMD_STATE_ACTIVE	"member"
 #define CRMD_STATE_INACTIVE	"down"
 
 #define CRMD_JOINSTATE_DOWN	"down"
 #define CRMD_JOINSTATE_PENDING	"pending"
 #define CRMD_JOINSTATE_MEMBER	"member"
 
 #define CRMD_RSCSTATE_START		"start"
 #define CRMD_RSCSTATE_START_PENDING	"starting"
 #define CRMD_RSCSTATE_START_OK		"running"
 #define CRMD_RSCSTATE_START_FAIL	"start_failed"
 #define CRMD_RSCSTATE_STOP		"stop"
 #define CRMD_RSCSTATE_STOP_PENDING	"stopping"
 #define CRMD_RSCSTATE_STOP_OK		"stopped"
 #define CRMD_RSCSTATE_STOP_FAIL		"stop_failed"
 #define CRMD_RSCSTATE_MON		"status"
 #define CRMD_RSCSTATE_MON_PENDING	CRMD_RSCSTATE_START_OK
 #define CRMD_RSCSTATE_MON_OK		CRMD_RSCSTATE_START_OK
 #define CRMD_RSCSTATE_MON_FAIL		"status_failed"
 /* #define CRMD_RSCSTATE_GENERIC		"pending" */
 #define CRMD_RSCSTATE_GENERIC_PENDING	"pending"
 #define CRMD_RSCSTATE_GENERIC_OK	"complete"
 #define CRMD_RSCSTATE_GENERIC_FAIL	"pending_failed"
 
 typedef GList* GListPtr;
 
 #define safe_str_eq(x, y)  (x!=NULL && y!=NULL && strcmp(x,y) == 0)
 #define safe_str_neq(x, y) (x != y && (x==NULL || y==NULL || strcmp(x,y) != 0))
 
 #define slist_iter(w, x, y, z, a) for(z = 0; z < g_list_length(y);  z++) { \
 		x *w = (x*)g_list_nth_data(y, z);			\
 		a;							\
 	}
 
 /* Developmental debug stuff */
 
 #define LOG_VERBOSE  LOG_DEBUG+1
 #define LOG_DEV      LOG_DEBUG+2
 #define LOG_TRACE    LOG_DEBUG+3
 
 #if 1
 #  define crm_crit(w...)    do_crm_log(LOG_CRIT,    __FUNCTION__, w)
 #  define crm_err(w...)     do_crm_log(LOG_ERR,     __FUNCTION__, w)
 #  define crm_warn(w...)    do_crm_log(LOG_WARNING, __FUNCTION__, w)
 #  define crm_notice(w...)  do_crm_log(LOG_NOTICE,  __FUNCTION__, w)
 #  define crm_info(w...)    do_crm_log(LOG_INFO,    __FUNCTION__, w)
 #  define crm_debug(w...)   do_crm_log(LOG_DEBUG,   __FUNCTION__, w)
 #  define crm_devel(w...)   do_crm_log(LOG_DEV,     __FUNCTION__, w)
 #  define crm_verbose(w...) do_crm_log(LOG_VERBOSE, __FUNCTION__, w)
 #  define crm_trace(w...)   do_crm_log(LOG_TRACE,   __FUNCTION__, w)
 #else
 #  define crm_crit(w...)    cl_log(LOG_CRIT,    w)
 #  define crm_err(w...)     cl_log(LOG_ERR,     w)
 #  define crm_warn(w...)    cl_log(LOG_WARNING, w)
 #  define crm_notice(w...)  cl_log(LOG_NOTICE,  w)
 #  define crm_info(w...)    cl_log(LOG_INFO,    w)
 #  define crm_debug(w...)   cl_log(LOG_DEBUG,   w)
 #  define crm_devel(w...)   cl_log(LOG_DEV,     w)
 #  define crm_verbose(w...) cl_log(LOG_VERBOSE, w)
 #  define crm_trace(w...)   cl_log(LOG_TRACE,   w)
 #endif
 
 #define crm_debug_action(x) if(crm_log_level >= LOG_DEBUG) {	\
 		x;						\
 	}
 
 #define crm_info_action(x) if(crm_log_level >= LOG_INFO) {	\
 		x;						\
 	}
 
 #define crm_xml_crit(x,y)    print_xml_formatted(LOG_CRIT,   __FUNCTION__, x,y)
 #define crm_xml_err(x,y)     print_xml_formatted(LOG_ERR,    __FUNCTION__, x,y)
 #define crm_xml_warn(x,y)    print_xml_formatted(LOG_WARNING,__FUNCTION__, x,y)
 #define crm_xml_notice(x,y)  print_xml_formatted(LOG_NOTICE, __FUNCTION__, x,y)
 #define crm_xml_info(x,y)    print_xml_formatted(LOG_INFO,   __FUNCTION__, x,y)
 #define crm_xml_debug(x,y)   print_xml_formatted(LOG_DEBUG,  __FUNCTION__, x,y)
 #define crm_xml_devel(x,y)   print_xml_formatted(LOG_DEV,    __FUNCTION__, x,y)
 #define crm_xml_verbose(x,y) print_xml_formatted(LOG_VERBOSE,__FUNCTION__, x,y)
 #define crm_xml_trace(x,y)   print_xml_formatted(LOG_TRACE,  __FUNCTION__, x,y)
 
-#define crm_malloc(x) malloc(x)
+#define crm_malloc(x,y) x = malloc(y);	\
+	if(x == NULL) {			\
+		crm_crit("out of memory");	\
+	}
 #define crm_strdup(x) strdup(x)
 #define crm_free(x)   if(x) { free(x); x=NULL; }
-
+#define crm_str(x)    (const char*)(x?x:"<null>")
 #endif