diff --git a/crm/cib/cibio.c b/crm/cib/cibio.c
index d2701b9e21..2f9aa51068 100644
--- a/crm/cib/cibio.c
+++ b/crm/cib/cibio.c
@@ -1,419 +1,421 @@
-/* $Id: cibio.c,v 1.27 2004/06/03 07:52:16 andrew Exp $ */
+/* $Id: cibio.c,v 1.28 2004/06/07 21:28:39 msoffen 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 <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/stat.h>
 
 #include <string.h>
 #include <stdlib.h>
 
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 
 #include <cibio.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/common/util.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 const char * local_resource_path[] =
 {
 	XML_CIB_TAG_STATUS,
 };
 
 const char * resource_path[] =
 {
 	XML_CIB_TAG_RESOURCES,
 };
 
 const char * node_path[] =
 {
 	XML_CIB_TAG_NODES,
 };
 
 const char * constraint_path[] =
 {
 	XML_CIB_TAG_CONSTRAINTS,
 };
 
 gboolean initialized = FALSE;
 xmlNodePtr the_cib = NULL;
 xmlNodePtr node_search = NULL;
 xmlNodePtr resource_search = NULL;
 xmlNodePtr constraint_search = NULL;
 xmlNodePtr status_search = NULL;
 
 /*
  * It is the callers responsibility to free both the new CIB (output)
  *     and the new CIB (input)
  */
 xmlNodePtr
 createEmptyCib(void)
 {
 	xmlNodePtr cib_root = NULL, config = NULL, status = NULL;
 	
 	cib_root = create_xml_node(NULL, XML_TAG_CIB);
 
 	config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION);
 	status = create_xml_node(cib_root, XML_CIB_TAG_STATUS);
 
 	set_node_tstamp(cib_root);
 	set_node_tstamp(config);
 	set_node_tstamp(status);
 	
 	set_xml_property_copy(cib_root, "version", "1");
 	set_xml_property_copy(cib_root, "generated", XML_BOOLEAN_TRUE);
 
 	create_xml_node(config, XML_CIB_TAG_NODES);
 	create_xml_node(config, XML_CIB_TAG_RESOURCES);
 	create_xml_node(config, XML_CIB_TAG_CONSTRAINTS);
 	
 	if (verifyCibXml(cib_root)) {
 		return cib_root;
 	}
 	crm_crit(
 	       "The generated CIB did not pass integrity testing!!"
 	       "  All hope is lost.");
 	return NULL;
 }
 
 gboolean
 verifyCibXml(xmlNodePtr cib)
 {
 	gboolean is_valid = TRUE;
 	xmlNodePtr tmp_node = NULL;
 	
 
 	if (cib == NULL) {
 		crm_err("XML Buffer was empty.");
 		return FALSE;
 	}
 	
 	tmp_node = get_object_root(XML_CIB_TAG_NODES, cib);
 	if (tmp_node == NULL) is_valid = FALSE;
 
 	tmp_node = get_object_root(XML_CIB_TAG_RESOURCES, cib);
 	if (tmp_node == NULL) is_valid = FALSE;
 
 	tmp_node = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib);
 	if (tmp_node == NULL) is_valid = FALSE;
 
 	tmp_node = get_object_root(XML_CIB_TAG_STATUS, cib);
  	if (tmp_node == NULL) is_valid = FALSE;
 
 	// more integrity tests
 
 	return is_valid;
 }
 
 /*
  * It is the callers responsibility to free the output of this function
  */
 xmlNodePtr
 readCibXml(char *buffer)
 {
 	xmlNodePtr root = string2xml(buffer);
 	if (verifyCibXml(root) == FALSE) {
 		free_xml(root);
 		return createEmptyCib();
 	}
 	return root;
 }
 
 /*
  * It is the callers responsibility to free the output of this function
  */
 xmlNodePtr
 readCibXmlFile(const char *filename)
 {
 	int s_res = -1;
 	struct stat buf;
 	xmlNodePtr root = NULL;
 	
 
 	if(filename != NULL) {
 		s_res = stat(filename, &buf);
 	}
 	
 	if (s_res == 0) {
 		FILE *cib_file = fopen(filename, "r");
 		root = file2xml(cib_file);
 		set_xml_property_copy(root, "generated", XML_BOOLEAN_FALSE);
 		fclose(cib_file);
 		
 	} else {
 		crm_warn("Stat of (%s) failed, file does not exist.",
 			 CIB_FILENAME);
 	}
 	
 	if (verifyCibXml(root) == FALSE) {
 		free_xml(root);
 //		return createEmptyCib();
 		root = NULL;
 	}
 
 	return root;
 }
 
 /*
  * The caller should never free the return value
  */
 xmlNodePtr
 get_the_CIB(void)
 {
 	
 	return the_cib;
 }
 
 gboolean
 uninitializeCib(void)
 {
 	xmlNodePtr tmp_cib = the_cib;
 	
 	
 	if(tmp_cib == NULL) {
 		crm_err("The CIB has already been deallocated.");
 		return FALSE;
 	}
 	
 	initialized = FALSE;
 	the_cib = NULL;
 	node_search = NULL;
 	resource_search = NULL;
 	constraint_search = NULL;
 	status_search = NULL;
 
 	crm_err("Deallocating the CIB.");
 	
 	free_xml(tmp_cib);
 
 	crm_err("The CIB has been deallocated.");
 	
 	return TRUE;
 }
 
 
 
 
 /*
  * This method will not free the old CIB pointer or the new one.
  * We rely on the caller to have saved a pointer to the old CIB
  *   and to free the old/bad one depending on what is appropriate.
  */
 gboolean
 initializeCib(xmlNodePtr new_cib)
 {
 	if (verifyCibXml(new_cib)) {
 
 		initialized = FALSE;
 		the_cib = new_cib;
 
 		// update search paths
 		/* not used yet...
 		node_search =
 			get_object_root(XML_CIB_TAG_NODES, new_cib);
 		resource_search =
 			get_object_root(XML_CIB_TAG_RESOURCES, new_cib);
 		constraint_search =
 			get_object_root(XML_CIB_TAG_CONSTRAINTS, new_cib);
 		status_search =
 			get_object_root(XML_CIB_TAG_STATUS, new_cib);
 		*/
 		initialized = TRUE;
 
 		crm_trace("CIB initialized");
 		return TRUE;
 	}
 	else {
 		crm_err("CIB Verification failed");
 	}
 	
 	return FALSE;
     
 }
 
 int
 moveFile(const char *oldname,
 	 const char *newname,
 	 gboolean backup,
 	 char *ext)
 {
 	/* move 'oldname' to 'newname' by creating a hard link to it
 	 *  and then removing the original hard link
 	 */
 	int res = 0;
 	struct stat tmp;
 	int s_res = stat(newname, &tmp);
 	
 	
 	if (s_res >= 0)
 	{
 		if (backup == TRUE) {
 			char backname[1024];
 			static const char *back_ext = "bak";
 			if (ext != NULL) back_ext = (char*)ext;
 	    
 			snprintf(backname, sizeof(backname)-1,
 				 "%s.%s", newname, back_ext);
 			moveFile(newname, backname, FALSE, NULL);
 		} else {
 			res = unlink(newname);
 			if (res < 0) {
 				perror("Could not remove the current backup of Cib");
 				return -1;
 			}
 		}
 	}
     
 	s_res = stat(oldname, &tmp);
 
 	if (s_res >= 0) {
 		res = link(oldname, newname);
 		if (res < 0) {
 			perror("Could not create backup of current Cib");
 			return -2;
 		}
 		res = unlink(oldname);
 		if (res < 0) {
 			perror("Could not unlink the current Cib");
 			return -3;
 		}
 	}
     
 	return 0;
     
 }
 
 
 int
 activateCibBuffer(char *buffer, const char *filename)
 {
 	int result = -1;
 	xmlNodePtr local_cib = NULL;
 	
 	
 	local_cib = readCibXml(buffer);
 	result = activateCibXml(local_cib, filename);
 	
 	return result;
 }
 
 /*
  * This method will free the old CIB pointer on success and the new one
  * on failure.
  */
 int
 activateCibXml(xmlNodePtr new_cib, const char *filename)
 {
 	int error_code = 0;
 	xmlNodePtr saved_cib = get_the_CIB();
 	const char *filename_bak = CIB_BACKUP; // calculate
 	xmlDocPtr foo;
+	time_t now;
+	char *now_str = NULL;
 	
 
 	if (initializeCib(new_cib) == TRUE) {
 		int res = moveFile(filename, filename_bak, FALSE, NULL);
 	
 		if (res  < 0) {
 			crm_info("Could not make backup of the current Cib "
 				 "(code: %d)... aborting update.", res);
 			error_code = -1;
 		} else {
 			crm_info("Writing CIB out to %s", CIB_FILENAME);
 	    
 			if (new_cib->doc == NULL) {
 				foo = xmlNewDoc("1.0");
 				xmlDocSetRootElement(foo, new_cib);
 				xmlSetTreeDoc(new_cib,foo);
 			}
 
-			time_t now = time(NULL);
-			char *now_str = asctime(localtime(&now));
+			now = time(NULL);
+			now_str = asctime(localtime(&now));
 			set_xml_property_copy(new_cib, "last_written",now_str);
 			free(now_str);
 			
 			/* save it.
 			 * set arg 3 to 0 to disable line breaks,1 to enable
 			 * res == num bytes saved
 			 */
 			res = xmlSaveFormatFile(filename,
 						new_cib->doc,
 						1);
 			
 			/* for some reason, reading back after saving with
 			 * line-breaks doesnt go real well 
 			 */
 			crm_info("Saved %d bytes to the Cib as XML",
 				 res);
 	    
 			if (res < 0) {
 				// assume 0 is good
 				if (moveFile(filename_bak,
 					     filename,
 					     FALSE,
 					     NULL) < -1) {
 					crm_crit("Could not restore the "
 						 "backup of the current Cib "
 						 "(code: %d)... panic!",
 						 res);
 					error_code = -2;
 					// should probably exit here 
 				} else if (initializeCib(saved_cib) == FALSE) {
 					// oh we are so dead 
 					crm_crit("Could not re-initialize "
 						 "with the old CIB.  "
 						 "Everything is about to go "
 						 "pear shaped");
 					error_code = -3;
 				} else {
 					crm_crit("Update of Cib failed "
 						 "(code: %d)... reverted to "
 						 "last known valid version",
 						 res);
 					
 					error_code = -4;
 				}
 			}
 		}
 	}
 	else
 	{
 		crm_info("Ignoring invalid or NULL Cib");
 		error_code = -5;
 	}
 
 // Make sure memory is cleaned up appropriately
 	if (error_code != 0) {
 		crm_trace("Freeing new CIB %p", new_cib);
 		free_xml(new_cib);
 	} else {
 		crm_trace("Freeing saved CIB %p", saved_cib);
 		free_xml(saved_cib);
 	}
 
 	return error_code;
     
 }
