From 3877c1391dce4bda0dae9adadd103f692559e38b Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Thu, 26 Jun 2025 17:19:51 -0500 Subject: [PATCH] Get shell somewhat working --- CMakeLists.txt | 4 + apps/tshell.cpp | 111 +++++++++++++++++++ include/TessesFramework/Platform/Process.hpp | 1 + include/TessesFramework/TessesFramework.hpp | 4 +- src/Platform/Environment.cpp | 4 +- src/Platform/Process.cpp | 63 ++++++----- 6 files changed, 159 insertions(+), 28 deletions(-) create mode 100644 apps/tshell.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 17ea5f7..32dbf13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ src/Mail/Smtp.cpp src/Serialization/Json.cpp src/Serialization/SQLite.cpp src/Platform/Environment.cpp +src/Platform/Process.cpp src/Streams/FileStream.cpp src/Streams/MemoryStream.cpp src/Streams/NetworkStream.cpp @@ -394,6 +395,9 @@ install(TARGETS tjsonunpretty DESTINATION bin) add_executable(ttime apps/ttime.cpp) target_link_libraries(ttime PUBLIC tessesframework) install(TARGETS ttime DESTINATION bin) +add_executable(tshell apps/tshell.cpp) +target_link_libraries(tshell PUBLIC tessesframework) +install(TARGETS tshell DESTINATION bin) endif() include(InstallRequiredSystemLibraries) diff --git a/apps/tshell.cpp b/apps/tshell.cpp new file mode 100644 index 0000000..d5ec2fd --- /dev/null +++ b/apps/tshell.cpp @@ -0,0 +1,111 @@ +#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& 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 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] == "rstdi") + { + if(args.size()<3) continue; + std::vector 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); + p.Start(); + p.WaitForExit(); + } + } + + TF_Quit(); +} \ No newline at end of file diff --git a/include/TessesFramework/Platform/Process.hpp b/include/TessesFramework/Platform/Process.hpp index 3915656..7dc154d 100644 --- a/include/TessesFramework/Platform/Process.hpp +++ b/include/TessesFramework/Platform/Process.hpp @@ -1,3 +1,4 @@ +#pragma once #include #include #include "TessesFramework/Streams/Stream.hpp" diff --git a/include/TessesFramework/TessesFramework.hpp b/include/TessesFramework/TessesFramework.hpp index c626c5d..31bbf38 100644 --- a/include/TessesFramework/TessesFramework.hpp +++ b/include/TessesFramework/TessesFramework.hpp @@ -35,6 +35,8 @@ #include "Serialization/Json.hpp" #include "Serialization/SQLite.hpp" #include "Platform/Environment.hpp" +#include "Platform/Process.hpp" +#include "Text/StringConverter.hpp" #include "SDL2/FontCache.hpp" #include "SDL2/Stream.hpp" -#include "SDL2/GUI.hpp" \ No newline at end of file +#include "SDL2/GUI.hpp" diff --git a/src/Platform/Environment.cpp b/src/Platform/Environment.cpp index ebe4108..a662006 100644 --- a/src/Platform/Environment.cpp +++ b/src/Platform/Environment.cpp @@ -216,9 +216,9 @@ namespace Tesses::Framework::Platform::Environment } FreeEnvironmentStringsW(environ0); #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); if(items.size() == 2) { diff --git a/src/Platform/Process.cpp b/src/Platform/Process.cpp index 9021dc9..ca9eab9 100644 --- a/src/Platform/Process.cpp +++ b/src/Platform/Process.cpp @@ -1,7 +1,7 @@ #include "TessesFramework/Platform/Process.hpp" #include "TessesFramework/Http/HttpUtils.hpp" #include "TessesFramework/Platform/Environment.hpp" - +#include #if defined(_WIN32) extern "C" { @@ -48,7 +48,7 @@ static void escape_windows_args(std::string& str, std::vector args) namespace Tesses::Framework::Platform { - class ProcessData { + class ProcessData : public HiddenFieldData { public: //TODO: Implement for WIN32 #if defined(_WIN32) @@ -90,7 +90,7 @@ namespace Tesses::Framework::Platform { HANDLE strm; bool writing; bool eos; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) #else int strm; @@ -105,7 +105,7 @@ namespace Tesses::Framework::Platform { this->writing = writing; this->eos = false; } - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) #else ProcessStream(int strm, bool writing) { @@ -119,7 +119,7 @@ namespace Tesses::Framework::Platform { //TODO: Implement for WIN32 #if defined(_WIN32) return this->strm == NULL || eos; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return true; #else return this->strm < 0 || eos; @@ -130,7 +130,7 @@ namespace Tesses::Framework::Platform { //TODO: Implement for WIN32 #if defined(_WIN32) return !writing && this->strm != NULL; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return false; #else return !writing && this->strm > -1; @@ -142,7 +142,7 @@ namespace Tesses::Framework::Platform { #if defined(_WIN32) return writing && this->strm != NULL; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return false; #else return writing && this->strm > -1; @@ -162,7 +162,7 @@ namespace Tesses::Framework::Platform { this->eos = true; } return (size_t)dataW; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return 0; #else if(this->strm < 0 || this->eos && writing) return 0; @@ -184,7 +184,7 @@ namespace Tesses::Framework::Platform { return 0; return (size_t)dataW; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return 0; #else if(this->strm < 0 || !writing) return 0; @@ -232,6 +232,21 @@ namespace Tesses::Framework::Platform { } } } + void Process::CloseStdInNow() + { + ProcessData* p = this->hidden.GetField(); + + #if defined(_WIN32) + if (p->stdin_strm != NULL) + CloseHandle(p->stdin_strm); + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) + + #else + if(p->stdin_strm > -1) + close(p->stdin_strm); + #endif + + } Process::~Process() { ProcessData* p = this->hidden.GetField(); @@ -258,7 +273,7 @@ namespace Tesses::Framework::Platform { ProcessData* p = this->hidden.GetField(); std::vector> envs; - + if(this->includeThisEnv) Environment::GetEnvironmentVariables(envs); @@ -269,6 +284,7 @@ namespace Tesses::Framework::Platform { { if(item.first == itemNew.first) { + item.second = itemNew.second; has=true; break; @@ -387,7 +403,7 @@ CreateProcessW( ); */ return false; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return false; #else @@ -460,6 +476,7 @@ CreateProcessW( std::vector env2; env2.resize(envs.size()); + for(size_t i = 0; i < envs.size(); i++) { env2[i] = envs[i].first + "=" + envs[i].second; @@ -468,13 +485,13 @@ CreateProcessW( char** argv = new char*[args.size()+1]; argv[args.size()]=NULL; char** envp = new char*[env2.size()+1]; - envp[env.size()]=NULL; + envp[env2.size()]=NULL; for(size_t i = 0; i < args.size();i++) { 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(); } @@ -515,7 +532,7 @@ CreateProcessW( void Process::Kill(int signal) { #if defined(_WIN32) - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) #else kill(this->hidden.GetField()->pid,signal); #endif @@ -524,8 +541,10 @@ CreateProcessW( int Process::WaitForExit() { #if defined(_WIN32) - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) - reutnr -1; + auto p = this->hidden.GetField(); + //WaitForSingleObject(this->p) + #elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) + return -1; #else int r; if(waitpid(this->hidden.GetField()->pid,&r,0) != -1) @@ -536,9 +555,7 @@ CreateProcessW( Tesses::Framework::Streams::Stream* Process::GetStdinStream() { - #if defined(_WIN32) - return nullptr; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return nullptr; #else return new ProcessStream(this->hidden.GetField()->stdin_strm,true); @@ -546,9 +563,7 @@ CreateProcessW( } Tesses::Framework::Streams::Stream* Process::GetStdoutStream() { - #if defined(_WIN32) - return nullptr; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return nullptr; #else return new ProcessStream(this->hidden.GetField()->stdout_strm,false); @@ -556,9 +571,7 @@ CreateProcessW( } Tesses::Framework::Streams::Stream* Process::GetStderrStream() { - #if defined(_WIN32) - return nullptr; - #elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__) + #if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) return nullptr; #else return new ProcessStream(this->hidden.GetField()->stderr_strm,false);