/*******************************************************************************
 * Copyright (c) 2005, 2009 Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *	  Guru Nagarajan, Intel - - Initial API and Implementation
 * $Id: TPTPUtil.cpp,v 1.49 2009/08/26 14:59:54 jwest Exp $
 *******************************************************************************/ 

#include <xercesc/util/PlatformUtils.hpp>

#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMWriter.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/framework/XMLFormatter.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/util/TransService.hpp>


#include <stdlib.h>
#include <stdio.h>
#ifdef MVS
    #include <pwd.h>
#endif

#include "tptp/TPTPUtils.h"
#include "tptp/TPTPConfig.h"

#ifdef _WIN32
	#include <sys/types.h>
	#include <sys/stat.h>
	#define TPTP_STAT _stat
	#define mode_t unsigned short
	#define S_ISDIR(mode) (((mode)&_S_IFMT) == _S_IFDIR)
	#define S_IWUSR _S_IWRITE
	#define S_IXUSR _S_IEXEC
#else
	#include <string.h>
	#include <unistd.h>
	#include <errno.h>
	#include <sys/stat.h>
	#include <sys/types.h>
	#if defined(__linux__)
		#include <linux/stat.h>  //for mode S_IXUSR
	#endif
	#define TPTP_STAT stat
  	#include <signal.h>
  	#include <sys/wait.h>
	#include <ctype.h>
#endif


//DOMImplementationRegistry::getDOMImplementation(chNull) -- TODO Fix the chNull for UTF

XERCES_CPP_NAMESPACE_USE

#include "tptp/ParserErrorHandler.h"

//Defines for processing the XML
#define XML_FRAG_ALL_TAGS	"*"
#define XML_FRAG_BEGIN_TAG	"Cmd"
#define XML_ATTR_DEST		"dest"
#define XML_ATTR_SRC		"src"
#define XML_ATTR_CTX		"ctxt"
#define XML_ATTR_IID		"iid"
#ifdef MVS
	#define DOM_CHAR_SET    "IBM-1047"
#else
	#define DOM_CHAR_SET	"UTF-8"
#endif

//Defines for building the XML
#define TAG_HDR				"<"
#define TAG_FTR				"</"
#define TAG_CLS				">"
#define ATTR_EQ				"="
#define ATTR_QT				"\""
#define WH_SPS				" "

#define TRANSCODER_BLOCK_SIZE (4*4096)
static XMLTranscoder* gTranscoder = NULL;
char * customTranscode(const XMLCh *xmlString) {
	// transcode the string into utf-8
	XMLTransService::Codes resCode;
	unsigned int charsEaten;
	char stackBuffer[TRANSCODER_BLOCK_SIZE];
	char *transcodeBuffer = stackBuffer;
	int transcodeBufferSize = TRANSCODER_BLOCK_SIZE;
	char *dynamicBuffer = NULL;
	char *resultString;

	if (gTranscoder == NULL) {
		gTranscoder = XMLPlatformUtils::fgTransService->
			makeNewTranscoderFor(DOM_CHAR_SET, resCode,
				TRANSCODER_BLOCK_SIZE, XMLPlatformUtils::fgMemoryManager);
		//TODO: should be deleted at the end
		if (resCode != XMLTransService::Ok) {
			//TODO: diagnostic message 
			return (NULL);
		}
	}

	int strLen = XMLString::stringLen(xmlString);
	int requiredBufferSize = (strLen + 1) * 2; // for worst case should be 4

	// if buffer too small
	if (requiredBufferSize > TRANSCODER_BLOCK_SIZE) {
		dynamicBuffer = (char*)tptp_malloc(requiredBufferSize);
		if (dynamicBuffer == NULL) {
			//TODO: diagnostic message
			return (NULL);
		}
		transcodeBuffer = dynamicBuffer;
		transcodeBufferSize = requiredBufferSize;
	}

	int numChars = gTranscoder->transcodeTo(xmlString,
		strLen,
		(XMLByte*) transcodeBuffer,
		transcodeBufferSize,
		charsEaten,
		XMLTranscoder::UnRep_Throw);

	transcodeBuffer[numChars] = '\0';
	resultString = XMLString::replicate(transcodeBuffer);

	if (dynamicBuffer) {
		tptp_free(dynamicBuffer);
	}

	return resultString;
}

int writeNodeToBuffer( DOMNode* node, char* buffer, unsigned int bufferLen )
{
	DOMImplementation   *impl = DOMImplementationRegistry::getDOMImplementation(&chNull);
	DOMWriter           *writer = ((DOMImplementationLS*)impl)->createDOMWriter();
    MemBufFormatTarget  *target = new MemBufFormatTarget;

    // Set the encoding to EBCDIC from UTF for z-series machines
	#ifdef MVS
		writer->setEncoding(XMLUni::fgIBM1047EncodingString);
	#endif

	writer->writeNode( target, *node );

	strncpy( buffer, (char *)target->getRawBuffer(), bufferLen );

	if ( target->getLen() > bufferLen )
	{
		buffer[bufferLen] = 0;
		return -1;
	}

	writer->release();

	delete target;

	return 0;
}

/************************************************************************/
int parseCommand( const char*       cmd,
                  int*              sourceID,
                  int*              context,
                  char**            interfaceID,
                  char**            cmdName,
                  tptp_list_t**		paramList )
{
	try {
		//Initialize the XML parser
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		//Initialize paramList for key value pairs
		*paramList = (tptp_list_t*)tptp_malloc( sizeof(tptp_list_t));
		tptp_list_init(*paramList);
		tptp_list_setNodeDestructor(*paramList, destroyParamNode);
		tptp_list_setNodeCopier(*paramList, copyParamNode);
		
		//Build a MemBuf Input source 
		MemBufInputSource *is = new MemBufInputSource((const XMLByte*)cmd,strlen(cmd),"parseCommand()",false);

		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		//Wrap the MemBufInputSource
		Wrapper4InputSource* domBufIS = new Wrapper4InputSource(is);

		//Get the DOM document by passing the input string to the parser
		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);
		
		//Get all the tags into the LnList
		XMLCh	*cmdTag = XMLString::transcode(XML_FRAG_BEGIN_TAG);
		DOMNodeList *nodelist = doc->getElementsByTagName(cmdTag);
		XMLString::release(&cmdTag);

		int nodelength = nodelist->getLength();
		
		if(nodelength == 0) { return -1;}

		
		for(int i = 0; i < nodelength; i++)
		{   
				DOMNode* cmdNode = nodelist->item(i)->getChildNodes()->item(0);
				// Look out for whitespace before the command node
				if ( cmdNode->getNodeType() == DOMNode::TEXT_NODE )
					cmdNode = nodelist->item(i)->getChildNodes()->item(1);


				char *attrTempName = customTranscode(cmdNode->getNodeName());
				*cmdName = (char *)tptp_malloc(strlen(attrTempName)+1);
				strcpy(*cmdName, attrTempName);
				XMLString::release(&attrTempName);

				/* Get the interface ID from the command sub-element */
				DOMNamedNodeMap *cmdattrs = cmdNode->getAttributes();
				int cmdattrlen = cmdattrs->getLength();
				for(int j=0;j<cmdattrlen;j++) 
				{
					DOMAttr *attributeNode = (DOMAttr*) cmdattrs->item(j);
					char *attrname = customTranscode(attributeNode->getName());
						
					if(strcmp(attrname,	XML_ATTR_IID) == 0)	{

						char *tempValue = customTranscode(attributeNode->getValue());
						*interfaceID = (char *)tptp_malloc(strlen(tempValue)+1);
						strcpy(*interfaceID, tempValue);
						XMLString::release(&tempValue);

						XMLString::release(&attrname);
						break;
					}

					XMLString::release(&attrname);
				
				} //for(all attributes)

				/* Get the Cmd attributes -- we expect src, dest and ctxt */
				DOMNamedNodeMap *attributes = nodelist->item(i)->getAttributes();
				int attrlen = attributes->getLength();
				for(int k=0;k<attrlen;k++) 
				{
					DOMAttr *attributeNode = (DOMAttr*) attributes->item(k);
					char *attrname = customTranscode(attributeNode->getName());
					char *attrvalue = customTranscode(attributeNode->getValue());
						
					if(strcmp(attrname, XML_ATTR_SRC) == 0){*sourceID = atoi(attrvalue);}
					if(strcmp(attrname,	XML_ATTR_CTX) == 0){*context = atoi(attrvalue);}
				
					XMLString::release(&attrvalue);
					XMLString::release(&attrname);
				
				} //for(all attributes)

				/* Get the parameters */
				DOMNodeList *childnodelist = cmdNode->getChildNodes();
				int childnodelength = childnodelist->getLength();
				for(int nl = 0; nl < childnodelength; nl++)
				{
					DOMNode* childnode = childnodelist->item(nl);
					if(childnode->getNodeType() == DOMNode::ELEMENT_NODE) 
					{
						tptp_param_t* newParam;
						char *tempparmname = customTranscode(childnode->getNodeName());
						
						DOMNode* paramnode = childnode->getFirstChild();
						DOMNodeList *paramchildren = childnode->getChildNodes();
						int numParamChildren = paramchildren->getLength();
						/* If we have multiple children, one or more of them may be whitespace */
						/* The others should be an XML element */
						if ( numParamChildren > 1 )
						{
							int np;
							char *parambuffer = NULL;
							int   buffersize = 0;
							char *tempparmval = (char*)tptp_malloc( strlen(cmd) + 1 ); // The biggest it could be

							if ( tempparmval != NULL )
							{
								for ( np = 0; np < numParamChildren; np++ )
								{
									if ( paramchildren->item(np)->getNodeType() == DOMNode::ELEMENT_NODE )
									{
										char *temp = parambuffer;

										/* write the node to our temporary buffer */
										writeNodeToBuffer( paramchildren->item(np), tempparmval, strlen(cmd) );

										parambuffer = (char*)tptp_realloc( temp, buffersize + strlen(tempparmval) + 1 );
										if ( parambuffer == NULL )
										{
											parambuffer = temp;
										}
										else
										{
											/* If this is the first allocation, put a NULL in the buffer */
											if ( buffersize == 0 )
											{
												parambuffer[0] = (char)'\0';
											}
											strcat( parambuffer, tempparmval );
											buffersize += strlen(tempparmval); // Don't add for the NULL because it gets added in the allocation
										}
									}
								}

								tptp_free(tempparmval);
							}

							if ( parambuffer != NULL )
							{
								newParam = initParamT(tempparmname, parambuffer);
								tptp_list_add(*paramList, (void*)newParam);
								tptp_free( parambuffer );
							}
						}
						else
						{
							if ( paramnode == NULL )
							{
								// TODO: ?
							}
							else if ( paramnode->getNodeType() == DOMNode::TEXT_NODE )
							{
		//TODO:FIX:The value for a parameter cannot have a line feed in it, don't know about a space
								char *tempparmval = customTranscode(paramnode->getNodeValue());
								newParam = initParamT(tempparmname, tempparmval);
								tptp_list_add(*paramList, (void*)newParam);
								XMLString::release( &tempparmval ); 
							}
							else if ( paramnode->getNodeType() == DOMNode::ELEMENT_NODE )
							{
								//TODO: Eliminate hardcoded maximum for an element in the XML
								//Need to findout/use the real length.
								//initParamT() does a strlen to calculate the length it allocates.
								//so we'd better have a null terminated string.
								//
								//this cannot be hardcoded to 8192
								//this code assumes the worst... it allocates the biggest
								//possible buffer it might need... that of a whole cmd.
								//
								char *tempparmval = (char*)tptp_malloc( strlen(cmd) + 1 ); // The biggest it could be
								writeNodeToBuffer( paramnode, tempparmval, strlen(cmd) );
								newParam = initParamT(tempparmname, tempparmval);
								tptp_list_add(*paramList, (void*)newParam);
								tptp_free(tempparmval);
							}
						}

						XMLString::release( &tempparmname );
					
					} // ELEMENT node
				} //for(all childnodelist.items())
		}// For the nodes in the nodelist 

		delete domBufIS;
		delete tptp_dom_err;
		parser->release();

		return 0;
	} //end try

	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing command string \"%s\"", (cmd?cmd:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing command string \"%s\"", (cmd?cmd:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing command string \"%s\"", (cmd?cmd:"null"));
		return -1;
	}
}

/**********GetDestinationID**********************************************/