diff --git a/crm/common/xml.c b/crm/common/xml.c
index 9d33881779..7f27e583cd 100644
--- a/crm/common/xml.c
+++ b/crm/common/xml.c
@@ -1,789 +1,789 @@
-/* $Id: xml.c,v 1.3 2004/06/03 07:52:16 andrew Exp $ */
+/* $Id: xml.c,v 1.4 2004/06/07 21:28:39 msoffen 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 <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_nested(xmlNodePtr root, const char **search_path, int len)
 {
 	int	j;
 	xmlNodePtr child;
 	xmlNodePtr lastMatch;
 	
 
 	if (root == NULL) {
 		return NULL;
 	}
 
 	if(search_path == NULL) {
 		crm_trace("Will never find NULL");
 		return NULL;
 	}
 	
 	
 	dump_array(LOG_TRACE,
 		   "Looking for.",
 		   search_path, len);
 	child = root->children, lastMatch = NULL;
 	for (j=0; j < len; ++j) {
 		gboolean is_found = FALSE;
 		if (search_path[j] == NULL) {
 			len = j; /* a NULL also means stop searching */
 			break;
 		}
 		
 		while(child != NULL) {
 			const char * child_name = (const char*)child->name;
 			crm_trace("comparing (%s) with (%s).",
 				   search_path[j],
 				   child->name);
 			if (strcmp(child_name, search_path[j]) == 0) {
 				lastMatch = child;
 				child = lastMatch->children;
 				crm_trace("found node (%s) @line (%ld).",
 					   search_path[j],
 					   xmlGetLineNo(child));
 				is_found = TRUE;
 				break;
 			}
 			child = child->next;
 		}
 		if (is_found == FALSE) {
 			crm_trace("No more siblings left... %s cannot be found.",
 				search_path[j]);
 			break;
 		}
 	}
 
 	if (j == len
 	    && lastMatch != NULL
 	    && strcmp(lastMatch->name, search_path[j-1]) == 0) {
 		crm_trace("returning node (%s).",
 			   xmlGetNodePath(lastMatch));
 		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)
 {
 
 	if(node_name == NULL) {
 		// set it on the current node
 		return set_xml_attr_nested(parent, NULL, 0,
 					   attr_name, attr_value, create);
 	}
 	return set_xml_attr_nested(parent, &node_name, 1,
 				   attr_name, attr_value, create);
 
 }
 
 xmlNodePtr
 set_xml_attr_nested(xmlNodePtr parent,
 		    const char **node_path, int length,
 		    const char *attr_name,
 		    const char *attr_value,
 		    gboolean create)
 {
 	xmlAttrPtr result        = NULL;
 	xmlNodePtr attr_parent   = NULL;
 	xmlNodePtr create_parent = NULL;
 	xmlNodePtr tmp;
 
 	if(parent == NULL && create == FALSE) {
 		crm_err("Can not set attribute in NULL parent");
 		return NULL;
 	} 
 
 	if(attr_name == NULL || strlen(attr_name) == 0) {
 		crm_err("Can not set attribute to %s with no name",
 		       attr_value);
 		return NULL;
 	}
 
 
 	if(length == 0 && parent != NULL) {
 		attr_parent = parent;
 
 	} else if(length == 0 || node_path == NULL
 		  || *node_path == NULL || strlen(*node_path) == 0) {
 		crm_err(
 		       "Can not create parent to set attribute %s=%s on",
 		       attr_name, attr_value);
 		return NULL;
 		
 	} else {
 		attr_parent = find_xml_node_nested(parent, node_path, length);
 	}
 	
 	if(create && attr_parent == NULL) {
 		int j = 0;
 		attr_parent = parent;
 		for (j=0; j < length; ++j) {
 			if (node_path[j] == NULL) {
 				break;
 			}
 			
 			tmp =
 				find_xml_node(attr_parent, node_path[j]);
 
 			if(tmp == NULL) {
 				attr_parent = create_xml_node(attr_parent,
 							      node_path[j]);
 				if(j==0) {
 					create_parent = attr_parent;
 				}
 				
 			} else {
 				attr_parent = tmp;
 			}
 		}
 		
 	} else if(attr_parent == NULL) {
 		crm_err("Can not find parent to set attribute on");
 		return NULL;
 		
 	}
 	
 	result = set_xml_property_copy(attr_parent, attr_name, attr_value);
 	if(result == NULL) {
 		crm_warn(
 		       "Could not set %s=%s at %s",
 		       attr_name, attr_value, xmlGetNodePath(attr_parent));
 	}
 
 	if(create_parent != NULL) {
 		return create_parent;
 	}
 	
 	return parent;
 }
 
 
 
 xmlNodePtr
 find_xml_node(xmlNodePtr root, const char * search_path)
 {
 	if(root == NULL) return NULL;
 	return find_xml_node_nested(root, &search_path, 1);
 }
 
 xmlNodePtr
 find_entity(xmlNodePtr parent,
 	    const char *node_name,
 	    const char *id,
 	    gboolean siblings)
 {
 	return find_entity_nested(parent,
 				  node_name,
 				  NULL,
 				  NULL,
 				  id,
 				  siblings);
 }
 xmlNodePtr
 find_entity_nested(xmlNodePtr parent,
 		   const char *node_name,
 		   const char *elem_filter_name,
 		   const char *elem_filter_value,
 		   const char *id,
 		   gboolean siblings)
 {
 	xmlNodePtr child;
+	xmlChar *child_id = NULL;
 	
 	crm_trace("Looking for %s elem with id=%s.", node_name, id);
 	while(parent != NULL) {
 		crm_trace("examining (%s).", xmlGetNodePath(parent));
 		child = parent->children;
 	
 		while(child != NULL) {
 			crm_trace("looking for (%s) [name].", node_name);
 			if (node_name != NULL
 			    && strcmp(child->name, node_name) != 0) {    
 				crm_trace(
 					"skipping entity (%s=%s) [node_name].",
 					xmlGetNodePath(child), child->name);
 				break;
 			} else if (elem_filter_name != NULL
 				   && elem_filter_value != NULL) {
 				const char* child_value = (const char*)
 					xmlGetProp(child, elem_filter_name);
 				
 				crm_trace(
 				       "comparing (%s) with (%s) [attr_value].",
 				       child_value, elem_filter_value);
 				if (strcmp(child_value, elem_filter_value)) {
 					crm_trace("skipping entity (%s) [attr_value].",
 						   xmlGetNodePath(child));
 					break;
 				}
 			}
 		
 			crm_trace(
 			       "looking for entity (%s) in %s.",
 			       id, xmlGetNodePath(child));
 			while(child != NULL) {
 				crm_trace(
 				       "looking for entity (%s) in %s.",
 				       id, xmlGetNodePath(child));
-				xmlChar *child_id =
-					xmlGetProp(child, XML_ATTR_ID);
+				child_id = xmlGetProp(child, XML_ATTR_ID);
 
 				if (child_id == NULL) {
 					crm_crit(
 					       "Entity (%s) has id=NULL..."
 					       "Cib not valid!",
 					       xmlGetNodePath(child));
 				} else if (strcmp(id, child_id) == 0) {
 					crm_trace("found entity (%s).", id);
 					return child;
 				}   
 				child = child->next;
 			}
 		}
 
 		if (siblings == TRUE) {
 			crm_trace("Nothing yet... checking siblings");	    
 			parent = parent->next;
 		} else
 			parent = NULL;
 	}
 	crm_info(
 	       "Couldnt find anything appropriate for %s elem with id=%s.",
 	       node_name, id);	    
 	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;
 }
 
 char * 
 dump_xml(xmlNodePtr msg)
 {
 	
 	return dump_xml_node(msg, FALSE);
 }
 
 void
 xml_message_debug(xmlNodePtr msg, const char *text)
 {
 	char *msg_buffer;
 
 	
 	if(msg == NULL) {
 		crm_verbose("%s: %s",
 		   text==NULL?"<null>":text,"<null>");
 		
 		return;
 	}
 	
 	msg_buffer = dump_xml_node(msg, FALSE);
 	crm_verbose("%s: %s",
 		   text==NULL?"<null>":text,
 		   msg_buffer==NULL?"<null>":msg_buffer);
 	crm_free(msg_buffer);
 	return;
 }
 
 char * 
 dump_xml_node(xmlNodePtr msg, gboolean whole_doc)
 {
 	int lpc = 0;
 	int msg_size = -1;
 	xmlChar *xml_message = NULL;
 	xmlBufferPtr xml_buffer;
 
 	
 	if (msg == NULL) return NULL;
 
 	xmlInitParser();
 
 	if (whole_doc) {
 		if (msg->doc == NULL) {
 			xmlDocPtr foo = xmlNewDoc("1.0");
 			xmlDocSetRootElement(foo, msg);
 			xmlSetTreeDoc(msg,foo);
 		}
 		xmlDocDumpMemory(msg->doc, &xml_message, &msg_size);
 	} else {
 		crm_trace("mem used by xml: %d", xmlMemUsed());
 		xmlMemoryDump ();
 	
 		xml_buffer = xmlBufferCreate();
 		msg_size = xmlNodeDump(xml_buffer, msg->doc, msg, 0, 0);
 
 		xml_message =
 			(xmlChar*)crm_strdup(xmlBufferContent(xml_buffer)); 
 		xmlBufferFree(xml_buffer);
 
 		if (!xml_message) {
 			crm_err(
 			       "memory allocation failed in dump_xml_node()");
 		}
 	}
 
 	xmlCleanupParser();
 	
 	// HA wont send messages with newlines in them.
 	for(; xml_message != NULL && lpc < msg_size; lpc++)
 		if (xml_message[lpc] == '\n')
 			xml_message[lpc] = ' ';
     
 	return (char*)xml_message; 
 }
 
 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);
 	if (name == NULL || strlen(name) <= 0) {
 		ret_value = NULL;
 		
 	} else if(node == 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
 	else if (a_node->doc != NULL)
 		xmlFreeDoc(a_node->doc);
 	else
 	{
 		/* 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)));
 	
 	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, node_iter = 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;
 			
 		}
 
 		node_iter = src_node->children;
 		while(node_iter != 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);
 			} 				
 			node_iter = node_iter->next;
 		}
 
 		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);
 
 	xml_message_debug(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>");
 	}
 	
 	for (j=0; j < depth && array[j] != NULL; j++) {
 		if (array[j] == NULL) break;
 		do_crm_log(log_level, __FUNCTION__,  "\t--> (%s).", array[j]);
 	}
 }
diff --git a/crm/crmd/election.c b/crm/crmd/election.c
index d9a9ff38e1..815047a5d1 100644
--- a/crm/crmd/election.c
+++ b/crm/crmd/election.c
@@ -1,384 +1,383 @@
 /* 
  * 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/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/xml.h>
 #include <crm/crm.h>
 #include <crmd_fsa.h>
 #include <crmd_messages.h>
 #include <crmd_callbacks.h>
 
 #include <crm/dmalloc_wrapper.h>
 
 void ghash_count_vote(gpointer key, gpointer value, gpointer user_data);
 
 /*	A_ELECTION_VOTE	*/
 enum crmd_fsa_input
 do_election_vote(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 election_result = I_NULL;
 	
 
 	/* dont vote if we're in one of these states or wanting to shut down */
 	switch(cur_state) {
 		case S_RECOVERY:
 		case S_RECOVERY_DC:
 		case S_STOPPING:
 		case S_RELEASE_DC:
 		case S_TERMINATE:
 			return I_NULL;
 			// log warning
 			break;
 		default:
 			if(is_set(fsa_input_register, R_SHUTDOWN)) {
 				return I_NULL;
 				// log warning
 			}
 			break;
 	}
 	
 	send_request(NULL, NULL, CRM_OP_VOTE,
 		     NULL, CRM_SYSTEM_CRMD, NULL);
 	
 	return election_result;
 }
 
 gboolean
 do_dc_heartbeat(gpointer data)
 {
 	fsa_timer_t *timer = (fsa_timer_t *)data;
 //	crm_debug("#!!#!!# Heartbeat timer just popped!");
 	
 	gboolean was_sent = send_request(NULL, NULL, CRM_OP_HBEAT, 
 					 NULL, CRM_SYSTEM_CRMD, NULL);
 
 	if(was_sent == FALSE) {
 		// this is bad
 		stopTimer(timer); // dont make it go off again
 		s_crmd_fsa(C_HEARTBEAT_FAILED, I_SHUTDOWN, NULL);
 	}
 	
 	return TRUE;
 }
 
 struct election_data_s 
 {
 		const char *winning_uname;
 		unsigned int winning_bornon;
 };
 
 /*	A_ELECTION_COUNT	*/
 enum crmd_fsa_input
 do_election_count_vote(long long action,
 		       enum crmd_fsa_cause cause,
 		       enum crmd_fsa_state cur_state,
 		       enum crmd_fsa_input current_input,
 		       void *data)
 {
 	gboolean we_loose = FALSE;
 	xmlNodePtr vote = (xmlNodePtr)data;
 	enum crmd_fsa_input election_result = I_NULL;
 	const char *vote_from = xmlGetProp(vote, XML_ATTR_HOSTFROM);
-	
-	
+	oc_node_t *our_node = NULL, * your_node = NULL;
+	struct election_data_s election_data;
 
 	if(vote_from == NULL || strcmp(vote_from, fsa_our_uname) == 0) {
 		// dont count our own vote
 		return election_result;
 	}
 
 	if(fsa_membership_copy->members_size < 1) {
 		// if even we are not in the cluster then we should not vote
 		return I_FAIL;
 		
 	}
 
-	oc_node_t *our_node = (oc_node_t*)
+	our_node = (oc_node_t*)
 		g_hash_table_lookup(fsa_membership_copy->members, fsa_our_uname);
 
-	oc_node_t *your_node = (oc_node_t*)
+	your_node = (oc_node_t*)
 		g_hash_table_lookup(fsa_membership_copy->members, vote_from);
 
 #if 0
 	crm_debug("%s (bornon=%d), our bornon (%d)",
 		   vote_from, our_node->born, my_born);
 
 	crm_debug("%s %s %s",
 	       fsa_our_uname,
 	       strcmp(fsa_our_uname, vote_from) < 0?"<":">=",
 	       vote_from);
 #endif
 	
 	if(is_set(fsa_input_register, R_SHUTDOWN)) {
 		crm_debug("Election fail: we are shutting down");
 		we_loose = TRUE;
 
 	} else if(our_node == NULL) {
 		crm_debug("Election fail: we dont exist in the CCM list");
 		we_loose = TRUE;
 		
 	} else if(your_node == NULL) {
 		crm_err("The other side doesnt exist in the CCM list");
 		
 	} else if(your_node->node_born_on < our_node->node_born_on) {
 		crm_debug("Election fail: born_on");
 		we_loose = TRUE;
 
 	} else if(your_node->node_born_on == our_node->node_born_on
 		  && strcmp(fsa_our_uname, vote_from) > 0) {
 		crm_debug("Election fail: uname");
 		we_loose = TRUE;
 
 	} else {
-		struct election_data_s election_data;
 		election_data.winning_uname = NULL;
 		election_data.winning_bornon = -1; // maximum integer
 		
 		crm_trace("We might win... we should vote (possibly again)");
 		election_result = I_DC_TIMEOUT; // new "default"
 
 		g_hash_table_foreach(fsa_membership_copy->members,
 				     ghash_count_vote, &election_data);
 		
 		crm_debug("Election winner should be %s (born_on=%d)",
 		       election_data.winning_uname, election_data.winning_bornon);
 		
 	
 		if(safe_str_eq(election_data.winning_uname, fsa_our_uname)){
 			crm_debug("Election win: lowest born_on and uname");
 			election_result = I_ELECTION_DC;
 		}
 	}
 	
 	if(we_loose) {
 		if(fsa_input_register & R_THE_DC) {
 			crm_debug("Give up the DC");
 			election_result = I_RELEASE_DC;
 			
 		} else {
 			crm_debug("We werent the DC anyway");
 			election_result = I_NOT_DC;
 			
 		}
 	}
 
 	if(we_loose || election_result == I_ELECTION_DC) {
 		// cancel timer, its been decided
 		stopTimer(election_timeout);
 	}
 	
 	return election_result;
 }
 
 /*	A_ELECT_TIMER_START, A_ELECTION_TIMEOUT 	*/
 // we won
 enum crmd_fsa_input
 do_election_timer_ctrl(long long action,
 		    enum crmd_fsa_cause cause,
 		    enum crmd_fsa_state cur_state,
 		    enum crmd_fsa_input current_input,
 		    void *data)
 {
 	
 
 	if(action & A_ELECT_TIMER_START) {
 		startTimer(election_timeout);
 		
 	} else if(action & A_ELECT_TIMER_STOP || action & A_ELECTION_TIMEOUT) {
 		stopTimer(election_timeout);
 		
 	} else {
 		crm_err("unexpected action %s",
 		       fsa_action2string(action));
 	}
 
 	if(action & A_ELECTION_TIMEOUT) {
 		crm_trace("The election timer went off, we win!");
 	
 		return I_ELECTION_DC;
 		
 	}
 
 	
 	return I_NULL;
 }
 
 /*	A_DC_TIMER_STOP, A_DC_TIMER_START	*/
 enum crmd_fsa_input
 do_dc_timer_control(long long action,
 		   enum crmd_fsa_cause cause,
 		   enum crmd_fsa_state cur_state,
 		   enum crmd_fsa_input current_input,
 		   void *data)
 {
 	gboolean timer_op_ok = TRUE;
 	
 
 	if(action & A_DC_TIMER_STOP) {
 		timer_op_ok = stopTimer(election_trigger);
 	}
 
 	/* dont start a timer that wasnt already running */
 	if(action & A_DC_TIMER_START && timer_op_ok) {
 		startTimer(election_trigger);
 	}
 	
 	return I_NULL;
 }
 
 
 /*	 A_DC_TAKEOVER	*/
 enum crmd_fsa_input
 do_dc_takeover(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, fragment = NULL;
 	
 
 	crm_trace("################## Taking over the DC ##################");
 	set_bit_inplace(&fsa_input_register, R_THE_DC);
 
 	crm_verbose("Am I the DC? %s", AM_I_DC?XML_BOOLEAN_YES:XML_BOOLEAN_NO);
 	
 	fsa_our_dc = NULL;
 	set_bit_inplace(&fsa_input_register, R_JOIN_OK);
 	set_bit_inplace(&fsa_input_register, R_INVOKE_PE);
 	
 	clear_bit_inplace(&fsa_input_register, R_CIB_DONE);
 	clear_bit_inplace(&fsa_input_register, R_HAVE_CIB);
 
 	startTimer(dc_heartbeat);
 
 	if (fsa_cluster_conn->llc_ops->set_cstatus_callback(
 		    fsa_cluster_conn, crmd_client_status_callback, NULL)!=HA_OK){
 		crm_err("Cannot set client status callback\n");
 		crm_err("REASON: %s\n",
 		       fsa_cluster_conn->llc_ops->errmsg(fsa_cluster_conn));
 	}
 
 	/* store our state in the CIB (since some fields will not be
 	 *  filled in because the DC doesnt go through the join process
 	 *  with itself
 	 *
 	 * bypass the TE for now, it will be informed in good time
 	 */
 	update = create_node_state(
 		fsa_our_uname, NULL, ONLINESTATUS, CRMD_JOINSTATE_MEMBER);
 	set_xml_property_copy(
 		update,XML_CIB_ATTR_EXPSTATE, CRMD_STATE_ACTIVE);
 	
 	fragment = create_cib_fragment(update, NULL);
 	store_request(NULL, fragment, CRM_OP_UPDATE, CRM_SYSTEM_DCIB);
 
 	free_xml(update);
 	free_xml(fragment);
 
 	/* Async get client status information in the cluster */
 	fsa_cluster_conn->llc_ops->client_status(
 		fsa_cluster_conn, NULL, CRM_SYSTEM_CRMD, -1);
 	
 	return I_NULL;
 }
 
 /*	 A_DC_RELEASE	*/
 enum crmd_fsa_input
 do_dc_release(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;
 	
 
 	crm_trace("################## Releasing the DC ##################");
 
 	stopTimer(dc_heartbeat);
 	if (fsa_cluster_conn->llc_ops->set_cstatus_callback(
 		    fsa_cluster_conn, NULL, NULL)!=HA_OK){
 		crm_err("Cannot unset client status callback\n");
 		crm_err("REASON: %s\n",
 		       fsa_cluster_conn->llc_ops->errmsg(fsa_cluster_conn));
 		result = I_ERROR;
 	}
 
 	if(action & A_DC_RELEASE) {
 		clear_bit_inplace(&fsa_input_register, R_THE_DC);
 		
 		/* get a new CIB from the new DC */
 		clear_bit_inplace(&fsa_input_register, R_HAVE_CIB);
 	} else if (action & A_DC_RELEASED) {
 
 		if(cur_state == S_STOPPING) {
 			result = I_SHUTDOWN; // necessary?
 			result = I_RELEASE_SUCCESS;
 		}
 #if 0
 		else if( are there errors ) {
 			// we cant stay up if not healthy
 			// or perhaps I_ERROR and go to S_RECOVER?
 			result = I_SHUTDOWN;
 		}
 #endif
 		else
 			result = I_RELEASE_SUCCESS;
 
 	} else {
 		crm_err("Warning, do_dc_release invoked for action %s",
 		       fsa_action2string(action));
 	}
 
 	crm_verbose("Am I still the DC? %s", AM_I_DC?XML_BOOLEAN_YES:XML_BOOLEAN_NO);
 
 	return result;
 }
 
 void
 ghash_count_vote(gpointer key, gpointer value, gpointer user_data)
 {
 	
 	struct election_data_s *election_data =
 		(struct election_data_s *)user_data;
 
 	oc_node_t *cur_node = (oc_node_t*)value;
 	const char *node_uname = (const char*)key;
 	
 	if(election_data->winning_bornon > cur_node->node_born_on) {
 		election_data->winning_uname = node_uname;
 		election_data->winning_bornon = cur_node->node_born_on;
 		
 	} else if(election_data->winning_bornon == cur_node->node_born_on
 		  && (election_data->winning_uname == NULL
 		      || strcmp(election_data->winning_uname, node_uname) > 0)) {
 		election_data->winning_uname = node_uname;
 		election_data->winning_bornon = cur_node->node_born_on;
 
 	}
 }
 
diff --git a/crm/crmd/lrm.c b/crm/crmd/lrm.c
index 16f8b6e81d..94a63d7154 100644
--- a/crm/crmd/lrm.c
+++ b/crm/crmd/lrm.c
@@ -1,660 +1,664 @@
 /* 
  * 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 <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 xml_agent_list);
 
 gboolean build_active_RAs(xmlNodePtr rsc_list);
 
 void do_update_resource(
 	lrm_rsc_t *rsc, int status, int rc, const char *op_type);
 
 enum crmd_fsa_input do_lrm_rsc_op(
 	lrm_rsc_t *rsc, rsc_id_t rid, const char *operation, xmlNodePtr msg);
 
 enum crmd_fsa_input do_lrm_monitor(lrm_rsc_t *rsc);
 
 enum crmd_fsa_input do_fake_lrm_op(gpointer data);
 
 GHashTable *xml2list(xmlNodePtr parent, const char **attr_path, int depth);
 
 const char *rsc_path[] = 
 {
 	"msg_data",
 	"rsc_op",
 	"resource",
 	"instance_attributes",
 	"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_NULL;//I_FAIL;
 	int ret = HA_OK;
 
 	if(action & A_LRM_DISCONNECT) {
 		fsa_lrm_conn->lrm_ops->signoff(fsa_lrm_conn);
 	}
 
 	if(action & A_LRM_CONNECT) {
 	
 		crm_trace("LRM: connect...");
 		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, lrm_monitor_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 xml_agent_list)
 {
 	int lpc = 0, llpc = 0;
 	GList *types    = NULL;
 	GList *classes  = NULL;
 	xmlNodePtr xml_agent = 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);
 
 		slist_iter(
 			type, char, types, llpc,
 			
 			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);
 
 			/* we dont have this yet */
 			set_xml_property_copy(xml_agent, "version",     "1");
 
 			)
 		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;
 
 	state_flag_t cur_state = 0;
 	const char *this_op    = NULL;
+	gboolean found = FALSE;
 	
 	lrm_list = fsa_lrm_conn->lrm_ops->get_all_rscs(fsa_lrm_conn);
 
 	slist_iter(
 		the_rsc, lrm_rsc_t, lrm_list, lpc,
 
 /* 		GHashTable* 	params; */
 		
 		xmlNodePtr xml_rsc = create_xml_node(rsc_list, "rsc_state");
 		const char *status_text = "<unknown>";
 		
 		set_xml_property_copy(xml_rsc, XML_ATTR_ID, the_rsc->id);
 		set_xml_property_copy(xml_rsc, "type",      the_rsc->type);
 		set_xml_property_copy(xml_rsc, "class",     the_rsc->class);
 		set_xml_property_copy(xml_rsc, "node_id",   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;
-			gboolean found = FALSE;
 
 			if(found == FALSE && safe_str_neq(this_op, "status")){
 				switch(op->status) {
 					case LRM_OP_DONE:
 						status_text = "done";
 						break;
 					case LRM_OP_CANCELLED:
 						status_text = "cancelled";
 						break;
 					case LRM_OP_TIMEOUT:
 						status_text = "timeout";
 						break;
 					case LRM_OP_NOTSUPPORTED:
 						status_text = "not suported";
 						break;
 					case LRM_OP_ERROR:
 						status_text = "error";
 						break;
 				}
 			}
 
 			if(found) {
 				set_xml_property_copy(
 					xml_rsc, "rsc_op", this_op);
 
 				/* we only want the last one */
 				break;
 			}
 			)
 
 		set_xml_property_copy(xml_rsc, "op_result", status_text);
 		
 		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");
 
 	/* Build a list of supported agents */
 	build_suppported_RAs(xml_agent_list);
 	
 	/* Build a list of active (not always running) resources */
 	build_active_RAs(rsc_list);
 
 	if(is_replace) {
 		set_xml_property_copy(xml_data, "replace", XML_CIB_TAG_LRM);
 	}
 	
 	set_xml_property_copy(xml_state, XML_ATTR_ID, 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,
 		fragment = NULL,
 		tmp1 = NULL;
 		fragment = NULL;
 	if(action & A_UPDATE_NODESTATUS) {
 
 #ifndef USE_FAKE_LRM
 		update = do_lrm_query(TRUE);
 #else
 		tmp1 = create_xml_node(NULL, XML_CIB_TAG_STATE);
 		set_xml_property_copy(tmp1, XML_ATTR_ID, fsa_our_uname);
 		update = create_cib_fragment(tmp1, NULL);
 #endif
 		/* this only happens locally.  the updates are pushed out
 		 * as part of the join process
 		 */
 		store_request(NULL, update, CRM_OP_UPDATE, CRM_SYSTEM_DC);
 		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;
 	rsc_id_t rid;
 	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
 	
 	crm_err("Action %s (%.16llx) only kind of supported\n",
 	       fsa_action2string(action), action);
 
 
 	msg = (xmlNodePtr)data;
 		
 	operation = get_xml_attr_nested(
 		msg, rsc_path, DIMOF(rsc_path) -3, XML_ATTR_OP, TRUE);
 	
 	
 	id_from_cib = get_xml_attr_nested(
 		msg, rsc_path, DIMOF(rsc_path) -2, XML_ATTR_ID, TRUE);
 	
 	// only the first 16 chars are used by the LRM
 	strncpy(rid, id_from_cib, 16);
 	
 	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 && strcmp(crm_op, "lrm_query") == 0) {
 		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 && strcmp(operation, "monitor") == 0) {
 		next_input = do_lrm_monitor(rsc);
 		
 	} 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, rsc_id_t rid, const char *operation, xmlNodePtr msg)
 {
 	lrm_op_t* op = NULL;
 
 	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);
 		
 		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_verbose("performing op %s...", operation);
 	op = g_new(lrm_op_t, 1);
 	op->op_type = operation;
 	op->params = xml2list(msg, rsc_path, DIMOF(rsc_path));
 	op->timeout = 0;
 	op->user_data = rsc;
 	rsc->ops->perform_op(rsc, op);
 
 	return I_NULL;
 }
 
 enum crmd_fsa_input
 do_lrm_monitor(lrm_rsc_t *rsc)
 {
 	lrm_mon_t* mon = NULL;
 
 	if(rsc == NULL) {
 		crm_err("Could not find resource to monitor");
 		return I_FAIL;
 	}
 	
 	mon = g_new(lrm_mon_t, 1);
 	mon->op_type = "status";
 	mon->params = NULL;
 	mon->timeout = 0;
 	mon->user_data = rsc;
 	mon->mode = LRM_MONITOR_SET;
 	mon->interval = 2;
 	mon->target = 1;
 	rsc->ops->set_monitor(rsc, mon);
 
 	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);
 	
 	if(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;
 		}
 	}
 	
 	return nvpair_hash;
 }
 
 
 void
 do_update_resource(lrm_rsc_t *rsc, int status, int rc, const char *op_type)
 {
 /*
   <status>
   <nodes_status id=uname>
   <lrm>
   <lrm_resources>
   <lrm_resource id=>
   </...>
 */
 	xmlNodePtr update, iter;
 	char *tmp = NULL;
 	xmlNodePtr fragment, tmp1;
 	
 	
 	update = create_xml_node(NULL, "node_state");
 	set_xml_property_copy(update, XML_ATTR_ID, 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_type);
 	
 	tmp = crm_itoa(status);
 	set_xml_property_copy(iter, XML_LRM_ATTR_OPSTATE, tmp);
 	crm_free(tmp);
 	
 	tmp = crm_itoa(rc);
 	set_xml_property_copy(iter, XML_LRM_ATTR_OPCODE, tmp);
 	crm_free(tmp);
 
 	set_xml_property_copy(iter, XML_LRM_ATTR_TARGET, fsa_our_uname);
 	
 	tmp1 = create_xml_node(NULL, XML_CIB_TAG_STATE);
 	set_xml_property_copy(tmp1, XML_ATTR_ID, fsa_our_uname);
 	add_node_copy(tmp1, update);
 
 	fragment = create_cib_fragment(tmp1, NULL);
 
 	send_request(NULL, fragment, CRM_OP_UPDATE,
 		     fsa_our_dc, CRM_SYSTEM_DCIB, NULL);
 	
 	free_xml(fragment);
 	free_xml(update);
 	free_xml(tmp1);
 }
 
 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_MONITOR_CALLBACK) {
 		lrm_mon_t* monitor = (lrm_mon_t*)data;
 		lrm_rsc_t* rsc = monitor->rsc;
 		
 
 		switch(monitor->status) {
 			case LRM_OP_DONE:
 				crm_trace("An LRM monitor operation passed");
 				return I_NULL;
 				break;
 
 			case LRM_OP_CANCELLED:
 			case LRM_OP_TIMEOUT:
 			case LRM_OP_NOTSUPPORTED:
 			case LRM_OP_ERROR:
 				crm_err("An LRM monitor operation failed"
 					" or was aborted");
 
 				do_update_resource(rsc,
 						   monitor->status,
 						   monitor->rc,
 						   monitor->op_type);
 
 				break;
 		}	
 
 	} else if(cause == C_LRM_OP_CALLBACK) {
 		lrm_op_t* op = (lrm_op_t*)data;
 		lrm_rsc_t* rsc = op->rsc;
 
 		switch(op->status) {
 			case LRM_OP_CANCELLED:
 			case LRM_OP_TIMEOUT:
 			case LRM_OP_NOTSUPPORTED:
 			case LRM_OP_ERROR:
 				crm_err("An LRM operation failed"
 					" or was aborted");
 				// keep going
 			case LRM_OP_DONE:
 
 				do_update_resource(rsc,
 						   op->status,
 						   op->rc,
 						   op->op_type);
 
 				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")) {
 
-		const char *op_status = NULL;
-		xmlNodePtr update = NULL;
-		xmlNodePtr state = create_xml_node(NULL, XML_CIB_TAG_STATE);
-		xmlNodePtr iter = create_xml_node(state, XML_CIB_TAG_LRM);
+		state = create_xml_node(NULL, XML_CIB_TAG_STATE);
+		iter = create_xml_node(state, XML_CIB_TAG_LRM);
 
 		crm_verbose("performing op %s...", operation);
 
 		// so we can identify where to do the update
 		set_xml_property_copy(state, XML_ATTR_ID, 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);
 
-		long int op_code = 0;
 
 #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;
 		}
-		char *op_code_s = crm_itoa(op_code);
+		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_OPSTATE,op_status);
 		set_xml_property_copy(iter, XML_LRM_ATTR_OPCODE, 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 d624e1dced..77f62358ef 100644
--- a/crm/crmd/messages.c
+++ b/crm/crmd/messages.c
@@ -1,889 +1,889 @@
 /* 
  * 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 <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;
 
 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(xml_relay_message);\
 	if(router_strm == NULL) {				\
 		router_strm = fopen("/tmp/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);
 #else
 #    define ROUTER_RESULT(x)	crm_verbose(x, NULL);
 #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_verbose("Message not authorized");
 			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)
 {
 	gboolean was_sent = FALSE;
 	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,
 				 host_to,
 				 sys_to,
 				 AM_I_DC?CRM_SYSTEM_DC:CRM_SYSTEM_CRMD,
 				 NULL,
 				 NULL);
 
 //	xml_message_debug(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);
 
 	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 dont_cc= TRUE;
 	gboolean processing_complete = FALSE;
 	const char *host_to = xmlGetProp(xml_relay_message,XML_ATTR_HOSTTO);
 	const char *sys_to  = xmlGetProp(xml_relay_message,XML_ATTR_SYSTO);
 
 	
 
 	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) {
 
 		xml_message_debug(xml_relay_message,
 				  "Bad message type, should be crm_message");
 		crm_err("Ignoring message of type %s",
 		       xml_relay_message->name);
 		return TRUE;
 	}
 	
 
 	if(sys_to == NULL) {
 		xml_message_debug(xml_relay_message,
 				  "Message did not have any value for sys_to");
 		crm_err("Message did not have any value for %s",
 		       XML_ATTR_SYSTO);
 		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;
 	}
 
 #if 0
 	crm_verbose("is_local    %d", is_local);
 	crm_verbose("is_for_dcib %d", is_for_dcib);
 	crm_verbose("is_for_dc   %d", is_for_dc);
 	crm_verbose("is_for_crm  %d", is_for_crm);
 	crm_verbose("AM_I_DC     %d", AM_I_DC);
 	crm_verbose("sys_to      %s", sys_to);
 	crm_verbose("host_to     %s", host_to);
 #endif
 	
 	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);
 			processing_complete = TRUE; 
 
 		} else {
 			ROUTER_RESULT("Message result: Discard, not DC");
 			processing_complete = TRUE; // discard
 		}
 		
 	} else if(is_local && (is_for_crm || is_for_cib)) {
 		ROUTER_RESULT("Message result: CRMd process");
 
 	} else if(is_local) {
 		if(dont_cc) {
 			ROUTER_RESULT("Message result: Local relay");
 
 		} else {
 			/* The DC should also get this message */
 			ROUTER_RESULT("Message result: Local relay with CC");
 		}
 		send_msg_via_ipc(xml_relay_message, sys_to);
 		processing_complete = TRUE & dont_cc;
 		
 	} else {
 		if(dont_cc) {
 			ROUTER_RESULT("Message result: External relay");
 		} else {
 			/* The DC should also get this message */
 			ROUTER_RESULT("Message result: External relay with CC");
 		}
 		send_msg_via_ha(xml_relay_message, host_to);
 		processing_complete = TRUE & dont_cc;
 		
 	}
 	
 	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) {
 			return FALSE;
 		}
 		
