Compare commits
23 Commits
91d513a672
...
9e79ef2a91
Author | SHA1 | Date |
---|---|---|
Bananymous | 9e79ef2a91 | |
Bananymous | 4d1b32f770 | |
Bananymous | a5a097fa4a | |
Bananymous | ad645f31d0 | |
Bananymous | f08d429851 | |
Bananymous | bac3219a01 | |
Bananymous | 09a527fb12 | |
Bananymous | 58a3a480b9 | |
Bananymous | a12bfe4639 | |
Bananymous | 6cda639869 | |
Bananymous | 2797fe116f | |
Bananymous | e768cd53fb | |
Bananymous | 83e2ad40d6 | |
Bananymous | 7ebd0699e3 | |
Bananymous | 46b1d4d194 | |
Bananymous | f60e265397 | |
Bananymous | 2e642327ea | |
Bananymous | a87ce41030 | |
Bananymous | 0c8cae4cc3 | |
Bananymous | ed325b4a45 | |
Bananymous | 1c67b5e812 | |
Bananymous | b6c964c444 | |
Bananymous | 6fedf06150 |
|
@ -86,6 +86,7 @@ set(KERNEL_SOURCES
|
||||||
kernel/Storage/StorageDevice.cpp
|
kernel/Storage/StorageDevice.cpp
|
||||||
kernel/Syscall.cpp
|
kernel/Syscall.cpp
|
||||||
kernel/Terminal/FramebufferTerminal.cpp
|
kernel/Terminal/FramebufferTerminal.cpp
|
||||||
|
kernel/Terminal/PseudoTerminal.cpp
|
||||||
kernel/Terminal/Serial.cpp
|
kernel/Terminal/Serial.cpp
|
||||||
kernel/Terminal/TTY.cpp
|
kernel/Terminal/TTY.cpp
|
||||||
kernel/Terminal/VirtualTTY.cpp
|
kernel/Terminal/VirtualTTY.cpp
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
Framebuffer = 1,
|
Framebuffer = 1,
|
||||||
TTY,
|
TTY,
|
||||||
Serial,
|
PTSMaster,
|
||||||
Null,
|
Null,
|
||||||
Zero,
|
Zero,
|
||||||
Debug,
|
Debug,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Array.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/ThreadBlocker.h>
|
#include <kernel/ThreadBlocker.h>
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return !m_buffer.empty(); }
|
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
|
|
||||||
|
@ -46,10 +47,13 @@ namespace Kernel
|
||||||
timespec m_atime {};
|
timespec m_atime {};
|
||||||
timespec m_mtime {};
|
timespec m_mtime {};
|
||||||
timespec m_ctime {};
|
timespec m_ctime {};
|
||||||
BAN::Vector<uint8_t> m_buffer;
|
|
||||||
ThreadBlocker m_thread_blocker;
|
ThreadBlocker m_thread_blocker;
|
||||||
|
|
||||||
uint32_t m_writing_count { 1 };
|
BAN::Array<uint8_t, PAGE_SIZE> m_buffer;
|
||||||
|
BAN::Atomic<size_t> m_buffer_size { 0 };
|
||||||
|
size_t m_buffer_tail { 0 };
|
||||||
|
|
||||||
|
BAN::Atomic<uint32_t> m_writing_count { 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_setuid(uid_t);
|
BAN::ErrorOr<long> sys_setuid(uid_t);
|
||||||
BAN::ErrorOr<long> sys_setgid(gid_t);
|
BAN::ErrorOr<long> sys_setgid(gid_t);
|
||||||
|
BAN::ErrorOr<long> sys_setsid();
|
||||||
BAN::ErrorOr<long> sys_seteuid(uid_t);
|
BAN::ErrorOr<long> sys_seteuid(uid_t);
|
||||||
BAN::ErrorOr<long> sys_setegid(gid_t);
|
BAN::ErrorOr<long> sys_setegid(gid_t);
|
||||||
BAN::ErrorOr<long> sys_setreuid(uid_t, uid_t);
|
BAN::ErrorOr<long> sys_setreuid(uid_t, uid_t);
|
||||||
|
@ -173,6 +174,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* storage);
|
BAN::ErrorOr<long> sys_ttyname(int fildes, char* storage);
|
||||||
BAN::ErrorOr<long> sys_isatty(int fildes);
|
BAN::ErrorOr<long> sys_isatty(int fildes);
|
||||||
|
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
||||||
|
BAN::ErrorOr<long> sys_ptsname(int fildes, char* buffer, size_t buffer_len);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
||||||
|
|
||||||
|
@ -219,8 +222,6 @@ namespace Kernel
|
||||||
// Load elf from a file
|
// Load elf from a file
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<LibELF::LoadableELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd, Kernel::PageTable&);
|
static BAN::ErrorOr<BAN::UniqPtr<LibELF::LoadableELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd, Kernel::PageTable&);
|
||||||
|
|
||||||
BAN::ErrorOr<int> block_until_exit(pid_t pid);
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> validate_string_access(const char*);
|
BAN::ErrorOr<void> validate_string_access(const char*);
|
||||||
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t);
|
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t);
|
||||||
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t);
|
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t);
|
||||||
|
@ -255,12 +256,12 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ExitStatus
|
struct ChildExitStatus
|
||||||
{
|
{
|
||||||
ThreadBlocker thread_blocker;
|
pid_t pid { 0 };
|
||||||
int exit_code { 0 };
|
pid_t pgrp { 0 };
|
||||||
BAN::Atomic<bool> exited { false };
|
int exit_code { 0 };
|
||||||
BAN::Atomic<int> waiting { 0 };
|
bool exited { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
Credentials m_credentials;
|
Credentials m_credentials;
|
||||||
|
@ -292,7 +293,10 @@ namespace Kernel
|
||||||
|
|
||||||
bool m_is_userspace { false };
|
bool m_is_userspace { false };
|
||||||
userspace_info_t m_userspace_info;
|
userspace_info_t m_userspace_info;
|
||||||
ExitStatus m_exit_status;
|
|
||||||
|
SpinLock m_child_exit_lock;
|
||||||
|
BAN::Vector<ChildExitStatus> m_child_exit_statuses;
|
||||||
|
ThreadBlocker m_child_exit_blocker;
|
||||||
|
|
||||||
bool m_has_called_exec { false };
|
bool m_has_called_exec { false };
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/WeakPtr.h>
|
||||||
|
#include <kernel/Terminal/TTY.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class PseudoTerminalSlave;
|
||||||
|
|
||||||
|
class PseudoTerminalMaster final : public CharacterDevice, public BAN::Weakable<PseudoTerminalMaster>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<PseudoTerminalMaster>> create(mode_t, uid_t, gid_t);
|
||||||
|
|
||||||
|
dev_t rdev() const override { return m_rdev; }
|
||||||
|
BAN::StringView name() const override { return "<ptmx>"_sv; }
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<PseudoTerminalSlave>> slave();
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::String> ptsname();
|
||||||
|
|
||||||
|
void putchar(uint8_t ch);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
|
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||||
|
|
||||||
|
bool can_read_impl() const override { SpinLockGuard _(m_buffer_lock); return m_buffer_size > 0; }
|
||||||
|
bool can_write_impl() const override { SpinLockGuard _(m_buffer_lock); return m_buffer_size < m_buffer->size(); }
|
||||||
|
bool has_error_impl() const override { return false; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
PseudoTerminalMaster(BAN::UniqPtr<VirtualRange>, mode_t, uid_t, gid_t);
|
||||||
|
~PseudoTerminalMaster();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAN::WeakPtr<PseudoTerminalSlave> m_slave;
|
||||||
|
|
||||||
|
mutable SpinLock m_buffer_lock;
|
||||||
|
ThreadBlocker m_buffer_blocker;
|
||||||
|
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||||
|
size_t m_buffer_tail { 0 };
|
||||||
|
size_t m_buffer_size { 0 };
|
||||||
|
|
||||||
|
const dev_t m_rdev;
|
||||||
|
|
||||||
|
friend class BAN::RefPtr<PseudoTerminalMaster>;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PseudoTerminalSlave final : public TTY, public BAN::Weakable<PseudoTerminalSlave>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<PseudoTerminalSlave>> create(BAN::String&& name, mode_t, uid_t, gid_t);
|
||||||
|
|
||||||
|
BAN::StringView name() const override { return m_name; }
|
||||||
|
|
||||||
|
uint32_t height() const override { return m_height; }
|
||||||
|
uint32_t width() const override { return m_width; }
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void putchar_impl(uint8_t ch) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PseudoTerminalSlave(BAN::UniqPtr<VirtualRange>, BAN::String&& name, mode_t, uid_t, gid_t);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAN::String m_name;
|
||||||
|
|
||||||
|
BAN::WeakPtr<PseudoTerminalMaster> m_master;
|
||||||
|
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||||
|
size_t m_buffer_tail { 0 };
|
||||||
|
size_t m_buffer_size { 0 };
|
||||||
|
|
||||||
|
uint32_t m_width { 0 };
|
||||||
|
uint32_t m_height { 0 };
|
||||||
|
|
||||||
|
friend class PseudoTerminalMaster;
|
||||||
|
friend class BAN::RefPtr<PseudoTerminalSlave>;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -63,11 +63,6 @@ namespace Kernel
|
||||||
Serial m_serial;
|
Serial m_serial;
|
||||||
BAN::CircularQueue<uint8_t, 128> m_input;
|
BAN::CircularQueue<uint8_t, 128> m_input;
|
||||||
SpinLock m_input_lock;
|
SpinLock m_input_lock;
|
||||||
|
|
||||||
public:
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
|
||||||
private:
|
|
||||||
const dev_t m_rdev;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ namespace Kernel
|
||||||
virtual uint32_t width() const = 0;
|
virtual uint32_t width() const = 0;
|
||||||
void putchar(uint8_t ch);
|
void putchar(uint8_t ch);
|
||||||
|
|
||||||
|
virtual dev_t rdev() const final override { return m_rdev; }
|
||||||
|
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||||
|
@ -54,17 +56,7 @@ namespace Kernel
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TTY(mode_t mode, uid_t uid, gid_t gid)
|
TTY(mode_t mode, uid_t uid, gid_t gid);
|
||||||
: CharacterDevice(mode, uid, gid)
|
|
||||||
{
|
|
||||||
// FIXME: add correct baud and flags
|
|
||||||
m_termios.c_iflag = 0;
|
|
||||||
m_termios.c_oflag = 0;
|
|
||||||
m_termios.c_cflag = CS8;
|
|
||||||
m_termios.c_lflag = ECHO | ICANON;
|
|
||||||
m_termios.c_ospeed = B38400;
|
|
||||||
m_termios.c_ispeed = B38400;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void putchar_impl(uint8_t ch) = 0;
|
virtual void putchar_impl(uint8_t ch) = 0;
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
|
@ -79,6 +71,8 @@ namespace Kernel
|
||||||
termios m_termios;
|
termios m_termios;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const dev_t m_rdev;
|
||||||
|
|
||||||
pid_t m_foreground_pgrp { 0 };
|
pid_t m_foreground_pgrp { 0 };
|
||||||
|
|
||||||
struct tty_ctrl_t
|
struct tty_ctrl_t
|
||||||
|
|
|
@ -83,11 +83,6 @@ namespace Kernel
|
||||||
bool m_show_cursor { true };
|
bool m_show_cursor { true };
|
||||||
|
|
||||||
TerminalDriver* m_terminal_driver { nullptr };
|
TerminalDriver* m_terminal_driver { nullptr };
|
||||||
|
|
||||||
public:
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
|
||||||
private:
|
|
||||||
const dev_t m_rdev;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ namespace Kernel
|
||||||
bool add_signal(int signal);
|
bool add_signal(int signal);
|
||||||
|
|
||||||
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout
|
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout
|
||||||
|
BAN::ErrorOr<void> sleep_or_eintr_ms(uint64_t ms) { return sleep_or_eintr_ns(ms * 1'000'000); }
|
||||||
|
BAN::ErrorOr<void> sleep_or_eintr_ns(uint64_t ns);
|
||||||
BAN::ErrorOr<void> block_or_eintr_indefinite(ThreadBlocker& thread_blocker);
|
BAN::ErrorOr<void> block_or_eintr_indefinite(ThreadBlocker& thread_blocker);
|
||||||
BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout) { return block_or_eintr_or_timeout_ns(thread_blocker, timeout_ms * 1'000'000, etimedout); }
|
BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout) { return block_or_eintr_or_timeout_ns(thread_blocker, timeout_ms * 1'000'000, etimedout); }
|
||||||
BAN::ErrorOr<void> block_or_eintr_or_waketime_ms(ThreadBlocker& thread_blocker, uint64_t wake_time_ms, bool etimedout) { return block_or_eintr_or_waketime_ns(thread_blocker, wake_time_ms * 1'000'000, etimedout); }
|
BAN::ErrorOr<void> block_or_eintr_or_waketime_ms(ThreadBlocker& thread_blocker, uint64_t wake_time_ms, bool etimedout) { return block_or_eintr_or_waketime_ns(thread_blocker, wake_time_ms * 1'000'000, etimedout); }
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
|
#include <kernel/Process.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -26,24 +28,23 @@ namespace Kernel
|
||||||
|
|
||||||
void Pipe::clone_writing()
|
void Pipe::clone_writing()
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
[[maybe_unused]] auto old_writing_count = m_writing_count.fetch_add(1);
|
||||||
ASSERT(m_writing_count > 0);
|
ASSERT(old_writing_count > 0);
|
||||||
m_writing_count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pipe::close_writing()
|
void Pipe::close_writing()
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
auto old_writing_count = m_writing_count.fetch_sub(1);
|
||||||
ASSERT(m_writing_count > 0);
|
ASSERT(old_writing_count > 0);
|
||||||
m_writing_count--;
|
if (old_writing_count == 1)
|
||||||
if (m_writing_count == 0)
|
|
||||||
m_thread_blocker.unblock();
|
m_thread_blocker.unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
|
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
while (m_buffer.empty())
|
|
||||||
|
while (m_buffer_size == 0)
|
||||||
{
|
{
|
||||||
if (m_writing_count == 0)
|
if (m_writing_count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -51,11 +52,20 @@ namespace Kernel
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer.size());
|
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer_size);
|
||||||
memcpy(buffer.data(), m_buffer.data(), to_copy);
|
|
||||||
|
|
||||||
memmove(m_buffer.data(), m_buffer.data() + to_copy, m_buffer.size() - to_copy);
|
if (m_buffer_tail + to_copy <= m_buffer.size())
|
||||||
MUST(m_buffer.resize(m_buffer.size() - to_copy));
|
memcpy(buffer.data(), m_buffer.data() + m_buffer_tail, to_copy);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const size_t before_wrap = m_buffer.size() - m_buffer_tail;
|
||||||
|
const size_t after_wrap = to_copy - before_wrap;
|
||||||
|
memcpy(buffer.data(), m_buffer.data() + m_buffer_tail, before_wrap);
|
||||||
|
memcpy(buffer.data() + before_wrap, m_buffer.data(), after_wrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer_tail = (m_buffer_tail + to_copy) % m_buffer.size();
|
||||||
|
m_buffer_size -= to_copy;
|
||||||
|
|
||||||
m_atime = SystemTimer::get().real_time();
|
m_atime = SystemTimer::get().real_time();
|
||||||
|
|
||||||
|
@ -68,10 +78,29 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
size_t old_size = m_buffer.size();
|
if (buffer.size() > m_buffer.size())
|
||||||
|
buffer = buffer.slice(0, m_buffer.size());
|
||||||
|
|
||||||
TRY(m_buffer.resize(old_size + buffer.size()));
|
while (m_buffer.size() - m_buffer_size < buffer.size())
|
||||||
memcpy(m_buffer.data() + old_size, buffer.data(), buffer.size());
|
{
|
||||||
|
LockFreeGuard lock_free(m_mutex);
|
||||||
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t to_copy = buffer.size();
|
||||||
|
const size_t buffer_head = (m_buffer_tail + m_buffer_size) % m_buffer.size();
|
||||||
|
|
||||||
|
if (buffer_head + to_copy <= m_buffer.size())
|
||||||
|
memcpy(m_buffer.data() + buffer_head, buffer.data(), to_copy);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const size_t before_wrap = m_buffer.size() - buffer_head;
|
||||||
|
const size_t after_wrap = to_copy - before_wrap;
|
||||||
|
memcpy(m_buffer.data() + buffer_head, buffer.data(), before_wrap);
|
||||||
|
memcpy(m_buffer.data(), buffer.data() + before_wrap, after_wrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer_size += to_copy;
|
||||||
|
|
||||||
timespec current_time = SystemTimer::get().real_time();
|
timespec current_time = SystemTimer::get().real_time();
|
||||||
m_mtime = current_time;
|
m_mtime = current_time;
|
||||||
|
@ -79,7 +108,7 @@ namespace Kernel
|
||||||
|
|
||||||
m_thread_blocker.unblock();
|
m_thread_blocker.unblock();
|
||||||
|
|
||||||
return buffer.size();
|
return to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,11 @@ namespace Kernel
|
||||||
|
|
||||||
m_open_files[fd] = result.release_value();
|
m_open_files[fd] = result.release_value();
|
||||||
|
|
||||||
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
if (m_open_files[fd]->path == "<pipe wr>"_sv)
|
||||||
((Pipe*)m_open_files[fd]->inode.ptr())->clone_writing();
|
{
|
||||||
|
ASSERT(m_open_files[fd]->inode->is_pipe());
|
||||||
|
static_cast<Pipe*>(m_open_files[fd]->inode.ptr())->clone_writing();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -59,7 +62,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
ASSERT(file.inode);
|
ASSERT(file.inode);
|
||||||
|
|
||||||
if (flags & ~(O_ACCMODE | O_NOFOLLOW | O_APPEND | O_TRUNC | O_CLOEXEC | O_TTY_INIT | O_DIRECTORY | O_CREAT | O_EXCL | O_NONBLOCK))
|
if (flags & ~(O_ACCMODE | O_NOFOLLOW | O_APPEND | O_TRUNC | O_CLOEXEC | O_TTY_INIT | O_NOCTTY | O_DIRECTORY | O_CREAT | O_EXCL | O_NONBLOCK))
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
if ((flags & O_ACCMODE) != O_RDWR && __builtin_popcount(flags & O_ACCMODE) != 1)
|
if ((flags & O_ACCMODE) != O_RDWR && __builtin_popcount(flags & O_ACCMODE) != 1)
|
||||||
|
@ -139,8 +142,8 @@ namespace Kernel
|
||||||
TRY(get_free_fd_pair(fds));
|
TRY(get_free_fd_pair(fds));
|
||||||
|
|
||||||
auto pipe = TRY(Pipe::create(m_credentials));
|
auto pipe = TRY(Pipe::create(m_credentials));
|
||||||
m_open_files[fds[0]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, ""_sv, 0, O_RDONLY));
|
m_open_files[fds[0]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, "<pipe rd>"_sv, 0, O_RDONLY));
|
||||||
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, ""_sv, 0, O_WRONLY));
|
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, "<pipe wr>"_sv, 0, O_WRONLY));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -152,8 +155,11 @@ namespace Kernel
|
||||||
int result = TRY(get_free_fd());
|
int result = TRY(get_free_fd());
|
||||||
m_open_files[result] = m_open_files[fildes];
|
m_open_files[result] = m_open_files[fildes];
|
||||||
|
|
||||||
if (m_open_files[result]->flags & O_WRONLY && m_open_files[result]->inode->is_pipe())
|
if (m_open_files[result]->path == "<pipe wr>"_sv)
|
||||||
((Pipe*)m_open_files[result]->inode.ptr())->clone_writing();
|
{
|
||||||
|
ASSERT(m_open_files[result]->inode->is_pipe());
|
||||||
|
static_cast<Pipe*>(m_open_files[result]->inode.ptr())->clone_writing();
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -172,8 +178,11 @@ namespace Kernel
|
||||||
m_open_files[fildes2] = m_open_files[fildes];
|
m_open_files[fildes2] = m_open_files[fildes];
|
||||||
m_open_files[fildes2]->flags &= ~O_CLOEXEC;
|
m_open_files[fildes2]->flags &= ~O_CLOEXEC;
|
||||||
|
|
||||||
if (m_open_files[fildes]->flags & O_WRONLY && m_open_files[fildes]->inode->is_pipe())
|
if (m_open_files[fildes2]->path == "<pipe wr>"_sv)
|
||||||
((Pipe*)m_open_files[fildes]->inode.ptr())->clone_writing();
|
{
|
||||||
|
ASSERT(m_open_files[fildes2]->inode->is_pipe());
|
||||||
|
static_cast<Pipe*>(m_open_files[fildes2]->inode.ptr())->clone_writing();
|
||||||
|
}
|
||||||
|
|
||||||
return fildes;
|
return fildes;
|
||||||
}
|
}
|
||||||
|
@ -303,8 +312,11 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
if (m_open_files[fd]->path == "<pipe wr>"_sv)
|
||||||
((Pipe*)m_open_files[fd]->inode.ptr())->close_writing();
|
{
|
||||||
|
ASSERT(m_open_files[fd]->inode->is_pipe());
|
||||||
|
static_cast<Pipe*>(m_open_files[fd]->inode.ptr())->close_writing();
|
||||||
|
}
|
||||||
|
|
||||||
m_open_files[fd].clear();
|
m_open_files[fd].clear();
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Storage/StorageDevice.h>
|
#include <kernel/Storage/StorageDevice.h>
|
||||||
|
#include <kernel/Terminal/PseudoTerminal.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
#include <LibELF/LoadableELF.h>
|
#include <LibELF/LoadableELF.h>
|
||||||
|
@ -185,7 +186,6 @@ namespace Kernel
|
||||||
ASSERT(m_threads.empty());
|
ASSERT(m_threads.empty());
|
||||||
ASSERT(m_mapped_regions.empty());
|
ASSERT(m_mapped_regions.empty());
|
||||||
ASSERT(!m_loadable_elf);
|
ASSERT(!m_loadable_elf);
|
||||||
ASSERT(m_exit_status.waiting == 0);
|
|
||||||
ASSERT(&PageTable::current() != m_page_table.ptr());
|
ASSERT(&PageTable::current() != m_page_table.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,21 +201,15 @@ namespace Kernel
|
||||||
SpinLockGuard _(s_process_lock);
|
SpinLockGuard _(s_process_lock);
|
||||||
for (size_t i = 0; i < s_processes.size(); i++)
|
for (size_t i = 0; i < s_processes.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_parent && s_processes[i]->pid() == m_parent)
|
if (s_processes[i] != this)
|
||||||
s_processes[i]->add_pending_signal(SIGCHLD);
|
continue;
|
||||||
if (s_processes[i] == this)
|
s_processes.remove(i);
|
||||||
s_processes.remove(i);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcFileSystem::get().on_process_delete(*this);
|
ProcFileSystem::get().on_process_delete(*this);
|
||||||
|
|
||||||
m_exit_status.exited = true;
|
|
||||||
m_exit_status.thread_blocker.unblock();
|
|
||||||
|
|
||||||
while (m_exit_status.waiting > 0)
|
|
||||||
Processor::yield();
|
|
||||||
|
|
||||||
m_process_lock.lock();
|
m_process_lock.lock();
|
||||||
|
|
||||||
m_open_file_descriptors.close_all();
|
m_open_file_descriptors.close_all();
|
||||||
|
@ -252,7 +246,35 @@ namespace Kernel
|
||||||
|
|
||||||
void Process::exit(int status, int signal)
|
void Process::exit(int status, int signal)
|
||||||
{
|
{
|
||||||
m_exit_status.exit_code = __WGENEXITCODE(status, signal);
|
if (m_parent)
|
||||||
|
{
|
||||||
|
for_each_process(
|
||||||
|
[&](Process& parent) -> BAN::Iteration
|
||||||
|
{
|
||||||
|
if (parent.pid() != m_parent)
|
||||||
|
return BAN::Iteration::Continue;
|
||||||
|
|
||||||
|
for (auto& child : parent.m_child_exit_statuses)
|
||||||
|
{
|
||||||
|
if (child.pid != pid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
child.exit_code = __WGENEXITCODE(status, signal);
|
||||||
|
child.exited = true;
|
||||||
|
|
||||||
|
parent.add_pending_signal(SIGCHLD);
|
||||||
|
Processor::scheduler().unblock_thread(parent.m_threads.front());
|
||||||
|
|
||||||
|
parent.m_child_exit_blocker.unblock();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BAN::Iteration::Break;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
while (!m_threads.empty())
|
while (!m_threads.empty())
|
||||||
m_threads.front()->on_exit();
|
m_threads.front()->on_exit();
|
||||||
}
|
}
|
||||||
|
@ -397,6 +419,20 @@ namespace Kernel
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
|
ChildExitStatus* child_exit_status = nullptr;
|
||||||
|
for (auto& child : m_child_exit_statuses)
|
||||||
|
{
|
||||||
|
if (child.pid != 0)
|
||||||
|
continue;
|
||||||
|
child_exit_status = &child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (child_exit_status == nullptr)
|
||||||
|
{
|
||||||
|
TRY(m_child_exit_statuses.emplace_back());
|
||||||
|
child_exit_status = &m_child_exit_statuses.back();
|
||||||
|
}
|
||||||
|
|
||||||
BAN::String working_directory;
|
BAN::String working_directory;
|
||||||
TRY(working_directory.append(m_working_directory));
|
TRY(working_directory.append(m_working_directory));
|
||||||
|
|
||||||
|
@ -422,6 +458,10 @@ namespace Kernel
|
||||||
forked->m_has_called_exec = false;
|
forked->m_has_called_exec = false;
|
||||||
memcpy(forked->m_signal_handlers, m_signal_handlers, sizeof(m_signal_handlers));
|
memcpy(forked->m_signal_handlers, m_signal_handlers, sizeof(m_signal_handlers));
|
||||||
|
|
||||||
|
*child_exit_status = {};
|
||||||
|
child_exit_status->pid = forked->pid();
|
||||||
|
child_exit_status->pgrp = forked->pgrp();
|
||||||
|
|
||||||
ASSERT(this == &Process::current());
|
ASSERT(this == &Process::current());
|
||||||
// FIXME: this should be able to fail
|
// FIXME: this should be able to fail
|
||||||
Thread* thread = MUST(Thread::current().clone(forked, sp, ip));
|
Thread* thread = MUST(Thread::current().clone(forked, sp, ip));
|
||||||
|
@ -541,58 +581,72 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<int> Process::block_until_exit(pid_t pid)
|
|
||||||
{
|
|
||||||
ASSERT(this->pid() != pid);
|
|
||||||
|
|
||||||
Process* target = nullptr;
|
|
||||||
for_each_process(
|
|
||||||
[pid, &target](Process& process)
|
|
||||||
{
|
|
||||||
if (process.pid() == pid)
|
|
||||||
{
|
|
||||||
process.m_exit_status.waiting++;
|
|
||||||
target = &process;
|
|
||||||
return BAN::Iteration::Break;
|
|
||||||
}
|
|
||||||
return BAN::Iteration::Continue;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (target == nullptr)
|
|
||||||
return BAN::Error::from_errno(ECHILD);
|
|
||||||
|
|
||||||
while (!target->m_exit_status.exited)
|
|
||||||
{
|
|
||||||
if (auto ret = Thread::current().block_or_eintr_indefinite(target->m_exit_status.thread_blocker); ret.is_error())
|
|
||||||
{
|
|
||||||
target->m_exit_status.waiting--;
|
|
||||||
return ret.release_error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int exit_status = target->m_exit_status.exit_code;
|
|
||||||
target->m_exit_status.waiting--;
|
|
||||||
|
|
||||||
return exit_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_wait(pid_t pid, int* stat_loc, int options)
|
BAN::ErrorOr<long> Process::sys_wait(pid_t pid, int* stat_loc, int options)
|
||||||
{
|
{
|
||||||
{
|
if (options & ~(WCONTINUED | WNOHANG | WUNTRACED))
|
||||||
LockGuard _(m_process_lock);
|
|
||||||
TRY(validate_pointer_access(stat_loc, sizeof(int)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: support options
|
|
||||||
if (options)
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
int stat = TRY(block_until_exit(pid));
|
// FIXME: support options stopped processes
|
||||||
if (stat_loc)
|
if (options & ~(WCONTINUED | WUNTRACED))
|
||||||
*stat_loc = stat;
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
return pid;
|
const auto pid_matches =
|
||||||
|
[&](const ChildExitStatus& child)
|
||||||
|
{
|
||||||
|
if (pid == -1)
|
||||||
|
return true;
|
||||||
|
if (pid == 0)
|
||||||
|
return child.pgrp == pgrp();
|
||||||
|
if (pid < 0)
|
||||||
|
return child.pgrp == -pid;
|
||||||
|
return child.pid == pid;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
pid_t exited_pid = 0;
|
||||||
|
int exit_code = 0;
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_child_exit_lock);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (auto& child : m_child_exit_statuses)
|
||||||
|
{
|
||||||
|
if (!pid_matches(child))
|
||||||
|
continue;
|
||||||
|
found = true;
|
||||||
|
if (!child.exited)
|
||||||
|
continue;
|
||||||
|
exited_pid = child.pid;
|
||||||
|
exit_code = child.exit_code;
|
||||||
|
child = {};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return BAN::Error::from_errno(ECHILD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exited_pid != 0)
|
||||||
|
{
|
||||||
|
if (stat_loc)
|
||||||
|
{
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
TRY(validate_pointer_access(stat_loc, sizeof(stat_loc)));
|
||||||
|
*stat_loc = exit_code;
|
||||||
|
}
|
||||||
|
remove_pending_signal(SIGCHLD);
|
||||||
|
return exited_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Thread::current().is_interrupted_by_signal())
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
|
|
||||||
|
if (options & WNOHANG)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
m_child_exit_blocker.block_indefinite();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
||||||
|
@ -860,8 +914,8 @@ namespace Kernel
|
||||||
int fd = TRY(m_open_file_descriptors.open(file, flags));
|
int fd = TRY(m_open_file_descriptors.open(file, flags));
|
||||||
|
|
||||||
// Open controlling terminal
|
// Open controlling terminal
|
||||||
if ((flags & O_TTY_INIT) && !(flags & O_NOCTTY) && file.inode->is_tty() && is_session_leader() && !m_controlling_terminal)
|
if (!(flags & O_NOCTTY) && file.inode->is_tty() && is_session_leader() && !m_controlling_terminal)
|
||||||
m_controlling_terminal = (TTY*)file.inode.ptr();
|
m_controlling_terminal = static_cast<TTY*>(file.inode.ptr());
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -1289,7 +1343,7 @@ namespace Kernel
|
||||||
break;
|
break;
|
||||||
|
|
||||||
LockFreeGuard free(m_process_lock);
|
LockFreeGuard free(m_process_lock);
|
||||||
SystemTimer::get().sleep_ms(1);
|
TRY(Thread::current().sleep_or_eintr_ms(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->readfds)
|
if (arguments->readfds)
|
||||||
|
@ -1681,6 +1735,50 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_posix_openpt(int flags)
|
||||||
|
{
|
||||||
|
if (flags & ~(O_RDWR | O_NOCTTY))
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
mode_t mode = 0440;
|
||||||
|
if (flags & O_WRONLY)
|
||||||
|
mode = 0660;
|
||||||
|
|
||||||
|
auto pts_master = TRY(PseudoTerminalMaster::create(mode, m_credentials.ruid(), m_credentials.rgid()));
|
||||||
|
auto pts_slave = TRY(pts_master->slave());
|
||||||
|
|
||||||
|
VirtualFileSystem::File file;
|
||||||
|
file.inode = pts_master;
|
||||||
|
TRY(file.canonical_path.append(pts_master->name()));
|
||||||
|
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
|
int pts_master_fd = TRY(m_open_file_descriptors.open(file, flags));
|
||||||
|
|
||||||
|
if (!(flags & O_NOCTTY) && is_session_leader() && !m_controlling_terminal)
|
||||||
|
m_controlling_terminal = (TTY*)pts_slave.ptr();
|
||||||
|
|
||||||
|
return pts_master_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_ptsname(int fildes, char* buffer, size_t buffer_len)
|
||||||
|
{
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
TRY(validate_pointer_access(buffer, buffer_len));
|
||||||
|
|
||||||
|
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||||
|
if (TRY(m_open_file_descriptors.path_of(fildes)) != "<ptmx>"_sv)
|
||||||
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
|
||||||
|
auto ptsname = TRY(static_cast<PseudoTerminalMaster*>(inode.ptr())->ptsname());
|
||||||
|
|
||||||
|
const size_t to_copy = BAN::Math::min(ptsname.size() + 1, buffer_len);
|
||||||
|
memcpy(buffer, ptsname.data(), to_copy);
|
||||||
|
buffer[to_copy] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_tty_ctrl(int fildes, int command, int flags)
|
BAN::ErrorOr<long> Process::sys_tty_ctrl(int fildes, int command, int flags)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
@ -1883,10 +1981,11 @@ namespace Kernel
|
||||||
if (!inode->is_tty())
|
if (!inode->is_tty())
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
|
||||||
if ((TTY*)inode.ptr() != m_controlling_terminal.ptr())
|
auto* tty = static_cast<TTY*>(inode.ptr());
|
||||||
|
if (tty != m_controlling_terminal.ptr())
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
|
||||||
((TTY*)inode.ptr())->set_foreground_pgrp(pgrp);
|
tty->set_foreground_pgrp(pgrp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1948,6 +2047,20 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(EPERM);
|
return BAN::Error::from_errno(EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_setsid()
|
||||||
|
{
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
|
if (is_session_leader() || m_pid == m_pgrp)
|
||||||
|
return BAN::Error::from_errno(EPERM);
|
||||||
|
|
||||||
|
m_sid = m_pid;
|
||||||
|
m_pgrp = m_pid;
|
||||||
|
m_controlling_terminal.clear();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_seteuid(uid_t uid)
|
BAN::ErrorOr<long> Process::sys_seteuid(uid_t uid)
|
||||||
{
|
{
|
||||||
if (uid < 0 || uid >= 1'000'000'000)
|
if (uid < 0 || uid >= 1'000'000'000)
|
||||||
|
@ -2225,7 +2338,7 @@ namespace Kernel
|
||||||
|
|
||||||
// FIXME: should we allow cross mapping access?
|
// FIXME: should we allow cross mapping access?
|
||||||
for (auto& mapped_region : m_mapped_regions)
|
for (auto& mapped_region : m_mapped_regions)
|
||||||
mapped_region->contains_fully(vaddr, size);
|
if (mapped_region->contains_fully(vaddr, size))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
// FIXME: elf should contain full range [vaddr, vaddr + size)
|
// FIXME: elf should contain full range [vaddr, vaddr + size)
|
||||||
|
|
|
@ -361,6 +361,8 @@ namespace Kernel
|
||||||
else
|
else
|
||||||
m_block_queue.add_thread_with_wake_time(node);
|
m_block_queue.add_thread_with_wake_time(node);
|
||||||
|
|
||||||
|
m_thread_count++;
|
||||||
|
|
||||||
Processor::set_interrupt_state(state);
|
Processor::set_interrupt_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
#include <kernel/Device/DeviceNumbers.h>
|
||||||
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
|
#include <kernel/Terminal/PseudoTerminal.h>
|
||||||
|
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
BAN::Atomic<uint32_t> s_pts_master_minor = 0;
|
||||||
|
BAN::Atomic<uint32_t> s_pts_slave_number = 0;
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<PseudoTerminalMaster>> PseudoTerminalMaster::create(mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
auto pts_master_buffer = TRY(VirtualRange::create_to_vaddr_range(
|
||||||
|
PageTable::kernel(),
|
||||||
|
KERNEL_OFFSET, static_cast<vaddr_t>(-1),
|
||||||
|
16 * PAGE_SIZE,
|
||||||
|
PageTable::Flags::ReadWrite | PageTable::Flags::Present, true
|
||||||
|
));
|
||||||
|
auto pts_master = TRY(BAN::RefPtr<PseudoTerminalMaster>::create(BAN::move(pts_master_buffer), mode, uid, gid));
|
||||||
|
|
||||||
|
auto pts_slave_buffer = TRY(VirtualRange::create_to_vaddr_range(
|
||||||
|
PageTable::kernel(),
|
||||||
|
KERNEL_OFFSET, static_cast<vaddr_t>(-1),
|
||||||
|
16 * PAGE_SIZE,
|
||||||
|
PageTable::Flags::ReadWrite | PageTable::Flags::Present, true
|
||||||
|
));
|
||||||
|
auto pts_slave_name = TRY(BAN::String::formatted("pts{}", s_pts_slave_number++));
|
||||||
|
auto pts_slave = TRY(BAN::RefPtr<PseudoTerminalSlave>::create(BAN::move(pts_slave_buffer), BAN::move(pts_slave_name), 0610, uid, gid));
|
||||||
|
|
||||||
|
pts_master->m_slave = TRY(pts_slave->get_weak_ptr());
|
||||||
|
pts_slave->m_master = TRY(pts_master->get_weak_ptr());
|
||||||
|
|
||||||
|
DevFileSystem::get().add_device(pts_slave);
|
||||||
|
|
||||||
|
return pts_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
PseudoTerminalMaster::PseudoTerminalMaster(BAN::UniqPtr<VirtualRange> buffer, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
: CharacterDevice(mode, uid, gid)
|
||||||
|
, m_buffer(BAN::move(buffer))
|
||||||
|
, m_rdev(makedev(DeviceNumber::PTSMaster, s_pts_master_minor++))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PseudoTerminalMaster::~PseudoTerminalMaster()
|
||||||
|
{
|
||||||
|
if (auto slave = m_slave.lock())
|
||||||
|
DevFileSystem::get().remove_device(slave);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<PseudoTerminalSlave>> PseudoTerminalMaster::slave()
|
||||||
|
{
|
||||||
|
if (auto slave = m_slave.lock())
|
||||||
|
return slave;
|
||||||
|
return BAN::Error::from_errno(ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::String> PseudoTerminalMaster::ptsname()
|
||||||
|
{
|
||||||
|
if (auto slave = m_slave.lock())
|
||||||
|
return TRY(BAN::String::formatted("/dev/{}", slave->name()));
|
||||||
|
return BAN::Error::from_errno(ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PseudoTerminalMaster::putchar(uint8_t ch)
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_buffer_lock);
|
||||||
|
|
||||||
|
if (m_buffer_size == m_buffer->size())
|
||||||
|
{
|
||||||
|
dwarnln("PseudoTerminalMaster buffer full");
|
||||||
|
m_buffer_tail = (m_buffer_tail + 1) % m_buffer->size();
|
||||||
|
m_buffer_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
*reinterpret_cast<uint8_t*>(m_buffer->vaddr() + (m_buffer_tail + m_buffer_size) % m_buffer->size()) = ch;
|
||||||
|
m_buffer_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> PseudoTerminalMaster::read_impl(off_t, BAN::ByteSpan buffer)
|
||||||
|
{
|
||||||
|
auto state = m_buffer_lock.lock();
|
||||||
|
|
||||||
|
while (m_buffer_size == 0)
|
||||||
|
{
|
||||||
|
m_buffer_lock.unlock(state);
|
||||||
|
TRY(Thread::current().block_or_eintr_indefinite(m_buffer_blocker));
|
||||||
|
m_buffer_lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t to_copy = BAN::Math::min(buffer.size(), m_buffer_size);
|
||||||
|
|
||||||
|
if (m_buffer_tail + to_copy < m_buffer->size())
|
||||||
|
memcpy(buffer.data(), reinterpret_cast<void*>(m_buffer->vaddr() + m_buffer_tail), to_copy);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const size_t before_wrap = m_buffer_size - m_buffer_tail;
|
||||||
|
const size_t after_wrap = to_copy - before_wrap;
|
||||||
|
|
||||||
|
memcpy(buffer.data(), reinterpret_cast<void*>(m_buffer->vaddr() + m_buffer_tail), before_wrap);
|
||||||
|
memcpy(buffer.data() + before_wrap, reinterpret_cast<void*>(m_buffer->vaddr()), after_wrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer_size -= to_copy;
|
||||||
|
m_buffer_tail = (m_buffer_tail + to_copy) % m_buffer->size();
|
||||||
|
|
||||||
|
m_buffer_lock.unlock(state);
|
||||||
|
|
||||||
|
return to_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> PseudoTerminalMaster::write_impl(off_t, BAN::ConstByteSpan buffer)
|
||||||
|
{
|
||||||
|
auto slave = m_slave.lock();
|
||||||
|
if (!slave)
|
||||||
|
return BAN::Error::from_errno(ENODEV);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < buffer.size(); i++)
|
||||||
|
slave->handle_input_byte(buffer[i]);
|
||||||
|
return buffer.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
PseudoTerminalSlave::PseudoTerminalSlave(BAN::UniqPtr<VirtualRange> buffer, BAN::String&& name, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
: TTY(mode, uid, gid)
|
||||||
|
, m_name(BAN::move(name))
|
||||||
|
, m_buffer(BAN::move(buffer))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void PseudoTerminalSlave::clear()
|
||||||
|
{
|
||||||
|
const char message[] { '\e', '[', '2', 'J' };
|
||||||
|
(void)write_impl(0, BAN::ConstByteSpan::from(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PseudoTerminalSlave::putchar_impl(uint8_t ch)
|
||||||
|
{
|
||||||
|
if (auto master = m_master.lock())
|
||||||
|
master->putchar(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
#include <BAN/Array.h>
|
#include <BAN/Array.h>
|
||||||
#include <kernel/Device/DeviceNumbers.h>
|
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
|
@ -7,7 +6,6 @@
|
||||||
#include <kernel/Terminal/Serial.h>
|
#include <kernel/Terminal/Serial.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
|
|
||||||
#define MAX_BAUD 115200
|
#define MAX_BAUD 115200
|
||||||
|
|
||||||
|
@ -33,6 +31,8 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static BAN::Atomic<uint32_t> s_next_tty_number = 0;
|
||||||
|
|
||||||
static constexpr uint16_t s_serial_ports[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8 };
|
static constexpr uint16_t s_serial_ports[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8 };
|
||||||
static BAN::Array<Serial, sizeof(s_serial_ports) / sizeof(*s_serial_ports)> s_serial_drivers;
|
static BAN::Array<Serial, sizeof(s_serial_ports) / sizeof(*s_serial_ports)> s_serial_drivers;
|
||||||
static bool s_has_devices { false };
|
static bool s_has_devices { false };
|
||||||
|
@ -40,12 +40,6 @@ namespace Kernel
|
||||||
static BAN::RefPtr<SerialTTY> s_com1;
|
static BAN::RefPtr<SerialTTY> s_com1;
|
||||||
static BAN::RefPtr<SerialTTY> s_com2;
|
static BAN::RefPtr<SerialTTY> s_com2;
|
||||||
|
|
||||||
static dev_t next_rdev()
|
|
||||||
{
|
|
||||||
static dev_t minor = 0;
|
|
||||||
return makedev(DeviceNumber::Serial, minor++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Serial::initialize()
|
void Serial::initialize()
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -179,9 +173,8 @@ namespace Kernel
|
||||||
|
|
||||||
SerialTTY::SerialTTY(Serial serial)
|
SerialTTY::SerialTTY(Serial serial)
|
||||||
: TTY(0600, 0, 0)
|
: TTY(0600, 0, 0)
|
||||||
, m_name(MUST(BAN::String::formatted("ttyS{}", minor(rdev()))))
|
, m_name(MUST(BAN::String::formatted("ttyS{}", s_next_tty_number++)))
|
||||||
, m_serial(serial)
|
, m_serial(serial)
|
||||||
, m_rdev(next_rdev())
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<SerialTTY>> SerialTTY::create(Serial serial)
|
BAN::ErrorOr<BAN::RefPtr<SerialTTY>> SerialTTY::create(Serial serial)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <BAN/UTF8.h>
|
#include <BAN/UTF8.h>
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
|
#include <kernel/Device/DeviceNumbers.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/Lock/LockGuard.h>
|
#include <kernel/Lock/LockGuard.h>
|
||||||
|
@ -20,6 +21,25 @@ namespace Kernel
|
||||||
|
|
||||||
static BAN::RefPtr<TTY> s_tty;
|
static BAN::RefPtr<TTY> s_tty;
|
||||||
|
|
||||||
|
static dev_t next_tty_rdev()
|
||||||
|
{
|
||||||
|
static BAN::Atomic<dev_t> s_minor = 0;
|
||||||
|
return makedev(DeviceNumber::TTY, s_minor++);
|
||||||
|
}
|
||||||
|
|
||||||
|
TTY::TTY(mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
: CharacterDevice(mode, uid, gid)
|
||||||
|
, m_rdev(next_tty_rdev())
|
||||||
|
{
|
||||||
|
// FIXME: add correct baud and flags
|
||||||
|
m_termios.c_iflag = 0;
|
||||||
|
m_termios.c_oflag = 0;
|
||||||
|
m_termios.c_cflag = CS8;
|
||||||
|
m_termios.c_lflag = ECHO | ICANON;
|
||||||
|
m_termios.c_ospeed = B38400;
|
||||||
|
m_termios.c_ispeed = B38400;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::RefPtr<TTY> TTY::current()
|
BAN::RefPtr<TTY> TTY::current()
|
||||||
{
|
{
|
||||||
ASSERT(s_tty);
|
ASSERT(s_tty);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <BAN/UTF8.h>
|
#include <BAN/UTF8.h>
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
#include <kernel/Device/DeviceNumbers.h>
|
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/Lock/LockGuard.h>
|
#include <kernel/Lock/LockGuard.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
|
@ -10,7 +9,6 @@
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
|
|
||||||
#define BEL 0x07
|
#define BEL 0x07
|
||||||
#define BS 0x08
|
#define BS 0x08
|
||||||
|
@ -25,11 +23,7 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
static dev_t next_rdev()
|
static BAN::Atomic<uint32_t> s_next_tty_number = 0;
|
||||||
{
|
|
||||||
static dev_t minor = 0;
|
|
||||||
return makedev(DeviceNumber::TTY, minor++);
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<VirtualTTY>> VirtualTTY::create(TerminalDriver* driver)
|
BAN::ErrorOr<BAN::RefPtr<VirtualTTY>> VirtualTTY::create(TerminalDriver* driver)
|
||||||
{
|
{
|
||||||
|
@ -43,9 +37,8 @@ namespace Kernel
|
||||||
|
|
||||||
VirtualTTY::VirtualTTY(TerminalDriver* driver)
|
VirtualTTY::VirtualTTY(TerminalDriver* driver)
|
||||||
: TTY(0600, 0, 0)
|
: TTY(0600, 0, 0)
|
||||||
, m_name(MUST(BAN::String::formatted("tty{}", minor(rdev()))))
|
, m_name(MUST(BAN::String::formatted("tty{}", s_next_tty_number++)))
|
||||||
, m_terminal_driver(driver)
|
, m_terminal_driver(driver)
|
||||||
, m_rdev(next_rdev())
|
|
||||||
{
|
{
|
||||||
m_width = m_terminal_driver->width();
|
m_width = m_terminal_driver->width();
|
||||||
m_height = m_terminal_driver->height();
|
m_height = m_terminal_driver->height();
|
||||||
|
|
|
@ -423,6 +423,16 @@ namespace Kernel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Thread::sleep_or_eintr_ns(uint64_t ns)
|
||||||
|
{
|
||||||
|
if (is_interrupted_by_signal())
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
|
SystemTimer::get().sleep_ns(ns);
|
||||||
|
if (is_interrupted_by_signal())
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Thread::block_or_eintr_indefinite(ThreadBlocker& thread_blocker)
|
BAN::ErrorOr<void> Thread::block_or_eintr_indefinite(ThreadBlocker& thread_blocker)
|
||||||
{
|
{
|
||||||
if (is_interrupted_by_signal())
|
if (is_interrupted_by_signal())
|
||||||
|
|
|
@ -4,6 +4,10 @@ NAME='doom'
|
||||||
VERSION='git'
|
VERSION='git'
|
||||||
DOWNLOAD_URL="https://github.com/ozkl/doomgeneric.git#613f870b6fa83ede448a247de5a2571092fa729d"
|
DOWNLOAD_URL="https://github.com/ozkl/doomgeneric.git#613f870b6fa83ede448a247de5a2571092fa729d"
|
||||||
|
|
||||||
|
configure() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
if [ ! -f doom1.wad ]; then
|
if [ ! -f doom1.wad ]; then
|
||||||
wget https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad || exit 1
|
wget https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad || exit 1
|
||||||
|
|
|
@ -6,7 +6,7 @@ if (( $# != 1 )); then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $BANAN_ROOT_DIR ]]; then
|
if [[ -z $BANAN_ROOT_DIR ]]; then
|
||||||
BANAN_ROOT_DIR="$(dirname $(realpath $0))/.."
|
BANAN_ROOT_DIR="$(realpath $(dirname $(realpath $0))/..)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source "$BANAN_ROOT_DIR/script/config.sh"
|
source "$BANAN_ROOT_DIR/script/config.sh"
|
||||||
|
@ -18,6 +18,10 @@ export PKG_CONFIG_SYSROOT_DIR="$BANAN_SYSROOT"
|
||||||
export PKG_CONFIG_LIBDIR="$PKG_CONFIG_SYSROOT_DIR/usr/lib/pkgconfig"
|
export PKG_CONFIG_LIBDIR="$PKG_CONFIG_SYSROOT_DIR/usr/lib/pkgconfig"
|
||||||
export PKG_CONFIG_PATH="$PKG_CONFIG_SYSROOT_DIR/usr/share/pkgconfig"
|
export PKG_CONFIG_PATH="$PKG_CONFIG_SYSROOT_DIR/usr/share/pkgconfig"
|
||||||
|
|
||||||
|
export CC="$BANAN_TOOLCHAIN_TRIPLE-gcc"
|
||||||
|
export CXX="$BANAN_TOOLCHAIN_TRIPLE-g++"
|
||||||
|
export LD="$BANAN_TOOLCHAIN_TRIPLE-ld"
|
||||||
|
|
||||||
if [ ! -f "$BANAN_SYSROOT/usr/lib/libc.a" ]; then
|
if [ ! -f "$BANAN_SYSROOT/usr/lib/libc.a" ]; then
|
||||||
pushd "$BANAN_ROOT_DIR" >/dev/null
|
pushd "$BANAN_ROOT_DIR" >/dev/null
|
||||||
./bos libc || exit 1
|
./bos libc || exit 1
|
||||||
|
@ -29,11 +33,13 @@ clean() {
|
||||||
find . -mindepth 1 -maxdepth 1 -not -name 'patches' -not -name 'build.sh' -exec rm -rf {} +
|
find . -mindepth 1 -maxdepth 1 -not -name 'patches' -not -name 'build.sh' -exec rm -rf {} +
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
configure() {
|
||||||
configure_options=("--host=$BANAN_ARCH-banan_os" '--prefix=/usr')
|
configure_options=("--host=$BANAN_ARCH-banan_os" '--prefix=/usr')
|
||||||
configure_options+=(${CONFIGURE_OPTIONS[*]})
|
configure_options+=("${CONFIGURE_OPTIONS[@]}")
|
||||||
|
./configure "${configure_options[@]}" || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
./configure ${configure_options[*]} || exit 1
|
build() {
|
||||||
make -j$(nproc) || exit 1
|
make -j$(nproc) || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +149,7 @@ fi
|
||||||
cd "$build_dir"
|
cd "$build_dir"
|
||||||
|
|
||||||
if (( $needs_compile )); then
|
if (( $needs_compile )); then
|
||||||
|
configure
|
||||||
build
|
build
|
||||||
sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash"
|
sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -4,7 +4,10 @@ NAME='ncurses'
|
||||||
VERSION='6.5'
|
VERSION='6.5'
|
||||||
DOWNLOAD_URL="https://ftp.gnu.org/gnu/ncurses/ncurses-$VERSION.tar.gz#136d91bc269a9a5785e5f9e980bc76ab57428f604ce3e5a5a90cebc767971cc6"
|
DOWNLOAD_URL="https://ftp.gnu.org/gnu/ncurses/ncurses-$VERSION.tar.gz#136d91bc269a9a5785e5f9e980bc76ab57428f604ce3e5a5a90cebc767971cc6"
|
||||||
CONFIGURE_OPTIONS=(
|
CONFIGURE_OPTIONS=(
|
||||||
'--disable-db-intall'
|
"--with-pkg-config='$PKG_CONFIG'"
|
||||||
|
"--with-pkg-config-libdir=/usr/lib/pkgconfig"
|
||||||
|
'--enable-pc-files'
|
||||||
|
'--enable-sigwinch'
|
||||||
'--disable-widec'
|
'--disable-widec'
|
||||||
'--without-ada'
|
'--without-ada'
|
||||||
'--without-manpages'
|
'--without-manpages'
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -z $BANAN_PORT_DIR ]; then
|
||||||
|
echo "You must set the BANAN_PORT_DIR environment variable" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
cd $(dirname $(realpath $0))
|
cd $(dirname $(realpath $0))
|
||||||
|
|
||||||
|
rm -f $BANAN_PORT_DIR/.installed
|
||||||
|
|
||||||
while IFS= read -r port; do
|
while IFS= read -r port; do
|
||||||
pushd $(dirname "$port") >/dev/null
|
pushd $(dirname "$port") >/dev/null
|
||||||
./build.sh
|
./build.sh
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
done < <(find . -name '.compile_hash')
|
done < <(find $BANAN_PORT_DIR -name '.compile_hash')
|
||||||
|
|
|
@ -4,7 +4,7 @@ NAME='vim'
|
||||||
VERSION='9.0'
|
VERSION='9.0'
|
||||||
DOWNLOAD_URL="ftp://ftp.vim.org/pub/vim/unix/vim-$VERSION.tar.bz2#a6456bc154999d83d0c20d968ac7ba6e7df0d02f3cb6427fb248660bacfb336e"
|
DOWNLOAD_URL="ftp://ftp.vim.org/pub/vim/unix/vim-$VERSION.tar.bz2#a6456bc154999d83d0c20d968ac7ba6e7df0d02f3cb6427fb248660bacfb336e"
|
||||||
TAR_CONTENT='vim90'
|
TAR_CONTENT='vim90'
|
||||||
DEPENDENCIES=('ncurses' )
|
DEPENDENCIES=('ncurses')
|
||||||
CONFIGURE_OPTIONS=(
|
CONFIGURE_OPTIONS=(
|
||||||
'--with-tlib=ncurses'
|
'--with-tlib=ncurses'
|
||||||
'--disable-nls'
|
'--disable-nls'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
if [[ -z $BANAN_ROOT_DIR ]]; then
|
if [[ -z $BANAN_ROOT_DIR ]]; then
|
||||||
if ! [[ -z $BANAN_SCRIPT_DIR ]]; then
|
if ! [[ -z $BANAN_SCRIPT_DIR ]]; then
|
||||||
export BANAN_ROOT_DIR=$BANAN_SCRIPT_DIR/..
|
export BANAN_ROOT_DIR="$(realpath $BANAN_SCRIPT_DIR/..)"
|
||||||
else
|
else
|
||||||
echo "You must set the BANAN_ROOT_DIR environment variable" >&2
|
echo "You must set the BANAN_ROOT_DIR environment variable" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -13,10 +13,12 @@ fi
|
||||||
|
|
||||||
export BANAN_TOOLCHAIN_DIR=$BANAN_ROOT_DIR/toolchain
|
export BANAN_TOOLCHAIN_DIR=$BANAN_ROOT_DIR/toolchain
|
||||||
export BANAN_TOOLCHAIN_PREFIX=$BANAN_TOOLCHAIN_DIR/local
|
export BANAN_TOOLCHAIN_PREFIX=$BANAN_TOOLCHAIN_DIR/local
|
||||||
export BANAN_TOOLCHAIN_TRIPLE_PREFIX=$BANAN_ARCH-banan_os
|
export BANAN_TOOLCHAIN_TRIPLE=$BANAN_ARCH-banan_os
|
||||||
|
|
||||||
export BANAN_BUILD_DIR=$BANAN_ROOT_DIR/build
|
export BANAN_BUILD_DIR=$BANAN_ROOT_DIR/build
|
||||||
|
|
||||||
|
export BANAN_PORT_DIR=$BANAN_ROOT_DIR/ports
|
||||||
|
|
||||||
export BANAN_SYSROOT=$BANAN_BUILD_DIR/sysroot
|
export BANAN_SYSROOT=$BANAN_BUILD_DIR/sysroot
|
||||||
export BANAN_SYSROOT_TAR=$BANAN_SYSROOT.tar
|
export BANAN_SYSROOT_TAR=$BANAN_SYSROOT.tar
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@ if [[ -z $BANAN_TOOLCHAIN_PREFIX ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $BANAN_TOOLCHAIN_TRIPLE_PREFIX ]]; then
|
if [[ -z $BANAN_TOOLCHAIN_TRIPLE ]]; then
|
||||||
echo "You must set the BANAN_TOOLCHAIN_TRIPLE_PREFIX environment variable" >&2
|
echo "You must set the BANAN_TOOLCHAIN_TRIPLE environment variable" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ build_binutils () {
|
||||||
enter_clean_build
|
enter_clean_build
|
||||||
|
|
||||||
../configure \
|
../configure \
|
||||||
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
|
--target="$BANAN_TOOLCHAIN_TRIPLE" \
|
||||||
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
||||||
--with-sysroot="$BANAN_SYSROOT" \
|
--with-sysroot="$BANAN_SYSROOT" \
|
||||||
--disable-initfini-array \
|
--disable-initfini-array \
|
||||||
|
@ -116,7 +116,7 @@ build_gcc () {
|
||||||
enter_clean_build
|
enter_clean_build
|
||||||
|
|
||||||
../configure \
|
../configure \
|
||||||
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
|
--target="$BANAN_TOOLCHAIN_TRIPLE" \
|
||||||
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
--prefix="$BANAN_TOOLCHAIN_PREFIX" \
|
||||||
--with-sysroot="$BANAN_SYSROOT" \
|
--with-sysroot="$BANAN_SYSROOT" \
|
||||||
--disable-initfini-array \
|
--disable-initfini-array \
|
||||||
|
@ -189,7 +189,7 @@ build_cmake() {
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILD_BINUTILS=1
|
BUILD_BINUTILS=1
|
||||||
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE_PREFIX-ld ]]; then
|
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE-ld ]]; then
|
||||||
echo "You already seem to have a binutils installed."
|
echo "You already seem to have a binutils installed."
|
||||||
read -e -p "Do you want to rebuild it [y/N]? " choice
|
read -e -p "Do you want to rebuild it [y/N]? " choice
|
||||||
if ! [[ "$choice" == [Yy]* ]]; then
|
if ! [[ "$choice" == [Yy]* ]]; then
|
||||||
|
@ -198,7 +198,7 @@ if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE_PREFIX-ld ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BUILD_GCC=1
|
BUILD_GCC=1
|
||||||
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE_PREFIX-gcc ]]; then
|
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE-gcc ]]; then
|
||||||
echo "You already seem to have a gcc installed."
|
echo "You already seem to have a gcc installed."
|
||||||
read -e -p "Do you want to rebuild it [y/N]? " choice
|
read -e -p "Do you want to rebuild it [y/N]? " choice
|
||||||
if ! [[ "$choice" == [Yy]* ]]; then
|
if ! [[ "$choice" == [Yy]* ]]; then
|
||||||
|
|
|
@ -3,7 +3,9 @@ set(LIBC_SOURCES
|
||||||
assert.cpp
|
assert.cpp
|
||||||
ctype.cpp
|
ctype.cpp
|
||||||
dirent.cpp
|
dirent.cpp
|
||||||
|
dlfcn.cpp
|
||||||
fcntl.cpp
|
fcntl.cpp
|
||||||
|
ftw.cpp
|
||||||
grp.cpp
|
grp.cpp
|
||||||
inttypes.cpp
|
inttypes.cpp
|
||||||
locale.cpp
|
locale.cpp
|
||||||
|
@ -13,13 +15,14 @@ set(LIBC_SOURCES
|
||||||
printf_impl.cpp
|
printf_impl.cpp
|
||||||
pwd.cpp
|
pwd.cpp
|
||||||
scanf_impl.cpp
|
scanf_impl.cpp
|
||||||
|
setjmp.cpp
|
||||||
signal.cpp
|
signal.cpp
|
||||||
stdio.cpp
|
stdio.cpp
|
||||||
stdlib.cpp
|
stdlib.cpp
|
||||||
string.cpp
|
string.cpp
|
||||||
strings.cpp
|
strings.cpp
|
||||||
stropts.cpp
|
|
||||||
sys/banan-os.cpp
|
sys/banan-os.cpp
|
||||||
|
sys/ioctl.cpp
|
||||||
sys/mman.cpp
|
sys/mman.cpp
|
||||||
sys/select.cpp
|
sys/select.cpp
|
||||||
sys/socket.cpp
|
sys/socket.cpp
|
||||||
|
@ -30,8 +33,12 @@ set(LIBC_SOURCES
|
||||||
termios.cpp
|
termios.cpp
|
||||||
time.cpp
|
time.cpp
|
||||||
unistd.cpp
|
unistd.cpp
|
||||||
|
utime.cpp
|
||||||
|
wchar.cpp
|
||||||
icxxabi.cpp
|
icxxabi.cpp
|
||||||
|
|
||||||
|
arch/${BANAN_ARCH}/setjmp.S
|
||||||
|
|
||||||
../../../BAN/BAN/Assert.cpp
|
../../../BAN/BAN/Assert.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// int setjmp(jmp_buf env)
|
||||||
|
.global setjmp
|
||||||
|
setjmp:
|
||||||
|
movl 4(%esp), %edx
|
||||||
|
|
||||||
|
leal 4(%esp), %eax
|
||||||
|
movl %eax, 0(%edx)
|
||||||
|
|
||||||
|
movl (%esp), %eax
|
||||||
|
movl %eax, 4(%edx)
|
||||||
|
|
||||||
|
xorl %eax, %eax
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
// void longjmp(jmp_buf env, int val)
|
||||||
|
.global longjmp
|
||||||
|
longjmp:
|
||||||
|
movl 4(%esp), %edx
|
||||||
|
|
||||||
|
movl 8(%esp), %ecx
|
||||||
|
movl $1, %eax
|
||||||
|
testl %ecx, %ecx
|
||||||
|
cmovnzl %ecx, %eax
|
||||||
|
|
||||||
|
movl 0(%edx), %esp
|
||||||
|
movl 4(%edx), %ecx
|
||||||
|
jmp *%ecx
|
|
@ -0,0 +1,23 @@
|
||||||
|
// int setjmp(jmp_buf env)
|
||||||
|
.global setjmp
|
||||||
|
setjmp:
|
||||||
|
leaq 8(%rsp), %rax
|
||||||
|
movq %rax, 0(%rdi)
|
||||||
|
|
||||||
|
movq (%rsp), %rax
|
||||||
|
movq %rax, 8(%rdi)
|
||||||
|
|
||||||
|
xorq %rax, %rax
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
// void longjmp(jmp_buf env, int val)
|
||||||
|
.global longjmp
|
||||||
|
longjmp:
|
||||||
|
movq $1, %rax
|
||||||
|
testq %rsi, %rsi
|
||||||
|
cmovnzq %rsi, %rax
|
||||||
|
|
||||||
|
movq 0(%rdi), %rsp
|
||||||
|
movq 8(%rdi), %rcx
|
||||||
|
jmp *%rcx
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
int dlclose(void*)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
char* dlerror(void)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* dlopen(const char*, int)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* dlsym(void* __restrict, const char* __restrict)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
|
|
||||||
|
#include <ftw.h>
|
||||||
|
|
||||||
|
int ftw(const char*, int (*)(const char*, const struct stat*, int), int)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
int nftw(const char*, int (*)(const char*, const struct stat*, int, struct FTW*), int, int)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
|
@ -39,26 +39,3 @@ extern "C" void __cxa_finalize(void* f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace __cxxabiv1
|
|
||||||
{
|
|
||||||
using __guard = uint64_t;
|
|
||||||
|
|
||||||
extern "C" int __cxa_guard_acquire (__guard* g)
|
|
||||||
{
|
|
||||||
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
|
|
||||||
uint8_t zero = 0;
|
|
||||||
return __atomic_compare_exchange_n(byte, &zero, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_guard_release (__guard* g)
|
|
||||||
{
|
|
||||||
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
|
|
||||||
__atomic_store_n(byte, 0, __ATOMIC_RELEASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void __cxa_guard_abort (__guard*)
|
|
||||||
{
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,13 +7,16 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
typedef int jmp_buf[1];
|
typedef long jmp_buf[2];
|
||||||
typedef int sigjmp_buf[1];
|
typedef long sigjmp_buf[2 + 1 + (sizeof(long long) / sizeof(long))];
|
||||||
|
|
||||||
void longjmp(jmp_buf env, int val);
|
#define _longjmp longjmp
|
||||||
void siglongjmp(sigjmp_buf env, int val);
|
void longjmp(jmp_buf env, int val);
|
||||||
int setjmp(jmp_buf env);
|
void siglongjmp(sigjmp_buf env, int val);
|
||||||
int sigsetjmp(sigjmp_buf env, int savemask);
|
|
||||||
|
#define _setjmp setjmp
|
||||||
|
int setjmp(jmp_buf env);
|
||||||
|
int sigsetjmp(sigjmp_buf env, int savemask);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,8 @@ struct sigevent
|
||||||
#define SIGVTALRM 26
|
#define SIGVTALRM 26
|
||||||
#define SIGXCPU 27
|
#define SIGXCPU 27
|
||||||
#define SIGXFSZ 28
|
#define SIGXFSZ 28
|
||||||
#define SIGRTMIN 29
|
#define SIGWINCH 29
|
||||||
|
#define SIGRTMIN 30
|
||||||
#define SIGRTMAX (SIGRTMIN+32)
|
#define SIGRTMAX (SIGRTMIN+32)
|
||||||
|
|
||||||
#define _SIGMIN SIGABRT
|
#define _SIGMIN SIGABRT
|
||||||
|
|
|
@ -73,6 +73,7 @@ int mblen(const char* s, size_t n);
|
||||||
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n);
|
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n);
|
||||||
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n);
|
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n);
|
||||||
char* mkdtemp(char* _template);
|
char* mkdtemp(char* _template);
|
||||||
|
char* mktemp(char* _template);
|
||||||
int mkstemp(char* _template);
|
int mkstemp(char* _template);
|
||||||
long mrand48(void);
|
long mrand48(void);
|
||||||
long nrand48(unsigned short xsubi[3]);
|
long nrand48(unsigned short xsubi[3]);
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#define __need_uid_t
|
#define __need_uid_t
|
||||||
#define __need_gid_t
|
#define __need_gid_t
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -71,45 +73,6 @@ struct str_list
|
||||||
int sl_nmods; /* Number of STREAMS module names. */
|
int sl_nmods; /* Number of STREAMS module names. */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define I_ATMARK 1
|
|
||||||
#define I_CANPUT 2
|
|
||||||
#define I_CKBAND 3
|
|
||||||
#define I_FDINSERT 4
|
|
||||||
#define I_FIND 5
|
|
||||||
#define I_FLUSH 6
|
|
||||||
#define I_FLUSHBAND 7
|
|
||||||
#define I_GETBAND 8
|
|
||||||
#define I_GETCLTIME 9
|
|
||||||
#define I_GETSIG 10
|
|
||||||
#define I_GRDOPT 11
|
|
||||||
#define I_GWROPT 12
|
|
||||||
#define I_LINK 13
|
|
||||||
#define I_LIST 14
|
|
||||||
#define I_LOOK 15
|
|
||||||
#define I_NREAD 16
|
|
||||||
#define I_PEEK 17
|
|
||||||
#define I_PLINK 18
|
|
||||||
#define I_POP 19
|
|
||||||
#define I_PUNLINK 20
|
|
||||||
#define I_PUSH 21
|
|
||||||
#define I_RECVFD 22
|
|
||||||
#define I_SENDFD 23
|
|
||||||
#define I_SETCLTIME 24
|
|
||||||
#define I_SETSIG 25
|
|
||||||
#define I_SRDOPT 26
|
|
||||||
#define I_STR 27
|
|
||||||
#define I_SWROPT 28
|
|
||||||
#define I_UNLINK 29
|
|
||||||
|
|
||||||
#define KDLOADFONT 30
|
|
||||||
|
|
||||||
struct winsize
|
|
||||||
{
|
|
||||||
unsigned short ws_row;
|
|
||||||
unsigned short ws_col;
|
|
||||||
};
|
|
||||||
#define TIOCGWINSZ 50
|
|
||||||
|
|
||||||
#define FLUSHR 1
|
#define FLUSHR 1
|
||||||
#define FLUSHRW 2
|
#define FLUSHRW 2
|
||||||
#define FLUSHW 3
|
#define FLUSHW 3
|
||||||
|
@ -152,7 +115,6 @@ int fattach(int, const char*);
|
||||||
int fdetach(const char*);
|
int fdetach(const char*);
|
||||||
int getmsg(int, struct strbuf* __restrict, struct strbuf* __restrict, int* __restrict);
|
int getmsg(int, struct strbuf* __restrict, struct strbuf* __restrict, int* __restrict);
|
||||||
int getpmsg(int, struct strbuf* __restrict, struct strbuf* __restrict, int* __restrict, int* __restrict);
|
int getpmsg(int, struct strbuf* __restrict, struct strbuf* __restrict, int* __restrict, int* __restrict);
|
||||||
int ioctl(int, int, ...);
|
|
||||||
int isastream(int);
|
int isastream(int);
|
||||||
int putmsg(int, const struct strbuf*, const struct strbuf*, int);
|
int putmsg(int, const struct strbuf*, const struct strbuf*, int);
|
||||||
int putpmsg(int, const struct strbuf*, const struct strbuf*, int, int);
|
int putpmsg(int, const struct strbuf*, const struct strbuf*, int, int);
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef _SYS_IOCTL_H
|
||||||
|
#define _SYS_IOCTL_H 1
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define I_ATMARK 1
|
||||||
|
#define I_CANPUT 2
|
||||||
|
#define I_CKBAND 3
|
||||||
|
#define I_FDINSERT 4
|
||||||
|
#define I_FIND 5
|
||||||
|
#define I_FLUSH 6
|
||||||
|
#define I_FLUSHBAND 7
|
||||||
|
#define I_GETBAND 8
|
||||||
|
#define I_GETCLTIME 9
|
||||||
|
#define I_GETSIG 10
|
||||||
|
#define I_GRDOPT 11
|
||||||
|
#define I_GWROPT 12
|
||||||
|
#define I_LINK 13
|
||||||
|
#define I_LIST 14
|
||||||
|
#define I_LOOK 15
|
||||||
|
#define I_NREAD 16
|
||||||
|
#define I_PEEK 17
|
||||||
|
#define I_PLINK 18
|
||||||
|
#define I_POP 19
|
||||||
|
#define I_PUNLINK 20
|
||||||
|
#define I_PUSH 21
|
||||||
|
#define I_RECVFD 22
|
||||||
|
#define I_SENDFD 23
|
||||||
|
#define I_SETCLTIME 24
|
||||||
|
#define I_SETSIG 25
|
||||||
|
#define I_SRDOPT 26
|
||||||
|
#define I_STR 27
|
||||||
|
#define I_SWROPT 28
|
||||||
|
#define I_UNLINK 29
|
||||||
|
|
||||||
|
#define KDLOADFONT 30
|
||||||
|
|
||||||
|
struct winsize
|
||||||
|
{
|
||||||
|
unsigned short ws_row;
|
||||||
|
unsigned short ws_col;
|
||||||
|
};
|
||||||
|
#define TIOCGWINSZ 50
|
||||||
|
#define TIOCSWINSZ 51
|
||||||
|
|
||||||
|
int ioctl(int, int, ...);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,34 +18,34 @@ typedef unsigned long __fd_mask;
|
||||||
#define __FD_MASK_SIZE (8 * sizeof(__fd_mask))
|
#define __FD_MASK_SIZE (8 * sizeof(__fd_mask))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
__fd_mask __bits[FD_SETSIZE / __FD_MASK_SIZE];
|
__fd_mask __fds_bits[FD_SETSIZE / __FD_MASK_SIZE];
|
||||||
} fd_set;
|
} fd_set;
|
||||||
|
|
||||||
#define FD_CLR(fd, setp) \
|
#define FD_CLR(fd, setp) \
|
||||||
do { \
|
do { \
|
||||||
__fd_mask off = (fd) / __FD_MASK_SIZE; \
|
__fd_mask off = (fd) / __FD_MASK_SIZE; \
|
||||||
__fd_mask bit = (fd) % __FD_MASK_SIZE; \
|
__fd_mask bit = (fd) % __FD_MASK_SIZE; \
|
||||||
(setp)->__bits[off] &= ~((__fd_mask)1 << bit); \
|
(setp)->__fds_bits[off] &= ~((__fd_mask)1 << bit); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define FD_ISSET(fd, setp) \
|
#define FD_ISSET(fd, setp) \
|
||||||
({ \
|
({ \
|
||||||
__fd_mask off = (fd) / __FD_MASK_SIZE; \
|
__fd_mask off = (fd) / __FD_MASK_SIZE; \
|
||||||
__fd_mask bit = (fd) % __FD_MASK_SIZE; \
|
__fd_mask bit = (fd) % __FD_MASK_SIZE; \
|
||||||
(setp)->__bits[off] & ((__fd_mask)1 << bit); \
|
(setp)->__fds_bits[off] & ((__fd_mask)1 << bit); \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define FD_SET(fd, setp) \
|
#define FD_SET(fd, setp) \
|
||||||
do { \
|
do { \
|
||||||
__fd_mask off = (fd) / __FD_MASK_SIZE; \
|
__fd_mask off = (fd) / __FD_MASK_SIZE; \
|
||||||
__fd_mask bit = (fd) % __FD_MASK_SIZE; \
|
__fd_mask bit = (fd) % __FD_MASK_SIZE; \
|
||||||
(setp)->__bits[off] |= ((__fd_mask)1 << bit); \
|
(setp)->__fds_bits[off] |= ((__fd_mask)1 << bit); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define FD_ZERO(setp) \
|
#define FD_ZERO(setp) \
|
||||||
do { \
|
do { \
|
||||||
for (int i = 0; i < (int)FD_SETSIZE / (int)__FD_MASK_SIZE; i++) \
|
for (int i = 0; i < (int)FD_SETSIZE / (int)__FD_MASK_SIZE; i++) \
|
||||||
(setp)->__bits[i] = (__fd_mask)0; \
|
(setp)->__fds_bits[i] = (__fd_mask)0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
struct sys_pselect_t
|
struct sys_pselect_t
|
||||||
|
|
|
@ -25,6 +25,7 @@ __BEGIN_DECLS
|
||||||
O(SYS_READ_DIR, readdir) \
|
O(SYS_READ_DIR, readdir) \
|
||||||
O(SYS_SET_UID, setuid) \
|
O(SYS_SET_UID, setuid) \
|
||||||
O(SYS_SET_GID, setgid) \
|
O(SYS_SET_GID, setgid) \
|
||||||
|
O(SYS_SET_SID, setsid) \
|
||||||
O(SYS_SET_EUID, seteuid) \
|
O(SYS_SET_EUID, seteuid) \
|
||||||
O(SYS_SET_EGID, setegid) \
|
O(SYS_SET_EGID, setegid) \
|
||||||
O(SYS_SET_REUID, setreuid) \
|
O(SYS_SET_REUID, setreuid) \
|
||||||
|
@ -87,6 +88,8 @@ __BEGIN_DECLS
|
||||||
O(SYS_SIGPENDING, sigpending) \
|
O(SYS_SIGPENDING, sigpending) \
|
||||||
O(SYS_SIGPROCMASK, sigprocmask) \
|
O(SYS_SIGPROCMASK, sigprocmask) \
|
||||||
O(SYS_SETITIMER, setitimer) \
|
O(SYS_SETITIMER, setitimer) \
|
||||||
|
O(SYS_POSIX_OPENPT, posix_openpt) \
|
||||||
|
O(SYS_PTSNAME, ptsname) \
|
||||||
|
|
||||||
enum Syscall
|
enum Syscall
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,7 +106,30 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
// FIXME: _CS prefixed definitions
|
// FIXME: _CS prefixed definitions
|
||||||
|
|
||||||
// FIXME: _PC prefixed definitions
|
enum
|
||||||
|
{
|
||||||
|
_PC_2_SYMLINKS,
|
||||||
|
_PC_ALLOC_SIZE_MIN,
|
||||||
|
_PC_ASYNC_IO,
|
||||||
|
_PC_CHOWN_RESTRICTED,
|
||||||
|
_PC_FILESIZEBITS,
|
||||||
|
_PC_LINK_MAX,
|
||||||
|
_PC_MAX_CANON,
|
||||||
|
_PC_MAX_INPUT,
|
||||||
|
_PC_NAME_MAX,
|
||||||
|
_PC_NO_TRUNC,
|
||||||
|
_PC_PATH_MAX,
|
||||||
|
_PC_PIPE_BUF,
|
||||||
|
_PC_PRIO_IO,
|
||||||
|
_PC_REC_INCR_XFER_SIZE,
|
||||||
|
_PC_REC_MAX_XFER_SIZE,
|
||||||
|
_PC_REC_MIN_XFER_SIZE,
|
||||||
|
_PC_REC_XFER_ALIGN,
|
||||||
|
_PC_SYMLINK_MAX,
|
||||||
|
_PC_SYNC_IO,
|
||||||
|
_PC_TIMESTAMP_RESOLUTION,
|
||||||
|
_PC_VDISABLE,
|
||||||
|
};
|
||||||
|
|
||||||
#define F_OK 0x01
|
#define F_OK 0x01
|
||||||
#define R_OK 0x02
|
#define R_OK 0x02
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <BAN/Assert.h>
|
#include <BAN/Assert.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -35,6 +36,38 @@ static const char* locale_to_str(locale_t locale)
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct lconv* localeconv(void)
|
||||||
|
{
|
||||||
|
constexpr char CHAR_MAX = __SCHAR_MAX__;
|
||||||
|
|
||||||
|
static lconv lconv;
|
||||||
|
lconv.currency_symbol = const_cast<char*>("");
|
||||||
|
lconv.decimal_point = const_cast<char*>(".");
|
||||||
|
lconv.frac_digits = CHAR_MAX;
|
||||||
|
lconv.grouping = const_cast<char*>("");
|
||||||
|
lconv.int_curr_symbol = const_cast<char*>("");
|
||||||
|
lconv.int_frac_digits = CHAR_MAX;
|
||||||
|
lconv.int_n_cs_precedes = CHAR_MAX;
|
||||||
|
lconv.int_n_sep_by_space = CHAR_MAX;
|
||||||
|
lconv.int_n_sign_posn = CHAR_MAX;
|
||||||
|
lconv.int_p_cs_precedes = CHAR_MAX;
|
||||||
|
lconv.int_p_sep_by_space = CHAR_MAX;
|
||||||
|
lconv.int_p_sign_posn = CHAR_MAX;
|
||||||
|
lconv.mon_decimal_point = const_cast<char*>("");
|
||||||
|
lconv.mon_grouping = const_cast<char*>("");
|
||||||
|
lconv.mon_thousands_sep = const_cast<char*>("");
|
||||||
|
lconv.negative_sign = const_cast<char*>("");
|
||||||
|
lconv.n_cs_precedes = CHAR_MAX;
|
||||||
|
lconv.n_sep_by_space = CHAR_MAX;
|
||||||
|
lconv.n_sign_posn = CHAR_MAX;
|
||||||
|
lconv.positive_sign = const_cast<char*>("");
|
||||||
|
lconv.p_cs_precedes = CHAR_MAX;
|
||||||
|
lconv.p_sep_by_space = CHAR_MAX;
|
||||||
|
lconv.p_sign_posn = CHAR_MAX;
|
||||||
|
lconv.thousands_sep = const_cast<char*>("");
|
||||||
|
return &lconv;
|
||||||
|
}
|
||||||
|
|
||||||
char* setlocale(int category, const char* locale_str)
|
char* setlocale(int category, const char* locale_str)
|
||||||
{
|
{
|
||||||
static char s_locale_buffer[128];
|
static char s_locale_buffer[128];
|
||||||
|
@ -94,7 +127,6 @@ char* setlocale(int category, const char* locale_str)
|
||||||
return s_locale_buffer;
|
return s_locale_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
locale_t __getlocale(int category)
|
locale_t __getlocale(int category)
|
||||||
{
|
{
|
||||||
switch (category)
|
switch (category)
|
||||||
|
|
|
@ -8,7 +8,12 @@
|
||||||
#define BUILTINS2(func) \
|
#define BUILTINS2(func) \
|
||||||
float func##f(float a, float b) { return __builtin_##func##f(a, b); } \
|
float func##f(float a, float b) { return __builtin_##func##f(a, b); } \
|
||||||
double func(double a, double b) { return __builtin_##func(a, b); } \
|
double func(double a, double b) { return __builtin_##func(a, b); } \
|
||||||
long double func##l(long double a, long double b) { return __builtin_##func##l(a, b); } \
|
long double func##l(long double a, long double b) { return __builtin_##func##l(a, b); }
|
||||||
|
|
||||||
|
#define BUILTINS2_TYPE(func, type) \
|
||||||
|
float func##f(float a, type b) { return __builtin_##func##f(a, b); } \
|
||||||
|
double func(double a, type b) { return __builtin_##func(a, b); } \
|
||||||
|
long double func##l(long double a, type b) { return __builtin_##func##l(a, b); }
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -38,6 +43,7 @@ BUILTINS2(fmod)
|
||||||
BUILTINS2(hypot)
|
BUILTINS2(hypot)
|
||||||
BUILTINS1(j0)
|
BUILTINS1(j0)
|
||||||
BUILTINS1(j1)
|
BUILTINS1(j1)
|
||||||
|
BUILTINS2_TYPE(ldexp, int)
|
||||||
BUILTINS1(lgamma)
|
BUILTINS1(lgamma)
|
||||||
BUILTINS1(log)
|
BUILTINS1(log)
|
||||||
BUILTINS1(log10)
|
BUILTINS1(log10)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
#include <BAN/Bitcast.h>
|
#include <BAN/Bitcast.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -11,6 +12,35 @@
|
||||||
|
|
||||||
int h_errno = 0;
|
int h_errno = 0;
|
||||||
|
|
||||||
|
void freeaddrinfo(struct addrinfo*)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* gai_strerror(int ecode)
|
||||||
|
{
|
||||||
|
switch (ecode)
|
||||||
|
{
|
||||||
|
case 0: return "Success";
|
||||||
|
case EAI_AGAIN: return "The name could not be resolved at this time.";
|
||||||
|
case EAI_BADFLAGS: return "The flags had an invalid value.";
|
||||||
|
case EAI_FAIL: return "A non-recoverable error occurred.";
|
||||||
|
case EAI_FAMILY: return "The address family was not recognized or the address length was invalid for the specified family.";
|
||||||
|
case EAI_MEMORY: return "There was a memory allocation failure.";
|
||||||
|
case EAI_NONAME: return "The name does not resolve for the supplied parameters. ";
|
||||||
|
case EAI_SERVICE: return "The service passed was not recognized for the specified socket type.";
|
||||||
|
case EAI_SOCKTYPE: return "The intended socket type was not recognized.";
|
||||||
|
case EAI_SYSTEM: return "A system error occurred. The error code can be found in errno.";
|
||||||
|
case EAI_OVERFLOW: return "An argument buffer overflowed.";
|
||||||
|
default: return "Unknown error.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getaddrinfo(const char* __restrict, const char* __restrict, const struct addrinfo* __restrict, struct addrinfo** __restrict)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
struct hostent* gethostbyname(const char* name)
|
struct hostent* gethostbyname(const char* name)
|
||||||
{
|
{
|
||||||
static char name_buffer[HOST_NAME_MAX + 1];
|
static char name_buffer[HOST_NAME_MAX + 1];
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
static_assert(sizeof(sigjmp_buf) == sizeof(jmp_buf) + sizeof(long) + sizeof(sigset_t));
|
||||||
|
|
||||||
|
void siglongjmp(sigjmp_buf env, int val)
|
||||||
|
{
|
||||||
|
if (env[2])
|
||||||
|
pthread_sigmask(SIG_SETMASK, reinterpret_cast<sigset_t*>(&env[3]), nullptr);
|
||||||
|
return longjmp(env, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sigsetjmp(sigjmp_buf env, int savemask)
|
||||||
|
{
|
||||||
|
env[2] = savemask;
|
||||||
|
if (savemask)
|
||||||
|
pthread_sigmask(0, nullptr, reinterpret_cast<sigset_t*>(&env[3]));
|
||||||
|
return setjmp(env);
|
||||||
|
}
|
|
@ -733,14 +733,12 @@ FILE* tmpfile(void);
|
||||||
|
|
||||||
char* tmpnam(char* storage)
|
char* tmpnam(char* storage)
|
||||||
{
|
{
|
||||||
static int s_counter = rand();
|
|
||||||
static char s_storage[PATH_MAX];
|
static char s_storage[PATH_MAX];
|
||||||
if (storage == nullptr)
|
if (storage == nullptr)
|
||||||
storage = s_storage;
|
storage = s_storage;
|
||||||
for (int i = 0; i < TMP_MAX; i++)
|
for (int i = 0; i < TMP_MAX; i++)
|
||||||
{
|
{
|
||||||
sprintf(storage, "/tmp/tmp_%04x", s_counter);
|
sprintf(storage, "/tmp/tmp_%04x", rand());
|
||||||
s_counter = rand();
|
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(storage, &st) == -1 && errno == ENOENT)
|
if (stat(storage, &st) == -1 && errno == ENOENT)
|
||||||
|
@ -842,3 +840,8 @@ int vsscanf(const char* s, const char* format, va_list arguments)
|
||||||
}, &s
|
}, &s
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* tmpfile(void)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
|
@ -514,6 +514,36 @@ int putenv(char* string)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* mktemp(char*)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
int posix_openpt(int oflag)
|
||||||
|
{
|
||||||
|
return syscall(SYS_POSIX_OPENPT, oflag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int grantpt(int)
|
||||||
|
{
|
||||||
|
// currently posix_openpt() does this
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unlockpt(int)
|
||||||
|
{
|
||||||
|
// currently posix_openpt() does this
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ptsname(int fildes)
|
||||||
|
{
|
||||||
|
static char buffer[PATH_MAX];
|
||||||
|
if (syscall(SYS_PTSNAME, fildes, buffer, sizeof(buffer)) == -1)
|
||||||
|
return nullptr;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
|
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
|
||||||
{
|
{
|
||||||
auto* us = reinterpret_cast<const unsigned char*>(s);
|
auto* us = reinterpret_cast<const unsigned char*>(s);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stropts.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -11,6 +13,11 @@ int chmod(const char* path, mode_t mode)
|
||||||
return syscall(SYS_CHMOD, path, mode);
|
return syscall(SYS_CHMOD, path, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fchmod(int, mode_t)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
int fstat(int fildes, struct stat* buf)
|
int fstat(int fildes, struct stat* buf)
|
||||||
{
|
{
|
||||||
return syscall(SYS_FSTAT, fildes, buf);
|
return syscall(SYS_FSTAT, fildes, buf);
|
||||||
|
|
|
@ -71,7 +71,7 @@ int tcflow(int, int);
|
||||||
int tcflush(int fd, int queue_selector)
|
int tcflush(int fd, int queue_selector)
|
||||||
{
|
{
|
||||||
dwarnln("FIXME: tcflush({}, {})", fd, queue_selector);
|
dwarnln("FIXME: tcflush({}, {})", fd, queue_selector);
|
||||||
ASSERT_NOT_REACHED();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcgetattr(int fildes, struct termios* termios)
|
int tcgetattr(int fildes, struct termios* termios)
|
||||||
|
|
|
@ -475,6 +475,11 @@ int setgid(gid_t gid)
|
||||||
return syscall(SYS_SET_GID, gid);
|
return syscall(SYS_SET_GID, gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int setsid(void)
|
||||||
|
{
|
||||||
|
return syscall(SYS_SET_SID);
|
||||||
|
}
|
||||||
|
|
||||||
int setreuid(uid_t ruid, uid_t euid)
|
int setreuid(uid_t ruid, uid_t euid)
|
||||||
{
|
{
|
||||||
return syscall(SYS_SET_REUID, ruid, euid);
|
return syscall(SYS_SET_REUID, ruid, euid);
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
|
|
||||||
|
#include <utime.h>
|
||||||
|
|
||||||
|
int utime(const char*, const struct utimbuf*)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
|
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
size_t mbrtowc(wchar_t* __restrict, const char* __restrict, size_t, mbstate_t* __restrict)
|
||||||
|
{
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
|
@ -147,7 +147,7 @@ BAN::Optional<BAN::String> parse_dollar(BAN::StringView command, size_t& i)
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
if (waitpid(pid, &status, 0) == -1 && errno != ECHILD)
|
if (waitpid(pid, &status, 0) == -1)
|
||||||
ERROR_RETURN("waitpid", {});
|
ERROR_RETURN("waitpid", {});
|
||||||
|
|
||||||
while (!output.empty() && output.back() == '\n')
|
while (!output.empty() && output.back() == '\n')
|
||||||
|
|
|
@ -4,59 +4,63 @@
|
||||||
#include <BAN/UTF8.h>
|
#include <BAN/UTF8.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void Terminal::start_shell()
|
void Terminal::start_shell()
|
||||||
{
|
{
|
||||||
int shell_stdin[2];
|
int pts_master = posix_openpt(O_RDWR | O_NOCTTY);
|
||||||
if (pipe(shell_stdin) == -1)
|
if (pts_master == -1)
|
||||||
{
|
{
|
||||||
dwarnln("pipe: {}", strerror(errno));
|
dwarnln("posix_openpt: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int shell_stdout[2];
|
if (grantpt(pts_master) == -1)
|
||||||
if (pipe(shell_stdout) == -1)
|
|
||||||
{
|
{
|
||||||
dwarnln("pipe: {}", strerror(errno));
|
dwarnln("grantpt: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int shell_stderr[2];
|
if (unlockpt(pts_master) == -1)
|
||||||
if (pipe(shell_stderr) == -1)
|
|
||||||
{
|
{
|
||||||
dwarnln("pipe: {}", strerror(errno));
|
dwarnln("unlockpt: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t shell_pid = fork();
|
pid_t shell_pid = fork();
|
||||||
if (shell_pid == 0)
|
if (shell_pid == 0)
|
||||||
{
|
{
|
||||||
if (dup2(shell_stdin[0], STDIN_FILENO) == -1)
|
if (setsid() == -1)
|
||||||
{
|
{
|
||||||
dwarnln("dup2: {}", strerror(errno));
|
dwarnln("setsid: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(shell_stdin[0]);
|
|
||||||
close(shell_stdin[1]);
|
|
||||||
|
|
||||||
if (dup2(shell_stdout[1], STDOUT_FILENO) == -1)
|
char* pts_slave_name = ptsname(pts_master);
|
||||||
|
if (pts_slave_name == nullptr)
|
||||||
{
|
{
|
||||||
dwarnln("dup2: {}", strerror(errno));
|
dwarnln("ptsname: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(shell_stdout[0]);
|
|
||||||
close(shell_stdout[1]);
|
|
||||||
|
|
||||||
if (dup2(shell_stderr[1], STDERR_FILENO) == -1)
|
int pts_slave = open(pts_slave_name, O_RDWR);
|
||||||
|
if (pts_slave == -1)
|
||||||
|
{
|
||||||
|
dwarnln("open: {}", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dup2(pts_slave, STDIN_FILENO) == -1 || dup2(pts_slave, STDOUT_FILENO) == -1 || dup2(pts_slave, STDERR_FILENO) == -1)
|
||||||
{
|
{
|
||||||
dwarnln("dup2: {}", strerror(errno));
|
dwarnln("dup2: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
close(shell_stderr[0]);
|
|
||||||
close(shell_stderr[1]);
|
close(pts_slave);
|
||||||
|
close(pts_master);
|
||||||
|
|
||||||
execl("/bin/Shell", "Shell", NULL);
|
execl("/bin/Shell", "Shell", NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -68,14 +72,8 @@ void Terminal::start_shell()
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(shell_stdin[0]);
|
|
||||||
close(shell_stdout[1]);
|
|
||||||
close(shell_stderr[1]);
|
|
||||||
|
|
||||||
m_shell_info = {
|
m_shell_info = {
|
||||||
.in = shell_stdin[1],
|
.pts_master = pts_master,
|
||||||
.out = shell_stdout[0],
|
|
||||||
.err = shell_stderr[0],
|
|
||||||
.pid = shell_pid
|
.pid = shell_pid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -95,22 +93,18 @@ void Terminal::run()
|
||||||
|
|
||||||
m_window->set_key_event_callback([&](LibGUI::EventPacket::KeyEvent event) { on_key_event(event); });
|
m_window->set_key_event_callback([&](LibGUI::EventPacket::KeyEvent event) { on_key_event(event); });
|
||||||
|
|
||||||
const int max_fd = BAN::Math::max(BAN::Math::max(m_shell_info.out, m_shell_info.err), m_window->server_fd());
|
const int max_fd = BAN::Math::max(m_shell_info.pts_master, m_window->server_fd());
|
||||||
while (!s_shell_exited)
|
while (!s_shell_exited)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(m_shell_info.out, &fds);
|
FD_SET(m_shell_info.pts_master, &fds);
|
||||||
FD_SET(m_shell_info.err, &fds);
|
|
||||||
FD_SET(m_window->server_fd(), &fds);
|
FD_SET(m_window->server_fd(), &fds);
|
||||||
|
|
||||||
select(max_fd + 1, &fds, nullptr, nullptr, nullptr);
|
select(max_fd + 1, &fds, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
if (FD_ISSET(m_shell_info.out, &fds))
|
if (FD_ISSET(m_shell_info.pts_master, &fds))
|
||||||
if (!read_shell(m_shell_info.out))
|
if (!read_shell())
|
||||||
break;
|
|
||||||
if (FD_ISSET(m_shell_info.err, &fds))
|
|
||||||
if (!read_shell(m_shell_info.err))
|
|
||||||
break;
|
break;
|
||||||
if (FD_ISSET(m_window->server_fd(), &fds))
|
if (FD_ISSET(m_window->server_fd(), &fds))
|
||||||
m_window->poll_events();
|
m_window->poll_events();
|
||||||
|
@ -118,10 +112,10 @@ void Terminal::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Terminal::read_shell(int fd)
|
bool Terminal::read_shell()
|
||||||
{
|
{
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
ssize_t nread = read(fd, buffer, sizeof(buffer) - 1);
|
ssize_t nread = read(m_shell_info.pts_master, buffer, sizeof(buffer) - 1);
|
||||||
if (nread < 0)
|
if (nread < 0)
|
||||||
dwarnln("read: {}", strerror(errno));
|
dwarnln("read: {}", strerror(errno));
|
||||||
if (nread <= 0)
|
if (nread <= 0)
|
||||||
|
@ -295,13 +289,13 @@ void Terminal::handle_csi(char ch)
|
||||||
m_state = State::Normal;
|
m_state = State::Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::putchar(uint32_t codepoint)
|
void Terminal::putchar(uint8_t ch)
|
||||||
{
|
{
|
||||||
if (m_state == State::ESC)
|
if (m_state == State::ESC)
|
||||||
{
|
{
|
||||||
if (codepoint != '[')
|
if (ch != '[')
|
||||||
{
|
{
|
||||||
dprintln("unknown escape character 0x{H}", codepoint);
|
dprintln("unknown escape character 0x{2H}", ch);
|
||||||
m_state = State::Normal;
|
m_state = State::Normal;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -314,13 +308,46 @@ void Terminal::putchar(uint32_t codepoint)
|
||||||
|
|
||||||
if (m_state == State::CSI)
|
if (m_state == State::CSI)
|
||||||
{
|
{
|
||||||
if (codepoint < 0x20 || codepoint > 0xFE)
|
if (ch < 0x20 || ch > 0xFE)
|
||||||
{
|
{
|
||||||
dprintln("invalid CSI 0x{H}", codepoint);
|
dprintln("invalid CSI 0x{2H}", ch);
|
||||||
m_state = State::Normal;
|
m_state = State::Normal;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handle_csi(codepoint);
|
handle_csi(ch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_utf8_bytes[m_utf8_index++] = ch;
|
||||||
|
|
||||||
|
const size_t utf8_len = BAN::UTF8::byte_length(m_utf8_bytes[0]);
|
||||||
|
if (utf8_len == 0)
|
||||||
|
{
|
||||||
|
dwarnln("invalid utf8 leading byte 0x{2H}", ch);
|
||||||
|
m_utf8_index = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_utf8_index < utf8_len)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const uint32_t codepoint = BAN::UTF8::to_codepoint(m_utf8_bytes);
|
||||||
|
m_utf8_index = 0;
|
||||||
|
|
||||||
|
if (codepoint == BAN::UTF8::invalid)
|
||||||
|
{
|
||||||
|
char utf8_hex[20];
|
||||||
|
char* ptr = utf8_hex;
|
||||||
|
for (uint8_t i = 0; i < utf8_len; i++)
|
||||||
|
{
|
||||||
|
*ptr++ = '0';
|
||||||
|
*ptr++ = 'x';
|
||||||
|
*ptr++ = (m_utf8_bytes[i] >> 4) < 10 ? (m_utf8_bytes[i] >> 4) + '0' : (m_utf8_bytes[i] >> 4) - 10 + 'A';
|
||||||
|
*ptr++ = (m_utf8_bytes[i] & 0xF) < 10 ? (m_utf8_bytes[i] & 0xF) + '0' : (m_utf8_bytes[i] & 0xF) - 10 + 'A';
|
||||||
|
*ptr++ = ' ';
|
||||||
|
}
|
||||||
|
*--ptr = '\0';
|
||||||
|
|
||||||
|
dwarnln("invalid utf8 {}", utf8_hex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,5 +403,5 @@ void Terminal::on_key_event(LibGUI::EventPacket::KeyEvent event)
|
||||||
if (event.released())
|
if (event.released())
|
||||||
return;
|
return;
|
||||||
if (const char* text = LibInput::key_to_utf8_ansi(event.key, event.modifier))
|
if (const char* text = LibInput::key_to_utf8_ansi(event.key, event.modifier))
|
||||||
write(m_shell_info.in, text, strlen(text));
|
write(m_shell_info.pts_master, text, strlen(text));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ public:
|
||||||
private:
|
private:
|
||||||
void handle_csi(char ch);
|
void handle_csi(char ch);
|
||||||
void handle_sgr();
|
void handle_sgr();
|
||||||
void putchar(uint32_t codepoint);
|
void putchar(uint8_t ch);
|
||||||
bool read_shell(int fd);
|
bool read_shell();
|
||||||
|
|
||||||
void on_key_event(LibGUI::EventPacket::KeyEvent);
|
void on_key_event(LibGUI::EventPacket::KeyEvent);
|
||||||
|
|
||||||
|
@ -31,9 +31,7 @@ private:
|
||||||
|
|
||||||
struct ShellInfo
|
struct ShellInfo
|
||||||
{
|
{
|
||||||
int in;
|
int pts_master;
|
||||||
int out;
|
|
||||||
int err;
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +56,9 @@ private:
|
||||||
State m_state { State::Normal };
|
State m_state { State::Normal };
|
||||||
CSIInfo m_csi_info;
|
CSIInfo m_csi_info;
|
||||||
|
|
||||||
|
uint8_t m_utf8_index { 0 };
|
||||||
|
uint8_t m_utf8_bytes[4] { };
|
||||||
|
|
||||||
Cursor m_saved_cursor { 0, 0 };
|
Cursor m_saved_cursor { 0, 0 };
|
||||||
uint32_t m_fg_color { 0xFFFFFF };
|
uint32_t m_fg_color { 0xFFFFFF };
|
||||||
uint32_t m_bg_color { 0x000000 };
|
uint32_t m_bg_color { 0x000000 };
|
||||||
|
|
|
@ -5,6 +5,7 @@ set(USERSPACE_TESTS
|
||||||
test-mmap-shared
|
test-mmap-shared
|
||||||
test-mouse
|
test-mouse
|
||||||
test-popen
|
test-popen
|
||||||
|
test-setjmp
|
||||||
test-sort
|
test-sort
|
||||||
test-tcp
|
test-tcp
|
||||||
test-udp
|
test-udp
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
set(SOURCES
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(test-setjmp ${SOURCES})
|
||||||
|
banan_link_library(test-setjmp libc)
|
||||||
|
|
||||||
|
install(TARGETS test-setjmp OPTIONAL)
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
jmp_buf env;
|
||||||
|
|
||||||
|
void iterate()
|
||||||
|
{
|
||||||
|
static volatile int count = 0;
|
||||||
|
if (count < 10)
|
||||||
|
{
|
||||||
|
count = count + 1;
|
||||||
|
longjmp(env, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("start\n");
|
||||||
|
if (int ret = setjmp(env))
|
||||||
|
printf("longjmp %d\n", ret);
|
||||||
|
iterate();
|
||||||
|
}
|
Loading…
Reference in New Issue