cregit-Linux how code gets into the kernel

Release 4.7 drivers/tty/pty.c

Directory: drivers/tty
/*
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Added support for a Unix98-style ptmx device.
 *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 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.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>


#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP

# define tty_debug_hangup(tty, f, args...)	tty_debug(tty, f, ##args)
#else

# define tty_debug_hangup(tty, f, args...)	do {} while (0)
#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) { BUG_ON(!tty); if (tty->driver->subtype == PTY_TYPE_MASTER) WARN_ON(tty->count > 1); else { if (tty_io_error(tty)) return; if (tty->count > 2) return; } set_bit(TTY_IO_ERROR, &tty->flags); wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); spin_lock_irq(&tty->ctrl_lock); tty->packet = 0; spin_unlock_irq(&tty->ctrl_lock); /* Review - krefs on tty_link ?? */ if (!tty->link) return; set_bit(TTY_OTHER_CLOSED, &tty->link->flags); wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); if (tty->driver->subtype == PTY_TYPE_MASTER) { set_bit(TTY_OTHER_CLOSED, &tty->flags); #ifdef CONFIG_UNIX98_PTYS if (tty->driver == ptm_driver) { mutex_lock(&devpts_mutex); if (tty->link->driver_data) devpts_pty_kill(tty->link->driver_data); mutex_unlock(&devpts_mutex); } #endif tty_vhangup(tty->link); } }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git13259.19%1348.15%
peter hurleypeter hurley4218.83%414.81%
alan coxalan cox219.42%311.11%
greg kroah-hartmangreg kroah-hartman135.83%13.70%
zou nan haizou nan hai62.69%13.70%
brian bloniarzbrian bloniarz31.35%13.70%
al viroal viro20.90%13.70%
jiri slabyjiri slaby20.90%13.70%
sukadev bhattiprolusukadev bhattiprolu10.45%13.70%
arnd bergmannarnd bergmann10.45%13.70%
Total223100.00%27100.00%

/* * 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) { tty_wakeup(tty->link); set_bit(TTY_THROTTLED, &tty->flags); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git2692.86%150.00%
alan coxalan cox27.14%150.00%
Total28100.00%2100.00%

/** * pty_write - write to a pty * @tty: the tty we write from * @buf: kernel buffer of data * @count: 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 int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) { struct tty_struct *to = tty->link; if (tty->stopped) return 0; if (c > 0) { /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to->port, buf, c); /* And shovel */ if (c) tty_flip_buffer_push(to->port); } return c; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git5573.33%650.00%
alan coxalan cox1013.33%216.67%
linus torvaldslinus torvalds68.00%216.67%
jiri slabyjiri slaby45.33%216.67%
Total75100.00%12100.00%

/** * 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 int pty_write_room(struct tty_struct *tty) { if (tty->stopped) return 0; return tty_buffer_space_avail(tty->link->port); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git1550.00%240.00%
linus torvaldslinus torvalds930.00%120.00%
alan coxalan cox310.00%120.00%
peter hurleypeter hurley310.00%120.00%
Total30100.00%5100.00%

/** * pty_chars_in_buffer - characters currently in our tx queue * @tty: our tty * * Report how much we have in the transmit queue. As everything is * instantly at the other end this is easy to implement. */
static int pty_chars_in_buffer(struct tty_struct *tty) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git14100.00%3100.00%
Total14100.00%3100.00%