int getDestinationID(const char* cmd, int *dest)
{
	try {
		//Build a MemBuf Input source 
		MemBufInputSource	*is = new MemBufInputSource((const XMLByte*)cmd, strlen(cmd), "getDestinationID()", false);

		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		//Wrap the MemBufInputSource
		Wrapper4InputSource	*domBufIS = new Wrapper4InputSource(is);

		//Initialize the XML parser
		DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser = ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		//Get the DOM document by passing the input string to the parser
		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);
		
		//Get all the tags into the LnList - just get the node "Cmd", its children and attributes
		XMLCh	*cmdTag = XMLString::transcode(XML_FRAG_BEGIN_TAG);
		DOMNodeList *nodelist = doc->getElementsByTagName(cmdTag);
		XMLString::release(&cmdTag);
	
		int nodelength = nodelist->getLength();	
		if(nodelength == 0) return -1;
		
		/* Get the attribute related information */			
		/* The attributes are stored in the NodeMap  HashMap of the attribute name - value */
		DOMNamedNodeMap *attributes = nodelist->item(0)->getAttributes();
		int attrlen = attributes->getLength();
		XMLCh* destAttr = XMLString::transcode(XML_ATTR_DEST);

		for(int k=0;k<attrlen;k++) 
		{
			DOMAttr *attributeNode = (DOMAttr*) attributes->item(k);
			if (XMLString::compareString(destAttr, attributeNode->getName()) == 0) {
				char *attrvalue = customTranscode(attributeNode->getValue());
				*dest = atoi(attrvalue);
				XMLString::release(&attrvalue);
				break;
			}
		} //Attribute loop
			
		XMLString::release(&destAttr);

		delete domBufIS;
		delete tptp_dom_err;
		parser->release();

		return 0;
	} //end try
	
	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG2("XML/DOM Exception occurred while parsing \"%s\" attribute in command string \"%s\"", XML_ATTR_DEST, (cmd?cmd:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG2("XML Exception occurred while parsing \"%s\" attribute in command string \"%s\"", XML_ATTR_DEST, (cmd?cmd:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG2("Unexpected exception occurred while parsing \"%s\" attribute in command string \"%s\"", XML_ATTR_DEST, (cmd?cmd:"null"));
		return -1;
	}
}


/*************************GetStringParm********************************/
int getStringParam( const char*          paramName,
                    const tptp_list_t*	 paramList,
                    char**               value )
{
	// Loop through the list of parameters, match the name and return its value
	// as a string.
	// We allocate the space for the string and the caller is expected to
	// free that space.
	tptp_node_t*  node;
	tptp_param_t* tmpParam;
	for (node = paramList->head; node != 0; node = node->next)
	{
		tmpParam = (tptp_param_t*)node->data;
		if ( !tmpParam ) continue;  //empty data field, skip this node
		if ( isEqualString(tmpParam->name, paramName) )
		{
			*value = (char *)tptp_malloc( strlen(tmpParam->value)+1 );
			strcpy( *value, tmpParam->value );
			return 0;
		}
	}

	return -1;
}

/*************************GetStringParm********************************/
int getXmlFragmentParam( const char*         paramName,
                         const tptp_list_t*  paramList,
                         char**              value )
{
	char* temp;
	int   ret;

	if ( value == NULL )
	{
		return TPTP_UNEXPECTED_NULL_ARG;
	}

	ret = getStringParam( paramName, paramList, &temp );
	if ( ret != 0 )
	{
		return ret;
	}

	// Allocate space for the XML fragment we're going to return
	// value string + element name before and after + 5 decorator chars + NULL
	*value = (char*)tptp_malloc( strlen(temp) + (2 * strlen(paramName)) + 5 + 1 );
	if ( *value == NULL )
	{
		tptp_free( temp );
		return TPTP_SYS_NO_MEM;
	}

	sprintf( *value, "<%s>%s</%s>", paramName, temp, paramName );

	tptp_free( temp );

	return 0;
}

/*************************GetStringListParm********************************/
int getStringListParam( const char*         paramName,
                        const tptp_list_t* 	paramList,
                        tptp_list_t*        strList )
{
	// Loop through the list of parameters, find the name and return its value
	// as a list of strings.
	tptp_node_t*  node;
	tptp_param_t* tmpParam;

	tptp_list_init(strList);

	for (node = paramList->head; node != 0; node = node->next)
	{
		tmpParam = (tptp_param_t*)node->data;
		if ( !tmpParam ) continue;  //empty data field, skip this node
		if ( isEqualString(tmpParam->name, paramName) )
		{
			// This function assumes looks for multiple parameters with the same
			//    name.  Each parameter value will be placed in the list
			char* newStr = (char *)tptp_malloc( strlen(tmpParam->value) + 1 );
			strcpy(newStr, tmpParam->value);
			tptp_list_add(strList, (void*) newStr);

			// Because we expect that there may be more matches, we don't return here
		}
	}

	// If we found no matches, indicate that with a negative return code
	if (strList->count == 0 )
	{
		return -1;
	}

	return 0;
}

/*************************GetIntegerParm********************************/
int getIntegerParam( const char*           paramName,
                     const tptp_list_t*    paramList,
                     int*                  value )
{
	// Loop through the list of parameters, match the name and return its value
	// as an integer.
	tptp_node_t*  node;
	tptp_param_t* tmpParam;
	for (node = paramList->head; node != 0; node = node->next)
	{
		tmpParam = (tptp_param_t*)node->data;
		if ( !tmpParam ) continue;  //empty data field, skip this node
		if ( isEqualString(tmpParam->name, paramName) )
		{
			*value = atoi(tmpParam->value);
			return 0;
		}
	}

	return -1;
}

//////////////////////////////////
// getPIDParm(parmName, parmList, value)
//
// parmName - name of parameter to get the value of
// parmList - parameter list to look in
// value - returns value of parmName as PID (system process ID)
// return value - 0 if success, otherwise -1
//
//////////////////////////////////
int getPIDParam( const char*        paramName,
                 const tptp_list_t* paramList,
                 PID*               value )
{
	// Loop through the list of parameters, match the name and return its value
	// as an integer.
	tptp_node_t*  node;
	tptp_param_t* tmpParam;
	for (node = paramList->head; node != 0; node = node->next)
	{
		tmpParam = (tptp_param_t*)node->data;
		if ( !tmpParam ) continue;  //empty data field, skip this node
		if ( isEqualString(tmpParam->name, paramName) )
		{
			*value = (PID)atol(tmpParam->value);
			return 0;
		}
	}

	return -1;
}

int parsePropertyListEntry( char* property, char** name, char** type, char** value )
{
	try {
		//Initialize the XML parser
		DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser = ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		//Build a MemBuf Input source 
		MemBufInputSource *is = new MemBufInputSource(reinterpret_cast<XMLByte const*>(property),
													  strlen(property),"parsePropertyListEntry()",false );
		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		//Wrap the MemBufInputSource
		Wrapper4InputSource* domBufIS = NULL; 
		domBufIS = new Wrapper4InputSource(is);

		*name = NULL;
		*type = NULL;
		*value = NULL;

		//Get the DOM document by passing the input string to the parser
		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);
		
		// Get all the tags into the LnList - just get the node "property" and its children
		XMLCh* propTag = XMLString::transcode("property");
		DOMNodeList *nodelist = doc->getElementsByTagName(propTag);
		XMLString::release(&propTag);
		
		int nodelength = nodelist->getLength();	
		if(nodelength == 0) { return -1;} /* No property tag and hence no more parsing */
		
		for(int i = 0; i < nodelength; i++)
		{   
				/* Get the parameters */
				DOMNodeList *childnodelist = nodelist->item(i)->getChildNodes();
				int childnodelength = childnodelist->getLength();
				for(int nl = 0; nl < childnodelength; nl++)
				{
					DOMNode* childnode = childnodelist->item(nl);
					if(childnode->getNodeType() == DOMNode::ELEMENT_NODE) 
					{
						char *tempparmname = customTranscode(childnode->getNodeName());
						
						DOMNode* paramnode = childnode->getFirstChild();
						DOMNodeList *paramchildren = childnode->getChildNodes();
						int numParamChildren = paramchildren->getLength();
						/* If we have multiple children, one of them is whitespace */
						/* The other one should be an XML element */
						if ( numParamChildren > 1 )
						{
							int np;
							for ( np = 0; np < numParamChildren; np++ )
							{
								if ( paramchildren->item(np)->getNodeType() == DOMNode::ELEMENT_NODE )
								{
									paramnode = paramchildren->item(np);
									break;
								}
							}
						}
						if ( (paramnode != NULL) &&
							 (paramnode->getNodeType() == DOMNode::TEXT_NODE) )
						{
							char *tempparmval = customTranscode(paramnode->getNodeValue());

							if ( isEqualString( tempparmname, "name" ) )
							{
								*name = (char*)tptp_malloc( strlen(tempparmval)+1 );
								if ( *name != NULL )
								{
									strcpy( *name, tempparmval );
								}
							}
							else if ( isEqualString( tempparmname, "type" ) )
							{
								*type = (char*)tptp_malloc( strlen(tempparmval)+1 );
								if ( *type != NULL )
								{
									strcpy( *type, tempparmval );
								}
							}
							else if ( isEqualString( tempparmname, "value" ) )
							{
								*value = (char*)tptp_malloc( strlen(tempparmval)+1 );
								if ( *value != NULL )
								{
									strcpy( *value, tempparmval );
								}
							}

							XMLString::release( &tempparmval ); 
						}

						XMLString::release( &tempparmname );
					}
				} //for(all childnodelist.items())
		}// For the nodes in the nodelist 

		delete domBufIS;
		delete tptp_dom_err;
		parser->release();

		if ( (*name != NULL) && (*type != NULL) && (*value != NULL) )
		{
			return 0;
		}
		else
		{
			/* Don't return any partial results */
			if ( *name != NULL )
			{
				tptp_free( *name );
				*name = NULL;
			}
			if ( *type != NULL )
			{
				tptp_free( *type );
				*type = NULL;
			}
			if ( *value != NULL )
			{
				tptp_free( *value );
				*value = NULL;
			}

			return -1;
		}
	} //end try
	
	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing property list entry string \"%s\"", (property?property:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing property list entry string \"%s\"", (property?property:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing property list entry string \"%s\"", (property?property:"null"));
		return -1;
	}
}

/******************Util Functions for building XML String**************/
int closeTag(const char *tagName, char **closedTag)
{
	*closedTag = 0;
	*closedTag = (char *)tptp_malloc(strlen(TAG_FTR)+strlen(tagName)+strlen(TAG_CLS)+1);
	sprintf(*closedTag,"%s%s%s",TAG_FTR,tagName,TAG_CLS);
	return 0;
}
int openAttribTag(const char *tagName, char **openTag)
{
	*openTag = 0;
	*openTag = (char *)tptp_malloc(strlen(TAG_HDR)+strlen(tagName)+1);
	sprintf(*openTag,"%s%s",TAG_HDR,tagName);
	return 0;
}

int openTag(const char *tagName, char **openTag)
{
	*openTag = 0;
	*openTag = (char *)tptp_malloc(strlen(TAG_HDR)+strlen(tagName)+strlen(TAG_CLS)+1);
	sprintf(*openTag,"%s%s%s",TAG_HDR,tagName,TAG_CLS);
	return 0;
}
int fmtAttrib(const char *attribName, const char *attribValue, char **attribStr)
{
	*attribStr = 0;
	*attribStr = (char *)tptp_malloc(strlen(WH_SPS)+strlen(attribName)+strlen(ATTR_EQ)+strlen(ATTR_QT)+strlen(attribValue)+strlen(ATTR_QT)+strlen(WH_SPS)+1);
	sprintf(*attribStr,"%s%s%s%s%s%s%s" ,WH_SPS,attribName,ATTR_EQ,ATTR_QT,attribValue,ATTR_QT,WH_SPS);
	return 0;
}
	
int isEqualString( const char* str1, const char* str2 )
{
	/* Even if both strings pointers are NULL, that isn't what we're looking for */
	if ( (str1 == NULL) || (str2 == NULL) )
		return 0;
		
	return ( strcmp(str1, str2) == 0 ? 1 : 0 );
}

#ifdef _WIN32
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}
#endif


