summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/Process.cpp27
-rw-r--r--Kernel/Process.h3
-rw-r--r--Kernel/Syscall.cpp6
-rw-r--r--Kernel/Syscall.h11
-rw-r--r--Kernel/TTY.cpp21
-rw-r--r--Kernel/TTY.h3
-rw-r--r--LibC/Makefile1
-rw-r--r--LibC/ioctl.cpp19
-rw-r--r--LibC/stdarg.h8
-rw-r--r--LibC/sys/ioctl.h10
-rw-r--r--LibC/sys/ioctl_numbers.h7
-rw-r--r--LibC/termcap.cpp1
-rw-r--r--LibC/unistd.cpp7
-rw-r--r--VirtualFileSystem/CharacterDevice.cpp6
-rw-r--r--VirtualFileSystem/CharacterDevice.h6
-rw-r--r--VirtualFileSystem/FileDescriptor.h3
16 files changed, 94 insertions, 45 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 3df32e6abb..5915872b30 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())
- 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)
+ if (!descriptor->is_character_device())
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 a354d00285..f15afd1ae9 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 557725fc15..95f41e0c82 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 a9346ff211..65ce348950 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 3fc553a8bd..6b2f2fb34c 100644
--- a/Kernel/TTY.cpp
+++ b/Kernel/TTY.cpp
@@ -1,6 +1,8 @@
#include "TTY.h"
#include "Process.h"
+#include <LibC/errno_numbers.h>
#include <LibC/signal_numbers.h>
+#include <LibC/sys/ioctl_numbers.h>
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<pid_t>(arg);
+ if (pgid < 0)
+ return -EINVAL;
+ set_pgid(arg);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
diff --git a/Kernel/TTY.h b/Kernel/TTY.h
index e8bce25f73..8018012ce0 100644
--- a/Kernel/TTY.h
+++ b/Kernel/TTY.h
@@ -3,6 +3,8 @@
#include <VirtualFileSystem/CharacterDevice.h>
#include <VirtualFileSystem/UnixTypes.h>
+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 bbe6a1136d..9cabeb8ea6 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 0000000000..dcfc7ce7a4
--- /dev/null
+++ b/LibC/ioctl.cpp
@@ -0,0 +1,19 @@
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <Kernel/Syscall.h>
+
+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 724ffb59d5..c58efc85fa 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 e69de29bb2..3a2dcd0b5f 100644
--- a/LibC/sys/ioctl.h
+++ b/LibC/sys/ioctl.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/ioctl_numbers.h>
+
+__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 0000000000..c0c0fe23d7
--- /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 d422d47697..5c8e9ce0a8 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 09387a5f64..821654494c 100644
--- a/LibC/unistd.cpp
+++ b/LibC/unistd.cpp
@@ -6,6 +6,7 @@
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
+#include <sys/ioctl.h>
#include <Kernel/Syscall.h>
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 10afe42b1c..851664ba9b 100644
--- a/VirtualFileSystem/CharacterDevice.cpp
+++ b/VirtualFileSystem/CharacterDevice.cpp
@@ -1,4 +1,5 @@
#include "CharacterDevice.h"
+#include <LibC/errno_numbers.h>
CharacterDevice::~CharacterDevice()
{
@@ -8,3 +9,8 @@ RetainPtr<FileDescriptor> 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 47127977dc..3c78a84da5 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 eeb2bec9ca..b5836cf4d3 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;