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

Pseudo-terminals: /dev/ptmx and /dev/pts/N. More...

#include <core/system.h>
#include <sys/uaccess.h>
#include <core/module.h>
#include <fs/vfs.h>
#include <fs/devpts.h>
#include <fs/posix.h>
#include <dev/dev.h>
#include <dev/tty.h>
#include <sys/sched.h>
#include <aquila/errno.h>
#include <ds/ringbuf.h>

Go to the source code of this file.

Data Structures

struct  pty
 A pseudo-terminal. More...

Macros

#define PTY_BUF   4096
#define PTY_MAX   256

Functions

static struct pty * pty_get (struct devid *dd)
 Returns the pseudo-terminal of a master (major 2) or slave (major 136) device, or NULL if there is none.
ssize_t pty_master_write (struct tty *tty, size_t size, void *buf)
 Takes the terminal's output, for the master to read.
ssize_t pty_slave_write (struct tty *tty, size_t size, void *buf)
 Takes the terminal's input, after its line editing, for the slave to read.
static void pty_input_flush (struct tty *tty)
 Drops the input that the slave hasn't read (tcflush()).
static int ptm_new (struct pty *pty, struct vnode **ref)
 Makes the master's vnode: an anonymous file, in no filesystem.
static ssize_t ptm_read (struct devid *dd, off_t offset, struct iobuf *io)
 Reads the terminal's output, and wakes up the writers waiting for room.
static ssize_t ptm_write (struct devid *dd, off_t offset, struct iobuf *io)
 Writes to the terminal, as typed input.
static int pty_ioctl (struct devid *dd, int request, void *argp)
 Handles a pseudo-terminal's ioctl()s: its number (TIOCGPTN), its lock (TIOCSPTLCK), and the terminal's own.
static int pts_new (struct pty *pty, struct vnode **ref)
 Makes the slave's node, /dev/pts/N, owned by the process that opened the master.
ssize_t pts_read (struct devid *dd, off_t offset, struct iobuf *io)
 Reads the slave's input.
ssize_t pts_write (struct devid *dd, off_t offset, struct iobuf *io)
 Writes to the slave: the terminal's output.
static int pts_eof (struct file *file)
 Returns whether a read of the slave that found no data is at the end of the file (the terminal says, from its mode).
int pts_can_read (struct file *file, size_t size)
 Says whether a read of the slave wouldn't have to wait.
static int ptm_can_read (struct file *file, size_t size)
 Returns whether the master can be read: the terminal output something.
static uint64_t pts_read_timeout (struct file *file)
 Returns how long a read of the slave may wait, from the terminal's mode (VTIME), or 0 for no limit.
static int pty_id_get (void)
 Takes the first free pseudo-terminal number.
int pty_new (struct proc *proc, struct vnode **master)
 Makes a new pseudo-terminal: its rings, its terminal, its master and its slave, /dev/pts/N.
static void pty_free (struct pty *pty)
 Ends a pseudo-terminal, once its master is closed: the terminal, its /dev/pts node and its number go.
int ptmx_open (struct file *file)
 Opens /dev/ptmx: a new pseudo-terminal is made, and the file is its master instead.
static int ptm_close (struct file *file)
 Closes the master.
static int pts_open (struct file *file)
 Opens the slave, which may become the process's controlling terminal.
int pty_init ()
 Registers the pseudo-terminals' devices: the masters (major 2) and the slaves (majors 136 to 143).

Variables

static struct pty * ptys [PTY_MAX] = {0}
static char pty_ids [PTY_MAX] = {0}
struct dev ptmdev
struct dev ptsdev

Detailed Description

Pseudo-terminals: /dev/ptmx and /dev/pts/N.

A pseudo-terminal is a terminal with a program on both sides. Opening /dev/ptmx (character device 5, 2) makes a new one and gives its master side: what the program there (a terminal emulator, script, an SSH server) writes is the terminal's input, and it reads the terminal's output. The slave side, /dev/pts/N in devpts, is the terminal that a shell runs on. The terminal layer (generic.c) does the line editing in between. There is a ring each way. Closing the master's last descriptor ends the pseudo-terminal.

Definition in file pty.c.

Macro Definition Documentation

◆ PTY_BUF

#define PTY_BUF   4096

Definition at line 51 of file pty.c.

Referenced by pty_new().

◆ PTY_MAX

#define PTY_MAX   256

Definition at line 52 of file pty.c.

Referenced by pty_id_get().

Function Documentation

