From 621217ffeb9bddec866ad8895bd01973977f2848 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 2 Nov 2018 13:14:25 +0100 Subject: [PATCH] Add tcsetpgrp()+tcgetpgrp(). One more step on the path to being able to ^C a runaway process. :^) --- Kernel/ProcFileSystem.cpp | 5 +++-- Kernel/Process.cpp | 31 +++++++++++++++++++++++++++++++ Kernel/Process.h | 2 ++ Kernel/Syscall.cpp | 4 ++++ Kernel/Syscall.h | 2 ++ Kernel/TTY.h | 4 ++++ LibC/unistd.cpp | 9 +++++++-- LibC/unistd.h | 2 ++ Userland/sh.cpp | 9 +++++++++ VirtualFileSystem/FileHandle.cpp | 7 +++++++ VirtualFileSystem/FileHandle.h | 1 + 11 files changed, 72 insertions(+), 4 deletions(-) diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index e899f4f314..f7c221f1cb 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -277,10 +277,11 @@ ByteBuffer procfs$summary() auto processes = Process::allProcesses(); auto buffer = ByteBuffer::createUninitialized(processes.size() * 256); char* ptr = (char*)buffer.pointer(); - ptr += ksprintf(ptr, "PID PGP SID OWNER STATE PPID NSCHED FDS TTY NAME\n"); + ptr += ksprintf(ptr, "PID TPG PGP SID OWNER STATE PPID NSCHED FDS TTY NAME\n"); for (auto* process : processes) { - ptr += ksprintf(ptr, "% 3u % 3u % 3u % 4u % 8s % 3u % 9u % 3u % 4s %s\n", + ptr += ksprintf(ptr, "% 3u % 3u % 3u % 3u % 4u % 8s % 3u % 9u % 3u % 4s %s\n", process->pid(), + process->tty() ? process->tty()->pgid() : 0, process->pgid(), process->sid(), process->uid(), diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 14deb2812a..24d0bdc16c 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1249,3 +1249,34 @@ int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) process->m_pgid = new_pgid; return 0; } + +pid_t Process::sys$tcgetpgrp(int fd) +{ + auto* handle = fileHandleIfExists(fd); + if (!handle) + return -EBADF; + if (!handle->isTTY()) + return -ENOTTY; + auto& tty = *handle->tty(); + if (&tty != m_tty) + return -ENOTTY; + return tty.pgid(); +} + +int Process::sys$tcsetpgrp(int fd, pid_t pgid) +{ + if (pgid < 0) + return -EINVAL; + if (get_sid_from_pgid(pgid) != m_sid) + return -EINVAL; + auto* handle = fileHandleIfExists(fd); + if (!handle) + return -EBADF; + if (!handle->isTTY()) + return -ENOTTY; + auto& tty = *handle->tty(); + if (&tty != m_tty) + return -ENOTTY; + tty.set_pgid(pgid); + return 0; +} diff --git a/Kernel/Process.h b/Kernel/Process.h index 12302ecbb1..dbec761466 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -86,6 +86,8 @@ public: int sys$setpgid(pid_t pid, pid_t pgid); pid_t sys$getpgrp(); pid_t sys$getpgid(pid_t); + pid_t sys$tcgetpgrp(int fd); + int sys$tcsetpgrp(int fd, pid_t pgid); uid_t sys$getuid(); gid_t sys$getgid(); pid_t sys$getpid(); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index e8163a4465..0ffbe7659e 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -124,6 +124,10 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) return current->sys$getpgid((pid_t)arg1); case Syscall::PosixGetpgrp: return current->sys$getpgrp(); + case Syscall::PosixTcgetpgrp: + return current->sys$tcgetpgrp((int)arg1); + case Syscall::PosixTcsetpgrp: + return current->sys$tcsetpgrp((int)arg1, (pid_t)arg2); default: kprintf("<%u> int0x80: Unknown function %x requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index f35658bf2a..97116c16f9 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -45,6 +45,8 @@ enum Function { PosixGetpgid = 0x2013, PosixSetpgid = 0x2014, PosixGetpgrp = 0x2015, + PosixTcsetpgrp = 0x2016, + PosixTcgetpgrp = 0x2017, }; void initialize(); diff --git a/Kernel/TTY.h b/Kernel/TTY.h index 76a144e6f9..e352efa1eb 100644 --- a/Kernel/TTY.h +++ b/Kernel/TTY.h @@ -12,6 +12,9 @@ public: virtual String ttyName() const = 0; + void set_pgid(pid_t pgid) { m_pgid = pgid; } + pid_t pgid() const { return m_pgid; } + protected: virtual bool isTTY() const final { return true; } @@ -22,5 +25,6 @@ protected: private: Vector m_buffer; + pid_t m_pgid { 0 }; }; diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 7f6e266f37..3492430198 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -25,9 +25,14 @@ pid_t setsid() return Syscall::invoke(Syscall::PosixSetsid); } -pid_t sys$getsid(pid_t pid) +pid_t tcgetpgrp(int fd) { - return Syscall::invoke(Syscall::PosixSetsid, (dword)pid); + return Syscall::invoke(Syscall::PosixTcgetpgrp, (dword)fd); +} + +int tcsetpgrp(int fd, pid_t pgid) +{ + return Syscall::invoke(Syscall::PosixTcsetpgrp, (dword)fd, (dword)pgid); } int setpgid(pid_t pid, pid_t pgid) diff --git a/LibC/unistd.h b/LibC/unistd.h index 9c73b778ef..cbc630628a 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -16,6 +16,8 @@ pid_t getpgrp(); uid_t getuid(); gid_t getgid(); pid_t getpid(); +pid_t tcgetpgrp(int fd); +int tcsetpgrp(int fd, pid_t pgid); int open(const char* path, int options); ssize_t read(int fd, void* buf, size_t count); ssize_t write(int fd, const void* buf, size_t count); diff --git a/Userland/sh.cpp b/Userland/sh.cpp index 7ad8361153..c5669449c5 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -142,10 +142,17 @@ static int runcmd(char* cmd) return 1; } + // FIXME: This is racy, since spawn has already started the new process. + // Once I have fork()+exec(), pgrp setup can be done in the child before exec()ing. + tcsetpgrp(0, ret); + // FIXME: waitpid should give us the spawned process's exit status int wstatus = 0; waitpid(ret, &wstatus, 0); + // FIXME: Racy as mentioned above. Rework once we have fork()+exec(). + tcsetpgrp(0, getpid()); + if (WIFEXITED(wstatus)) { //printf("Exited normally with status %d\n", WEXITSTATUS(wstatus)); } else { @@ -173,6 +180,8 @@ int main(int, char**) { g = new GlobalState; g->sid = setsid(); + tcsetpgrp(0, getpgrp()); + int rc = gethostname(g->hostname, sizeof(g->hostname)); if (rc < 0) perror("gethostname"); diff --git a/VirtualFileSystem/FileHandle.cpp b/VirtualFileSystem/FileHandle.cpp index 6f9354a143..49199f6b22 100644 --- a/VirtualFileSystem/FileHandle.cpp +++ b/VirtualFileSystem/FileHandle.cpp @@ -176,6 +176,13 @@ const TTY* FileHandle::tty() const return nullptr; } +TTY* FileHandle::tty() +{ + if (auto* device = m_vnode->characterDevice()) + return static_cast(device); + return nullptr; +} + int FileHandle::close() { return 0; diff --git a/VirtualFileSystem/FileHandle.h b/VirtualFileSystem/FileHandle.h index d5e0d1bf2d..bf6a842891 100644 --- a/VirtualFileSystem/FileHandle.h +++ b/VirtualFileSystem/FileHandle.h @@ -30,6 +30,7 @@ public: bool isTTY() const; const TTY* tty() const; + TTY* tty(); InodeMetadata metadata() const { return m_vnode->metadata(); }