summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--LibC/stdlib.cpp15
-rw-r--r--LibC/stdlib.h2
-rw-r--r--Terminal/Terminal.cpp2
-rw-r--r--Terminal/main.cpp60
-rw-r--r--VirtualFileSystem/CharacterDevice.h1
-rw-r--r--VirtualFileSystem/FileDescriptor.cpp24
-rw-r--r--VirtualFileSystem/FileDescriptor.h5
-rw-r--r--VirtualFileSystem/VirtualFileSystem.cpp1
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;