AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
generic.c File Reference

The terminal layer: the line discipline, and job control. More...

#include <core/system.h>
#include <core/arch.h>
#include <sys/sched.h>
#include <dev/tty.h>
#include <sys/uaccess.h>
#include <sys/signal.h>
#include <aquila/fcntl.h>

Go to the source code of this file.

Macros

#define IS_CC(tty, c, cc)

Functions

static void tty_echo (struct tty *tty, char c)
 Echoes a character, a control character as ^X.
static void tty_erase (struct tty *tty)
 Erases the last character of the line being edited, on the screen too with ECHOE.
static void tty_deliver (struct tty *tty)
 Hands the line being edited to the readers.
static int tty_signal (struct tty *tty, char c)
 Handles a signal character (with ISIG): the foreground group gets the signal.
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), and puts it through the line discipline to what programs read.
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 the start of a line), or with VMIN and VTIME both 0 in non-canonical mode.
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, otherwise until there is some.
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_background (struct tty *tty, int sig)
 Stops a background process that reads the terminal, writes it or changes it: if the current process is of the terminal's session but not of its foreground group, its group gets the signal and stops until it is continued in the foreground.
static int tty_out (struct tty *tty, const char *s, size_t n)
 Sends n bytes to the device.
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 (OPOST, POSIX's output modes): NL as CR NL (ONLCR), CR as NL (OCRNL), no CR in the first column (ONOCR), and NL returning the carriage too (ONLRET).
static void tty_release (struct tty *tty)
 Frees a terminal's memory.
static int tty_wait_start (struct tty *tty)
 Waits while the terminal's output is stopped (IXON).
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 buffer, the iobuf moved on only as far as was taken.
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 group, its window size, and becoming the controlling terminal (TIOCSCTTY).
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, OPOST with ONLCR) and the usual special characters.
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 has none (unless O_NOCTTY), if no session has it already.
void tty_hangup (struct tty *tty)
 Hangs up a controlling terminal, when its session ends (its leader exited) or the terminal goes away: its foreground group gets SIGHUP (and SIGCONT, in case it was stopped), and the terminal belongs to no session anymore.
void tty_flush (struct tty *tty, int which)
 Drops a terminal's input (TCIFLUSH, TCIOFLUSH): the line being edited, what the device holds for readers, and the pending end-of-files.
int tty_free (struct tty *tty)
 Ends a terminal: it is hung up, and freed.

Detailed Description

The terminal layer: the line discipline, and job control.

Every terminal (a virtual terminal, a serial port, a pseudo-terminal) has a struct tty between its device's two sides. The master side is the device's (the keyboard, the UART, the program on a pseudo-terminal's master), the slave side the programs that read and write the terminal. Input from the master goes through the line discipline: translation, flow control, signal characters, and in canonical mode line editing, with what is typed echoed. Output from the programs goes through output processing (OPOST) to the device. The terminal also belongs to a session, whose foreground process group may read and write it; the other groups are stopped when they try (SIGTTIN, SIGTTOU). See docs/kernel/devices.md.

Definition in file generic.c.

Macro Definition Documentation

◆ IS_CC

#define IS_CC ( tty,
c,
cc )
Value:
((tty)->tios.c_cc[cc] && (c) == (tty)->tios.c_cc[cc])
A terminal, and its line discipline's state.
Definition tty.h:25

Definition at line 30 of file generic.c.

Referenced by tty_master_write(), and tty_signal().

Function Documentation

◆ tty_background()

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 is of the terminal's session but not of its foreground group, its group gets the signal and stops until it is continued in the foreground.

Writes are only stopped with TOSTOP, which the callers check.

Parameters
ttythe terminal
sigSIGTTIN for a read, SIGTTOU for a write or a change
Returns
0 if the process may go on; -ERESTARTSYS once the signal is sent (the call returns, the group stops on its way out, and the call is made again once it is continued); or -EIO for a read with SIGTTIN ignored or blocked, or from an orphaned group

Definition at line 259 of file generic.c.

References curproc, ERESTARTSYS, tty::fg, NULL, proc::pgrp, pgrp_orphaned(), pgroup::session, tty::session, SIG_IGN, proc::sigaction, proc::sigmask, signal_pgrp_send(), and tty_background().

Referenced by pts_read(), pts_write(), tty_background(), tty_ioctl(), uart_read(), uart_write(), vt_read(), and vt_write().

◆ tty_can_read()

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.

With VMIN and VTIME 0 a read doesn't wait either, but it isn't readable without input, as on Linux and the BSDs: a program that waits for input in select() would otherwise never sleep.

