From fc09d398954ab5f658a7fc73ea730d7510e3bc93 Mon Sep 17 00:00:00 2001 From: Matheus Date: Wed, 28 Aug 2024 20:26:43 -0300 Subject: [PATCH] jobctl: allow tty stealing --- kernel-src/include/kernel/jobctl.h | 2 +- kernel-src/io/tty.c | 15 ++------ kernel-src/sys/jobctl.c | 55 +++++++++++++++++++----------- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/kernel-src/include/kernel/jobctl.h b/kernel-src/include/kernel/jobctl.h index be9eb935..6e53ac73 100644 --- a/kernel-src/include/kernel/jobctl.h +++ b/kernel-src/include/kernel/jobctl.h @@ -11,7 +11,7 @@ void jobctl_addproc(proc_t *parent, proc_t *proc); void jobctl_procremove(proc_t *proc); pid_t jobctl_getpgid(proc_t *proc); pid_t jobctl_getsid(proc_t *proc); -void jobctl_setctty(proc_t *proc, void *ctty); +int jobctl_setctty(proc_t *proc, void *ctty, bool steal); void *jobctl_getctty(proc_t *proc); int jobctl_signal(proc_t *proc, int signal); proc_t *jobctl_getforeground(proc_t *proc); diff --git a/kernel-src/io/tty.c b/kernel-src/io/tty.c index fb576733..953409fc 100644 --- a/kernel-src/io/tty.c +++ b/kernel-src/io/tty.c @@ -320,19 +320,8 @@ int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result) { case TCSETS: return USERCOPY_POSSIBLY_FROM_USER(&tty->termios, arg, sizeof(termios_t)); case TIOCSCTTY: { - if (arg) { - int steal; - int e = USERCOPY_POSSIBLY_FROM_USER(&steal, arg, sizeof(int)); - if (e) - return e; - - if (steal == 1) { - printf("tty: stealing not supported\n"); - return EINVAL; - } - } // set as controlling tty - jobctl_setctty(_cpu()->thread->proc, tty); + return jobctl_setctty(_cpu()->thread->proc, tty, (uintptr_t)arg == 1); break; } case TIOCGPGRP: { @@ -399,7 +388,7 @@ static int open(int minor, vnode_t **vnode, int flags) { return ENODEV; } else if ((flags & V_FFLAGS_NOCTTY) == 0) { // set as controlling tty - jobctl_setctty(_cpu()->thread->proc, tty); + jobctl_setctty(_cpu()->thread->proc, tty, false); } return 0; diff --git a/kernel-src/sys/jobctl.c b/kernel-src/sys/jobctl.c index 2f691b09..3af0872f 100644 --- a/kernel-src/sys/jobctl.c +++ b/kernel-src/sys/jobctl.c @@ -33,9 +33,9 @@ static void removefromlist(proc_t *pgrp, proc_t *proc) { spinlock_release(&pgrp->pgrp.lock); } -void jobctl_setctty(proc_t *proc, void *_ctty) { +int jobctl_setctty(proc_t *proc, void *_ctty, bool steal) { tty_t *tty = _ctty; - + int error = 0; bool intstatus = interrupt_set(false); spinlock_acquire(&proc->jobctllock); @@ -45,21 +45,38 @@ void jobctl_setctty(proc_t *proc, void *_ctty) { if (proc->session.leader) goto leave; - if (tty == NULL && proc->session.controllingtty) { - unholdtty = proc->session.controllingtty; - proc->session.controllingtty = NULL; - spinlock_acquire(&unholdtty->sessionlock); - unholdtty->session = NULL; - spinlock_release(&unholdtty->sessionlock); + tty_t *checktty = proc->session.controllingtty; + if (tty == NULL && checktty) { + if (checktty) + spinlock_acquire(&checktty->sessionlock); + + // check if it was stolen + if (checktty->session == proc) { + // not stolen, unset it + // TODO SIGHUP and SIGCONT to foregroup group + unholdtty = checktty; + proc->session.controllingtty = NULL; + checktty->session = NULL; + } + + spinlock_release(&checktty->sessionlock); } if (tty && proc->session.controllingtty == NULL) { spinlock_acquire(&tty->sessionlock); + if (tty->session == NULL) { VOP_HOLD(tty->mastervnode); proc->session.controllingtty = tty; tty->session = proc; + } else if (steal) { + // vnode reference gets transferred over to the new proc + tty->session->session.controllingtty = NULL; + tty->session = proc; + } else { + error = EPERM; } + spinlock_release(&tty->sessionlock); } @@ -70,6 +87,8 @@ void jobctl_setctty(proc_t *proc, void *_ctty) { if (unholdtty) { VOP_RELEASE(unholdtty->mastervnode); } + + return error; } void *jobctl_getctty(proc_t *proc) { @@ -77,23 +96,19 @@ void *jobctl_getctty(proc_t *proc) { bool intstatus = interrupt_set(false); spinlock_acquire(&proc->jobctllock); + proc_t *session = proc->session.leader ? proc->session.leader : proc; - if (proc->session.leader) { - proc_t *session = proc->session.leader; + if (session != proc) spinlock_acquire(&session->jobctllock); - tty = session->session.controllingtty; - if (tty) { - VOP_HOLD(tty->mastervnode); - } - - spinlock_release(&session->jobctllock); - } else if (proc->session.controllingtty){ - // is the session leader - tty = proc->session.controllingtty; + tty = session->session.controllingtty; + if (tty) { VOP_HOLD(tty->mastervnode); } + if (session != proc) + spinlock_release(&session->jobctllock); + spinlock_release(&proc->jobctllock); interrupt_set(intstatus); return tty; @@ -262,7 +277,7 @@ void jobctl_detach(proc_t *proc) { if (unholdsession) { PROC_RELEASE(unholdsession); } else { - jobctl_setctty(proc, NULL); + jobctl_setctty(proc, NULL, 0); jobctl_signal(foreground, SIGHUP); jobctl_signal(foreground, SIGCONT); PROC_RELEASE(foreground);