//////////////////////////////////
// getTagName(cmdStr, tagName)
//
// cmdStr - string to search
// tagName - returns the name string, must be freed by caller
// return value - integer offset into cmdStr, points to end of tagName or -1 if error
//
// Find opening "<" tag bracket and return the name associated with it.
//////////////////////////////////
int getTagName( const char* cmdStr, char** tagName)
{
	int i=0;
	int startIdx=0;
	int endIdx=0;
	int length=0;

	//Find start of tag name; ignoring anything prior to opening tag bracket
	while ((cmdStr[i] != '\0') && (cmdStr[i] != '<'))
		i++;
	if (cmdStr[i] == '\0') return -1; //Error: invalid command
	i++; //Move past the '<'

	//Skip whitespace
	while ((cmdStr[i] != '\0') &&
		   ((cmdStr[i] == ' ') ||
		    (cmdStr[i] == '\t') ||
		    (cmdStr[i] == '\n')))
		   i++;
	if (cmdStr[i] == '\0') return -1; //Error: invalid command

	startIdx = i;
	//Find end of tag name
	while ((cmdStr[i] != '\0') &&
		   (cmdStr[i] != ' ') &&
		   (cmdStr[i] != '\t') &&
		   (cmdStr[i] != '\n') &&
		   (cmdStr[i] != '>') )
		   i++;

	if (i <= startIdx ) return -1; //Error: invalid command
	endIdx = i;

	// Make a copy of name to pass back, caller must free this space.
	length = endIdx - startIdx;
	*tagName=(char*)tptp_malloc(length+1);
	if (*tagName == NULL) return -1; //Internal error: out of memory
	strncpy(*tagName, &(cmdStr[startIdx]),length);
	(*tagName)[length] = 0; //Null terminate the string
	
	return endIdx;
}



int getFileSize(char * fileName) 
{
	struct TPTP_STAT statBuf;

	if (TPTP_STAT(fileName, &statBuf) != 0) {
		return -1;
	}
	return statBuf.st_size;
}

int validateDirectory(char* dirName) {
	struct TPTP_STAT statBuf;

	if (TPTP_STAT(dirName, &statBuf) != 0) {
		return 0;
	}

	return (S_ISDIR(statBuf.st_mode)) ? 1 : 0;
}

int isAbsolutePath(const char* path) {
	int n;
	
	if (path == NULL) return 0;
	
	n = strlen(path);
	if (n == 0) return 0;
	
#ifdef _WIN32
	if(n >= 3 && isalpha(*path) && *(path+1)==':' && *(path+2)=='\\') return 1;
	return (*path == '\\') ? 1 : 0;
#else
	return (*path == '/') ? 1 : 0;
#endif	
}

char* getTempDir() {
	char* dir;
	
	dir = getenv("TEMP");
	if(dir != NULL) return dir;
	
#ifdef _WIN32
	return "C:\\tmp";
#else
	return "/tmp";
#endif
}

int getConfigElementName( const char* cmdStr, char** elemName)
{
	int i=0;
	int startIdx=0;
	int endIdx=0;
	int length=0;

	//Skip whitespace
	while ((cmdStr[i] != '\0') &&
		   ((cmdStr[i] == ' ') ||
		    (cmdStr[i] == '\t') ||
		    (cmdStr[i] == '\n')))
		   i++;
	if (cmdStr[i] == '\0') return -1; //Error: invalid command
	
	startIdx = i;
	//Find end of element name
	while ((cmdStr[i] != '\0') &&
		   (cmdStr[i] != ' ') &&
		   (cmdStr[i] != '\t') &&
		   (cmdStr[i] != '\n') &&
		   (cmdStr[i] != '=') &&
		   (cmdStr[i] != '>'))
		   i++;

	if (i <= startIdx ) return -1; //Error: invalid command
	endIdx = i;

	startIdx++; 
	// Make a copy of name to pass back, caller must free this space.
	length = endIdx - startIdx;
	*elemName=(char*)tptp_malloc(length+1);
	if (*elemName == NULL) return -1; //Internal error: out of memory
	strncpy(*elemName, &(cmdStr[startIdx]),length);
	(*elemName)[length] = 0; //Null terminate the string
	
	return endIdx;
}
int skipConfigElementClose( const char* cmdStr )
{
	int i=0;

	//Skip whitespace
	while ((cmdStr[i] != '\0') &&
		   ((cmdStr[i] == ' ') ||
		    (cmdStr[i] == '\t') ||
		    (cmdStr[i] == '\n')))
		   i++;
	if (cmdStr[i] == '\0') return -1; //Error: invalid command
	
	//Find end of element name
	while ((cmdStr[i] != '\0') && (cmdStr[i] != '>'))
	   i++;

	//Skip the close tag
	i++;
	
	return i;
}
int getConfigElementValue( const char* cmdStr, char** elemValue)
{
	int i=0;
	int startIdx=0;
	int endIdx=0;
	int length=0;
	char delim = '\0'; // TODO: Figure out what this is meant to be.  It was unitialized before.

	//Skip whitespace
	while ((cmdStr[i] != '\0') &&
		   ((cmdStr[i] == ' ') ||
		    (cmdStr[i] == '\t') ||
		    (cmdStr[i] == '\n')))
		   i++;
	if (cmdStr[i] == '\0') return -1; //Error: invalid command

	i++; //Move past the '=' or the ">" need to have an error check 

	//Skip whitespace
	while ((cmdStr[i] != '\0') &&
		   ((cmdStr[i] == ' ') ||
		    (cmdStr[i] == '\t') ||
		    (cmdStr[i] == '\n')))
		   i++;
	if (cmdStr[i] == '\0') return -1; //Error: invalid command

	startIdx = i;
	//Find end of element value
	while ((cmdStr[i] != '\0') &&
		   (cmdStr[i] != delim) && cmdStr[i] != '<')
		   i++;

	if (i <= startIdx ) return -1; //Error: invalid command
	endIdx = i;

	// Make a copy of value to pass back, caller must free this space.
	length = endIdx - startIdx;
	*elemValue=(char*)tptp_malloc(length+1);
	if (*elemValue == NULL) return -1; //Internal error: out of memory
	strncpy(*elemValue, &(cmdStr[startIdx]),length);
	(*elemValue)[length] = 0; //Null terminate the string
	
	return ++endIdx; //Move past the closing delim for the value
}

int getSocketConfigInfo(const char* config, SocketConfigInfo *socketInfo) {
	tptp_param_t* param;
	tptp_node_t*  node;

	socketInfo->securityEnabled = 0;	// default
	socketInfo->sslProviderLib = NULL;
	socketInfo->params = NULL;
	
	if (getXMLElements(config, &socketInfo->params) < 0) return -1;

	for (node = socketInfo->params->head; node != 0; node = node->next) {
		param = (tptp_param_t*) node->data;
		if (param == NULL) continue;

		if (isEqualString(param->name, "Port")) {
			socketInfo->portNumber = atoi(param->value);
		} 
		else if (isEqualString(param->name, "SecurityEnabled")) {
			socketInfo->securityEnabled = isEqualString(param->value, "true");
		} 
		else if (isEqualString(param->name, "Hosts Configuration")) {
			socketInfo->hostConfig = param->value;
		} 
		else if (isEqualString(param->name, "Allow host")) {
			socketInfo->allowHosts = param->value;
		} 
		else if (isEqualString(param->name, "SSLproviderLib")) {
			socketInfo->sslProviderLib = param->value;
		} 
	}

	return 0;
}

