linux/drivers/tty/tty_io.c

// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

/*
 * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
 * or rs-channels. It also implements echoing, cooked mode etc.
 *
 * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
 *
 * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
 * tty_struct and tty_queue structures.  Previously there was an array
 * of 256 tty_struct's which was statically allocated, and the
 * tty_queue structures were allocated at boot time.  Both are now
 * dynamically allocated only when the tty is open.
 *
 * Also restructured routines so that there is more of a separation
 * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
 * the low-level tty routines (serial.c, pty.c, console.c).  This
 * makes for cleaner and more compact code.  -TYT, 9/17/92
 *
 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
 * which can be dynamically activated and de-activated by the line
 * discipline handling modules (like SLIP).
 *
 * NOTE: pay no attention to the line discipline code (yet); its
 * interface is still subject to change in this version...
 * -- TYT, 1/31/92
 *
 * Added functionality to the OPOST tty handling.  No delays, but all
 * other bits should be there.
 *	-- Nick Holloway <[email protected]>, 27th May 1993.
 *
 * Rewrote canonical mode and added more termios flags.
 *	-- [email protected] (J. Cowley), 13Jan94
 *
 * Reorganized FASYNC support so mouse code can share it.
 *	-- [email protected], 9Sep95
 *
 * New TIOCLINUX variants added.
 *	-- [email protected], 19-Nov-95
 *
 * Restrict vt switching via ioctl()
 *      -- [email protected], 5-Dec-95
 *
 * Move console and virtual terminal code to more appropriate files,
 * implement CONFIG_VT and generalize console device interface.
 *	-- Marko Kohtala <[email protected]>, March 97
 *
 * Rewrote tty_init_dev and tty_release_dev to eliminate races.
 *	-- Bill Hawes <[email protected]>, June 97
 *
 * Added devfs support.
 *      -- C. Scott Ananian <[email protected]>, 13-Jan-1998
 *
 * Added support for a Unix98-style ptmx device.
 *      -- C. Scott Ananian <[email protected]>, 14-Jan-1998
 *
 * Reduced memory usage for older ARM systems
 *      -- Russell King <[email protected]>
 *
 * Move do_SAK() into process context.  Less stack use in devfs functions.
 * alloc_tty_struct() always uses kmalloc()
 *			 -- Andrew Morton <[email protected]> 17Mar01
 */

#include <linux/types.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/fcntl.h>
#include <linux/sched/signal.h>
#include <linux/sched/task.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/devpts_fs.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/console.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/kd.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/ppp-ioctl.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/ratelimit.h>
#include <linux/compat.h>
#include <linux/uaccess.h>
#include <linux/termios_internal.h>
#include <linux/fs.h>

#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>

#include <linux/kmod.h>
#include <linux/nsproxy.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

#define TTY_PARANOIA_CHECK
#define CHECK_TTY_COUNT

struct ktermios tty_std_termios =;
EXPORT_SYMBOL();

/* This list gets poked at by procfs and various bits of boot up code. This
 * could do with some rationalisation such as pulling the tty proc function
 * into this file.
 */

LIST_HEAD();			/* linked list of tty drivers */

/* Mutex to protect creating and releasing a tty */
DEFINE_MUTEX();

static ssize_t tty_read(struct kiocb *, struct iov_iter *);
static ssize_t tty_write(struct kiocb *, struct iov_iter *);
static __poll_t tty_poll(struct file *, poll_table *);
static int tty_open(struct inode *, struct file *);
#ifdef CONFIG_COMPAT
static long tty_compat_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg);
#else
#define tty_compat_ioctl
#endif
static int __tty_fasync(int fd, struct file *filp, int on);
static int tty_fasync(int fd, struct file *filp, int on);
static void release_tty(struct tty_struct *tty, int idx);

/**
 * free_tty_struct - free a disused tty
 * @tty: tty struct to free
 *
 * Free the write buffers, tty queue and tty memory itself.
 *
 * Locking: none. Must be called after tty is definitely unused
 */
static void free_tty_struct(struct tty_struct *tty)
{}

static inline struct tty_struct *file_tty(struct file *file)
{}

int tty_alloc_file(struct file *file)
{}

/* Associate a new file with the tty structure */
void tty_add_file(struct tty_struct *tty, struct file *file)
{}

/**
 * tty_free_file - free file->private_data
 * @file: to free private_data of
 *
 * This shall be used only for fail path handling when tty_add_file was not
 * called yet.
 */
void tty_free_file(struct file *file)
{}

/* Delete file from its tty */
static void tty_del_file(struct file *file)
{}