Parameters
ttythe terminal
bufferedhow many bytes the device holds for readers
Returns
whether there is something to read

Definition at line 240 of file generic.c.

References tty::eof, and tty_can_read().

Referenced by pts_can_read(), tty_can_read(), uart_can_read(), and vt_can_read().

◆ tty_deliver()

void tty_deliver ( struct tty * tty)
static

Hands the line being edited to the readers.

Definition at line 64 of file generic.c.

References tty::cook, tty::pos, tty::slave_write, and tty_deliver().

Referenced by tty_deliver(), and tty_master_write().

◆ tty_echo()

void tty_echo ( struct tty * tty,
char c )
static

Echoes a character, a control character as ^X.

Definition at line 33 of file generic.c.

References tty_echo(), and tty_slave_write().

Referenced by tty_echo(), tty_master_write(), and tty_signal().

◆ tty_eof()

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 the start of a line), or with VMIN and VTIME both 0 in non-canonical mode.

An end-of-file is used up.

Parameters
ttythe terminal
Returns
1 if the read returns 0, 0 if it waits

Definition at line 200 of file generic.c.

References tty::eof, tty::tios, and tty_eof().

Referenced by pts_eof(), tty_eof(), uart_file_eof(), and vt_file_eof().

◆ tty_erase()

void tty_erase ( struct tty * tty)
static

Erases the last character of the line being edited, on the screen too with ECHOE.

Definition at line 47 of file generic.c.

References tty::cook, tty::pos, tty::tios, tty_erase(), and tty_slave_write().

Referenced by tty_erase(), and tty_master_write().

◆ tty_flush()

void tty_flush ( struct tty * tty,
int which )

Drops a terminal's input (TCIFLUSH, TCIOFLUSH): the line being edited, what the device holds for readers, and the pending end-of-files.

Output isn't kept anywhere, so there is none to drop.

Parameters
ttythe terminal
whichTCIFLUSH, TCOFLUSH or TCIOFLUSH

Definition at line 691 of file generic.c.

References tty::eof, tty::input_flush, tty::pos, and tty_flush().

Referenced by tty_flush(), and tty_ioctl().

◆ tty_free()

int tty_free ( struct tty * tty)

Ends a terminal: it is hung up, and freed.

If writers are waiting for its output to start again, they are woken up instead, and the last one frees it.

Parameters
ttythe terminal
Returns
0

Definition at line 718 of file generic.c.

References tty::gone, tty::start_wait, tty::start_waiters, tty::stopped, tty_free(), tty_hangup(), tty_release(), and waitq_wakeup().

Referenced by pty_free(), pty_new(), and tty_free().

◆ tty_hangup()

void tty_hangup ( struct tty * tty)

Hangs up a controlling terminal, when its session ends (its leader exited) or the terminal goes away: its foreground group gets SIGHUP (and SIGCONT, in case it was stopped), and the terminal belongs to no session anymore.

Parameters
ttythe terminal

Definition at line 668 of file generic.c.

References session::ctty, tty::fg, NULL, tty::session, signal_pgrp_send(), and tty_hangup().

Referenced by proc_kill(), tty_free(), and tty_hangup().

◆ tty_ioctl()

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 group, its window size, and becoming the controlling terminal (TIOCSCTTY).

Parameters
ttythe terminal
requestthe request
argpits argument, in user memory (or the value itself, for TCFLSH)
Returns
0 or what the request returns, or a negative errno (-ENOTTY for a request terminals don't have)

Definition at line 455 of file generic.c.

References session::ctty, curproc, tty::fg, session::leader, NULL, pgroup::pgid, session::pgps, queue_for, tty::session, session::sid, tty::start_wait, tty::stopped, tty::tios, tty_background(), tty_flush(), tty_ioctl(), waitq_wakeup(), and tty::ws.

Referenced by pty_ioctl(), tty_ioctl(), uart_ioctl(), and vt_ioctl().

◆ tty_master_write()

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), and puts it through the line discipline to what programs read.

Canonical mode collects lines, with erase (VERASE), kill (VKILL) and end-of-file (VEOF); otherwise, the programs get the characters as they come.

Parameters
ttythe terminal
sizethe input's size, in bytes
bufthe input
Returns
size: all of it is taken (what doesn't fit in a line is dropped)

Definition at line 111 of file generic.c.

References tty::cook, tty::eof, IS_CC, tty::pos, tty::size, tty::slave_write, tty::start_wait, tty::stopped, tty::tios, tty_deliver(), tty_echo(), tty_erase(), tty_master_write(), tty_signal(), and waitq_wakeup().

Referenced by ptm_write(), tty_master_write(), uart_receive_handler(), and vt_input_to().

◆ tty_new()

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, OPOST with ONLCR) and the usual special characters.

