summaryrefslogtreecommitdiff
path: root/DevTools/HackStudio/TerminalWrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'DevTools/HackStudio/TerminalWrapper.cpp')
-rw-r--r--DevTools/HackStudio/TerminalWrapper.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/DevTools/HackStudio/TerminalWrapper.cpp b/DevTools/HackStudio/TerminalWrapper.cpp
new file mode 100644
index 0000000000..d1f20bf8bb
--- /dev/null
+++ b/DevTools/HackStudio/TerminalWrapper.cpp
@@ -0,0 +1,95 @@
+#include "TerminalWrapper.h"
+#include <AK/String.h>
+#include <LibCore/CConfigFile.h>
+#include <LibGUI/GBoxLayout.h>
+#include <LibVT/TerminalWidget.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+static void run_command(int ptm_fd, const String& command)
+{
+ pid_t pid = fork();
+ if (pid == 0) {
+ const char* tty_name = ptsname(ptm_fd);
+ if (!tty_name) {
+ perror("ptsname");
+ exit(1);
+ }
+ close(ptm_fd);
+ int pts_fd = open(tty_name, O_RDWR);
+ if (pts_fd < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ // NOTE: It's okay if this fails.
+ (void)ioctl(0, TIOCNOTTY);
+
+ close(0);
+ close(1);
+ close(2);
+
+ int rc = dup2(pts_fd, 0);
+ if (rc < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ rc = dup2(pts_fd, 1);
+ if (rc < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ rc = dup2(pts_fd, 2);
+ if (rc < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ rc = close(pts_fd);
+ if (rc < 0) {
+ perror("close");
+ exit(1);
+ }
+ rc = ioctl(0, TIOCSCTTY);
+ if (rc < 0) {
+ perror("ioctl(TIOCSCTTY)");
+ exit(1);
+ }
+ const char* args[4] = { "/bin/Shell", nullptr, nullptr, nullptr };
+ if (!command.is_empty()) {
+ args[1] = "-c";
+ args[2] = command.characters();
+ }
+ const char* envs[] = { "TERM=xterm", "PATH=/bin:/usr/bin:/usr/local/bin", nullptr };
+ rc = execve("/bin/Shell", const_cast<char**>(args), const_cast<char**>(envs));
+ if (rc < 0) {
+ perror("execve");
+ exit(1);
+ }
+ ASSERT_NOT_REACHED();
+ }
+}
+
+TerminalWrapper::TerminalWrapper(GWidget* parent)
+ : GWidget(parent)
+{
+ set_layout(make<GBoxLayout>(Orientation::Vertical));
+
+ int ptm_fd = open("/dev/ptmx", O_RDWR);
+ if (ptm_fd < 0) {
+ perror("open(ptmx)");
+ ASSERT_NOT_REACHED();
+ }
+
+ run_command(ptm_fd, "/bin/Shell");
+
+ RefPtr<CConfigFile> config = CConfigFile::get_for_app("Terminal");
+ m_terminal_widget = TerminalWidget::construct(ptm_fd, config);
+ add_child(*m_terminal_widget);
+}
+
+TerminalWrapper::~TerminalWrapper()
+{
+}