/* Set the lock flag on a pty */
static int pty_set_lock(struct tty_struct *tty, int __user *arg) { int val; if (get_user(val, arg)) return -EFAULT; if (val) set_bit(TTY_PTY_LOCK, &tty->flags); else clear_bit(TTY_PTY_LOCK, &tty->flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git5998.33%150.00%
al viroal viro11.67%150.00%
Total60100.00%2100.00%


static int pty_get_lock(struct tty_struct *tty, int __user *arg) { int locked = test_bit(TTY_PTY_LOCK, &tty->flags); return put_user(locked, arg); }

Contributors

PersonTokensPropCommitsCommitProp
cyrill gorcunovcyrill gorcunov37100.00%1100.00%
Total37100.00%1100.00%

/* Set the packet mode on a pty */
static int pty_set_pktmode(struct tty_struct *tty, int __user *arg) { int pktmode; if (get_user(pktmode, arg)) return -EFAULT; spin_lock_irq(&tty->ctrl_lock); if (pktmode) { if (!tty->packet) { tty->link->ctrl_status = 0; smp_mb(); tty->packet = 1; } } else tty->packet = 0; spin_unlock_irq(&tty->ctrl_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
cyrill gorcunovcyrill gorcunov7987.78%133.33%
peter hurleypeter hurley1112.22%266.67%
Total90100.00%3100.00%

/* Get the packet mode of a pty */
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg) { int pktmode = tty->packet; return put_user(pktmode, arg); }

Contributors

PersonTokensPropCommitsCommitProp
cyrill gorcunovcyrill gorcunov31100.00%1100.00%
Total31100.00%1100.00%

/* Send a signal to the slave */
static int pty_signal(struct tty_struct *tty, int sig) { struct pid *pgrp; if (sig != SIGINT && sig != SIGQUIT && sig != SIGTSTP) return -EINVAL; if (tty->link) { pgrp = tty_get_pgrp(tty->link); if (pgrp) kill_pgrp(pgrp, sig, 1); put_pid(pgrp); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
howard chuhoward chu5269.33%133.33%
peter hurleypeter hurley2330.67%266.67%
Total75100.00%3100.00%


static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; struct tty_ldisc *ld; if (!to) return; ld = tty_ldisc_ref(to); tty_buffer_flush(to, ld); if (ld) tty_ldisc_deref(ld); if (to->packet) { spin_lock_irq(&tty->ctrl_lock); tty->ctrl_status |= TIOCPKT_FLUSHWRITE; wake_up_interruptible(&to->read_wait); spin_unlock_irq(&tty->ctrl_lock); } }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git4852.17%350.00%
peter hurleypeter hurley3032.61%233.33%
alan coxalan cox1415.22%116.67%
Total92100.00%6100.00%


static int pty_open(struct tty_struct *tty, struct file *filp) { if (!tty || !tty->link) return -ENODEV; if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) goto out; if (test_bit(TTY_PTY_LOCK, &tty->link->flags)) goto out; if (tty->driver->subtype == PTY_TYPE_SLAVE && tty->link->count != 1) goto out; clear_bit(TTY_IO_ERROR, &tty->flags); clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); set_bit(TTY_THROTTLED, &tty->flags); return 0; out: set_bit(TTY_IO_ERROR, &tty->flags); return -EIO; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git9973.88%975.00%
peter hurleypeter hurley3526.12%325.00%
Total134100.00%12100.00%


static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty); int old_flow = ((old_termios->c_iflag & IXON) && (old_termios->c_cc[VSTOP] == '\023') && (old_termios->c_cc[VSTART] == '\021')); int new_flow = (I_IXON(tty) && STOP_CHAR(tty) == '\023' && START_CHAR(tty) == '\021'); if ((old_flow != new_flow) || extproc) { spin_lock_irq(&tty->ctrl_lock); if (old_flow != new_flow) { tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); if (new_flow) tty->ctrl_status |= TIOCPKT_DOSTOP; else tty->ctrl_status |= TIOCPKT_NOSTOP; } if (extproc) tty->ctrl_status |= TIOCPKT_IOCTL; spin_unlock_irq(&tty->ctrl_lock); wake_up_interruptible(&tty->link->read_wait); } } tty->termios.c_cflag &= ~(CSIZE | PARENB); tty->termios.c_cflag |= (CS8 | CREAD); }

Contributors

PersonTokensPropCommitsCommitProp
peter hurleypeter hurley17480.93%350.00%
pre-gitpre-git3817.67%116.67%
alan coxalan cox31.40%233.33%
Total215100.00%6100.00%