-		gboolean can_reply = FALSE; // no-one has registered with this id
 		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_err("Message not authorized");
 		}
 		
 		return can_reply;
 	}
 	
 	crm_info("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);
 	}
 
-	struct crm_subsystem_s *the_subsystem = NULL;
-
 	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);
 		}
 	}
 	
 	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_info("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)
 {
 	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,  TRUE);
 
 	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);
 
 //	xml_message_debug(stored_msg, "Processing message");
 
 	crm_debug("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);
 		xml_message_debug(stored_msg, "Bad message");
 		
 	} else if(strcmp(type, XML_ATTR_REQUEST) == 0){
 		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;
 				
 		} 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_HBEAT) == 0) {
 			next_input = I_DC_HEARTBEAT;
 				
 		} else if(strcmp(op, CRM_OP_WELCOME) == 0) {
 			next_input = I_WELCOME;
 				
 		} 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_xml_property_copy(
 				node_state, XML_ATTR_ID, 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, CRM_OP_ANNOUNCE) == 0) {
 			next_input = I_NODE_JOIN;
 			
 		} else if(strcmp(op, CRM_OP_REPLACE) == 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");
 				
 			xmlNodePtr 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(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;
 			xml_message_debug(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");
 	}
 	
 #ifdef MSG_LOG
 	msg_text = dump_xml(root);
 	if(msg_out_strm == NULL) {
 		msg_out_strm = fopen("/tmp/outbound.log", "w");
 	}
 	fprintf(msg_out_strm, "[%d HA (%s:%d)]\t%s\n",
 		all_is_good,
 		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;
 
 	
 //	crm_debug("relaying msg to sub_sys=%s via IPC", sys);
 
 	client_channel =
 		(IPC_Channel*)g_hash_table_lookup (ipc_clients, sys);
 
 	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);
 		xml_message_debug(action, "Change the way we handle");
 		relay_message(process_cib_message(action, TRUE), TRUE);
 		
 	} else if(sys != NULL && strcmp(sys, CRM_SYSTEM_LRMD) == 0) {
 
 		do_lrm_invoke(A_LRM_INVOKE, C_IPC_MESSAGE,
 			      fsa_state, I_MESSAGE, action);
 		
 	} else {
 		crm_err("Unknown Sub-system (%s)... discarding message.",
 			sys);
 	}    
 	return;
 }	
diff --git a/crm/crmd/subsystems.c b/crm/crmd/subsystems.c
index 32be281f49..13f35831b9 100644
--- a/crm/crmd/subsystems.c
+++ b/crm/crmd/subsystems.c
@@ -1,630 +1,629 @@
 /* 
  * 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 <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) {
 		const char *op = get_xml_attr(
 			cib_msg, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE);
 
 		const char *sys_from = xmlGetProp(cib_msg, XML_ATTR_SYSFROM);
 
 		xml_message_debug(cib_msg, "[CIB] Invoking with");
 		if(cib_msg == NULL) {
 			crm_err("No message for CIB command");
 			return I_NULL; // I_ERROR
 
 		} else if(op == NULL) {
 			xml_message_debug(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(sys_from != NULL
 		   && 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");
 			xml_message_debug(answer, "Couldnt route: ");
 			result = I_ERROR;
 
 		} else if(AM_I_DC
 			  && (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
 			      || strcmp(op, CRM_OP_ERASE) == 0)) {
 			result = I_CIB_UPDATE;	
 #if 0
 		// check the answer, see if we are interested in it also
 		} else if(interested in reply) {
 			put_message(answer);
 			result = I_REQUEST;
 #endif
 		}
 
 		free_xml(answer);
 		return result;
 
 	/* experimental */
 	} else if(action & A_CIB_INVOKE_LOCAL) {
 		xml_message_debug(cib_msg, "[CIB] Invoking with");
 		if(cib_msg == NULL) {
 			crm_err("No message for CIB command");
 			return I_NULL; // I_ERROR
 		}
 		
 		answer = process_cib_message(cib_msg, TRUE);
 		put_message(answer);
 		return I_REQUEST;
 
 	} else if(action & A_CIB_BUMPGEN) {  
  		// check if the response was ok before next bit
 
 		section = get_xml_attr(cib_msg, XML_TAG_OPTIONS,
 				       XML_ATTR_FILTER_TYPE, FALSE);
 		
 		/* set the section so that we dont always send the
 		 * whole thing
 		 */
 
 		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;
 		
 	}
 	
-	xmlNodePtr local_cib = get_cib_copy();
+	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){
-			int lpc = CLIENT_EXIT_WAIT;
-			int pid_status = -1;
+			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) {
 		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));
 	
 		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 b432d7e9c2..8b72508bb8 100644
--- a/crm/crmd/utils.c
+++ b/crm/crmd/utils.c
@@ -1,634 +1,636 @@
 /* 
  * 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 <crmd_fsa.h>
 
 #include <clplumbing/Gmain_timeout.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <signal.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->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 {
 		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);
 }
 
 
 xmlNodePtr
 create_node_state(const char *node,
 		  const char *ccm_state,
 		  const char *crmd_state,
 		  const char *join_state)
 {
 	xmlNodePtr node_state = create_xml_node(NULL, XML_CIB_TAG_STATE);
 	
 	set_xml_property_copy(node_state, XML_ATTR_ID, node);
 	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);
 	}
 
 	xml_message_debug(node_state, "created");
 
 	return node_state;
 }
 
 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_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 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_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;
 }
diff --git a/crm/pengine/color.c b/crm/pengine/color.c
index 3afbb5ec2a..cccb48f9d9 100644
--- a/crm/pengine/color.c
+++ b/crm/pengine/color.c
@@ -1,476 +1,480 @@
-/* $Id: color.c,v 1.1 2004/06/07 10:29:03 andrew Exp $ */
+/* $Id: color.c,v 1.2 2004/06/07 21:28:39 msoffen 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 <glib.h>
 #include <libxml/tree.h>
 
 #include <pengine.h>
 #include <pe_utils.h>
 
 color_t *no_color = NULL;
 
 gboolean has_agent(node_t *a_node, const char *class, const char *type);
 
 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,
 			 color_t *local_color,
 			 color_t *other_color,
 			 GListPtr *colors,
 			 GListPtr resources);
 
 gboolean strict_preproc(rsc_to_rsc_t *constraint,
 			color_t *local_color,
 			color_t *other_color,
 			GListPtr *colors,
 			GListPtr resources);
 
 gboolean is_active(rsc_to_node_t *cons);
 
 gboolean choose_color(resource_t *lh_resource);
 
 
 gboolean 
 apply_node_constraints(GListPtr constraints, GListPtr nodes)
 {
-	crm_verbose("Applying constraints...");
 	int lpc = 0;
+
+	crm_verbose("Applying constraints...");
 	slist_iter(
 		cons, rsc_to_node_t, constraints, lpc,
+		resource_t *rsc_lh = NULL;
+
 		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;
 		}
     
-		resource_t *rsc_lh = cons->rsc_lh;
+		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);
 			continue;
 		} else {
 			int llpc = 0;
 			slist_iter(node_rh, node_t, cons->node_list_rh, llpc,
 				   update_node_weight(
 					   cons, node_rh->details->id, nodes));
 		}
 		
 		/* dont add it to the resource,
 		 *  the information is in the resouce's node list
 		 */
 		);
 	
 	return TRUE;
 	
 }
 
 gboolean
 apply_agent_constraints(GListPtr resources)
 {
 	int lpc;
 	int lpc2;
 	slist_iter(
 		rsc, resource_t, resources, lpc,
 
 		slist_iter(
 			node, node_t, rsc->allowed_nodes, lpc2,
 			
 			if(has_agent(node, rsc->class, rsc->type) == FALSE) {
 				/* remove node from contention */
 				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
 				 */
 				lpc2 = 0;
 				rsc->allowed_nodes = g_list_remove(
 					rsc->allowed_nodes, node);
 				crm_free(node);
 			}
 			
 			)
 		);
 	return TRUE;
 }
 
 gboolean
 has_agent(node_t *a_node, const char *class, const char *type)
 {
 	int lpc;
 	slist_iter(
 		agent, lrm_agent_t, a_node->details->agents, lpc,
 
 		if(safe_str_eq(type, agent->type)){
 			if(class == NULL) {
 				return TRUE;
 			} else if(safe_str_eq(class, agent->class)) {
 				return TRUE;
 			}
 		}
 		);
 		
 	return FALSE;
 }
 
 gboolean
 is_active(rsc_to_node_t *cons)
 {
 	/* todo: check constraint lifetime */
 	return TRUE;
 }
 
 gboolean
 strict_preproc(rsc_to_rsc_t *constraint,
 	       color_t *local_color, color_t *other_color,
 	       GListPtr *colors, GListPtr resources)
 {
 	resource_t * lh_resource = constraint->rsc_lh;
 	switch(constraint->strength) {
 		case must:
 			if(constraint->rsc_rh->runnable == FALSE) {
 				crm_warn("Resource %s must run on the same"
 					 " node as %s (cons %s), but %s is not"
 					 " runnable.",
 					 constraint->rsc_lh->id,
 					 constraint->rsc_rh->id,
 					 constraint->id,
 					 constraint->rsc_rh->id);
 				constraint->rsc_lh->runnable = FALSE;
 			}
 			break;
 			
 			// x * should * should_not = x
 		case should:
 			if(constraint->rsc_rh->provisional == FALSE) {
 				local_color->local_weight = 
 					local_color->local_weight * 2.0;
 			}
 				break;
 		case should_not:
 			if(constraint->rsc_rh->provisional == FALSE) {
 				local_color->local_weight = 
 					local_color->local_weight * 0.5;
 			}
 
 //			if(g_list_length(lh_resource->candidate_colors)==1)
 			create_color(
 				colors, lh_resource->allowed_nodes, resources);
 			
 			
 			break;
 		case must_not:
 			if(constraint->rsc_rh->provisional == FALSE
 				&& local_color->id != no_color->id) {
 				lh_resource->candidate_colors =
 					g_list_remove(
 						lh_resource->candidate_colors,
 						local_color);
 				crm_debug_action(
 					print_color(
 						"Removed",local_color,FALSE));
 				
 // surely this is required... but mtrace says no...
 //				crm_free(local_color);
 			}
 			break;
 		default:
 			// error
 			break;
 	}
 	return TRUE;
 }
 
 gboolean
 strict_postproc(rsc_to_rsc_t *constraint,
 		color_t *local_color, color_t *other_color,
 		GListPtr *colors, GListPtr resources)
 {
 	print_rsc_to_rsc("Post processing", constraint, FALSE);
 	
 	switch(constraint->strength) {
 		case must:
 			if(constraint->rsc_rh->provisional == TRUE) {
 				constraint->rsc_rh->color = other_color;
 				constraint->rsc_rh->provisional = FALSE;
 				color_resource(constraint->rsc_rh,
 					       colors, resources);
 			}
 			// else check for error
 			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;
 			}
 			
 			break;
 			
 		case should:
 			break;
 		case should_not:
 			break;
 		case must_not:
 			if(constraint->rsc_rh->provisional == TRUE) {
 				// check for error
 			}
 			break;
 		default:
 			// error
 			break;
 	}
 	return TRUE;
 }
 
 gboolean
 choose_color(resource_t *lh_resource)
 {
 	int lpc = 0;
 
 	if(lh_resource->runnable == FALSE) {
 		lh_resource->color = find_color(
 			lh_resource->candidate_colors, no_color);
 		lh_resource->provisional = FALSE;
 
 	}
 
 	if(lh_resource->provisional) {
 		GListPtr 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 = node_list_and(
 				this_color->details->candidate_nodes, 
 				lh_resource->allowed_nodes);
 
 			if(g_list_length(intersection) != 0) {
 				// TODO: merge node weights
 				GListPtr old_list =
 					this_color->details->candidate_nodes;
 
 				pe_free_shallow(old_list);
 				
 				this_color->details->candidate_nodes =
 					intersection;
 				
 				lh_resource->color = this_color;
 				lh_resource->provisional = FALSE;
 				break;
 			} else {
 				pe_free_shallow(intersection);
 			}
 			
 			);
 	}
 	return !lh_resource->provisional;
 }
 
 gboolean
 rsc_preproc(resource_t *lh_resource, GListPtr *colors, GListPtr resources)
 {
 	int lpc = 0;
 	color_t *other_color = NULL;
 	color_t *local_color = NULL;
 	slist_iter(
 		constraint, rsc_to_rsc_t, lh_resource->rsc_cons, lpc,
 		if(lh_resource->runnable == FALSE) {
 			return FALSE;
 		}
 
 		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;
 		}
 		other_color = constraint->rsc_rh->color;
 		local_color = find_color(
 			lh_resource->candidate_colors, other_color);
 
 		strict_preproc(
 			constraint,local_color,other_color,colors,resources);
 		);
 	
 	return TRUE;
 }
 
 gboolean
 rsc_postproc(resource_t *lh_resource, GListPtr *colors, GListPtr resources)
 {
 	int lpc = 0;
 	color_t *local_color = lh_resource->color;
 	slist_iter(
 		constraint, rsc_to_rsc_t, lh_resource->rsc_cons, lpc,
 		color_t *other_color = find_color(
 			constraint->rsc_rh->candidate_colors, local_color);
 		
 		strict_postproc(
 			constraint, local_color, other_color,colors,resources);
 		);
 	
 	return TRUE;
 }
 
 void
 color_resource(resource_t *lh_resource, GListPtr *colors, GListPtr resources)
 {
 	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);
 	
 	// filter out nodes with a negative weight
 	filter_nodes(lh_resource);
 
 	/* avoid looping through lists when we know this resource
 	 * cant be started
 	 */
 	if(lh_resource->allowed_nodes != NULL) {
 		/* Choose a color from the candidates or,
 		 *  create a new one if no color is suitable 
 		 * (this may need modification pending further napkin drawings)
 		 */
 		choose_color(lh_resource);	
   
 		crm_verbose("* Colors %d, Nodes %d",
 			    g_list_length(*colors),max_valid_nodes);
 	
 		if(lh_resource->provisional) {
 			lh_resource->color = create_color(
 				colors, lh_resource->allowed_nodes, resources);
 		}
 	}
 	
 	if(lh_resource->color == NULL) {
 		crm_err("Could not color resource %s", lh_resource->id);
 		print_resource("ERROR: No color", lh_resource, FALSE);
 		lh_resource->color = find_color(
 			lh_resource->candidate_colors, 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) {
 		node_t *node_tmp = pe_find_node(nodes, id);
 		node_rh = node_copy(node_tmp);
 		cons->rsc_lh->allowed_nodes =
 			g_list_append(cons->rsc_lh->allowed_nodes, node_rh);
 	}
 
 	if(node_rh == NULL) {
 		// error
 		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->id,
 			 node_rh->weight);
 		return TRUE;
 	}
 	
 	crm_verbose("Constraint %s: node %s weight %s %f.",
 		      cons->id,
 		      node_rh->details->id,
 		      modifier2text(cons->modifier),
 		      node_rh->weight);
 	
 	switch(cons->modifier) {
 		case set:
 			node_rh->weight = cons->weight;
 			node_rh->fixed = TRUE;
 			break;
 		case inc:
 			node_rh->weight += cons->weight;
 			break;
 		case dec:
 			node_rh->weight -= cons->weight;
 			break;
 		case modifier_none:
 			// warning
 			break;
 	}
 	return TRUE;
 }
diff --git a/crm/pengine/graph.c b/crm/pengine/graph.c
index 370f968a0f..ac4f0116c5 100644
--- a/crm/pengine/graph.c
+++ b/crm/pengine/graph.c
@@ -1,205 +1,206 @@
-/* $Id: graph.c,v 1.1 2004/06/07 10:29:03 andrew Exp $ */
+/* $Id: graph.c,v 1.2 2004/06/07 21:28:39 msoffen 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 <glib.h>
 #include <libxml/tree.h>
 
 #include <pengine.h>
 #include <pe_utils.h>
 
 
 
 
 GListPtr
 create_action_set(action_t *action)
 {
 	int lpc;
 	GListPtr tmp = NULL;
 	GListPtr result = NULL;
 	gboolean preceeding_complete = FALSE;
 
 	if(action->processed) {
 		return NULL;
 	}
 
 	crm_debug_action(print_action("Create action set for", action, FALSE));
 	
 	// process actions_before
 	if(action->seen_count == 0) {
 		crm_verbose("Processing \"before\" for action %d", action->id);
 		slist_iter(
 			other, action_wrapper_t, action->actions_before, lpc,
 
 			tmp = create_action_set(other->action);
 			result = g_list_concat(result, tmp);
 			preceeding_complete = TRUE;
 			);
 		
 	} else {
 		crm_verbose("Already seen action %d", action->id);
 		crm_verbose("Processing \"before\" for action %d", action->id);
 		slist_iter(
 			other, action_wrapper_t, action->actions_before, lpc,
 			
 			if(other->action->seen_count > action->seen_count
 			   && other->strength == must) {
 				tmp = create_action_set(other->action);
 				result = g_list_concat(result, tmp);
 			}	
 			);
 	}
 	
 	// add ourselves
 	if(action->runnable) {
 		if(action->processed == FALSE) {
 			crm_verbose("Adding self %d", action->id);
 			result = g_list_append(result, action);
 		} else {
 			crm_verbose("Already added self %d", action->id);
 		}
 		
 	} else {
 		crm_verbose("Skipping ourselves, we're not runnable");
 	}
 	action->processed = TRUE;
 	
 	if(preceeding_complete == FALSE) {
 		
 		/* add any "before" actions that arent already processed */
 		slist_iter(
 			other, action_wrapper_t, action->actions_before, lpc,
 			
 			tmp = create_action_set(other->action);
 			result = g_list_concat(result, tmp);
 			);
 	}
 
 	action->seen_count = action->seen_count + 1;
 	
 	/* process actions_after
 	 *
 	 * do this regardless of whether we are runnable.  Any direct or
 	 *  indirect hard/XML_STRENGTH_VAL_MUST dependancies on us will have
 	 *  been picked up earlier on in stage 7
 	 */
 	crm_verbose("Processing \"after\" for action %d", action->id);
 	slist_iter(
 		other, action_wrapper_t, action->actions_after, lpc,
 		
 		tmp = create_action_set(other->action);
 		result = g_list_concat(result, tmp);
 		);
 	
 	return result;
 }
 
 
 gboolean
 update_runnable(GListPtr actions)
 {
 
 	int lpc = 0, lpc2 = 0;
 	gboolean change = TRUE;
 
 	while(change) {
 		change = FALSE;
 		slist_iter(
 			action, action_t, actions, lpc,
 
 			if(action->runnable) {
 				continue;
 			} else if(action->optional) {
 				continue;
 			}
 			
 			slist_iter(
 				other, action_wrapper_t, action->actions_after, lpc2,
 				if(other->action->runnable == FALSE) {
 					continue;
 				}
 				
 				change = TRUE;
 				crm_debug_action(
 					print_action("Marking unrunnable",
 						     other->action, FALSE));
 				other->action->runnable = FALSE;
 				);
 			);
 	}
 	return TRUE;
 }
 
 xmlNodePtr
 action2xml(action_t *action)
 {
 	xmlNodePtr action_xml = NULL;
 	
 	if(action == NULL) {
 		return NULL;
 	}
 	
 	switch(action->task) {
 		case stonith_op:
 			action_xml = create_xml_node(NULL, "pseduo_event");
 			break;
 		case shutdown_crm:
 			action_xml = create_xml_node(NULL, "crm_event");
 			break;
 		default:
 			action_xml = create_xml_node(NULL, "rsc_op");
 			add_node_copy(action_xml, action->rsc->xml);
 			
 			break;
 	}
 
 	set_xml_property_copy(action_xml,
 			      XML_LRM_ATTR_TARGET,
 			      safe_val4(NULL, action, node, details, id));
 
 	set_xml_property_copy(action_xml,
 			      XML_ATTR_ID,
 			      crm_itoa(action->id));
 
 	set_xml_property_copy(action_xml,
 			      XML_LRM_ATTR_RUNNABLE,
 			      action->runnable?XML_BOOLEAN_TRUE:XML_BOOLEAN_FALSE);
 
 	set_xml_property_copy(action_xml,
 			      XML_LRM_ATTR_OPTIONAL,
 			      action->optional?XML_BOOLEAN_TRUE:XML_BOOLEAN_FALSE);
 
 	set_xml_property_copy(action_xml,
 			      XML_LRM_ATTR_TASK,
 			      task2text(action->task));
 
 	set_xml_property_copy(action_xml,
 			      XML_LRM_ATTR_DISCARD,
 			      action->discard?XML_BOOLEAN_TRUE:XML_BOOLEAN_FALSE);
 
 	set_xml_property_copy(action_xml,
 			      "allow_fail",
 			      action->failure_is_fatal?XML_BOOLEAN_FALSE:XML_BOOLEAN_TRUE);
 
 	return action_xml;
 }
diff --git a/crm/pengine/pengine.c b/crm/pengine/pengine.c
index d0a7704ea1..632ed5881c 100755
--- a/crm/pengine/pengine.c
+++ b/crm/pengine/pengine.c
@@ -1,243 +1,246 @@
-/* $Id: pengine.c,v 1.33 2004/06/07 10:29:03 andrew Exp $ */
+/* $Id: pengine.c,v 1.34 2004/06/07 21:28:39 msoffen 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 <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("/tmp/pemsg.log", "w");
 	}
 
-	char *msg_buffer = dump_xml_node(msg, FALSE);
+	msg_buffer = dump_xml_node(msg, FALSE);
 	fprintf(pemsg_strm, "%s: %s\n", "[in ]", msg_buffer);
 	fflush(pemsg_strm);
 	crm_free(msg_buffer);
 	
-	const char *sys_to = xmlGetProp(msg, XML_ATTR_SYSTO);
+	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);
 		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);
 		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,
 	       stonith_list, shutdown_list);
 
 	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(action_sets, &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);
 
 	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 1e61d91380..9cdee71644 100644
--- a/crm/pengine/ptest.c
+++ b/crm/pengine/ptest.c
@@ -1,299 +1,299 @@
-/* $Id: ptest.c,v 1.20 2004/06/07 10:29:03 andrew Exp $ */
+/* $Id: ptest.c,v 1.21 2004/06/07 21:28:39 msoffen 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/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 lpc2 = 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_enable_stderr(TRUE);
 	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;
       
 				/* 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':
 				printf("option %d", flag);
 				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 =#=#=#=#=");
 
-	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;
 
 #ifdef MCHECK
 	mtrace();
 #endif
 	set_crm_log_level(LOG_VERBOSE);
 	
 	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,
 	       stonith_list, shutdown_list);
 
 	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("========= Action Sets =========");
 
 	crm_debug("\t========= Set %d (Un-runnable) =========", -1);
 	slist_iter(action, action_t, actions, lpc,
 		   if(action->optional == FALSE && action->runnable == FALSE) {
 			   print_action("\t", action, TRUE);
 		   }
 		);
 
-	int lpc2;
 	slist_iter(action_set, GList, action_sets, lpc,
 		   crm_debug("\t========= Set %d =========", lpc);
 		   slist_iter(action, action_t, action_set, lpc2,
 			      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(action_sets, &graph);
 
 //	GListPtr action_sets = NULL;
 
 
 	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);
 
 	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_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
 	set_crm_log_level(LOG_INFO);
 
-	char *msg_buffer = dump_xml_node(graph, FALSE);
+	msg_buffer = dump_xml_node(graph, FALSE);
 	fprintf(stdout, "%s\n", msg_buffer);
 	fflush(stdout);
 	crm_free(msg_buffer);
 
 	
 	return 0;
 }
diff --git a/crm/pengine/stages.c b/crm/pengine/stages.c
index e3507b515d..04ffb4d65b 100644
--- a/crm/pengine/stages.c
+++ b/crm/pengine/stages.c
@@ -1,643 +1,653 @@
-/* $Id: stages.c,v 1.1 2004/06/07 10:29:03 andrew Exp $ */
+/* $Id: stages.c,v 1.2 2004/06/07 21:28:39 msoffen 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 <glib.h>
 #include <libxml/tree.h>
 
 #include <pengine.h>
 #include <pe_utils.h>
 
 
 /*
  * 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);
 
 	/* reset remaining global variables */
 	max_valid_nodes = 0;
 	order_id = 1;
 	action_id = 1;
 	
 	unpack_nodes(safe_val(NULL, cib_nodes, children), nodes);
 
 	unpack_resources(safe_val(NULL, cib_resources, children),
 			 resources, actions, action_constraints, *nodes);
 
 	unpack_status(safe_val(NULL, cib_status, children),
 		      *nodes, *resources, node_constraints);
 
 	unpack_constraints(safe_val(NULL, cib_constraints, children),
 			   *nodes, *resources,
 			   node_constraints, action_constraints);
 
 	slist_iter(
 		node, node_t, *nodes, lpc,
 		if(node->details->shutdown) {
 			*shutdown_list = g_list_append(*shutdown_list, node);
 			crm_verbose("Scheduling Node %s for shutdown",
 			       node->details->id);
 
 		} else if(node->details->unclean) {
 			*stonith_list = g_list_append(*stonith_list, node);
 			crm_verbose("Scheduling Node %s for STONITH",
 			       node->details->id);
 
 		}
 		);
 	
 	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;
 	color_t *current_color = NULL;
 	
 	// Set initial color
 	// Set color.candidate_nodes = all active nodes
 	if(no_color != NULL) {
 		crm_free(no_color->details);
 		crm_free(no_color);
 	}
 	no_color = create_color(NULL, NULL, sorted_rscs);
 	current_color = create_color(colors, sorted_nodes, sorted_rscs);
 	
 	// Set resource.color = color (all resources)
 	// Set resource.provisional = TRUE (all resources)
 	slist_iter(
 		this_resource, resource_t, sorted_rscs, lpc,
 
 		this_resource->color = current_color;
 		this_resource->provisional = TRUE;
 		);
 
 	crm_verbose("initialized resources to default color");
   
 	// 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;
 }
 
 #define color_n_nodes color_n->details->candidate_nodes
 #define color_n_plus_1_nodes color_n_plus_1->details->candidate_nodes
 
 /*
  * Choose a node for each (if possible) color
  */
 gboolean
 stage4(GListPtr colors)
 {
 	int lpc = 0;
 	color_t *color_n = NULL;
 	color_t *color_n_plus_1 = NULL;
+	GListPtr xor = NULL;
+	GListPtr minus = NULL;
 	
 	for(lpc = 0; lpc < g_list_length(colors); lpc++) {
 		color_n = color_n_plus_1;
 		color_n_plus_1 = (color_t*)g_list_nth_data(colors, lpc);
 
 		crm_debug_action(
 			print_color("Choose node for...", color_n, FALSE));
 		
 		if(color_n == NULL) {
 			continue;
 		}
 
-		GListPtr xor = node_list_xor(color_n_nodes,
+		xor = node_list_xor(color_n_nodes,
 					      color_n_plus_1_nodes);
-		GListPtr minus = node_list_minus(color_n_nodes,
+		minus = node_list_minus(color_n_nodes,
 						  color_n_plus_1_nodes);
 
 		if(g_list_length(xor) == 0 || g_list_length(minus) == 0) {
 			crm_verbose("Choose any node from our list");
 			choose_node_from_list(colors, color_n, color_n_nodes);
 
 		} else {
 			crm_verbose("Choose a node not in n+1");
 			choose_node_from_list(colors, color_n, minus);      
 		}
 
 		pe_free_shallow(xor);
 		pe_free_shallow(minus);
 	}
 
 	// choose last color
 	if(color_n_plus_1 != NULL) {
 		crm_debug_action(print_color("Choose node for last color...",
 				   color_n_plus_1,
 				   FALSE));
 
 		choose_node_from_list(colors,
 				      color_n_plus_1, 
 				      color_n_plus_1_nodes);
 	}
 	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)
 {
 	
-	crm_verbose("filling in the nodes to perform the actions on");
 	int lpc = 0;
+
+	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));
 		
 		if(safe_val(NULL, rsc, stop) == NULL
 		   || safe_val(NULL, rsc, start) == NULL) {
 			// error
 			crm_err("Either start action (%p) or"
 				" stop action (%p) were not defined",
 				safe_val(NULL, rsc, stop),
 				safe_val(NULL, rsc, start));
 			continue;
 		}
 		if(safe_val4(NULL, rsc, color, details, chosen_node) == NULL){
 			rsc->stop->node = safe_val(NULL, rsc, cur_node);
 			
 			rsc->start->node = NULL;
 			crm_warn("Stop resource %s (%s)",
 				  safe_val(NULL, rsc, id),
 				  safe_val5(NULL, rsc, stop, node,details,id));
 
 			crm_debug_action(
 				print_action(
 					CRMD_STATE_ACTIVE, rsc->stop, FALSE));
 			
 			
 		} else if(safe_str_eq(safe_val4(NULL, rsc,cur_node,details,id),
 				      safe_val6(NULL, rsc, color ,details,
 						chosen_node, details, id))){
 			crm_verbose("No change for Resource %s (%s)",
 				    safe_val(NULL, rsc, id),
 				    safe_val4(NULL,rsc,cur_node,details,id));
 
 			rsc->stop->optional = TRUE;
 			rsc->start->optional = TRUE;
 			rsc->stop->node = safe_val(NULL, rsc, cur_node);
 			rsc->start->node = safe_val4(NULL, rsc, color,
 						     details, chosen_node);
 			
 		} else if(safe_val4(NULL, rsc,cur_node,details,id) == NULL) {
 			rsc->stop->optional = TRUE;
 			rsc->start->node = safe_val4(NULL, rsc, color,
 						     details, chosen_node);
 
 			crm_debug("Start resource %s (%s)",
 				  safe_val(NULL, rsc, id),
 				  safe_val5(NULL, rsc, start,node,details,id));
 			
 		} else {
 			rsc->stop->node = safe_val(NULL, rsc, cur_node);
 			rsc->start->node = safe_val4(NULL, rsc, color,
 						     details, chosen_node);
 			crm_debug("Move resource %s (%s -> %s)",
 				  safe_val(NULL, rsc, id),
 				  safe_val5(NULL, rsc, stop, node,details,id),
 				  safe_val5(NULL, rsc, start,node,details,id));
 		}
 
 		if(rsc->stop->node != NULL) {
 			rsc->stop->runnable = TRUE;
 		}
 		if(rsc->start->node != NULL) {
 			rsc->start->runnable = TRUE;
 		}
 
 		);
 	
 	return TRUE;
 }
 
 /*
  * Create dependacies for stonith and shutdown operations
  */
 gboolean
 stage6(GListPtr *actions, GListPtr *action_constraints,
        GListPtr stonith_nodes, GListPtr shutdown_nodes)
 {
 	int lpc = 0;
 	int llpc = 0;
+	action_t *down_node = NULL;
+
 	slist_iter(
 		node, node_t, shutdown_nodes, lpc,
 
-		action_t *down_node =
+		down_node =
 			action_new(action_id++, NULL, shutdown_crm);
 		down_node->node = node;
 		down_node->runnable = TRUE;
 
 		*actions = g_list_append(*actions, down_node);
 		
 		slist_iter(
 			rsc, resource_t, node->details->running_rsc, llpc,
 			
 			order_constraint_t *order = (order_constraint_t*)
 				crm_malloc(sizeof(order_constraint_t));
 
 			/* stop resources before shutdown */
 			order->id = order_id++;
 			order->lh_action = rsc->stop;
 			order->rh_action = down_node;
 			order->strength = must;
 
 			crm_debug_action(
 				print_action("LH (Shutdown)",
 					     order->lh_action, FALSE));
 			crm_debug_action(
 				print_action("RH (Shutdown)",
 					     order->rh_action, FALSE));
 			
 			*action_constraints =
 				g_list_append(*action_constraints, order);
 			);
 		);
 
 	slist_iter(
 		node, node_t, stonith_nodes, lpc,	
 
 		action_t *stonith_node =
 			action_new(action_id++, NULL, stonith_op);
 		stonith_node->node = node;
 		stonith_node->runnable = TRUE;
 
 		*actions = g_list_append(*actions, stonith_node);
 
 		slist_iter(
 			rsc, resource_t, node->details->running_rsc, llpc,
 			
 			order_constraint_t *order = NULL;
 
-#if 1
 			/*
 			 * Mark the stop as irrelevant
 			 *
 			 * Possibly one day failed actions wont terminate
 			 *   the transition, but not yet
 			 */
 			rsc->stop->discard = TRUE;
-#else			
-			rsc->stop->optional = TRUE;
-#endif
+
+			/* This is always the opposite of the discard. */
+			rsc->stop->optional = ! rsc->stop->discard;
 
 			/* try stopping the resource before stonithing the node
 			 *
 			 * if the stop succeeds, the transitioner can then
 			 * decided if  stonith is needed
 			 */
 			order = (order_constraint_t*)
 				crm_malloc(sizeof(order_constraint_t));
 			order->lh_action = rsc->stop;
 			order->rh_action = stonith_node;
 			order->id = order_id++;
 			order->strength = must;
 			*action_constraints =
 				g_list_append(*action_constraints, order);
 
 			/* stonith before start */
 			order = (order_constraint_t*)
 				crm_malloc(sizeof(order_constraint_t));
 
 			order->id = order_id++;
 			order->lh_action = stonith_node;
 			order->rh_action = rsc->start;
 			order->strength = must;
 			*action_constraints =
 				g_list_append(*action_constraints, order);
 			);
 		);
 	
 
 	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;
+
 /*
 	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("Processing %d -> %d",
 		       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));
 
-		action_wrapper_t *wrapper = (action_wrapper_t*)
+		wrapper = (action_wrapper_t*)
 			crm_malloc(sizeof(action_wrapper_t));
 		wrapper->action = order->rh_action;
 		wrapper->strength = order->strength;
 
-		GListPtr list = order->lh_action->actions_after;
+		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;
 		);
 //	}
 	
 	update_runnable(actions);
 
 	slist_iter(
 		rsc, resource_t, resources, lpc,	
 
 		GListPtr action_set = NULL;
 		/* any non-essential stop actions will be marked redundant by
 		 *  during stage6
 		 */
 		action_set = create_action_set(rsc->start);
 		if(action_set != NULL) {
 			crm_verbose("Created action set for %s->start",
 			       rsc->id);
 			*action_sets = g_list_append(*action_sets,
 						      action_set);
 		} else {
 			crm_verbose("No actions resulting from %s->start",
 			       rsc->id);
 		}
 		);
 	
 	
 	return TRUE;
 }
 
 /*
  * Create a dependancy graph to send to the transitioner (via the CRMd)
  */
 gboolean
 stage8(GListPtr action_sets, xmlNodePtr *graph)
 {
 	int lpc = 0;
+	int lpc2;
 	xmlNodePtr xml_action_set = 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);
 		   }
 		);
 */
-	int lpc2;
 	slist_iter(action_set, GList, action_sets, lpc,
 		   crm_verbose("Processing Action Set %d", lpc);
 		   xml_action_set = create_xml_node(NULL, "actions");
 		   set_xml_property_copy(
 			   xml_action_set, XML_ATTR_ID, crm_itoa(lpc));
 
 		   slist_iter(action, action_t, action_set, lpc2,
 			      xmlNodePtr xml_action = action2xml(action);
 			      xmlAddChild(xml_action_set, xml_action);
 			   )
 		   xmlAddChild(*graph, xml_action_set);
 		);
 
 	xml_message_debug(*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, id);
 		new_node_id = safe_val6(
 			NULL, rsc, color, details, chosen_node, details, id);
 
 		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, id));
 			
 		} 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(GListPtr colors, color_t *color, GListPtr nodes)
 {
 	int lpc;
 	/*
 	  1. Sort by weight
 	  2. color.chosen_node = highest wieghted node 
 	  3. remove color.chosen_node from all other colors
 	*/
 	nodes = g_list_sort(nodes, sort_node_weight);
 	color->details->chosen_node =
 		node_copy((node_t*)g_list_nth_data(nodes, 0));
 
 	if(color->details->chosen_node == NULL) {
 		crm_err("Could not allocate a node for color %d",
 			color->id);
 		return FALSE;
 	}
 
 	slist_iter(
 		color_n, color_t, colors, lpc,
 		
 		node_t *other_node =
 			pe_find_node(color_n->details->candidate_nodes,
 				     color->details->chosen_node->details->id);
 
 		if(color_n != color) {
 			color_n->details->candidate_nodes =
 				g_list_remove(color_n->details->candidate_nodes,
 					       other_node);
 			//		crm_free(other_node);
 		}	
 		);
 	
 	return TRUE;
 }