◆ ptm_can_read()

int ptm_can_read ( struct file * file,
size_t size )
static

Returns whether the master can be read: the terminal output something.

Definition at line 320 of file pty.c.

References pty::out, ptm_can_read(), pty_get(), and VNODE_DEV.

Referenced by ptm_can_read().

◆ ptm_close()

int ptm_close ( struct file * file)
static

Closes the master.

It is in no filesystem, so its references are counted here; the last close ends the pseudo-terminal.

Definition at line 474 of file pty.c.

References kfree(), vnode::p, ptm_close(), pty_free(), and vnode::ref.

Referenced by ptm_close().

◆ ptm_new()

int ptm_new ( struct pty * pty,
struct vnode ** ref )
static

Makes the master's vnode: an anonymous file, in no filesystem.

Returns 0, or -ENOMEM.

Definition at line 151 of file pty.c.

References DEV, pty::id, kmalloc(), M_ZERO, vnode::mode, NULL, vnode::p, ptm_new(), pty::pts_read_queue, pty::pts_write_queue, vnode::rdev, vnode::read_queue, vnode::ref, and vnode::write_queue.

Referenced by ptm_new(), and pty_new().

◆ ptm_read()

ssize_t ptm_read ( struct devid * dd,
off_t offset,
struct iobuf * io )
static

Reads the terminal's output, and wakes up the writers waiting for room.

Definition at line 172 of file pty.c.

References pty::out, ptm_read(), pty::pts_read_queue, pty_get(), iobuf::resid, and waitq_wakeup().

Referenced by ptm_read().

◆ ptm_write()

ssize_t ptm_write ( struct devid * dd,
off_t offset,
struct iobuf * io )
static

Writes to the terminal, as typed input.

Definition at line 185 of file pty.c.

References ptm_write(), pty_get(), pty::tty, tty_master_write(), and tty_write_iobuf().

Referenced by ptm_write().

◆ ptmx_open()

int ptmx_open ( struct file * file)

Opens /dev/ptmx: a new pseudo-terminal is made, and the file is its master instead.

Parameters
filethe file being opened
Returns
0, or a negative errno

Definition at line 460 of file pty.c.

References curproc, ptmx_open(), pty_new(), and vfs_close().

Referenced by ptmx_open().

◆ pts_can_read()

int pts_can_read ( struct file * file,
size_t size )

Says whether a read of the slave wouldn't have to wait.

Parameters
filethe open slave
sizehow much would be read
Returns
whether it can be read

Definition at line 310 of file pty.c.

References pty::in, pts_can_read(), pty_get(), pty::tty, tty_can_read(), and VNODE_DEV.

Referenced by pts_can_read().

◆ pts_eof()

int pts_eof ( struct file * file)
static

Returns whether a read of the slave that found no data is at the end of the file (the terminal says, from its mode).

Definition at line 297 of file pty.c.

References pts_eof(), pty_get(), pty::tty, tty_eof(), and VNODE_DEV.

Referenced by pts_eof().

◆ pts_new()

int pts_new ( struct pty * pty,
struct vnode ** ref )
static

Makes the slave's node, /dev/pts/N, owned by the process that opened the master.

Returns 0 or a negative errno.

Definition at line 219 of file pty.c.

References curproc, DEV, devpts_root, pty::id, memset(), NULL, pts_new(), pty::pts_read_queue, pty::pts_write_queue, vnode::read_queue, vnode::ref, snprintf(), vfs_vmknod(), and vnode::write_queue.

Referenced by pts_new(), and pty_new().

◆ pts_open()

int pts_open ( struct file * file)
static

Opens the slave, which may become the process's controlling terminal.

Definition at line 487 of file pty.c.

References posix_file_open(), pts_open(), pty_get(), pty::tty, tty_open(), and VNODE_DEV.

Referenced by pts_open().

◆ pts_read()

ssize_t pts_read ( struct devid * dd,
off_t offset,
struct iobuf * io )

Reads the slave's input.

A process of a background group gets SIGTTIN instead.

Parameters
ddthe device's number
offsetnot used: a terminal has no offset
iowhere to put what is read
Returns
how much was read, or a negative errno

Definition at line 253 of file pty.c.

References pty::in, pts_read(), pty::pts_read_queue, pty_get(), iobuf::resid, pty::tty, tty_background(), and waitq_wakeup().

Referenced by pts_read().

◆ pts_read_timeout()

uint64_t pts_read_timeout ( struct file * file)
static

