staticvoid pty_close(struct tty_struct *tty, struct file *filp)
{ 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->ctrl.packet = false;
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);
}
}
/* * 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.
*/ staticvoid pty_unthrottle(struct tty_struct *tty)
{
tty_wakeup(tty->link);
set_bit(TTY_THROTTLED, &tty->flags);
}
/** * 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.
*/
/** * 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.
*/
/* 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;
}
/** * 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
*/ staticvoid pty_start(struct tty_struct *tty)
{ unsignedlong flags;
/** * 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
*/ staticint 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;
driver->ttys[tty->index] = NULL; if (pair)
pair->driver->ttys[pair->index] = NULL;
}
staticint pty_bsd_ioctl(struct tty_struct *tty, unsignedint cmd, unsignedlong 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;
}
#ifdef CONFIG_COMPAT staticlong pty_bsd_compat_ioctl(struct tty_struct *tty, unsignedint cmd, unsignedlong arg)
{ /* * PTY ioctls don't require any special translation between 32-bit and * 64-bit userspace, they are already compatible.
*/ return pty_bsd_ioctl(tty, cmd, (unsignedlong)compat_ptr(arg));
} #else #define pty_bsd_compat_ioctl NULL #endif
staticint 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.
*/ staticconststruct 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,
.unthrottle = pty_unthrottle,
.ioctl = pty_bsd_ioctl,
.compat_ioctl = pty_bsd_compat_ioctl,
.cleanup = pty_cleanup,
.resize = pty_resize,
.remove = pty_remove
};
/** * 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)
{ int fd; struct file *filp; int retval = -EINVAL; struct path path;
staticint pty_unix98_ioctl(struct tty_struct *tty, unsignedint cmd, unsignedlong 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, (unsignedint __user *)arg); case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg);
}
return -ENOIOCTLCMD;
}
#ifdef CONFIG_COMPAT staticlong pty_unix98_compat_ioctl(struct tty_struct *tty, unsignedint cmd, unsignedlong arg)
{ /* * PTY ioctls don't require any special translation between 32-bit and * 64-bit userspace, they are already compatible.
*/ return pty_unix98_ioctl(tty, cmd,
cmd == TIOCSIG ? arg : (unsignedlong)compat_ptr(arg));
} #else #define pty_unix98_compat_ioctl NULL #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.
*/
staticstruct 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);
}
/** * 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.
*/
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;
}
/* this is called once with whichever end is closed last */ staticvoid pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{ struct pts_fs_info *fsi;
/** * 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
*/
/* 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;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.