/** * pty_do_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) { struct pid *pgrp, *rpgrp; struct tty_struct *pty = tty->link; /* For a PTY we need to lock the tty side */ mutex_lock(&tty->winsize_mutex); if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; /* Signal the foreground process group of both ptys */ pgrp = tty_get_pgrp(tty); rpgrp = tty_get_pgrp(pty); if (pgrp) kill_pgrp(pgrp, SIGWINCH, 1); if (rpgrp != pgrp && rpgrp) kill_pgrp(rpgrp, SIGWINCH, 1); put_pid(pgrp); put_pid(rpgrp); tty->winsize = *ws; pty->winsize = *ws; /* Never used so will go away soon */ done: mutex_unlock(&tty->winsize_mutex); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
alan coxalan cox13994.56%125.00%
peter hurleypeter hurley74.76%250.00%
josh triplettjosh triplett10.68%125.00%
Total147100.00%4100.00%

/** * 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) { unsigned long flags; if (tty->link && tty->link->packet) { spin_lock_irqsave(&tty->ctrl_lock, flags); tty->ctrl_status &= ~TIOCPKT_STOP; tty->ctrl_status |= TIOCPKT_START; spin_unlock_irqrestore(&tty->ctrl_lock, flags); wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); } }

Contributors

PersonTokensPropCommitsCommitProp
peter hurleypeter hurley74100.00%2100.00%
Total74100.00%2100.00%


static void pty_stop(struct tty_struct *tty) { unsigned long flags; if (tty->link && tty->link->packet) { spin_lock_irqsave(&tty->ctrl_lock, flags); tty->ctrl_status &= ~TIOCPKT_START; tty->ctrl_status |= TIOCPKT_STOP; spin_unlock_irqrestore(&tty->ctrl_lock, flags); wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); } }

Contributors

PersonTokensPropCommitsCommitProp
peter hurleypeter hurley74100.00%2100.00%
Total74100.00%2100.00%

/** * 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) { struct tty_struct *o_tty; struct tty_port *ports[2]; int idx = tty->index; int retval = -ENOMEM; /* Opening the slave first has always returned -EIO */ if (driver->subtype != PTY_TYPE_MASTER) return -EIO; ports[0] = kmalloc(sizeof **ports, GFP_KERNEL); ports[1] = kmalloc(sizeof **ports, GFP_KERNEL); if (!ports[0] || !ports[1]) goto err; if (!try_module_get(driver->other->owner)) { /* This cannot in fact currently happen */ goto err; } o_tty = alloc_tty_struct(driver->other, idx); if (!o_tty) goto err_put_module; tty_set_lock_subclass(o_tty); lockdep_set_subclass(&o_tty->termios_rwsem, TTY_LOCK_SLAVE); if (legacy) { /* We always use new tty termios data so we can do this the easy way .. */ tty_init_termios(tty); tty_init_termios(o_tty); driver->other->ttys[idx] = o_tty; driver->ttys[idx] = tty; } else { memset(&tty->termios_locked, 0, sizeof(tty->termios_locked)); tty->termios = driver->init_termios; memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked)); o_tty->termios = driver->other->init_termios; } /* * Everything allocated ... set up the o_tty structure. */ tty_driver_kref_get(driver->other); /* Establish the links in both directions */ tty->link = o_tty; o_tty->link = tty; tty_port_init(ports[0]); tty_port_init(ports[1]); tty_buffer_set_limit(ports[0], 8192); tty_buffer_set_limit(ports[1], 8192); o_tty->port = ports[0]; tty->port = ports[1]; o_tty->port->itty = o_tty; tty_buffer_set_lock_subclass(o_tty->port); tty_driver_kref_get(driver); tty->count++; o_tty->count++; return 0; err_put_module: module_put(driver->other->owner); err: kfree(ports[0]); kfree(ports[1]); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
jiri slabyjiri slaby17143.96%430.77%
alan coxalan cox14035.99%215.38%
peter hurleypeter hurley6015.42%538.46%
rasmus villemoesrasmus villemoes184.63%215.38%
Total389100.00%13100.00%


