Get process betterGet shell somewhat working

This commit is contained in:
2025-06-26 17:19:51 -05:00
parent e4f75b69a6
commit 55408a3f1b
9 changed files with 349 additions and 48 deletions

View File

@ -19,6 +19,7 @@ src/Mail/Smtp.cpp
src/Serialization/Json.cpp src/Serialization/Json.cpp
src/Serialization/SQLite.cpp src/Serialization/SQLite.cpp
src/Platform/Environment.cpp src/Platform/Environment.cpp
src/Platform/Process.cpp
src/Streams/FileStream.cpp src/Streams/FileStream.cpp
src/Streams/MemoryStream.cpp src/Streams/MemoryStream.cpp
src/Streams/NetworkStream.cpp src/Streams/NetworkStream.cpp
@ -394,6 +395,9 @@ install(TARGETS tjsonunpretty DESTINATION bin)
add_executable(ttime apps/ttime.cpp) add_executable(ttime apps/ttime.cpp)
target_link_libraries(ttime PUBLIC tessesframework) target_link_libraries(ttime PUBLIC tessesframework)
install(TARGETS ttime DESTINATION bin) install(TARGETS ttime DESTINATION bin)
add_executable(tshell apps/tshell.cpp)
target_link_libraries(tshell PUBLIC tessesframework)
install(TARGETS tshell DESTINATION bin)
endif() endif()
include(InstallRequiredSystemLibraries) include(InstallRequiredSystemLibraries)

View File

