summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-01-15 06:30:19 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-01-15 06:30:19 +0100
commit2f74c2f43009723c996f508f423eab3013b47792 (patch)
treec63ab495172eec96867ff28ffcffb5fbcbca0c98 /Kernel
parentecb4ab0943530794fb00a0a6e2a82e3e94e2f9a3 (diff)
downloadserenity-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/Makefile2
-rw-r--r--Kernel/MasterPTY.cpp42
-rw-r--r--Kernel/MasterPTY.h26
-rw-r--r--Kernel/Process.cpp20
-rw-r--r--Kernel/Process.h1
-rw-r--r--Kernel/SlavePTY.cpp30
-rw-r--r--Kernel/SlavePTY.h24
-rw-r--r--Kernel/Syscall.cpp2
-rw-r--r--Kernel/Syscall.h1
-rw-r--r--Kernel/i386.cpp2
-rw-r--r--Kernel/init.cpp25
-rwxr-xr-xKernel/makeall.sh2
-rwxr-xr-xKernel/sync.sh8
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