From c99f8af66da3464447e3f310cddb21f63d59292a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 16 Nov 2018 13:11:21 +0100 Subject: [PATCH] Add ioctl() and reimplement tcsetpgrp/tcsetpgrp as ioctls. --- Kernel/Process.cpp | 27 +++------------------------ Kernel/Process.h | 3 +-- Kernel/Syscall.cpp | 6 ++---- Kernel/Syscall.h | 11 +++++------ Kernel/TTY.cpp | 21 +++++++++++++++++++++ Kernel/TTY.h | 3 +++ LibC/Makefile | 1 + LibC/ioctl.cpp | 19 +++++++++++++++++++ LibC/stdarg.h | 8 ++++---- LibC/sys/ioctl.h | 10 ++++++++++ LibC/sys/ioctl_numbers.h | 7 +++++++ LibC/termcap.cpp | 1 + LibC/unistd.cpp | 7 +++---- VirtualFileSystem/CharacterDevice.cpp | 6 ++++++ VirtualFileSystem/CharacterDevice.h | 6 +++++- VirtualFileSystem/FileDescriptor.h | 3 +++ 16 files changed, 94 insertions(+), 45 deletions(-) create mode 100644 LibC/ioctl.cpp create mode 100644 LibC/sys/ioctl_numbers.h diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 3df32e6abb1..5915872b303 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1586,35 +1586,14 @@ int Process::sys$tcsetattr(int fd, int optional_actions, const Unix::termios* tp return 0; } -pid_t Process::sys$tcgetpgrp(int fd) +int Process::sys$ioctl(int fd, unsigned request, unsigned arg) { auto* descriptor = file_descriptor(fd); if (!descriptor) return -EBADF; - if (!descriptor->isTTY()) + if (!descriptor->is_character_device()) return -ENOTTY; - auto& tty = *descriptor->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* descriptor = file_descriptor(fd); - if (!descriptor) - return -EBADF; - if (!descriptor->isTTY()) - return -ENOTTY; - auto& tty = *descriptor->tty(); - if (&tty != m_tty) - return -ENOTTY; - tty.set_pgid(pgid); - return 0; + return descriptor->character_device()->ioctl(*this, request, arg); } int Process::sys$getdtablesize() diff --git a/Kernel/Process.h b/Kernel/Process.h index a354d00285d..f15afd1ae99 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -118,8 +118,6 @@ 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(); uid_t sys$geteuid(); @@ -175,6 +173,7 @@ public: int sys$fcntl(int fd, int cmd, dword extra_arg); int sys$tcgetattr(int fd, Unix::termios*); int sys$tcsetattr(int fd, int optional_actions, const Unix::termios*); + int sys$ioctl(int fd, unsigned request, unsigned arg); static void initialize(); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 557725fc15d..95f41e0c824 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -125,10 +125,6 @@ static DWORD handle(RegisterDump& regs, DWORD function, DWORD arg1, DWORD arg2, return current->sys$getpgid((pid_t)arg1); case Syscall::SC_getpgrp: return current->sys$getpgrp(); - case Syscall::SC_tcgetpgrp: - return current->sys$tcgetpgrp((int)arg1); - case Syscall::SC_tcsetpgrp: - return current->sys$tcsetpgrp((int)arg1, (pid_t)arg2); case Syscall::SC_fork: return current->sys$fork(regs); case Syscall::SC_execve: @@ -179,6 +175,8 @@ static DWORD handle(RegisterDump& regs, DWORD function, DWORD arg1, DWORD arg2, return current->sys$tcgetattr((int)arg1, (Unix::termios*)arg2); case Syscall::SC_tcsetattr: return current->sys$tcsetattr((int)arg1, (int)arg2, (const Unix::termios*)arg3); + case Syscall::SC_ioctl: + return current->sys$ioctl((int)arg1, (unsigned)arg2, (unsigned)arg3); 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 a9346ff2112..65ce348950e 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -37,8 +37,6 @@ __ENUMERATE_SYSCALL(getpgid) \ __ENUMERATE_SYSCALL(setpgid) \ __ENUMERATE_SYSCALL(getpgrp) \ - __ENUMERATE_SYSCALL(tcsetpgrp) \ - __ENUMERATE_SYSCALL(tcgetpgrp) \ __ENUMERATE_SYSCALL(fork) \ __ENUMERATE_SYSCALL(execve) \ __ENUMERATE_SYSCALL(geteuid) \ @@ -66,6 +64,7 @@ __ENUMERATE_SYSCALL(fcntl) \ __ENUMERATE_SYSCALL(tcsetattr) \ __ENUMERATE_SYSCALL(tcgetattr) \ + __ENUMERATE_SYSCALL(ioctl) \ #define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function)) @@ -104,28 +103,28 @@ struct SC_mmap_params { void initialize(); -inline dword invoke(dword function) +inline dword invoke(Function function) { dword result; asm volatile("int $0x80":"=a"(result):"a"(function):"memory"); return result; } -inline dword invoke(dword function, dword arg1) +inline dword invoke(Function function, dword arg1) { dword result; asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1):"memory"); return result; } -inline dword invoke(dword function, dword arg1, dword arg2) +inline dword invoke(Function function, dword arg1, dword arg2) { dword result; asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2):"memory"); return result; } -inline dword invoke(dword function, dword arg1, dword arg2, dword arg3) +inline dword invoke(Function function, dword arg1, dword arg2, dword arg3) { dword result; asm volatile("int $0x80":"=a"(result):"a"(function),"d"(arg1),"c"(arg2),"b"(arg3):"memory"); diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp index 3fc553a8bd6..6b2f2fb34c8 100644 --- a/Kernel/TTY.cpp +++ b/Kernel/TTY.cpp @@ -1,6 +1,8 @@ #include "TTY.h" #include "Process.h" +#include #include +#include TTY::TTY(unsigned major, unsigned minor) : CharacterDevice(major, minor) @@ -66,3 +68,22 @@ void TTY::set_termios(const Unix::termios& t) should_echo_input(), should_generate_signals()); } + +int TTY::ioctl(Process& process, unsigned request, unsigned arg) +{ + if (process.tty() != this) + return -ENOTTY; + switch (request) { + case TIOCGPGRP: + return pgid(); + case TIOCSPGRP: { + // FIXME: Validate pgid fully. + pid_t pgid = static_cast(arg); + if (pgid < 0) + return -EINVAL; + set_pgid(arg); + return 0; + } + } + return -EINVAL; +} diff --git a/Kernel/TTY.h b/Kernel/TTY.h index e8bce25f736..8018012ce00 100644 --- a/Kernel/TTY.h +++ b/Kernel/TTY.h @@ -3,6 +3,8 @@ #include #include +class Process; + class TTY : public CharacterDevice { public: virtual ~TTY() override; @@ -10,6 +12,7 @@ public: virtual ssize_t read(byte*, size_t) override; virtual ssize_t write(const byte*, size_t) override; virtual bool hasDataAvailableForRead() const override; + virtual int ioctl(Process&, unsigned request, unsigned arg) override final; virtual String ttyName() const = 0; diff --git a/LibC/Makefile b/LibC/Makefile index bbe6a1136d3..9cabeb8ea6f 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -30,6 +30,7 @@ LIBC_OBJS = \ termios.o \ ulimit.o \ qsort.o \ + ioctl.o \ entry.o OBJS = $(AK_OBJS) $(LIBC_OBJS) diff --git a/LibC/ioctl.cpp b/LibC/ioctl.cpp new file mode 100644 index 00000000000..dcfc7ce7a41 --- /dev/null +++ b/LibC/ioctl.cpp @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include + +extern "C" { + +int ioctl(int fd, unsigned request, ...) +{ + va_list ap; + va_start(ap, request); + unsigned arg = va_arg(ap, unsigned); + int rc = Syscall::invoke(Syscall::SC_ioctl, (dword)fd, (dword)request, (dword)arg); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +} + diff --git a/LibC/stdarg.h b/LibC/stdarg.h index 724ffb59d57..c58efc85fa0 100644 --- a/LibC/stdarg.h +++ b/LibC/stdarg.h @@ -4,11 +4,11 @@ __BEGIN_DECLS -typedef char* va_list; +typedef __builtin_va_list va_list; -#define va_start(ap, v) ap = (va_list)&v + sizeof(v) -#define va_arg(ap, t) ((t*)(ap += sizeof(t)))[-1] -#define va_end(ap) ap = nullptr +#define va_start(v, l) __builtin_va_start(v, l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v, l) __builtin_va_arg(v, l) __END_DECLS diff --git a/LibC/sys/ioctl.h b/LibC/sys/ioctl.h index e69de29bb2d..3a2dcd0b5f2 100644 --- a/LibC/sys/ioctl.h +++ b/LibC/sys/ioctl.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +__BEGIN_DECLS + +int ioctl(int fd, unsigned request, ...); + +__END_DECLS diff --git a/LibC/sys/ioctl_numbers.h b/LibC/sys/ioctl_numbers.h new file mode 100644 index 00000000000..c0c0fe23d70 --- /dev/null +++ b/LibC/sys/ioctl_numbers.h @@ -0,0 +1,7 @@ +#pragma once + +enum IOCtlNumber { + TIOCGPGRP, + TIOCSPGRP, +}; + diff --git a/LibC/termcap.cpp b/LibC/termcap.cpp index d422d476975..5c8e9ce0a8d 100644 --- a/LibC/termcap.cpp +++ b/LibC/termcap.cpp @@ -108,6 +108,7 @@ char* tgoto(const char* cap, int col, int row) int tputs(const char* str, int affcnt, int (*putc)(int)) { printf("%s", str); + return 0; } } diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 09387a5f644..821654494c4 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include extern "C" { @@ -60,14 +61,12 @@ pid_t setsid() pid_t tcgetpgrp(int fd) { - int rc = Syscall::invoke(Syscall::SC_tcgetpgrp, (dword)fd); - __RETURN_WITH_ERRNO(rc, rc, -1); + return ioctl(fd, TIOCGPGRP); } int tcsetpgrp(int fd, pid_t pgid) { - int rc = Syscall::invoke(Syscall::SC_tcsetpgrp, (dword)fd, (dword)pgid); - __RETURN_WITH_ERRNO(rc, rc, -1); + return ioctl(fd, TIOCSPGRP, pgid); } int setpgid(pid_t pid, pid_t pgid) diff --git a/VirtualFileSystem/CharacterDevice.cpp b/VirtualFileSystem/CharacterDevice.cpp index 10afe42b1c9..851664ba9be 100644 --- a/VirtualFileSystem/CharacterDevice.cpp +++ b/VirtualFileSystem/CharacterDevice.cpp @@ -1,4 +1,5 @@ #include "CharacterDevice.h" +#include CharacterDevice::~CharacterDevice() { @@ -8,3 +9,8 @@ RetainPtr CharacterDevice::open(int options) { return VFS::the().open(*this, options); } + +int CharacterDevice::ioctl(Process&, unsigned, unsigned) +{ + return -ENOTTY; +} diff --git a/VirtualFileSystem/CharacterDevice.h b/VirtualFileSystem/CharacterDevice.h index 47127977dce..3c78a84da53 100644 --- a/VirtualFileSystem/CharacterDevice.h +++ b/VirtualFileSystem/CharacterDevice.h @@ -4,6 +4,8 @@ #include "Limits.h" #include "FileDescriptor.h" +class Process; + class CharacterDevice { public: virtual ~CharacterDevice(); @@ -20,10 +22,12 @@ public: virtual bool isTTY() const { return false; } + virtual int ioctl(Process&, unsigned request, unsigned arg); + protected: CharacterDevice(unsigned major, unsigned minor) : m_major(major), m_minor(minor) { } private: unsigned m_major { 0 }; - unsigned m_minor{ 0 }; + unsigned m_minor { 0 }; }; diff --git a/VirtualFileSystem/FileDescriptor.h b/VirtualFileSystem/FileDescriptor.h index eeb2bec9ca9..b5836cf4d3c 100644 --- a/VirtualFileSystem/FileDescriptor.h +++ b/VirtualFileSystem/FileDescriptor.h @@ -38,6 +38,9 @@ public: bool isDirectory() const; + bool is_character_device() const { return m_vnode && m_vnode->isCharacterDevice(); } + CharacterDevice* character_device() { return m_vnode ? m_vnode->characterDevice() : nullptr; } + #ifdef SERENITY bool isTTY() const; const TTY* tty() const;