/**
 * tty_name - return tty naming
 * @tty: tty structure
 *
 * Convert a tty structure into a name. The name reflects the kernel naming
 * policy and if udev is in use may not reflect user space
 *
 * Locking: none
 */
const char *tty_name(const struct tty_struct *tty)
{}
EXPORT_SYMBOL();

const char *tty_driver_name(const struct tty_struct *tty)
{}

static int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
			      const char *routine)
{}

/* Caller must hold tty_lock */
static void check_tty_count(struct tty_struct *tty, const char *routine)
{}

/**
 * get_tty_driver - find device of a tty
 * @device: device identifier
 * @index: returns the index of the tty
 *
 * This routine returns a tty driver structure, given a device number and also
 * passes back the index number.
 *
 * Locking: caller must hold tty_mutex
 */
static struct tty_driver *get_tty_driver(dev_t device, int *index)
{}

/**
 * tty_dev_name_to_number - return dev_t for device name
 * @name: user space name of device under /dev
 * @number: pointer to dev_t that this function will populate
 *
 * This function converts device names like ttyS0 or ttyUSB1 into dev_t like
 * (4, 64) or (188, 1). If no corresponding driver is registered then the
 * function returns -%ENODEV.
 *
 * Locking: this acquires tty_mutex to protect the tty_drivers list from
 *	being modified while we are traversing it, and makes sure to
 *	release it before exiting.
 */
int tty_dev_name_to_number(const char *name, dev_t *number)
{}
EXPORT_SYMBOL_GPL();

#ifdef CONFIG_CONSOLE_POLL

/**
 * tty_find_polling_driver - find device of a polled tty
 * @name: name string to match
 * @line: pointer to resulting tty line nr
 *
 * This routine returns a tty driver structure, given a name and the condition
 * that the tty driver is capable of polled operation.
 */
struct tty_driver *tty_find_polling_driver(char *name, int *line)
{}
EXPORT_SYMBOL_GPL();
#endif

static ssize_t hung_up_tty_read(struct kiocb *iocb, struct iov_iter *to)
{}

static ssize_t hung_up_tty_write(struct kiocb *iocb, struct iov_iter *from)
{}

/* No kernel lock held - none needed ;) */
static __poll_t hung_up_tty_poll(struct file *filp, poll_table *wait)
{}

static long hung_up_tty_ioctl(struct file *file, unsigned int cmd,
		unsigned long arg)
{}

static long hung_up_tty_compat_ioctl(struct file *file,
				     unsigned int cmd, unsigned long arg)
{}

static int hung_up_tty_fasync(int fd, struct file *file, int on)
{}

static void tty_show_fdinfo(struct seq_file *m, struct file *file)
{}

static const struct file_operations tty_fops =;

static const struct file_operations console_fops =;

static const struct file_operations hung_up_tty_fops =;

static DEFINE_SPINLOCK(redirect_lock);
static struct file *redirect;

/**
 * tty_wakeup - request more data
 * @tty: terminal
 *
 * Internal and external helper for wakeups of tty. This function informs the
 * line discipline if present that the driver is ready to receive more output
 * data.
 */
void tty_wakeup(struct tty_struct *tty)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_release_redirect - Release a redirect on a pty if present
 * @tty: tty device
 *
 * This is available to the pty code so if the master closes, if the slave is a
 * redirect it can release the redirect.
 */
static struct file *tty_release_redirect(struct tty_struct *tty)
{}

/**
 * __tty_hangup - actual handler for hangup events
 * @tty: tty device
 * @exit_session: if non-zero, signal all foreground group processes
 *
 * This can be called by a "kworker" kernel thread. That is process synchronous
 * but doesn't hold any locks, so we need to make sure we have the appropriate
 * locks for what we're doing.
 *
 * The hangup event clears any pending redirections onto the hung up device. It
 * ensures future writes will error and it does the needed line discipline
 * hangup and signal delivery. The tty object itself remains intact.
 *
 * Locking:
 *  * BTM
 *
 *   * redirect lock for undoing redirection
 *   * file list lock for manipulating list of ttys
 *   * tty_ldiscs_lock from called functions
 *   * termios_rwsem resetting termios data
 *   * tasklist_lock to walk task list for hangup event
 *
 *    * ->siglock to protect ->signal/->sighand
 *
 */
static void __tty_hangup(struct tty_struct *tty, int exit_session)
{}

static void do_tty_hangup(struct work_struct *work)
{}

/**
 * tty_hangup - trigger a hangup event
 * @tty: tty to hangup
 *
 * A carrier loss (virtual or otherwise) has occurred on @tty. Schedule a
 * hangup sequence to run after this event.
 */
