diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-01-15 06:30:19 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-01-15 06:30:19 +0100 |
commit | 2f74c2f43009723c996f508f423eab3013b47792 (patch) | |
tree | c63ab495172eec96867ff28ffcffb5fbcbca0c98 /Kernel | |
parent | ecb4ab0943530794fb00a0a6e2a82e3e94e2f9a3 (diff) | |
download | serenity-2f74c2f43009723c996f508f423eab3013b47792.zip |
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.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Makefile | 2 | ||||
-rw-r--r-- | Kernel/MasterPTY.cpp | 42 | ||||
-rw-r--r-- | Kernel/MasterPTY.h | 26 | ||||
-rw-r--r-- | Kernel/Process.cpp | 20 | ||||
-rw-r--r-- | Kernel/Process.h | 1 | ||||
-rw-r--r-- | Kernel/SlavePTY.cpp | 30 | ||||
-rw-r--r-- | Kernel/SlavePTY.h | 24 | ||||
-rw-r--r-- | Kernel/Syscall.cpp | 2 | ||||
-rw-r--r-- | Kernel/Syscall.h | 1 | ||||
-rw-r--r-- | Kernel/i386.cpp | 2 | ||||
-rw-r--r-- | Kernel/init.cpp | 25 | ||||
-rwxr-xr-x | Kernel/makeall.sh | 2 | ||||
-rwxr-xr-x | Kernel/sync.sh | 8 |
13 files changed, 183 insertions, 2 deletions
diff --git a/Kernel/Makefile b/Kernel/Makefile index dab935cfe9..7f11b75522 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -19,6 +19,8 @@ KERNEL_OBJS = \ ProcFileSystem.o \ RTC.o \ TTY.o \ + MasterPTY.o \ + SlavePTY.o \ VirtualConsole.o \ FIFO.o \ Scheduler.o \ diff --git a/Kernel/MasterPTY.cpp b/Kernel/MasterPTY.cpp new file mode 100644 index 0000000000..2894839bc1 --- /dev/null +++ b/Kernel/MasterPTY.cpp @@ -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); +} diff --git a/Kernel/MasterPTY.h b/Kernel/MasterPTY.h new file mode 100644 index 0000000000..5876402680 --- /dev/null +++ b/Kernel/MasterPTY.h @@ -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; +}; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 7e806b3ee5..9869f1421d 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -19,6 +19,7 @@ #include "FIFO.h" #include "KSyms.h" #include <Widgets/Window.h> +#include "MasterPTY.h" //#define DEBUG_IO //#define TASK_DEBUG @@ -989,6 +990,23 @@ int Process::sys$ttyname_r(int fd, char* buffer, size_t size) 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) { if (!validate_read(data, size)) @@ -1270,7 +1288,7 @@ int Process::sys$open(const char* path, int options) return -EFAULT; if (number_of_open_file_descriptors() >= m_max_open_file_descriptors) return -EMFILE; - int error; + int error = -EWHYTHO; auto descriptor = VFS::the().open(path, error, options, cwd_inode()->identifier()); if (!descriptor) return error; diff --git a/Kernel/Process.h b/Kernel/Process.h index cff3df1d76..85ae1c6bda 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -167,6 +167,7 @@ public: int sys$uname(utsname*); int sys$readlink(const char*, 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&); int sys$execve(const char* filename, const char** argv, const char** envp); int sys$isatty(int fd); diff --git a/Kernel/SlavePTY.cpp b/Kernel/SlavePTY.cpp new file mode 100644 index 0000000000..3d3a3c439e --- /dev/null +++ b/Kernel/SlavePTY.cpp @@ -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); +} diff --git a/Kernel/SlavePTY.h b/Kernel/SlavePTY.h new file mode 100644 index 0000000000..34601e0b14 --- /dev/null +++ b/Kernel/SlavePTY.h @@ -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 }; +}; + diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index df00742e51..547e67fc6f 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -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); case Syscall::SC_ttyname_r: 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: return current->sys$setsid(); case Syscall::SC_getsid: diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 9085724a92..f0e315ec47 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -66,6 +66,7 @@ __ENUMERATE_SYSCALL(times) \ __ENUMERATE_SYSCALL(utime) \ __ENUMERATE_SYSCALL(sync) \ + __ENUMERATE_SYSCALL(ptsname_r) \ __ENUMERATE_SYSCALL(gui_create_window) \ __ENUMERATE_SYSCALL(gui_destroy_window) \ __ENUMERATE_SYSCALL(gui_get_window_backing_store) \ diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index d24dac9c1c..221bb5ef7a 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -7,7 +7,7 @@ #include "IRQHandler.h" #include "PIC.h" -#define PAGE_FAULT_DEBUG +//#define PAGE_FAULT_DEBUG struct DescriptorTablePointer { word size; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 4d2e83a79b..8001460b58 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -22,6 +22,8 @@ #include "VirtualConsole.h" #include "Scheduler.h" #include "PS2MouseDevice.h" +#include "MasterPTY.h" +#include "SlavePTY.h" #define SPAWN_GUI_TEST_APP //#define SPAWN_MULTIPLE_SHELLS @@ -36,6 +38,14 @@ VirtualConsole* tty3; Keyboard* keyboard; PS2MouseDevice* ps2mouse; GUIEventDevice* gui_event_device; +MasterPTY* ptm0; +MasterPTY* ptm1; +MasterPTY* ptm2; +MasterPTY* ptm3; +SlavePTY* pts0; +SlavePTY* pts1; +SlavePTY* pts2; +SlavePTY* pts3; #ifdef STRESS_TEST_SPAWNING static void spawn_stress() NORETURN; @@ -56,6 +66,16 @@ static void spawn_stress() } #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() { @@ -75,6 +95,11 @@ static void init_stage2() auto dev_random = make<RandomDevice>(); 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(*ps2mouse); vfs->register_character_device(*gui_event_device); diff --git a/Kernel/makeall.sh b/Kernel/makeall.sh index dd3e0e447e..15c36c18ab 100755 --- a/Kernel/makeall.sh +++ b/Kernel/makeall.sh @@ -6,6 +6,8 @@ make -C ../LibC clean && \ make -C ../LibC && \ make -C ../Userland clean && \ make -C ../Userland && \ +make -C ../Terminal clean && \ +make -C ../Terminal && \ make clean &&\ make && \ sudo ./sync.sh diff --git a/Kernel/sync.sh b/Kernel/sync.sh index d72dca30c6..0aa9cf6e98 100755 --- a/Kernel/sync.sh +++ b/Kernel/sync.sh @@ -9,6 +9,14 @@ mknod mnt/dev/tty1 c 4 1 mknod mnt/dev/tty2 c 4 2 mknod mnt/dev/tty3 c 4 3 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 cp -R ../Base/* mnt/ cp -v ../Userland/sh mnt/bin/sh |