Compare commits
No commits in common. "9e79ef2a9175c9586c0fe28b1e5eae40fed6d955" and "91d513a672ad93a2059807f73451aaaa1d4568df" have entirely different histories.
9e79ef2a91
...
91d513a672
|
@ -86,7 +86,6 @@ 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,
|
||||||
PTSMaster,
|
Serial,
|
||||||
Null,
|
Null,
|
||||||
Zero,
|
Zero,
|
||||||
Debug,
|
Debug,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#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>
|
||||||
|
|
||||||
|
@ -34,7 +33,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_size > 0; }
|
virtual bool can_read_impl() const override { return !m_buffer.empty(); }
|
||||||
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; }
|
||||||
|
|
||||||
|
@ -47,13 +46,10 @@ 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;
|
||||||
|
|
||||||
BAN::Array<uint8_t, PAGE_SIZE> m_buffer;
|
uint32_t m_writing_count { 1 };
|
||||||
BAN::Atomic<size_t> m_buffer_size { 0 };
|
|
||||||
size_t m_buffer_tail { 0 };
|
|
||||||
|
|
||||||
BAN::Atomic<uint32_t> m_writing_count { 1 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,6 @@ 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);
|
||||||
|
@ -174,8 +173,6 @@ 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);
|
||||||
|
|
||||||
|
@ -222,6 +219,8 @@ 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);
|
||||||
|
@ -256,12 +255,12 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ChildExitStatus
|
struct ExitStatus
|
||||||
{
|
{
|
||||||
pid_t pid { 0 };
|
ThreadBlocker thread_blocker;
|
||||||
pid_t pgrp { 0 };
|
|
||||||
int exit_code { 0 };
|
int exit_code { 0 };
|
||||||
bool exited { false };
|
BAN::Atomic<bool> exited { false };
|
||||||
|
BAN::Atomic<int> waiting { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
Credentials m_credentials;
|
Credentials m_credentials;
|
||||||
|
@ -293,10 +292,7 @@ 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 };
|
||||||
|
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
#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,6 +63,11 @@ 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,8 +42,6 @@ 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;
|
||||||
|
@ -56,7 +54,17 @@ 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;
|
||||||
|
@ -71,8 +79,6 @@ 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,6 +83,11 @@ 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,8 +49,6 @@ 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,8 +3,6 @@
|
||||||
#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
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -28,23 +26,24 @@ namespace Kernel
|
||||||
|
|
||||||
void Pipe::clone_writing()
|
void Pipe::clone_writing()
|
||||||
{
|
{
|
||||||
[[maybe_unused]] auto old_writing_count = m_writing_count.fetch_add(1);
|
LockGuard _(m_mutex);
|
||||||
ASSERT(old_writing_count > 0);
|
ASSERT(m_writing_count > 0);
|
||||||
|
m_writing_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pipe::close_writing()
|
void Pipe::close_writing()
|
||||||
{
|
{
|
||||||
auto old_writing_count = m_writing_count.fetch_sub(1);
|
LockGuard _(m_mutex);
|
||||||
ASSERT(old_writing_count > 0);
|
ASSERT(m_writing_count > 0);
|
||||||
if (old_writing_count == 1)
|
m_writing_count--;
|
||||||
|
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;
|
||||||
|
@ -52,20 +51,11 @@ namespace Kernel
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
|
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer_size);
|
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer.size());
|
||||||
|
memcpy(buffer.data(), m_buffer.data(), to_copy);
|
||||||
|
|
||||||
if (m_buffer_tail + to_copy <= m_buffer.size())
|
memmove(m_buffer.data(), m_buffer.data() + to_copy, m_buffer.size() - to_copy);
|
||||||
memcpy(buffer.data(), m_buffer.data() + m_buffer_tail, to_copy);
|
MUST(m_buffer.resize(m_buffer.size() - 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();
|
||||||
|
|
||||||
|
@ -78,29 +68,10 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
if (buffer.size() > m_buffer.size())
|
size_t old_size = m_buffer.size();
|
||||||
buffer = buffer.slice(0, m_buffer.size());
|
|
||||||
|
|
||||||
while (m_buffer.size() - m_buffer_size < buffer.size())
|
TRY(m_buffer.resize(old_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;
|
||||||
|
@ -108,7 +79,7 @@ namespace Kernel
|
||||||
|
|
||||||
m_thread_blocker.unblock();
|
m_thread_blocker.unblock();
|
||||||
|
|
||||||
return to_copy;
|
return buffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,11 +48,8 @@ namespace Kernel
|
||||||
|
|
||||||
m_open_files[fd] = result.release_value();
|
m_open_files[fd] = result.release_value();
|
||||||
|
|
||||||
if (m_open_files[fd]->path == "<pipe wr>"_sv)
|
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
||||||
{
|
((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 {};
|
||||||
|
@ -62,7 +59,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_NOCTTY | O_DIRECTORY | O_CREAT | O_EXCL | O_NONBLOCK))
|
if (flags & ~(O_ACCMODE | O_NOFOLLOW | O_APPEND | O_TRUNC | O_CLOEXEC | O_TTY_INIT | 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)
|
||||||
|
@ -142,8 +139,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, "<pipe rd>"_sv, 0, O_RDONLY));
|
m_open_files[fds[0]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, ""_sv, 0, O_RDONLY));
|
||||||
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, "<pipe wr>"_sv, 0, O_WRONLY));
|
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, ""_sv, 0, O_WRONLY));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -155,11 +152,8 @@ 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]->path == "<pipe wr>"_sv)
|
if (m_open_files[result]->flags & O_WRONLY && m_open_files[result]->inode->is_pipe())
|
||||||
{
|
((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;
|
||||||
}
|
}
|
||||||
|
@ -178,11 +172,8 @@ 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[fildes2]->path == "<pipe wr>"_sv)
|
if (m_open_files[fildes]->flags & O_WRONLY && m_open_files[fildes]->inode->is_pipe())
|
||||||
{
|
((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;
|
||||||
}
|
}
|
||||||
|
@ -312,11 +303,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
if (m_open_files[fd]->path == "<pipe wr>"_sv)
|
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
||||||
{
|
((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,7 +13,6 @@
|
||||||
#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>
|
||||||
|
@ -186,6 +185,7 @@ 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,15 +201,21 @@ 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 (s_processes[i] != this)
|
if (m_parent && s_processes[i]->pid() == m_parent)
|
||||||
continue;
|
s_processes[i]->add_pending_signal(SIGCHLD);
|
||||||
|
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();
|
||||||
|
@ -246,35 +252,7 @@ namespace Kernel
|
||||||
|
|
||||||
void Process::exit(int status, int signal)
|
void Process::exit(int status, int signal)
|
||||||
{
|
{
|
||||||
if (m_parent)
|
m_exit_status.exit_code = __WGENEXITCODE(status, signal);
|
||||||
{
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
@ -419,20 +397,6 @@ 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));
|
||||||
|
|
||||||
|
@ -458,10 +422,6 @@ 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));
|
||||||
|
@ -581,72 +541,58 @@ 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))
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
|
|
||||||
// FIXME: support options stopped processes
|
|
||||||
if (options & ~(WCONTINUED | WUNTRACED))
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
|
|
||||||
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);
|
LockGuard _(m_process_lock);
|
||||||
TRY(validate_pointer_access(stat_loc, sizeof(stat_loc)));
|
TRY(validate_pointer_access(stat_loc, sizeof(int)));
|
||||||
*stat_loc = exit_code;
|
|
||||||
}
|
|
||||||
remove_pending_signal(SIGCHLD);
|
|
||||||
return exited_pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Thread::current().is_interrupted_by_signal())
|
// FIXME: support options
|
||||||
return BAN::Error::from_errno(EINTR);
|
if (options)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
if (options & WNOHANG)
|
int stat = TRY(block_until_exit(pid));
|
||||||
return 0;
|
if (stat_loc)
|
||||||
|
*stat_loc = stat;
|
||||||
|
|
||||||
m_child_exit_blocker.block_indefinite();
|
return pid;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
BAN::ErrorOr<long> Process::sys_sleep(int seconds)
|
||||||
|
@ -914,8 +860,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_NOCTTY) && file.inode->is_tty() && is_session_leader() && !m_controlling_terminal)
|
if ((flags & O_TTY_INIT) && !(flags & O_NOCTTY) && file.inode->is_tty() && is_session_leader() && !m_controlling_terminal)
|
||||||
m_controlling_terminal = static_cast<TTY*>(file.inode.ptr());
|
m_controlling_terminal = (TTY*)file.inode.ptr();
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -1343,7 +1289,7 @@ namespace Kernel
|
||||||
break;
|
break;
|
||||||
|
|
||||||
LockFreeGuard free(m_process_lock);
|
LockFreeGuard free(m_process_lock);
|
||||||
TRY(Thread::current().sleep_or_eintr_ms(1));
|
SystemTimer::get().sleep_ms(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments->readfds)
|
if (arguments->readfds)
|
||||||
|
@ -1735,50 +1681,6 @@ 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);
|
||||||
|
@ -1981,11 +1883,10 @@ namespace Kernel
|
||||||
if (!inode->is_tty())
|
if (!inode->is_tty())
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
|
||||||
auto* tty = static_cast<TTY*>(inode.ptr());
|
if ((TTY*)inode.ptr() != m_controlling_terminal.ptr())
|
||||||
if (tty != m_controlling_terminal.ptr())
|
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
|
||||||
tty->set_foreground_pgrp(pgrp);
|
((TTY*)inode.ptr())->set_foreground_pgrp(pgrp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2047,20 +1948,6 @@ 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)
|
||||||
|
@ -2338,7 +2225,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)
|
||||||
if (mapped_region->contains_fully(vaddr, size))
|
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,8 +361,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,142 +0,0 @@
|
||||||
#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,4 +1,5 @@
|
||||||
#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>
|
||||||
|
@ -6,6 +7,7 @@
|
||||||
#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
|
||||||
|
|
||||||
|
@ -31,8 +33,6 @@
|
||||||
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,6 +40,12 @@ 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;
|
||||||
|
@ -173,8 +179,9 @@ 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{}", s_next_tty_number++)))
|
, m_name(MUST(BAN::String::formatted("ttyS{}", minor(rdev()))))
|
||||||
, 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,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/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/Lock/LockGuard.h>
|
#include <kernel/Lock/LockGuard.h>
|
||||||
|
@ -21,25 +20,6 @@ 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,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/Lock/LockGuard.h>
|
#include <kernel/Lock/LockGuard.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
|
@ -9,6 +10,7 @@
|
||||||
|
|
||||||
#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
|
||||||
|
@ -23,7 +25,11 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
static BAN::Atomic<uint32_t> s_next_tty_number = 0;
|
static dev_t next_rdev()
|
||||||
|
{
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
@ -37,8 +43,9 @@ 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{}", s_next_tty_number++)))
|
, m_name(MUST(BAN::String::formatted("tty{}", minor(rdev()))))
|
||||||
, 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,16 +423,6 @@ 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,10 +4,6 @@ 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="$(realpath $(dirname $(realpath $0))/..)"
|
BANAN_ROOT_DIR="$(dirname $(realpath $0))/.."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source "$BANAN_ROOT_DIR/script/config.sh"
|
source "$BANAN_ROOT_DIR/script/config.sh"
|
||||||
|
@ -18,10 +18,6 @@ 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
|
||||||
|
@ -33,13 +29,11 @@ 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 {} +
|
||||||
}
|
}
|
||||||
|
|
||||||
configure() {
|
|
||||||
configure_options=("--host=$BANAN_ARCH-banan_os" '--prefix=/usr')
|
|
||||||
configure_options+=("${CONFIGURE_OPTIONS[@]}")
|
|
||||||
./configure "${configure_options[@]}" || exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
configure_options=("--host=$BANAN_ARCH-banan_os" '--prefix=/usr')
|
||||||
|
configure_options+=(${CONFIGURE_OPTIONS[*]})
|
||||||
|
|
||||||
|
./configure ${configure_options[*]} || exit 1
|
||||||
make -j$(nproc) || exit 1
|
make -j$(nproc) || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +143,6 @@ 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,10 +4,7 @@ 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=(
|
||||||
"--with-pkg-config='$PKG_CONFIG'"
|
'--disable-db-intall'
|
||||||
"--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,16 +1,9 @@
|
||||||
#!/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 $BANAN_PORT_DIR -name '.compile_hash')
|
done < <(find . -name '.compile_hash')
|
||||||
|
|
|
@ -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="$(realpath $BANAN_SCRIPT_DIR/..)"
|
export BANAN_ROOT_DIR=$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,12 +13,10 @@ 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=$BANAN_ARCH-banan_os
|
export BANAN_TOOLCHAIN_TRIPLE_PREFIX=$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 ]]; then
|
if [[ -z $BANAN_TOOLCHAIN_TRIPLE_PREFIX ]]; then
|
||||||
echo "You must set the BANAN_TOOLCHAIN_TRIPLE environment variable" >&2
|
echo "You must set the BANAN_TOOLCHAIN_TRIPLE_PREFIX 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" \
|
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
|
||||||
--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" \
|
--target="$BANAN_TOOLCHAIN_TRIPLE_PREFIX" \
|
||||||
--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-ld ]]; then
|
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE_PREFIX-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-ld ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BUILD_GCC=1
|
BUILD_GCC=1
|
||||||
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE-gcc ]]; then
|
if [[ -f $BANAN_TOOLCHAIN_PREFIX/bin/$BANAN_TOOLCHAIN_TRIPLE_PREFIX-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,9 +3,7 @@ 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
|
||||||
|
@ -15,14 +13,13 @@ 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
|
||||||
|
@ -33,12 +30,8 @@ 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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,23 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,23 +0,0 @@
|
||||||
#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();
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#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,3 +39,26 @@ 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,14 +7,11 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
typedef long jmp_buf[2];
|
typedef int jmp_buf[1];
|
||||||
typedef long sigjmp_buf[2 + 1 + (sizeof(long long) / sizeof(long))];
|
typedef int sigjmp_buf[1];
|
||||||
|
|
||||||
#define _longjmp longjmp
|
|
||||||
void longjmp(jmp_buf env, int val);
|
void longjmp(jmp_buf env, int val);
|
||||||
void siglongjmp(sigjmp_buf env, int val);
|
void siglongjmp(sigjmp_buf env, int val);
|
||||||
|
|
||||||
#define _setjmp setjmp
|
|
||||||
int setjmp(jmp_buf env);
|
int setjmp(jmp_buf env);
|
||||||
int sigsetjmp(sigjmp_buf env, int savemask);
|
int sigsetjmp(sigjmp_buf env, int savemask);
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,7 @@ struct sigevent
|
||||||
#define SIGVTALRM 26
|
#define SIGVTALRM 26
|
||||||
#define SIGXCPU 27
|
#define SIGXCPU 27
|
||||||
#define SIGXFSZ 28
|
#define SIGXFSZ 28
|
||||||
#define SIGWINCH 29
|
#define SIGRTMIN 29
|
||||||
#define SIGRTMIN 30
|
|
||||||
#define SIGRTMAX (SIGRTMIN+32)
|
#define SIGRTMAX (SIGRTMIN+32)
|
||||||
|
|
||||||
#define _SIGMIN SIGABRT
|
#define _SIGMIN SIGABRT
|
||||||
|
|
|
@ -73,7 +73,6 @@ 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,8 +7,6 @@
|
||||||
|
|
||||||
__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>
|
||||||
|
@ -73,6 +71,45 @@ 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
|
||||||
|
@ -115,6 +152,7 @@ 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);
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
#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 __fds_bits[FD_SETSIZE / __FD_MASK_SIZE];
|
__fd_mask __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)->__fds_bits[off] &= ~((__fd_mask)1 << bit); \
|
(setp)->__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)->__fds_bits[off] & ((__fd_mask)1 << bit); \
|
(setp)->__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)->__fds_bits[off] |= ((__fd_mask)1 << bit); \
|
(setp)->__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)->__fds_bits[i] = (__fd_mask)0; \
|
(setp)->__bits[i] = (__fd_mask)0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
struct sys_pselect_t
|
struct sys_pselect_t
|
||||||
|
|
|
@ -25,7 +25,6 @@ __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) \
|
||||||
|
@ -88,8 +87,6 @@ __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,30 +106,7 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
// FIXME: _CS prefixed definitions
|
// FIXME: _CS prefixed definitions
|
||||||
|
|
||||||
enum
|
// FIXME: _PC prefixed definitions
|
||||||
{
|
|
||||||
_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,6 +1,5 @@
|
||||||
#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>
|
||||||
|
@ -36,38 +35,6 @@ 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];
|
||||||
|
@ -127,6 +94,7 @@ 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,12 +8,7 @@
|
||||||
#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
|
||||||
|
|
||||||
|
@ -43,7 +38,6 @@ 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,4 +1,3 @@
|
||||||
#include <BAN/Assert.h>
|
|
||||||
#include <BAN/Bitcast.h>
|
#include <BAN/Bitcast.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -12,35 +11,6 @@
|
||||||
|
|
||||||
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];
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
#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,12 +733,14 @@ 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", rand());
|
sprintf(storage, "/tmp/tmp_%04x", s_counter);
|
||||||
|
s_counter = rand();
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(storage, &st) == -1 && errno == ENOENT)
|
if (stat(storage, &st) == -1 && errno == ENOENT)
|
||||||
|
@ -840,8 +842,3 @@ int vsscanf(const char* s, const char* format, va_list arguments)
|
||||||
}, &s
|
}, &s
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* tmpfile(void)
|
|
||||||
{
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
|
@ -514,36 +514,6 @@ 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 <sys/ioctl.h>
|
#include <stropts.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include <BAN/Assert.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -13,11 +11,6 @@ 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);
|
||||||
return 0;
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcgetattr(int fildes, struct termios* termios)
|
int tcgetattr(int fildes, struct termios* termios)
|
||||||
|
|
|
@ -475,11 +475,6 @@ 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);
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
#include <BAN/Assert.h>
|
|
||||||
|
|
||||||
#include <utime.h>
|
|
||||||
|
|
||||||
int utime(const char*, const struct utimbuf*)
|
|
||||||
{
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
#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)
|
if (waitpid(pid, &status, 0) == -1 && errno != ECHILD)
|
||||||
ERROR_RETURN("waitpid", {});
|
ERROR_RETURN("waitpid", {});
|
||||||
|
|
||||||
while (!output.empty() && output.back() == '\n')
|
while (!output.empty() && output.back() == '\n')
|
||||||
|
|
|
@ -4,63 +4,59 @@
|
||||||
#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 pts_master = posix_openpt(O_RDWR | O_NOCTTY);
|
int shell_stdin[2];
|
||||||
if (pts_master == -1)
|
if (pipe(shell_stdin) == -1)
|
||||||
{
|
{
|
||||||
dwarnln("posix_openpt: {}", strerror(errno));
|
dwarnln("pipe: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grantpt(pts_master) == -1)
|
int shell_stdout[2];
|
||||||
|
if (pipe(shell_stdout) == -1)
|
||||||
{
|
{
|
||||||
dwarnln("grantpt: {}", strerror(errno));
|
dwarnln("pipe: {}", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlockpt(pts_master) == -1)
|
int shell_stderr[2];
|
||||||
|
if (pipe(shell_stderr) == -1)
|
||||||
{
|
{
|
||||||
dwarnln("unlockpt: {}", strerror(errno));
|
dwarnln("pipe: {}", 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 (setsid() == -1)
|
if (dup2(shell_stdin[0], STDIN_FILENO) == -1)
|
||||||
{
|
|
||||||
dwarnln("setsid: {}", strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* pts_slave_name = ptsname(pts_master);
|
|
||||||
if (pts_slave_name == nullptr)
|
|
||||||
{
|
|
||||||
dwarnln("ptsname: {}", strerror(errno));
|
|
||||||
exit(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_stdin[0]);
|
||||||
|
close(shell_stdin[1]);
|
||||||
|
|
||||||
close(pts_slave);
|
if (dup2(shell_stdout[1], STDOUT_FILENO) == -1)
|
||||||
close(pts_master);
|
{
|
||||||
|
dwarnln("dup2: {}", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
close(shell_stdout[0]);
|
||||||
|
close(shell_stdout[1]);
|
||||||
|
|
||||||
|
if (dup2(shell_stderr[1], STDERR_FILENO) == -1)
|
||||||
|
{
|
||||||
|
dwarnln("dup2: {}", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
close(shell_stderr[0]);
|
||||||
|
close(shell_stderr[1]);
|
||||||
|
|
||||||
execl("/bin/Shell", "Shell", NULL);
|
execl("/bin/Shell", "Shell", NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -72,8 +68,14 @@ 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 = {
|
||||||
.pts_master = pts_master,
|
.in = shell_stdin[1],
|
||||||
|
.out = shell_stdout[0],
|
||||||
|
.err = shell_stderr[0],
|
||||||
.pid = shell_pid
|
.pid = shell_pid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -93,18 +95,22 @@ 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(m_shell_info.pts_master, m_window->server_fd());
|
const int max_fd = BAN::Math::max(BAN::Math::max(m_shell_info.out, m_shell_info.err), 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.pts_master, &fds);
|
FD_SET(m_shell_info.out, &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.pts_master, &fds))
|
if (FD_ISSET(m_shell_info.out, &fds))
|
||||||
if (!read_shell())
|
if (!read_shell(m_shell_info.out))
|
||||||
|
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();
|
||||||
|
@ -112,10 +118,10 @@ void Terminal::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Terminal::read_shell()
|
bool Terminal::read_shell(int fd)
|
||||||
{
|
{
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
ssize_t nread = read(m_shell_info.pts_master, buffer, sizeof(buffer) - 1);
|
ssize_t nread = read(fd, buffer, sizeof(buffer) - 1);
|
||||||
if (nread < 0)
|
if (nread < 0)
|
||||||
dwarnln("read: {}", strerror(errno));
|
dwarnln("read: {}", strerror(errno));
|
||||||
if (nread <= 0)
|
if (nread <= 0)
|
||||||
|
@ -289,13 +295,13 @@ void Terminal::handle_csi(char ch)
|
||||||
m_state = State::Normal;
|
m_state = State::Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::putchar(uint8_t ch)
|
void Terminal::putchar(uint32_t codepoint)
|
||||||
{
|
{
|
||||||
if (m_state == State::ESC)
|
if (m_state == State::ESC)
|
||||||
{
|
{
|
||||||
if (ch != '[')
|
if (codepoint != '[')
|
||||||
{
|
{
|
||||||
dprintln("unknown escape character 0x{2H}", ch);
|
dprintln("unknown escape character 0x{H}", codepoint);
|
||||||
m_state = State::Normal;
|
m_state = State::Normal;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -308,46 +314,13 @@ void Terminal::putchar(uint8_t ch)
|
||||||
|
|
||||||
if (m_state == State::CSI)
|
if (m_state == State::CSI)
|
||||||
{
|
{
|
||||||
if (ch < 0x20 || ch > 0xFE)
|
if (codepoint < 0x20 || codepoint > 0xFE)
|
||||||
{
|
{
|
||||||
dprintln("invalid CSI 0x{2H}", ch);
|
dprintln("invalid CSI 0x{H}", codepoint);
|
||||||
m_state = State::Normal;
|
m_state = State::Normal;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handle_csi(ch);
|
handle_csi(codepoint);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,5 +376,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.pts_master, text, strlen(text));
|
write(m_shell_info.in, 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(uint8_t ch);
|
void putchar(uint32_t codepoint);
|
||||||
bool read_shell();
|
bool read_shell(int fd);
|
||||||
|
|
||||||
void on_key_event(LibGUI::EventPacket::KeyEvent);
|
void on_key_event(LibGUI::EventPacket::KeyEvent);
|
||||||
|
|
||||||
|
@ -31,7 +31,9 @@ private:
|
||||||
|
|
||||||
struct ShellInfo
|
struct ShellInfo
|
||||||
{
|
{
|
||||||
int pts_master;
|
int in;
|
||||||
|
int out;
|
||||||
|
int err;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,9 +58,6 @@ 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,7 +5,6 @@ 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
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
set(SOURCES
|
|
||||||
main.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(test-setjmp ${SOURCES})
|
|
||||||
banan_link_library(test-setjmp libc)
|
|
||||||
|
|
||||||
install(TARGETS test-setjmp OPTIONAL)
|
|
|
@ -1,22 +0,0 @@
|
||||||
#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