diff --git a/Kernel/DevPtsFS.cpp b/Kernel/DevPtsFS.cpp new file mode 100644 index 0000000000..a59e31b649 --- /dev/null +++ b/Kernel/DevPtsFS.cpp @@ -0,0 +1,67 @@ +#include "DevPtsFS.h" +#include +#include + +static DevPtsFS* s_the; + +DevPtsFS& DevPtsFS::the() +{ + ASSERT(s_the); + return *s_the; +} + +RetainPtr DevPtsFS::create() +{ + return adopt(*new DevPtsFS); +} + +DevPtsFS::DevPtsFS() +{ + s_the = this; +} + +DevPtsFS::~DevPtsFS() +{ +} + +bool DevPtsFS::initialize() +{ + SynthFS::initialize(); + return true; +} + +const char* DevPtsFS::class_name() const +{ + return "DevPtsFS"; +} + +RetainPtr DevPtsFS::create_slave_pty_device_file(unsigned index) +{ + auto file = adopt(*new SynthFSInode(*this, generate_inode_index())); + + StringBuilder builder; + builder.appendf("%u", index); + file->m_name = builder.build(); + + file->m_metadata.size = 0; + file->m_metadata.uid = 0; + file->m_metadata.gid = 0; + file->m_metadata.mode = 0020666; + file->m_metadata.majorDevice = 11; + file->m_metadata.minorDevice = index; + file->m_metadata.mtime = mepoch; + return file; +} + +void DevPtsFS::register_slave_pty(SlavePTY& slave_pty) +{ + InterruptDisabler disabler; + auto inode_id = add_file(create_slave_pty_device_file(slave_pty.index())); + slave_pty.set_devpts_inode_id(inode_id); +} + +void DevPtsFS::unregister_slave_pty(SlavePTY& slave_pty) +{ + InterruptDisabler disabler; + remove_file(slave_pty.devpts_inode_id().index()); +} diff --git a/Kernel/DevPtsFS.h b/Kernel/DevPtsFS.h new file mode 100644 index 0000000000..6c98e6e639 --- /dev/null +++ b/Kernel/DevPtsFS.h @@ -0,0 +1,29 @@ +#pragma once + +#include "SlavePTY.h" +#include +#include + +class Process; + +class DevPtsFS final : public SynthFS { +public: + static DevPtsFS& the() PURE; + + virtual ~DevPtsFS() override; + static RetainPtr create(); + + virtual bool initialize() override; + virtual const char* class_name() const override; + + void register_slave_pty(SlavePTY&); + void unregister_slave_pty(SlavePTY&); + +private: + DevPtsFS(); + + RetainPtr create_slave_pty_device_file(unsigned index); + + HashTable m_slave_ptys; +}; + diff --git a/Kernel/Makefile b/Kernel/Makefile index e253c5b7c7..3c572674b5 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -29,6 +29,7 @@ KERNEL_OBJS = \ ELFImage.o \ ELFLoader.o \ KSyms.o \ + DevPtsFS.o \ PS2MouseDevice.o \ GUIEventDevice.o diff --git a/Kernel/MasterPTY.cpp b/Kernel/MasterPTY.cpp index caacf08c95..5ee7fee65a 100644 --- a/Kernel/MasterPTY.cpp +++ b/Kernel/MasterPTY.cpp @@ -6,7 +6,6 @@ MasterPTY::MasterPTY(unsigned index) , m_slave(*new SlavePTY(*this, index)) , m_index(index) { - VFS::the().register_character_device(m_slave); } MasterPTY::~MasterPTY() @@ -16,7 +15,7 @@ MasterPTY::~MasterPTY() String MasterPTY::pts_name() const { char buffer[32]; - ksprintf(buffer, "/dev/pts%u", m_index); + ksprintf(buffer, "/dev/pts/%u", m_index); return buffer; } diff --git a/Kernel/PTYMultiplexer.cpp b/Kernel/PTYMultiplexer.cpp index 33a1e3cc0f..95da1b96a7 100644 --- a/Kernel/PTYMultiplexer.cpp +++ b/Kernel/PTYMultiplexer.cpp @@ -2,12 +2,14 @@ #include "MasterPTY.h" #include +static const unsigned s_max_pty_pairs = 8; + PTYMultiplexer::PTYMultiplexer() : CharacterDevice(5, 2) { - m_freelist.ensure_capacity(4); - for (int i = 4; i > 0; --i) - m_freelist.unchecked_append(adopt(*new MasterPTY(i - 1))); + m_freelist.ensure_capacity(s_max_pty_pairs); + for (int i = s_max_pty_pairs; i > 0; --i) + m_freelist.unchecked_append(i - 1); } PTYMultiplexer::~PTYMultiplexer() @@ -21,7 +23,8 @@ RetainPtr PTYMultiplexer::open(int& error, int options) error = -EBUSY; return nullptr; } - auto master = m_freelist.take_last(); + auto master_index = m_freelist.take_last(); + auto master = adopt(*new MasterPTY(master_index)); 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 index 44981e4749..ee338fd135 100644 --- a/Kernel/PTYMultiplexer.h +++ b/Kernel/PTYMultiplexer.h @@ -23,5 +23,5 @@ private: virtual const char* class_name() const override { return "PTYMultiplexer"; } Lock m_lock; - Vector> m_freelist; + Vector m_freelist; }; diff --git a/Kernel/SlavePTY.cpp b/Kernel/SlavePTY.cpp index 226be88b9c..6185f590bc 100644 --- a/Kernel/SlavePTY.cpp +++ b/Kernel/SlavePTY.cpp @@ -1,22 +1,26 @@ #include "SlavePTY.h" #include "MasterPTY.h" +#include "DevPtsFS.h" SlavePTY::SlavePTY(MasterPTY& master, unsigned index) : TTY(11, index) , m_master(master) , m_index(index) { + VFS::the().register_character_device(*this); + DevPtsFS::the().register_slave_pty(*this); set_size(80, 25); } SlavePTY::~SlavePTY() { + DevPtsFS::the().unregister_slave_pty(*this); } String SlavePTY::tty_name() const { char buffer[32]; - ksprintf(buffer, "/dev/pts%u", m_index); + ksprintf(buffer, "/dev/pts/%u", m_index); return buffer; } diff --git a/Kernel/SlavePTY.h b/Kernel/SlavePTY.h index 23aa996840..4d7fcaf147 100644 --- a/Kernel/SlavePTY.h +++ b/Kernel/SlavePTY.h @@ -11,6 +11,9 @@ public: void on_master_write(const byte*, size_t); unsigned index() const { return m_index; } + InodeIdentifier devpts_inode_id() const { return m_devpts_inode_id; } + void set_devpts_inode_id(InodeIdentifier inode_id) { m_devpts_inode_id = inode_id; } + private: // ^TTY virtual String tty_name() const override; @@ -25,5 +28,6 @@ private: MasterPTY& m_master; unsigned m_index; + InodeIdentifier m_devpts_inode_id; }; diff --git a/Kernel/SyntheticFileSystem.h b/Kernel/SyntheticFileSystem.h index 765eb6a146..a001c5b913 100644 --- a/Kernel/SyntheticFileSystem.h +++ b/Kernel/SyntheticFileSystem.h @@ -45,6 +45,7 @@ struct SynthFSInodeCustomData { class SynthFSInode final : public Inode { friend class SynthFS; + friend class DevPtsFS; public: virtual ~SynthFSInode() override; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 46711f4c0b..37d9bdde11 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -22,6 +22,7 @@ #include "Scheduler.h" #include "PS2MouseDevice.h" #include "PTYMultiplexer.h" +#include "DevPtsFS.h" //#define SPAWN_GUITEST #define SPAWN_GUITEST2 @@ -95,6 +96,7 @@ static void init_stage2() load_ksyms(); vfs->mount(ProcFS::the(), "/proc"); + vfs->mount(DevPtsFS::the(), "/dev/pts"); Vector environment; environment.append("TERM=ansi"); @@ -167,6 +169,9 @@ void init() auto procfs = ProcFS::create(); procfs->initialize(); + auto devptsfs = DevPtsFS::create(); + devptsfs->initialize(); + Process::initialize(); Process::create_kernel_process("init_stage2", init_stage2); Process::create_kernel_process("syncd", [] { diff --git a/Kernel/sync.sh b/Kernel/sync.sh index ae578d2fdd..d0fe75f92c 100755 --- a/Kernel/sync.sh +++ b/Kernel/sync.sh @@ -11,14 +11,7 @@ mknod mnt/dev/tty3 c 4 3 mknod mnt/dev/keyboard c 85 1 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 -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 +mkdir mnt/dev/pts mknod mnt/dev/gui_events c 66 1 cp -R ../Base/* mnt/ cp -v ../Userland/sh mnt/bin/sh diff --git a/Userland/sh.cpp b/Userland/sh.cpp index bac8b67949..8b6b788c51 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -14,7 +14,6 @@ struct GlobalState { String cwd; String username; - const char* ttyname_short { nullptr }; char ttyname[32]; char hostname[32]; pid_t sid; @@ -356,7 +355,7 @@ static void greeting() perror("uname"); return; } - printf("\n%s/%s on %s\n\n", uts.sysname, uts.machine, g->ttyname_short); + printf("\n%s/%s on %s\n\n", uts.sysname, uts.machine, g->ttyname); } int main(int, char**) @@ -384,8 +383,7 @@ int main(int, char**) rc = ttyname_r(0, g->ttyname, sizeof(g->ttyname)); if (rc < 0) perror("ttyname_r"); - else - g->ttyname_short = strrchr(g->ttyname, '/') + 1; + { auto* pw = getpwuid(getuid()); if (pw)