Add tcsetpgrp(2) and tcgetpgrp(2).

This commit is contained in:
Jonas 'Sortie' Termansen 2013-06-12 02:18:07 +02:00
parent b6349e21cb
commit 938f722dcb
16 changed files with 227 additions and 8 deletions

View File

@ -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 \

View File

@ -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" */

View File

@ -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);

34
libc/tcgetpgrp.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
tcgetpgrp.cpp
Get the foreground process group of a terminal.
*******************************************************************************/
#include <sys/syscall.h>
#include <unistd.h>
DEFN_SYSCALL1(pid_t, sys_tcgetpgrp, SYSCALL_TCGETPGRP, int);
extern "C" pid_t tcgetpgrp(int fd)
{
return sys_tcgetpgrp(fd);
}

34
libc/tcsetpgrp.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
tcsetpgrp.cpp
set the foreground process group of a terminal.
*******************************************************************************/
#include <sys/syscall.h>
#include <unistd.h>
DEFN_SYSCALL2(int, sys_tcsetpgrp, SYSCALL_TCSETPGRP, int, pid_t);
extern "C" int tcsetpgrp(int fd, pid_t pgid)
{
return sys_tcsetpgrp(fd, pgid);
}

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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 )

View File

@ -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<Descriptor> 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<Descriptor> 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);

View File

@ -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 )

View File

@ -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;
};

View File

@ -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);