diff --git a/crm/pengine/unpack.c b/crm/pengine/unpack.c
index fd68826300..267af76162 100644
--- a/crm/pengine/unpack.c
+++ b/crm/pengine/unpack.c
@@ -1,879 +1,907 @@
-/* $Id: unpack.c,v 1.1 2004/06/07 10:29:03 andrew Exp $ */
+/* $Id: unpack.c,v 1.2 2004/06/07 21:28:39 msoffen 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 <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;
 int action_id = 1;
 
 GListPtr match_attrs(xmlNodePtr attr_exp, 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_to_rsc(
 	xmlNodePtr xml_obj, GListPtr rsc_list, GListPtr *action_constraints);
 
 gboolean unpack_lrm_rsc_state(node_t *node,
 			      xmlNodePtr lrm_state,
 			      GListPtr rsc_list,
 			      GListPtr *node_constraints);
 
 gboolean add_node_attrs(xmlNodePtr attrs, node_t *node);
 
 gboolean unpack_healthy_resource(GListPtr *node_constraints,
 	xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node);
 
 gboolean unpack_failed_resource(GListPtr *node_constraints,
 	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 create_rsc_to_rsc(const char *id, enum con_strength strength,
 			   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);
 
 
 gboolean
 unpack_nodes(xmlNodePtr xml_nodes, GListPtr *nodes)
 {
+		node_t *new_node  = NULL;
+		xmlNodePtr xml_obj = NULL;
+		xmlNodePtr attrs   = NULL;
+		const char *id     = NULL;
+		const char *type   = NULL;
+
 	crm_verbose("Begining unpack...");
 	while(xml_nodes != NULL) {
-		xmlNodePtr xml_obj = xml_nodes;
-		xmlNodePtr attrs   = xml_obj->children;
-		const char *id     = xmlGetProp(xml_obj, XML_ATTR_ID);
-		const char *type   = xmlGetProp(xml_obj, XML_ATTR_TYPE);
+		xml_obj = xml_nodes;
+		attrs   = xml_obj->children;
+		id     = xmlGetProp(xml_obj, XML_ATTR_ID);
+		type   = xmlGetProp(xml_obj, XML_ATTR_TYPE);
 
 		crm_verbose("Processing node %s", id);
 
 		if(attrs != NULL) {
 			attrs = attrs->children;
 		}
 		
 		xml_nodes = xml_nodes->next;
 	
 		if(id == NULL) {
 			crm_err("Must specify id tag in <node>");
 			continue;
 		}
 		if(type == NULL) {
 			crm_err("Must specify type tag in <node>");
 			continue;
 		}
-		node_t *new_node  = crm_malloc(sizeof(node_t));
+		new_node  = crm_malloc(sizeof(node_t));
 		new_node->weight  = 1.0;
 		new_node->fixed   = FALSE;
 		new_node->details = (struct node_shared_s*)
 			crm_malloc(sizeof(struct node_shared_s));
 		new_node->details->id		= crm_strdup(id);
 		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(
 			g_str_hash, g_str_equal);
 
 		if(safe_str_eq(type, "node")) {
 			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)
 {
+	xmlNodePtr xml_obj   = NULL;
+	const char *id       = NULL;
+	const char *priority = NULL;
+	float priority_f;
+	resource_t *new_rsc = NULL;
+	action_t *action_stop = NULL;
+	action_t *action_start = NULL;
+	order_constraint_t *order = NULL;
+
+
 	crm_verbose("Begining unpack...");
 	while(xml_resources != NULL) {
-		xmlNodePtr xml_obj   = xml_resources;
-		const char *id       = xmlGetProp(xml_obj, XML_ATTR_ID);
-		const char *priority = xmlGetProp(
+		xml_obj   = xml_resources;
+		id       = xmlGetProp(xml_obj, XML_ATTR_ID);
+		priority = xmlGetProp(
 			xml_obj, XML_CIB_ATTR_PRIORITY);
 		// todo: check for null
-		float priority_f     = atof(priority);
+		priority_f     = atof(priority);
 
 		xml_resources = xml_resources->next;
 
 		crm_verbose("Processing resource...");
 		
 		if(id == NULL) {
 			crm_err("Must specify id tag in <resource>");
 			continue;
 		}
-		resource_t *new_rsc = crm_malloc(sizeof(resource_t));
+		new_rsc = crm_malloc(sizeof(resource_t));
 		new_rsc->id		= id;
 		new_rsc->class		= xmlGetProp(xml_obj, "class");
 		new_rsc->type		= xmlGetProp(xml_obj, "type");
 		new_rsc->xml		= xml_obj;
 		new_rsc->priority	= priority_f; 
 		new_rsc->candidate_colors = NULL;
 		new_rsc->color		= NULL; 
 		new_rsc->runnable	= TRUE; 
 		new_rsc->provisional	= TRUE; 
 		new_rsc->allowed_nodes	= node_list_dup(all_nodes);    
 		new_rsc->rsc_cons	= NULL; 
 		new_rsc->node_cons	= NULL; 
 		new_rsc->cur_node	= NULL;
 		
-		action_t *action_stop = action_new(
+		action_stop = action_new(
 			action_id++, new_rsc, stop_rsc);
 
-		action_t *action_start = action_new(
+		action_start = action_new(
 			action_id++, new_rsc, start_rsc);
 
 		new_rsc->stop = action_stop;
 		*actions = g_list_append(*actions, action_stop);
 
 		new_rsc->start = action_start;
 		*actions = g_list_append(*actions, action_start);
 
-		order_constraint_t *order = (order_constraint_t*)
+		order = (order_constraint_t*)
 			crm_malloc(sizeof(order_constraint_t));
 		order->id	 = order_id++;
 		order->lh_action = action_stop;
 		order->rh_action = action_start;
 		order->strength  = startstop;
 
 		*action_cons     = g_list_append(*action_cons, order);
 		*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...");
 	while(xml_constraints != NULL) {
 		const char *id = xmlGetProp(xml_constraints, XML_ATTR_ID);
 		xmlNodePtr xml_obj = xml_constraints;
 		xml_constraints = xml_constraints->next;
 		if(id == NULL) {
 			crm_err("Constraint must have an id");
 			continue;
 		}
 
 		crm_verbose("Processing constraint %s %s",
 			      xml_obj->name,id);
 		if(safe_str_eq("rsc_to_rsc", xml_obj->name)) {
 			unpack_rsc_to_rsc(xml_obj, resources,
 					  action_constraints);
 
 		} else if(safe_str_eq("rsc_to_node", xml_obj->name)) {
 			unpack_rsc_to_node(xml_obj, resources, nodes,
 					   node_constraints);
 			
 		} else if(safe_str_eq("rsc_to_attr", xml_obj->name)) {
 			unpack_rsc_to_attr(xml_obj, resources, nodes,
 					   node_constraints);
 			
 		} else {
 			crm_err("Unsupported constraint type: %s",
 			       xml_obj->name);
 		}
 	}
 
 	return TRUE;
 }
 
 
 gboolean
 unpack_rsc_to_node(xmlNodePtr xml_obj,
 		   GListPtr rsc_list,
 		   GListPtr node_list,
 		   GListPtr *node_constraints)	
 {
 	
 	xmlNodePtr node_ref = xml_obj->children;
 	rsc_to_node_t *new_con = crm_malloc(sizeof(rsc_to_node_t));
 	const char *id_lh =  xmlGetProp(xml_obj, "from");
 	const char *id =  xmlGetProp(xml_obj, XML_ATTR_ID);
 
 	const char *mod = xmlGetProp(xml_obj, "modifier");
 	const char *weight = xmlGetProp(xml_obj, "weight");
 	float weight_f = atof(weight);
 
 	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);
 	}
 
 	new_con->id = id;
 	new_con->rsc_lh = rsc_lh;
 	new_con->weight = weight_f;
 			
 	if(safe_str_eq(mod, "set")){
 		new_con->modifier = set;
 	} else if(safe_str_eq(mod, "inc")){
 		new_con->modifier = inc;
 	} else if(safe_str_eq(mod, "dec")){
 		new_con->modifier = dec;
 	} else {
 		// error
 	}
 /*
   <rsc_to_node>
   <node_ref id= type= name=/>
   <node_ref id= type= name=/>
   <node_ref id= type= name=/>
 */		
 //			
 
 	while(node_ref != NULL) {
 		const char *xml_name = node_ref->name;
 		const char *id_rh = xmlGetProp(node_ref, XML_NVPAIR_ATTR_NAME);
 		node_t *node_rh =  pe_find_node(node_list, id_rh);
 		node_ref = node_ref->next;
 		
 		if(node_rh == NULL) {
 			// error
 			crm_err("node %s (from %s) not found",
 				id_rh, xml_name);
 			continue;
 		}
 		
 		new_con->node_list_rh =
 			g_list_append(new_con->node_list_rh, node_rh);
 
 		
 		/* dont add it to the resource,
 		 *  the information is in the resouce's node list
 		 */
 	}
 	*node_constraints = g_list_append(*node_constraints, new_con);
 
 	return TRUE;
 }
 
 
 gboolean
 unpack_rsc_to_attr(xmlNodePtr xml_obj,
 		   GListPtr rsc_list,
 		   GListPtr node_list,
 		   GListPtr *node_constraints)
 {
 /*
 <rsc_to_attr id="cons4" from="rsc2" weight="20.0" modifier="inc">
 <attr_expression id="attr_exp_1"/>
   <node_match id="node_match_1" type="has_attr" target="cpu"/>
   <node_match id="node_match_2" type="attr_value" target="kernel" value="2.6"/>
 </attr_expression>
 <attr_expression id="attr_exp_2"/>
   <node_match id="node_match_3" type="has_attr" target="hdd"/>
   <node_match id="node_match_4" type="attr_value" target="kernel" value="2.4"/>
 </attr_expression>
 
    Translation:
        give any node a +ve weight of 20.0 to run rsc2 if:
           attr "cpu" is set _and_ "kernel"="2.6", _or_
 	  attr "hdd" is set _and_ "kernel"="2.4"
 
    Further translation:
        2 constraints that give any node a +ve weight of 20.0 to run rsc2
        cons1: attr "cpu" is set and "kernel"="2.6"
        cons2: attr "hdd" is set and "kernel"="2.4"
        
 */
 	
 	xmlNodePtr attr_exp = xml_obj->children;
 	const char *id_lh   =  xmlGetProp(xml_obj, "from");
 	const char *mod     = xmlGetProp(xml_obj, "modifier");
 	const char *weight  = xmlGetProp(xml_obj, "weight");
 	const char *id      = xmlGetProp(attr_exp, XML_ATTR_ID);
 	float weight_f      = atof(weight);
 	enum con_modifier a_modifier = modifier_none;
 	
 	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;
 	}
 			
 	if(safe_str_eq(mod, "set")){
 		a_modifier = set;
 	} else if(safe_str_eq(mod, "inc")){
 		a_modifier = inc;
 	} else if(safe_str_eq(mod, "dec")){
 		a_modifier = dec;
 	} else {
 		// error
 	}		
 
 	if(attr_exp == NULL) {
 		crm_err("no attrs for constraint %s", id);
 	}
 	
 	while(attr_exp != NULL) {
 		rsc_to_node_t *new_con = crm_malloc(sizeof(rsc_to_node_t));
 		new_con->id = xmlGetProp(attr_exp, XML_ATTR_ID);
 		new_con->rsc_lh = rsc_lh;
 		new_con->weight = weight_f;
 		new_con->modifier = a_modifier;
 
 		new_con->node_list_rh = match_attrs(attr_exp, node_list);
 		
 		if(new_con->node_list_rh == NULL) {
 			crm_warn("No matching nodes for constraint  %s (%s)",
 				 xmlGetProp(attr_exp, XML_NVPAIR_ATTR_NAME),
 				 attr_exp->name);
 		}
 		crm_debug_action(print_rsc_to_node("Added", new_con, FALSE));
 		*node_constraints = g_list_append(*node_constraints, new_con);
 
 		/* dont add it to the resource,
 		 *  the information is in the resouce's node list
 		 */
 		attr_exp = attr_exp->next;
 	}
 	return TRUE;
 }
 
 
 // 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 *node_constraints)
 {
 	const char *id        = NULL;
 
 	xmlNodePtr node_state = NULL;
 	xmlNodePtr lrm_rsc    = NULL;
 	xmlNodePtr lrm_agents = NULL;
 	xmlNodePtr attrs      = NULL;
 	node_t    *this_node  = NULL;
 	
 	crm_verbose("Begining unpack");
 	while(status != NULL) {
 		node_state = status;
 		status     = status->next;
 
 		id         = xmlGetProp(node_state, XML_ATTR_ID);
 		
 		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", id);
 		this_node = pe_find_node(nodes, id);
 
 		if(id == NULL) {
 			// error
 			continue;
 
 		} else if(this_node == NULL) {
 			crm_err("Node %s in status section no longer exists",
 				id);
 			continue;
 		}
 		
 		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, 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 *id	       = xmlGetProp(node_state,XML_ATTR_ID);
 	const char *state      = xmlGetProp(node_state,XML_LRM_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    = 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", id);
 		}
 
 		if(this_node->details->shutdown) {
 			crm_verbose("Node %s is due for shutdown", id);
 		}
 	}
 	return TRUE;
 }
 
 gboolean
 is_node_unclean(xmlNodePtr node_state)
 {
 	const char *state      = xmlGetProp(node_state,XML_LRM_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;
 	xmlNodePtr xml_agent = agent_list->children;
 	while(xml_agent != NULL){
 		agent = (lrm_agent_t*)crm_malloc(sizeof(lrm_agent_t));
 		agent->class = xmlGetProp(xml_agent, "class");
 		agent->type  = xmlGetProp(xml_agent, "type");
 
 		node->details->agents =
 			g_list_append(node->details->agents, agent);
 		
 		xml_agent = xml_agent->next;
 	}
 	
 	return TRUE;
 }
 
 
 gboolean
 unpack_lrm_rsc_state(node_t *node, xmlNodePtr lrm_rsc,
 		     GListPtr rsc_list, GListPtr *node_constraints)
 {
 	xmlNodePtr rsc_entry  = NULL;
 	const char *rsc_id    = NULL;
 	const char *node_id   = NULL;
 	const char *rsc_state = NULL;
 	const char *rsc_code  = NULL;
 	resource_t *rsc_lh    = NULL;
+	int rsc_code_i = 0;
 	
 	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_STATE);
 		rsc_code  = xmlGetProp(rsc_entry, "op_code");
 		
 		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;
 		}
 		
-		int rsc_code_i = atoi(rsc_code);
+		rsc_code_i = atoi(rsc_code);
 
 		switch(rsc_code_i) {
 			case 0:
 				unpack_healthy_resource(node_constraints,
 							rsc_entry,rsc_lh,node);
 				break;
 			default:
 				unpack_failed_resource(node_constraints,
 						       rsc_entry,rsc_lh,node);
 				break;
 		}
 
 	}
 	return TRUE;
 }
 
 gboolean
 unpack_failed_resource(GListPtr *node_constraints,
 		       xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node)
 {
 	const char *last_op  = xmlGetProp(rsc_entry, "last_op");
 
 	if(safe_str_eq(last_op, "start")) {
 		/* not running */
 		/* do not run the resource here again */
 		rsc_to_node_t *new_cons = crm_malloc(sizeof(rsc_to_node_t));
 		new_cons->id		= "dont_run_generate"; // genereate
 		new_cons->weight	= -1.0;
 		new_cons->modifier	= set;
 		new_cons->rsc_lh	= rsc_lh;
 		new_cons->node_list_rh	= g_list_append(NULL, node);
 		
 		*node_constraints = g_list_append(*node_constraints, new_cons);
 
 	} else if(safe_str_eq(last_op, "stop")) {
 		/* must assume still running */
 		/* remedial action:
 		 *   shutdown (so all other resources are stopped gracefully)
 		 *   and then STONITH node
 		 */
 		node->details->shutdown = TRUE;
 		node->details->unclean  = TRUE;
 		
 	} else {
 		/* unknown action... */
 		/* remedial action: ???
 		 *   shutdown (so all other resources are stopped gracefully)
 		 *   and then STONITH node
 		 */
 		node->details->shutdown = TRUE;
 		node->details->unclean  = TRUE;
 	}
 
 	return TRUE;
 }
 
 gboolean
 unpack_healthy_resource(GListPtr *node_constraints,
 			xmlNodePtr rsc_entry, resource_t *rsc_lh, node_t *node)
 {
 	const char *last_op  = xmlGetProp(rsc_entry, "last_op");
 
 	rsc_to_node_t *new_cons = crm_malloc(sizeof(rsc_to_node_t));
 	new_cons->id		= "healthy_generate"; // genereate one
 	new_cons->weight	= 1.0;
 	new_cons->modifier	= inc;
 	new_cons->rsc_lh	= rsc_lh;
 	new_cons->node_list_rh	= g_list_append(NULL, node);
 	
 	*node_constraints = g_list_append(*node_constraints, new_cons);
 	
 	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->id,
 				node->details->id);
 			// TODO: some recovery action!!
 			// like force a stop on the first node?
 			
 		} else {
 			/* we prefer to stay running here */
 			new_cons->weight = 100.0;
 			
 			/* create the link between this node and the rsc */
 			crm_verbose("Setting cur_node = %s for rsc = %s",
 				    node->details->id, rsc_lh->id);
 			
 			rsc_lh->cur_node = node;
 			node->details->running_rsc = g_list_append(
 				node->details->running_rsc, rsc_lh);
 		}
 		
 	} else {
 		/* we prefer to start where we once ran successfully */
 		new_cons->weight = 20.0;
 
 	}
 
 	crm_debug_action(
 		print_rsc_to_node("Added", new_cons, FALSE));
 	
 	return TRUE;
 }
 
 gboolean
 create_rsc_to_rsc(const char *id, enum con_strength strength,
 		  resource_t *rsc_lh, resource_t *rsc_rh)
 {
+	rsc_to_rsc_t *inverted_con = NULL;
+	rsc_to_rsc_t *new_con = NULL;
+
 	if(rsc_lh == NULL || rsc_rh == NULL){
 		// error
 		return FALSE;
 	}
 
-	rsc_to_rsc_t *new_con = crm_malloc(sizeof(rsc_to_node_t));
-	rsc_to_rsc_t *inverted_con = NULL;
+	new_con = crm_malloc(sizeof(rsc_to_node_t));
 
 	new_con->id = id;
 	new_con->rsc_lh = rsc_lh;
 	new_con->rsc_rh = rsc_rh;
 	new_con->strength = strength;
 	
 	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);
 
 	return TRUE;
 }
 
 gboolean
 create_ordering(const char *id, enum con_strength strength,
 		resource_t *rsc_lh, resource_t *rsc_rh,
 		GListPtr *action_constraints)
 {
+	action_t *lh_stop = NULL;
+	action_t *lh_start = NULL;
+	action_t *rh_stop = NULL;
+	action_t *rh_start = NULL;
+	order_constraint_t *order = NULL;
+
 	if(rsc_lh == NULL || rsc_rh == NULL){
 		// error
 		return FALSE;
 	}
 	
-	action_t *lh_stop = rsc_lh->stop;
-	action_t *lh_start = rsc_lh->start;
-	action_t *rh_stop = rsc_rh->stop;
-	action_t *rh_start = rsc_rh->start;
+	lh_stop = rsc_lh->stop;
+	lh_start = rsc_lh->start;
+	rh_stop = rsc_rh->stop;
+	rh_start = rsc_rh->start;
 	
-	order_constraint_t *order = (order_constraint_t*)
+	order = (order_constraint_t*)
 		crm_malloc(sizeof(order_constraint_t));
 	order->id = order_id++;
 	order->lh_action = lh_stop;
 	order->rh_action = rh_stop;
 	order->strength = strength;
 	*action_constraints = g_list_append(*action_constraints, order);
 	
 	order = (order_constraint_t*)
 		crm_malloc(sizeof(order_constraint_t));
 	order->id = order_id++;
 	order->lh_action = rh_start;
 	order->rh_action = lh_start;
 	order->strength = strength;
 	*action_constraints = g_list_append(*action_constraints, order);
 
 	return TRUE;
 }
 
 gboolean
 unpack_rsc_to_rsc(xmlNodePtr xml_obj,
 		  GListPtr rsc_list,
 		  GListPtr *action_constraints)
 {
 	const char *id_lh =  xmlGetProp(xml_obj, "from");
 	const char *id =  xmlGetProp(xml_obj, XML_ATTR_ID);
 	resource_t *rsc_lh = pe_find_resource(rsc_list, id_lh);
 	const char *id_rh = xmlGetProp(xml_obj, "to");
 	resource_t *rsc_rh = pe_find_resource(rsc_list, id_rh);
 	const char *strength = xmlGetProp(xml_obj, "strength");
 	const char *type = xmlGetProp(xml_obj, XML_ATTR_TYPE);
 	enum con_strength strength_e = ignore;
 
 	if(rsc_lh == NULL) {
 		crm_err("No resource (con=%s, rsc=%s)",
 		       id, id_lh);
 		return FALSE;
 	}
 	if(safe_str_eq(strength, XML_STRENGTH_VAL_MUST)) {
 		strength_e = must;
 		
 	} else if(safe_str_eq(strength, XML_STRENGTH_VAL_SHOULD)) {
 		strength_e = should;
 		
 	} else if(safe_str_eq(strength, XML_STRENGTH_VAL_SHOULDNOT)) {
 		strength_e = should_not;
 		
 	} else if(safe_str_eq(strength, XML_STRENGTH_VAL_MUSTNOT)) {
 		strength_e = must_not;
 	} else {
 		// error
 	}
 
 	if(safe_str_eq(type, "ordering")) {
 		// make an action_cons instead
 		return create_ordering(
 			id, strength_e, rsc_lh, rsc_rh, action_constraints);
 	}
 
 	return create_rsc_to_rsc(id, strength_e, rsc_lh, rsc_rh);
 }
 
 GListPtr
 match_attrs(xmlNodePtr attr_exp, GListPtr node_list)
 {
 	int lpc = 0;
 	GListPtr result = NULL;
+	const char *h_val = NULL;
+
 	slist_iter(
 		node, node_t, node_list, lpc,
 		xmlNodePtr node_match = attr_exp->children;
 		gboolean accept = TRUE;
 		
 		while(accept && node_match != NULL) {
 			const char *type = xmlGetProp(
 				node_match, XML_ATTR_TYPE);
 			const char *value= xmlGetProp(
 				node_match, XML_NVPAIR_ATTR_VALUE);
 			const char *name = xmlGetProp(node_match, "target");
 			node_match = node_match->next;
 			
 			if(name == NULL || type == NULL) {
 				// error
 				continue;
 			}
 			
-			const char *h_val = (const char*)
+			h_val = (const char*)
 				g_hash_table_lookup(node->details->attrs, name);
 			
 			if(h_val != NULL && safe_str_eq(type, "has_attr")){
 				accept = TRUE;
 			} else if(h_val == NULL
 				     && safe_str_eq(type, "not_attr")) {
 				accept = TRUE;
 			} else if(h_val != NULL
 				  && safe_str_eq(type, "attr_value")
 				  && safe_str_eq(h_val, value)) {
 				accept = TRUE;
 			} else {
 				accept = FALSE;
 			}
 		}
 		
 		if(accept) {
 			result = g_list_append(result, node);
 			
 		}		   
 		);
 	
 	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;
 	}	
 	return TRUE;
 }