void tty_hangup(struct tty_struct *tty)
{}
EXPORT_SYMBOL();

/**
 * tty_vhangup - process vhangup
 * @tty: tty to hangup
 *
 * The user has asked via system call for the terminal to be hung up. We do
 * this synchronously so that when the syscall returns the process is complete.
 * That guarantee is necessary for security reasons.
 */
void tty_vhangup(struct tty_struct *tty)
{}
EXPORT_SYMBOL();


/**
 * tty_vhangup_self - process vhangup for own ctty
 *
 * Perform a vhangup on the current controlling tty
 */
void tty_vhangup_self(void)
{}

/**
 * tty_vhangup_session - hangup session leader exit
 * @tty: tty to hangup
 *
 * The session leader is exiting and hanging up its controlling terminal.
 * Every process in the foreground process group is signalled %SIGHUP.
 *
 * We do this synchronously so that when the syscall returns the process is
 * complete. That guarantee is necessary for security reasons.
 */
void tty_vhangup_session(struct tty_struct *tty)
{}

/**
 * tty_hung_up_p - was tty hung up
 * @filp: file pointer of tty
 *
 * Return: true if the tty has been subject to a vhangup or a carrier loss
 */
int tty_hung_up_p(struct file *filp)
{}
EXPORT_SYMBOL();

void __stop_tty(struct tty_struct *tty)
{}

/**
 * stop_tty - propagate flow control
 * @tty: tty to stop
 *
 * Perform flow control to the driver. May be called on an already stopped
 * device and will not re-call the &tty_driver->stop() method.
 *
 * This functionality is used by both the line disciplines for halting incoming
 * flow and by the driver. It may therefore be called from any context, may be
 * under the tty %atomic_write_lock but not always.
 *
 * Locking:
 *	flow.lock
 */
void stop_tty(struct tty_struct *tty)
{}
EXPORT_SYMBOL();

void __start_tty(struct tty_struct *tty)
{}

/**
 * start_tty - propagate flow control
 * @tty: tty to start
 *
 * Start a tty that has been stopped if at all possible. If @tty was previously
 * stopped and is now being started, the &tty_driver->start() method is invoked
 * and the line discipline woken.
 *
 * Locking:
 *	flow.lock
 */
void start_tty(struct tty_struct *tty)
{}
EXPORT_SYMBOL();

static void tty_update_time(struct tty_struct *tty, bool mtime)
{}

/*
 * Iterate on the ldisc ->read() function until we've gotten all
 * the data the ldisc has for us.
 *
 * The "cookie" is something that the ldisc read function can fill
 * in to let us know that there is more data to be had.
 *
 * We promise to continue to call the ldisc until it stops returning
 * data or clears the cookie. The cookie may be something that the
 * ldisc maintains state for and needs to free.
 */
static ssize_t iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty,
				struct file *file, struct iov_iter *to)
{}


/**
 * tty_read - read method for tty device files
 * @iocb: kernel I/O control block
 * @to: destination for the data read
 *
 * Perform the read system call function on this terminal device. Checks
 * for hung up devices before calling the line discipline method.
 *
 * Locking:
 *	Locks the line discipline internally while needed. Multiple read calls
 *	may be outstanding in parallel.
 */
static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to)
{}

void tty_write_unlock(struct tty_struct *tty)
{}

int tty_write_lock(struct tty_struct *tty, bool ndelay)
{}

/*
 * Split writes up in sane blocksizes to avoid
 * denial-of-service type attacks
 */
static ssize_t iterate_tty_write(struct tty_ldisc *ld, struct tty_struct *tty,
				 struct file *file, struct iov_iter *from)
{}

#ifdef CONFIG_PRINT_QUOTA_WARNING
/**
 * tty_write_message - write a message to a certain tty, not just the console.
 * @tty: the destination tty_struct
 * @msg: the message to write
 *
 * This is used for messages that need to be redirected to a specific tty. We
 * don't put it into the syslog queue right now maybe in the future if really
 * needed.
 *
 * We must still hold the BTM and test the CLOSING flag for the moment.
 *
 * This function is DEPRECATED, do not use in new code.
 */
void tty_write_message(struct tty_struct *tty, char *msg)
{
	if (tty) {
		mutex_lock(&tty->atomic_write_lock);
		tty_lock(tty);
		if (tty->ops->write && tty->count > 0)
			tty->ops->write(tty, msg, strlen(msg));
		tty_unlock(tty);
		tty_write_unlock(tty);
	}
}
#endif

static ssize_t file_tty_write(struct file *file, struct kiocb *iocb, struct iov_iter *from)
{}

