forked from Bananymous/banan-os
Kernel: Rework syscall calling
I removed the intermediate function when calling syscalls. Now syscall handler calls the current process automatically. Only exception is sys_fork, since it needs a assembly trampoline for the new thread.
This commit is contained in:
parent
ce55422a24
commit
bf617036c7
|
@ -121,7 +121,7 @@ namespace IDT
|
|||
if (tid && Kernel::Thread::current().is_userspace() && !Kernel::Thread::current().is_in_syscall())
|
||||
{
|
||||
auto message = BAN::String::formatted("{}, aborting\n", isr_exceptions[isr]);
|
||||
(void)Kernel::Process::current().write(STDERR_FILENO, message.data(), message.size());
|
||||
(void)Kernel::Process::current().sys_write(STDERR_FILENO, message.data(), message.size());
|
||||
asm volatile("sti");
|
||||
Kernel::Process::current().exit(1);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <kernel/Thread.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
|
||||
namespace LibELF { class ELF; }
|
||||
|
||||
|
@ -46,60 +47,60 @@ namespace Kernel
|
|||
void add_thread(Thread*);
|
||||
void on_thread_exit(Thread&);
|
||||
|
||||
BAN::ErrorOr<void> set_termios(const termios&);
|
||||
|
||||
pid_t pid() const { return m_pid; }
|
||||
|
||||
BAN::ErrorOr<Process*> fork(uintptr_t rsp, uintptr_t rip);
|
||||
BAN::ErrorOr<void> exec(BAN::StringView path, const char* const* argv, const char* const* envp);
|
||||
BAN::ErrorOr<long> sys_exit(int status);
|
||||
|
||||
int block_until_exit();
|
||||
BAN::ErrorOr<pid_t> wait(pid_t pid, int* stat_loc, int options);
|
||||
BAN::ErrorOr<long> sys_gettermios(::termios*);
|
||||
BAN::ErrorOr<long> sys_settermios(const ::termios*);
|
||||
|
||||
BAN::ErrorOr<void> setenvp(char** envp);
|
||||
BAN::ErrorOr<long> sys_fork(uintptr_t rsp, uintptr_t rip);
|
||||
BAN::ErrorOr<long> sys_exec(BAN::StringView path, const char* const* argv, const char* const* envp);
|
||||
|
||||
BAN::ErrorOr<void> set_pwd(const char* path);
|
||||
BAN::ErrorOr<char*> get_pwd(char* buffer, size_t size);
|
||||
BAN::ErrorOr<long> sys_wait(pid_t pid, int* stat_loc, int options);
|
||||
BAN::ErrorOr<long> sys_sleep(int seconds);
|
||||
|
||||
BAN::ErrorOr<void> set_uid(uid_t);
|
||||
BAN::ErrorOr<void> set_gid(gid_t);
|
||||
BAN::ErrorOr<void> set_euid(uid_t);
|
||||
BAN::ErrorOr<void> set_egid(gid_t);
|
||||
BAN::ErrorOr<void> set_reuid(uid_t, uid_t);
|
||||
BAN::ErrorOr<void> set_regid(gid_t, gid_t);
|
||||
BAN::ErrorOr<long> sys_setenvp(char** envp);
|
||||
|
||||
uid_t get_uid() const { return m_credentials.ruid(); }
|
||||
gid_t get_gid() const { return m_credentials.rgid(); }
|
||||
uid_t get_euid() const { return m_credentials.euid(); }
|
||||
gid_t get_egid() const { return m_credentials.egid(); }
|
||||
BAN::ErrorOr<long> sys_setpwd(const char* path);
|
||||
BAN::ErrorOr<long> sys_getpwd(char* buffer, size_t size);
|
||||
|
||||
BAN::ErrorOr<int> open(BAN::StringView, int);
|
||||
BAN::ErrorOr<int> openat(int, BAN::StringView, int);
|
||||
BAN::ErrorOr<void> close(int fd);
|
||||
BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t count);
|
||||
BAN::ErrorOr<size_t> write(int fd, const void* buffer, size_t count);
|
||||
BAN::ErrorOr<void> creat(BAN::StringView name, mode_t);
|
||||
BAN::ErrorOr<long> sys_setuid(uid_t);
|
||||
BAN::ErrorOr<long> sys_setgid(gid_t);
|
||||
BAN::ErrorOr<long> sys_seteuid(uid_t);
|
||||
BAN::ErrorOr<long> sys_setegid(gid_t);
|
||||
BAN::ErrorOr<long> sys_setreuid(uid_t, uid_t);
|
||||
BAN::ErrorOr<long> sys_setregid(gid_t, gid_t);
|
||||
|
||||
BAN::ErrorOr<void> seek(int fd, off_t offset, int whence);
|
||||
BAN::ErrorOr<off_t> tell(int fd);
|
||||
BAN::ErrorOr<long> sys_getuid() const { return m_credentials.ruid(); }
|
||||
BAN::ErrorOr<long> sys_getgid() const { return m_credentials.rgid(); }
|
||||
BAN::ErrorOr<long> sys_geteuid() const { return m_credentials.euid(); }
|
||||
BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); }
|
||||
|
||||
BAN::ErrorOr<void> fstat(int fd, struct stat*);
|
||||
BAN::ErrorOr<void> stat(BAN::StringView path, struct stat*, int flags);
|
||||
BAN::ErrorOr<long> sys_open(BAN::StringView, int);
|
||||
BAN::ErrorOr<long> sys_openat(int, BAN::StringView, int);
|
||||
BAN::ErrorOr<long> sys_close(int fd);
|
||||
BAN::ErrorOr<long> sys_read(int fd, void* buffer, size_t count);
|
||||
BAN::ErrorOr<long> sys_write(int fd, const void* buffer, size_t count);
|
||||
BAN::ErrorOr<long> sys_creat(BAN::StringView name, mode_t);
|
||||
|
||||
BAN::ErrorOr<long> sys_seek(int fd, off_t offset, int whence);
|
||||
BAN::ErrorOr<long> sys_tell(int fd);
|
||||
|
||||
BAN::ErrorOr<long> sys_fstat(int fd, struct stat*);
|
||||
BAN::ErrorOr<long> sys_stat(BAN::StringView path, struct stat*, int flags);
|
||||
|
||||
BAN::ErrorOr<void> mount(BAN::StringView source, BAN::StringView target);
|
||||
|
||||
BAN::ErrorOr<void> read_next_directory_entries(int fd, DirectoryEntryList* buffer, size_t buffer_size);
|
||||
BAN::ErrorOr<long> sys_read_dir_entries(int fd, DirectoryEntryList* buffer, size_t buffer_size);
|
||||
|
||||
BAN::ErrorOr<BAN::String> working_directory() const;
|
||||
BAN::ErrorOr<void> set_working_directory(BAN::StringView);
|
||||
BAN::ErrorOr<long> sys_alloc(size_t);
|
||||
BAN::ErrorOr<long> sys_free(void*);
|
||||
|
||||
BAN::ErrorOr<long> sys_termid(char*) const;
|
||||
|
||||
TTY& tty() { ASSERT(m_tty); return *m_tty; }
|
||||
|
||||
BAN::ErrorOr<void*> allocate(size_t);
|
||||
void free(void*);
|
||||
|
||||
void termid(char*) const;
|
||||
|
||||
static Process& current() { return Thread::current().process(); }
|
||||
|
||||
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
||||
|
@ -117,6 +118,8 @@ namespace Kernel
|
|||
// Copy an elf file from the current page table to the processes own
|
||||
void load_elf_to_memory(LibELF::ELF&);
|
||||
|
||||
int block_until_exit();
|
||||
|
||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -37,15 +37,15 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<Font> Font::load(BAN::StringView path)
|
||||
{
|
||||
int fd = TRY(Process::current().open(path, O_RDONLY));
|
||||
BAN::ScopeGuard _([fd] { MUST(Process::current().close(fd)); });
|
||||
int fd = TRY(Process::current().sys_open(path, O_RDONLY));
|
||||
BAN::ScopeGuard _([fd] { MUST(Process::current().sys_close(fd)); });
|
||||
|
||||
struct stat st;
|
||||
TRY(Process::current().fstat(fd, &st));
|
||||
TRY(Process::current().sys_fstat(fd, &st));
|
||||
|
||||
BAN::Vector<uint8_t> file_data;
|
||||
TRY(file_data.resize(st.st_size));
|
||||
TRY(Process::current().read(fd, file_data.data(), st.st_size));
|
||||
TRY(Process::current().sys_read(fd, file_data.data(), st.st_size));
|
||||
|
||||
if (file_data.size() < 4)
|
||||
return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall);
|
||||
|
|
|
@ -65,15 +65,15 @@ namespace Kernel
|
|||
{
|
||||
PageTableScope _(process->page_table());
|
||||
|
||||
argv = (char**)MUST(process->allocate(sizeof(char**) * 2));
|
||||
argv[0] = (char*)MUST(process->allocate(path.size() + 1));
|
||||
argv = (char**)MUST(process->sys_alloc(sizeof(char**) * 2));
|
||||
argv[0] = (char*)MUST(process->sys_alloc(path.size() + 1));
|
||||
memcpy(argv[0], path.data(), path.size());
|
||||
argv[0][path.size()] = '\0';
|
||||
argv[1] = nullptr;
|
||||
|
||||
BAN::StringView env1 = "PATH=/bin:/usr/bin"sv;
|
||||
envp = (char**)MUST(process->allocate(sizeof(char**) * 2));
|
||||
envp[0] = (char*)MUST(process->allocate(env1.size() + 1));
|
||||
envp = (char**)MUST(process->sys_alloc(sizeof(char**) * 2));
|
||||
envp[0] = (char*)MUST(process->sys_alloc(env1.size() + 1));
|
||||
memcpy(envp[0], env1.data(), env1.size());
|
||||
envp[0][env1.size()] = '\0';
|
||||
envp[1] = nullptr;
|
||||
|
@ -159,13 +159,40 @@ namespace Kernel
|
|||
Scheduler::get().set_current_process_done();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_termios(const termios& termios)
|
||||
BAN::ErrorOr<long> Process::sys_exit(int status)
|
||||
{
|
||||
exit(status);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_gettermios(::termios* termios)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
if (m_tty == nullptr)
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
m_tty->set_termios(termios);
|
||||
return {};
|
||||
|
||||
Kernel::termios ktermios = m_tty->get_termios();
|
||||
termios->c_lflag = 0;
|
||||
if (ktermios.canonical)
|
||||
termios->c_lflag |= ICANON;
|
||||
if (ktermios.echo)
|
||||
termios->c_lflag |= ECHO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_settermios(const ::termios* termios)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
if (m_tty == nullptr)
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
Kernel::termios ktermios;
|
||||
ktermios.echo = termios->c_lflag & ECHO;
|
||||
ktermios.canonical = termios->c_lflag & ICANON;
|
||||
|
||||
m_tty->set_termios(ktermios);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<LibELF::ELF>> Process::load_elf_for_exec(const Credentials& credentials, BAN::StringView file_path, const BAN::String& cwd, const BAN::Vector<BAN::StringView>& path_env)
|
||||
|
@ -241,7 +268,7 @@ namespace Kernel
|
|||
return BAN::move(elf);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<Process*> Process::fork(uintptr_t rsp, uintptr_t rip)
|
||||
BAN::ErrorOr<long> Process::sys_fork(uintptr_t rsp, uintptr_t rip)
|
||||
{
|
||||
Process* forked = create_process(m_credentials);
|
||||
|
||||
|
@ -271,10 +298,10 @@ namespace Kernel
|
|||
|
||||
register_process(forked);
|
||||
|
||||
return forked;
|
||||
return forked->pid();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::exec(BAN::StringView path, const char* const* argv, const char* const* envp)
|
||||
BAN::ErrorOr<long> Process::sys_exec(BAN::StringView path, const char* const* argv, const char* const* envp)
|
||||
{
|
||||
BAN::Vector<BAN::String> str_argv;
|
||||
for (int i = 0; argv && argv[i]; i++)
|
||||
|
@ -289,7 +316,14 @@ namespace Kernel
|
|||
path_env = TRY(BAN::StringView(envp[i]).substring(5).split(':'));
|
||||
}
|
||||
|
||||
auto elf = TRY(load_elf_for_exec(m_credentials, path, TRY(working_directory()), path_env));
|
||||
BAN::String working_directory;
|
||||
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
TRY(working_directory.append(m_working_directory));
|
||||
}
|
||||
|
||||
auto elf = TRY(load_elf_for_exec(m_credentials, path, working_directory, path_env));
|
||||
|
||||
LockGuard lock_guard(m_lock);
|
||||
|
||||
|
@ -313,19 +347,19 @@ namespace Kernel
|
|||
{
|
||||
LockGuard _(page_table());
|
||||
|
||||
m_userspace_info.argv = (char**)MUST(allocate(sizeof(char**) * (str_argv.size() + 1)));
|
||||
m_userspace_info.argv = (char**)MUST(sys_alloc(sizeof(char**) * (str_argv.size() + 1)));
|
||||
for (size_t i = 0; i < str_argv.size(); i++)
|
||||
{
|
||||
m_userspace_info.argv[i] = (char*)MUST(allocate(str_argv[i].size() + 1));
|
||||
m_userspace_info.argv[i] = (char*)MUST(sys_alloc(str_argv[i].size() + 1));
|
||||
memcpy(m_userspace_info.argv[i], str_argv[i].data(), str_argv[i].size());
|
||||
m_userspace_info.argv[i][str_argv[i].size()] = '\0';
|
||||
}
|
||||
m_userspace_info.argv[str_argv.size()] = nullptr;
|
||||
|
||||
m_userspace_info.envp = (char**)MUST(allocate(sizeof(char**) * (str_envp.size() + 1)));
|
||||
m_userspace_info.envp = (char**)MUST(sys_alloc(sizeof(char**) * (str_envp.size() + 1)));
|
||||
for (size_t i = 0; i < str_envp.size(); i++)
|
||||
{
|
||||
m_userspace_info.envp[i] = (char*)MUST(allocate(str_envp[i].size() + 1));
|
||||
m_userspace_info.envp[i] = (char*)MUST(sys_alloc(str_envp[i].size() + 1));
|
||||
memcpy(m_userspace_info.envp[i], str_envp[i].data(), str_envp[i].size());
|
||||
m_userspace_info.envp[i][str_envp[i].size()] = '\0';
|
||||
}
|
||||
|
@ -370,7 +404,7 @@ namespace Kernel
|
|||
return ret;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<pid_t> Process::wait(pid_t pid, int* stat_loc, int options)
|
||||
BAN::ErrorOr<long> Process::sys_wait(pid_t pid, int* stat_loc, int options)
|
||||
{
|
||||
Process* target = nullptr;
|
||||
|
||||
|
@ -392,11 +426,17 @@ namespace Kernel
|
|||
return ret;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::setenvp(char** envp)
|
||||
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
||||
{
|
||||
PIT::sleep(seconds * 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_setenvp(char** envp)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
m_userspace_info.envp = envp;
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Process::load_elf_to_memory(LibELF::ELF& elf)
|
||||
|
@ -450,7 +490,7 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<int> Process::open(BAN::StringView path, int flags)
|
||||
BAN::ErrorOr<long> Process::sys_open(BAN::StringView path, int flags)
|
||||
{
|
||||
if (flags & ~(O_RDONLY | O_WRONLY | O_NOFOLLOW | O_SEARCH))
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
@ -470,7 +510,7 @@ namespace Kernel
|
|||
return fd;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<int> Process::openat(int fd, BAN::StringView path, int flags)
|
||||
BAN::ErrorOr<long> Process::sys_openat(int fd, BAN::StringView path, int flags)
|
||||
{
|
||||
BAN::String absolute_path;
|
||||
|
||||
|
@ -483,19 +523,19 @@ namespace Kernel
|
|||
TRY(absolute_path.push_back('/'));
|
||||
TRY(absolute_path.append(path));
|
||||
|
||||
return open(absolute_path, flags);
|
||||
return sys_open(absolute_path, flags);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::close(int fd)
|
||||
BAN::ErrorOr<long> Process::sys_close(int fd)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
TRY(validate_fd(fd));
|
||||
auto& open_file_description = this->open_file_description(fd);
|
||||
open_file_description.inode = nullptr;
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> Process::read(int fd, void* buffer, size_t count)
|
||||
BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count)
|
||||
{
|
||||
OpenFileDescription open_fd_copy;
|
||||
|
||||
|
@ -519,7 +559,7 @@ namespace Kernel
|
|||
return nread;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> Process::write(int fd, const void* buffer, size_t count)
|
||||
BAN::ErrorOr<long> Process::sys_write(int fd, const void* buffer, size_t count)
|
||||
{
|
||||
OpenFileDescription open_fd_copy;
|
||||
|
||||
|
@ -543,7 +583,7 @@ namespace Kernel
|
|||
return nwrite;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::seek(int fd, off_t offset, int whence)
|
||||
BAN::ErrorOr<long> Process::sys_seek(int fd, off_t offset, int whence)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
TRY(validate_fd(fd));
|
||||
|
@ -571,17 +611,17 @@ namespace Kernel
|
|||
return BAN::Error::from_errno(EINVAL);
|
||||
open_fd.offset = new_offset;
|
||||
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<off_t> Process::tell(int fd)
|
||||
BAN::ErrorOr<long> Process::sys_tell(int fd)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
TRY(validate_fd(fd));
|
||||
return open_file_description(fd).offset;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode)
|
||||
BAN::ErrorOr<long> Process::sys_creat(BAN::StringView path, mode_t mode)
|
||||
{
|
||||
auto absolute_path = TRY(absolute_path_of(path));
|
||||
|
||||
|
@ -596,7 +636,7 @@ namespace Kernel
|
|||
auto parent_file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, directory, O_WRONLY));
|
||||
TRY(parent_file.inode->create_file(file_name, mode));
|
||||
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::mount(BAN::StringView source, BAN::StringView target)
|
||||
|
@ -611,7 +651,7 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::fstat(int fd, struct stat* out)
|
||||
BAN::ErrorOr<long> Process::sys_fstat(int fd, struct stat* out)
|
||||
{
|
||||
OpenFileDescription open_fd_copy;
|
||||
|
||||
|
@ -635,18 +675,18 @@ namespace Kernel
|
|||
out->st_blksize = open_fd_copy.inode->blksize();
|
||||
out->st_blocks = open_fd_copy.inode->blocks();
|
||||
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::stat(BAN::StringView path, struct stat* out, int flags)
|
||||
BAN::ErrorOr<long> Process::sys_stat(BAN::StringView path, struct stat* out, int flags)
|
||||
{
|
||||
int fd = TRY(open(path, flags));
|
||||
auto ret = fstat(fd, out);
|
||||
MUST(close(fd));
|
||||
int fd = TRY(sys_open(path, flags));
|
||||
auto ret = sys_fstat(fd, out);
|
||||
MUST(sys_close(fd));
|
||||
return ret;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::read_next_directory_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
||||
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
||||
{
|
||||
OpenFileDescription open_fd_copy;
|
||||
|
||||
|
@ -664,10 +704,10 @@ namespace Kernel
|
|||
open_file_description(fd).offset = open_fd_copy.offset + 1;
|
||||
}
|
||||
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_pwd(const char* path)
|
||||
BAN::ErrorOr<long> Process::sys_setpwd(const char* path)
|
||||
{
|
||||
BAN::String absolute_path;
|
||||
|
||||
|
@ -683,10 +723,10 @@ namespace Kernel
|
|||
LockGuard _(m_lock);
|
||||
m_working_directory = BAN::move(file.canonical_path);
|
||||
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<char*> Process::get_pwd(char* buffer, size_t size)
|
||||
BAN::ErrorOr<long> Process::sys_getpwd(char* buffer, size_t size)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
|
||||
|
@ -696,31 +736,7 @@ namespace Kernel
|
|||
memcpy(buffer, m_working_directory.data(), m_working_directory.size());
|
||||
buffer[m_working_directory.size()] = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::String> Process::working_directory() const
|
||||
{
|
||||
BAN::String result;
|
||||
|
||||
LockGuard _(m_lock);
|
||||
TRY(result.append(m_working_directory));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_working_directory(BAN::StringView path)
|
||||
{
|
||||
BAN::String absolute_path = TRY(absolute_path_of(path));
|
||||
|
||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_SEARCH));
|
||||
if (!file.inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
|
||||
LockGuard _(m_lock);
|
||||
m_working_directory = BAN::move(file.canonical_path);
|
||||
|
||||
return {};
|
||||
return (long)buffer;
|
||||
}
|
||||
|
||||
static constexpr size_t allocator_size_for_allocation(size_t value)
|
||||
|
@ -738,7 +754,7 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void*> Process::allocate(size_t bytes)
|
||||
BAN::ErrorOr<long> Process::sys_alloc(size_t bytes)
|
||||
{
|
||||
vaddr_t address = 0;
|
||||
|
||||
|
@ -782,10 +798,10 @@ namespace Kernel
|
|||
|
||||
if (address == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
return (void*)address;
|
||||
return address;
|
||||
}
|
||||
|
||||
void Process::free(void* ptr)
|
||||
BAN::ErrorOr<long> Process::sys_free(void* ptr)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
|
||||
|
@ -798,26 +814,28 @@ namespace Kernel
|
|||
// remove allocators when we have low memory... ?
|
||||
if (allocator->allocations() == 0)
|
||||
m_fixed_width_allocators.remove(i);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_general_allocator && m_general_allocator->deallocate((vaddr_t)ptr))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
dwarnln("free called on pointer that was not allocated");
|
||||
dwarnln("free called on pointer that was not allocated");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
void Process::termid(char* buffer) const
|
||||
BAN::ErrorOr<long> Process::sys_termid(char* buffer) const
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
if (m_tty == nullptr)
|
||||
buffer[0] = '\0';
|
||||
strcpy(buffer, "/dev/");
|
||||
strcpy(buffer + 5, m_tty->name().data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_uid(uid_t uid)
|
||||
BAN::ErrorOr<long> Process::sys_setuid(uid_t uid)
|
||||
{
|
||||
if (uid < 0 || uid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -831,7 +849,7 @@ namespace Kernel
|
|||
m_credentials.set_euid(uid);
|
||||
m_credentials.set_ruid(uid);
|
||||
m_credentials.set_suid(uid);
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the process does not have appropriate privileges, but uid is equal to the real user ID or the saved set-user-ID,
|
||||
|
@ -839,13 +857,13 @@ namespace Kernel
|
|||
if (uid == m_credentials.ruid() || uid == m_credentials.suid())
|
||||
{
|
||||
m_credentials.set_euid(uid);
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_gid(gid_t gid)
|
||||
BAN::ErrorOr<long> Process::sys_setgid(gid_t gid)
|
||||
{
|
||||
if (gid < 0 || gid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -859,7 +877,7 @@ namespace Kernel
|
|||
m_credentials.set_egid(gid);
|
||||
m_credentials.set_rgid(gid);
|
||||
m_credentials.set_sgid(gid);
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the process does not have appropriate privileges, but gid is equal to the real group ID or the saved set-group-ID,
|
||||
|
@ -867,13 +885,13 @@ namespace Kernel
|
|||
if (gid == m_credentials.rgid() || gid == m_credentials.sgid())
|
||||
{
|
||||
m_credentials.set_egid(gid);
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_euid(uid_t uid)
|
||||
BAN::ErrorOr<long> Process::sys_seteuid(uid_t uid)
|
||||
{
|
||||
if (uid < 0 || uid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -885,13 +903,13 @@ namespace Kernel
|
|||
if (uid == m_credentials.ruid() || uid == m_credentials.suid() || m_credentials.is_superuser())
|
||||
{
|
||||
m_credentials.set_euid(uid);
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_egid(gid_t gid)
|
||||
BAN::ErrorOr<long> Process::sys_setegid(gid_t gid)
|
||||
{
|
||||
if (gid < 0 || gid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -904,16 +922,16 @@ namespace Kernel
|
|||
if (gid == m_credentials.rgid() || gid == m_credentials.sgid() || m_credentials.is_superuser())
|
||||
{
|
||||
m_credentials.set_egid(gid);
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_reuid(uid_t ruid, uid_t euid)
|
||||
BAN::ErrorOr<long> Process::sys_setreuid(uid_t ruid, uid_t euid)
|
||||
{
|
||||
if (ruid == -1 && euid == -1)
|
||||
return {};
|
||||
return 0;
|
||||
|
||||
if (ruid < -1 || ruid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -951,13 +969,13 @@ namespace Kernel
|
|||
if (euid != -1)
|
||||
m_credentials.set_euid(euid);
|
||||
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_regid(gid_t rgid, gid_t egid)
|
||||
BAN::ErrorOr<long> Process::sys_setregid(gid_t rgid, gid_t egid)
|
||||
{
|
||||
if (rgid == -1 && egid == -1)
|
||||
return {};
|
||||
return 0;
|
||||
|
||||
if (rgid < -1 || rgid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -995,22 +1013,29 @@ namespace Kernel
|
|||
if (egid != -1)
|
||||
m_credentials.set_egid(egid);
|
||||
|
||||
return {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::String> Process::absolute_path_of(BAN::StringView path) const
|
||||
{
|
||||
if (path.empty())
|
||||
return working_directory();
|
||||
if (path.empty() || path == "."sv)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
return m_working_directory;
|
||||
}
|
||||
|
||||
BAN::String absolute_path;
|
||||
if (path.front() != '/')
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
TRY(absolute_path.append(m_working_directory));
|
||||
}
|
||||
|
||||
if (!absolute_path.empty() && absolute_path.back() != '/')
|
||||
TRY(absolute_path.push_back('/'));
|
||||
|
||||
TRY(absolute_path.append(path));
|
||||
|
||||
return absolute_path;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,243 +7,14 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
void sys_exit(int status)
|
||||
{
|
||||
Process::current().exit(status);
|
||||
}
|
||||
|
||||
long sys_read(int fd, void* buffer, size_t size)
|
||||
{
|
||||
auto res = Process::current().read(fd, buffer, size);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return res.value();
|
||||
}
|
||||
|
||||
long sys_write(int fd, const void* buffer, size_t size)
|
||||
{
|
||||
auto res = Process::current().write(fd, buffer, size);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return res.value();
|
||||
}
|
||||
|
||||
int sys_close(int fd)
|
||||
{
|
||||
auto res = Process::current().close(fd);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_termid(char* buffer)
|
||||
{
|
||||
Process::current().termid(buffer);
|
||||
}
|
||||
|
||||
int sys_open(const char* path, int oflags)
|
||||
{
|
||||
auto res = Process::current().open(path, oflags);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return res.value();
|
||||
}
|
||||
|
||||
int sys_openat(int fd, const char* path, int oflags)
|
||||
{
|
||||
auto res = Process::current().openat(fd, path, oflags);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return res.value();
|
||||
}
|
||||
|
||||
long sys_alloc(size_t bytes)
|
||||
{
|
||||
auto res = Process::current().allocate(bytes);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return (long)res.value();
|
||||
}
|
||||
|
||||
void sys_free(void* ptr)
|
||||
{
|
||||
Process::current().free(ptr);
|
||||
}
|
||||
|
||||
long sys_seek(int fd, long offset, int whence)
|
||||
{
|
||||
auto res = Process::current().seek(fd, offset, whence);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_tell(int fd)
|
||||
{
|
||||
auto res = Process::current().tell(fd);
|
||||
if (res.is_error())
|
||||
return -res.error().get_error_code();
|
||||
return res.value();
|
||||
}
|
||||
|
||||
long sys_get_termios(::termios* termios)
|
||||
{
|
||||
auto current = Process::current().tty().get_termios();
|
||||
memset(termios, 0, sizeof(::termios));
|
||||
if (current.canonical)
|
||||
termios->c_lflag |= ICANON;
|
||||
if (current.echo)
|
||||
termios->c_lflag |= ECHO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_termios(const ::termios* termios)
|
||||
{
|
||||
Kernel::termios new_termios;
|
||||
new_termios.canonical = termios->c_lflag & ICANON;
|
||||
new_termios.echo = termios->c_lflag & ECHO;
|
||||
Process::current().tty().set_termios(new_termios);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" long sys_fork(uintptr_t rsp, uintptr_t rip)
|
||||
{
|
||||
auto ret = Process::current().fork(rsp, rip);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return ret.value()->pid();
|
||||
}
|
||||
|
||||
long sys_exec(const char* pathname, const char* const* argv, const char* const* envp)
|
||||
{
|
||||
auto ret = Process::current().exec(pathname, argv, envp);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
long sys_sleep(unsigned int seconds)
|
||||
{
|
||||
PIT::sleep(seconds * 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_wait(pid_t pid, int* stat_loc, int options)
|
||||
{
|
||||
auto ret = Process::current().wait(pid, stat_loc, options);
|
||||
auto ret = Process::current().sys_fork(rsp, rip);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return ret.value();
|
||||
}
|
||||
|
||||
long sys_fstat(int fd, struct stat* buf)
|
||||
{
|
||||
auto ret = Process::current().fstat(fd, buf);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_setenvp(char** envp)
|
||||
{
|
||||
auto ret = Process::current().setenvp(envp);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_read_dir_entries(int fd, API::DirectoryEntryList* buffer, size_t buffer_size)
|
||||
{
|
||||
auto ret = Process::current().read_next_directory_entries(fd, buffer, buffer_size);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_uid(uid_t uid)
|
||||
{
|
||||
auto ret = Process::current().set_uid(uid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_gid(gid_t gid)
|
||||
{
|
||||
auto ret = Process::current().set_gid(gid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_euid(uid_t uid)
|
||||
{
|
||||
auto ret = Process::current().set_euid(uid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_egid(gid_t gid)
|
||||
{
|
||||
auto ret = Process::current().set_egid(gid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_reuid(uid_t ruid, uid_t euid)
|
||||
{
|
||||
auto ret = Process::current().set_reuid(ruid, euid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_regid(gid_t rgid, gid_t egid)
|
||||
{
|
||||
auto ret = Process::current().set_regid(rgid, egid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_get_uid()
|
||||
{
|
||||
return Process::current().get_uid();
|
||||
}
|
||||
|
||||
long sys_get_gid()
|
||||
{
|
||||
return Process::current().get_gid();
|
||||
}
|
||||
|
||||
long sys_get_euid()
|
||||
{
|
||||
return Process::current().get_euid();
|
||||
}
|
||||
|
||||
long sys_get_egid()
|
||||
{
|
||||
return Process::current().get_egid();
|
||||
}
|
||||
|
||||
long sys_get_pwd(char* buffer, size_t size)
|
||||
{
|
||||
auto ret = Process::current().get_pwd(buffer, size);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return (long)ret.value();
|
||||
}
|
||||
|
||||
long sys_set_pwd(const char* path)
|
||||
{
|
||||
auto ret = Process::current().set_pwd(path);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" long sys_fork_trampoline();
|
||||
|
||||
extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5)
|
||||
|
@ -258,108 +29,108 @@ namespace Kernel
|
|||
(void)arg4;
|
||||
(void)arg5;
|
||||
|
||||
long ret = 0;
|
||||
BAN::ErrorOr<long> ret = BAN::Error::from_errno(ENOSYS);
|
||||
|
||||
switch (syscall)
|
||||
{
|
||||
case SYS_EXIT:
|
||||
sys_exit((int)arg1);
|
||||
ret = Process::current().sys_exit((int)arg1);
|
||||
break;
|
||||
case SYS_READ:
|
||||
ret = sys_read((int)arg1, (void*)arg2, (size_t)arg3);
|
||||
ret = Process::current().sys_read((int)arg1, (void*)arg2, (size_t)arg3);
|
||||
break;
|
||||
case SYS_WRITE:
|
||||
ret = sys_write((int)arg1, (const void*)arg2, (size_t)arg3);
|
||||
ret = Process::current().sys_write((int)arg1, (const void*)arg2, (size_t)arg3);
|
||||
break;
|
||||
case SYS_TERMID:
|
||||
sys_termid((char*)arg1);
|
||||
ret = Process::current().sys_termid((char*)arg1);
|
||||
break;
|
||||
case SYS_CLOSE:
|
||||
ret = sys_close((int)arg1);
|
||||
ret = Process::current().sys_close((int)arg1);
|
||||
break;
|
||||
case SYS_OPEN:
|
||||
ret = sys_open((const char*)arg1, (int)arg2);
|
||||
ret = Process::current().sys_open((const char*)arg1, (int)arg2);
|
||||
break;
|
||||
case SYS_OPENAT:
|
||||
ret = sys_openat((int)arg1, (const char*)arg2, (int)arg3);
|
||||
ret = Process::current().sys_openat((int)arg1, (const char*)arg2, (int)arg3);
|
||||
break;
|
||||
case SYS_ALLOC:
|
||||
ret = sys_alloc((size_t)arg1);
|
||||
ret = Process::current().sys_alloc((size_t)arg1);
|
||||
break;
|
||||
case SYS_FREE:
|
||||
sys_free((void*)arg1);
|
||||
ret = Process::current().sys_free((void*)arg1);
|
||||
break;
|
||||
case SYS_SEEK:
|
||||
ret = sys_seek((int)arg1, (long)arg2, (int)arg3);
|
||||
ret = Process::current().sys_seek((int)arg1, (long)arg2, (int)arg3);
|
||||
break;
|
||||
case SYS_TELL:
|
||||
ret = sys_tell((int)arg1);
|
||||
ret = Process::current().sys_tell((int)arg1);
|
||||
break;
|
||||
case SYS_GET_TERMIOS:
|
||||
ret = sys_get_termios((::termios*)arg1);
|
||||
ret = Process::current().sys_gettermios((::termios*)arg1);
|
||||
break;
|
||||
case SYS_SET_TERMIOS:
|
||||
ret = sys_set_termios((const ::termios*)arg1);
|
||||
ret = Process::current().sys_settermios((const ::termios*)arg1);
|
||||
break;
|
||||
case SYS_FORK:
|
||||
ret = sys_fork_trampoline();
|
||||
break;
|
||||
case SYS_EXEC:
|
||||
ret = sys_exec((const char*)arg1, (const char* const*)arg2, (const char* const*)arg3);
|
||||
ret = Process::current().sys_exec((const char*)arg1, (const char* const*)arg2, (const char* const*)arg3);
|
||||
break;
|
||||
case SYS_SLEEP:
|
||||
ret = sys_sleep((unsigned int)arg1);
|
||||
ret = Process::current().sys_sleep((unsigned int)arg1);
|
||||
break;
|
||||
case SYS_WAIT:
|
||||
ret = sys_wait((pid_t)arg1, (int*)arg2, (int)arg3);
|
||||
ret = Process::current().sys_wait((pid_t)arg1, (int*)arg2, (int)arg3);
|
||||
break;
|
||||
case SYS_FSTAT:
|
||||
ret = sys_fstat((int)arg1, (struct stat*)arg2);
|
||||
ret = Process::current().sys_fstat((int)arg1, (struct stat*)arg2);
|
||||
break;
|
||||
case SYS_SETENVP:
|
||||
ret = sys_setenvp((char**)arg1);
|
||||
ret = Process::current().sys_setenvp((char**)arg1);
|
||||
break;
|
||||
case SYS_READ_DIR_ENTRIES:
|
||||
ret = sys_read_dir_entries((int)arg1, (API::DirectoryEntryList*)arg2, (size_t)arg3);
|
||||
ret = Process::current().sys_read_dir_entries((int)arg1, (API::DirectoryEntryList*)arg2, (size_t)arg3);
|
||||
break;
|
||||
case SYS_SET_UID:
|
||||
ret = sys_set_uid((uid_t)arg1);
|
||||
ret = Process::current().sys_setuid((uid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_GID:
|
||||
ret = sys_set_gid((gid_t)arg1);
|
||||
ret = Process::current().sys_setgid((gid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_EUID:
|
||||
ret = sys_set_euid((uid_t)arg1);
|
||||
ret = Process::current().sys_seteuid((uid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_EGID:
|
||||
ret = sys_set_egid((gid_t)arg1);
|
||||
ret = Process::current().sys_setegid((gid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_REUID:
|
||||
ret = sys_set_reuid((uid_t)arg1, (uid_t)arg2);
|
||||
ret = Process::current().sys_setreuid((uid_t)arg1, (uid_t)arg2);
|
||||
break;
|
||||
case SYS_SET_REGID:
|
||||
ret = sys_set_regid((gid_t)arg1, (gid_t)arg2);
|
||||
ret = Process::current().sys_setregid((gid_t)arg1, (gid_t)arg2);
|
||||
break;
|
||||
case SYS_GET_UID:
|
||||
ret = sys_get_uid();
|
||||
ret = Process::current().sys_getuid();
|
||||
break;
|
||||
case SYS_GET_GID:
|
||||
ret = sys_get_gid();
|
||||
ret = Process::current().sys_getgid();
|
||||
break;
|
||||
case SYS_GET_EUID:
|
||||
ret = sys_get_euid();
|
||||
ret = Process::current().sys_geteuid();
|
||||
break;
|
||||
case SYS_GET_EGID:
|
||||
ret = sys_get_egid();
|
||||
ret = Process::current().sys_getegid();
|
||||
break;
|
||||
case SYS_GET_PWD:
|
||||
ret = sys_get_pwd((char*)arg1, (size_t)arg2);
|
||||
ret = Process::current().sys_getpwd((char*)arg1, (size_t)arg2);
|
||||
break;
|
||||
case SYS_SET_PWD:
|
||||
ret = sys_set_pwd((const char*)arg1);
|
||||
ret = Process::current().sys_setpwd((const char*)arg1);
|
||||
break;
|
||||
default:
|
||||
dwarnln("Unknown syscall {}", syscall);
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -367,7 +138,9 @@ namespace Kernel
|
|||
|
||||
Thread::current().set_in_syscall(false);
|
||||
|
||||
return ret;
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return ret.value();
|
||||
}
|
||||
|
||||
}
|
|
@ -62,11 +62,11 @@ namespace Kernel
|
|||
s_input_process = Process::create_kernel(
|
||||
[](void*)
|
||||
{
|
||||
int fd = MUST(Process::current().open("/dev/input0"sv, O_RDONLY));
|
||||
int fd = MUST(Process::current().sys_open("/dev/input0"sv, O_RDONLY));
|
||||
while (true)
|
||||
{
|
||||
Input::KeyEvent event;
|
||||
ASSERT(MUST(Process::current().read(fd, &event, sizeof(event))) == sizeof(event));
|
||||
ASSERT(MUST(Process::current().sys_read(fd, &event, sizeof(event))) == sizeof(event));
|
||||
TTY::current()->on_key(event);
|
||||
}
|
||||
}, nullptr
|
||||
|
|
Loading…
Reference in New Issue