Kernel/LibC: Replace terminal syscalls with ioctls
isatty, tc{get,set}attr, tc{get,set}pgrp are now implemented as ioctls
instead of separate syscalls
This commit is contained in:
@@ -56,6 +56,7 @@ namespace Kernel
|
||||
pid_t pid() const { return m_pid; }
|
||||
|
||||
bool is_session_leader() const { return pid() == sid(); }
|
||||
bool is_pgrpg_in_this_session(pid_t) const;
|
||||
|
||||
const char* name() const { return m_cmdline.empty() ? "<unknown>" : m_cmdline.front().data(); }
|
||||
|
||||
@@ -63,9 +64,6 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<long> sys_exit(int status);
|
||||
|
||||
BAN::ErrorOr<long> sys_tcgetattr(int fildes, termios*);
|
||||
BAN::ErrorOr<long> sys_tcsetattr(int fildes, int optional_actions, const termios*);
|
||||
|
||||
BAN::ErrorOr<long> sys_fork(uintptr_t rsp, uintptr_t rip);
|
||||
BAN::ErrorOr<long> sys_exec(const char* path, const char* const* argv, const char* const* envp);
|
||||
|
||||
@@ -186,7 +184,6 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
|
||||
|
||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* name, size_t namesize);
|
||||
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);
|
||||
|
||||
@@ -218,9 +215,6 @@ namespace Kernel
|
||||
BAN::ErrorOr<long> sys_pthread_self();
|
||||
BAN::ErrorOr<long> sys_pthread_kill(pthread_t thread, int signal);
|
||||
|
||||
BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
|
||||
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);
|
||||
|
||||
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
||||
|
||||
BAN::ErrorOr<long> sys_load_keymap(const char* path);
|
||||
|
||||
@@ -33,9 +33,6 @@ namespace Kernel
|
||||
public:
|
||||
virtual BAN::ErrorOr<void> set_font(LibFont::Font&&) { return BAN::Error::from_errno(EINVAL); }
|
||||
|
||||
void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; }
|
||||
pid_t foreground_pgrp() const { return m_foreground_pgrp; }
|
||||
|
||||
BAN::ErrorOr<void> tty_ctrl(int command, int flags);
|
||||
|
||||
// for kprint
|
||||
@@ -52,9 +49,6 @@ namespace Kernel
|
||||
void on_key_event(LibInput::KeyEvent);
|
||||
void handle_input_byte(uint8_t);
|
||||
|
||||
void get_termios(termios*);
|
||||
BAN::ErrorOr<void> set_termios(const termios*);
|
||||
|
||||
virtual bool is_tty() const override { return true; }
|
||||
|
||||
virtual dev_t rdev() const final override { return m_rdev; }
|
||||
@@ -87,10 +81,12 @@ namespace Kernel
|
||||
bool putchar(uint8_t ch);
|
||||
void do_backspace();
|
||||
|
||||
termios get_termios();
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
pid_t m_foreground_pgrp { 0 };
|
||||
BAN::Atomic<pid_t> m_foreground_pgrp { 0 };
|
||||
|
||||
struct tty_ctrl_t
|
||||
{
|
||||
|
||||
@@ -226,6 +226,23 @@ namespace Kernel
|
||||
ASSERT(!m_page_table);
|
||||
}
|
||||
|
||||
bool Process::is_pgrpg_in_this_session(pid_t pgrp) const
|
||||
{
|
||||
bool valid_pgrp = false;
|
||||
for_each_process(
|
||||
[&](Process& process)
|
||||
{
|
||||
if (process.sid() == sid() && process.pgrp() == pgrp)
|
||||
{
|
||||
valid_pgrp = true;
|
||||
return BAN::Iteration::Break;
|
||||
}
|
||||
return BAN::Iteration::Continue;
|
||||
}
|
||||
);
|
||||
return valid_pgrp;
|
||||
}
|
||||
|
||||
void Process::add_thread(Thread* thread)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
@@ -624,40 +641,6 @@ namespace Kernel
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_tcgetattr(int fildes, termios* user_termios)
|
||||
{
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||
if (!inode->is_tty())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
struct termios termios;
|
||||
static_cast<TTY*>(inode.ptr())->get_termios(&termios);
|
||||
|
||||
TRY(write_to_user(user_termios, &termios, sizeof(struct termios)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_tcsetattr(int fildes, int optional_actions, const termios* user_termios)
|
||||
{
|
||||
//if (optional_actions != TCSANOW)
|
||||
// return BAN::Error::from_errno(EINVAL);
|
||||
(void)optional_actions;
|
||||
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||
if (!inode->is_tty())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
termios termios;
|
||||
TRY(read_from_user(user_termios, &termios, sizeof(struct termios)));
|
||||
|
||||
TRY(static_cast<TTY*>(inode.ptr())->set_termios(&termios));
|
||||
|
||||
// FIXME: SIGTTOU
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_fork(uintptr_t sp, uintptr_t ip)
|
||||
{
|
||||
auto page_table = BAN::UniqPtr<PageTable>::adopt(TRY(PageTable::create_userspace()));
|
||||
@@ -2764,15 +2747,6 @@ namespace Kernel
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_isatty(int fildes)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||
if (!inode->is_tty())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_posix_openpt(int flags)
|
||||
{
|
||||
if (flags & ~(O_RDWR | O_NOCTTY))
|
||||
@@ -3449,64 +3423,6 @@ namespace Kernel
|
||||
return BAN::Error::from_errno(ESRCH);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_tcgetpgrp(int fd)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||
|
||||
// NOTE: This is a hack but I'm not sure how terminal is supposted to get
|
||||
// slave's foreground pgroup while not having controlling terminal
|
||||
if (TRY(m_open_file_descriptors.path_of(fd)) == "<ptmx>"_sv)
|
||||
return TRY(static_cast<PseudoTerminalMaster*>(inode.ptr())->slave())->foreground_pgrp();
|
||||
|
||||
if (!m_controlling_terminal)
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
if (!inode->is_tty())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
auto* tty = static_cast<TTY*>(inode.ptr());
|
||||
if (tty != m_controlling_terminal.ptr())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
return tty->foreground_pgrp();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_tcsetpgrp(int fd, pid_t pgrp)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
if (!m_controlling_terminal)
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
bool valid_pgrp = false;
|
||||
for_each_process(
|
||||
[&](Process& process)
|
||||
{
|
||||
if (process.sid() == sid() && process.pgrp() == pgrp)
|
||||
{
|
||||
valid_pgrp = true;
|
||||
return BAN::Iteration::Break;
|
||||
}
|
||||
return BAN::Iteration::Continue;
|
||||
}
|
||||
);
|
||||
if (!valid_pgrp)
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||
if (!inode->is_tty())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
auto* tty = static_cast<TTY*>(inode.ptr());
|
||||
if (tty != m_controlling_terminal.ptr())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
tty->set_foreground_pgrp(pgrp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_setuid(uid_t uid)
|
||||
{
|
||||
if (uid < 0 || uid >= 1'000'000'000)
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Kernel
|
||||
return BAN::Error::from_errno(ENODEV);
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
return CharacterDevice::ioctl(request, argument);
|
||||
}
|
||||
|
||||
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)
|
||||
|
||||
@@ -210,8 +210,47 @@ namespace Kernel
|
||||
(void)Process::kill(-m_foreground_pgrp, SIGWINCH);
|
||||
return 0;
|
||||
}
|
||||
case TCGETS:
|
||||
{
|
||||
SpinLockGuard _(m_termios_lock);
|
||||
auto* termios = static_cast<struct termios*>(argument);
|
||||
*termios = m_termios;
|
||||
return 0;
|
||||
}
|
||||
case TCSETSW:
|
||||
case TCSETSF:
|
||||
dwarnln("TODO: proper TCSETSW/TCSETSWF");
|
||||
[[fallthrough]];
|
||||
case TCSETS:
|
||||
{
|
||||
// FIXME: do some validation
|
||||
SpinLockGuard _(m_termios_lock);
|
||||
const auto* termios = static_cast<const struct termios*>(argument);
|
||||
m_termios = *termios;
|
||||
return 0;
|
||||
}
|
||||
case TIOCGPGRP:
|
||||
{
|
||||
pid_t* pgrp = static_cast<pid_t*>(argument);
|
||||
*pgrp = m_foreground_pgrp.load();
|
||||
return 0;
|
||||
}
|
||||
case TIOCSPGRP:
|
||||
{
|
||||
const pid_t pgrp = *static_cast<const pid_t*>(argument);
|
||||
|
||||
if (!Process::current().is_pgrpg_in_this_session(pgrp))
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
|
||||
if (this != Process::current().controlling_terminal().ptr())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
|
||||
m_foreground_pgrp = pgrp;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
return CharacterDevice::ioctl(request, argument);
|
||||
}
|
||||
|
||||
void TTY::on_key_event(LibInput::RawKeyEvent event)
|
||||
@@ -234,19 +273,10 @@ namespace Kernel
|
||||
after_write();
|
||||
}
|
||||
|
||||
void TTY::get_termios(termios* termios)
|
||||
termios TTY::get_termios()
|
||||
{
|
||||
SpinLockGuard _(m_termios_lock);
|
||||
*termios = m_termios;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TTY::set_termios(const termios* termios)
|
||||
{
|
||||
// FIXME: do some validation
|
||||
|
||||
SpinLockGuard _(m_termios_lock);
|
||||
m_termios = *termios;
|
||||
return {};
|
||||
return m_termios;
|
||||
}
|
||||
|
||||
void TTY::handle_input_byte(uint8_t ch)
|
||||
@@ -256,9 +286,7 @@ namespace Kernel
|
||||
|
||||
LockGuard _0(m_mutex);
|
||||
|
||||
termios termios;
|
||||
get_termios(&termios);
|
||||
|
||||
const auto termios = get_termios();
|
||||
|
||||
if ((termios.c_iflag & ISTRIP))
|
||||
ch &= 0x7F;
|
||||
@@ -394,8 +422,7 @@ namespace Kernel
|
||||
if (!m_tty_ctrl.draw_graphics)
|
||||
return true;
|
||||
|
||||
termios termios;
|
||||
get_termios(&termios);
|
||||
const auto termios = get_termios();
|
||||
|
||||
SpinLockGuard _1(m_write_lock);
|
||||
if (termios.c_oflag & OPOST)
|
||||
|
||||
Reference in New Issue
Block a user