int getNamedPipeConfigInfo( const char* config, char **pipeName )
{
	char* tagName=NULL;
	char* elementName=NULL;
	char* elementValue=NULL;
	int mstrIdx=0;
	int nextIdx=0;

	nextIdx = getTagName(config, &tagName);
	if ((nextIdx == -1) || (tagName == NULL)) goto errorReturn; //Error: badly formed cmd


	if (!isEqualString(tagName, "Configuration") ) goto errorReturn; //Error: Don't have a "Cmd"
	mstrIdx += nextIdx;
	mstrIdx++;
	tptp_free(tagName); tagName=NULL;

	while (1)
	{
		nextIdx = getConfigElementName(&(config[mstrIdx]), &elementName);
		if ((nextIdx == -1) || (elementName == NULL)) goto errorReturn; //Error: badly formed cmd
		mstrIdx += nextIdx;

		nextIdx = getConfigElementValue(&(config[mstrIdx]), &elementValue);
		if ((nextIdx == -1) || (elementValue == NULL)) goto errorReturn; //Error: badly formed cmd
		mstrIdx += nextIdx;

		nextIdx = skipConfigElementClose(&(config[mstrIdx]));
		if (nextIdx == -1) goto errorReturn; //Error: badly formed cmd
		mstrIdx += nextIdx;

		if (isEqualString(elementName, "PipeName"))
		{
			*pipeName = (char *) tptp_malloc(strlen(elementValue) + 1);
			strcpy(*pipeName, elementValue);
			break;
		}
		tptp_free(elementName); elementName=NULL;
		tptp_free(elementValue); elementValue=NULL;
	}

	if (elementName) {tptp_free(elementName); elementName=NULL;}
	if (elementValue) {tptp_free(elementValue); elementValue=NULL;}

	return 0;

errorReturn:
	if (tagName != NULL) tptp_free(tagName);
	if (elementName != NULL) tptp_free(elementName);
	if (elementValue != NULL) tptp_free(elementValue);
	return -1; //TODO: replace with real error codes
}

int getSharedMemConfigInfo( const char* config, char **memName)
{
	char* tagName=NULL;
	char* elementName=NULL;
	char* elementValue=NULL;
	int mstrIdx=0;
	int nextIdx=0;

	nextIdx = getTagName(config, &tagName);
	if ((nextIdx == -1) || (tagName == NULL)) goto errorReturn; //Error: badly formed cmd

	if (!isEqualString(tagName, "Configuration") ) goto errorReturn; //Error: Don't have a "Cmd"
	mstrIdx += nextIdx;
	mstrIdx++;
	tptp_free(tagName); tagName=NULL;

	while (1)
	{
		nextIdx = getConfigElementName(&(config[mstrIdx]), &elementName);
		if ((nextIdx == -1) || (elementName == NULL)) goto errorReturn; //Error: badly formed cmd
		mstrIdx += nextIdx;

		nextIdx = getConfigElementValue(&(config[mstrIdx]), &elementValue);
		if ((nextIdx == -1) || (elementValue == NULL)) goto errorReturn; //Error: badly formed cmd
		mstrIdx += nextIdx;

		nextIdx = skipConfigElementClose(&(config[mstrIdx]));
		if (nextIdx == -1) goto errorReturn; //Error: badly formed cmd
		mstrIdx += nextIdx;

		if (isEqualString(elementName, "MemName"))
		{
			*memName = (char *) tptp_malloc(strlen(elementValue) + 1);
			strcpy(*memName, elementValue);
			break;
		}
		tptp_free(elementName); elementName=NULL;
		tptp_free(elementValue); elementValue=NULL;
	}

	if (elementName) {tptp_free(elementName); elementName=NULL;}
	if (elementValue) {tptp_free(elementValue); elementValue=NULL;}

	return 0;

errorReturn:
	if (tagName != NULL) tptp_free(tagName);
	if (elementName != NULL) tptp_free(elementName);
	if (elementValue != NULL) tptp_free(elementValue);
	return -1; //TODO: replace with real error codes
}





DOMNode* getConfigurationNodeByName(const char *initString, char *targetNodeName){


	try {
		//Build a MemBuf Input source 
		MemBufInputSource *is = new MemBufInputSource((const XMLByte*)initString,strlen(initString),"getNodeByName()",false);
		
		//Wrap the MemBufInputSource
		Wrapper4InputSource* domBufIS = NULL; 
		domBufIS = new Wrapper4InputSource(is);
	
		//Get the DOM document by passing the input string to the parser
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);

		//Get all the tags into the LnList
		XMLCh *varTag = XMLString::transcode(ELEMENT_CONFIGURATION_VARIABLE);
		DOMNodeList *node = doc->getElementsByTagName(varTag);
		XMLString::release(&varTag);
				
		DOMNodeList *varNode = node->item(0)->getChildNodes();
		int varNodeLength = varNode->getLength();
		
		for (int k=0; k<varNodeLength; k++) 
		{
			DOMNode *n = varNode->item(k);
		
			char *nodeName = customTranscode(n->getNodeName());
		
			if(strcmp(nodeName,targetNodeName) == 0){		
				return varNode->item(k);
			}
		}
		
		return NULL;
	}// end of try
	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing Host list in string \"%s\"", (initString?initString:"null"));
		return NULL;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing Host list in string \"%s\"", (initString?initString:"null"));
		return NULL;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing Host list in string \"%s\"", (initString?initString:"null"));
		return NULL;
	}
}

int getConfigurationString( const char* config, char* name, char **value )
{
	DOMNode *node = getConfigurationNodeByName(config, name);
	if(node == NULL){
		return -1;
	}	
	
	char* elementValue = customTranscode(node->getFirstChild()->getNodeValue());
	*value = (char*)tptp_malloc( sizeof(elementValue)+1);
	strcpy(*value, elementValue);
	return 0;


}

int getConfigurationInt( const char* config, char* name, tptp_int32 *value ){


	DOMNode *node = getConfigurationNodeByName(config, name);
	if(node == NULL){
		return -1;
	}	
	
	char* elementValue = customTranscode(node->getFirstChild()->getNodeValue());
	*value = atoi(elementValue);
	
	return 0;
}






