X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fpty.c;h=9826bbd0f67a475985ff3a47f9de9130f335afa8;hb=6367666f534ee8fa9c6a7b667f38b5e445f85918;hp=a47386427eb2c152cc3a8c73c59f5cc2850a841b;hpb=8d40237c730b8be87c1b80a5d96b9c603fefa829;p=linux-2.6.git diff --git a/drivers/char/pty.c b/drivers/char/pty.c index a47386427..9826bbd0f 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include /* These are global because they are accessed in tty_io.c */ @@ -55,9 +55,9 @@ static void pty_close(struct tty_struct * tty, struct file * filp) if (!tty->link) return; tty->link->packet = 0; - set_bit(TTY_OTHER_CLOSED, &tty->link->flags); wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); + set_bit(TTY_OTHER_CLOSED, &tty->link->flags); if (tty->driver->subtype == PTY_TYPE_MASTER) { set_bit(TTY_OTHER_CLOSED, &tty->flags); #ifdef CONFIG_UNIX98_PTYS @@ -103,18 +103,51 @@ static void pty_unthrottle(struct tty_struct * tty) * not our partners. We can't just take the other one blindly without * risking deadlocks. There is also the small matter of TTY_DONT_FLIP */ -static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count) +static int pty_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) { struct tty_struct *to = tty->link; - int c; + int c=0, n, room; + char *temp_buffer; if (!to || tty->stopped) return 0; - c = to->ldisc.receive_room(to); - if (c > count) - c = count; - to->ldisc.receive_buf(to, buf, NULL, c); + if (from_user) { + down(&tty->flip.pty_sem); + temp_buffer = &tty->flip.char_buf[0]; + while (count > 0) { + /* check space so we don't copy needlessly */ + n = to->ldisc.receive_room(to); + if (n > count) + n = count; + if (!n) break; + + n = min(n, PTY_BUF_SIZE); + n -= copy_from_user(temp_buffer, buf, n); + if (!n) { + if (!c) + c = -EFAULT; + break; + } + + /* check again in case the buffer filled up */ + room = to->ldisc.receive_room(to); + if (n > room) + n = room; + if (!n) break; + buf += n; + c += n; + count -= n; + to->ldisc.receive_buf(to, temp_buffer, NULL, n); + } + up(&tty->flip.pty_sem); + } else { + c = to->ldisc.receive_room(to); + if (c > count) + c = count; + to->ldisc.receive_buf(to, buf, NULL, c); + } return c; }