Returns how long a read of the slave may wait, from the terminal's mode (VTIME), or 0 for no limit.

Definition at line 328 of file pty.c.

References pts_read_timeout(), pty_get(), pty::tty, tty_read_timeout(), and VNODE_DEV.

Referenced by pts_read_timeout().

◆ pts_write()

ssize_t pts_write ( struct devid * dd,
off_t offset,
struct iobuf * io )

Writes to the slave: the terminal's output.

With TOSTOP set, a process of a background group gets SIGTTOU instead.

Parameters
ddthe device's number
offsetnot used: a terminal has no offset
iowhat to write
Returns
how much was written, or a negative errno

Definition at line 280 of file pty.c.

References pts_write(), pty_get(), tty::tios, pty::tty, tty_background(), tty_slave_write(), and tty_write_iobuf().

Referenced by pts_write().

◆ pty_free()

void pty_free ( struct pty * pty)
static

Ends a pseudo-terminal, once its master is closed: the terminal, its /dev/pts node and its number go.

Definition at line 426 of file pty.c.

References devpts_root, pty::id, pty::in, kfree(), NULL, pty::out, pty::pts_read_queue, pty::pts_write_queue, pty_free(), pty_ids, ptys, vnode::read_queue, pty::slave, snprintf(), pty::tty, tty_free(), vfs_close(), vfs_vunlink(), waitq_wakeup(), and vnode::write_queue.

Referenced by ptm_close(), and pty_free().

◆ pty_get()

struct pty * pty_get ( struct devid * dd)
static

Returns the pseudo-terminal of a master (major 2) or slave (major 136) device, or NULL if there is none.

Definition at line 65 of file pty.c.

References devid::major, devid::minor, NULL, pty_get(), and ptys.

Referenced by ptm_can_read(), ptm_read(), ptm_write(), pts_can_read(), pts_eof(), pts_open(), pts_read(), pts_read_timeout(), pts_write(), pty_get(), and pty_ioctl().

◆ pty_id_get()

int pty_id_get ( void )
inlinestatic

Takes the first free pseudo-terminal number.

Returns it, or -ENOSPC if every one is taken.

Definition at line 340 of file pty.c.

References pty::id, pty_id_get(), pty_ids, and PTY_MAX.

Referenced by pty_id_get(), and pty_new().

◆ pty_init()

int pty_init ( )

Registers the pseudo-terminals' devices: the masters (major 2) and the slaves (majors 136 to 143).

Returns
0

Definition at line 504 of file pty.c.

References kdev_chrdev_register(), ptmdev, ptsdev, and pty_init().

Referenced by pty_init().

◆ pty_input_flush()

void pty_input_flush ( struct tty * tty)
static

Drops the input that the slave hasn't read (tcflush()).

Definition at line 136 of file pty.c.

References pty::in, tty::p, and pty_input_flush().

Referenced by pty_input_flush(), and pty_new().

◆ pty_ioctl()

int pty_ioctl ( struct devid * dd,
int request,
void * argp )
static

Handles a pseudo-terminal's ioctl()s: its number (TIOCGPTN), its lock (TIOCSPTLCK), and the terminal's own.

Definition at line 195 of file pty.c.

References pty::id, pty_get(), pty_ioctl(), pty::tty, and tty_ioctl().

Referenced by pty_ioctl().

◆ pty_master_write()

ssize_t pty_master_write ( struct tty * tty,
size_t size,
void * buf )

Takes the terminal's output, for the master to read.

It waits while the ring is full, until all of it is taken or a signal comes.

Parameters
ttythe terminal
sizethe output's size, in bytes
bufthe output
Returns
how much was taken, or -ERESTARTSYS if a signal came before any was

Definition at line 84 of file pty.c.

References pty::out, tty::p, pty::pts_read_queue, pty_master_write(), and waitq_sleep().

Referenced by pty_master_write(), and pty_new().

◆ pty_new()

int pty_new ( struct proc * proc,
struct vnode ** master )

Makes a new pseudo-terminal: its rings, its terminal, its master and its slave, /dev/pts/N.

Parameters
procthe process making it
masterset to the master's vnode
Returns
0, or a negative errno (-ENOSPC if every number is taken)

Definition at line 360 of file pty.c.

References tty::dev, pty::id, pty::in, tty::input_flush, kfree(), kmalloc(), M_ZERO, pty::master, NULL, pty::out, ptm_new(), ptmdev, pts_new(), PTY_BUF, pty_id_get(), pty_ids, pty_input_flush(), pty_master_write(), pty_new(), pty_slave_write(), ptys, pty::slave, pty::tty, tty_free(), tty_new(), and tty::vnode.