diff --git a/crm/pengine/utils.c b/crm/pengine/utils.c
index 88cf6deea9..2bedc961e5 100644
--- a/crm/pengine/utils.c
+++ b/crm/pengine/utils.c
@@ -1,968 +1,978 @@
-/* $Id: utils.c,v 1.24 2004/06/07 10:29:03 andrew Exp $ */
+/* $Id: utils.c,v 1.25 2004/06/07 21:28:39 msoffen 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>
 
 void print_str_str(gpointer key, gpointer value, gpointer user_data);
 gboolean ghash_free_str_str(gpointer key, gpointer value, gpointer user_data);
 
 /* 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");
-	rsc_to_rsc_t *inverted_con =
+	inverted_con =
 		crm_malloc(sizeof(rsc_to_node_t));
 
 	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;
 
 	crm_debug_action(
 		print_rsc_to_rsc("Inverted constraint", inverted_con, FALSE)
 		);
 	return inverted_con;
 }
 
 rsc_to_node_t *
 copy_constraint(rsc_to_node_t *constraint) 
 {
 	rsc_to_node_t *copied_con = crm_malloc(sizeof(rsc_to_node_t));
 
 	copied_con->id		 = crm_strdup(constraint->id);
 
 	copied_con->rsc_lh = constraint->rsc_lh;
 	copied_con->node_list_rh = constraint->node_list_rh;
 	copied_con->modifier	 = constraint->modifier;
 	copied_con->weight	 = constraint->weight;
   
 	return copied_con;
 }
 
 
 /* are the contents of list1 and list2 equal */
 /* nodes with weight < 0 are ignored */
 gboolean
 node_list_eq(GListPtr list1, GListPtr list2)
 {
 	GListPtr result = NULL;
  
 	if(g_list_length(list1) != g_list_length(list2)) {
 		return FALSE;
 	}
   
 	// do stuff
 	crm_err("Not yet implemented");
  
 	return g_list_length(result) != 0;
 }
 
 /* the intersection of list1 and list2 
  * when merging weights, nodes set to < 0  in either list will always
  * have their weight set to -1 in the result
  */
 GListPtr
 node_list_and(GListPtr list1, GListPtr list2)
 {
 	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 = NULL;
 		node_t *other_node = find_list_node(list2, node->details->id);
 
 		if(node == NULL || other_node == NULL) {
 			continue;
 			
 			// merge node weights
 		} else if(node->weight < 0 || other_node->weight < 0) {
 			new_node = node_copy(node);
 			new_node->weight = -1;
 		} else {
 			new_node = node_copy(node);
 			new_node->weight = 
 				node->weight + other_node->weight;
 			if(new_node->weight != 0) {
 				new_node->weight = new_node->weight /2.0;
 			}
 		}
 		result = g_list_append(result, new_node);
 	}
  
 	return result;
 }
 
 node_t *
 find_list_node(GListPtr list, const char *id)
 {
 	int lpc = 0;
 	slist_iter(
 		thing, node_t, list, lpc,
 		if(safe_str_eq(thing->details->id, id)) {
 			return thing;
 		}
 		);
 	
 	return NULL;
 }
 
 /* list1 - list2 */
 GListPtr
 node_list_minus(GListPtr list1, GListPtr list2)
 {
 	GListPtr result = NULL;
 	int lpc = 0;
 
 	slist_iter(
 		node, node_t, list1, lpc,
 		node_t *other_node = find_list_node(list2, node->details->id);
 		
+		node_t *new_node = NULL;
 		if(node == NULL || other_node != NULL) {
 			continue;
 			
 		}
-		node_t *new_node = node_copy(node);
+		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)
 {
 	GListPtr result = NULL;
 	int lpc = 0;
+	node_t *new_node = NULL;
 	
 	slist_iter(
 		node, node_t, list1, lpc,
 		node_t *other_node = (node_t*)find_list_node(list2, node->details->id);
 
 		if(node == NULL || other_node != NULL) {
 			continue;
 		}
-		node_t *new_node = node_copy(node);
+		new_node = node_copy(node);
 		result = g_list_append(result, new_node);
 		);
 	
  
 	slist_iter(
 		node, node_t, list1, lpc,
 		node_t *other_node = (node_t*)find_list_node(list1, node->details->id);
 
 		if(node == NULL || other_node != NULL) {
 			continue;
 		}
-		node_t *new_node = node_copy(node);
+		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_dup(GListPtr list1)
 {
 	GListPtr result = NULL;
 	int lpc = 0;
 	slist_iter(
 		this_node, node_t, list1, lpc,
 		node_t *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);
 		return NULL;
 	}
-	node_t *new_node = crm_malloc(sizeof(node_t));
+	new_node = crm_malloc(sizeof(node_t));
 	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, GListPtr nodes, GListPtr resources)
 {
 	color_t *new_color = NULL;
 	
 	if(g_list_length(*colors) >= max_valid_nodes) {
 		return NULL;
 	}
 	
 	new_color = crm_malloc(sizeof(color_t));
 
 	new_color->id = color_id++;
 	new_color->local_weight = 1.0;
 	new_color->details = crm_malloc(sizeof(struct color_shared_s));
 	new_color->details->id = new_color->id; 
 	new_color->details->chosen_node = NULL; 
 	new_color->details->candidate_nodes = node_list_dup(nodes);
 
 	crm_debug_action(print_color("Created color", new_color, TRUE));
 
 	if(colors != NULL) {
 		*colors = g_list_append(*colors, new_color);      
 	}
 	
 	if(resources != NULL) {
 		/* Add any new color to the list of candidate_colors for
 		 * resources that havent been decided yet 
 		 */
 		int lpc;
 		slist_iter(
 			rsc, resource_t, resources, lpc,
 			if(rsc->provisional && rsc->runnable) {
 				color_t *color_copy = (color_t *)
 					cl_malloc(sizeof(color_t));
 
 				color_copy->id      = new_color->id;
 				color_copy->details = new_color->details;
 				color_copy->local_weight = 1.0; 
 
 				rsc->candidate_colors =
 					g_list_append(rsc->candidate_colors,
 						       color_copy);
 			}
 			);
 	}
 	
 	return new_color;
 }
 
 
 /*
  * 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 = 0; // restart the loop
 		}
 		);
 
 	return TRUE;
 }
 
 resource_t *
 pe_find_resource(GListPtr rsc_list, const char *id_rh)
 {
 	int lpc = 0;
 	for(lpc = 0; lpc < g_list_length(rsc_list); lpc++) {
 		resource_t *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 *id)
 {
 	int lpc = 0;
   
 	for(lpc = 0; lpc < g_list_length(nodes); lpc++) {
 		node_t *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;
 	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(int id, resource_t *rsc, enum action_tasks task)
 {
 	action_t *action = (action_t*)crm_malloc(sizeof(action_t));
 	action->id   = 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   = FALSE;
 	action->processed  = FALSE;
 	action->optional   = FALSE;
 	action->seen_count = 0;
 
 	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 ignore:
 			result = "ignore";
 			break;
 		case must:
 			result = XML_STRENGTH_VAL_MUST;
 			break;
 		case should:
 			result = XML_STRENGTH_VAL_SHOULD;
 			break;
 		case should_not:
 			result = XML_STRENGTH_VAL_SHOULDNOT;
 			break;
 		case must_not:
 			result = XML_STRENGTH_VAL_MUSTNOT;
 			break;
 		case startstop:
 			result = "start/stop";
 			break;
 	}
 	return result;
 };
 
 const char *
 modifier2text(enum con_modifier modifier)
 {
 	const char *result = "<unknown>";
 	switch(modifier)
 	{
 		case modifier_none:
 			result = "modifier_none";
 			break;
 		case set:
 			result = "set";
 			break;
 		case inc:
 			result = "inc";
 			break;
 		case dec: 
 			result = "dec";
 			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->id, 
 	       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->id,
 	       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,
 	       color->details->chosen_node==NULL?"<unset>":color->details->chosen_node->details->id,
 	       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):",
 	       pre_text==NULL?"":pre_text,
 	       pre_text==NULL?"":": ",
 	       "rsc_to_node",
 	       cons->id, cons);
 
 	if(details == FALSE) {
 		crm_debug("\t%s --> %s, %f (node placement rule)",
 		       cons->rsc_lh->id, 
 		       modifier2text(cons->modifier),
 		       cons->weight);
 
-		int lpc = 0;
 		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",
 			  cons->rsc_lh==NULL?"null":cons->rsc_lh->id, 
 			  cons->rsc_rh==NULL?"null":cons->rsc_rh->id, 
 			  strength2text(cons->strength));
 	}
 } 
 
 void
 print_resource(const char *pre_text, resource_t *rsc, gboolean details)
 { 
+	int lpc = 0;
+
 	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, id));
 
 	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, id));
 			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, id));
 			
 			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;
 
 		if(details != NULL) {
 //			crm_free(details->id);
 			g_hash_table_foreach_remove(
 				details->attrs, ghash_free_str_str, NULL);
 
 			g_hash_table_destroy(details->attrs);
 			crm_free(details);
 		}
 		
 		crm_free(node);
 	}
 	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);
 			crm_free(details->chosen_node);
 			crm_free(details);
 		}
 		crm_free(color);
 	}
 	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_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;
+	int lpc;
 	
 	while(resources != NULL) {
 		list_item = resources;
 		rsc = (resource_t *)list_item->data;
 		resources = resources->next;
 
 //		crm_free(rsc->id);
 		
 //		crm_verbose("color");
 //		crm_free(rsc->color);
 
-		int lpc;
 		slist_iter(clr, color_t, rsc->candidate_colors, lpc,
 			   print_color("deleting", clr, FALSE));
 		
 //		pe_free_shallow(rsc->candidate_colors);
 		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);
 		crm_free(rsc);
 	}
 	g_list_free(resources);
 	
 }
 
 
 void
 pe_free_actions(GListPtr actions) 
 {
+	GListPtr list_item = NULL;
+	action_t *action = NULL;
+
 	while(actions != NULL) {
-		GListPtr list_item = actions;
-		action_t *action = (action_t *)list_item->data;
+		list_item = actions;
+		action = (action_t *)list_item->data;
 		actions = actions->next;
 
 		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;
 		crm_free(action);
 	}
 	g_list_free(actions);
 }
 
 
 
 void
 pe_free_rsc_to_rsc(rsc_to_rsc_t *cons)
 { 
 	if(cons != NULL) {
 //		crm_free(cons->id);
 		crm_free(cons);
 	}
 }
 
 void
 pe_free_rsc_to_node(rsc_to_node_t *cons)
 {
 	if(cons != NULL) {
 //		crm_free(cons->id);
 		pe_free_shallow(cons->node_list_rh); // node_t*
 		crm_free(cons);
 	}
 }
-
diff --git a/crm/tengine/tengine.c b/crm/tengine/tengine.c
index f86c6044cb..e92dcaa634 100644
--- a/crm/tengine/tengine.c
+++ b/crm/tengine/tengine.c
@@ -1,684 +1,695 @@
-/* $Id: tengine.c,v 1.17 2004/06/03 07:52:17 andrew Exp $ */
+/* $Id: tengine.c,v 1.18 2004/06/07 21:28:39 msoffen 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/msg.h>
 #include <crm/common/xml.h>
 #include <tengine.h>
 
 GListPtr graph = NULL;
 IPC_Channel *crm_ch = NULL;
 
 typedef struct action_list_s 
 {
 		gboolean force;
 		int index;
 		int index_max;
 		GListPtr actions;
 } action_list_t;
 
 void print_state(void);
 gboolean initialize_graph(void);
 gboolean unpack_graph(xmlNodePtr xml_graph);
 gboolean extract_event(xmlNodePtr msg);
 gboolean initiate_transition(void);
 gboolean initiate_action(action_list_t *list);
 gboolean process_graph_event(const char *event_node,
 			     const char *event_rsc, 
 			     const char *event_action, 
 			     const char *event_status, 
 			     const char *event_rc);
 
 void send_success(void);
 void send_abort(xmlNodePtr msg);
 
 gboolean
 initialize_graph(void)
 {
 	while(g_list_length(graph) > 0) {
 		action_list_t *action_list = g_list_nth_data(graph, 0);
 		while(g_list_length(action_list->actions) > 0) {
 			xmlNodePtr action =
 				g_list_nth_data(action_list->actions, 0);
 			action_list->actions =
 				g_list_remove(action_list->actions, action);
 			free_xml(action);
 		}
 		graph = g_list_remove(graph, action_list);
 		crm_free(action_list);
 	}
 
 	graph = NULL;
 	
 	return TRUE;
 }
 
 
 gboolean
 unpack_graph(xmlNodePtr xml_graph)
 {
 /*
 <transition_graph>
 	<actions id="0">
 		<rsc_op id="5" runnable=XML_BOOLEAN_FALSE optional=XML_BOOLEAN_TRUE task="stop">
 			<resource id="rsc3" priority="3.0"/>
 		</rsc_op>
 */
 	xmlNodePtr xml_action_list = xml_graph?xml_graph->children:NULL;
 	if(xml_action_list == NULL) {
 		// nothing to do
 		return FALSE;
 	}
 	
 	while(xml_action_list != NULL) {
 		xmlNodePtr xml_obj = xml_action_list;
 		xmlNodePtr xml_action = xml_obj->children;
 		action_list_t *action_list = (action_list_t*)
 			crm_malloc(sizeof(action_list_t));
 
 		xml_action_list = xml_action_list->next;
 
 		action_list->force = FALSE;
 		action_list->index = -1;
 		action_list->index_max = 0;
 		action_list->actions = NULL;
 		
 		while(xml_action != NULL) {
 			xmlNodePtr action =
 				copy_xml_node_recursive(xml_action);
 
 			action_list->actions =
 				g_list_append(action_list->actions, action);
 			
 			action_list->index_max++;
 			xml_action = xml_action->next;
 		}
 		
 		graph = g_list_append(graph, action_list);
 	}
 	
 
 	return TRUE;
 }
 
 gboolean
 extract_event(xmlNodePtr msg)
 {
 	gboolean abort      = FALSE;
 	xmlNodePtr iter     = NULL;
 	const char *section = NULL;
 
 	const char *event_action = NULL;
 	const char *event_node   = NULL;
 	const char *event_rsc    = NULL;
 	const char *event_status = NULL;
 	const char *event_rc     = 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"/>
 */
 
 	iter = find_xml_node(msg, XML_TAG_FRAGMENT);
 	section = xmlGetProp(iter, XML_ATTR_SECTION);
 
 	if(safe_str_neq(section, XML_CIB_TAG_STATUS)) {
 		// these too are never expected
 		return FALSE;
 	}
 	
 	iter = find_xml_node(iter, XML_TAG_CIB);
 	iter = get_object_root(XML_CIB_TAG_STATUS, iter);
 	iter = iter->children;
 	
 	while(abort == FALSE && iter != NULL) {
 		xmlNodePtr node_state = iter;
 		xmlNodePtr child = iter->children;
 		const char *state = xmlGetProp(
 			node_state, XML_CIB_ATTR_JOINSTATE);
 		iter = iter->next;
 
 		if(xmlGetProp(node_state, XML_CIB_ATTR_SHUTDOWN) != NULL
 		   || xmlGetProp(node_state, XML_CIB_ATTR_STONITH) != NULL) {
 			abort = TRUE;
 			
 		} else if(state != NULL && child == NULL) {
 			/* node state update,
 			 * possibly from a shutdown we requested
 			 */
 			event_status = state;
 			event_node   = xmlGetProp(node_state, XML_ATTR_ID);
 			
 			if(safe_str_eq(event_status, CRMD_JOINSTATE_DOWN)) {
 				event_action = XML_CIB_ATTR_SHUTDOWN;
 			} else {
 				// never expected... yet.  STONITH?
 				event_action = "startup";
 			}
 			
 			abort = !process_graph_event(event_node,
 						     event_rsc,
 						     event_action,
 						     event_status,
 						     event_rc);
 
 		} else if(state == NULL && child != NULL) {
 			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;
 			}
 			
 			while(abort == FALSE && child != NULL) {
 				event_action = xmlGetProp(
 					child, XML_LRM_ATTR_LASTOP);
 				event_node   = xmlGetProp(
 					child, XML_LRM_ATTR_TARGET);
 				event_rsc    = xmlGetProp(
 					child, XML_ATTR_ID);
 				event_status = xmlGetProp(
 					child, XML_LRM_ATTR_OPSTATE);
 				event_rc     = xmlGetProp(
 					child, XML_LRM_ATTR_OPCODE);
 				
 				abort = !process_graph_event(event_node,
 							     event_rsc,
 							     event_action,
 							     event_status,
 							     event_rc);
 
 				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
 			 */
 			abort = TRUE;
 			
 		} else {
 			/* ignore */
 		}
 	}
 	
 	return !abort;
 }
 
 gboolean
 process_graph_event(const char *event_node,
 		    const char *event_rsc, 
 		    const char *event_action, 
 		    const char *event_status, 
 		    const char *event_rc)
 {
 	int lpc;
 	xmlNodePtr action        = NULL; // <rsc_op> or <crm_event>
 	xmlNodePtr next_action   = NULL;
 	action_list_t *matched_action_list = NULL;
+	const char *this_action = NULL;
+	const char *this_node   = NULL;
+	const char *this_rsc    = NULL;
 
 // Find the action corresponding to this event
 	slist_iter(
 		action_list, action_list_t, graph, lpc,
 		action = g_list_nth_data(action_list->actions,
 					  action_list->index);
 
 		if(action == NULL) {
 			continue;
 		}
 /*
 		<rsc_op id= runnable= optional= task= on_node= >
 			<resource id="rsc3" priority="3.0"/>
 		</rsc_op>
 */
-		const char *this_action = xmlGetProp(
+
+		this_action = xmlGetProp(
 			action, XML_LRM_ATTR_TASK);
-		const char *this_node   = xmlGetProp(
+		this_node   = xmlGetProp(
 			action, XML_LRM_ATTR_TARGET);
-		const char *this_rsc    = xmlGetProp(
+		this_rsc    = xmlGetProp(
 			action->children, XML_ATTR_ID);
 
 		if(safe_str_neq(this_node, event_node)) {
 			continue;
 
 		} else if(safe_str_neq(this_action, event_action)) {
 			continue;
 			
 		} else if(safe_str_eq(action->name, "rsc_op")
 			  && safe_str_eq(this_rsc, event_rsc)) {
 			matched_action_list = action_list;
 
 		} else if(safe_str_eq(action->name, "crm_event")) {
 			matched_action_list = action_list;
 		}
 		);			
 
 	if(matched_action_list == NULL) {
 		// unexpected event, trigger a pe-recompute
 		// possibly do this only for certain types of actions
 		crm_err("Unexpected event... matched action list was NULL");
 		return FALSE;
 	}
 	
 	// how do we distinguish action failure?
 	if(safe_str_neq(event_rc, "0")){
 		if(safe_str_neq((const char*)xmlGetProp(action, "allow_fail"),
 				XML_BOOLEAN_TRUE)) {
 			crm_err("Action %s to %s on %s resulted in failure..."
 			       " aborting transition.",
 			       event_action, event_rsc, event_node);
 			return FALSE;
 		}
 	}
 	
 	while(matched_action_list->index <= matched_action_list->index_max) {
 		gboolean passed = FALSE;
 		next_action = g_list_nth_data(matched_action_list->actions,
 					       matched_action_list->index);
 		
 		passed = initiate_action(matched_action_list);
 
 		if(passed == FALSE) {
 			crm_err("Initiation of next event failed");
 			return FALSE;
 			
 		} else if(matched_action_list->index >
 			  matched_action_list->index_max) {
 			/* last action in that list, check if there are
 			 *  anymore actions at all
 			 */
 			slist_iter(
 				action_list, action_list_t, graph, lpc,
 				if(action_list->index <=
 				   action_list->index_max){
 					return TRUE;
 				}
 				);
 		} else {
 			return TRUE;
 			
 		}
 
 	}
 	crm_info("Transition complete...");
 
 	send_success();
 	
 	return TRUE;
 }
 
 gboolean
 initiate_transition(void)
 {
 	int lpc;
 	gboolean anything = FALSE;
 
 	
 	
 	slist_iter(
 		action_list, action_list_t, graph, lpc,
 		if(initiate_action(action_list)
 		   && action_list->index <= action_list->index_max) {
 			anything = TRUE;
 		}
 		);
 
 	return anything;
 }
 
 gboolean
 initiate_action(action_list_t *list) 
 {
 	gboolean is_optional  = TRUE;
 	xmlNodePtr xml_action = NULL;
 	const char *on_node   = NULL;
 	const char *id        = NULL;
 	const char *runnable  = NULL;
 	const char *optional  = NULL;
 	const char *task      = NULL;
 	const char *discard   = NULL;
+#ifndef TESTING
+	xmlNodePtr options = NULL;
+	xmlNodePtr data = NULL;
+	xmlNodePtr rsc_op = NULL;
+#endif
 	
 	while(TRUE) {
 		
 		list->index++;
 		xml_action = g_list_nth_data(list->actions, list->index);
 		
 		if(xml_action == NULL) {
 			crm_info("No tasks left on this list");
 			list->index = list->index_max + 1;
 			
 			return TRUE;
 		}
 		
 		discard  = xmlGetProp(xml_action, XML_LRM_ATTR_DISCARD);
 		on_node  = xmlGetProp(xml_action, XML_LRM_ATTR_TARGET);
 		id       = xmlGetProp(xml_action, XML_ATTR_ID);
 		runnable = xmlGetProp(xml_action, XML_LRM_ATTR_RUNNABLE);
 		optional = xmlGetProp(xml_action, XML_LRM_ATTR_OPTIONAL);
 		task     = xmlGetProp(xml_action, XML_LRM_ATTR_TASK);
 		
 		if(safe_str_eq(discard, XML_BOOLEAN_TRUE)) {
 			crm_info("Skipping discarded rsc-op (%s): %s %s on %s",
 				 id, task,
 				 xmlGetProp(xml_action->children, XML_ATTR_ID),
 				 on_node);
 			continue;
 		}
 
 		if(safe_str_neq(optional, XML_BOOLEAN_TRUE)) {
 			is_optional = FALSE;
 		}
 		
 		list->force = list->force || !is_optional;
 
 		crm_verbose("Processing action %s (id=%s) on %s",
 		       task, id, on_node);
 		
 		if(list->force && is_optional) {
 			crm_info("Forcing execution of otherwise optional task "
 				 "due to a dependancy on a previous action");
 		}
 		
 		if(list->force == FALSE && is_optional) {
 			if(safe_str_eq(xml_action->name, "rsc_op")){
 				crm_info("Skipping optional rsc-op (%s):"
 					 " %s %s on %s",
 					 id, task,
 					 xmlGetProp(xml_action->children,
 						    XML_ATTR_ID),
 				       on_node);
 			} else {
 				crm_info("Skipping optional command"
 					 " %s (id=%s) on %s",
 					 task, id, on_node);
 			}
 			
 		} else if(safe_str_eq(runnable, XML_BOOLEAN_FALSE)) {
 			crm_err("Terminated transition on un-runnable command:"
 				" %s (id=%s) on %s",
 				task, id, on_node);
 			return FALSE;
 			
 		} else if(id == NULL || strlen(id) == 0
 			  || on_node == NULL || strlen(on_node) == 0
 			  || task == NULL || strlen(task) == 0) {
 			// error
 			crm_err("Failed on corrupted command: %s (id=%s) on %s",
 				task, id, on_node);
 			
 			return FALSE;
 			
 		} else if(safe_str_eq(xml_action->name, "pseduo_event")){
 			if(safe_str_eq(task, "stonith")){
 				crm_info("Executing %s (%s) of node %s",
 					 task, id, on_node);
 /*
   translate this into a stonith op by deisgnated node
   may need the CIB to determine who is running the stonith resource
     for this node
   more liekly, have the pengine find and supply that info 
 */
 			} else {
 				crm_err("Failed on unsupported %s: "
 					"%s (id=%s) on %s",
 					xml_action->name, task, id, on_node);
 				
 				return FALSE;
 			}
 			
 			
 		} else if(safe_str_eq(xml_action->name, "crm_event")){
 			/*
 			  <crm_msg op=XML_LRM_ATTR_TASK to=XML_RES_ATTR_TARGET>
 			*/
 			crm_info("Executing crm-event (%s): %s on %s",
 				 id, task, on_node);
 #ifndef TESTING
-			xmlNodePtr options = create_xml_node(
+			options = create_xml_node(
 				NULL, XML_TAG_OPTIONS);
 			set_xml_property_copy(options, XML_ATTR_OP, task);
 			
 			send_ipc_request(crm_ch, options, NULL,
 					 on_node, CRM_SYSTEM_CRMD, CRM_SYSTEM_TENGINE,
 					 NULL, NULL);
 			
 			free_xml(options);
 			return TRUE;
 #endif			
 		} else if(safe_str_eq(xml_action->name, "rsc_op")){
 			crm_info("Executing rsc-op (%s): %s %s on %s",
 				 id, task,
 				 xmlGetProp(xml_action->children, XML_ATTR_ID),
 				 on_node);
 #ifndef TESTING
 			/*
 			  <msg_data>
 			  <rsc_op id="operation number" on_node="" task="">
 			  <resource>...</resource>
 			*/
-			xmlNodePtr options = create_xml_node(
+			options = create_xml_node(
 				NULL, XML_TAG_OPTIONS);
-			xmlNodePtr data = create_xml_node(NULL, "msg_data");
-			xmlNodePtr rsc_op = create_xml_node(data, "rsc_op");
+			data = create_xml_node(NULL, "msg_data");
+			rsc_op = create_xml_node(data, "rsc_op");
 			
 			set_xml_property_copy(options, XML_ATTR_OP, "rsc_op");
 			
 			set_xml_property_copy(rsc_op, XML_ATTR_ID, id);
 			set_xml_property_copy(
 				rsc_op, XML_LRM_ATTR_TASK, task);
 			set_xml_property_copy(
 				rsc_op, XML_LRM_ATTR_TARGET, on_node);
 			
 			add_node_copy(rsc_op, xml_action->children);
 			
 			send_ipc_request(crm_ch, options, data,
 					 on_node, "lrmd", CRM_SYSTEM_TENGINE,
 					 NULL, NULL);
 			
 			free_xml(options);
 			free_xml(data);
 			return TRUE;
 #endif			
 			
 		} else {
 			// error
 			crm_err("Failed on unsupported command type: "
 				"%s, %s (id=%s) on %s",
 				xml_action->name, task, id, on_node);
 
 			return FALSE;
 		}
 	}
 	
 	return FALSE;
 }
 
 FILE *msg_te_strm = NULL;
 
 gboolean
 process_te_message(xmlNodePtr msg, IPC_Channel *sender)
 {
+	xmlNodePtr graph = NULL;
 	const char *op = get_xml_attr (msg, XML_TAG_OPTIONS,
 				       XML_ATTR_OP, FALSE);
 
 	const char *sys_to = xmlGetProp(msg, XML_ATTR_SYSTO);
 	const char *ref    = xmlGetProp(msg, XML_ATTR_REFERENCE);
 
 	crm_debug("Processing %s (%s) message", op, ref);
 
 #ifdef MSG_LOG
 	if(msg_te_strm == NULL) {
 		msg_te_strm = fopen("/tmp/te.log", "w");
 	}
 	fprintf(msg_te_strm, "[Input %s]\t%s\n",
 		op, dump_xml_node(msg, FALSE));
 	fflush(msg_te_strm);
 #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;
 	}
 
 	
 	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);
 		return FALSE;
 		
 	} else if(strcmp(op, CRM_OP_TRANSITION) == 0) {
 
 		crm_trace("Initializing graph...");
 		initialize_graph();
 
-		xmlNodePtr graph = find_xml_node(msg, "transition_graph");
+		graph = find_xml_node(msg, "transition_graph");
 		crm_trace("Unpacking graph...");
 		unpack_graph(graph);
 		crm_trace("Initiating transition...");
 		if(initiate_transition() == FALSE) {
 			// nothing to be done.. means we're done.
 			crm_info("No actions to be taken..."
 			       " transition compelte.");
 			send_success();		
 		}
 		crm_trace("Processing complete...");
 		
 		
 	} else if(strcmp(op, CRM_OP_EVENTCC) == 0) {
 		const char *true_op = get_xml_attr (msg, XML_TAG_OPTIONS,
 						    XML_ATTR_TRUEOP, TRUE);
 		if(true_op == NULL) {
 			crm_err(
 			       "Illegal update,"
 			       " the original operation must be specified");
 			send_abort(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(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);
 		}
 		
 	} 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);
 	}
 	
 	return TRUE;
 }
 
 void
 send_abort(xmlNodePtr msg)
 {	
 	xmlNodePtr options = create_xml_node(NULL, XML_TAG_OPTIONS);
 
 	print_state();
 	
 	crm_trace("Sending \"abort\" message");
 	
 #ifdef MSG_LOG
 	fprintf(msg_te_strm, "[Result ]\tTransition aborted\n");
 	fflush(msg_te_strm);
 #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(void)
 {	
 	xmlNodePtr options = create_xml_node(NULL, XML_TAG_OPTIONS);
 
 	print_state();
 
 	crm_trace("Sending \"complete\" message");
 
 #ifdef MSG_LOG
 	fprintf(msg_te_strm, "[Result ]\tTransition complete\n");
 	fflush(msg_te_strm);
 #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(void)
 {
 	int lpc = 0;
 	crm_debug("#!!#!!# Start Transitioner state");
 	if(graph == NULL) {
 		crm_debug("\tEmpty transition graph");
 	} else {
 		slist_iter(
 			action_list, action_list_t, graph, lpc,
 
 			crm_debug("\tAction set %d: %d of %d actions invoked",
 				  lpc, action_list->index,
 				  action_list->index_max);
 			);
 	}
 	
 	crm_debug("#!!#!!# End Transitioner state");
 }
diff --git a/crm/tengine/ttest.c b/crm/tengine/ttest.c
index 4d0361d3e7..f249746b9b 100644
--- a/crm/tengine/ttest.c
+++ b/crm/tengine/ttest.c
@@ -1,140 +1,142 @@
-/* $Id: ttest.c,v 1.6 2004/06/07 10:40:33 andrew Exp $ */
+/* $Id: ttest.c,v 1.7 2004/06/07 21:28:39 msoffen 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/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 <tengine.h>
 
 extern gboolean unpack_graph(xmlNodePtr xml_graph);
 extern gboolean initiate_transition(void);
 extern gboolean initialize_graph(void);
 
 int
 main(int argc, char **argv)
 {
 	int argerr = 0;
 	int flag;
+	xmlNodePtr xml_graph = NULL;
   
 	cl_log_set_entity("ttest");
 	cl_log_enable_stderr(TRUE);
 	cl_log_set_facility(LOG_USER);
 
 	while (1) {
 		int option_index = 0;
 		static struct option long_options[] = {
 			// Top-level Options
 			{"daemon", 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;
       
 				/* 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':
 				printf("option %d", flag);
 				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 =#=#=#=#=");
   
 #ifdef MTRACE  
 	mtrace();
 #endif
+
 	crm_trace("Initializing graph...");
 	initialize_graph();
 	
-	xmlNodePtr xml_graph = file2xml(stdin);
+	xml_graph = file2xml(stdin);
 
 	crm_trace("Unpacking graph...");
 	unpack_graph(xml_graph);
 	crm_trace("Initiating transition...");
 
 	if(initiate_transition() == FALSE) {
 		// nothing to be done.. means we're done.
 		crm_info("No actions to be taken..."
 		       " transition compelte.");
 	}
 
 	initialize_graph();
 	free_xml(xml_graph);
 #ifdef MTRACE  
 	muntrace();
 #endif
 	crm_trace("Transition complete...");
 
 	return 0;
 }
diff --git a/lib/plugins/lrm/raexechb.c b/lib/plugins/lrm/raexechb.c
index 17d5a24ab6..1954a10679 100644
--- a/lib/plugins/lrm/raexechb.c
+++ b/lib/plugins/lrm/raexechb.c
@@ -1,315 +1,316 @@
 /* 
  * 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
  *
  * File: raexechb.c
  * Author: Sun Jiang Dong <sunjd@cn.ibm.com>
  * Copyright (c) 2004 International Business Machines
  *
  * This code implements the Resource Agent Plugin Module for LSB style.
  * It's a part of Local Resource Manager. Currently it's used by lrmd only.
  */
 
 #include <portability.h>
 #include <stdio.h>		
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
 #include <dirent.h>
+#include <libgen.h>
 #include <glib.h>
 #include <clplumbing/cl_log.h>
 #include <pils/plugin.h>
 #include <lrm/raexec.h>
 
 #define PIL_PLUGINTYPE		RA_EXEC_TYPE
 #define PIL_PLUGIN		heartbeat
 #define PIL_PLUGINTYPE_S	"RAExec"
 #define PIL_PLUGIN_S		"heartbeat"
 #define PIL_PLUGINLICENSE	LICENSE_PUBDOM
 #define PIL_PLUGINLICENSEURL	URL_PUBDOM
 
 static const char * RA_PATH = "/etc/ha.d/resource.d/";
 
 /* The begin of exported function list */
 static int execra(const char * ra_name,  
 		  const char * op,
 	 	  GHashTable * cmd_params,
 		  GHashTable * env_params);
 
 static uniform_ret_execra_t map_ra_retvalue(int ret_execra, const char * op);
 static int get_resource_list(GList ** rsc_info);
 /* The end of exported function list */
  
 /* The begin of internal used function & data list */
 #define MAX_PARAMETER_NUM 40
 typedef char * RA_ARGV[MAX_PARAMETER_NUM];
 
 static int prepare_cmd_parameters(const char * ra_name, const char * op, 
 		GHashTable * params, RA_ARGV params_argv);
 static void params_hash_to_argv(gpointer key, gpointer value,
                                 gpointer user_data);
 static int raexec_setenv(GHashTable * env_params);
 static void set_env(gpointer key, gpointer value, gpointer user_data);
 /* The end of internal function & data list */
 
 /* Rource agent execution plugin operations */
 static struct RAExecOps raops =
 {	execra,
 	map_ra_retvalue,
 	get_resource_list
 };
 
 /*
  * The following two functions are only exported to the plugin infrastructure.
  */
 
 /*
  * raexec_closepi is called as part of shutting down the plugin.
  * If there was any global data allocated, or file descriptors opened, etc.
  * which is associated with the plugin, and not a single interface
  * in particular, here's our chance to clean it up.
  */
 static void raexec_closepi(PILPlugin *pi)
 {
 }
 
 /*
  * raexec_close_intf called as part of shutting down the md5 HBauth interface.
  * If there was any global data allocated, or file descriptors opened, etc.
  * which is associated with the md5 implementation, here's our chance
  * to clean it up.
  */
 static PIL_rc raexec_closeintf(PILInterface *pi, void *pd)
 {
 	return PIL_OK;
 }
 
 PIL_PLUGIN_BOILERPLATE("1.0", Debug, raexec_closepi);
 
 static const PILPluginImports*  PluginImports;
 static PILPlugin*               OurPlugin;
 static PILInterface*		OurInterface;
 static void*			OurImports;
 static void*			interfprivate;
 
 /*
  * Our plugin initialization and registration function
  * It gets called when the plugin gets loaded.
  */
 PIL_rc
 PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports);
 
 PIL_rc
 PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports)
 {
 	/* Force the compiler to do a little type checking */
 	(void)(PILPluginInitFun)PIL_PLUGIN_INIT;
 
 	PluginImports = imports;
 	OurPlugin = us;
 
 	/* Register ourself as a plugin */
 	imports->register_plugin(us, &OurPIExports);  
 
 	/*  Register our interfaces */
  	return imports->register_interface(us, PIL_PLUGINTYPE_S,  PIL_PLUGIN_S,	
 		&raops, raexec_closeintf, &OurInterface, &OurImports,
 		interfprivate); 
 }
 
 /*
  *	Real work starts here ;-)
  */
 
 static int 
 execra( const char * ra_name, const char * op, 
 	GHashTable * cmd_params, GHashTable * env_params )
 {
         RA_ARGV params_argv;
 	uniform_ret_execra_t exit_value;
 	char *ra_name_dup, *base_name;
 	GString * ra_dirname;
 
 	cl_log(LOG_DEBUG, "To execute a RA %s.", ra_name);
 	/* Prepare the call parameter */
 	if (0 > prepare_cmd_parameters(ra_name, op, cmd_params, params_argv)) {
 		cl_log(LOG_ERR, "HB RA: Error of preparing parameters");
 		return -1;
 	}
 
 	ra_dirname = g_string_new(ra_name);
 	ra_name_dup = strndup(ra_name, RA_MAX_DIRNAME_LENGTH);
 	base_name = basename(ra_name_dup);
 	/*
 	 * If ra_name only contains basename, then append RA_PATH.
 	 * If ra_name is a pathname, then don't deal with it.
 	 */
 	if ( strncmp(ra_name, base_name, RA_MAX_BASENAME_LENGTH) == 0 ) {
 		g_string_insert(ra_dirname, 0, RA_PATH);
 	}
 	free(ra_name_dup);
 
 	/* For heartbeat scripts, no definite specification for parameters
 	 * Not set calling parameters
 	 */
 	raexec_setenv(env_params);
 	if ( execv(ra_name, params_argv) < 0 ) {
 		cl_log(LOG_ERR, "execl error when to execute RA %s.", ra_name);
 	}
 
         switch (errno) {
                 case ENOENT:   /* No such file or directory */
                 case EISDIR:   /* Is a directory */
                         exit_value = EXECRA_NO_RA;
                         break;
 
                 default:
                         exit_value = EXECRA_EXEC_UNKNOWN_ERROR;
         }
 
         cl_log(LOG_ERR, "execl error when to execute RA %s.", ra_name);
         exit(exit_value);
 }
 
 static int 
 prepare_cmd_parameters(const char * raname, const char * op,
 	GHashTable * params_ht, RA_ARGV params_argv)
 {
 	/* For heartbeat scripts, no corresponding definite specification
 	 * Maybe not need this function? 	
 	 */ 
 	int tmp_len;
         int ht_size = 0;
 
 	if (params_ht) {
 		g_hash_table_size(params_ht);
 	}
         if ( ht_size+3 > MAX_PARAMETER_NUM ) {
                 cl_log(LOG_ERR, "Too many parameters");
                 return -1;
         }
                                                                                         
 	tmp_len = strnlen(raname, 160) + 1;
         params_argv[0] = g_new(char, tmp_len);
         strncpy(params_argv[0], raname, tmp_len);
 
 	tmp_len = strnlen(op, 160) + 1;
         params_argv[1] = g_new(char, tmp_len);
         strncpy(params_argv[1], op, tmp_len);
 
         params_argv[ht_size+2] = NULL;
                                                                                         
 	if (params_ht) {
         	g_hash_table_foreach(params_ht, params_hash_to_argv, 
 					&params_argv);
 	}
                                                                                         
         return 0;
 }
 
 static uniform_ret_execra_t 
 map_ra_retvalue(int ret_execra, const char * op)
 {
 	/* Now there is no related specification for Heartbeat standard.
 	 * Temporarily deal as below.
 	 */
 	return ret_execra;
 }
 
 static int 
 get_resource_list(GList ** rsc_info)
 {
 	struct dirent **namelist;
 	int file_num;
 
 	if ( rsc_info == NULL ) {
 		cl_log(LOG_ERR, "Parameter error: get_resource_list");
 		return -2;
 	}
 
 	if ( *rsc_info != NULL ) {
 		cl_log(LOG_ERR, "Parameter error: get_resource_list."\
 			"will cause memory leak.");
 		*rsc_info = NULL;
 	}
  
 	file_num = scandir(RA_PATH, &namelist, 0, alphasort);
 	if (file_num < 0) {
 		cl_log(LOG_ERR, "scandir failed in OCF RA plugin");
 		return -2;
 	} else 
 	{
 		while (file_num--) {
 			rsc_info_t * rsc_info_tmp = NULL;
 			if (*(namelist[file_num]->d_name) != '.') {
 				rsc_info_tmp = g_new(rsc_info_t, 1);	
 				rsc_info_tmp->rsc_type = 
 					g_strdup(namelist[file_num]->d_name);
 			/* 
 			 * Since the version definition isn't cleat yet,
 			 * the version is setted 1.0.
 			 */
 				rsc_info_tmp->version = g_strdup("1.0");
 				*rsc_info = g_list_append(*rsc_info, 
 						(gpointer)rsc_info_tmp);
 			}
 			free(namelist[file_num]);
 		}
 		free(namelist);
 	}
 	return g_list_length(*rsc_info);			
 }
 
 static void
 params_hash_to_argv(gpointer key, gpointer value, gpointer user_data)
 {
 	int param_index;
         RA_ARGV  * ra_argv = (RA_ARGV *) user_data;
 
         if (ra_argv == NULL ) {
                 return;
         }
 	
         /* the parameter index start from 1 */
         /* and start from 2 in argv array */
 	param_index = atoi( (char*) key );
 	(*ra_argv)[param_index + 1] = g_new(char, 21);
 	*((*ra_argv)[param_index + 1] + 20) = '\0';
         strncpy((*ra_argv)[param_index + 1], (char*)value,
                 strnlen((char*)value, 20));
 }
 
 static int 
 raexec_setenv(GHashTable * env_params)
 {
 	/* 
 	 * For heartbeat scripts, no definite specification for environment 
 	 * parameters. Maybe no need to this function? 	
 	 */ 
         if (env_params) {
         	g_hash_table_foreach(env_params, set_env, NULL);
         }
         /* Need to free the env_params ? */
         return 0;
 }
 
 static void
 set_env(gpointer key, gpointer value, gpointer user_data)
 {
         setenv((const char *)key, (const char *)value, 1);
         /*Need to free the memory to which key and value point?*/
 }
diff --git a/lib/plugins/lrm/raexeclsb.c b/lib/plugins/lrm/raexeclsb.c
index fa87e6797a..1d878ae769 100644
--- a/lib/plugins/lrm/raexeclsb.c
+++ b/lib/plugins/lrm/raexeclsb.c
@@ -1,324 +1,325 @@
 /* 
  * 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
  *
  * File: raexeclsb.c
  * Author: Sun Jiang Dong <sunjd@cn.ibm.com>
  * Copyright (c) 2004 International Business Machines
  *
  * This code implements the Resource Agent Plugin Module for LSB style.
  * It's a part of Local Resource Manager. Currently it's used by lrmd only.
  */
 
 #include <portability.h>
 #include <stdio.h>		
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
 #include <dirent.h>
 #include <glib.h>
 #include <clplumbing/cl_log.h>
 #include <pils/plugin.h>
 #include <lrm/raexec.h>
+#include <libgen.h>
 
 #define PIL_PLUGINTYPE		RA_EXEC_TYPE
 #define PIL_PLUGIN		lsb
 #define PIL_PLUGINTYPE_S	"RAExec"
 #define PIL_PLUGIN_S		"lsb"
 #define PIL_PLUGINLICENSE	LICENSE_PUBDOM
 #define PIL_PLUGINLICENSEURL	URL_PUBDOM
 
 /*
  * Are there multiple paths? Now according to LSB init scripts, the answer 
  * is 'no', but should be 'yes' for lsb none-init scripts?
  */
 static const char * RA_PATH = "/usr/lib/lsb/";
 static const int status_op_exitcode_map[] = { 0, 11, 12, 13, 14 };
 
 /* The begin of exported function list */
 static int execra(const char * ra_name,  
 		  const char * op,
 	 	  GHashTable * cmd_params,
 		  GHashTable * env_params);
 
 static uniform_ret_execra_t map_ra_retvalue(int ret_execra, const char * op);
 static int get_resource_list(GList ** rsc_info);
 /* The end of exported function list */
 
 /* The begin of internal used function & data list */
 #define MAX_PARAMETER_NUM 40 
 typedef char * RA_ARGV[MAX_PARAMETER_NUM];
 
 static int prepare_cmd_parameters(const char * raname, const char * op, 
 	GHashTable * params, RA_ARGV params_argv);  
 static void params_hash_to_argv(gpointer key, gpointer value, 
 				gpointer user_data);
 static int raexec_setenv(GHashTable * env_params);
 static void set_env(gpointer key, gpointer value, gpointer user_data);
 /* The end of internal function & data list */
 
 /* Rource agent execution plugin operations */
 static struct RAExecOps raops =
 {	execra,
 	map_ra_retvalue,
 	get_resource_list
 };
 
 /*
  * The following two functions are only exported to the plugin infrastructure.
  */
 
 /*
  * raexec_closepi is called as part of shutting down the plugin.
  * If there was any global data allocated, or file descriptors opened, etc.
  * which is associated with the plugin, and not a single interface
  * in particular, here's our chance to clean it up.
  */
 static void raexec_closepi(PILPlugin *pi)
 {
 }
 
 /*
  * raexec_close_intf called as part of shutting down the md5 HBauth interface.
  * If there was any global data allocated, or file descriptors opened, etc.
  * which is associated with the md5 implementation, here's our chance
  * to clean it up.
  */
 static PIL_rc raexec_closeintf(PILInterface *pi, void *pd)
 {
 	return PIL_OK;
 }
 
 PIL_PLUGIN_BOILERPLATE("1.0", Debug, raexec_closepi);
 
 static const PILPluginImports*  PluginImports;
 static PILPlugin*               OurPlugin;
 static PILInterface*		OurInterface;
 static void*			OurImports;
 static void*			interfprivate;
 
 /*
  * Our plugin initialization and registration function
  * It gets called when the plugin gets loaded.
  */
 PIL_rc
 PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports);
 
 PIL_rc
 PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports)
 {
 	/* Force the compiler to do a little type checking */
 	(void)(PILPluginInitFun)PIL_PLUGIN_INIT;
 
 	PluginImports = imports;
 	OurPlugin = us;
 
 	/* Register ourself as a plugin */
 	imports->register_plugin(us, &OurPIExports);  
 
 	/*  Register our interfaces */
  	return imports->register_interface(us, PIL_PLUGINTYPE_S,  PIL_PLUGIN_S,	
 		&raops, raexec_closeintf, &OurInterface, &OurImports,
 		interfprivate); 
 }
 
 /*
  *	Real work starts here ;-)
  */
 
 static int 
 execra( const char * ra_name, const char * op, 
 	GHashTable * cmd_params, GHashTable * env_params )
 {
 	uniform_ret_execra_t exit_value;
 	RA_ARGV params_argv;
 	char *ra_name_dup, *base_name;
 	GString * ra_dirname;
 
 	cl_log(LOG_DEBUG, "To execute a RA %s.", ra_name);
 	/* Prepare the call parameter */
 	if (0 > prepare_cmd_parameters(ra_name, op, cmd_params, params_argv)) {
 		cl_log(LOG_ERR, "lsb RA: Error of preparing parameters");
 		return -1;
 	}
 	
 	ra_dirname = g_string_new(ra_name);
 	ra_name_dup = strndup(ra_name, RA_MAX_DIRNAME_LENGTH);
 	base_name = basename(ra_name_dup);
 	/*
 	 * If ra_name only contains basename, then append RA_PATH.
 	 * If ra_name is a pathname, then don't deal with it.
 	 */
 	if ( strncmp(ra_name, base_name, RA_MAX_BASENAME_LENGTH) == 0 ) {
 		g_string_insert(ra_dirname, 0, RA_PATH);
 	}
 	free(ra_name_dup);
 	
 	raexec_setenv(env_params);
 	execv(ra_dirname->str, params_argv);
 
         switch (errno) {
                 case ENOENT:   /* No such file or directory */
                 case EISDIR:   /* Is a directory */
                         exit_value = EXECRA_NO_RA;
                         break;
 
                 default:
                         exit_value = EXECRA_EXEC_UNKNOWN_ERROR;
         }
 
         cl_log(LOG_ERR, "execl error when to execute RA %s.", ra_name);
         exit(exit_value);
 }
 
 static uniform_ret_execra_t 
 map_ra_retvalue(int ret_execra, const char * op)
 {
 	/* Except op equals 'status', the UNIFORM_RET_EXECRA is compatible 
 	   with LSB standard. 
 	*/
 	if ( strncmp(op, "status", 6) == 0 ) {
 		if (ret_execra < 0 || ret_execra > 4 ) {
 			ret_execra = 4;
 		}
 		return status_op_exitcode_map[ret_execra];	
 	} else
 	{
 		return ret_execra;
 	}
 }
 
 static int 
 get_resource_list(GList ** rsc_info)
 {
 	struct dirent **namelist;
 	int file_num;
 
 	if ( rsc_info == NULL ) {
 		cl_log(LOG_ERR, "Parameter error: get_resource_list");
 		return -2;
 	}
 
 	if ( *rsc_info != NULL ) {
 		cl_log(LOG_ERR, "Parameter error: get_resource_list."\
 			"will cause memory leak.");
 		*rsc_info = NULL;
 	}
  
 	file_num = scandir(RA_PATH, &namelist, 0, alphasort);
 	if (file_num < 0) {
 		cl_log(LOG_ERR, "scandir failed in OCF RA plugin");
 		return -2;
 	} else 
 	{
 		while (file_num--) {
 			rsc_info_t * rsc_info_tmp;
 			if (*(namelist[file_num]->d_name) != '.') {
 				rsc_info_tmp = g_new(rsc_info_t, 1);	
 				rsc_info_tmp->rsc_type = 
 					g_strdup(namelist[file_num]->d_name);
 			/* 
 			 * Since the version definition isn't cleat yet,
 			 * the version is setted 1.0.
 			 */
 				rsc_info_tmp->version = g_strdup("1.0");
 				*rsc_info = g_list_append(*rsc_info, 
 						(gpointer)rsc_info_tmp);
 			}
 			free(namelist[file_num]);
 		}
 		free(namelist);
 	}
 	return g_list_length(*rsc_info);			
 }
 
 static int 
 prepare_cmd_parameters(const char * raname, const char * op, 
 			GHashTable * params_ht, RA_ARGV params_argv)
 {
 	/* For lsb init scripts, no corresponding definite specification
 	 * But for lsb none-init scripts, maybe need it.
 	 */ 
 
 	int tmp_len;
 	int ht_size = 0;
 	if (params_ht) {
 		ht_size = g_hash_table_size(params_ht);
 	}
 
 	if ( ht_size+3 > MAX_PARAMETER_NUM ) {
 		cl_log(LOG_ERR, "Too many parameters");
 		return -1;
 	}
 	
 	tmp_len = strnlen(raname, 160) + 1;
 	params_argv[0] = g_new(gchar, tmp_len); 
 	strncpy(params_argv[0], raname, tmp_len);
 
 	tmp_len = strnlen(op, 160) + 1;
 	params_argv[1] = g_new(gchar, tmp_len); 
 	strncpy(params_argv[1], op, tmp_len);
 	params_argv[ht_size+2] = NULL; 
 	
 	if (params_ht) {
 		g_hash_table_foreach(params_ht, 
 				params_hash_to_argv, params_argv);
 	}
 
 	return 0;
 }
 
 static void
 params_hash_to_argv(gpointer key, gpointer value, gpointer user_data)
 {
         RA_ARGV * ra_argv  = user_data;
 	int param_index;
 
 	if (user_data == NULL) {
 		return;
 	}
         if (*ra_argv == NULL ) {
                 return;
         }
 
 	/* the parameter index start from 1 */
 	/* and start from 2 in argv array */
 	param_index = atoi((char *)key);
 	(*ra_argv)[param_index + 1] = g_new(gchar, 21);
 	*((*ra_argv)[param_index + 1] + 20) = '\0';
         strncpy((*ra_argv)[param_index +1], (char*)value,
                 strnlen((char*)value, 20));
 }
 
 static int 
 raexec_setenv(GHashTable * env_params)
 {
 	/* For lsb init scripts, no corresponding definite specification
 	 * But for lsb none-init scripts, maybe need it.
 	 */ 
         if (env_params) {
         	g_hash_table_foreach(env_params, set_env, NULL);
         }
         return 0;
 }
 
 static void
 set_env(gpointer key, gpointer value, gpointer user_data)
 {
         setenv((const char *)key, (const char *)value, 1);
         /*Need to free the memory to which key and value point?*/
 }