static void pty_cleanup(struct tty_struct *tty) { tty_port_put(tty->port); }

Contributors

PersonTokensPropCommitsCommitProp
jiri slabyjiri slaby18100.00%2100.00%
Total18100.00%2100.00%

/* Traditional BSD devices */ #ifdef CONFIG_LEGACY_PTYS
static int pty_install(struct tty_driver *driver, struct tty_struct *tty) { return pty_common_install(driver, tty, true); }

Contributors

PersonTokensPropCommitsCommitProp
jiri slabyjiri slaby26100.00%1100.00%
Total26100.00%1100.00%


static void pty_remove(struct tty_driver *driver, struct tty_struct *tty) { struct tty_struct *pair = tty->link; driver->ttys[tty->index] = NULL; if (pair) pair->driver->ttys[pair->index] = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
alan coxalan cox53100.00%1100.00%
Total53100.00%1100.00%


static int pty_bsd_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { switch (cmd) { case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ return pty_set_lock(tty, (int __user *) arg); case TIOCGPTLCK: /* Get PT Lock status */ return pty_get_lock(tty, (int __user *)arg); case TIOCPKT: /* Set PT packet mode */ return pty_set_pktmode(tty, (int __user *)arg); case TIOCGPKT: /* Get PT packet mode */ return pty_get_pktmode(tty, (int __user *)arg); case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg); case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */ return -EINVAL; } return -ENOIOCTLCMD; }

Contributors

PersonTokensPropCommitsCommitProp
cyrill gorcunovcyrill gorcunov5142.50%233.33%
christoph hellwigchristoph hellwig3730.83%116.67%
howard chuhoward chu1512.50%116.67%
andrew mortonandrew morton97.50%116.67%
jiri slabyjiri slaby86.67%116.67%
Total120100.00%6100.00%

static int legacy_count = CONFIG_LEGACY_PTY_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 = { .install = pty_install, .open = pty_open, .close = pty_close, .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .ioctl = pty_bsd_ioctl, .cleanup = pty_cleanup, .resize = pty_resize, .remove = pty_remove }; static const struct tty_operations slave_pty_ops_bsd = { .install = pty_install, .open = pty_open, .close = pty_close, .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, .cleanup = pty_cleanup, .resize = pty_resize, .start = pty_start, .stop = pty_stop, .remove = pty_remove };
static void __init legacy_pty_init(void) { struct tty_driver *pty_driver, *pty_slave_driver; if (legacy_count <= 0) return; pty_driver = tty_alloc_driver(legacy_count, TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(pty_driver)) panic("Couldn't allocate pty driver"); pty_slave_driver = tty_alloc_driver(legacy_count, TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(pty_slave_driver)) panic("Couldn't allocate pty slave driver"); pty_driver->driver_name = "pty_master"; pty_driver->name = "pty"; pty_driver->major = PTY_MASTER_MAJOR; pty_driver->minor_start = 0; pty_driver->type = TTY_DRIVER_TYPE_PTY; pty_driver->subtype = PTY_TYPE_MASTER; pty_driver->init_termios = tty_std_termios; pty_driver->init_termios.c_iflag = 0; pty_driver->init_termios.c_oflag = 0; pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pty_driver->init_termios.c_lflag = 0; pty_driver->init_termios.c_ispeed = 38400; pty_driver->init_termios.c_ospeed = 38400; pty_driver->other = pty_slave_driver; tty_set_operations(pty_driver, &master_pty_ops_bsd); pty_slave_driver->driver_name = "pty_slave"; pty_slave_driver->name = "ttyp"; pty_slave_driver->major = PTY_SLAVE_MAJOR; pty_slave_driver->minor_start = 0; pty_slave_driver->type = TTY_DRIVER_TYPE_PTY; pty_slave_driver->subtype = PTY_TYPE_SLAVE; pty_slave_driver->init_termios = tty_std_termios; pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pty_slave_driver->init_termios.c_ispeed = 38400; pty_slave_driver->init_termios.c_ospeed = 38400; pty_slave_driver->other = pty_driver; tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd); if (tty_register_driver(pty_driver)) panic("Couldn't register pty driver"); if (tty_register_driver(pty_slave_driver)) panic("Couldn't register pty slave driver"); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git15453.10%1052.63%
al viroal viro5920.34%15.26%
alan coxalan cox3211.03%15.26%
jiri slabyjiri slaby144.83%15.26%
linus torvaldslinus torvalds103.45%15.26%
kay sieverskay sievers93.10%15.26%
dan carpenterdan carpenter62.07%15.26%
andrew mortonandrew morton31.03%210.53%
christoph hellwigchristoph hellwig31.03%15.26%
Total290100.00%19100.00%

#else
static inline void legacy_pty_init(void) { }

Contributors

PersonTokensPropCommitsCommitProp
christoph hellwigchristoph hellwig8100.00%1100.00%
Total8100.00%1100.00%

#endif /* Unix98 devices */ #ifdef CONFIG_UNIX98_PTYS static struct cdev ptmx_cdev;
static int pty_unix98_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { switch (cmd) { case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ return pty_set_lock(tty, (int __user *)arg); case TIOCGPTLCK: /* Get PT Lock status */ return pty_get_lock(tty, (int __user *)arg); case TIOCPKT: /* Set PT packet mode */ return pty_set_pktmode(tty, (int __user *)arg); case TIOCGPKT: /* Get PT packet mode */ return pty_get_pktmode(tty, (int __user *)arg); case TIOCGPTN: /* Get PT Number */ return put_user(tty->index, (unsigned int __user *)arg); case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg); } return -ENOIOCTLCMD; }

Contributors

PersonTokensPropCommitsCommitProp
christoph hellwigchristoph hellwig6650.00%125.00%
cyrill gorcunovcyrill gorcunov5138.64%250.00%
howard chuhoward chu1511.36%125.00%
Total132100.00%4100.00%

/** * ptm_unix98_lookup - find a pty master * @driver: ptm driver * @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) { /* Master must be open via /dev/ptmx */ return ERR_PTR(-EIO); }

Contributors

PersonTokensPropCommitsCommitProp
alan coxalan cox1965.52%125.00%
konstantin khlebnikovkonstantin khlebnikov517.24%125.00%
sukadev bhattiprolusukadev bhattiprolu310.34%125.00%
linus torvaldslinus torvalds26.90%125.00%
Total29100.00%4100.00%

/** * pts_unix98_lookup - find a pty slave * @driver: pts driver * @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) { struct tty_struct *tty; mutex_lock(&devpts_mutex); tty = devpts_get_priv(file->f_path.dentry); mutex_unlock(&devpts_mutex); /* Master must be open before slave */ if (!tty) return ERR_PTR(-EIO); return tty; }

Contributors

PersonTokensPropCommitsCommitProp
alan coxalan cox5483.08%240.00%
linus torvaldslinus torvalds710.77%120.00%
sukadev bhattiprolusukadev bhattiprolu34.62%120.00%
jiri slabyjiri slaby11.54%120.00%
Total65100.00%5100.00%


static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) { return pty_common_install(driver, tty, false); }

Contributors

PersonTokensPropCommitsCommitProp
alan coxalan cox2492.31%266.67%
jiri slabyjiri slaby27.69%133.33%
Total26100.00%3100.00%

/* this is called once with whichever end is closed last */
static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) { struct pts_fs_info *fsi; if (tty->driver->subtype == PTY_TYPE_MASTER) fsi = tty->driver_data; else fsi = tty->link->driver_data; if (fsi) { devpts_kill_index(fsi, tty->index); devpts_release(fsi); } }

Contributors

PersonTokensPropCommitsCommitProp
herton ronaldo krzesinskiherton ronaldo krzesinski2842.42%112.50%
jiri slabyjiri slaby2334.85%337.50%
linus torvaldslinus torvalds69.09%112.50%
colin kingcolin king69.09%112.50%
alan coxalan cox23.03%112.50%
eric w. biedermaneric w. biederman11.52%112.50%
Total66100.00%8100.00%

