//
// $Id: UnameProbe.cpp,v 1.9 2005/03/28 15:59: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 "UnameProbe.h"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  UnameProbe Class  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
UnameProbe *UnameProbe::instance = NULL;

UnameProbe::UnameProbe()
{
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//  Simply initialize myUnameData and call GetNameInfo
	//
	//------------------------------------------------------------------------------------//

	myUnameData = new UnameData();
	GetNameInfo();
}

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

}

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

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

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

	return instance;	
}

pdVector UnameProbe::Run(ProbeData *probeDataIn)
{
	//------------------------------------------------------------------------------------//
	//  ABSTRACT
	//
	//  Get the uname info for this system.
	//	Only call the GetNameInfo method if myUnameData is NULL. Otherwise just copy  
	//	the data in myUnameData to data out. 
	//
	//------------------------------------------------------------------------------------//

	pdVector resultVector;

	//	Copy the uname data to the data out object
	UnameData *dataOut  = new UnameData();
	
	dataOut->os_name->value = myUnameData->os_name->value;
	dataOut->os_name->status = myUnameData->os_name->status;
	dataOut->os_name->dataType = myUnameData->os_name->dataType;

	dataOut->node_name->value = myUnameData->node_name->value;
	dataOut->node_name->status = myUnameData->node_name->status;
	dataOut->node_name->dataType = myUnameData->node_name->dataType;

	dataOut->os_release->value = myUnameData->os_release->value;
	dataOut->os_release->status = myUnameData->os_release->status;
	dataOut->os_release->dataType = myUnameData->os_release->dataType;

	dataOut->os_version->value = myUnameData->os_version->value;
	dataOut->os_version->status = myUnameData->os_version->status;
	dataOut->os_version->dataType = myUnameData->os_version->dataType;

	dataOut->machine_class->value = myUnameData->machine_class->value;
	dataOut->machine_class->status = myUnameData->machine_class->status;
	dataOut->machine_class->dataType = myUnameData->machine_class->dataType;

	//	Add the dataIn object to the result vector
	resultVector.push_back(dataOut);

	return resultVector;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Private Members  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

void UnameProbe::GetNameInfo()
{
	//------------------------------------------------------------------------------------//
	//
	//  ABSTRACT
	//
	//  Get the uname info and put it in the UnameData object
	//
	//------------------------------------------------------------------------------------//
	
	struct utsname tmpName;
	
	if (uname(&tmpName) > -1) {
		myUnameData->os_name->value = tmpName.sysname;
		myUnameData->os_name->status = exists;
		myUnameData->os_name->dataType = stringType;

		myUnameData->node_name->value = tmpName.nodename;
		myUnameData->node_name->status = exists;
		myUnameData->node_name->dataType = stringType;

		myUnameData->os_release->value = tmpName.release;
		myUnameData->os_release->status = exists;
		myUnameData->os_release->dataType = stringType;

		myUnameData->os_version->value = tmpName.version;
		myUnameData->os_version->status = exists;
		myUnameData->os_version->dataType = stringType;

		myUnameData->machine_class->value = tmpName.machine;
		myUnameData->machine_class->status = exists;
		myUnameData->machine_class->dataType = stringType;

		// These two appear to be the same on a Linux system
		myUnameData->processor_type->value = myUnameData->machine_class->value;
		myUnameData->processor_type->status = exists;
		myUnameData->processor_type->dataType = stringType;

	} else {
		myUnameData->SetMessage("Error: UnameProbe() unable to get uname information");
		myUnameData->SetStatus(error);

		myUnameData->os_name->status = error;
		myUnameData->os_name->dataType = stringType;

		myUnameData->node_name->status = error;
		myUnameData->node_name->dataType = stringType;

		myUnameData->os_release->status = error;
		myUnameData->os_release->dataType = stringType;

		myUnameData->os_version->status = error;
		myUnameData->os_version->dataType = stringType;

		myUnameData->machine_class->status = error;
		myUnameData->machine_class->dataType = stringType;

		myUnameData->processor_type->status = error;
		myUnameData->processor_type->dataType = stringType;
	}

	//I am laving this Solaris condition here for reference use
	//When I have to write a Solaris uname probe. I will just use this probe as a template
	/*#ifdef SUNOS

	char buf[64];
	
	memset(buf, '\0', sizeof(buf));
	if (sysinfo(SI_ARCHITECTURE, buf, sizeof(buf)) > -1) 
	{
		processorType = buf;
	}
	
	memset(buf, '\0', sizeof(buf));
	if (sysinfo(SI_PLATFORM, buf, sizeof(buf)) > -1) 
	{
		hardwarePlatform = buf;
	}
	#endif*/
}



