Browse Source

Add a /dev/pts filesystem and make PTY allocation dynamic.

You can now open as many PTY pairs as you like. Well, it's actually capped
at 8 for now, but it's just a constant and trivial to change.

Unregistering a PTY pair is untested because I didn't want to start
mucking with that in Terminal right now.
Andreas Kling 6 years ago
parent
commit
e9b948103d

+ 67 - 0
Kernel/DevPtsFS.cpp

@@ -0,0 +1,67 @@
+#include "DevPtsFS.h"
+#include <Kernel/VirtualFileSystem.h>
+#include <AK/StringBuilder.h>
+
+static DevPtsFS* s_the;
+
+DevPtsFS& DevPtsFS::the()
+{
+    ASSERT(s_the);
+    return *s_the;
+}
+
+RetainPtr<DevPtsFS> 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<SynthFSInode> 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());
+}

+ 29 - 0
Kernel/DevPtsFS.h

@@ -0,0 +1,29 @@
+#pragma once
+
+#include "SlavePTY.h"
+#include <AK/Types.h>
+#include <Kernel/SyntheticFileSystem.h>
+
+class Process;
+
+class DevPtsFS final : public SynthFS {
+public:
+    static DevPtsFS& the() PURE;
+
+    virtual ~DevPtsFS() override;
+    static RetainPtr<DevPtsFS> 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<SynthFSInode> create_slave_pty_device_file(unsigned index);
+
+    HashTable<SlavePTY*> m_slave_ptys;
+};
+

+ 1 - 0
Kernel/Makefile

@@ -29,6 +29,7 @@ KERNEL_OBJS = \
        ELFImage.o \
        ELFLoader.o \
        KSyms.o \
+       DevPtsFS.o \
        PS2MouseDevice.o \
        GUIEventDevice.o
 

+ 1 - 2
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;
 }
 

+ 7 - 4
Kernel/PTYMultiplexer.cpp

@@ -2,12 +2,14 @@
 #include "MasterPTY.h"
 #include <LibC/errno_numbers.h>
 
+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<FileDescriptor> 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);
 }

+ 1 - 1
Kernel/PTYMultiplexer.h

@@ -23,5 +23,5 @@ private:
     virtual const char* class_name() const override { return "PTYMultiplexer"; }
 
     Lock m_lock;
-    Vector<RetainPtr<MasterPTY>> m_freelist;
+    Vector<unsigned> m_freelist;
 };

+ 5 - 1
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;
 }
 

+ 4 - 0
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;
 };
 

+ 1 - 0
Kernel/SyntheticFileSystem.h

@@ -45,6 +45,7 @@ struct SynthFSInodeCustomData {
 
 class SynthFSInode final : public Inode {
     friend class SynthFS;
+    friend class DevPtsFS;
 public:
     virtual ~SynthFSInode() override;
 

+ 5 - 0
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<String> 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", [] {

+ 1 - 8
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

+ 2 - 4
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)