23#include <aquila/fcntl.h>
30#define IS_CC(tty, c, cc) ((tty)->tios.c_cc[cc] && (c) == (tty)->tios.c_cc[cc])
35 if ((
unsigned char) c <
' ' && c !=
'\n' && c !=
'\t') {
36 char cc[] = {
'^', c +
'@'};
38 }
else if (c == 0x7f) {
56 int width = ((
unsigned char) c <
' ' && c !=
'\t') || c == 0x7f ? 2 : 1;
76 int sig =
IS_CC(
tty, c, VINTR) ? SIGINT :
83 if (!(
tty->
tios.c_lflag & NOFLSH))
113 struct termios *tios = &
tty->
tios;
116 for (
size_t i = 0; i < size; ++i) {
121 if (tios->c_iflag & IGNCR)
123 if (tios->c_iflag & ICRNL)
125 }
else if (c ==
'\n' && (tios->c_iflag & INLCR)) {
131 if (tios->c_iflag & IXON) {
149 if (!(tios->c_lflag & ICANON)) {
152 if (tios->c_lflag & ECHO)
170 }
else if (c ==
'\n' ||
IS_CC(
tty, c, VEOL)) {
173 if ((tios->c_lflag & ECHO) || (c ==
'\n' && (tios->c_lflag & ECHONL)))
184 if (tios->c_lflag & ECHO)
203 if (!(
tty->
tios.c_lflag & ICANON))
226 return tty->
tios.c_cc[VTIME] * 100000000ULL;
242 return buffered ||
tty->
eof;
266 return sig == SIGTTIN ? -EIO : 0;
299 const char *buf = (
const char *) _buf;
300 tcflag_t oflag =
tty->
tios.c_oflag;
302 if (!(oflag & OPOST))
307 for (written = 0; written < size; ++written) {
308 char c = buf[written];
336 }
else if (c ==
'\r') {
338 if ((oflag & ONOCR) && !
tty->
col)
361 else if ((
unsigned char) c >=
' ' && c != 0x7f)
390 return err ? err : -EIO;
411 size_t size = io->
resid, done = 0;
421 while (done < size) {
425 return done ? (
ssize_t) done : len;
430 return done ? (
ssize_t) done : r;
436 if (r < len || io->fault)
461 return copyout(argp, &
tty->
tios,
sizeof(
struct termios));
467 if (copyin(&tios, argp,
sizeof(tios)))
473 if (request == TCSETSF)
507 return copyout(argp, &pgid,
sizeof(pgid));
516 if (copyin(&
pgid, argp,
sizeof(
pgid)))
526 struct pgroup *pg = node->value;
540 return copyout(argp, &
tty->
ws,
sizeof(
struct winsize));
544 if (copyin(&ws, argp,
sizeof(ws)))
585 ttyio slave,
void *p,
struct tty **ref)
590 if (!
tty)
return -ENOMEM;
608 tty->
tios.c_iflag = ICRNL | IXON;
609 tty->
tios.c_oflag = OPOST | ONLCR;
610 tty->
tios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
649 int console =
file->vnode &&
file->vnode->rdev ==
DEV(5, 1);
693 if (which == TCOFLUSH)
#define DEV(major, minor)
void tty_hangup(struct tty *tty)
Hangs up a controlling terminal, when its session ends (its leader exited) or the terminal goes away:...
ssize_t tty_slave_write(struct tty *tty, size_t size, void *_buf)
Takes what programs write to the terminal, and sends it to the device through output processing (OPOS...
static void tty_erase(struct tty *tty)
Erases the last character of the line being edited, on the screen too with ECHOE.
static int tty_out(struct tty *tty, const char *s, size_t n)
Sends n bytes to the device.
static int tty_wait_start(struct tty *tty)
Waits while the terminal's output is stopped (IXON).
int tty_ioctl(struct tty *tty, int request, void *argp)
Handles a terminal's ioctl()s: its modes (TCGETS, TCSETS, ...), flushing, its session and foreground ...
int tty_free(struct tty *tty)
Ends a terminal: it is hung up, and freed.
static void tty_echo(struct tty *tty, char c)
Echoes a character, a control character as ^X.
ssize_t tty_write_iobuf(struct tty *tty, struct iobuf *io, ttyio write)
Writes to a terminal from an iobuf (user memory), to either side: a piece at a time through a kernel ...
int tty_new(struct proc *proc, size_t buf_size, ttyio master, ttyio slave, void *p, struct tty **ref)
Makes a new terminal, with the default modes (canonical, echo, signals, ICRNL, IXON,...
ssize_t tty_master_write(struct tty *tty, size_t size, void *buf)
Takes input from the terminal's device (the keyboard, a UART, or a pseudo-terminal's master),...
int tty_can_read(struct tty *tty, size_t buffered)
Says whether the terminal is readable, for select() and poll(): there is input, or an end-of-file.
int tty_eof(struct tty *tty)
Says whether a read that found nothing to return should return 0 at once: at an end-of-file (VEOF at ...
int tty_background(struct tty *tty, int sig)
Stops a background process that reads the terminal, writes it or changes it: if the current process i...
static void tty_deliver(struct tty *tty)
Hands the line being edited to the readers.
#define IS_CC(tty, c, cc)
static void tty_release(struct tty *tty)
Frees a terminal's memory.
uint64_t tty_read_timeout(struct tty *tty)
Says how long a read waits for input: VTIME tenths of a second with VMIN 0 in non-canonical mode,...
static int tty_signal(struct tty *tty, char c)
Handles a signal character (with ISIG): the foreground group gets the signal.
void tty_open(struct tty *tty, struct file *file)
Handles a terminal device being opened: it becomes the controlling terminal of a session leader that ...
void tty_flush(struct tty *tty, int which)
Drops a terminal's input (TCIFLUSH, TCIOFLUSH): the line being edited, what the device holds for read...
size_t iobuf_skip(struct iobuf *io, size_t n)
Moves an iobuf past bytes, without copying them.
ssize_t iobuf_peek(struct iobuf *io, void *dst, size_t n)
Copies bytes from the iobuf's buffer into the kernel, without moving past them.
#define MALLOC_DEFINE(type, _name, _desc)
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
void kfree(void *)
Frees an object that kmalloc() gave.
int pgrp_orphaned(struct pgroup *pgrp, struct proc *gone)
Says whether a process group is orphaned (POSIX): none of its members has a parent in another group o...
int signal_pgrp_send(struct pgroup *pg, int signal)
Sends a signal to every process of a process group.
unsigned long long int uint64_t
An open file (POSIX's "open file description", fs/file.c).
A process group: the processes of a job.
struct session * session
its session
struct aquila_sigaction sigaction[SIG_MAX+1]
its signal actions
struct pgroup * pgrp
its process group, and its node on the group's list
sigset_t sigmask
its blocked signals, a bit (1 << sig) each
A session: its process groups, and its controlling terminal.
struct queue * pgps
its process groups
struct tty * ctty
its controlling terminal, or NULL
struct proc * leader
its leader, the process that made it
pid_t sid
the session's ID
A terminal, and its line discipline's state.
struct pgroup * fg
the foreground process group, or NULL
size_t size
the size of cook
ttyio master_write
writes to the master side: input, as if typed
size_t col
the output's column (for OPOST's ONOCR and ONLRET), and whether an ONLCR newline's CR was sent but no...
size_t pos
how much of cook is used
struct session * session
the session it is the controlling terminal of, or NULL
char * cook
the line being edited, in canonical mode
int stopped
whether output is stopped (IXON: VSTOP came); writes wait on start_wait for VSTART.
void * p
the device's own data
ttyio slave_write
writes to the slave side: output, for the device
void(*) input_flush(struct tty *tty)
discards the input that readers haven't read yet
int eof
how many end-of-files (VEOF at the start of a line) reads still have to return
ssize_t(*) ttyio(struct tty *tty, size_t size, void *buf)
void waitq_wakeup(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, and every thread polling it.
int waitq_sleep(struct waitq *waitq)
Puts the current thread to sleep on a wait queue until it is woken up.