Parameters
procthe process making it (not used)
buf_sizethe size of its line buffer, or 0 for TTY_BUF_SIZE
masterhow the terminal sends output to its device
slavehow the terminal hands input to its readers
pthe device's own data, for those two
refset to the new terminal
Returns
0, or -ENOMEM

Definition at line 584 of file generic.c.

References tty::col, tty::cook, kfree(), kmalloc(), M_ZERO, tty::master_write, tty::nl_owed, NULL, tty::p, tty::pos, tty::size, tty::slave_write, tty::tios, TTY_BUF_SIZE, tty_new(), and tty::ws.

Referenced by pty_new(), tty_new(), uart_setup(), and vt_setup().

◆ tty_open()

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 has none (unless O_NOCTTY), if no session has it already.

Opening /dev/console doesn't do it, as on Linux: init writes there, and would otherwise take the terminal that is also the console (the first virtual terminal, or the UART) from the session that a getty starts on it.

Parameters
ttythe terminal
filethe file being opened

Definition at line 646 of file generic.c.

References session::ctty, curproc, DEV, tty::fg, file::flags, session::leader, tty::session, and tty_open().

Referenced by pts_open(), tty_open(), uart_file_open(), and vt_file_open().

◆ tty_out()

int tty_out ( struct tty * tty,
const char * s,
size_t n )
static

Sends n bytes to the device.

Returns whether it took all of them.

Definition at line 280 of file generic.c.

References tty::master_write, and tty_out().

Referenced by tty_out(), and tty_slave_write().

◆ tty_read_timeout()

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, otherwise until there is some.

Parameters
ttythe terminal
Returns
the time, in ns, or 0 for no limit

Definition at line 221 of file generic.c.

References tty::tios, and tty_read_timeout().

Referenced by pts_read_timeout(), tty_read_timeout(), uart_read_timeout(), and vt_read_timeout().

◆ tty_release()

void tty_release ( struct tty * tty)
static

Frees a terminal's memory.

Definition at line 704 of file generic.c.

References tty::cook, kfree(), and tty_release().

Referenced by tty_free(), tty_release(), and tty_wait_start().

◆ tty_signal()

int tty_signal ( struct tty * tty,
char c )
static

Handles a signal character (with ISIG): the foreground group gets the signal.

Returns whether c was one.

Definition at line 74 of file generic.c.

References tty::fg, IS_CC, tty::pos, signal_pgrp_send(), tty::tios, tty_echo(), tty_signal(), and tty_slave_write().

Referenced by tty_master_write(), and tty_signal().

◆ tty_slave_write()

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 (OPOST, POSIX's output modes): NL as CR NL (ONLCR), CR as NL (OCRNL), no CR in the first column (ONOCR), and NL returning the carriage too (ONLRET).

The column is tracked for them.

Parameters
ttythe terminal
sizethe output's size, in bytes
_bufthe output
Returns
how many bytes of it went (the device may take fewer)

Definition at line 297 of file generic.c.

References tty::col, tty::master_write, tty::nl_owed, tty::tios, tty_out(), and tty_slave_write().

Referenced by pts_write(), tty_echo(), tty_erase(), tty_signal(), tty_slave_write(), tty_write_iobuf(), uart_write(), and vt_write().

◆ tty_wait_start()

int tty_wait_start ( struct tty * tty)
static

Waits while the terminal's output is stopped (IXON).

Returns 0 once it starts again, -ERESTARTSYS for a signal, or -EIO if the terminal went away meanwhile (and its last waiter then frees it).

Definition at line 376 of file generic.c.

References tty::gone, tty::start_wait, tty::start_waiters, tty::stopped, tty_release(), tty_wait_start(), and waitq_sleep().

Referenced by tty_wait_start(), and tty_write_iobuf().

◆ tty_write_iobuf()

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 buffer, the iobuf moved on only as far as was taken.

Parameters
ttythe terminal
iowhat to write
writethe side: tty_master_write (input, from a pseudo-terminal's master) or tty_slave_write (a program's output)
Returns
how many bytes were written, or a negative errno

Definition at line 408 of file generic.c.

References iobuf_peek(), iobuf_skip(), MIN, iobuf::resid, tty::stopped, tty_slave_write(), tty_wait_start(), and tty_write_iobuf().

Referenced by ptm_write(), pts_write(), tty_write_iobuf(), uart_write(), and vt_write().