mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 16:18:12 +00:00
Add basic PTY support.
For now, there are four hard-coded PTYs: /dev/pt{m,s}[0123] Use this in the Terminal to open a pty pair and spawn a shell.
This commit is contained in:
parent
ecb4ab0943
commit
2f74c2f430
21 changed files with 287 additions and 10 deletions
|
@ -19,6 +19,8 @@ KERNEL_OBJS = \
|
||||||
ProcFileSystem.o \
|
ProcFileSystem.o \
|
||||||
RTC.o \
|
RTC.o \
|
||||||
TTY.o \
|
TTY.o \
|
||||||
|
MasterPTY.o \
|
||||||
|
SlavePTY.o \
|
||||||
VirtualConsole.o \
|
VirtualConsole.o \
|
||||||
FIFO.o \
|
FIFO.o \
|
||||||
Scheduler.o \
|
Scheduler.o \
|
||||||
|
|
42
Kernel/MasterPTY.cpp
Normal file
42
Kernel/MasterPTY.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#include "MasterPTY.h"
|
||||||
|
#include "SlavePTY.h"
|
||||||
|
|
||||||
|
MasterPTY::MasterPTY(unsigned index)
|
||||||
|
: CharacterDevice(10, index)
|
||||||
|
, m_index(index)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MasterPTY::~MasterPTY()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
String MasterPTY::pts_name() const
|
||||||
|
{
|
||||||
|
dbgprintf("MasterPTY::pts_name requested for index %u!\n", m_index);
|
||||||
|
char buffer[32];
|
||||||
|
ksprintf(buffer, "/dev/pts%u", m_index);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t MasterPTY::read(byte* buffer, size_t size)
|
||||||
|
{
|
||||||
|
return m_buffer.read(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t MasterPTY::write(const byte* buffer, size_t size)
|
||||||
|
{
|
||||||
|
m_slave->on_master_write(buffer, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MasterPTY::has_data_available_for_reading(Process&) const
|
||||||
|
{
|
||||||
|
return !m_buffer.is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MasterPTY::on_slave_write(const byte* data, size_t size)
|
||||||
|
{
|
||||||
|
m_buffer.write(data, size);
|
||||||
|
}
|
26
Kernel/MasterPTY.h
Normal file
26
Kernel/MasterPTY.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <VirtualFileSystem/CharacterDevice.h>
|
||||||
|
#include "DoubleBuffer.h"
|
||||||
|
|
||||||
|
class SlavePTY;
|
||||||
|
|
||||||
|
class MasterPTY final : public CharacterDevice {
|
||||||
|
public:
|
||||||
|
explicit MasterPTY(unsigned index);
|
||||||
|
virtual ~MasterPTY() override;
|
||||||
|
void set_slave(SlavePTY& slave) { m_slave = &slave; }
|
||||||
|
|
||||||
|
virtual ssize_t read(byte*, size_t) override;
|
||||||
|
virtual ssize_t write(const byte*, size_t) override;
|
||||||
|
virtual bool has_data_available_for_reading(Process&) const override;
|
||||||
|
virtual bool is_master_pty() const override { return true; }
|
||||||
|
|
||||||
|
String pts_name() const;
|
||||||
|
void on_slave_write(const byte*, size_t);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned m_index;
|
||||||
|
SlavePTY* m_slave { nullptr };
|
||||||
|
DoubleBuffer m_buffer;
|
||||||
|
};
|
|
@ -19,6 +19,7 @@
|
||||||
#include "FIFO.h"
|
#include "FIFO.h"
|
||||||
#include "KSyms.h"
|
#include "KSyms.h"
|
||||||
#include <Widgets/Window.h>
|
#include <Widgets/Window.h>
|
||||||
|
#include "MasterPTY.h"
|
||||||
|
|
||||||
//#define DEBUG_IO
|
//#define DEBUG_IO
|
||||||
//#define TASK_DEBUG
|
//#define TASK_DEBUG
|
||||||
|
@ -989,6 +990,23 @@ int Process::sys$ttyname_r(int fd, char* buffer, size_t size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Process::sys$ptsname_r(int fd, char* buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (!validate_write(buffer, size))
|
||||||
|
return -EFAULT;
|
||||||
|
auto* descriptor = file_descriptor(fd);
|
||||||
|
if (!descriptor)
|
||||||
|
return -EBADF;
|
||||||
|
auto* master_pty = descriptor->master_pty();
|
||||||
|
if (!master_pty)
|
||||||
|
return -ENOTTY;
|
||||||
|
auto pts_name = master_pty->pts_name();
|
||||||
|
if (size < pts_name.length() + 1)
|
||||||
|
return -ERANGE;
|
||||||
|
strcpy(buffer, pts_name.characters());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t Process::sys$write(int fd, const void* data, size_t size)
|
ssize_t Process::sys$write(int fd, const void* data, size_t size)
|
||||||
{
|
{
|
||||||
if (!validate_read(data, size))
|
if (!validate_read(data, size))
|
||||||
|
@ -1270,7 +1288,7 @@ int Process::sys$open(const char* path, int options)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (number_of_open_file_descriptors() >= m_max_open_file_descriptors)
|
if (number_of_open_file_descriptors() >= m_max_open_file_descriptors)
|
||||||
return -EMFILE;
|
return -EMFILE;
|
||||||
int error;
|
int error = -EWHYTHO;
|
||||||
auto descriptor = VFS::the().open(path, error, options, cwd_inode()->identifier());
|
auto descriptor = VFS::the().open(path, error, options, cwd_inode()->identifier());
|
||||||
if (!descriptor)
|
if (!descriptor)
|
||||||
return error;
|
return error;
|
||||||
|
|
|
@ -167,6 +167,7 @@ public:
|
||||||
int sys$uname(utsname*);
|
int sys$uname(utsname*);
|
||||||
int sys$readlink(const char*, char*, size_t);
|
int sys$readlink(const char*, char*, size_t);
|
||||||
int sys$ttyname_r(int fd, char*, size_t);
|
int sys$ttyname_r(int fd, char*, size_t);
|
||||||
|
int sys$ptsname_r(int fd, char*, size_t);
|
||||||
pid_t sys$fork(RegisterDump&);
|
pid_t sys$fork(RegisterDump&);
|
||||||
int sys$execve(const char* filename, const char** argv, const char** envp);
|
int sys$execve(const char* filename, const char** argv, const char** envp);
|
||||||
int sys$isatty(int fd);
|
int sys$isatty(int fd);
|
||||||
|
|
30
Kernel/SlavePTY.cpp
Normal file
30
Kernel/SlavePTY.cpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include "SlavePTY.h"
|
||||||
|
#include "MasterPTY.h"
|
||||||
|
|
||||||
|
SlavePTY::SlavePTY(unsigned index)
|
||||||
|
: TTY(11, index)
|
||||||
|
, m_index(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SlavePTY::~SlavePTY()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
String SlavePTY::tty_name() const
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
ksprintf(buffer, "/dev/pts%u", m_index);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlavePTY::on_master_write(const byte* buffer, size_t size)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < size; ++i)
|
||||||
|
emit(buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlavePTY::on_tty_write(const byte* data, size_t size)
|
||||||
|
{
|
||||||
|
m_master->on_slave_write(data, size);
|
||||||
|
}
|
24
Kernel/SlavePTY.h
Normal file
24
Kernel/SlavePTY.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TTY.h"
|
||||||
|
|
||||||
|
class MasterPTY;
|
||||||
|
|
||||||
|
class SlavePTY final : public TTY {
|
||||||
|
public:
|
||||||
|
explicit SlavePTY(unsigned index);
|
||||||
|
virtual ~SlavePTY() override;
|
||||||
|
void set_master(MasterPTY& master) { m_master = &master; }
|
||||||
|
|
||||||
|
virtual String tty_name() const override;
|
||||||
|
|
||||||
|
void on_master_write(const byte*, size_t);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void on_tty_write(const byte*, size_t) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned m_index;
|
||||||
|
MasterPTY* m_master { nullptr };
|
||||||
|
};
|
||||||
|
|
|
@ -121,6 +121,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
|
||||||
return current->sys$readlink((const char*)arg1, (char*)arg2, (size_t)arg3);
|
return current->sys$readlink((const char*)arg1, (char*)arg2, (size_t)arg3);
|
||||||
case Syscall::SC_ttyname_r:
|
case Syscall::SC_ttyname_r:
|
||||||
return current->sys$ttyname_r((int)arg1, (char*)arg2, (size_t)arg3);
|
return current->sys$ttyname_r((int)arg1, (char*)arg2, (size_t)arg3);
|
||||||
|
case Syscall::SC_ptsname_r:
|
||||||
|
return current->sys$ptsname_r((int)arg1, (char*)arg2, (size_t)arg3);
|
||||||
case Syscall::SC_setsid:
|
case Syscall::SC_setsid:
|
||||||
return current->sys$setsid();
|
return current->sys$setsid();
|
||||||
case Syscall::SC_getsid:
|
case Syscall::SC_getsid:
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
__ENUMERATE_SYSCALL(times) \
|
__ENUMERATE_SYSCALL(times) \
|
||||||
__ENUMERATE_SYSCALL(utime) \
|
__ENUMERATE_SYSCALL(utime) \
|
||||||
__ENUMERATE_SYSCALL(sync) \
|
__ENUMERATE_SYSCALL(sync) \
|
||||||
|
__ENUMERATE_SYSCALL(ptsname_r) \
|
||||||
__ENUMERATE_SYSCALL(gui_create_window) \
|
__ENUMERATE_SYSCALL(gui_create_window) \
|
||||||
__ENUMERATE_SYSCALL(gui_destroy_window) \
|
__ENUMERATE_SYSCALL(gui_destroy_window) \
|
||||||
__ENUMERATE_SYSCALL(gui_get_window_backing_store) \
|
__ENUMERATE_SYSCALL(gui_get_window_backing_store) \
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "IRQHandler.h"
|
#include "IRQHandler.h"
|
||||||
#include "PIC.h"
|
#include "PIC.h"
|
||||||
|
|
||||||
#define PAGE_FAULT_DEBUG
|
//#define PAGE_FAULT_DEBUG
|
||||||
|
|
||||||
struct DescriptorTablePointer {
|
struct DescriptorTablePointer {
|
||||||
word size;
|
word size;
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "VirtualConsole.h"
|
#include "VirtualConsole.h"
|
||||||
#include "Scheduler.h"
|
#include "Scheduler.h"
|
||||||
#include "PS2MouseDevice.h"
|
#include "PS2MouseDevice.h"
|
||||||
|
#include "MasterPTY.h"
|
||||||
|
#include "SlavePTY.h"
|
||||||
|
|
||||||
#define SPAWN_GUI_TEST_APP
|
#define SPAWN_GUI_TEST_APP
|
||||||
//#define SPAWN_MULTIPLE_SHELLS
|
//#define SPAWN_MULTIPLE_SHELLS
|
||||||
|
@ -36,6 +38,14 @@ VirtualConsole* tty3;
|
||||||
Keyboard* keyboard;
|
Keyboard* keyboard;
|
||||||
PS2MouseDevice* ps2mouse;
|
PS2MouseDevice* ps2mouse;
|
||||||
GUIEventDevice* gui_event_device;
|
GUIEventDevice* gui_event_device;
|
||||||
|
MasterPTY* ptm0;
|
||||||
|
MasterPTY* ptm1;
|
||||||
|
MasterPTY* ptm2;
|
||||||
|
MasterPTY* ptm3;
|
||||||
|
SlavePTY* pts0;
|
||||||
|
SlavePTY* pts1;
|
||||||
|
SlavePTY* pts2;
|
||||||
|
SlavePTY* pts3;
|
||||||
|
|
||||||
#ifdef STRESS_TEST_SPAWNING
|
#ifdef STRESS_TEST_SPAWNING
|
||||||
static void spawn_stress() NORETURN;
|
static void spawn_stress() NORETURN;
|
||||||
|
@ -56,6 +66,16 @@ static void spawn_stress()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void make_pty_pair(unsigned index)
|
||||||
|
{
|
||||||
|
auto* master = new MasterPTY(index);
|
||||||
|
auto* slave = new SlavePTY(index);
|
||||||
|
master->set_slave(*slave);
|
||||||
|
slave->set_master(*master);
|
||||||
|
VFS::the().register_character_device(*master);
|
||||||
|
VFS::the().register_character_device(*slave);
|
||||||
|
}
|
||||||
|
|
||||||
static void init_stage2() NORETURN;
|
static void init_stage2() NORETURN;
|
||||||
static void init_stage2()
|
static void init_stage2()
|
||||||
{
|
{
|
||||||
|
@ -75,6 +95,11 @@ static void init_stage2()
|
||||||
auto dev_random = make<RandomDevice>();
|
auto dev_random = make<RandomDevice>();
|
||||||
vfs->register_character_device(*dev_random);
|
vfs->register_character_device(*dev_random);
|
||||||
|
|
||||||
|
make_pty_pair(0);
|
||||||
|
make_pty_pair(1);
|
||||||
|
make_pty_pair(2);
|
||||||
|
make_pty_pair(3);
|
||||||
|
|
||||||
vfs->register_character_device(*keyboard);
|
vfs->register_character_device(*keyboard);
|
||||||
vfs->register_character_device(*ps2mouse);
|
vfs->register_character_device(*ps2mouse);
|
||||||
vfs->register_character_device(*gui_event_device);
|
vfs->register_character_device(*gui_event_device);
|
||||||
|
|
|
@ -6,6 +6,8 @@ make -C ../LibC clean && \
|
||||||
make -C ../LibC && \
|
make -C ../LibC && \
|
||||||
make -C ../Userland clean && \
|
make -C ../Userland clean && \
|
||||||
make -C ../Userland && \
|
make -C ../Userland && \
|
||||||
|
make -C ../Terminal clean && \
|
||||||
|
make -C ../Terminal && \
|
||||||
make clean &&\
|
make clean &&\
|
||||||
make && \
|
make && \
|
||||||
sudo ./sync.sh
|
sudo ./sync.sh
|
||||||
|
|
|
@ -9,6 +9,14 @@ mknod mnt/dev/tty1 c 4 1
|
||||||
mknod mnt/dev/tty2 c 4 2
|
mknod mnt/dev/tty2 c 4 2
|
||||||
mknod mnt/dev/tty3 c 4 3
|
mknod mnt/dev/tty3 c 4 3
|
||||||
mknod mnt/dev/psaux c 10 1
|
mknod mnt/dev/psaux c 10 1
|
||||||
|
mknod mnt/dev/ptm0 c 10 0
|
||||||
|
mknod mnt/dev/ptm1 c 10 1
|
||||||
|
mknod mnt/dev/ptm2 c 10 2
|
||||||
|
mknod mnt/dev/ptm3 c 10 3
|
||||||
|
mknod mnt/dev/pts0 c 11 0
|
||||||
|
mknod mnt/dev/pts1 c 11 1
|
||||||
|
mknod mnt/dev/pts2 c 11 2
|
||||||
|
mknod mnt/dev/pts3 c 11 3
|
||||||
mknod mnt/dev/gui_events c 66 1
|
mknod mnt/dev/gui_events c 66 1
|
||||||
cp -R ../Base/* mnt/
|
cp -R ../Base/* mnt/
|
||||||
cp -v ../Userland/sh mnt/bin/sh
|
cp -v ../Userland/sh mnt/bin/sh
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <AK/Assertions.h>
|
#include <AK/Assertions.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
#include <Kernel/Syscall.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
@ -215,6 +217,19 @@ long atol(const char* str)
|
||||||
return atoi(str);
|
return atoi(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char ptsname_buf[32];
|
||||||
|
char* ptsname(int fd)
|
||||||
|
{
|
||||||
|
if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0)
|
||||||
|
return nullptr;
|
||||||
|
return ptsname_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ptsname_r(int fd, char* buffer, size_t size)
|
||||||
|
{
|
||||||
|
int rc = syscall(SC_ptsname_r, fd, buffer, size);
|
||||||
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long s_next_rand = 1;
|
static unsigned long s_next_rand = 1;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ long atol(const char*);
|
||||||
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
|
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
|
||||||
void exit(int status) __NORETURN;
|
void exit(int status) __NORETURN;
|
||||||
void abort() __NORETURN;
|
void abort() __NORETURN;
|
||||||
|
char* ptsname(int fd);
|
||||||
|
int ptsname_r(int fd, char* buffer, size_t);
|
||||||
|
|
||||||
#define RAND_MAX 32767
|
#define RAND_MAX 32767
|
||||||
int rand();
|
int rand();
|
||||||
|
|
|
@ -49,8 +49,6 @@ Terminal::Terminal()
|
||||||
word* line_mem = reinterpret_cast<word*>(m_buffer);
|
word* line_mem = reinterpret_cast<word*>(m_buffer);
|
||||||
for (word i = 0; i < rows() * columns(); ++i)
|
for (word i = 0; i < rows() * columns(); ++i)
|
||||||
line_mem[i] = 0x0720;
|
line_mem[i] = 0x0720;
|
||||||
|
|
||||||
inject_string_at(2, 2, "I am text inside the Terminal buffer.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::inject_string_at(word row, word column, const String& string)
|
void Terminal::inject_string_at(word row, word column, const String& string)
|
||||||
|
|
|
@ -11,12 +11,50 @@
|
||||||
#include <gui.h>
|
#include <gui.h>
|
||||||
#include "Terminal.h"
|
#include "Terminal.h"
|
||||||
|
|
||||||
static void paint(GraphicsBitmap& bitmap, int width, int height);
|
static void make_shell(int ptm_fd)
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
{
|
||||||
int fd = open("/dev/gui_events", O_RDONLY);
|
pid_t pid = fork();
|
||||||
if (fd < 0) {
|
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);
|
||||||
|
dbgprintf("*** In child (%d), opening slave pty %s, pts_fd=%d\n", getpid(), tty_name, pts_fd);
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
dup2(pts_fd, 0);
|
||||||
|
dup2(pts_fd, 1);
|
||||||
|
dup2(pts_fd, 2);
|
||||||
|
close(pts_fd);
|
||||||
|
int rc = execve("/bin/sh", nullptr, nullptr);
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("execve");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
} else {
|
||||||
|
dbgprintf("*** In parent, child is %d\n", pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
int ptm_fd = open("/dev/ptm0", O_RDWR);
|
||||||
|
if (ptm_fd < 0) {
|
||||||
|
perror("open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgprintf("ptm_fd = %d\n", ptm_fd);
|
||||||
|
|
||||||
|
make_shell(ptm_fd);
|
||||||
|
|
||||||
|
int event_fd = open("/dev/gui_events", O_RDONLY);
|
||||||
|
if (event_fd < 0) {
|
||||||
perror("open");
|
perror("open");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +64,17 @@ int main(int argc, char** argv)
|
||||||
terminal.paint();
|
terminal.paint();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
byte buffer[1024];
|
||||||
|
ssize_t ptm_nread = read(ptm_fd, buffer, sizeof(buffer));
|
||||||
|
if (ptm_nread > 0) {
|
||||||
|
for (ssize_t i = 0; i < ptm_nread; ++i) {
|
||||||
|
terminal.on_char(buffer[i]);
|
||||||
|
}
|
||||||
|
terminal.paint();
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
GUI_Event event;
|
GUI_Event event;
|
||||||
ssize_t nread = read(fd, &event, sizeof(event));
|
ssize_t nread = read(event_fd, &event, sizeof(event));
|
||||||
if (nread < 0) {
|
if (nread < 0) {
|
||||||
perror("read");
|
perror("read");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -39,10 +86,13 @@ int main(int argc, char** argv)
|
||||||
case GUI_Event::Type::MouseDown: dbgprintf("WID=%x MouseDown %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseDown: dbgprintf("WID=%x MouseDown %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
case GUI_Event::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
case GUI_Event::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
case GUI_Event::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
|
||||||
|
default:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == GUI_Event::Type::MouseDown)
|
if (event.type == GUI_Event::Type::MouseDown)
|
||||||
terminal.paint();
|
terminal.paint();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ public:
|
||||||
unsigned minor() const { return m_minor; }
|
unsigned minor() const { return m_minor; }
|
||||||
|
|
||||||
virtual bool is_tty() const { return false; }
|
virtual bool is_tty() const { return false; }
|
||||||
|
virtual bool is_master_pty() const { return false; }
|
||||||
|
|
||||||
virtual int ioctl(Process&, unsigned request, unsigned arg);
|
virtual int ioctl(Process&, unsigned request, unsigned arg);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#ifdef SERENITY
|
#ifdef SERENITY
|
||||||
#include "TTY.h"
|
#include "TTY.h"
|
||||||
|
#include "MasterPTY.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<Vnode>&& vnode)
|
RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<Vnode>&& vnode)
|
||||||
|
@ -258,6 +259,29 @@ TTY* FileDescriptor::tty()
|
||||||
return static_cast<TTY*>(device);
|
return static_cast<TTY*>(device);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileDescriptor::is_master_pty() const
|
||||||
|
{
|
||||||
|
if (is_fifo())
|
||||||
|
return false;
|
||||||
|
if (auto* device = m_vnode->characterDevice())
|
||||||
|
return device->is_master_pty();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MasterPTY* FileDescriptor::master_pty() const
|
||||||
|
{
|
||||||
|
if (!is_master_pty())
|
||||||
|
return nullptr;
|
||||||
|
return static_cast<const MasterPTY*>(m_vnode->characterDevice());
|
||||||
|
}
|
||||||
|
|
||||||
|
MasterPTY* FileDescriptor::master_pty()
|
||||||
|
{
|
||||||
|
if (!is_master_pty())
|
||||||
|
return nullptr;
|
||||||
|
return static_cast<MasterPTY*>(m_vnode->characterDevice());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int FileDescriptor::close()
|
int FileDescriptor::close()
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#ifdef SERENITY
|
#ifdef SERENITY
|
||||||
class TTY;
|
class TTY;
|
||||||
|
class MasterPTY;
|
||||||
class Process;
|
class Process;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -46,6 +47,10 @@ public:
|
||||||
bool is_tty() const;
|
bool is_tty() const;
|
||||||
const TTY* tty() const;
|
const TTY* tty() const;
|
||||||
TTY* tty();
|
TTY* tty();
|
||||||
|
|
||||||
|
bool is_master_pty() const;
|
||||||
|
const MasterPTY* master_pty() const;
|
||||||
|
MasterPTY* master_pty();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
InodeMetadata metadata() const { return m_vnode->metadata(); }
|
InodeMetadata metadata() const { return m_vnode->metadata(); }
|
||||||
|
|
|
@ -265,6 +265,7 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
|
||||||
auto inode = resolve_path(path, base, error, options);
|
auto inode = resolve_path(path, base, error, options);
|
||||||
if (!inode.is_valid())
|
if (!inode.is_valid())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
// FIXME: Propagate any error from get_or_create_node().
|
||||||
auto vnode = get_or_create_node(inode);
|
auto vnode = get_or_create_node(inode);
|
||||||
if (!vnode)
|
if (!vnode)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue