mirror of https://github.com/layters/testshop
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
8.5 KiB
264 lines
8.5 KiB
#include "process.hpp"
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#ifdef __gnu_linux__
|
|
#include <unistd.h> // fork, execvp
|
|
//#include <sys/types.h> // ?
|
|
#include <dirent.h> // closedir, opendir
|
|
#include <signal.h> // kill
|
|
#endif
|
|
|
|
#include <fstream>
|
|
|
|
#include "logger.hpp"
|
|
#include "filesystem.hpp" // neroshop::filesystem
|
|
#include "string.hpp"
|
|
|
|
neroshop::Process::Process()
|
|
{
|
|
#ifdef __gnu_linux__
|
|
handle = -1; // default
|
|
#endif
|
|
}
|
|
////////////////////
|
|
neroshop::Process::Process(const std::string& program, const std::string& arg) : Process()
|
|
{
|
|
if(!create(program, arg)) {
|
|
neroshop::print("Process creation failed", 1);
|
|
}
|
|
}
|
|
////////////////////
|
|
neroshop::Process::~Process()
|
|
{
|
|
#ifdef __gnu_linux__
|
|
#ifdef DOKUN_DEBUG0
|
|
std::cout << DOKUN_UI_TAG "process (" << name << ") has been deallocated" << std::endl;
|
|
#endif
|
|
#endif
|
|
terminate(); // kill pid
|
|
}
|
|
////////////////////
|
|
std::vector<std::tuple<std::string, int, bool>> neroshop::Process::process_list({});
|
|
////////////////////
|
|
void * neroshop::Process::open()
|
|
{
|
|
#ifdef _WIN32
|
|
this->handle = static_cast<void *>(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()));
|
|
return this->handle;
|
|
#endif
|
|
#ifdef __gnu_linux__
|
|
#endif
|
|
return nullptr;
|
|
}
|
|
////////////////////
|
|
bool neroshop::Process::create(const std::string& program, const std::string& argument)
|
|
{
|
|
#ifdef _WIN32
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ZeroMemory (&si, sizeof(si));
|
|
si.cb = sizeof (si);
|
|
ZeroMemory (&pi, sizeof(pi));
|
|
// static_cast<LPSTR>(const_cast<char *>(program.c_str()))
|
|
std::string cmd = program + argument;
|
|
// Start the child process.
|
|
if(CreateProcess(
|
|
NULL,//static_cast<LPCTSTR>("glue.exe"), // No module name (use command line)
|
|
static_cast<LPSTR>(const_cast<char *>(cmd.c_str())),//static_cast<LPCTSTR>("glue.exe srlua.exe main.lua main.exe"), // Command line
|
|
NULL, // Process handle not inheritable
|
|
NULL, // Thread handle not inheritable
|
|
FALSE, // Set handle inheritance to FALSE
|
|
CREATE_NEW_CONSOLE, // No creation flags
|
|
NULL, // Use parent's environment block
|
|
NULL, // Use parent's starting directory
|
|
&si, // Pointer to STARTUPINFO structure
|
|
&pi ) // Pointer to PROCESS_INFORMATION structure
|
|
== 0)
|
|
{
|
|
return false;
|
|
}
|
|
// Wait until child process exits.
|
|
WaitForSingleObject (pi.hProcess, INFINITE);
|
|
// Close process and thread handles.
|
|
CloseHandle (pi.hProcess);
|
|
CloseHandle (pi.hThread );
|
|
#endif
|
|
#ifdef __gnu_linux__
|
|
pid_t child_pid = fork (); // holds the process id (pid)
|
|
if (child_pid != 0) {
|
|
// the handle is basically the process id (pid)
|
|
this->handle = static_cast<pid_t>(child_pid);
|
|
this->name = program.substr(program.find_last_of("\\/") + 1);//program;
|
|
// store process information in "process_list"
|
|
process_list.push_back(std::make_tuple(program, child_pid, (child_pid != -1)));
|
|
}
|
|
else {
|
|
std::vector<std::string> arg_split = neroshop::string::split(argument, " ");
|
|
char * arg_list[arg_split.size()];
|
|
for(int i = 0; i < arg_split.size(); i++)
|
|
{
|
|
arg_list[i] = static_cast<char *>(const_cast<char *>(arg_split[i].c_str()));
|
|
//std::cout << arg_list[i] << std::endl;
|
|
}
|
|
arg_list[arg_split.size()] = nullptr; // arg_list must end with a nullptr
|
|
/* Now execute PROGRAM, searching for it in the path. */
|
|
execvp (static_cast<char *>(const_cast<char *>(program.c_str())), arg_list);
|
|
/* The execvp function returns only if an error occurs. */
|
|
fprintf (stderr, "an error occurred in execvp\n");
|
|
abort ();
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
////////////////////
|
|
bool neroshop::Process::terminate()
|
|
{
|
|
#ifdef _WIN32
|
|
return (TerminateProcess(static_cast<HANDLE>(this->handle), 0) != 0);
|
|
#endif
|
|
#ifdef __gnu_linux__
|
|
if(handle == -1) return true; // if pid has already been killed then no need to kill it again, so exit function
|
|
// kill function doesn't even work -.-
|
|
if(kill(static_cast<pid_t>(handle), SIGKILL) != 0) {// 0=success, -1=failure // #include <signal.h>
|
|
std::cout << "FAILED to kill process: " << handle << std::endl;
|
|
return false;
|
|
}
|
|
// just to be sure process has been killed
|
|
// this doesn't work either LOL
|
|
//std::system(std::string("kill " + std::to_string(handle)).c_str());
|
|
handle = -1;// set handle to default value so we know its been properly deleted
|
|
////std::cout << DOKUN_UI_TAG "process (" << name << ") terminated\n";
|
|
return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
////////////////////
|
|
bool neroshop::Process::terminate(const Process& process)
|
|
{
|
|
#ifdef _WIN32
|
|
return (TerminateProcess(static_cast<HANDLE>(process.get_handle()), 0) != 0);
|
|
#endif
|
|
#ifdef __gnu_linux__
|
|
// kill function doesn't even work -.-
|
|
return const_cast<Process&>(process).terminate();//return (kill(static_cast<pid_t>(process.get_handle()), SIGTERM) != -1); //0=success, -1=failure// #include <signal.h>
|
|
#endif
|
|
return false;
|
|
}
|
|
////////////////////
|
|
void neroshop::Process::terminate_by_process_id(int process_id) {
|
|
#ifdef __gnu_linux__
|
|
while(process_id != -1) {
|
|
if(kill(static_cast<pid_t>(process_id), SIGTERM) < 0) // kill all instances of this process
|
|
std::cout << "FAILED to kill process " << process_id << std::endl;
|
|
}
|
|
#endif
|
|
}
|
|
////////////////////
|
|
void neroshop::Process::terminate_by_process_name(const std::string& process_name) {
|
|
#ifdef __gnu_linux__
|
|
while(neroshop::Process::get_process_by_name(process_name) != -1) {// while this process is still running
|
|
if(kill(static_cast<pid_t>(neroshop::Process::get_process_by_name(process_name)), SIGTERM) < 0) // kill all instances of this process
|
|
std::cout << "FAILED to kill process " << process_name << std::endl;
|
|
}
|
|
#endif
|
|
}
|
|
////////////////////
|
|
void neroshop::Process::exit(int code)
|
|
{
|
|
#ifdef _WIN32
|
|
ExitProcess(code);
|
|
#endif
|
|
#ifdef __gnu_linux__
|
|
#endif
|
|
}
|
|
////////////////////
|
|
////////////////////
|
|
////////////////////
|
|
////////////////////
|
|
void neroshop::Process::show_processes(void) { // displays all processes from current session
|
|
for(int i = 0; i < process_list.size(); i++) {
|
|
std::cout
|
|
<< "\033[1;35;49mprocess[" << i << "] ("
|
|
<< "name: " << std::get<0>(process_list[i]) << ", "
|
|
<< "id: " << std::get<1>(process_list[i]) << ", "
|
|
<< "status: " << std::get<2>(process_list[i])
|
|
<< ")\033[0m"
|
|
<< std::endl;
|
|
}
|
|
}
|
|
////////////////////
|
|
////////////////////
|
|
////////////////////
|
|
////////////////////
|
|
#ifdef _WIN32
|
|
void * neroshop::Process::get_handle() const
|
|
{
|
|
return this->handle;
|
|
}
|
|
#endif
|
|
////////////////////
|
|
#ifdef __gnu_linux__
|
|
int neroshop::Process::get_handle() const
|
|
{
|
|
return handle;
|
|
}
|
|
////////////////////
|
|
std::string neroshop::Process::get_name() const {
|
|
return name;
|
|
}
|
|
////////////////////
|
|
int neroshop::Process::get_process_by_name(const std::string& process_name) { // UPDATE(2022-02-05): this doesn't work as well as I expected it to :/
|
|
int pid = -1;
|
|
// Open the /proc directory
|
|
DIR *dp = opendir("/proc");
|
|
if (dp != NULL)
|
|
{
|
|
// Enumerate all entries in directory until process found
|
|
struct dirent *dirp;
|
|
while (pid < 0 && (dirp = readdir(dp)))
|
|
{
|
|
// Skip non-numeric entries
|
|
int id = atoi(dirp->d_name);
|
|
if (id > 0)
|
|
{
|
|
// Read contents of virtual /proc/{pid}/cmdline file
|
|
std::string cmdPath = std::string("/proc/") + dirp->d_name + "/cmdline";
|
|
std::ifstream cmdFile(cmdPath.c_str());
|
|
std::string cmdLine;
|
|
std::getline(cmdFile, cmdLine);
|
|
if (!cmdLine.empty())
|
|
{
|
|
// Keep first cmdline item which contains the program path
|
|
size_t pos = cmdLine.find('\0');
|
|
if (pos != std::string::npos)
|
|
cmdLine = cmdLine.substr(0, pos);
|
|
// Keep program name only, removing the path
|
|
pos = cmdLine.rfind('/');
|
|
if (pos != std::string::npos)
|
|
cmdLine = cmdLine.substr(pos + 1);
|
|
// Compare against requested process name
|
|
if (process_name == cmdLine)
|
|
pid = id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
closedir(dp);
|
|
return pid;
|
|
}
|
|
#endif
|
|
////////////////////
|
|
void * neroshop::Process::get_active()
|
|
{
|
|
#ifdef _WIN32
|
|
return static_cast<void *>(GetCurrentProcess());
|
|
#endif
|
|
#ifdef __gnu_linux__
|
|
#endif
|
|
return nullptr;
|
|
}
|