Compare commits

...

23 Commits

Author SHA1 Message Date
Bananymous 9e79ef2a91 Terminal: Use pseudo terminal instead of pipes
Terminal can now send signals from keyboard (ctrl+c) to programs running
in the terminal!
2024-08-11 01:02:59 +03:00
Bananymous 4d1b32f770 Kernel: open does not need TTY_INIT to set the controlling terminal 2024-08-11 01:02:59 +03:00
Bananymous a5a097fa4a Kernel/LibC: Add initial pseudo terminal support
This patch implements posix_openpt() and ptsname()

grantpt() and unlockpt() are left in LibC as stubs, as posix_openpt
currently does all of the needed work.
2024-08-11 01:02:59 +03:00
Bananymous ad645f31d0 Kernel/LibC: Add setsid() 2024-08-11 00:58:12 +03:00
Bananymous f08d429851 Terminal: Add utf8 parsing for input
This patch adds possibility to render multibyte utf8 codepoints!
2024-08-11 00:54:51 +03:00
Bananymous bac3219a01 Kernel: Fix `Pipe::can_read_impl()`
The logic was inversed, which made all select calls report incorrectly
for pipes. This made terminal emulator just freeze.
2024-08-10 18:18:25 +03:00
Bananymous 09a527fb12 Kernel: Fix scheduler thread counter
I was actually never incrementing the counter :D
2024-08-10 18:18:25 +03:00
Bananymous 58a3a480b9 Ports: Update the port system once again! 2024-08-10 18:18:25 +03:00
Bananymous a12bfe4639 LibC: Don't crash when calling tcflush() 2024-08-09 17:03:21 +03:00
Bananymous 6cda639869 LibC: Add stubs for tmpfile, mktemp and fchmod 2024-08-09 17:02:49 +03:00
Bananymous 2797fe116f LibC: Add stubs for some functions in {dlfcn,ftw,utime,wchar}.h 2024-08-09 17:01:41 +03:00
Bananymous e768cd53fb LibC: Add definition for SIGWINCH
This is actually not yet sent, but programs can install signal handlers
for it!
2024-08-09 17:00:13 +03:00
Bananymous 83e2ad40d6 LibC: Implement gai_strerror and add stubs for {get,free}addrinfo 2024-08-09 16:59:49 +03:00
Bananymous 7ebd0699e3 LibC: Add _PC* definitions to unistd.h
These are not used for anything yet
2024-08-09 16:58:58 +03:00
Bananymous 46b1d4d194 LibC: Remove cxx abi stuff from libc
These will cause multiple definitions when linking with libstdc++
2024-08-09 16:58:11 +03:00
Bananymous f60e265397 LibC: Add ldexp to math.cpp 2024-08-09 16:57:16 +03:00
Bananymous 2e642327ea LibC: Implement localeconv() 2024-08-09 16:56:48 +03:00
Bananymous a87ce41030 LibC: rename fd_set internal variable
binutils seems to need access to the internal type and uses this name
for lookup.
2024-08-09 16:55:52 +03:00
Bananymous 0c8cae4cc3 LibC: Move ioctl to <sys/ioctl.h>
Some ports seem to be assuming that ioctl exists there and not in
stropts.h
2024-08-09 16:54:30 +03:00
Bananymous ed325b4a45 Kernel: Fix typo in userspace address validation 2024-08-09 16:52:57 +03:00
Bananymous 1c67b5e812 Kernel: Fix wait syscall to report status of exited children 2024-08-09 16:52:35 +03:00
Bananymous b6c964c444 Kernel: Rewrite pipes
Pipes have now a fixed size buffer and pipe clone and close is working
again.
2024-08-09 16:50:19 +03:00
Bananymous 6fedf06150 LibC: Implement {sig,_,}{longjmp,setjmp} 2024-08-09 15:58:56 +03:00
57 changed files with 1032 additions and 293 deletions

View File

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

View File

@ -9,7 +9,7 @@ namespace Kernel
{ {
Framebuffer = 1, Framebuffer = 1,
TTY, TTY,
Serial, PTSMaster,
Null, Null,
Zero, Zero,
Debug, Debug,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();

View File

@ -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)

View File

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

View File

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

View File

@ -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)

View File

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

View File

@ -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();

View File

@ -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())

View File

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

View File

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

View File

@ -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'

View File

@ -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')

View File

@ -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'

View File

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

View File

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

View File

@ -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
) )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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]);

View File

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

View File

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

View File

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

View File

@ -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
{ {

View File

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

View File

@ -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)

View File

@ -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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)

View File

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

View File

@ -0,0 +1,8 @@
#include <BAN/Assert.h>
#include <utime.h>
int utime(const char*, const struct utimbuf*)
{
ASSERT_NOT_REACHED();
}

View File

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

View File

@ -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')

View File

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

View File

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

View File

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

View File

@ -0,0 +1,8 @@
set(SOURCES
main.cpp
)
add_executable(test-setjmp ${SOURCES})
banan_link_library(test-setjmp libc)
install(TARGETS test-setjmp OPTIONAL)

View File

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