@ -41,7 +41,8 @@
"cacheVariables": { "cacheVariables": {
"CMAKE_C_COMPILER": "cl.exe", "CMAKE_C_COMPILER": "cl.exe",
"CMAKE_CXX_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe",
"TESSESFRAMEWORK_FETCHCONTENT": true "TESSESFRAMEWORK_ENABLE_MBED": false,
"TESSESFRAMEWORK_FETCHCONTENT": false
}, },
"condition": { "condition": {
"type": "equals", "type": "equals",

127
apps/tshell.cpp Normal file
View File

@ -0,0 +1,127 @@
#include "TessesFramework/TessesFramework.hpp"
#include "TessesFramework/Platform/Process.hpp"
using namespace Tesses::Framework;
using namespace Tesses::Framework::Platform;
using namespace Tesses::Framework::TextStreams;
using namespace Tesses::Framework::Filesystem;
void split_command(std::string cmd, std::vector<std::string>& args)
{
bool inStr=false;
std::string cur={};
auto flush=[&]()->void {
if(cur.empty()) return;
args.push_back(cur);
cur={};
};
for(size_t i = 0; i < cmd.size(); i++)
{
if(inStr)
{
if(cmd[i] == '\"') inStr=false;
else if(cmd[i] == '\\')
{
i++;
if(i < cmd.size())
{
cmd.push_back(cmd[i]);
}
}
else cur.push_back(cmd[i]);
}
else
{
if(cmd[i] == ' ') flush();
else if(cmd[i] == '\"') {
inStr=true;
}
else {
cur.push_back(cmd[i]);
}
}
}
flush();
}
int main(int argc,char** argv)
{
TF_Init();
while(true)
{
std::cout << VFSPath::GetAbsoluteCurrentDirectory().ToString() << "$ ";
std::string text;
StdIn().ReadLine(text);
std::vector<std::string> args;
split_command(text,args);
if(args.empty()) continue;
if(args[0] == "exit") break;
else if(args[0] == "echo") { if(args.size() > 1) std::cout << args[1] << std::endl;}
else if(args[0] == "cd") {
if(args.size() < 2)
{
VFSPath::SetAbsoluteCurrentDirectory(Environment::SpecialFolders::GetHomeFolder());
}
else {
VFSPath::SetAbsoluteCurrentDirectory(args[1]);
}
}
else if(args[0] == "printargs")
{
for(size_t i = 1; i < args.size(); i++)
{
std::cout << "\"" << Http::HttpUtils::Replace(args[i],"\"","\\\"") << "\"" << std::endl;
}
}
else if (args[0] == "sigtermtest")
{
if (args.size() < 2) continue;
std::vector<std::string> args2(args.begin() + 1, args.end());
auto path = Environment::GetRealExecutablePath(args2[0]);
Platform::Process p(path.ToString(), args2);
if (p.Start())
{
std::cout << "Press enter to sigterm" << std::endl;
StdIn().ReadLine();
p.Kill(SIGTERM);
}
}
else if(args[0] == "rstdi")
{
if(args.size()<3) continue;
std::vector<std::string> args2(args.begin()+2,args.end());
auto f = LocalFS.OpenFile(args[1],"rb");
if(f != nullptr)
{
auto path = Environment::GetRealExecutablePath(args2[0]);
Platform::Process p(path.ToString(),args2);
p.redirectStdIn=true;
if(p.Start())
{
auto strm = p.GetStdinStream();
f->CopyTo(strm);
delete strm;
p.CloseStdInNow();
p.WaitForExit();
}
delete f;
}
}
else {
auto path = Environment::GetRealExecutablePath(args[0]);
Platform::Process p(path.ToString(),args);
if (p.Start())
p.WaitForExit();
else
std::cout << "Failed To Run Process: " << path.ToString() << std::endl;
}
}
TF_Quit();
}

View File

@ -1,12 +1,19 @@
#pragma once
#include <vector> #include <vector>
#include <string> #include <string>
#include "TessesFramework/Streams/Stream.hpp" #include "TessesFramework/Streams/Stream.hpp"
#include "TessesFramework/HiddenField.hpp" #include "TessesFramework/HiddenField.hpp"
#include <signal.h>
#if defined(_WIN32)
#define SIGKILL 9
#endif
namespace Tesses::Framework::Platform { namespace Tesses::Framework::Platform {
class Process { class Process {
private: private:
HiddenField hidden; HiddenField hidden;
bool exited = false;
int exitCode=0;
public: public:
std::string name; std::string name;
std::vector<std::string> args; std::vector<std::string> args;
@ -16,6 +23,8 @@ class Process {
bool redirectStdIn=false; bool redirectStdIn=false;
bool redirectStdOut=false; bool redirectStdOut=false;
bool redirectStdErr=false; bool redirectStdErr=false;
bool HasExited();
void CloseStdInNow(); void CloseStdInNow();
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT //YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT

View File

@ -35,6 +35,8 @@
#include "Serialization/Json.hpp" #include "Serialization/Json.hpp"
#include "Serialization/SQLite.hpp" #include "Serialization/SQLite.hpp"
#include "Platform/Environment.hpp" #include "Platform/Environment.hpp"
#include "Platform/Process.hpp"
#include "Text/StringConverter.hpp"
#include "SDL2/FontCache.hpp" #include "SDL2/FontCache.hpp"
#include "SDL2/Stream.hpp" #include "SDL2/Stream.hpp"
#include "SDL2/GUI.hpp" #include "SDL2/GUI.hpp"

View File

@ -208,6 +208,7 @@ namespace Tesses::Framework::Filesystem
} }
VFSPath VFSPath::MakeAbsolute(VFSPath curDir) VFSPath VFSPath::MakeAbsolute(VFSPath curDir)
{ {
if (!this->relative) return *this;
VFSPath p2 = curDir / *this; VFSPath p2 = curDir / *this;
return p2.CollapseRelativeParents(); return p2.CollapseRelativeParents();
} }

View File

@ -7,6 +7,7 @@
#include <windows.h> #include <windows.h>
#include "TessesFramework/Filesystem/VFSFix.hpp" #include "TessesFramework/Filesystem/VFSFix.hpp"
#include "TessesFramework/Text/StringConverter.hpp" #include "TessesFramework/Text/StringConverter.hpp"
using namespace Tesses::Framework::Text::StringConverter; using namespace Tesses::Framework::Text::StringConverter;
#endif #endif
#if !defined(_WIN32) #if !defined(_WIN32)
@ -120,8 +121,9 @@ namespace Tesses::Framework::Platform::Environment
VFSPath GetRealExecutablePath(VFSPath realPath) VFSPath GetRealExecutablePath(VFSPath realPath)
{ {
using namespace Tesses::Framework::Http; using namespace Tesses::Framework::Http;
if(!realPath.relative) return realPath.MakeAbsolute(); if(!realPath.relative) return realPath;
if(LocalFS.FileExists(realPath)) return realPath.MakeAbsolute(); if(LocalFS.FileExists(realPath)) return realPath.MakeAbsolute();
const char* path = std::getenv("PATH"); const char* path = std::getenv("PATH");
#if defined(_WIN32) #if defined(_WIN32)
@ -216,9 +218,9 @@ namespace Tesses::Framework::Platform::Environment
} }
FreeEnvironmentStringsW(environ0); FreeEnvironmentStringsW(environ0);
#else #else
for(char** envthing = environ; envthing != NULL; envthing++) for(char** envthing = environ; *envthing != NULL; envthing++)
{ {
//if(*envthing == NULL) break;
auto items = Http::HttpUtils::SplitString(*envthing,"=",2); auto items = Http::HttpUtils::SplitString(*envthing,"=",2);
if(items.size() == 2) if(items.size() == 2)
{ {

View File

@ -1,6 +1,7 @@
#include "TessesFramework/Platform/Process.hpp" #include "TessesFramework/Platform/Process.hpp"
#include "TessesFramework/Http/HttpUtils.hpp" #include "TessesFramework/Http/HttpUtils.hpp"
#include "TessesFramework/Platform/Environment.hpp" #include "TessesFramework/Platform/Environment.hpp"
#include <iostream>
#if defined(_WIN32) #if defined(_WIN32)
@ -8,7 +9,7 @@ extern "C" {
#include <windows.h> #include <windows.h>
} }
#include "TessesFramework/Filesystem/VFSFix.hpp" #include "TessesFramework/Filesystem/VFSFix.hpp"
#include 'TessesFramework/Text/StringConverter.hpp' #include "TessesFramework/Text/StringConverter.hpp"
using namespace Tesses::Framework::Text::StringConverter; using namespace Tesses::Framework::Text::StringConverter;
static void escape_windows_args(std::string& str, std::vector<std::string> args) static void escape_windows_args(std::string& str, std::vector<std::string> args)
{ {
@ -38,7 +39,6 @@ static void escape_windows_args(std::string& str, std::vector<std::string> args)
#else #else
#include <unistd.h> #include <unistd.h>
#include <signal.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -48,16 +48,30 @@ static void escape_windows_args(std::string& str, std::vector<std::string> args)
namespace Tesses::Framework::Platform { namespace Tesses::Framework::Platform {
class ProcessData { class ProcessData : public HiddenFieldData {
public: public:
//TODO: Implement for WIN32 //TODO: Implement for WIN32
#if defined(_WIN32) #if defined(_WIN32)
STARTUPINFO si; STARTUPINFOW si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
HANDLE stdin_strm; HANDLE stdin_strm;
HANDLE stdout_strm; HANDLE stdout_strm;
HANDLE stderr_strm; HANDLE stderr_strm;
static int __stdcall KillGraceFully(HWND hndle, LPARAM arg)
{
auto pd=static_cast<ProcessData*>((void*)arg);
DWORD curProc;
GetWindowThreadProcessId(hndle, &curProc);
if (curProc == pd->pi.dwProcessId)
{
PostMessage(hndle, WM_CLOSE, 0, 0);
return true;
}
return false;
}
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
@ -67,6 +81,8 @@ namespace Tesses::Framework::Platform {
int stderr_strm; int stderr_strm;
pid_t pid; pid_t pid;
#endif #endif
ProcessData() { ProcessData() {
//TODO: Implement for WIN32 //TODO: Implement for WIN32
#if defined(_WIN32) #if defined(_WIN32)
@ -90,7 +106,7 @@ namespace Tesses::Framework::Platform {
HANDLE strm; HANDLE strm;
bool writing; bool writing;
bool eos; bool eos;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else #else
int strm; int strm;
@ -105,7 +121,7 @@ namespace Tesses::Framework::Platform {
this->writing = writing; this->writing = writing;
this->eos = false; this->eos = false;
} }
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else #else
ProcessStream(int strm, bool writing) ProcessStream(int strm, bool writing)
{ {
@ -119,7 +135,7 @@ namespace Tesses::Framework::Platform {
//TODO: Implement for WIN32 //TODO: Implement for WIN32
#if defined(_WIN32) #if defined(_WIN32)
return this->strm == NULL || eos; return this->strm == NULL || eos;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return true; return true;
#else #else
return this->strm < 0 || eos; return this->strm < 0 || eos;
@ -130,7 +146,7 @@ namespace Tesses::Framework::Platform {
//TODO: Implement for WIN32 //TODO: Implement for WIN32
#if defined(_WIN32) #if defined(_WIN32)
return !writing && this->strm != NULL; return !writing && this->strm != NULL;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return false; return false;
#else #else
return !writing && this->strm > -1; return !writing && this->strm > -1;
@ -142,7 +158,7 @@ namespace Tesses::Framework::Platform {
#if defined(_WIN32) #if defined(_WIN32)
return writing && this->strm != NULL; return writing && this->strm != NULL;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return false; return false;
#else #else
return writing && this->strm > -1; return writing && this->strm > -1;
@ -161,8 +177,8 @@ namespace Tesses::Framework::Platform {
if (dataR == 0) { if (dataR == 0) {
this->eos = true; this->eos = true;
} }
return (size_t)dataW; return (size_t)dataR;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return 0; return 0;
#else #else
if(this->strm < 0 || this->eos && writing) return 0; if(this->strm < 0 || this->eos && writing) return 0;
@ -184,7 +200,7 @@ namespace Tesses::Framework::Platform {
return 0; return 0;
return (size_t)dataW; return (size_t)dataW;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return 0; return 0;
#else #else
if(this->strm < 0 || !writing) return 0; if(this->strm < 0 || !writing) return 0;
@ -213,6 +229,31 @@ namespace Tesses::Framework::Platform {
this->includeThisEnv = includeThisEnv; this->includeThisEnv = includeThisEnv;
this->hidden.AllocField<ProcessData>(); this->hidden.AllocField<ProcessData>();
} }
bool Process::HasExited()
{
if (this->exited) return true;
ProcessData* p = this->hidden.GetField<ProcessData*>();
#if defined(_WIN32)
if (WaitForSingleObject(p->pi.hProcess, 0) == WAIT_OBJECT_0)
{
DWORD ec = 0;
GetExitCodeProcess(p->pi.hProcess,&ec);
this->exitCode = (int)ec;
this->exited = true;
return true;
}
#else
int r;
if (waitpid(this->hidden.GetField<ProcessData*>()->pid, &r, WNOHANG) != -1)
{
this->exited = true;
this->exitCode = r;
return r;
}
#endif
return false;
}
Process::Process(std::string name, std::vector<std::string> args, std::vector<std::string> env,bool includeThisEnv) : Process(name,args,std::vector<std::pair<std::string,std::string>>(),includeThisEnv) Process::Process(std::string name, std::vector<std::string> args, std::vector<std::string> env,bool includeThisEnv) : Process(name,args,std::vector<std::pair<std::string,std::string>>(),includeThisEnv)
{ {
this->env.resize(env.size()); this->env.resize(env.size());
@ -232,11 +273,35 @@ namespace Tesses::Framework::Platform {
} }
} }
} }
void Process::CloseStdInNow()
{
ProcessData* p = this->hidden.GetField<ProcessData*>();
#if defined(_WIN32)
if (p->stdin_strm != NULL)
{
CloseHandle(p->stdin_strm);
p->stdin_strm = NULL;
}
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else
if (p->stdin_strm > -1)
{
close(p->stdin_strm);
p->stdin_strm = -1;
}
#endif
}
Process::~Process() Process::~Process()
{ {
ProcessData* p = this->hidden.GetField<ProcessData*>(); ProcessData* p = this->hidden.GetField<ProcessData*>();
#if defined(_WIN32) #if defined(_WIN32)
if(!this->exited)
Kill(SIGTERM);
if (p->stdin_strm != NULL) if (p->stdin_strm != NULL)
CloseHandle(p->stdin_strm); CloseHandle(p->stdin_strm);
@ -245,9 +310,25 @@ namespace Tesses::Framework::Platform {
if (p->stderr_strm != NULL) if (p->stderr_strm != NULL)
CloseHandle(p->stderr_strm); CloseHandle(p->stderr_strm);
CloseHandle(p->pi.hProcess); CloseHandle(p->pi.hProcess);
CloseHandle(p->pi.hThread); CloseHandle(p->pi.hThread);
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else
if (!this->exited)
{
Kill(SIGTERM);
WaitForExit();
}
if (p->stdin_strm != -1)
close(p->stdin_strm);
if (p->stdout_strm != -1)
close(p->stdout_strm);
if (p->stderr_strm != -1)
close(p->stderr_strm);
#endif #endif
} }
@ -258,7 +339,7 @@ namespace Tesses::Framework::Platform {
ProcessData* p = ProcessData* p =
this->hidden.GetField<ProcessData*>(); this->hidden.GetField<ProcessData*>();
std::vector<std::pair<std::string,std::string>> envs; std::vector<std::pair<std::string,std::string>> envs;
if(this->includeThisEnv) if(this->includeThisEnv)
Environment::GetEnvironmentVariables(envs); Environment::GetEnvironmentVariables(envs);
@ -269,6 +350,7 @@ namespace Tesses::Framework::Platform {
{ {
if(item.first == itemNew.first) if(item.first == itemNew.first)
{ {
item.second = itemNew.second; item.second = itemNew.second;
has=true; has=true;
break; break;
@ -278,6 +360,11 @@ namespace Tesses::Framework::Platform {
} }
#if defined(_WIN32) #if defined(_WIN32)
ZeroMemory(&p->si, sizeof(p->si));
p->si.cb = sizeof(p->si);
ZeroMemory(&p->pi, sizeof(p->pi));
std::u16string u16_name; std::u16string u16_name;
std::u16string u16_args; std::u16string u16_args;
std::string args; std::string args;
@ -306,66 +393,89 @@ namespace Tesses::Framework::Platform {
attr.nLength = sizeof(attr); attr.nLength = sizeof(attr);
attr.lpSecurityDescriptor = NULL; attr.lpSecurityDescriptor = NULL;
attr.bInheritHandle = true; attr.bInheritHandle = true;
p->si->hStdInput = NULL; p->si.hStdInput = NULL;
p->si->hStdOutput = NULL; p->si.hStdOutput = NULL;
p->si->hStdError = NULL; p->si.hStdError = NULL;
p->stdin_strm = NULL; p->stdin_strm = NULL;
p->stdout_strm = NULL; p->stdout_strm = NULL;
p->stderr_strm = NULL; p->stderr_strm = NULL;
if (this->redirectStdIn || this->redirectStdOut || this->redirectStdErr)
{
p->si.dwFlags |= STARTF_USESTDHANDLES;
if (!this->redirectStdIn)
{
p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
}
if (!this->redirectStdOut)
{
p->si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
}
if (!this->redirectStdOut)
{
p->si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
}
}
if (this->redirectStdIn) if (this->redirectStdIn)
{ {
if (!CreatePipe(&p->si->hStdInput, &p->stdin_strm, &attr,0)) return false; if (!CreatePipe(&p->si.hStdInput, &p->stdin_strm, &attr,0)) return false;
SetHandleInformation(p->stdin_strm, HANDLE_FLAG_INHERIT, 0);
} }
if (this->redirectStdOut) if (this->redirectStdOut)
{ {
if (!CreatePipe(&p->stdout_strm, &p->si->hStdOutput, &attr, 0)) if (!CreatePipe(&p->stdout_strm, &p->si.hStdOutput, &attr, 0))
{ {
if (this->redirectStdIn) if (this->redirectStdIn)
{ {
CloseHandle(p->stdin_strm); CloseHandle(p->stdin_strm);
CloseHandle(p->si->hStdInput); CloseHandle(p->si.hStdInput);
} }
return false; return false;
} }
SetHandleInformation(p->stdout_strm, HANDLE_FLAG_INHERIT, 0);
} }
if (this->redirectStdErr) if (this->redirectStdErr)
{ {
if (!CreatePipe(&p->stderr_strm, &p->si->hStdError, &attr, 0)) if (!CreatePipe(&p->stderr_strm, &p->si.hStdError, &attr, 0))
{ {
if (this->redirectStdIn) if (this->redirectStdIn)
{ {
CloseHandle(p->stdin_strm); CloseHandle(p->stdin_strm);
CloseHandle(p->si->hStdInput); CloseHandle(p->si.hStdInput);
} }
if (this->redirectStdOut) if (this->redirectStdOut)
{ {
CloseHandle(p->stdout_strm); CloseHandle(p->stdout_strm);
CloseHandle(p->si->hStdOutput); CloseHandle(p->si.hStdOutput);
} }
return false; return false;
} }
SetHandleInformation(p->stderr_strm, HANDLE_FLAG_INHERIT, 0);
} }
if (!CreateProcessW(u16_name.c_str(), u16_args.data(), NULL, NULL, (this->redirectStdIn || this->redirectStdOut || this->redirectStdErr), CREATE_UNICODE_ENVIRONMENT, (LPCWSTR)env.c_str(), workDir.empty() ? (LPCWSTR)NULL : (LPCWSTR)workDir.c_str(), &(p->si), &(p->pi))) if (!CreateProcessW((LPCWSTR)u16_name.c_str(), (LPWSTR)u16_args.data(), NULL, NULL, (this->redirectStdIn || this->redirectStdOut || this->redirectStdErr), CREATE_UNICODE_ENVIRONMENT, (LPVOID)env.c_str(), workDir.empty() ? (LPCWSTR)NULL : (LPCWSTR)workDir.c_str(), &(p->si), &(p->pi)))
{ {
if (this->redirectStdIn) if (this->redirectStdIn)
{ {
CloseHandle(p->stdin_strm); CloseHandle(p->stdin_strm);
CloseHandle(p->si->hStdInput); CloseHandle(p->si.hStdInput);
} }
if (this->redirectStdOut) if (this->redirectStdOut)
{ {
CloseHandle(p->stdout_strm); CloseHandle(p->stdout_strm);
CloseHandle(p->si->hStdOutput); CloseHandle(p->si.hStdOutput);
} }
if (this->redirectStdErr) if (this->redirectStdErr)
{ {
CloseHandle(p->stderr_strm); CloseHandle(p->stderr_strm);
CloseHandle(p->si->hStdError); CloseHandle(p->si.hStdError);
} }
return false; return false;
} }
@ -386,8 +496,8 @@ CreateProcessW(
_Out_ LPPROCESS_INFORMATION lpProcessInformation _Out_ LPPROCESS_INFORMATION lpProcessInformation
); );
*/ */
return false; return true;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return false; return false;
#else #else
@ -460,6 +570,7 @@ CreateProcessW(
std::vector<std::string> env2; std::vector<std::string> env2;
env2.resize(envs.size()); env2.resize(envs.size());
for(size_t i = 0; i < envs.size(); i++) for(size_t i = 0; i < envs.size(); i++)
{ {
env2[i] = envs[i].first + "=" + envs[i].second; env2[i] = envs[i].first + "=" + envs[i].second;
@ -468,13 +579,13 @@ CreateProcessW(
char** argv = new char*[args.size()+1]; char** argv = new char*[args.size()+1];
argv[args.size()]=NULL; argv[args.size()]=NULL;
char** envp = new char*[env2.size()+1]; char** envp = new char*[env2.size()+1];
envp[env.size()]=NULL; envp[env2.size()]=NULL;
for(size_t i = 0; i < args.size();i++) for(size_t i = 0; i < args.size();i++)
{ {
argv[i] = (char*)args[i].c_str(); argv[i] = (char*)args[i].c_str();
} }
for(size_t i = 0; i < env.size();i++) for(size_t i = 0; i < env2.size();i++)
{ {
envp[i] = (char*)env2[i].c_str(); envp[i] = (char*)env2[i].c_str();
} }
@ -512,10 +623,31 @@ CreateProcessW(
#endif #endif
} }
void Process::Kill(int signal) void Process::Kill(int signal)
{ {
#if defined(_WIN32) #if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) if (signal != SIGKILL && signal != SIGTERM) std::cout << "WARN: We terminated the process" << std::endl;
if (signal == SIGTERM)
{
auto win = this->hidden.GetField<ProcessData*>();
if (EnumWindows(ProcessData::KillGraceFully, (LPARAM)(void*)win))
{
if (WaitForSingleObject(win->pi.hProcess, 60000) != WAIT_OBJECT_0)
{
PostThreadMessage(win->pi.dwThreadId, WM_QUIT, 0, 0);
}
}
else {
PostThreadMessage(win->pi.dwThreadId, WM_QUIT, 0, 0);
}
}
else
TerminateProcess(this->hidden.GetField<ProcessData*>()->pi.hProcess,-1);
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else #else
kill(this->hidden.GetField<ProcessData*>()->pid,signal); kill(this->hidden.GetField<ProcessData*>()->pid,signal);
#endif #endif
@ -523,22 +655,34 @@ CreateProcessW(
int Process::WaitForExit() int Process::WaitForExit()
{ {
if (this->exited) return this->exitCode;
#if defined(_WIN32) #if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) auto p = this->hidden.GetField<ProcessData*>();
reutnr -1; WaitForSingleObject(p->pi.hProcess, INFINITE);
DWORD ret=0;
GetExitCodeProcess(p->pi.hThread, &ret);
this->exitCode = (int)ret;
this->exited = true;
return (int)ret;
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return -1;
#else #else
int r; int r;
if(waitpid(this->hidden.GetField<ProcessData*>()->pid,&r,0) != -1) if (waitpid(this->hidden.GetField<ProcessData*>()->pid, &r, 0) != -1)
{
this->exited = true;
this->exitCode = r;
return r; return r;
}
return -1; return -1;
#endif #endif
} }
Tesses::Framework::Streams::Stream* Process::GetStdinStream() Tesses::Framework::Streams::Stream* Process::GetStdinStream()
{ {
#if defined(_WIN32) if (this->exited) return nullptr;
return nullptr; #if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return nullptr; return nullptr;
#else #else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true); return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true);
@ -546,9 +690,9 @@ CreateProcessW(
} }
Tesses::Framework::Streams::Stream* Process::GetStdoutStream() Tesses::Framework::Streams::Stream* Process::GetStdoutStream()
{ {
#if defined(_WIN32)
return nullptr; if (this->exited) return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return nullptr; return nullptr;
#else #else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false); return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false);
@ -556,9 +700,9 @@ CreateProcessW(
} }
Tesses::Framework::Streams::Stream* Process::GetStderrStream() Tesses::Framework::Streams::Stream* Process::GetStderrStream()
{ {
#if defined(_WIN32)
return nullptr; if (this->exited) return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) #if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return nullptr; return nullptr;
#else #else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false); return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false);

View File

@ -132,6 +132,14 @@ namespace Tesses::Framework
} }
#endif #endif
#if defined(_WIN32)
MSG winMSG;
if (PeekMessage(&winMSG, NULL, WM_QUIT, WM_QUIT, 1))
{
isRunning = false;
}
#endif
#if defined(TESSESFRAMEWORK_ENABLE_SDL2) #if defined(TESSESFRAMEWORK_ENABLE_SDL2)
Tesses::Framework::SDL2::gui.Update(); Tesses::Framework::SDL2::gui.Update();
@ -182,6 +190,8 @@ namespace Tesses::Framework
tzset(); tzset();
#if defined(_WIN32) #if defined(_WIN32)
system(" "); system(" ");
signal(SIGINT, _sigInt);
signal(SIGTERM, _sigInt);
#endif #endif
isRunning=true; isRunning=true;
@ -214,6 +224,7 @@ if (iResult != 0) {
#else #else
signal(SIGPIPE,SIG_IGN); signal(SIGPIPE,SIG_IGN);
signal(SIGINT,_sigInt); signal(SIGINT,_sigInt);
signal(SIGTERM, _sigInt);
#endif #endif
} }