//
// $Id: EnvironmentVariableProbe.cpp,v 1.6 2005/04/08 18:58:43 bakerj Exp $
//
//****************************************************************************************//
// Copyright (c) 2005, The MITRE Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice, this list
//       of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice, this 
//       list of conditions and the following disclaimer in the documentation and/or other
//       materials provided with the distribution.
//     * Neither the name of The MITRE Corporation nor the names of its contributors may be
//       used to endorse or promote products derived from this software without specific 
//       prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//****************************************************************************************//

#include "EnvironmentVariableProbe.h"

//****************************************************************************************//
//								EnvironmentVariableProbe Class									  //	
//****************************************************************************************//
EnvironmentVariableProbe *EnvironmentVariableProbe::instance = NULL;

EnvironmentVariableProbe::EnvironmentVariableProbe()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Do nothing for now
	//
	// -----------------------------------------------------------------------
}

EnvironmentVariableProbe::~EnvironmentVariableProbe()
{
	// -----------------------------------------------------------------------
	//
	//  ABSTRACT
	//
	//  Do nothing for now
	//
	// -----------------------------------------------------------------------
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Public Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Probe* EnvironmentVariableProbe::Instance()
{

	// -----------------------------------------------------------------------
	//
	//  ABSTRACT
	//
	//	Ensure that the EnvironmentVariableProbe is a singleton.
	// -----------------------------------------------------------------------

	// Use lazy initialization
	if(instance == NULL) 
		instance = new EnvironmentVariableProbe();

	return instance;	
}

string EnvironmentVariableProbe::GetEnvironmentVariableValue(string variable)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return the value of the specified variable
	//
	// -----------------------------------------------------------------------

	string value = "";
	EnvironmentVariableData *envIn	= new EnvironmentVariableData();
	envIn->name->object = variable;
	envIn->name->type = literal;

	//	Call the probe
	Probe *probe = EnvironmentVariableProbe::Instance();
	pdVector envOut;
	envOut = probe->Run(envIn);
	delete envIn;
	envIn = NULL;

	// Must write a record to the sc file for this env so that
	// it can be used durring analysis
	envOut[0]->Write();

	EnvironmentVariableData *resultEnvData = (EnvironmentVariableData*)envOut[0];

	//	Check the status 
	if(resultEnvData->GetStatus() == error) {
		string errMsg = "Error: An error occured while collecting data for the specified environment variable.\n";
		errMsg.append("Probe message: " + resultEnvData->GetMessage());
		throw EnvironmentVariableProbeException(errMsg);

	} else if(resultEnvData->GetStatus() == doesNotExist) {
		string errMsg = "Error: The specified environment variable does not exist.\n";
		errMsg.append("Probe message: " + resultEnvData->GetMessage());
		throw EnvironmentVariableProbeException(errMsg);
	}

	//	Return the Value
	return resultEnvData->value->value;
}

pdVector EnvironmentVariableProbe::Run(ProbeData *probeDataIn)
{
	
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Return the value of the environment variable specified. If it is not 
	//	found return NULL. 
	//
	//	NOTE: Pattern matching is not supported.
	//
	// -----------------------------------------------------------------------

	pdVector returnVector;

	EnvironmentVariableData *envVarIn = (EnvironmentVariableData*)probeDataIn;

	EnvironmentVariableData *envVarOut = new EnvironmentVariableData();
	envVarOut->name->object = envVarIn->name->object;

	char * envValue = getenv(envVarOut->name->object.c_str());

	//	Check the value 
	if(envValue == NULL) {
		envVarOut->SetMessage("Message: Unable to find the value of: " + envVarIn->name->object);
		envVarOut->SetStatus(doesNotExist);

	} else {
        envVarOut->value->value = envValue;
	}

	returnVector.push_back(envVarOut);
	return (returnVector);
}

//****************************************************************************************//
//						EnvironmentVariableProbeException Class							  //	
//****************************************************************************************//
EnvironmentVariableProbeException::EnvironmentVariableProbeException(string errMsgIn, int severity) : Exception(errMsgIn, severity)
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Set the error message and then set the severity to ERROR_FATAL. This is 
	//	done with the explicit call to the Exception class constructor that 
	//	takes a single string param.
	//
	// -----------------------------------------------------------------------

}

EnvironmentVariableProbeException::~EnvironmentVariableProbeException()
{
	// -----------------------------------------------------------------------
	//	Abstract
	//
	//	Do nothing for now
	//
	// -----------------------------------------------------------------------

}