1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-20 13:45:06 +00:00

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.
This commit is contained in:
Andreas Kling 2019-01-30 00:49:20 +01:00
parent c30e2c8d44
commit e9b948103d
12 changed files with 124 additions and 20 deletions

67
Kernel/DevPtsFS.cpp Normal file
View file

@ -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
Kernel/DevPtsFS.h Normal file
View file

@ -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;
};

View file

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

View file

@ -6,7 +6,6 @@ MasterPTY::MasterPTY(unsigned index)
, m_slave(*new SlavePTY(*this, index)) , m_slave(*new SlavePTY(*this, index))
, m_index(index) , m_index(index)
{ {
VFS::the().register_character_device(m_slave);
} }
MasterPTY::~MasterPTY() MasterPTY::~MasterPTY()
@ -16,7 +15,7 @@ MasterPTY::~MasterPTY()
String MasterPTY::pts_name() const String MasterPTY::pts_name() const
{ {
char buffer[32]; char buffer[32];
ksprintf(buffer, "/dev/pts%u", m_index); ksprintf(buffer, "/dev/pts/%u", m_index);
return buffer; return buffer;
} }

View file

@ -2,12 +2,14 @@
#include "MasterPTY.h" #include "MasterPTY.h"
#include <LibC/errno_numbers.h> #include <LibC/errno_numbers.h>
static const unsigned s_max_pty_pairs = 8;
PTYMultiplexer::PTYMultiplexer() PTYMultiplexer::PTYMultiplexer()
: CharacterDevice(5, 2) : CharacterDevice(5, 2)
{ {
m_freelist.ensure_capacity(4); m_freelist.ensure_capacity(s_max_pty_pairs);
for (int i = 4; i > 0; --i) for (int i = s_max_pty_pairs; i > 0; --i)
m_freelist.unchecked_append(adopt(*new MasterPTY(i - 1))); m_freelist.unchecked_append(i - 1);
} }
PTYMultiplexer::~PTYMultiplexer() PTYMultiplexer::~PTYMultiplexer()
@ -21,7 +23,8 @@ RetainPtr<FileDescriptor> PTYMultiplexer::open(int& error, int options)
error = -EBUSY; error = -EBUSY;
return nullptr; 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()); dbgprintf("PTYMultiplexer::open: Vending master %u\n", master->index());
return VFS::the().open(move(master), error, options); return VFS::the().open(move(master), error, options);
} }

View file

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

View file

@ -1,22 +1,26 @@
#include "SlavePTY.h" #include "SlavePTY.h"
#include "MasterPTY.h" #include "MasterPTY.h"
#include "DevPtsFS.h"
SlavePTY::SlavePTY(MasterPTY& master, unsigned index) SlavePTY::SlavePTY(MasterPTY& master, unsigned index)
: TTY(11, index) : TTY(11, index)
, m_master(master) , m_master(master)
, m_index(index) , m_index(index)
{ {
VFS::the().register_character_device(*this);
DevPtsFS::the().register_slave_pty(*this);
set_size(80, 25); set_size(80, 25);
} }
SlavePTY::~SlavePTY() SlavePTY::~SlavePTY()
{ {
DevPtsFS::the().unregister_slave_pty(*this);
} }
String SlavePTY::tty_name() const String SlavePTY::tty_name() const
{ {
char buffer[32]; char buffer[32];
ksprintf(buffer, "/dev/pts%u", m_index); ksprintf(buffer, "/dev/pts/%u", m_index);
return buffer; return buffer;
} }

View file

@ -11,6 +11,9 @@ public:
void on_master_write(const byte*, size_t); void on_master_write(const byte*, size_t);
unsigned index() const { return m_index; } 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: private:
// ^TTY // ^TTY
virtual String tty_name() const override; virtual String tty_name() const override;
@ -25,5 +28,6 @@ private:
MasterPTY& m_master; MasterPTY& m_master;
unsigned m_index; unsigned m_index;
InodeIdentifier m_devpts_inode_id;
}; };

View file

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

View file

@ -22,6 +22,7 @@
#include "Scheduler.h" #include "Scheduler.h"
#include "PS2MouseDevice.h" #include "PS2MouseDevice.h"
#include "PTYMultiplexer.h" #include "PTYMultiplexer.h"
#include "DevPtsFS.h"
//#define SPAWN_GUITEST //#define SPAWN_GUITEST
#define SPAWN_GUITEST2 #define SPAWN_GUITEST2
@ -95,6 +96,7 @@ static void init_stage2()
load_ksyms(); load_ksyms();
vfs->mount(ProcFS::the(), "/proc"); vfs->mount(ProcFS::the(), "/proc");
vfs->mount(DevPtsFS::the(), "/dev/pts");
Vector<String> environment; Vector<String> environment;
environment.append("TERM=ansi"); environment.append("TERM=ansi");
@ -167,6 +169,9 @@ void init()
auto procfs = ProcFS::create(); auto procfs = ProcFS::create();
procfs->initialize(); procfs->initialize();
auto devptsfs = DevPtsFS::create();
devptsfs->initialize();
Process::initialize(); Process::initialize();
Process::create_kernel_process("init_stage2", init_stage2); Process::create_kernel_process("init_stage2", init_stage2);
Process::create_kernel_process("syncd", [] { Process::create_kernel_process("syncd", [] {

View file

@ -11,14 +11,7 @@ mknod mnt/dev/tty3 c 4 3
mknod mnt/dev/keyboard c 85 1 mknod mnt/dev/keyboard c 85 1
mknod mnt/dev/psaux c 10 1 mknod mnt/dev/psaux c 10 1
mknod mnt/dev/ptmx c 5 2 mknod mnt/dev/ptmx c 5 2
mknod mnt/dev/ptm0 c 10 0 mkdir mnt/dev/pts
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 mknod mnt/dev/gui_events c 66 1
cp -R ../Base/* mnt/ cp -R ../Base/* mnt/
cp -v ../Userland/sh mnt/bin/sh cp -v ../Userland/sh mnt/bin/sh

View file

@ -14,7 +14,6 @@
struct GlobalState { struct GlobalState {
String cwd; String cwd;
String username; String username;
const char* ttyname_short { nullptr };
char ttyname[32]; char ttyname[32];
char hostname[32]; char hostname[32];
pid_t sid; pid_t sid;
@ -356,7 +355,7 @@ static void greeting()
perror("uname"); perror("uname");
return; 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**) int main(int, char**)
@ -384,8 +383,7 @@ int main(int, char**)
rc = ttyname_r(0, g->ttyname, sizeof(g->ttyname)); rc = ttyname_r(0, g->ttyname, sizeof(g->ttyname));
if (rc < 0) if (rc < 0)
perror("ttyname_r"); perror("ttyname_r");
else
g->ttyname_short = strrchr(g->ttyname, '/') + 1;
{ {
auto* pw = getpwuid(getuid()); auto* pw = getpwuid(getuid());
if (pw) if (pw)