summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/Makefile1
-rw-r--r--Kernel/MasterPTY.h2
-rw-r--r--Kernel/PTYMultiplexer.cpp27
-rw-r--r--Kernel/PTYMultiplexer.h24
-rw-r--r--Kernel/Process.cpp7
-rw-r--r--Kernel/SlavePTY.h2
-rw-r--r--Kernel/init.cpp12
-rwxr-xr-xKernel/sync.sh1
-rw-r--r--Terminal/main.cpp20
-rw-r--r--VirtualFileSystem/CharacterDevice.cpp5
-rw-r--r--VirtualFileSystem/CharacterDevice.h2
-rw-r--r--VirtualFileSystem/VirtualFileSystem.cpp7
-rw-r--r--VirtualFileSystem/VirtualFileSystem.h2
13 files changed, 75 insertions, 37 deletions
diff --git a/Kernel/Makefile b/Kernel/Makefile
index 0854940359..149cffa46c 100644
--- a/Kernel/Makefile
+++ b/Kernel/Makefile
@@ -19,6 +19,7 @@ KERNEL_OBJS = \
ProcFileSystem.o \
RTC.o \
TTY.o \
+ PTYMultiplexer.o \
MasterPTY.o \
SlavePTY.o \
VirtualConsole.o \
diff --git a/Kernel/MasterPTY.h b/Kernel/MasterPTY.h
index 0837e250a4..aa4a27daf0 100644
--- a/Kernel/MasterPTY.h
+++ b/Kernel/MasterPTY.h
@@ -6,7 +6,6 @@
class SlavePTY;
class MasterPTY final : public CharacterDevice {
- AK_MAKE_ETERNAL
public:
explicit MasterPTY(unsigned index);
virtual ~MasterPTY() override;
@@ -17,6 +16,7 @@ public:
virtual bool can_write(Process&) const override;
virtual bool is_master_pty() const override { return true; }
+ unsigned index() const { return m_index; }
String pts_name() const;
void on_slave_write(const byte*, size_t);
diff --git a/Kernel/PTYMultiplexer.cpp b/Kernel/PTYMultiplexer.cpp
new file mode 100644
index 0000000000..26403e898c
--- /dev/null
+++ b/Kernel/PTYMultiplexer.cpp
@@ -0,0 +1,27 @@
+#include "PTYMultiplexer.h"
+#include "MasterPTY.h"
+#include <LibC/errno_numbers.h>
+
+PTYMultiplexer::PTYMultiplexer()
+ : CharacterDevice(5, 2)
+{
+ m_freelist.ensureCapacity(4);
+ for (int i = 4; i > 0; --i)
+ m_freelist.unchecked_append(adopt(*new MasterPTY(i - 1)));
+}
+
+PTYMultiplexer::~PTYMultiplexer()
+{
+}
+
+RetainPtr<FileDescriptor> PTYMultiplexer::open(int& error, int options)
+{
+ LOCKER(m_lock);
+ if (m_freelist.is_empty()) {
+ error = -EBUSY;
+ return nullptr;
+ }
+ auto master = m_freelist.takeLast();
+ dbgprintf("PTYMultiplexer::open: Vending master %u\n", master->index());
+ return VFS::the().open(move(master), error, options);
+}
diff --git a/Kernel/PTYMultiplexer.h b/Kernel/PTYMultiplexer.h
new file mode 100644
index 0000000000..4646fc7f05
--- /dev/null
+++ b/Kernel/PTYMultiplexer.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <VirtualFileSystem/CharacterDevice.h>
+#include <AK/Lock.h>
+
+class MasterPTY;
+
+class PTYMultiplexer final : public CharacterDevice {
+ AK_MAKE_ETERNAL
+public:
+ PTYMultiplexer();
+ virtual ~PTYMultiplexer() override;
+
+ // ^CharacterDevice
+ virtual RetainPtr<FileDescriptor> open(int& error, int options) override;
+ virtual ssize_t read(Process&, byte*, size_t) override { return 0; }
+ virtual ssize_t write(Process&, const byte*, size_t) override { return 0; }
+ virtual bool can_read(Process&) const override { return true; }
+ virtual bool can_write(Process&) const override { return true; }
+
+private:
+ SpinLock m_lock;
+ Vector<RetainPtr<MasterPTY>> m_freelist;
+};
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index dbc9f56ab8..8b7bd457ac 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -617,9 +617,10 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring
} else {
m_fds.resize(m_max_open_file_descriptors);
if (tty) {
- m_fds[0].set(tty->open(O_RDONLY));
- m_fds[1].set(tty->open(O_WRONLY));
- m_fds[2].set(tty->open(O_WRONLY));
+ int error;
+ m_fds[0].set(tty->open(error, O_RDONLY));
+ m_fds[1].set(tty->open(error, O_WRONLY));
+ m_fds[2].set(tty->open(error, O_WRONLY));
}
}
diff --git a/Kernel/SlavePTY.h b/Kernel/SlavePTY.h
index 773dcee6b4..1b01219349 100644
--- a/Kernel/SlavePTY.h
+++ b/Kernel/SlavePTY.h
@@ -5,13 +5,13 @@
class MasterPTY;
class SlavePTY final : public TTY {
- AK_MAKE_ETERNAL
public:
virtual ~SlavePTY() override;
virtual String tty_name() const override;
void on_master_write(const byte*, size_t);
+ unsigned index() const { return m_index; }
protected:
virtual void on_tty_write(const byte*, size_t) override;
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index 2348d53b88..52a942ac8d 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -22,7 +22,7 @@
#include "VirtualConsole.h"
#include "Scheduler.h"
#include "PS2MouseDevice.h"
-#include "MasterPTY.h"
+#include "PTYMultiplexer.h"
#define SPAWN_GUI_TEST_APP
//#define SPAWN_MULTIPLE_SHELLS
@@ -37,10 +37,6 @@ VirtualConsole* tty3;
Keyboard* keyboard;
PS2MouseDevice* ps2mouse;
GUIEventDevice* gui_event_device;
-MasterPTY* ptm0;
-MasterPTY* ptm1;
-MasterPTY* ptm2;
-MasterPTY* ptm3;
#ifdef STRESS_TEST_SPAWNING
static void spawn_stress() NORETURN;
@@ -80,10 +76,8 @@ static void init_stage2()
auto dev_random = make<RandomDevice>();
vfs->register_character_device(*dev_random);
- VFS::the().register_character_device(*new MasterPTY(0));
- VFS::the().register_character_device(*new MasterPTY(1));
- VFS::the().register_character_device(*new MasterPTY(2));
- VFS::the().register_character_device(*new MasterPTY(3));
+ auto dev_ptmx = make<PTYMultiplexer>();
+ vfs->register_character_device(*dev_ptmx);
vfs->register_character_device(*keyboard);
vfs->register_character_device(*ps2mouse);
diff --git a/Kernel/sync.sh b/Kernel/sync.sh
index 0aa9cf6e98..85e619b0cc 100755
--- a/Kernel/sync.sh
+++ b/Kernel/sync.sh
@@ -9,6 +9,7 @@ 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/ptmx c 5 2
mknod mnt/dev/ptm0 c 10 0
mknod mnt/dev/ptm1 c 10 1
mknod mnt/dev/ptm2 c 10 2
diff --git a/Terminal/main.cpp b/Terminal/main.cpp
index 90b0cb23e0..3d1f1decc3 100644
--- a/Terminal/main.cpp
+++ b/Terminal/main.cpp
@@ -59,23 +59,13 @@ static int max(int a, int b)
return a > b ? a : b;
}
-static int open_ptm()
-{
- char buf[32];
- for (unsigned i = 0; i < 4; ++i) {
- sprintf(buf, "/dev/ptm%u", i);
- int fd = open(buf, O_RDWR);
- if (fd)
- return fd;
- }
- dbgprintf("No master PTY available :(\n");
- exit(1);
- return -1;
-}
-
int main(int, char**)
{
- int ptm_fd = open_ptm();
+ int ptm_fd = open("/dev/ptmx", O_RDWR);
+ if (ptm_fd < 0) {
+ perror("open(ptmx)");
+ return 1;
+ }
make_shell(ptm_fd);
diff --git a/VirtualFileSystem/CharacterDevice.cpp b/VirtualFileSystem/CharacterDevice.cpp
index 61150da2e9..b76e6caba4 100644
--- a/VirtualFileSystem/CharacterDevice.cpp
+++ b/VirtualFileSystem/CharacterDevice.cpp
@@ -3,12 +3,11 @@
CharacterDevice::~CharacterDevice()
{
- ASSERT_NOT_REACHED();
}
-RetainPtr<FileDescriptor> CharacterDevice::open(int options)
+RetainPtr<FileDescriptor> CharacterDevice::open(int& error, int options)
{
- return VFS::the().open(*this, options);
+ return VFS::the().open(*this, error, options);
}
int CharacterDevice::ioctl(Process&, unsigned, unsigned)
diff --git a/VirtualFileSystem/CharacterDevice.h b/VirtualFileSystem/CharacterDevice.h
index 58df4618ab..92c29ed2cd 100644
--- a/VirtualFileSystem/CharacterDevice.h
+++ b/VirtualFileSystem/CharacterDevice.h
@@ -13,7 +13,7 @@ public:
InodeMetadata metadata() const { return { }; }
- RetainPtr<FileDescriptor> open(int options);
+ virtual RetainPtr<FileDescriptor> open(int& error, int options);
virtual bool can_read(Process&) const = 0;
virtual bool can_write(Process&) const = 0;
diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp
index 3700ea332a..957c39421c 100644
--- a/VirtualFileSystem/VirtualFileSystem.cpp
+++ b/VirtualFileSystem/VirtualFileSystem.cpp
@@ -128,11 +128,12 @@ void VFS::traverse_directory_inode(Inode& dir_inode, Function<bool(const FS::Dir
});
}
-RetainPtr<FileDescriptor> VFS::open(CharacterDevice& device, int options)
+RetainPtr<FileDescriptor> VFS::open(RetainPtr<CharacterDevice>&& device, int& error, int options)
{
// FIXME: Respect options.
(void) options;
- return FileDescriptor::create(device);
+ (void) error;
+ return FileDescriptor::create(move(device));
}
RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options, InodeIdentifier base)
@@ -148,7 +149,7 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
kprintf("VFS::open: no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
return nullptr;
}
- return FileDescriptor::create((*it).value);
+ return (*it).value->open(error, options);
}
return FileDescriptor::create(move(inode));
}
diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h
index 86a19e62f5..4472eb5e34 100644
--- a/VirtualFileSystem/VirtualFileSystem.h
+++ b/VirtualFileSystem/VirtualFileSystem.h
@@ -63,7 +63,7 @@ public:
bool mount_root(RetainPtr<FS>&&);
bool mount(RetainPtr<FS>&&, const String& path);
- RetainPtr<FileDescriptor> open(CharacterDevice&, int options);
+ RetainPtr<FileDescriptor> open(RetainPtr<CharacterDevice>&&, int& error, int options);
RetainPtr<FileDescriptor> open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier());
RetainPtr<FileDescriptor> create(const String& path, InodeIdentifier base, int& error);
bool mkdir(const String& path, mode_t mode, InodeIdentifier base, int& error);