| /* |
| * 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); |
| } |