/**
* Add the XML attrs to the list
*/
int addElementAttrs(DOMNode* node, tptp_list_t* paramList)
{
	DOMNamedNodeMap *cmdattrs = node->getAttributes();
	int cmdattrlen = cmdattrs->getLength();
	for(int j=0;j<cmdattrlen;j++) 
	{
		DOMAttr *attributeNode = (DOMAttr*) cmdattrs->item(j);
		char *attrname = customTranscode(attributeNode->getName());
		char *attrvalue = customTranscode(attributeNode->getValue());
		tptp_param_t* newParam;
		newParam = initParamT(attrname, attrvalue);
		tptp_list_add(paramList, (void*)newParam);
	    XMLString::release(&attrvalue);
		XMLString::release(&attrname);
	}		
	return 0;			
	
}
/**
*This is for getting all the XML elements into the list 
*/
int getXMLElements( const char* cmd, tptp_list_t** paramList)
{
	try {
		// Allocate and init the return paramList in case nothing is found.
		*paramList = (tptp_list_t*)tptp_malloc( sizeof(tptp_list_t));
		tptp_list_init(*paramList);
		tptp_list_setNodeDestructor(*paramList, destroyParamNode);
		tptp_list_setNodeCopier(*paramList, copyParamNode);

		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
		
		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		parser->setFeature(XMLUni::fgDOMWhitespaceInElementContent,false);
		parser->setFeature(XMLUni::fgDOMValidation,true);

		MemBufInputSource *is = new MemBufInputSource((const XMLByte*)cmd,strlen(cmd),"getXMLElements()",false);

		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		Wrapper4InputSource* domBufIS = NULL; 
		domBufIS = new Wrapper4InputSource(is);

		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);
		DOMTreeWalker* iter = doc->createTreeWalker(doc->getDocumentElement(),DOMNodeFilter::SHOW_ELEMENT,NULL,true);
        
		DOMNode *curr = iter->getCurrentNode();
		if(curr != NULL)
		{
			char *tempparmval = "\0";
			tptp_param_t* newParam;
			char *tempparmname = customTranscode(curr->getNodeName());
 				
			newParam = initParamT(tempparmname, tempparmval);
			tptp_list_add(*paramList, (void*)newParam);
			addElementAttrs(curr, *paramList);
			XMLString::release(&tempparmname);

		}
		while(curr)
		{
			curr = iter->nextNode();
			if(curr != NULL)
			{
				tptp_param_t* newParam;
				char *tempparmname = customTranscode(curr->getNodeName());	
				addElementAttrs(curr, *paramList);
					
				DOMNode* paramnode = curr->getFirstChild();
				if ( paramnode == NULL )
				{
					//DO NOTHING
				}
				else if ( paramnode->getNodeType() == DOMNode::TEXT_NODE )
				{
					char *tempparmval = customTranscode(paramnode->getNodeValue());
					newParam = initParamT(tempparmname, tempparmval);
					tptp_list_add(*paramList, (void*)newParam);
					XMLString::release( &tempparmval ); 
				}
				else if ( paramnode->getNodeType() == DOMNode::ELEMENT_NODE )
				{
					char *tempparmval = "\0";
					newParam = initParamT(tempparmname, tempparmval);
					tptp_list_add(*paramList, (void*)newParam);
				}
				
				XMLString::release( &tempparmname );
			}
		}
		
		delete domBufIS;
		delete tptp_dom_err;
		parser->release();
		return 0;
	} //end try
	
	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while creating a cmd parameter list by parsing XML elements of a command string \"%s\"", (cmd?cmd:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while creating a cmd parameter list by parsing XML elements of a command string \"%s\"", (cmd?cmd:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while creating a cmd parameter list by parsing XML elements of a command string \"%s\"", (cmd?cmd:"null"));
		return -1;
	}
}



/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Find the string value of an element within an XML fragment
 *                                                       
 * @return
 *	  0         success
 *    non-zero	failure
 *
 *********************************************************************/

int getXmlFragmentElementString( const char* fragment, char* rootName, char* elemName, char **value )
{
	try {
		//Initialize the XML parser
		DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser = ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
		
		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		//Build a MemBuf Input source 
		MemBufInputSource *is = new MemBufInputSource(reinterpret_cast<XMLByte const*>(fragment),
													  strlen(fragment),"getXmlFragmentElementString()",false );

		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		//Wrap the MemBufInputSource
		Wrapper4InputSource* domBufIS = NULL; 
		domBufIS = new Wrapper4InputSource(is);

		*value = NULL;

		//Get the DOM document by passing the input string to the parser
		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);
		
		//Get all the tags into the LnList - just get the node "Cmd", its children and attributes
		XMLCh* rootTag = XMLString::transcode(rootName);
		DOMNodeList *nodelist = doc->getElementsByTagName(rootTag);
		XMLString::release(&rootTag);
		
		int nodelength = nodelist->getLength();	

		if(nodelength == 0) 
		{ 
			/* Clean up */
			delete parser;
			delete domBufIS;

			return -1;
		} /* No root tag and hence no more parsing */

		for(int i = 0; i < nodelength; i++)
		{   
				DOMNodeList *childlist = nodelist->item(i)->getChildNodes();
		
				int childlength = childlist->getLength();	

				for(int j = 0; j < childlength; j++)
				{
					DOMNode* node = childlist->item(j);
					char*    nodeName = customTranscode(node->getNodeName());

					if ( 0 == strcmp( nodeName, elemName ) )
					{
						DOMNode* elemnode = node->getFirstChild();
						DOMNodeList *elemchildren = node->getChildNodes();
						int numElemChildren = elemchildren->getLength();

						/* If we have multiple children, one of them is whitespace */
						/* The other one should be an XML element */
						if ( numElemChildren > 1 )
						{
							int np;
							for ( np = 0; np < numElemChildren; np++ )
							{
								if ( elemchildren->item(np)->getNodeType() == DOMNode::ELEMENT_NODE )
								{
									elemnode = elemchildren->item(np);
									break;
								}
							}
						}
						if ( elemnode == NULL )
						{
							// TODO: ?
						}
						else if ( elemnode->getNodeType() == DOMNode::TEXT_NODE )
						{
							char *tempValue = customTranscode(elemnode->getNodeValue());
							*value = (char *)tptp_malloc(strlen(tempValue)+1);
							strcpy(*value, tempValue);
							XMLString::release(&tempValue);

							XMLString::release( &nodeName );
							break;
						}
						else if ( elemnode->getNodeType() == DOMNode::ELEMENT_NODE )
						{
							// TODO: Change writeNodeBuffer to dynamically allocate memory
							*value = (char*)tptp_malloc( 8193 );
							writeNodeToBuffer( elemnode, *value, 8192 );
							XMLString::release( &nodeName );
							break;
						}
					}

					XMLString::release( &nodeName );
				}
		}// For the nodes in the nodelist 

		delete domBufIS;
		delete tptp_dom_err;
		parser->release();

		if ( *value == 0 )
		{
			return -1;
		}

		return 0;
	} //end try
	
	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing string value of an XML element in fragment \"%s\"", (fragment?fragment:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing string value of an XML element in fragment \"%s\"", (fragment?fragment:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing string value of an XML element in fragment \"%s\"", (fragment?fragment:"null"));
		return -1;
	}
}