/**
 * tty_write - write method for tty device file
 * @iocb: kernel I/O control block
 * @from: iov_iter with data to write
 *
 * Write data to a tty device via the line discipline.
 *
 * Locking:
 *	Locks the line discipline as required
 *	Writes to the tty driver are serialized by the atomic_write_lock
 *	and are then processed in chunks to the device. The line
 *	discipline write method will not be invoked in parallel for
 *	each device.
 */
static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)
{}

ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter)
{}

/**
 * tty_send_xchar - send priority character
 * @tty: the tty to send to
 * @ch: xchar to send
 *
 * Send a high priority character to the tty even if stopped.
 *
 * Locking: none for xchar method, write ordering for write method.
 */
int tty_send_xchar(struct tty_struct *tty, u8 ch)
{}

/**
 * pty_line_name - generate name for a pty
 * @driver: the tty driver in use
 * @index: the minor number
 * @p: output buffer of at least 6 bytes
 *
 * Generate a name from a @driver reference and write it to the output buffer
 * @p.
 *
 * Locking: None
 */
static void pty_line_name(struct tty_driver *driver, int index, char *p)
{}

/**
 * tty_line_name - generate name for a tty
 * @driver: the tty driver in use
 * @index: the minor number
 * @p: output buffer of at least 7 bytes
 *
 * Generate a name from a @driver reference and write it to the output buffer
 * @p.
 *
 * Locking: None
 */
static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
{}

/**
 * tty_driver_lookup_tty() - find an existing tty, if any
 * @driver: the driver for the tty
 * @file: file object
 * @idx: the minor number
 *
 * Return: the tty, if found. If not found, return %NULL or ERR_PTR() if the
 * driver lookup() method returns an error.
 *
 * Locking: tty_mutex must be held. If the tty is found, bump the tty kref.
 */
static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
		struct file *file, int idx)
{}

/**
 * tty_init_termios - helper for termios setup
 * @tty: the tty to set up
 *
 * Initialise the termios structure for this tty. This runs under the
 * %tty_mutex currently so we can be relaxed about ordering.
 */
void tty_init_termios(struct tty_struct *tty)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_standard_install - usual tty->ops->install
 * @driver: the driver for the tty
 * @tty: the tty
 *
 * If the @driver overrides @tty->ops->install, it still can call this function
 * to perform the standard install operations.
 */
int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_driver_install_tty() - install a tty entry in the driver
 * @driver: the driver for the tty
 * @tty: the tty
 *
 * Install a tty object into the driver tables. The @tty->index field will be
 * set by the time this is called. This method is responsible for ensuring any
 * need additional structures are allocated and configured.
 *
 * Locking: tty_mutex for now
 */
static int tty_driver_install_tty(struct tty_driver *driver,
						struct tty_struct *tty)
{}

/**
 * tty_driver_remove_tty() - remove a tty from the driver tables
 * @driver: the driver for the tty
 * @tty: tty to remove
 *
 * Remove a tty object from the driver tables. The tty->index field will be set
 * by the time this is called.
 *
 * Locking: tty_mutex for now
 */
static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty)
{}

/**
 * tty_reopen() - fast re-open of an open tty
 * @tty: the tty to open
 *
 * Re-opens on master ptys are not allowed and return -%EIO.
 *
 * Locking: Caller must hold tty_lock
 * Return: 0 on success, -errno on error.
 */
static int tty_reopen(struct tty_struct *tty)
{}

/**
 * tty_init_dev - initialise a tty device
 * @driver: tty driver we are opening a device on
 * @idx: device index
 *
 * Prepare a tty device. This may not be a "new" clean device but could also be
 * an active device. The pty drivers require special handling because of this.
 *
 * Locking:
 *	The function is called under the tty_mutex, which protects us from the
 *	tty struct or driver itself going away.
 *
 * On exit the tty device has the line discipline attached and a reference
 * count of 1. If a pair was created for pty/tty use and the other was a pty
 * master then it too has a reference count of 1.
 *
 * WSH 06/09/97: Rewritten to remove races and properly clean up after a failed
 * open. The new code protects the open with a mutex, so it's really quite
 * straightforward. The mutex locking can probably be relaxed for the (most
 * common) case of reopening a tty.
 *
 * Return: new tty structure
 */
struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
{}

/**
 * tty_save_termios() - save tty termios data in driver table
 * @tty: tty whose termios data to save
 *
 * Locking: Caller guarantees serialisation with tty_init_termios().
 */
void tty_save_termios(struct tty_struct *tty)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_flush_works - flush all works of a tty/pty pair
 * @tty: tty device to flush works for (or either end of a pty pair)
 *
 * Sync flush all works belonging to @tty (and the 'other' tty).
 */
