static int write_chan(struct tty_struct * tty, struct file * file, const unsigned char * buf, unsigned int nr) { struct wait_queue wait = { current, NULL }; int c; const unsigned char *b = buf; int retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) { retval = tty_check_change(tty); if (retval) return retval; } add_wait_queue(&tty->write_wait, &wait); while (1) { current->state = TASK_INTERRUPTIBLE; if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } if (O_OPOST(tty)) { while (nr > 0) { c = get_user(b); if (opost(c, tty) < 0) break; b++; nr--; } if (tty->driver.flush_chars) tty->driver.flush_chars(tty); } else { c = tty->driver.write(tty, 1, b, nr); b += c; nr -= c; } if (!nr) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; }
static int write_chan(struct tty_struct * tty, struct file * file, unsigned char * buf, unsigned int nr) { struct wait_queue wait = { current, NULL }; int c; unsigned char *b = buf; int retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) { retval = check_change(tty, tty->line); if (retval) return retval; } add_wait_queue(&tty->write_q.proc_list, &wait); while (1) { current->state = TASK_INTERRUPTIBLE; if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } while (nr > 0) { c = get_fs_byte(b); /* Care is needed here: opost() can abort even if the write_q is not full. */ if (opost(c, tty) < 0) break; b++; nr--; } TTY_WRITE_FLUSH(tty); if (!nr) break; if (EMPTY(&tty->write_q) && !need_resched) continue; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&tty->write_q.proc_list, &wait); return (b - buf) ? b - buf : retval; }
static int tty_write(struct inode * inode, struct file * file, char * buf, int count) { int dev, i, is_console; struct tty_struct * tty; dev = file->f_rdev; is_console = (inode->i_rdev == CONSOLE_DEV); if (MAJOR(dev) != TTY_MAJOR) { printk("tty_write: pseudo-major != TTY_MAJOR\n"); return -EINVAL; } dev = MINOR(dev); if (is_console && redirect) tty = redirect; else tty = TTY_TABLE(dev); if (!tty || !tty->write || (tty->flags & (1 << TTY_IO_ERROR))) return -EIO; #if 0 if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) && (current->tty == dev) && (tty->pgrp != current->pgrp)) { if (is_orphaned_pgrp(current->pgrp)) return -EIO; if (!is_ignored(SIGTTOU)) { (void) kill_pg(current->pgrp, SIGTTOU, 1); return -ERESTARTSYS; } } #endif if (ldiscs[tty->disc].write) /* XXX casts are for what kernel-wide prototypes should be. */ i = (ldiscs[tty->disc].write)(tty,file,(unsigned char *)buf,(unsigned int)count); else i = -EIO; if (i > 0) inode->i_mtime = CURRENT_TIME; return i; }
static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t nr) { const unsigned char *b = buf; DECLARE_WAITQUEUE(wait, current); int c; ssize_t retval = 0; if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; } process_echoes(tty); add_wait_queue(&tty->write_wait, &wait); while (1) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { while (nr > 0) { ssize_t num = process_output_block(tty, b, nr); if (num < 0) { if (num == -EAGAIN) break; retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; c = *b; if (process_output(c, tty) < 0) break; b++; nr--; } if (tty->ops->flush_chars) tty->ops->flush_chars(tty); } else { while (nr > 0) { c = tty->ops->write(tty, b, nr); if (c < 0) { retval = c; goto break_out; } if (!c) break; b += c; nr -= c; } } if (!nr) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } schedule(); } break_out: __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); if (b - buf != nr && tty->fasync) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); return (b - buf) ? b - buf : retval; }
static ssize_t write_chan(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr) { const unsigned char *b = buf; struct wait_queue wait = { current, NULL }; int c; ssize_t retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if (L_TOSTOP(tty) && file->f_dentry->d_inode->i_rdev != CONSOLE_DEV && file->f_dentry->d_inode->i_rdev != SYSCONS_DEV) { retval = tty_check_change(tty); if (retval) return retval; } add_wait_queue(&tty->write_wait, &wait); while (1) { current->state = TASK_INTERRUPTIBLE; if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { while (nr > 0) { ssize_t num = opost_block(tty, b, nr); if (num < 0) { retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; current->state = TASK_RUNNING; get_user(c, b); current->state = TASK_INTERRUPTIBLE; if (opost(c, tty) < 0) break; b++; nr--; } if (tty->driver.flush_chars) tty->driver.flush_chars(tty); } else { current->state = TASK_RUNNING; c = tty->driver.write(tty, 1, b, nr); current->state = TASK_INTERRUPTIBLE; if (c < 0) { retval = c; goto break_out; } b += c; nr -= c; } if (!nr) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } schedule(); } break_out: current->state = TASK_RUNNING; remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; }
static ssize_t write_chan(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr) { const unsigned char *b = buf; DECLARE_WAITQUEUE(wait, current); int c; ssize_t retval = 0; int transaction_commit = committing_transaction(); /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if ((!transaction_commit) && L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; } add_wait_queue(&tty->write_wait, &wait); while (1) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if ((!transaction_commit) && (tty_hung_up_p(file) || (tty->link && !tty->link->count))) { retval = -EIO; break; } if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { while (nr > 0) { ssize_t num = opost_block(tty, b, nr); if (num < 0) { if (num == -EAGAIN) break; retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; c = *b; if (opost(c, tty) < 0) break; b++; nr--; } if (tty->driver->flush_chars) tty->driver->flush_chars(tty); } else { while (nr > 0) { c = tty->driver->write(tty, b, nr); if (c < 0) { retval = c; goto break_out; } if (!c) break; b += c; nr -= c; } } if (!nr) break; if ((!transaction_commit) && (tx_cache_get_file_ro(file)->f_flags & O_NONBLOCK)) { retval = -EAGAIN; break; } schedule(); } break_out: __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; }