Referenced by ptmx_open(), and pty_new().

◆ pty_slave_write()

ssize_t pty_slave_write ( struct tty * tty,
size_t size,
void * buf )

Takes the terminal's input, after its line editing, for the slave to read.

It waits while the ring is full, until all of it is taken or a signal comes.

Parameters
ttythe terminal
sizethe input's size, in bytes
bufthe input
Returns
how much was taken, or -ERESTARTSYS if a signal came before any was

Definition at line 115 of file pty.c.

References pty::in, tty::p, pty::pts_read_queue, pty_slave_write(), and waitq_sleep().

Referenced by pty_new(), and pty_slave_write().

Variable Documentation

◆ ptmdev

struct dev ptmdev
Initial value:
= {
.name = "ptmdev",
.read = ptm_read,
.write = ptm_write,
.ioctl = pty_ioctl,
.fops = {
.open = ptmx_open,
.close = ptm_close,
.read = posix_file_read,
.write = posix_file_write,
.ioctl = posix_file_ioctl,
.can_read = ptm_can_read,
.can_write = __vfs_can_always,
.eof = __vfs_eof_never,
},
}
int posix_file_ioctl(struct file *file, int request, void *argp)
Passes an ioctl() request on to the file's vnode (a device's, or its filesystem's).
Definition ioctl.c:19
ssize_t posix_file_read(struct file *file, struct iobuf *io)
Reads from an open file at its offset, and moves the offset past what was read.
Definition read.c:29
ssize_t posix_file_write(struct file *file, struct iobuf *io)
Writes to an open file at its offset, and moves the offset past what was written.
Definition write.c:25
static int ptm_can_read(struct file *file, size_t size)
Returns whether the master can be read: the terminal output something.
Definition pty.c:320
static int pty_ioctl(struct devid *dd, int request, void *argp)
Handles a pseudo-terminal's ioctl()s: its number (TIOCGPTN), its lock (TIOCSPTLCK),...
Definition pty.c:195
static ssize_t ptm_write(struct devid *dd, off_t offset, struct iobuf *io)
Writes to the terminal, as typed input.
Definition pty.c:185
static ssize_t ptm_read(struct devid *dd, off_t offset, struct iobuf *io)
Reads the terminal's output, and wakes up the writers waiting for room.
Definition pty.c:172
int ptmx_open(struct file *file)
Opens /dev/ptmx: a new pseudo-terminal is made, and the file is its master instead.
Definition pty.c:460
static int ptm_close(struct file *file)
Closes the master.
Definition pty.c:474

Definition at line 60 of file pty.c.

Referenced by pty_init(), pty_new(), and ttydev_mux().

◆ ptsdev

struct dev ptsdev
Initial value:
= {
.name = "ptsdev",
.read = pts_read,
.write = pts_write,
.ioctl = pty_ioctl,
.fops = {
.open = pts_open,
.read = posix_file_read,
.write = posix_file_write,
.ioctl = posix_file_ioctl,
.can_read = pts_can_read,
.can_write = __vfs_can_always,
.eof = pts_eof,
.read_timeout = pts_read_timeout,
}
}
static uint64_t pts_read_timeout(struct file *file)
Returns how long a read of the slave may wait, from the terminal's mode (VTIME), or 0 for no limit.
Definition pty.c:328
static int pts_eof(struct file *file)
Returns whether a read of the slave that found no data is at the end of the file (the terminal says,...
Definition pty.c:297
ssize_t pts_read(struct devid *dd, off_t offset, struct iobuf *io)
Reads the slave's input.
Definition pty.c:253
ssize_t pts_write(struct devid *dd, off_t offset, struct iobuf *io)
Writes to the slave: the terminal's output.
Definition pty.c:280
int pts_can_read(struct file *file, size_t size)
Says whether a read of the slave wouldn't have to wait.
Definition pty.c:310
static int pts_open(struct file *file)
Opens the slave, which may become the process's controlling terminal.
Definition pty.c:487

Definition at line 61 of file pty.c.

Referenced by pty_init().

◆ pty_ids

char pty_ids[PTY_MAX] = {0}
static

Definition at line 58 of file pty.c.

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

◆ ptys

struct pty* ptys[PTY_MAX] = {0}
static

Definition at line 54 of file pty.c.

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