static void tty_flush_works(struct tty_struct *tty)
{}

/**
 * release_one_tty - release tty structure memory
 * @work: work of tty we are obliterating
 *
 * Releases memory associated with a tty structure, and clears out the
 * driver table slots. This function is called when a device is no longer
 * in use. It also gets called when setup of a device fails.
 *
 * Locking:
 *	takes the file list lock internally when working on the list of ttys
 *	that the driver keeps.
 *
 * This method gets called from a work queue so that the driver private
 * cleanup ops can sleep (needed for USB at least)
 */
static void release_one_tty(struct work_struct *work)
{}

static void queue_release_one_tty(struct kref *kref)
{}

/**
 * tty_kref_put - release a tty kref
 * @tty: tty device
 *
 * Release a reference to the @tty device and if need be let the kref layer
 * destruct the object for us.
 */
void tty_kref_put(struct tty_struct *tty)
{}
EXPORT_SYMBOL();

/**
 * release_tty - release tty structure memory
 * @tty: tty device release
 * @idx: index of the tty device release
 *
 * Release both @tty and a possible linked partner (think pty pair),
 * and decrement the refcount of the backing module.
 *
 * Locking:
 *	tty_mutex
 *	takes the file list lock internally when working on the list of ttys
 *	that the driver keeps.
 */
static void release_tty(struct tty_struct *tty, int idx)
{}

/**
 * tty_release_checks - check a tty before real release
 * @tty: tty to check
 * @idx: index of the tty
 *
 * Performs some paranoid checking before true release of the @tty. This is a
 * no-op unless %TTY_PARANOIA_CHECK is defined.
 */
static int tty_release_checks(struct tty_struct *tty, int idx)
{}

/**
 * tty_kclose - closes tty opened by tty_kopen
 * @tty: tty device
 *
 * Performs the final steps to release and free a tty device. It is the same as
 * tty_release_struct() except that it also resets %TTY_PORT_KOPENED flag on
 * @tty->port.
 */
void tty_kclose(struct tty_struct *tty)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_release_struct - release a tty struct
 * @tty: tty device
 * @idx: index of the tty
 *
 * Performs the final steps to release and free a tty device. It is roughly the
 * reverse of tty_init_dev().
 */
void tty_release_struct(struct tty_struct *tty, int idx)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_release - vfs callback for close
 * @inode: inode of tty
 * @filp: file pointer for handle to tty
 *
 * Called the last time each file handle is closed that references this tty.
 * There may however be several such references.
 *
 * Locking:
 *	Takes BKL. See tty_release_dev().
 *
 * Even releasing the tty structures is a tricky business. We have to be very
 * careful that the structures are all released at the same time, as interrupts
 * might otherwise get the wrong pointers.
 *
 * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
 * lead to double frees or releasing memory still in use.
 */
int tty_release(struct inode *inode, struct file *filp)
{}

/**
 * tty_open_current_tty - get locked tty of current task
 * @device: device number
 * @filp: file pointer to tty
 * @return: locked tty of the current task iff @device is /dev/tty
 *
 * Performs a re-open of the current task's controlling tty.
 *
 * We cannot return driver and index like for the other nodes because devpts
 * will not work then. It expects inodes to be from devpts FS.
 */
static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp)
{}

/**
 * tty_lookup_driver - lookup a tty driver for a given device file
 * @device: device number
 * @filp: file pointer to tty
 * @index: index for the device in the @return driver
 *
 * If returned value is not erroneous, the caller is responsible to decrement
 * the refcount by tty_driver_kref_put().
 *
 * Locking: %tty_mutex protects get_tty_driver()
 *
 * Return: driver for this inode (with increased refcount)
 */
static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
		int *index)
{}

static struct tty_struct *tty_kopen(dev_t device, int shared)
{}

/**
 * tty_kopen_exclusive - open a tty device for kernel
 * @device: dev_t of device to open
 *
 * Opens tty exclusively for kernel. Performs the driver lookup, makes sure
 * it's not already opened and performs the first-time tty initialization.
 *
 * Claims the global %tty_mutex to serialize:
 *  * concurrent first-time tty initialization
 *  * concurrent tty driver removal w/ lookup
 *  * concurrent tty removal from driver table
 *
 * Return: the locked initialized &tty_struct
 */
struct tty_struct *tty_kopen_exclusive(dev_t device)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_kopen_shared - open a tty device for shared in-kernel use
 * @device: dev_t of device to open
 *
 * Opens an already existing tty for in-kernel use. Compared to
 * tty_kopen_exclusive() above it doesn't ensure to be the only user.
 *
 * Locking: identical to tty_kopen() above.
 */
