diff options
-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 | ||||
-rw-r--r-- | LibC/stdlib.cpp | 15 | ||||
-rw-r--r-- | LibC/stdlib.h | 2 | ||||
-rw-r--r-- | Terminal/Terminal.cpp | 2 | ||||
-rw-r--r-- | Terminal/main.cpp | 60 | ||||
-rw-r--r-- | VirtualFileSystem/CharacterDevice.h | 1 | ||||
-rw-r--r-- | VirtualFileSystem/FileDescriptor.cpp | 24 | ||||
-rw-r--r-- | VirtualFileSystem/FileDescriptor.h | 5 | ||||
-rw-r--r-- | VirtualFileSystem/VirtualFileSystem.cpp | 1 |
21 files changed, 286 insertions, 9 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 diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp index deceb9f4e6..2c11843ef7 100644 --- a/LibC/stdlib.cpp +++ b/LibC/stdlib.cpp @@ -5,8 +5,10 @@ #include <string.h> #include <alloca.h> #include <assert.h> +#include <errno.h> #include <AK/Assertions.h> #include <AK/Types.h> +#include <Kernel/Syscall.h> extern "C" { @@ -215,6 +217,19 @@ long atol(const char* 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; diff --git a/LibC/stdlib.h b/LibC/stdlib.h index 29e5e4e66b..696d5c0a43 100644 --- a/LibC/stdlib.h +++ b/LibC/stdlib.h @@ -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 exit(int status) __NORETURN; void abort() __NORETURN; +char* ptsname(int fd); +int ptsname_r(int fd, char* buffer, size_t); #define RAND_MAX 32767 int rand(); diff --git a/Terminal/Terminal.cpp b/Terminal/Terminal.cpp index 2b47f33741..89b0348c8f 100644 --- a/Terminal/Terminal.cpp +++ b/Terminal/Terminal.cpp @@ -49,8 +49,6 @@ Terminal::Terminal() word* line_mem = reinterpret_cast<word*>(m_buffer); for (word i = 0; i < rows() * columns(); ++i) 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) diff --git a/Terminal/main.cpp b/Terminal/main.cpp index ed769205ba..c325a7734b 100644 --- a/Terminal/main.cpp +++ b/Terminal/main.cpp @@ -11,12 +11,50 @@ #include <gui.h> #include "Terminal.h" -static void paint(GraphicsBitmap& bitmap, int width, int height); +static void make_shell(int ptm_fd) +{ + 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); + 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 argc, char** argv) +int main(int, char**) { - int fd = open("/dev/gui_events", O_RDONLY); - if (fd < 0) { + 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"); return 1; } @@ -26,8 +64,17 @@ int main(int argc, char** argv) terminal.paint(); 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; - ssize_t nread = read(fd, &event, sizeof(event)); + ssize_t nread = read(event_fd, &event, sizeof(event)); if (nread < 0) { perror("read"); 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::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; + default: + ASSERT_NOT_REACHED(); } if (event.type == GUI_Event::Type::MouseDown) terminal.paint(); +#endif } return 0; } diff --git a/VirtualFileSystem/CharacterDevice.h b/VirtualFileSystem/CharacterDevice.h index 2028ee0f5d..6812a22e6e 100644 --- a/VirtualFileSystem/CharacterDevice.h +++ b/VirtualFileSystem/CharacterDevice.h @@ -21,6 +21,7 @@ public: unsigned minor() const { return m_minor; } virtual bool is_tty() const { return false; } + virtual bool is_master_pty() const { return false; } virtual int ioctl(Process&, unsigned request, unsigned arg); diff --git a/VirtualFileSystem/FileDescriptor.cpp b/VirtualFileSystem/FileDescriptor.cpp index 7fb9700907..32a13af2cd 100644 --- a/VirtualFileSystem/FileDescriptor.cpp +++ b/VirtualFileSystem/FileDescriptor.cpp @@ -8,6 +8,7 @@ #ifdef SERENITY #include "TTY.h" +#include "MasterPTY.h" #endif RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<Vnode>&& vnode) @@ -258,6 +259,29 @@ TTY* FileDescriptor::tty() return static_cast<TTY*>(device); 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 int FileDescriptor::close() diff --git a/VirtualFileSystem/FileDescriptor.h b/VirtualFileSystem/FileDescriptor.h index 675f1aeb2b..2441f18913 100644 --- a/VirtualFileSystem/FileDescriptor.h +++ b/VirtualFileSystem/FileDescriptor.h @@ -9,6 +9,7 @@ #ifdef SERENITY class TTY; +class MasterPTY; class Process; #endif @@ -46,6 +47,10 @@ public: bool is_tty() const; const TTY* tty() const; TTY* tty(); + + bool is_master_pty() const; + const MasterPTY* master_pty() const; + MasterPTY* master_pty(); #endif InodeMetadata metadata() const { return m_vnode->metadata(); } diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index 9144017d63..d23be21a32 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -265,6 +265,7 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options, auto inode = resolve_path(path, base, error, options); if (!inode.is_valid()) return nullptr; + // FIXME: Propagate any error from get_or_create_node(). auto vnode = get_or_create_node(inode); if (!vnode) return nullptr; |