static const struct tty_operations ptm_unix98_ops = { .lookup = ptm_unix98_lookup, .install = pty_unix98_install, .remove = pty_unix98_remove, .open = pty_open, .close = pty_close, .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .ioctl = pty_unix98_ioctl, .resize = pty_resize, .cleanup = pty_cleanup }; static const struct tty_operations pty_unix98_ops = { .lookup = pts_unix98_lookup, .install = pty_unix98_install, .remove = pty_unix98_remove, .open = pty_open, .close = pty_close, .write = pty_write, .write_room = pty_write_room, .flush_buffer = pty_flush_buffer, .chars_in_buffer = pty_chars_in_buffer, .unthrottle = pty_unthrottle, .set_termios = pty_set_termios, .start = pty_start, .stop = pty_stop, .cleanup = pty_cleanup, }; /** * 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) { struct pts_fs_info *fsi; struct tty_struct *tty; struct dentry *dentry; int retval; int index; nonseekable_open(inode, filp); /* We refuse fsnotify events on ptmx, since it's a shared resource */ filp->f_mode |= FMODE_NONOTIFY; retval = tty_alloc_file(filp); if (retval) return retval; fsi = devpts_acquire(filp); if (IS_ERR(fsi)) { retval = PTR_ERR(fsi); goto out_free_file; } /* find a device that is not in use. */ mutex_lock(&devpts_mutex); index = devpts_new_index(fsi); mutex_unlock(&devpts_mutex); retval = index; if (index < 0) goto out_put_fsi; mutex_lock(&tty_mutex); tty = tty_init_dev(ptm_driver, index); /* The tty returned here is locked so we can safely drop the mutex */ mutex_unlock(&tty_mutex); retval = PTR_ERR(tty); if (IS_ERR(tty)) goto out; /* * From here on out, the tty is "live", and the index and * fsi will be killed/put by the tty_release() */ set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty->driver_data = fsi; tty_add_file(tty, filp); dentry = devpts_pty_new(fsi, index, tty->link); if (IS_ERR(dentry)) { retval = PTR_ERR(dentry); goto err_release; } tty->link->driver_data = dentry; retval = ptm_driver->ops->open(tty, filp); if (retval) goto err_release; tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); tty_unlock(tty); return 0; err_release: tty_unlock(tty); // This will also put-ref the fsi tty_release(inode, filp); return retval; out: devpts_kill_index(fsi, index); out_put_fsi: devpts_release(fsi); out_free_file: tty_free_file(filp); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
alan coxalan cox14646.95%626.09%
linus torvaldslinus torvalds6520.90%313.04%
jiri slabyjiri slaby4213.50%417.39%
peter hurleypeter hurley227.07%313.04%
eric w. biedermaneric w. biederman165.14%14.35%
arnd bergmannarnd bergmann82.57%14.35%
nick pigginnick piggin61.93%28.70%
sukadev bhattiprolusukadev bhattiprolu41.29%14.35%
greg kroah-hartmangreg kroah-hartman10.32%14.35%
herton ronaldo krzesinskiherton ronaldo krzesinski10.32%14.35%
Total311100.00%23100.00%

