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:
parent
c30e2c8d44
commit
e9b948103d
12 changed files with 124 additions and 20 deletions
67
Kernel/DevPtsFS.cpp
Normal file
67
Kernel/DevPtsFS.cpp
Normal 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
29
Kernel/DevPtsFS.h
Normal 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;
|
||||||
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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", [] {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue