linux/drivers/tty/pty.c

// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Added support for a Unix98-style ptmx device.
 *    -- C. Scott Ananian <[email protected]>, 14-Jan-1998
 *
 */

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/fcntl.h>
#include <linux/sched/signal.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/bitops.h>
#include <linux/devpts_fs.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/mount.h>
#include <linux/file.h>
#include <linux/ioctl.h>
#include <linux/compat.h>
#include "tty.h"

#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
#define tty_debug_hangup
#else
#define tty_debug_hangup(tty, f, args...)
#endif

#ifdef CONFIG_UNIX98_PTYS
static struct tty_driver *ptm_driver;
static struct tty_driver *pts_driver;
static DEFINE_MUTEX(devpts_mutex);
#endif

static void pty_close(struct tty_struct *tty, struct file *filp)
{}

/*
 * The unthrottle routine is called by the line discipline to signal
 * that it can receive more characters.  For PTY's, the TTY_THROTTLED
 * flag is always set, to force the line discipline to always call the
 * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
 * characters in the queue.  This is necessary since each time this
 * happens, we need to wake up any sleeping processes that could be
 * (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
 * for the pty buffer to be drained.
 */
static void pty_unthrottle(struct tty_struct *tty)
{}

/**
 *	pty_write		-	write to a pty
 *	@tty: the tty we write from
 *	@buf: kernel buffer of data
 *	@c: bytes to write
 *
 *	Our "hardware" write method. Data is coming from the ldisc which
 *	may be in a non sleeping state. We simply throw this at the other
 *	end of the link as if we were an IRQ handler receiving stuff for
 *	the other side of the pty/tty pair.
 */

static ssize_t pty_write(struct tty_struct *tty, const u8 *buf, size_t c)
{}

/**
 *	pty_write_room	-	write space
 *	@tty: tty we are writing from
 *
 *	Report how many bytes the ldisc can send into the queue for
 *	the other device.
 */

static unsigned int pty_write_room(struct tty_struct *tty)
{}

/* Set the lock flag on a pty */
static int pty_set_lock(struct tty_struct *tty, int __user *arg)
{}

static int pty_get_lock(struct tty_struct *tty, int __user *arg)
{}

/* Set the packet mode on a pty */
static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
{}

/* Get the packet mode of a pty */
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
{}

/* Send a signal to the slave */
static int pty_signal(struct tty_struct *tty, int sig)
{}

static void pty_flush_buffer(struct tty_struct *tty)
{}

static int pty_open(struct tty_struct *tty, struct file *filp)
{}

static void pty_set_termios(struct tty_struct *tty,
			    const struct ktermios *old_termios)
{}

/**
 *	pty_resize		-	resize event
 *	@tty: tty being resized
 *	@ws: window size being set.
 *
 *	Update the termios variables and send the necessary signals to
 *	peform a terminal resize correctly
 */

static int pty_resize(struct tty_struct *tty,  struct winsize *ws)
{}

/**
 *	pty_start - start() handler
 *	pty_stop  - stop() handler
 *	@tty: tty being flow-controlled
 *
 *	Propagates the TIOCPKT status to the master pty.
 *
 *	NB: only the master pty can be in packet mode so only the slave
 *	    needs start()/stop() handlers
 */
static void pty_start(struct tty_struct *tty)
{}

static void pty_stop(struct tty_struct *tty)
{}

/**
 *	pty_common_install		-	set up the pty pair
 *	@driver: the pty driver
 *	@tty: the tty being instantiated
 *	@legacy: true if this is BSD style
 *
 *	Perform the initial set up for the tty/pty pair. Called from the
 *	tty layer when the port is first opened.
 *
 *	Locking: the caller must hold the tty_mutex
 */
static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
		bool legacy)
{}

static void pty_cleanup(struct tty_struct *tty)
{}

/* Traditional BSD devices */
#ifdef CONFIG_LEGACY_PTYS

static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
{}

static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
{}

static int pty_bsd_ioctl(struct tty_struct *tty,
			 unsigned int cmd, unsigned long arg)
{}

#ifdef CONFIG_COMPAT
static long pty_bsd_compat_ioctl(struct tty_struct *tty,
				 unsigned int cmd, unsigned long arg)
{}
#else
#define pty_bsd_compat_ioctl
#endif

static int legacy_count =;
/*
 * not really modular, but the easiest way to keep compat with existing
 * bootargs behaviour is to continue using module_param here.
 */
module_param(legacy_count, int, 0);

/*
 * The master side of a pty can do TIOCSPTLCK and thus
 * has pty_bsd_ioctl.
 */
static const struct tty_operations master_pty_ops_bsd =;

static const struct tty_operations slave_pty_ops_bsd =;

static void __init legacy_pty_init(void)
{}
#else
static inline void legacy_pty_init(void) { }
#endif

/* Unix98 devices */
#ifdef CONFIG_UNIX98_PTYS
static struct cdev ptmx_cdev;

/**
 *	ptm_open_peer - open the peer of a pty
 *	@master: the open struct file of the ptmx device node
 *	@tty: the master of the pty being opened
 *	@flags: the flags for open
 *
 *	Provide a race free way for userspace to open the slave end of a pty
 *	(where they have the master fd and cannot access or trust the mount
 *	namespace /dev/pts was mounted inside).
 */
int ptm_open_peer(struct file *master, struct tty_struct *tty, int flags)
{}

static int pty_unix98_ioctl(struct tty_struct *tty,
			    unsigned int cmd, unsigned long arg)
{}

#ifdef CONFIG_COMPAT
static long pty_unix98_compat_ioctl(struct tty_struct *tty,
				 unsigned int cmd, unsigned long arg)
{}
#else
#define pty_unix98_compat_ioctl
#endif

/**
 *	ptm_unix98_lookup	-	find a pty master
 *	@driver: ptm driver
 *	@file: unused
 *	@idx: tty index
 *
 *	Look up a pty master device. Called under the tty_mutex for now.
 *	This provides our locking.
 */

static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
		struct file *file, int idx)
{}

/**
 *	pts_unix98_lookup	-	find a pty slave
 *	@driver: pts driver
 *	@file: file pointer to tty
 *	@idx: tty index
 *
 *	Look up a pty master device. Called under the tty_mutex for now.
 *	This provides our locking for the tty pointer.
 */

static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
		struct file *file, int idx)
{}

static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
{}

/* this is called once with whichever end is closed last */
static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{}

static void pty_show_fdinfo(struct tty_struct *tty, struct seq_file *m)
{}

static const struct tty_operations ptm_unix98_ops =;

static const struct tty_operations pty_unix98_ops =;

/**
 *	ptmx_open		-	open a unix 98 pty master
 *	@inode: inode of device file
 *	@filp: file pointer to tty
 *
 *	Allocate a unix98 pty master device from the ptmx driver.
 *
 *	Locking: tty_mutex protects the init_dev work. tty->count should
 *		protect the rest.
 *		allocated_ptys_lock handles the list of free pty numbers
 */

static int ptmx_open(struct inode *inode, struct file *filp)
{}

static struct file_operations ptmx_fops __ro_after_init;

static void __init unix98_pty_init(void)
{}

#else
static inline void unix98_pty_init(void) { }
#endif

static int __init pty_init(void)
{}
device_initcall(pty_init);