blob: a0625c703bd0f35ed2d9a01ff10c38571fbb1486 [file] [log] [blame]
/*
* linux/kernel/chr_drv/pty.c
*
* (C) 1991 Linus Torvalds
*/
/*
* pty.c
*
* This module implements the pty functions
* void mpty_write(struct tty_struct * queue);
* void spty_write(struct tty_struct * queue);
*/
#include <errno.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/io.h>
int pty_open(unsigned int dev, struct file * filp)
{
struct tty_struct * tty;
tty = tty_table + dev;
if (!tty->link)
return -ENODEV;
wake_up(&tty->read_q->proc_list);
if (filp->f_flags & O_NDELAY)
return 0;
if (IS_A_PTY_MASTER(dev)) {
tty->link->count++;
return 0;
}
while (!tty->link->count && !(current->signal & ~current->blocked))
interruptible_sleep_on(&tty->link->read_q->proc_list);
if (!tty->link->count)
return -ERESTARTSYS;
return 0;
}
void pty_close(unsigned int dev, struct file * filp)
{
struct tty_struct * tty;
tty = tty_table + dev;
wake_up(&tty->read_q->proc_list);
if (IS_A_PTY_MASTER(dev)) {
tty->link->count--;
if (tty->link->pgrp > 0)
kill_pg(tty->link->pgrp,SIGHUP,1);
}
}
static inline void pty_copy(struct tty_struct * from, struct tty_struct * to)
{
int c;
while (!from->stopped && !EMPTY(from->write_q)) {
if (FULL(to->read_q)) {
if (FULL(to->secondary))
break;
TTY_READ_FLUSH(to);
continue;
}
c = GETCH(from->write_q);
PUTCH(c,to->read_q);
if (current->signal & ~current->blocked)
break;
}
TTY_READ_FLUSH(to);
wake_up(&from->write_q->proc_list);
}
/*
* This routine gets called when tty_write has put something into
* the write_queue. It copies the input to the output-queue of it's
* slave.
*/
void mpty_write(struct tty_struct * tty)
{
if (tty->link)
pty_copy(tty,tty->link);
}
void spty_write(struct tty_struct * tty)
{
if (tty->link)
pty_copy(tty,tty->link);
}