int getXmlFragmentElementInt( const char* fragment, char* rootName, char* elemName, int* value )
{
	char* valStr;
	int   ret;

	if ( value == NULL )
	{
		return TPTP_UNEXPECTED_NULL_ARG;
	}

	ret = getXmlFragmentElementString( fragment, rootName, elemName, &valStr );
	if ( ret != 0 )
	{
		return ret;
	}

	*value = atoi(valStr);

	tptp_free( valStr );

	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Find the string value of an element within an XML fragment
 *                                                       
 * @return
 *	  0         success
 *    non-zero	failure
 *
 *********************************************************************/

int getXmlFragmentElementPID( const char* fragment, char* rootName, char* elemName, PID *value )
{
	char* valStr;
	int   ret;

	if ( value == NULL )
	{
		return TPTP_UNEXPECTED_NULL_ARG;
	}

	ret = getXmlFragmentElementString( fragment, rootName, elemName, &valStr );
	if ( ret != 0 )
	{
		return ret;
	}

	*value = (PID)atoi(valStr);

	tptp_free( valStr );

	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Initialize the XML platform utilities. To be called ONCE by an
 *    application, and only once.
 *                                                       
 * @return
 *		void
 *
 *********************************************************************/

void initializeXMLPlatformUtils()
{
	XMLPlatformUtils::Initialize();
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Terminate the XML platform utilities. To be called ONCE by an
 *    application after ALL XML calls are complete.
 *                                                       
 * @return
 *		void
 *
 *********************************************************************/

void terminateXMLPlatformUtils()
{
	XMLPlatformUtils::Terminate();
}

#define ELEMENT_NAME_ALLOW "Allow"
#define ELEMENT_NAME_DENY "Deny"
#define ELEMENT_TRANS_LYR_VARIABLE "TransportLayer"
#define ELEMENT_CONFIGURATION_VARIABLE "Configuration"


/** Converts an ASCII hex character to an int. */
int getcharhexval(char c) {
    if(c >= '0' && c <=  '9') {
         return c - '0';
    }

    if(c >= 'A' && c <= 'F') {
         return c - 'A' + 10;
    }    
    
    if(c >= 'a' && c <= 'f') {
         return c - 'a' + 10;         
    }
    
    return -1;
    
}

void parseStringIntoBlock(char *str, unsigned char *result) {
	unsigned int val = 0;

	val = getcharhexval(str[2])*16 + getcharhexval(str[3]);
	result[1] = (unsigned char)val;
	

	val = getcharhexval(str[0]) * 16 + getcharhexval(str[1]);
	result[0] = (unsigned char)val;

}

void parseIPv6IP(char *str, unsigned char *result) {
	
	char *nameTemp = 0;
	int i;
	
	nameTemp = (char *)tptp_malloc(strlen(str)+10);
	strcpy(nameTemp, str);
	
	if(strcmp(str, "::1") == 0) {
		for(int x = 0; x < 16; x++) {
			result[x] = 0;
		}
		result[15] = 1;
		
		return;
	}

	/* start at the back of the string and calculate the address*/
	for(i=14; i>0; i-=2) {
		char *current=strrchr(nameTemp, ':');
		if(current == NULL) {
			// The IP address is of an improper format, so bail.
			tptp_free(nameTemp);
			for(int x = 0; x < 16; x++) {
				result[x] = 0;
			}
			return;
		}
		// result[i]=(char)atoi(current+1);
		parseStringIntoBlock(current+1, &(result[i]));

		*current='\0';
	}
	parseStringIntoBlock(nameTemp, &(result[0]));
	// result[0]=atoi(nameTemp);

	tptp_free(nameTemp);
	
}

void tptp_addNetwork(network_list_t *list, int allow, tptp_host_wildcard_t wildcard, char *name, char *mask)
{
	char *nameTemp = NULL;
	char *maskTemp = NULL;

	/* Create the node in the list */
	network_list_node_t *network_node;
	network_t *network;

	network_node=(network_list_node_t*)tptp_malloc(sizeof(network_list_node_t));
	network=(network_t*)tptp_malloc(sizeof(network_t));

	/* set the type in the node */
	network->allow=allow;
	
	/* copy name to a temporary buffer */
	if (name != NULL) {
		nameTemp = (char *) tptp_malloc(strlen(name) +1);
		strcpy(nameTemp, name);
	}
	
	/* copy mask to a temporary buffer */
	if (mask != NULL) {
		maskTemp = (char *) tptp_malloc(strlen(mask) +1);
		strcpy(maskTemp, mask);
	}

	/* If the wildcard in TPTP_HW_NAMED then we need to copy the address information */
	if(wildcard==TPTP_HW_NAMED) {
		network->hostname = (char *) tptp_malloc(strlen(nameTemp) +1);
		strcpy(network->hostname, nameTemp);
	}

	/* If this is a network then we need to copy the IPv4 address information */
	if(wildcard==TPTP_HW_NET && strstr(name, ".") != NULL) {
		int i;

		/* start at the back of the string and calculate the address*/
		for(i=3; i>0; i--) {
			char *current=strrchr(nameTemp, '.');
			network->net[i]=(char)atoi(current+1);
			*current='\0';
		}
		network->net[0]=atoi(nameTemp);

		for(i=3; i>0; i--) {
			char *current=strrchr(maskTemp, '.');
			network->mask[i]=(char)atoi(current+1);
			*current='\0';
		}
		network->mask[0]=atoi(maskTemp);
		
		network->netAndMaskAreIpv4 = 1;
	
	} // TPTP_HW_NET - IPv6 address
	else if(wildcard==TPTP_HW_NET && strstr(name, ":") != NULL) {

		parseIPv6IP(name, network->netipv6);
		parseIPv6IP(mask, network->maskipv6);
		
		network->netAndMaskAreIpv4 = 0;
	}

	if(nameTemp) tptp_free(nameTemp); nameTemp = NULL;
	if(maskTemp) tptp_free(maskTemp); maskTemp = NULL;

	/* set the wildcard in the node */
	network->wildcard=wildcard;

	/* And the node to the list */
	network_node->entry=network;
	network_node->next=NULL;
	network_node->previous=list->tail;
	list->tail=network_node;
	/* If this not the first entry we must set the link in the previous tail */
	if(network_node->previous) {
		network_node->previous->next=network_node;
	}
	else {
		list->head=network_node;
	}
}



int parseUserList(const char *initString, char **userType, char **userList){

	DOMNode *userNode = getConfigurationNodeByName(initString, "UserDefinition");
	if(userNode == NULL)
		return -1;

	DOMNamedNodeMap *attributes = userNode->getAttributes();
	
	for (unsigned int index = 0; index < attributes->getLength(); index++) {
		DOMAttr *attributeNode = (DOMAttr*) attributes->item(index);
		char *cAttrName = customTranscode(attributeNode->getName());
		char *cAttrValue = customTranscode(attributeNode->getValue());
				
		if(strcmp(ATTRB_USER_TYPE, cAttrName)==0) {
			*userType = (char *) tptp_malloc(strlen(cAttrValue) +1);
			strcpy(*userType, cAttrValue);
		}
		if(strcmp(ATTRB_USER_LIST, cAttrName)==0) {
			*userList = (char *) tptp_malloc(strlen(cAttrValue) +1);								
			strcpy(*userList, cAttrValue);
		}
	}
	return 0;
}
	
int parseHostList(const char *initString, network_list_t **nList)
{
	try {
		//Build a MemBuf Input source 
		MemBufInputSource *is = new MemBufInputSource((const XMLByte*)initString,strlen(initString),"parseHostList()",false);

		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		//Wrap the MemBufInputSource
		Wrapper4InputSource* domBufIS = NULL; 
		domBufIS = new Wrapper4InputSource(is);

		//Get the DOM document by passing the input string to the parser
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);

		//Initialize the list to NULL... just so that we can check it later.
		//It's possible there will be no host list.
		*nList = NULL;
		
		//Get all the tags into the LnList
		XMLCh *varTag = XMLString::transcode(ELEMENT_CONFIGURATION_VARIABLE);
		DOMNodeList *node = doc->getElementsByTagName(varTag);
		XMLString::release(&varTag);
				
		DOMNodeList *varNode = node->item(0)->getChildNodes();
		int varNodeLength = varNode->getLength();

		for (int k=0; k<varNodeLength; k++) 
		{
			char *nodeName = customTranscode(varNode->item(k)->getNodeName());
			if(strcmp(nodeName, "Hosts") == 0)
			{
				DOMNodeList *childvarNode = varNode->item(k)->getChildNodes();
				int childNodeLength = childvarNode->getLength();
				int j;
				network_list_t *pList;

				*nList = (network_list_t *) tptp_malloc(sizeof(network_list_t));
				pList = *nList;
				pList->head = NULL;
				pList->tail = NULL;


				for (j=0; j<childNodeLength;j++) {
					char *childnodeName = customTranscode(childvarNode->item(j)->getNodeName());

					if(strcmp(ELEMENT_NAME_DENY, childnodeName)==0) {
						char *host, *net, *mask, *hostlist;
						host = net = mask = hostlist = NULL;
						DOMNamedNodeMap *attributes = childvarNode->item(j)->getAttributes();

						for (unsigned int index = 0; index < attributes->getLength(); index++) {
							DOMAttr *attributeNode = (DOMAttr*) attributes->item(index);
							char *cAttrName = customTranscode(attributeNode->getName());
							char *cAttrValue = customTranscode(attributeNode->getValue());
				
							if(strcmp("type", cAttrName)==0) {
								host = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(host, cAttrValue);
							}
							else if(strcmp("net", cAttrName)==0) {
								net = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(net, cAttrValue);
							}
							else if(strcmp("mask", cAttrName)==0) {
								mask = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(mask, cAttrValue);
							}else if(strcmp(ATTRB_HOST_LIST, cAttrName)==0) {
								hostlist = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(hostlist, cAttrValue);
							}
							
							XMLString::release(&cAttrName);
							XMLString::release(&cAttrValue);
						}

						if(host) { /* Is this a host specification or a network */
							/* Check for wildcards */
							if(strcmp(HOST_TYPE_ALL, host)==0) {
								tptp_addNetwork(*nList, 0, TPTP_HW_ALL, NULL, NULL);
							}
							else if(strcmp(HOST_TYPE_LOCAL, host)==0) {
								tptp_addNetwork(*nList, 0, TPTP_HW_LOCAL, NULL, NULL);
							}
							else {
								tptp_addNetwork(*nList, 0, TPTP_HW_NAMED, hostlist, NULL);
							}
						}
						else { /* if this is a net-mask pair */
							/* Ignore if one of net or mask is not there */
							if((net == NULL) || (mask == NULL)) {
								//ra_logServiceMessage(__FILE__, __LINE__, RA_WARNING, "Configuration file element 'Deny' does not have both 'net' and 'mask' attributes. Line ignored.");
							}
							else {
								tptp_addNetwork(*nList, 0, TPTP_HW_NET, net, mask);
							}
						}
						if(host) tptp_free(host); host = NULL;
						if(net) tptp_free(net); net = NULL;
						if(mask) tptp_free(mask); mask = NULL;
					}
					else if(strcmp(ELEMENT_NAME_ALLOW, childnodeName)==0) {
						char *host, *net, *mask, *hostlist;
						host = net = mask = hostlist = NULL;
						DOMNamedNodeMap *attributes = childvarNode->item(j)->getAttributes();

						for (unsigned int index = 0; index < attributes->getLength(); index++) {
							DOMAttr *attributeNode = (DOMAttr*) attributes->item(index);
							char *cAttrName = customTranscode(attributeNode->getName());
							char *cAttrValue = customTranscode(attributeNode->getValue());
							if(strcmp("type", cAttrName)==0) {
								host = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(host, cAttrValue);
							}
							else if(strcmp("net", cAttrName)==0) {
								net = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(net, cAttrValue);
							}
							else if(strcmp("mask", cAttrName)==0) {
								mask = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(mask, cAttrValue);
							}else if(strcmp(ATTRB_HOST_LIST, cAttrName)==0) {
								hostlist = (char *) tptp_malloc(strlen(cAttrValue) +1);
								strcpy(hostlist, cAttrValue);
							}
							
							XMLString::release(&cAttrName);
							XMLString::release(&cAttrValue);
						}

						if(host) { /* Is this a host specification or a network */
							/* Check for wildcards */
							if(strcmp(HOST_TYPE_ALL, host)==0) {
								tptp_addNetwork(*nList, 1, TPTP_HW_ALL, NULL, NULL);
							}
							else if(strcmp(HOST_TYPE_LOCAL, host)==0) {
								tptp_addNetwork(*nList, 1, TPTP_HW_LOCAL, NULL, NULL);
							}else if(strcmp(HOST_TYPE_CUSTOM, host)==0) { 

								char *tok = strtok(hostlist, ",");
								while(tok != NULL) {
									char *trimTok = trim(tok);
									tptp_addNetwork(*nList, 1, TPTP_HW_NAMED, trimTok, NULL);
									tok = strtok(NULL, ",");
								
								}
							}
						}
						else { /* if this is a net-mask pair */
							/* Ignore if one of net or mask is not there */
							if((net == NULL) || (mask == NULL)) {
								//ra_logServiceMessage(__FILE__, __LINE__, RA_WARNING, "Configuration file element 'Allow' does not have both 'net' and 'mask' attributes. Line ignored.");
							}
							else {
								tptp_addNetwork(*nList, 1, TPTP_HW_NET, net, mask);
							}
						}
						if(host) tptp_free(host); host = NULL;
						if(net) tptp_free(net); net = NULL;
						if(mask) tptp_free(mask); mask = NULL;
					}

					XMLString::release(&childnodeName);
				}
			}
			
			XMLString::release(&nodeName);
		}
		
		delete domBufIS;
		delete tptp_dom_err;
		parser->release();
		
		return 0;
	} //end try
	
	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing Host list in string \"%s\"", (initString?initString:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing Host list in string \"%s\"", (initString?initString:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing Host list in string \"%s\"", (initString?initString:"null"));
		return -1;
	}
}

/*
 * --------------------------------------------------------------------------------
 * All the platform-dependent vrfusrpwd() functions below
 * --------------------------------------------------------------------------------
 */

#if defined(_WIN32)
/*
 *	Windows/IA32 section, in-process authentication
 */
int vrfusrpwd(tptp_string *userid, tptp_string *password) {
	HANDLE handle;
	return LogonUser(userid, NULL, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &handle) ? 1 : 0;
}
#elif defined(__MVS__)
/*
 *	OS/390 section, in-process authentication. BPX.DAEMON is needed.
 */
int vrfusrpwd(tptp_string *userid, tptp_string *password) {
	return __passwd(userid, password, NULL) ? 0 : 1;
}
#elif defined(__OS400__)
/*
 *	OS/400 section, in-process authentication
 */
int vrfusrpwd(tptp_string *userid, tptp_string *password) {
	struct error_code_t errorCode;
	char profileHandle[12];  /* profile handle, required by QSYGETPH API */
	char useridBuf[10] = "          ";

	/* In descrypted case, the password is in code page of 437 */
	errorCode.bytesProvided = 64;
	errorCode.bytesAvailable = 0;

	if(userid[0] == '*') {
		return 0;
	}
	else if(strlen(userid) > 10) {
		return 0;
	}
	else {
		int i;
		for(i = 0; i < strlen(userid); i++) {
			useridBuf[i] = toupper(userid[i]); /* change it all to upper case */
		}
	}

	QSYGETPH(useridBuf, password, profileHandle, &errorCode, strlen(password), 37); /* CCSID of password is 37 (EBCDIC) */

	if(errorCode.bytesAvailable > 0) {
		char *exc = (char*)ra_malloc(sizeof(char) * 8);
		BZERO(exc, 8);
		strncpy(exc, errorCode.exceptionID, 7);
		ra_free(exc);

		return 0;
	}
	else {
		return 1;  /* authentication successful */
	}
}
#else /* non-Windows, non-OS/400 */
/*
 * Launch a separate process to authenticate user name and password
 */
int vrfusrpwd(tptp_string *userid, tptp_string *password) {
	FILE *fp;
	int success = 0; // FALSE
	char *serverHome;
	char *authCmd;
	int authLen;
	int status;
	int rc=0;

	struct sigaction ignoreHandler; /* Use this handler for bypassing pre-configured signal handler */
	struct sigaction oldHandler; /* Used to temporary storing the configured signal handler */

	serverHome = getCacheEnv("default", RASERVER_HOME_CONFIG_NAME);
	/* Do not pass user ID and password since they will be shown by running 'ps' */
	authLen = strlen(serverHome) + 1 + strlen(BIN_DIR) + 1 + strlen(CHKPASS_CMD) + 1; /* Bug 168705 : need a null at the end for strcat() */
	authCmd = (char*)malloc(sizeof(char) * authLen);
	BZERO(authCmd, authLen);
	strcpy(authCmd, serverHome);
	strcat(authCmd, "/");
	strcat(authCmd, "bin");
	strcat(authCmd, "/");
	strcat(authCmd, CHKPASS_CMD);

	/* Disable default SIGCHLD handler since system() call doesn't work with user-supplied signal handlers */
	BZERO(&ignoreHandler, sizeof(struct sigaction));
	BZERO(&oldHandler, sizeof(struct sigaction));

	ignoreHandler.sa_handler = SIG_DFL; /* Reset to default SIGCHLD handler */
	sigaction(SIGCHLD, &ignoreHandler, &oldHandler); /* Store the previous signal handler */

	fp = popen(authCmd, "w");
	fprintf(fp, "%s\n", userid);
	fprintf(fp, "%s\n", password);
	status = pclose(fp);
	if(WIFEXITED(status)) {
		rc = WEXITSTATUS(status);
	}

	if(rc == 100) { /* 100 indicates success */
		success = 1;
	}
	else {
		success = 0;
	}

	/* Re-enable the user-specified SIGCHLD handler */
	sigaction(SIGCHLD, &oldHandler, NULL);

	free(authCmd);

	return success;
}

#endif

char* trim(char *str){
	
	char *ptr = (char*)tptp_malloc(strlen(str)+1);
	int i,j=0;
	for(i=0;str[i]!='\0';i++){
		if (str[i] != ' ' && str[i] != '\t') 
		ptr[j++]=str[i];
	} 
	ptr[j]='\0';
	return ptr;
} 


