mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:17:34 +00:00
HackStudio: Add optional parameters to TerminalWrapper::run()
The optional parameters allow specifying a working directory and controlling whether or not to block until the command returns.
This commit is contained in:
parent
3afd17db9d
commit
afb4c447b4
2 changed files with 36 additions and 4 deletions
|
@ -7,6 +7,7 @@
|
||||||
#include "TerminalWrapper.h"
|
#include "TerminalWrapper.h"
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibCore/ConfigFile.h>
|
#include <LibCore/ConfigFile.h>
|
||||||
|
#include <LibGUI/Application.h>
|
||||||
#include <LibGUI/BoxLayout.h>
|
#include <LibGUI/BoxLayout.h>
|
||||||
#include <LibGUI/MessageBox.h>
|
#include <LibGUI/MessageBox.h>
|
||||||
#include <LibVT/TerminalWidget.h>
|
#include <LibVT/TerminalWidget.h>
|
||||||
|
@ -22,7 +23,7 @@
|
||||||
|
|
||||||
namespace HackStudio {
|
namespace HackStudio {
|
||||||
|
|
||||||
void TerminalWrapper::run_command(const String& command)
|
void TerminalWrapper::run_command(const String& command, Optional<String> working_directory, WaitForExit wait_for_exit)
|
||||||
{
|
{
|
||||||
if (m_pid != -1) {
|
if (m_pid != -1) {
|
||||||
GUI::MessageBox::show(window(),
|
GUI::MessageBox::show(window(),
|
||||||
|
@ -39,6 +40,8 @@ void TerminalWrapper::run_command(const String& command)
|
||||||
}
|
}
|
||||||
|
|
||||||
int ptm_fd = ptm_res.value();
|
int ptm_fd = ptm_res.value();
|
||||||
|
m_child_exited = false;
|
||||||
|
m_child_exit_status.clear();
|
||||||
|
|
||||||
m_pid = fork();
|
m_pid = fork();
|
||||||
if (m_pid < 0) {
|
if (m_pid < 0) {
|
||||||
|
@ -46,8 +49,21 @@ void TerminalWrapper::run_command(const String& command)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pid > 0)
|
if (m_pid > 0) {
|
||||||
|
if (wait_for_exit == WaitForExit::Yes) {
|
||||||
|
GUI::Application::the()->event_loop().spin_until([this]() {
|
||||||
|
return m_child_exited;
|
||||||
|
});
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (working_directory.has_value()) {
|
||||||
|
if (chdir(working_directory->characters())) {
|
||||||
|
perror("chdir");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (setup_slave_pseudoterminal(ptm_fd).is_error()) {
|
if (setup_slave_pseudoterminal(ptm_fd).is_error()) {
|
||||||
perror("setup_pseudoterminal");
|
perror("setup_pseudoterminal");
|
||||||
|
@ -93,6 +109,7 @@ ErrorOr<int> TerminalWrapper::setup_master_pseudoterminal(WaitForChildOnExit wai
|
||||||
perror("waitpid");
|
perror("waitpid");
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(wstatus)) {
|
if (WIFEXITED(wstatus)) {
|
||||||
m_terminal_widget->inject_string(String::formatted("\033[{};1m(Command exited with code {})\033[0m\r\n", wstatus == 0 ? 32 : 31, WEXITSTATUS(wstatus)));
|
m_terminal_widget->inject_string(String::formatted("\033[{};1m(Command exited with code {})\033[0m\r\n", wstatus == 0 ? 32 : 31, WEXITSTATUS(wstatus)));
|
||||||
} else if (WIFSTOPPED(wstatus)) {
|
} else if (WIFSTOPPED(wstatus)) {
|
||||||
|
@ -100,6 +117,9 @@ ErrorOr<int> TerminalWrapper::setup_master_pseudoterminal(WaitForChildOnExit wai
|
||||||
} else if (WIFSIGNALED(wstatus)) {
|
} else if (WIFSIGNALED(wstatus)) {
|
||||||
m_terminal_widget->inject_string(String::formatted("\033[34;1m(Command signaled with {}!)\033[0m\r\n", strsignal(WTERMSIG(wstatus))));
|
m_terminal_widget->inject_string(String::formatted("\033[34;1m(Command signaled with {}!)\033[0m\r\n", strsignal(WTERMSIG(wstatus))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_child_exit_status = WEXITSTATUS(wstatus);
|
||||||
|
m_child_exited = true;
|
||||||
}
|
}
|
||||||
m_pid = -1;
|
m_pid = -1;
|
||||||
|
|
||||||
|
@ -187,4 +207,10 @@ TerminalWrapper::~TerminalWrapper()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TerminalWrapper::child_exit_status() const
|
||||||
|
{
|
||||||
|
VERIFY(m_child_exit_status.has_value());
|
||||||
|
return m_child_exit_status.value();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,11 @@ class TerminalWrapper final : public GUI::Widget {
|
||||||
C_OBJECT(TerminalWrapper)
|
C_OBJECT(TerminalWrapper)
|
||||||
public:
|
public:
|
||||||
virtual ~TerminalWrapper() override;
|
virtual ~TerminalWrapper() override;
|
||||||
|
enum class WaitForExit {
|
||||||
void run_command(const String&);
|
No,
|
||||||
|
Yes
|
||||||
|
};
|
||||||
|
void run_command(const String&, Optional<String> working_directory = {}, WaitForExit = WaitForExit::No);
|
||||||
void kill_running_command();
|
void kill_running_command();
|
||||||
void clear_including_history();
|
void clear_including_history();
|
||||||
|
|
||||||
|
@ -30,6 +33,7 @@ public:
|
||||||
};
|
};
|
||||||
ErrorOr<int> setup_master_pseudoterminal(WaitForChildOnExit = WaitForChildOnExit::Yes);
|
ErrorOr<int> setup_master_pseudoterminal(WaitForChildOnExit = WaitForChildOnExit::Yes);
|
||||||
static ErrorOr<void> setup_slave_pseudoterminal(int master_fd);
|
static ErrorOr<void> setup_slave_pseudoterminal(int master_fd);
|
||||||
|
int child_exit_status() const;
|
||||||
|
|
||||||
Function<void()> on_command_exit;
|
Function<void()> on_command_exit;
|
||||||
|
|
||||||
|
@ -39,6 +43,8 @@ private:
|
||||||
RefPtr<VT::TerminalWidget> m_terminal_widget;
|
RefPtr<VT::TerminalWidget> m_terminal_widget;
|
||||||
pid_t m_pid { -1 };
|
pid_t m_pid { -1 };
|
||||||
bool m_user_spawned { true };
|
bool m_user_spawned { true };
|
||||||
|
bool m_child_exited { false };
|
||||||
|
Optional<int> m_child_exit_status;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue