Terminal: Use pseudo terminal instead of pipes
Terminal can now send signals from keyboard (ctrl+c) to programs running in the terminal!
This commit is contained in:
parent
4d1b32f770
commit
9e79ef2a91
|
@ -4,59 +4,63 @@
|
||||||
#include <BAN/UTF8.h>
|
#include <BAN/UTF8.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void Terminal::start_shell()
|
void Terminal::start_shell()
|
||||||
{
|
{
|
||||||
int shell_stdin[2];
|
int pts_master = posix_openpt(O_RDWR | O_NOCTTY);
|
||||||
if (pipe(shell_stdin) == -1)
|
if (pts_master == -1)
|
||||||
{
|
{
|
||||||
dwarnln("pipe: {}", strerror(errno));
|
dwarnln("posix_openpt: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int shell_stdout[2];
|
if (grantpt(pts_master) == -1)
|
||||||
if (pipe(shell_stdout) == -1)
|
|
||||||
{
|
{
|
||||||
dwarnln("pipe: {}", strerror(errno));
|
dwarnln("grantpt: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int shell_stderr[2];
|
if (unlockpt(pts_master) == -1)
|
||||||
if (pipe(shell_stderr) == -1)
|
|
||||||
{
|
{
|
||||||
dwarnln("pipe: {}", strerror(errno));
|
dwarnln("unlockpt: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t shell_pid = fork();
|
pid_t shell_pid = fork();
|
||||||
if (shell_pid == 0)
|
if (shell_pid == 0)
|
||||||
{
|
{
|
||||||
if (dup2(shell_stdin[0], STDIN_FILENO) == -1)
|
if (setsid() == -1)
|
||||||
{
|
{
|
||||||
dwarnln("dup2: {}", strerror(errno));
|
dwarnln("setsid: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(shell_stdin[0]);
|
|
||||||
close(shell_stdin[1]);
|
|
||||||
|
|
||||||
if (dup2(shell_stdout[1], STDOUT_FILENO) == -1)
|
char* pts_slave_name = ptsname(pts_master);
|
||||||
|
if (pts_slave_name == nullptr)
|
||||||
{
|
{
|
||||||
dwarnln("dup2: {}", strerror(errno));
|
dwarnln("ptsname: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(shell_stdout[0]);
|
|
||||||
close(shell_stdout[1]);
|
|
||||||
|
|
||||||
if (dup2(shell_stderr[1], STDERR_FILENO) == -1)
|
int pts_slave = open(pts_slave_name, O_RDWR);
|
||||||
|
if (pts_slave == -1)
|
||||||
|
{
|
||||||
|
dwarnln("open: {}", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dup2(pts_slave, STDIN_FILENO) == -1 || dup2(pts_slave, STDOUT_FILENO) == -1 || dup2(pts_slave, STDERR_FILENO) == -1)
|
||||||
{
|
{
|
||||||
dwarnln("dup2: {}", strerror(errno));
|
dwarnln("dup2: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(shell_stderr[0]);
|
|
||||||
close(shell_stderr[1]);
|
close(pts_slave);
|
||||||
|
close(pts_master);
|
||||||
|
|
||||||
execl("/bin/Shell", "Shell", NULL);
|
execl("/bin/Shell", "Shell", NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -68,14 +72,8 @@ void Terminal::start_shell()
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(shell_stdin[0]);
|
|
||||||
close(shell_stdout[1]);
|
|
||||||
close(shell_stderr[1]);
|
|
||||||
|
|
||||||
m_shell_info = {
|
m_shell_info = {
|
||||||
.in = shell_stdin[1],
|
.pts_master = pts_master,
|
||||||
.out = shell_stdout[0],
|
|
||||||
.err = shell_stderr[0],
|
|
||||||
.pid = shell_pid
|
.pid = shell_pid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -95,22 +93,18 @@ void Terminal::run()
|
||||||
|
|
||||||
m_window->set_key_event_callback([&](LibGUI::EventPacket::KeyEvent event) { on_key_event(event); });
|
m_window->set_key_event_callback([&](LibGUI::EventPacket::KeyEvent event) { on_key_event(event); });
|
||||||
|
|
||||||
const int max_fd = BAN::Math::max(BAN::Math::max(m_shell_info.out, m_shell_info.err), m_window->server_fd());
|
const int max_fd = BAN::Math::max(m_shell_info.pts_master, m_window->server_fd());
|
||||||
while (!s_shell_exited)
|
while (!s_shell_exited)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(m_shell_info.out, &fds);
|
FD_SET(m_shell_info.pts_master, &fds);
|
||||||
FD_SET(m_shell_info.err, &fds);
|
|
||||||
FD_SET(m_window->server_fd(), &fds);
|
FD_SET(m_window->server_fd(), &fds);
|
||||||
|
|
||||||
select(max_fd + 1, &fds, nullptr, nullptr, nullptr);
|
select(max_fd + 1, &fds, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
if (FD_ISSET(m_shell_info.out, &fds))
|
if (FD_ISSET(m_shell_info.pts_master, &fds))
|
||||||
if (!read_shell(m_shell_info.out))
|
if (!read_shell())
|
||||||
break;
|
|
||||||
if (FD_ISSET(m_shell_info.err, &fds))
|
|
||||||
if (!read_shell(m_shell_info.err))
|
|
||||||
break;
|
break;
|
||||||
if (FD_ISSET(m_window->server_fd(), &fds))
|
if (FD_ISSET(m_window->server_fd(), &fds))
|
||||||
m_window->poll_events();
|
m_window->poll_events();
|
||||||
|
@ -118,10 +112,10 @@ void Terminal::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Terminal::read_shell(int fd)
|
bool Terminal::read_shell()
|
||||||
{
|
{
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
ssize_t nread = read(fd, buffer, sizeof(buffer) - 1);
|
ssize_t nread = read(m_shell_info.pts_master, buffer, sizeof(buffer) - 1);
|
||||||
if (nread < 0)
|
if (nread < 0)
|
||||||
dwarnln("read: {}", strerror(errno));
|
dwarnln("read: {}", strerror(errno));
|
||||||
if (nread <= 0)
|
if (nread <= 0)
|
||||||
|
@ -409,5 +403,5 @@ void Terminal::on_key_event(LibGUI::EventPacket::KeyEvent event)
|
||||||
if (event.released())
|
if (event.released())
|
||||||
return;
|
return;
|
||||||
if (const char* text = LibInput::key_to_utf8_ansi(event.key, event.modifier))
|
if (const char* text = LibInput::key_to_utf8_ansi(event.key, event.modifier))
|
||||||
write(m_shell_info.in, text, strlen(text));
|
write(m_shell_info.pts_master, text, strlen(text));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ private:
|
||||||
void handle_csi(char ch);
|
void handle_csi(char ch);
|
||||||
void handle_sgr();
|
void handle_sgr();
|
||||||
void putchar(uint8_t ch);
|
void putchar(uint8_t ch);
|
||||||
bool read_shell(int fd);
|
bool read_shell();
|
||||||
|
|
||||||
void on_key_event(LibGUI::EventPacket::KeyEvent);
|
void on_key_event(LibGUI::EventPacket::KeyEvent);
|
||||||
|
|
||||||
|
@ -31,9 +31,7 @@ private:
|
||||||
|
|
||||||
struct ShellInfo
|
struct ShellInfo
|
||||||
{
|
{
|
||||||
int in;
|
int pts_master;
|
||||||
int out;
|
|
||||||
int err;
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue