// =============================================================================
// Zboard Config Utility
// Copyright (C) 2007  Matt Razza

// 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
// of the License, or (at your option) any later version.

// This program 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 program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
// -------------------------------------------------------------------------------
// This file manages and interfaces with the
// processes.
// ===============================================================================

// Load header file
#include "zboard-info.h"

// ========================================================================
// Public Functions
// ========================================================================

// Check if a given application is running
bool linuxProcInfo::isRunning(std::string procName, bool bVerbose)
{
	DIR *dirData; //Dir tracker
	dirent *dirName; //Dir name struct (info)
	std::string sDir = "/proc", sProcID = ""; //String of dir
	dirData = opendir(sDir.c_str()); //Open it

	while ((dirName = readdir(dirData))) //Scan all files in dir
	{
		sDir = "/proc/";
		sDir += dirName->d_name;
		sProcID = dirName->d_name;

		if (linuxFileInfo::isDirectory(sDir, bVerbose)) //Is the file/dir a dir?
		{
			if (linuxFileInfo::fileExists(sDir + "/status") && sProcID != "." && sProcID != "..") //Is it a process?
			{
				if (getProcName(stoi(sProcID)) == procName) //Check if it's the proc
				{
					closedir(dirData);
					return true;
				}
			}
		}
	}

	closedir(dirData);
	return false;
}

// Gets a proc name from it's pid
std::string linuxProcInfo::getProcName(unsigned int pid)
{
	// Set the dir
	std::string sDir = "/proc/";
	sDir += itos(pid);
	std::string sFile = sDir + "/status", sData = "";

	std::ifstream fileStream(sFile.c_str()); //Open the file
	fileStream >> sData; //Readline
	fileStream >> sData; //Readline
	fileStream.close(); //Close the file

	return sData;
}

// Prints the running processes
void linuxProcInfo::printRunning(bool bVerbose)
{
	DIR *dirData; //Dir tracker
	dirent *dirName; //Dir name struct (info)
	std::string sDir = "/proc", sProcID = ""; //String of dir
	dirData = opendir(sDir.c_str()); //Open it

	while ((dirName = readdir(dirData))) //Scan all files in dir
	{
		sDir = "/proc/";
		sDir += dirName->d_name;
		sProcID = dirName->d_name;

		if (linuxFileInfo::isDirectory(sDir, bVerbose)) //Is the file/dir a dir?
		{
			if (linuxFileInfo::fileExists(sDir + "/status") && sProcID != "." && sProcID != "..") //Is it a process?
			{
				printf("PID: %s; Name: %s\n", sProcID.c_str(), getProcName(stoi(sProcID)).c_str());
			}
		}
	}

	closedir(dirData);
}

// Gets PID for a given proc
int linuxProcInfo::getPID(std::string procName, bool bVerbose)
{
	DIR *dirData; //Dir tracker
	dirent *dirName; //Dir name struct (info)
	std::string sDir = "/proc", sProcID = ""; //String of dir
	dirData = opendir(sDir.c_str()); //Open it

	while ((dirName = readdir(dirData))) //Scan all files in dir
	{
		sDir = "/proc/";
		sDir += dirName->d_name;
		sProcID = dirName->d_name;

		if (linuxFileInfo::isDirectory(sDir, bVerbose)) //Is the file/dir a dir?
		{
			if (linuxFileInfo::fileExists(sDir + "/status") && sProcID != "." && sProcID != "..") //Is it a process?
			{
				if (getProcName(stoi(sProcID)) == procName) //Check if it's the proc
				{
					closedir(dirData);
					return stoi(sProcID);
				}
			}
		}
	}

	closedir(dirData);
	return -1;
}

// Kills a PID
bool linuxProcInfo::killPID(unsigned int pid)
{
	std::string sCommand = "kill ";
	int iRet;

	sCommand += itos(pid);
	iRet = system(sCommand.c_str());

	return !iRet;
}

// ========================================================================
// Private Functions
// ========================================================================

// Converts an int to a str
std::string linuxProcInfo::itos(unsigned int iVar)
{
	std::ostringstream o;

	if (!(o << iVar))
	{
		printf("\n\033[1;31m[Internal Error]\033[0m\n");
		printf("Please send the following output to the developer...\n\n");
		printf("vr:     %i:%i:%i\n", verMajor, verMinor, verRevision);
		printf("int:    %i\n", iVar);
		printf("oxp:    lpiITOS\n");
	}

	return o.str();
}

// Converts a std::string to an int
int linuxProcInfo::stoi(std::string sVar)
{
	std::istringstream in(sVar);
	int out = 0;

	if (!(in >> out))
	{
		printf("\n\033[1;31m[Internal Error]\033[0m\n");
		printf("Please send the following output to the developer...\n\n");
		printf("vr:     %i:%i:%i\n", verMajor, verMinor, verRevision);
		printf("str:    %s\n", sVar.c_str());
		printf("oxp:    lpiSTOI\n");
	}

	return out;
}