static struct file_operations ptmx_fops;
static void __init unix98_pty_init(void) { ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX, TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM | TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(ptm_driver)) panic("Couldn't allocate Unix98 ptm driver"); pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX, TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM | TTY_DRIVER_DYNAMIC_ALLOC); if (IS_ERR(pts_driver)) panic("Couldn't allocate Unix98 pts driver"); ptm_driver->driver_name = "pty_master"; ptm_driver->name = "ptm"; ptm_driver->major = UNIX98_PTY_MASTER_MAJOR; ptm_driver->minor_start = 0; ptm_driver->type = TTY_DRIVER_TYPE_PTY; ptm_driver->subtype = PTY_TYPE_MASTER; ptm_driver->init_termios = tty_std_termios; ptm_driver->init_termios.c_iflag = 0; ptm_driver->init_termios.c_oflag = 0; ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; ptm_driver->init_termios.c_lflag = 0; ptm_driver->init_termios.c_ispeed = 38400; ptm_driver->init_termios.c_ospeed = 38400; ptm_driver->other = pts_driver; tty_set_operations(ptm_driver, &ptm_unix98_ops); pts_driver->driver_name = "pty_slave"; pts_driver->name = "pts"; pts_driver->major = UNIX98_PTY_SLAVE_MAJOR; pts_driver->minor_start = 0; pts_driver->type = TTY_DRIVER_TYPE_PTY; pts_driver->subtype = PTY_TYPE_SLAVE; pts_driver->init_termios = tty_std_termios; pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pts_driver->init_termios.c_ispeed = 38400; pts_driver->init_termios.c_ospeed = 38400; pts_driver->other = ptm_driver; tty_set_operations(pts_driver, &pty_unix98_ops); if (tty_register_driver(ptm_driver)) panic("Couldn't register Unix98 ptm driver"); if (tty_register_driver(pts_driver)) panic("Couldn't register Unix98 pts driver"); /* Now create the /dev/ptmx special device */ tty_default_fops(&ptmx_fops); ptmx_fops.open = ptmx_open; cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver"); device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro12534.63%211.11%
alan coxalan cox11130.75%422.22%
pre-gitpre-git8523.55%738.89%
jiri slabyjiri slaby226.09%15.56%
christoph hellwigchristoph hellwig92.49%15.56%
dan carpenterdan carpenter61.66%15.56%
andrew mortonandrew morton20.55%15.56%
cong dingcong ding10.28%15.56%
Total361100.00%18100.00%

#else
static inline void unix98_pty_init(void) { }

Contributors

PersonTokensPropCommitsCommitProp
christoph hellwigchristoph hellwig8100.00%1100.00%
Total8100.00%1100.00%

#endif
static int __init pty_init(void) { legacy_pty_init(); unix98_pty_init(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
christoph hellwigchristoph hellwig1477.78%133.33%
pre-gitpre-git422.22%266.67%
Total18100.00%3100.00%

device_initcall(pty_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
alan coxalan cox99826.33%2115.11%
pre-gitpre-git78620.73%3323.74%
peter hurleypeter hurley61416.20%2417.27%
jiri slabyjiri slaby3579.42%1712.23%
cyrill gorcunovcyrill gorcunov2516.62%21.44%
al viroal viro1894.99%42.88%
linus torvaldslinus torvalds1704.48%75.04%
christoph hellwigchristoph hellwig1503.96%10.72%
howard chuhoward chu832.19%10.72%
herton ronaldo krzesinskiherton ronaldo krzesinski290.76%10.72%
kay sieverskay sievers240.63%10.72%
andrew mortonandrew morton200.53%32.16%
rasmus villemoesrasmus villemoes190.50%21.44%
eric w. biedermaneric w. biederman170.45%10.72%
greg kroah-hartmangreg kroah-hartman140.37%21.44%
dan carpenterdan carpenter120.32%10.72%
sukadev bhattiprolusukadev bhattiprolu110.29%10.72%
arnd bergmannarnd bergmann90.24%21.44%
nick pigginnick piggin60.16%21.44%
zou nan haizou nan hai60.16%10.72%
colin kingcolin king60.16%10.72%
konstantin khlebnikovkonstantin khlebnikov50.13%10.72%
brian bloniarzbrian bloniarz30.08%10.72%
alexey dobriyanalexey dobriyan30.08%10.72%
paul gortmakerpaul gortmaker20.05%10.72%
cong dingcong ding20.05%21.44%
tejun heotejun heo10.03%10.72%
roel kluinroel kluin10.03%10.72%
josh triplettjosh triplett10.03%10.72%
adrian bunkadrian bunk10.03%10.72%
daniel mackdaniel mack10.03%10.72%
Total3791100.00%139100.00%
Directory: drivers/tty
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}