Get shell somewhat working

This commit is contained in:
2025-06-26 17:19:51 -05:00
parent e4f75b69a6
commit 3877c1391d
6 changed files with 159 additions and 28 deletions

View File

@ -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)

111
apps/tshell.cpp Normal file
View File

@ -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<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] == "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);
p.Start();
p.WaitForExit();
}
}
TF_Quit();
}

View File

@ -1,3 +1,4 @@
#pragma once
#include <vector>
#include <string>
#include "TessesFramework/Streams/Stream.hpp"

View File

@ -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"
#include "SDL2/GUI.hpp"

View File

@ -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)
{

View File

@ -1,7 +1,7 @@
#include "TessesFramework/Platform/Process.hpp"
#include "TessesFramework/Http/HttpUtils.hpp"
#include "TessesFramework/Platform/Environment.hpp"
#include <iostream>
#if defined(_WIN32)
extern "C" {
@ -48,7 +48,7 @@ static void escape_windows_args(std::string& str, std::vector<std::string> 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<ProcessData*>();
#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<ProcessData*>();
@ -258,7 +273,7 @@ namespace Tesses::Framework::Platform {
ProcessData* p =
this->hidden.GetField<ProcessData*>();
std::vector<std::pair<std::string,std::string>> 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<std::string> 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<ProcessData*>()->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<ProcessData*>();
//WaitForSingleObject(this->p)
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
return -1;
#else
int r;
if(waitpid(this->hidden.GetField<ProcessData*>()->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<ProcessData*>()->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<ProcessData*>()->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<ProcessData*>()->stderr_strm,false);