struct tty_struct *tty_kopen_shared(dev_t device)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_open_by_driver - open a tty device
 * @device: dev_t of device to open
 * @filp: file pointer to tty
 *
 * Performs the driver lookup, checks for a reopen, or otherwise performs the
 * first-time tty initialization.
 *
 *
 * Claims the global tty_mutex to serialize:
 *  * concurrent first-time tty initialization
 *  * concurrent tty driver removal w/ lookup
 *  * concurrent tty removal from driver table
 *
 * Return: the locked initialized or re-opened &tty_struct
 */
static struct tty_struct *tty_open_by_driver(dev_t device,
					     struct file *filp)
{}

/**
 * tty_open - open a tty device
 * @inode: inode of device file
 * @filp: file pointer to tty
 *
 * tty_open() and tty_release() keep up the tty count that contains the number
 * of opens done on a tty. We cannot use the inode-count, as different inodes
 * might point to the same tty.
 *
 * Open-counting is needed for pty masters, as well as for keeping track of
 * serial lines: DTR is dropped when the last close happens.
 * (This is not done solely through tty->count, now.  - Ted 1/27/92)
 *
 * The termios state of a pty is reset on the first open so that settings don't
 * persist across reuse.
 *
 * Locking:
 *  * %tty_mutex protects tty, tty_lookup_driver() and tty_init_dev().
 *  * @tty->count should protect the rest.
 *  * ->siglock protects ->signal/->sighand
 *
 * Note: the tty_unlock/lock cases without a ref are only safe due to %tty_mutex
 */
static int tty_open(struct inode *inode, struct file *filp)
{}


/**
 * tty_poll - check tty status
 * @filp: file being polled
 * @wait: poll wait structures to update
 *
 * Call the line discipline polling method to obtain the poll status of the
 * device.
 *
 * Locking: locks called line discipline but ldisc poll method may be
 * re-entered freely by other callers.
 */
static __poll_t tty_poll(struct file *filp, poll_table *wait)
{}

static int __tty_fasync(int fd, struct file *filp, int on)
{}

static int tty_fasync(int fd, struct file *filp, int on)
{}

static bool tty_legacy_tiocsti __read_mostly = IS_ENABLED();
/**
 * tiocsti - fake input character
 * @tty: tty to fake input into
 * @p: pointer to character
 *
 * Fake input to a tty device. Does the necessary locking and input management.
 *
 * FIXME: does not honour flow control ??
 *
 * Locking:
 *  * Called functions take tty_ldiscs_lock
 *  * current->signal->tty check is safe without locks
 */
static int tiocsti(struct tty_struct *tty, u8 __user *p)
{}

/**
 * tiocgwinsz - implement window query ioctl
 * @tty: tty
 * @arg: user buffer for result
 *
 * Copies the kernel idea of the window size into the user buffer.
 *
 * Locking: @tty->winsize_mutex is taken to ensure the winsize data is
 * consistent.
 */
static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
{}

/**
 * tty_do_resize - resize event
 * @tty: tty being resized
 * @ws: new dimensions
 *
 * Update the termios variables and send the necessary signals to peform a
 * terminal resize correctly.
 */
int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
{}
EXPORT_SYMBOL();

/**
 * tiocswinsz - implement window size set ioctl
 * @tty: tty side of tty
 * @arg: user buffer for result
 *
 * Copies the user idea of the window size to the kernel. Traditionally this is
 * just advisory information but for the Linux console it actually has driver
 * level meaning and triggers a VC resize.
 *
 * Locking:
 *	Driver dependent. The default do_resize method takes the tty termios
 *	mutex and ctrl.lock. The console takes its own lock then calls into the
 *	default method.
 */
static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)
{}

/**
 * tioccons - allow admin to move logical console
 * @file: the file to become console
 *
 * Allow the administrator to move the redirected console device.
 *
 * Locking: uses redirect_lock to guard the redirect information
 */
static int tioccons(struct file *file)
{}

/**
 * tiocsetd - set line discipline
 * @tty: tty device
 * @p: pointer to user data
 *
 * Set the line discipline according to user request.
 *
 * Locking: see tty_set_ldisc(), this function is just a helper
 */
static int tiocsetd(struct tty_struct *tty, int __user *p)
{}

/**
 * tiocgetd - get line discipline
 * @tty: tty device
 * @p: pointer to user data
 *
 * Retrieves the line discipline id directly from the ldisc.
 *
 * Locking: waits for ldisc reference (in case the line discipline is changing
 * or the @tty is being hungup)
 */
