/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:   
* This file was autogenerated by rpcgen, but should be modified by the developer.
* Make sure you don't use the -component_mod flag in future or this file will be overwritten.
* Thu Oct 16 14:41:55 2003
* System Includes
*
*/




#include <stdio.h>
#include <signal.h>


/****************************************************************************************
 * 
 * Local Includes
 * 
 ***************************************************************************************/
#include "CSvcHostexecuteasync.h"
#include "CSHostexecuteasync.h"
#include "../include/standard_unix.h"
#include "../include/strncpynt.h"

/****************************************************************************************
 * 
 * Implementation
 * 
 ***************************************************************************************/
CSHostexecuteasync::CSHostexecuteasync()
{
	iProcess = NULL;
}

CSHostexecuteasync::~CSHostexecuteasync()
{
	assert( iProcess == NULL );
}

int CSHostexecuteasync::GetKey()
{
	return iKey;
}

void CSHostexecuteasync::SetKey( int aKey )
{
	iKey = aKey;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: cstr_startprocess
 * 
 ***************************************************************************************/
TResult CSHostexecuteasync::cstr_startprocess( char *aArgs )
{
	TResult rv = { ERR_NONE, 0, 0 };
	int errcode;
	TCAProcessError perr;

	// create a process object
	iProcess = new CAProcess();
	assert( iProcess != NULL );

	// start the process running
	perr = iProcess->StartProcess( aArgs, &errcode, true, true, false );
	if( perr != CAE_NONE ) {
		rv.iStandardResult = ERR_START_PROCESS_ERROR;
		rv.iExtendedCode = (int)perr;
		rv.iSystemError = errcode;
		delete iProcess;
		iProcess = NULL;
		return rv;
	}

	// done - success
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: dstr_removeprocess
 * 
 ***************************************************************************************/
TResult CSHostexecuteasync::dstr_removeprocess( int aArgs, int *aDeleteInstance )
{
	TResult rv = { ERR_NONE, 0, 0 };
	TCAProcessError perr;
	TProcessStatus pstatus;

	// make sure that we still have a process
	assert( iProcess != NULL );
	
	// get the status of the process to make sure we are ok
	perr = iProcess->GetProcessStatus( &pstatus );
	assert( perr == CAE_NONE );
	if( pstatus == PS_STARTED ) {
	  *aDeleteInstance = 0;
	  rv.iStandardResult = ERR_INVALIDSTATE;
	  return rv;
	}

	// ok - remove the process
	delete iProcess;
	iProcess = NULL;

	// done - success
	*aDeleteInstance = 1; 
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: killprocess
 * 
 ***************************************************************************************/
TResult CSHostexecuteasync::killprocess( int aArgs )
{
	return StopProcessWithSignal( SIGKILL );
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: stopprocess
 * 
 ***************************************************************************************/
TResult CSHostexecuteasync::stopprocess( int aArgs )
{
	return StopProcessWithSignal( SIGTERM );
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: getprocessinfo
 * 
 ***************************************************************************************/
THostExecuteAsyncProcessInfo CSHostexecuteasync::getprocessinfo( int aArgs )
{
	string command_line;
	THostExecuteAsyncProcessInfo rv;
	TCAProcessError perr;
	TProcessStatus pstatus = PS_INVALID;
	TProcessExitReason preason = ER_INVALID;
	int exitcode = 0;

	// check the state
	assert( iProcess != NULL );

	// interrogate the process	
	perr = iProcess->GetProcessStatus( &pstatus );
	assert( perr == CAE_NONE );
	if( (pstatus == PS_STOPPED) || (pstatus == PS_ABANDONNED) ) {
		perr = iProcess->GetExitReason( &preason );
		assert( perr == CAE_NONE );
	}
	if( (pstatus == PS_STOPPED) || (pstatus == PS_ABANDONNED) ) {
		perr = iProcess->GetExitCode( &exitcode );
		assert( perr == CAE_NONE );
	}
	command_line = iProcess->GetCommandString();

	// copy into the rv
	rv.iErrorCode = ERR_NONE;
	rv.iErrorDetail = 0;
	rv.iProcessStatus = (int)pstatus;
	rv.iProcessExitReason = (int)preason;
	rv.iExitCode = exitcode;
	STRNCPY_NULL_TERMINATE( rv.iCommandLine, command_line.c_str(), MAXCOMMANDLINE );

	// done - success
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: getstandardoutput
 * 
 ***************************************************************************************/
TVarData CSHostexecuteasync::getstandardoutput( int aArgs )
{
	TVarData rv;
	TCAProcessError perr;
	int output_read_count, error_read_count, read_error;
	string output;

	// since we create in the constructor and stop in the destructor there must be a process
	assert( iProcess != NULL );

	// poll for new output - ignore errors since there may be some buffered data anyway
	perr = iProcess->PollProcessForNewOutput( 0, &output_read_count, &error_read_count );

	// now read it into a string
	output_read_count = iProcess->GetRecordedStandardOutput( &output, &read_error );
	if( output_read_count == 0 ) {
	  rv.TVarData_val = NULL;
	  rv.TVarData_len = 0;
	  return rv;
	}

	// copy it into a buffer
	rv.TVarData_val = (char*)malloc( output.size() + 1 );
	rv.TVarData_len = output.size() + 1;
	memcpy( rv.TVarData_val, output.c_str(), output.size() );
	rv.TVarData_val[output.size()] = 0;
	return rv;
}


/****************************************************************************************
 * 
 * PUBLIC FUNCTION: getstandarderror
 * 
 ***************************************************************************************/
TVarData CSHostexecuteasync::getstandarderror( int aArgs )
{
	TVarData rv;
	TCAProcessError perr;
	int output_read_count, error_read_count, read_error;
	string stderror;

	// since we create in the constructor and stop in the destructor there must be a process
	assert( iProcess != NULL );

	// poll for new output - ignore errors since there may be some buffered data anyway
	perr = iProcess->PollProcessForNewOutput( 0, &output_read_count, &error_read_count );

	// now read it into a string
	error_read_count = iProcess->GetRecordedStandardError( &stderror, &read_error );
	if( error_read_count == 0 ) {
	  rv.TVarData_len = 0;
	  rv.TVarData_val = NULL;
	  return rv;
	}

	// copy it into a buffer
	rv.TVarData_val = (char*)malloc( stderror.size() + 1 );
	rv.TVarData_len = stderror.size() + 1;
	memcpy( rv.TVarData_val, stderror.c_str(), stderror.size() );
	rv.TVarData_val[stderror.size()] = 0;
	return rv;
}


/****************************************************************************************
 * 
 * PRIVATE FUNCTION: StopProcessWithSignal
 * 
 ***************************************************************************************/
TResult CSHostexecuteasync::StopProcessWithSignal( int aSignal )
{
	TResult rv = { ERR_NONE, 0, 0 };
	TCAProcessError perr;
	TProcessStatus pstatus;

	// since we create in the constructor and stop in the destructor there must be a process
	assert( iProcess != NULL );

	// if the process isn't running then it has died outside the scope of this controller, 
	// clean up the state, return an error since this is noteworthy and should be either 
	// expected or not happen.
	perr = iProcess->GetProcessStatus( &pstatus );
	assert( perr == CAE_NONE );
	if( pstatus != PS_STARTED ) {
	  assert( (pstatus == PS_STOPPED) || (pstatus == PS_ABANDONNED) );
	  rv.iStandardResult = ERR_PROCESS_TERMINATED_OUTSIDE_SCOPE;
	  return rv;
	}

	// request the process to stop
	perr = iProcess->RequestStop( aSignal );
	if( perr != CAE_NONE ) {
	  rv.iStandardResult = ERR_STOP_PROCESS_ERROR;
	  rv.iExtendedCode = (int)perr;
	  return rv;
	}

	// wait for the process to stop
	perr = iProcess->WaitForProcessToTerminate( -1 );
	if( perr != CAE_NONE ) {
	  rv.iStandardResult = ERR_WAIT_PROCESS_ERROR;
	  rv.iExtendedCode = (int)perr;
	  return rv;
	}

	// done - success
	return rv;
}
