From 938f722dcbe2652fe96e77983f2dd495db1e5f43 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 12 Jun 2013 02:18:07 +0200 Subject: [PATCH] Add tcsetpgrp(2) and tcgetpgrp(2). --- libc/Makefile | 2 ++ libc/include/fsmarshall-msg.h | 21 ++++++++++++- libc/include/unistd.h | 4 +-- libc/tcgetpgrp.cpp | 34 +++++++++++++++++++++ libc/tcsetpgrp.cpp | 34 +++++++++++++++++++++ sortix/descriptor.cpp | 10 ++++++ sortix/fs/user.cpp | 34 +++++++++++++++++++++ sortix/include/sortix/kernel/descriptor.h | 2 ++ sortix/include/sortix/kernel/inode.h | 4 +++ sortix/include/sortix/kernel/vnode.h | 2 ++ sortix/include/sortix/syscallnum.h | 4 ++- sortix/inode.cpp | 14 +++++++++ sortix/io.cpp | 20 ++++++++++++ sortix/logterminal.cpp | 37 ++++++++++++++++++++--- sortix/logterminal.h | 3 ++ sortix/vnode.cpp | 10 ++++++ 16 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 libc/tcgetpgrp.cpp create mode 100644 libc/tcsetpgrp.cpp diff --git a/libc/Makefile b/libc/Makefile index b684ea44..d126ef57 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -354,6 +354,8 @@ sys/socket/socket.o \ sys/socket/socketpair.o \ system.o \ sys/time/gettimeofday.o \ +tcgetpgrp.o \ +tcsetpgrp.o \ tfork.o \ time/clock_getres.o \ time/clock_gettime.o \ diff --git a/libc/include/fsmarshall-msg.h b/libc/include/fsmarshall-msg.h index 427c237a..37626c38 100644 --- a/libc/include/fsmarshall-msg.h +++ b/libc/include/fsmarshall-msg.h @@ -324,7 +324,26 @@ struct fsm_req_unref ino_t ino; }; -#define FSM_MSG_NUM 40 +#define FSM_REQ_TCSETPGRP 40 +struct fsm_req_tcsetpgrp +{ + ino_t ino; + pid_t pgid; +}; + +#define FSM_REQ_TCGETPGRP 41 +struct fsm_req_tcgetpgrp +{ + ino_t ino; +}; + +#define FSM_RESP_TCGETPGRP 42 +struct fsm_resp_tcgetpgrp +{ + pid_t pgid; +}; + +#define FSM_MSG_NUM 43 #if defined(__cplusplus) } /* extern "C" */ diff --git a/libc/include/unistd.h b/libc/include/unistd.h index d7587b37..a695b262 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -284,8 +284,6 @@ void swab(const void* __restrict, void* __restrict, ssize_t); int symlink(const char*, const char*); int symlinkat(const char*, int, const char*); void sync(void); -pid_t tcgetpgrp(int); -int tcsetpgrp(int, pid_t); int ttyname_r(int, char*, size_t); #if __POSIX_OBSOLETE <= 200801 @@ -354,6 +352,8 @@ int setpgid(pid_t, pid_t); int setuid(uid_t); unsigned sleep(unsigned); long sysconf(int); +pid_t tcgetpgrp(int); +int tcsetpgrp(int, pid_t); int truncate(const char*, off_t); int truncateat(int dirfd, const char*, off_t); char* ttyname(int); diff --git a/libc/tcgetpgrp.cpp b/libc/tcgetpgrp.cpp new file mode 100644 index 00000000..47da799b --- /dev/null +++ b/libc/tcgetpgrp.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + tcgetpgrp.cpp + Get the foreground process group of a terminal. + +*******************************************************************************/ + +#include + +#include + +DEFN_SYSCALL1(pid_t, sys_tcgetpgrp, SYSCALL_TCGETPGRP, int); + +extern "C" pid_t tcgetpgrp(int fd) +{ + return sys_tcgetpgrp(fd); +} diff --git a/libc/tcsetpgrp.cpp b/libc/tcsetpgrp.cpp new file mode 100644 index 00000000..ad529778 --- /dev/null +++ b/libc/tcsetpgrp.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + tcsetpgrp.cpp + set the foreground process group of a terminal. + +*******************************************************************************/ + +#include + +#include + +DEFN_SYSCALL2(int, sys_tcsetpgrp, SYSCALL_TCSETPGRP, int, pid_t); + +extern "C" int tcsetpgrp(int fd, pid_t pgid) +{ + return sys_tcsetpgrp(fd, pgid); +} diff --git a/sortix/descriptor.cpp b/sortix/descriptor.cpp index 08ed411f..367b547a 100644 --- a/sortix/descriptor.cpp +++ b/sortix/descriptor.cpp @@ -548,6 +548,16 @@ int Descriptor::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) return vnode->tcgetwinsize(ctx, ws); } +int Descriptor::tcsetpgrp(ioctx_t* ctx, pid_t pgid) +{ + return vnode->tcsetpgrp(ctx, pgid); +} + +pid_t Descriptor::tcgetpgrp(ioctx_t* ctx) +{ + return vnode->tcgetpgrp(ctx); +} + int Descriptor::settermmode(ioctx_t* ctx, unsigned mode) { return vnode->settermmode(ctx, mode); diff --git a/sortix/fs/user.cpp b/sortix/fs/user.cpp index 77347e94..32cec508 100644 --- a/sortix/fs/user.cpp +++ b/sortix/fs/user.cpp @@ -213,6 +213,8 @@ public: const char* filename); virtual ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); + virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid); + virtual pid_t tcgetpgrp(ioctx_t* ctx); virtual int settermmode(ioctx_t* ctx, unsigned mode); virtual int gettermmode(ioctx_t* ctx, unsigned* mode); virtual int poll(ioctx_t* ctx, PollNode* node); @@ -1115,6 +1117,38 @@ int Unode::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) return ret; } +int Unode::tcsetpgrp(ioctx_t* /*ctx*/, pid_t pgid) +{ + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + int ret = -1; + struct fsm_req_tcsetpgrp msg; + msg.ino = ino; + msg.pgid = pgid; + if ( SendMessage(channel, FSM_REQ_TCSETPGRP, &msg, sizeof(msg)) && + RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) ) + ret = 0; + channel->KernelClose(); + return ret; +} + +pid_t Unode::tcgetpgrp(ioctx_t* /*ctx*/) +{ + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + pid_t ret = -1; + struct fsm_req_tcgetpgrp msg; + struct fsm_resp_tcgetpgrp resp; + msg.ino = ino; + if ( SendMessage(channel, FSM_REQ_TCGETPGRP, &msg, sizeof(msg)) && + RecvMessage(channel, FSM_RESP_TCGETPGRP, &resp, sizeof(resp)) ) + ret = resp.pgid; + channel->KernelClose(); + return ret; +} + int Unode::settermmode(ioctx_t* /*ctx*/, unsigned mode) { Channel* channel = server->Connect(); diff --git a/sortix/include/sortix/kernel/descriptor.h b/sortix/include/sortix/kernel/descriptor.h index ef60ed5f..4fc6fa2b 100644 --- a/sortix/include/sortix/kernel/descriptor.h +++ b/sortix/include/sortix/kernel/descriptor.h @@ -78,6 +78,8 @@ public: int symlink(ioctx_t* ctx, const char* oldname, const char* filename); ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); + int tcsetpgrp(ioctx_t* ctx, pid_t pgid); + pid_t tcgetpgrp(ioctx_t* ctx); int settermmode(ioctx_t* ctx, unsigned mode); int gettermmode(ioctx_t* ctx, unsigned* mode); int poll(ioctx_t* ctx, PollNode* node); diff --git a/sortix/include/sortix/kernel/inode.h b/sortix/include/sortix/kernel/inode.h index 09a1296e..e463c28d 100644 --- a/sortix/include/sortix/kernel/inode.h +++ b/sortix/include/sortix/kernel/inode.h @@ -87,6 +87,8 @@ public: const char* filename) = 0; virtual ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz) = 0; virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws) = 0; + virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid) = 0; + virtual pid_t tcgetpgrp(ioctx_t* ctx) = 0; virtual int settermmode(ioctx_t* ctx, unsigned mode) = 0; virtual int gettermmode(ioctx_t* ctx, unsigned* mode) = 0; virtual int poll(ioctx_t* ctx, PollNode* node) = 0; @@ -163,6 +165,8 @@ public: const char* filename); virtual ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); + virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid); + virtual pid_t tcgetpgrp(ioctx_t* ctx); virtual int settermmode(ioctx_t* ctx, unsigned mode); virtual int gettermmode(ioctx_t* ctx, unsigned* mode); virtual int poll(ioctx_t* ctx, PollNode* node); diff --git a/sortix/include/sortix/kernel/vnode.h b/sortix/include/sortix/kernel/vnode.h index de586ef2..5c6c98e6 100644 --- a/sortix/include/sortix/kernel/vnode.h +++ b/sortix/include/sortix/kernel/vnode.h @@ -75,6 +75,8 @@ public: ssize_t readlink(ioctx_t* ctx, char* buf, size_t bufsiz); int fsbind(ioctx_t* ctx, Vnode* node, int flags); int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); + int tcsetpgrp(ioctx_t* ctx, pid_t pgid); + pid_t tcgetpgrp(ioctx_t* ctx); int settermmode(ioctx_t* ctx, unsigned mode); int gettermmode(ioctx_t* ctx, unsigned* mode); int poll(ioctx_t* ctx, PollNode* node); diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h index dd31dfba..fc796650 100644 --- a/sortix/include/sortix/syscallnum.h +++ b/sortix/include/sortix/syscallnum.h @@ -135,6 +135,8 @@ #define SYSCALL_MKPARTITION 111 #define SYSCALL_GETPGID 112 #define SYSCALL_SETPGID 113 -#define SYSCALL_MAX_NUM 114 /* index of highest constant + 1 */ +#define SYSCALL_TCGETPGRP 114 +#define SYSCALL_TCSETPGRP 115 +#define SYSCALL_MAX_NUM 116 /* index of highest constant + 1 */ #endif diff --git a/sortix/inode.cpp b/sortix/inode.cpp index 33c9149c..09a85cbf 100644 --- a/sortix/inode.cpp +++ b/sortix/inode.cpp @@ -265,6 +265,20 @@ int AbstractInode::tcgetwinsize(ioctx_t* /*ctx*/, struct winsize* /*ws*/) return errno = ENOTTY, -1; } +int AbstractInode::tcsetpgrp(ioctx_t* /*ctx*/, pid_t /*pgid*/) +{ + if ( inode_type == INODE_TYPE_TTY ) + return errno = EBADF, -1; + return errno = ENOTTY, -1; +} + +pid_t AbstractInode::tcgetpgrp(ioctx_t* /*ctx*/) +{ + if ( inode_type == INODE_TYPE_TTY ) + return errno = EBADF, -1; + return errno = ENOTTY, -1; +} + int AbstractInode::settermmode(ioctx_t* /*ctx*/, unsigned /*mode*/) { if ( inode_type == INODE_TYPE_TTY ) diff --git a/sortix/io.cpp b/sortix/io.cpp index 031c5c1a..e3077745 100644 --- a/sortix/io.cpp +++ b/sortix/io.cpp @@ -604,6 +604,24 @@ static int sys_tcgetwinsize(int fd, struct winsize* ws) return desc->tcgetwinsize(&ctx, ws); } +static int sys_tcsetpgrp(int fd, pid_t pgid) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + ioctx_t ctx; SetupUserIOCtx(&ctx); + return desc->tcsetpgrp(&ctx, pgid); +} + +static int sys_tcgetpgrp(int fd) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + ioctx_t ctx; SetupUserIOCtx(&ctx); + return desc->tcgetpgrp(&ctx); +} + static int sys_renameat_inner(int olddirfd, const char* oldpath, int newdirfd, const char* newpath) { @@ -973,7 +991,9 @@ void Init() Syscall::Register(SYSCALL_SEND, (void*) sys_send); Syscall::Register(SYSCALL_SETTERMMODE, (void*) sys_settermmode); Syscall::Register(SYSCALL_STAT, (void*) sys_stat); + Syscall::Register(SYSCALL_TCGETPGRP, (void*) sys_tcgetpgrp); Syscall::Register(SYSCALL_TCGETWINSIZE, (void*) sys_tcgetwinsize); + Syscall::Register(SYSCALL_TCSETPGRP, (void*) sys_tcsetpgrp); Syscall::Register(SYSCALL_TRUNCATEAT, (void*) sys_truncateat); Syscall::Register(SYSCALL_TRUNCATE, (void*) sys_truncate); Syscall::Register(SYSCALL_UNLINKAT, (void*) sys_unlinkat); diff --git a/sortix/logterminal.cpp b/sortix/logterminal.cpp index 1226964c..99d015a0 100644 --- a/sortix/logterminal.cpp +++ b/sortix/logterminal.cpp @@ -84,6 +84,7 @@ LogTerminal::LogTerminal(dev_t dev, mode_t mode, uid_t owner, gid_t group, this->datacond = KTHREAD_COND_INITIALIZER; this->numwaiting = 0; this->numeofs = 0; + this->foreground_pgid = 0; keyboard->SetOwner(this, NULL); } @@ -128,6 +129,27 @@ int LogTerminal::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) return 0; } +int LogTerminal::tcsetpgrp(ioctx_t* /*ctx*/, pid_t pgid) +{ + ScopedLock lock(&termlock); + Process* process = Process::Get(pgid); + if ( !pgid || !process ) + return errno = ESRCH, -1; + kthread_mutex_lock(&process->groupchildlock); + bool is_process_group = process->group == process; + kthread_mutex_unlock(&process->groupchildlock); + if ( !is_process_group ) + return errno = EINVAL, -1; + foreground_pgid = pgid; + return 0; +} + +pid_t LogTerminal::tcgetpgrp(ioctx_t* /*ctx*/) +{ + ScopedLock lock(&termlock); + return foreground_pgid = 0; +} + int LogTerminal::sync(ioctx_t* /*ctx*/) { return Log::Sync() ? 0 : -1; @@ -152,10 +174,17 @@ void LogTerminal::ProcessKeystroke(int kbkey) { while ( linebuffer.CanBackspace() ) linebuffer.Backspace(); - pid_t pid = Process::HackGetForegroundProcess(); - Process* process = Process::Get(pid); - if ( process ) - process->DeliverSignal(SIGINT); + if ( foreground_pgid ) + { + if ( Process* process = Process::Get(foreground_pgid) ) + process->DeliverGroupSignal(SIGINT); + } + else // TODO: Backwards compatibility, delete this. + { + pid_t pid = Process::HackGetForegroundProcess(); + if ( Process* process = Process::Get(pid) ) + process->DeliverSignal(SIGINT); + } return; } if ( termmode & TERMMODE_SIGNAL && control && kbkey == KBKEY_D ) diff --git a/sortix/logterminal.h b/sortix/logterminal.h index 8763ee0d..8abbe6dd 100644 --- a/sortix/logterminal.h +++ b/sortix/logterminal.h @@ -45,6 +45,8 @@ public: virtual ssize_t read(ioctx_t* ctx, uint8_t* buf, size_t count); virtual ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count); virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws); + virtual int tcsetpgrp(ioctx_t* ctx, pid_t pgid); + virtual pid_t tcgetpgrp(ioctx_t* ctx); virtual int settermmode(ioctx_t* ctx, unsigned termmode); virtual int gettermmode(ioctx_t* ctx, unsigned* termmode); virtual int poll(ioctx_t* ctx, PollNode* node); @@ -69,6 +71,7 @@ private: LineBuffer linebuffer; size_t partiallywritten; unsigned termmode; + pid_t foreground_pgid; bool control; }; diff --git a/sortix/vnode.cpp b/sortix/vnode.cpp index e635e5d7..1f520e99 100644 --- a/sortix/vnode.cpp +++ b/sortix/vnode.cpp @@ -224,6 +224,16 @@ int Vnode::tcgetwinsize(ioctx_t* ctx, struct winsize* ws) return inode->tcgetwinsize(ctx, ws); } +int Vnode::tcsetpgrp(ioctx_t* ctx, pid_t pgid) +{ + return inode->tcsetpgrp(ctx, pgid); +} + +pid_t Vnode::tcgetpgrp(ioctx_t* ctx) +{ + return inode->tcgetpgrp(ctx); +} + int Vnode::settermmode(ioctx_t* ctx, unsigned mode) { return inode->settermmode(ctx, mode);