static int tiocgetd(struct tty_struct *tty, int __user *p)
{}

/**
 * send_break - performed time break
 * @tty: device to break on
 * @duration: timeout in mS
 *
 * Perform a timed break on hardware that lacks its own driver level timed
 * break functionality.
 *
 * Locking:
 *	@tty->atomic_write_lock serializes
 */
static int send_break(struct tty_struct *tty, unsigned int duration)
{}

/**
 * tty_get_tiocm - get tiocm status register
 * @tty: tty device
 *
 * Obtain the modem status bits from the tty driver if the feature
 * is supported.
 */
int tty_get_tiocm(struct tty_struct *tty)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_tiocmget - get modem status
 * @tty: tty device
 * @p: pointer to result
 *
 * Obtain the modem status bits from the tty driver if the feature is
 * supported. Return -%ENOTTY if it is not available.
 *
 * Locking: none (up to the driver)
 */
static int tty_tiocmget(struct tty_struct *tty, int __user *p)
{}

/**
 * tty_tiocmset - set modem status
 * @tty: tty device
 * @cmd: command - clear bits, set bits or set all
 * @p: pointer to desired bits
 *
 * Set the modem status bits from the tty driver if the feature
 * is supported. Return -%ENOTTY if it is not available.
 *
 * Locking: none (up to the driver)
 */
static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd,
	     unsigned __user *p)
{}

/**
 * tty_get_icount - get tty statistics
 * @tty: tty device
 * @icount: output parameter
 *
 * Gets a copy of the @tty's icount statistics.
 *
 * Locking: none (up to the driver)
 */
int tty_get_icount(struct tty_struct *tty,
		   struct serial_icounter_struct *icount)
{}
EXPORT_SYMBOL_GPL();

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

static int tty_set_serial(struct tty_struct *tty, struct serial_struct *ss)
{}

static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user *ss)
{}

static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user *ss)
{}

/*
 * if pty, return the slave side (real_tty)
 * otherwise, return self
 */
static struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
{}

/*
 * Split this up, as gcc can choke on it otherwise..
 */
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{}

#ifdef CONFIG_COMPAT

struct serial_struct32 {};

static int compat_tty_tiocsserial(struct tty_struct *tty,
		struct serial_struct32 __user *ss)
{}

static int compat_tty_tiocgserial(struct tty_struct *tty,
			struct serial_struct32 __user *ss)
{}
static long tty_compat_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{}
#endif

static int this_tty(const void *t, struct file *file, unsigned fd)
{}

/*
 * This implements the "Secure Attention Key" ---  the idea is to
 * prevent trojan horses by killing all processes associated with this
 * tty when the user hits the "Secure Attention Key".  Required for
 * super-paranoid applications --- see the Orange Book for more details.
 *
 * This code could be nicer; ideally it should send a HUP, wait a few
 * seconds, then send a INT, and then a KILL signal.  But you then
 * have to coordinate with the init process, since all processes associated
 * with the current tty must be dead before the new getty is allowed
 * to spawn.
 *
 * Now, if it would be correct ;-/ The current code has a nasty hole -
 * it doesn't catch files in flight. We may send the descriptor to ourselves
 * via AF_UNIX socket, close it and later fetch from socket. FIXME.
 *
 * Nasty bug: do_SAK is being called in interrupt context.  This can
 * deadlock.  We punt it up to process context.  AKPM - 16Mar2001
 */
void __do_SAK(struct tty_struct *tty)
{}

static void do_SAK_work(struct work_struct *work)
{}

/*
 * The tq handling here is a little racy - tty->SAK_work may already be queued.
 * Fortunately we don't need to worry, because if ->SAK_work is already queued,
 * the values which we write to it will be identical to the values which it
 * already has. --akpm
 */
void do_SAK(struct tty_struct *tty)
{}
EXPORT_SYMBOL();

/* Must put_device() after it's unused! */
static struct device *tty_get_device(struct tty_struct *tty)
{}


/**
 * alloc_tty_struct - allocate a new tty
 * @driver: driver which will handle the returned tty
 * @idx: minor of the tty
 *
 * This subroutine allocates and initializes a tty structure.
 *
 * Locking: none - @tty in question is not exposed at this point
 */
struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
{}

/**
 * tty_put_char - write one character to a tty
 * @tty: tty
 * @ch: character to write
 *
 * Write one byte to the @tty using the provided @tty->ops->put_char() method
 * if present.
 *
 * Note: the specific put_char operation in the driver layer may go
 * away soon. Don't call it directly, use this method
 *
 * Return: the number of characters successfully output.
 */