diff --git a/lib/plugins/lrm/raexecocf.c b/lib/plugins/lrm/raexecocf.c
index 9c6e998a55..67386be333 100644
--- a/lib/plugins/lrm/raexecocf.c
+++ b/lib/plugins/lrm/raexecocf.c
@@ -1,254 +1,255 @@
 /* 
  * 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
  *
  * File: raexecocf.c
  * Author: Sun Jiang Dong <sunjd@cn.ibm.com>
  * Copyright (c) 2004 International Business Machines
  *
  * This code implements the Resource Agent Plugin Module for LSB style.
  * It's a part of Local Resource Manager. Currently it's used by lrmd only.
  */
 
 #include <portability.h>
 #include <stdio.h>		
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <libgen.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
 #include <dirent.h>
 #include <glib.h>
 #include <clplumbing/cl_log.h>
 #include <pils/plugin.h>
 #include <lrm/raexec.h>
 
 #define PIL_PLUGINTYPE		RA_EXEC_TYPE
 #define PIL_PLUGIN		ocf
 #define PIL_PLUGINTYPE_S	"RAExec"
 #define PIL_PLUGIN_S		"ocf"
 #define PIL_PLUGINLICENSE	LICENSE_PUBDOM
 #define PIL_PLUGINLICENSEURL	URL_PUBDOM
 
 /* 
  * Are there multiple paths? Now according to OCF spec, the answer is 'no'.
  * But actually or for future?
  */
 static const char * RA_PATH = "/usr/ocf/resource.d/";
 
 /* The begin of exported function list */
 static int execra(const char * ra_name,  
 		  const char * op,
 	 	  GHashTable * cmd_params,
 		  GHashTable * env_params);
 
 static uniform_ret_execra_t map_ra_retvalue(int ret_execra, const char * op);
 
 static int get_resource_list(GList ** rsc_info);
 /* The end of exported function list */
  
 /* The begin of internal used function & data list */
 static int raexec_setenv(GHashTable * env_params);
 static void set_env(gpointer key, gpointer value, gpointer user_data);
 /* The end of internal function & data list */
 
 /* Rource agent execution plugin operations */
 static struct RAExecOps raops =
 {	execra,
 	map_ra_retvalue,
 	get_resource_list
 };
 
 /*
  * The following two functions are only exported to the plugin infrastructure.
  */
 
 /*
  * raexec_closepi is called as part of shutting down the plugin.
  * If there was any global data allocated, or file descriptors opened, etc.
  * which is associated with the plugin, and not a single interface
  * in particular, here's our chance to clean it up.
  */
 static void raexec_closepi(PILPlugin *pi)
 {
 }
 
 /*
  * raexec_close_intf called as part of shutting down the md5 HBauth interface.
  * If there was any global data allocated, or file descriptors opened, etc.
  * which is associated with the md5 implementation, here's our chance
  * to clean it up.
  */
 static PIL_rc raexec_closeintf(PILInterface *pi, void *pd)
 {
 	return PIL_OK;
 }
 
 PIL_PLUGIN_BOILERPLATE("1.0", Debug, raexec_closepi);
 
 static const PILPluginImports*  PluginImports;
 static PILPlugin*               OurPlugin;
 static PILInterface*		OurInterface;
 static void*			OurImports;
 static void*			interfprivate;
 
 /*
  * Our plugin initialization and registration function
  * It gets called when the plugin gets loaded.
  */
 PIL_rc
 PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports);
 
 PIL_rc
 PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports)
 {
 	/* Force the compiler to do a little type checking */
 	(void)(PILPluginInitFun)PIL_PLUGIN_INIT;
 
 	PluginImports = imports;
 	OurPlugin = us;
 
 	/* Register ourself as a plugin */
 	imports->register_plugin(us, &OurPIExports);  
 
 	/*  Register our interfaces */
  	return imports->register_interface(us, PIL_PLUGINTYPE_S,  PIL_PLUGIN_S,	
 		&raops, raexec_closeintf, &OurInterface, &OurImports,
 		interfprivate); 
 }
 
 /*
  *	Real work starts here ;-)
  */
 
 static int 
 execra( const char * ra_name, const char * op, 
 	GHashTable * cmd_params, GHashTable * env_params )
 {
 	char *ra_name_dup, *base_name;
 	GString * ra_dirname;
 	
 	uniform_ret_execra_t exit_value;
 
 	cl_log(LOG_DEBUG, "To execute a RA %s", ra_name);
 	/* Prepare the call parameter */
 	if (!cmd_params) {
 		if (g_hash_table_size(cmd_params) > 0) {
 			cl_log(LOG_ERR, "OCF RA should have no "\
 				"command-line parameters.");
 		}
 	}
 	
 	ra_dirname = g_string_new(ra_name);
 	ra_name_dup = strndup(ra_name, RA_MAX_DIRNAME_LENGTH);
 	base_name = basename(ra_name_dup);
 	/* 
 	 * If ra_name only contains basename, then append RA_PATH.
 	 * If ra_name is a pathname, then don't deal with it.
 	 */
 	if ( strncmp(ra_name, base_name, RA_MAX_BASENAME_LENGTH) == 0 ) {
 		g_string_insert(ra_dirname, 0, RA_PATH);		
 	} 
 	free(ra_name_dup);
 
 	/* execute the RA */
 	raexec_setenv(env_params);
 	cl_log(LOG_ERR, "ra_dirname is:%s", ra_dirname->str);
 	execl(ra_dirname->str, ra_dirname->str, op, NULL); 
 	
 	switch (errno) {
 		case ENOENT:   /* No such file or directory */
 		case EISDIR:   /* Is a directory */
 			exit_value = EXECRA_NO_RA;
 			break;
 
 		default:
 			exit_value = EXECRA_EXEC_UNKNOWN_ERROR;
 	}
 
 	cl_log(LOG_ERR, "execl error when to execute RA %s.", ra_name);
 	g_string_free(ra_dirname, TRUE);
 	exit(exit_value);
 }
 
 static uniform_ret_execra_t 
 map_ra_retvalue(int ret_execra, const char * op)
 {
 	/* Because the UNIFORM_RET_EXECRA is compatible with OCF standard */
 	return ret_execra;
 }
 
 static int 
 get_resource_list(GList ** rsc_info)
 {
 	struct dirent **namelist;
 	int file_num;
 
 	if ( rsc_info == NULL ) {
 		cl_log(LOG_ERR, "Parameter error: get_resource_list");
 		return -2;
 	}
 
 	if ( *rsc_info != NULL ) {
 		cl_log(LOG_ERR, "Parameter error: get_resource_list."\
 			"will cause memory leak.");
 		*rsc_info = NULL;
 	}
  
 	file_num = scandir(RA_PATH, &namelist, 0, alphasort);
 	if (file_num < 0) {
 		cl_log(LOG_ERR, "scandir failed in OCF RA plugin");
 		return -2;
 	} else 
 	{
 		while (file_num--) {
 			rsc_info_t * rsc_info_tmp;
 			if (*(namelist[file_num]->d_name) != '.') {
 				rsc_info_tmp = g_new(rsc_info_t, 1);	
 				rsc_info_tmp->rsc_type = 
 					g_strdup(namelist[file_num]->d_name);
 			/* 
 			 * Since the version definition isn't cleat yet,
 			 * the version is setted 1.0.
 			 */
 				rsc_info_tmp->version = g_strdup("1.0");
 				*rsc_info = g_list_append(*rsc_info, 
 						(gpointer)rsc_info_tmp);
 			}
 			free(namelist[file_num]);
 		}
 		free(namelist);
 	}
 	return g_list_length(*rsc_info);			
 }
 
 static int 
 raexec_setenv(GHashTable * env_params)
 {
 	if (!env_params) {
 		return -1;
 	}
 
 	g_hash_table_foreach(env_params, set_env, NULL);
 	/* Need to free the env_params ? */
 	return 0;
 }
 
 static void 
 set_env(gpointer key, gpointer value, gpointer user_data)
 {
 	setenv((const char *)key, (const char *)value, 1);	
 	/*Need to free the memory to which key and value point?*/
 }