int tty_put_char(struct tty_struct *tty, u8 ch)
{}
EXPORT_SYMBOL_GPL();

static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
		unsigned int index, unsigned int count)
{}

/**
 * tty_register_device - register a tty device
 * @driver: the tty driver that describes the tty device
 * @index: the index in the tty driver for this tty device
 * @device: a struct device that is associated with this tty device.
 *	This field is optional, if there is no known struct device
 *	for this tty device it can be set to NULL safely.
 *
 * This call is required to be made to register an individual tty device
 * if the tty driver's flags have the %TTY_DRIVER_DYNAMIC_DEV bit set.  If
 * that bit is not set, this function should not be called by a tty
 * driver.
 *
 * Locking: ??
 *
 * Return: A pointer to the struct device for this tty device (or
 * ERR_PTR(-EFOO) on error).
 */
struct device *tty_register_device(struct tty_driver *driver, unsigned index,
				   struct device *device)
{}
EXPORT_SYMBOL();

static void tty_device_create_release(struct device *dev)
{}

/**
 * tty_register_device_attr - register a tty device
 * @driver: the tty driver that describes the tty device
 * @index: the index in the tty driver for this tty device
 * @device: a struct device that is associated with this tty device.
 *	This field is optional, if there is no known struct device
 *	for this tty device it can be set to %NULL safely.
 * @drvdata: Driver data to be set to device.
 * @attr_grp: Attribute group to be set on device.
 *
 * This call is required to be made to register an individual tty device if the
 * tty driver's flags have the %TTY_DRIVER_DYNAMIC_DEV bit set. If that bit is
 * not set, this function should not be called by a tty driver.
 *
 * Locking: ??
 *
 * Return: A pointer to the struct device for this tty device (or
 * ERR_PTR(-EFOO) on error).
 */
struct device *tty_register_device_attr(struct tty_driver *driver,
				   unsigned index, struct device *device,
				   void *drvdata,
				   const struct attribute_group **attr_grp)
{}
EXPORT_SYMBOL_GPL();

/**
 * tty_unregister_device - unregister a tty device
 * @driver: the tty driver that describes the tty device
 * @index: the index in the tty driver for this tty device
 *
 * If a tty device is registered with a call to tty_register_device() then
 * this function must be called when the tty device is gone.
 *
 * Locking: ??
 */
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{}
EXPORT_SYMBOL();

/**
 * __tty_alloc_driver - allocate tty driver
 * @lines: count of lines this driver can handle at most
 * @owner: module which is responsible for this driver
 * @flags: some of %TTY_DRIVER_ flags, will be set in driver->flags
 *
 * This should not be called directly, some of the provided macros should be
 * used instead. Use IS_ERR() and friends on @retval.
 */
struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,
		unsigned long flags)
{}
EXPORT_SYMBOL();

static void destruct_tty_driver(struct kref *kref)
{}

/**
 * tty_driver_kref_put - drop a reference to a tty driver
 * @driver: driver of which to drop the reference
 *
 * The final put will destroy and free up the driver.
 */
void tty_driver_kref_put(struct tty_driver *driver)
{}
EXPORT_SYMBOL();

/**
 * tty_register_driver - register a tty driver
 * @driver: driver to register
 *
 * Called by a tty driver to register itself.
 */
int tty_register_driver(struct tty_driver *driver)
{}
EXPORT_SYMBOL();

/**
 * tty_unregister_driver - unregister a tty driver
 * @driver: driver to unregister
 *
 * Called by a tty driver to unregister itself.
 */
void tty_unregister_driver(struct tty_driver *driver)
{}
EXPORT_SYMBOL();

dev_t tty_devnum(struct tty_struct *tty)
{}
EXPORT_SYMBOL();

void tty_default_fops(struct file_operations *fops)
{}

static char *tty_devnode(const struct device *dev, umode_t *mode)
{}

const struct class tty_class =;

static int __init tty_class_init(void)
{}

postcore_initcall(tty_class_init);

/* 3/2004 jmc: why do these devices exist? */
static struct cdev tty_cdev, console_cdev;

static ssize_t show_cons_active(struct device *dev,
				struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR(active, S_IRUGO, show_cons_active, NULL);

static struct attribute *cons_dev_attrs[] =;

ATTRIBUTE_GROUPS();

static struct device *consdev;

void console_sysfs_notify(void)
{}

static struct ctl_table tty_table[] =;

/*
 * Ok, now we can initialize the rest of the tty devices and can count
 * on memory allocations, interrupts etc..
 */
int __init tty_init(void)
{}