FreeBSD/sys/kern/tty_ttydisc.c
/*
 * Just like the old TTY implementation, we need to copy data in chunks
 * into a temporary buffer. One of the reasons why we need to do this,
 * is because output processing (only TAB3 though) may allow the buffer
 * to grow eight times.
 */
Just like the old TTY implementation, we need to copy data in chunks
into a temporary buffer. One of the reasons why we need to do this,
is because output processing (only TAB3 though) may allow the buffer
to grow eight times.
Just like the old TTY implementation we need to copy data in chunks into a temporary buffer . One of the reasons why we need to do this is because output processing ( only TAB3 though ) may allow the buffer to grow eight times .
int
ttydisc_write(struct tty *tp, struct uio *uio, int ioflag)
{
	char ob[TTY_STACKBUF];
	char *obstart;
	int error = 0;
	unsigned int oblen = 0;
	tty_lock_assert(tp, MA_OWNED);
	if (tp->t_flags & TF_ZOMBIE)
		return (EIO);
	while (uio->uio_resid > 0) {
		unsigned int nlen;
		MPASS(oblen == 0);
		obstart = ob;
		nlen = MIN(uio->uio_resid, sizeof ob);
		tty_unlock(tp);
		error = uiomove(ob, nlen, uio);
		tty_lock(tp);
		if (error != 0)
			break;
		oblen = nlen;
		if (tty_gone(tp)) {
			error = ENXIO;
			break;
		}
		MPASS(oblen > 0);
		do {
			unsigned int plen, wlen;
			if (CMP_FLAG(o, OPOST)) {
				plen = ttydisc_findchar(obstart, oblen);
			} else {
				plen = oblen;
			}
			if (plen == 0) {
				if (ttydisc_write_oproc(tp, *obstart) == 0) {
					obstart++;
					oblen--;
					tp->t_writepos = tp->t_column;
					ttyinq_reprintpos_set(&tp->t_inq);
					continue;
				}
			} else {
				wlen = ttyoutq_write(&tp->t_outq, obstart, plen);
				obstart += wlen;
				oblen -= wlen;
				tp->t_column += wlen;
				tp->t_writepos = tp->t_column;
				ttyinq_reprintpos_set(&tp->t_inq);
				if (wlen == plen)
					continue;
			}
			tp->t_flags |= TF_HIWAT_OUT;
			if (ioflag & IO_NDELAY) {
				error = EWOULDBLOCK;
				goto done;
			}
			ttydevsw_outwakeup(tp);
			if ((tp->t_flags & TF_HIWAT_OUT) == 0)
				continue;
			error = tty_wait(tp, &tp->t_outwait);
			if (error)
				goto done;
			if (tp->t_flags & TF_ZOMBIE) {
				error = EIO;
				goto done;
			}
		} while (oblen > 0);
	}
done:
	if (!tty_gone(tp))
		ttydevsw_outwakeup(tp);
	uio->uio_resid += oblen;
	return (error);
}
int ttydisc_write ( struct tty * tp , struct uio * uio , int ioflag ) { char ob [ TTY_STACKBUF ] ; char * obstart ; int error = 0 ; unsigned int oblen = 0 ; tty_lock_assert ( tp , MA_OWNED ) ; if ( tp -> t_flags & TF_ZOMBIE ) return ( EIO ) ; while ( uio -> uio_resid > 0 ) { unsigned int nlen ; MPASS ( oblen == 0 ) ; obstart = ob ; nlen = MIN ( uio -> uio_resid , sizeof ob ) ; tty_unlock ( tp ) ; error = uiomove ( ob , nlen , uio ) ; tty_lock ( tp ) ; if ( error != 0 ) break ; oblen = nlen ; if ( tty_gone ( tp ) ) { error = ENXIO ; break ; } MPASS ( oblen > 0 ) ; do { unsigned int plen , wlen ; if ( CMP_FLAG ( o , OPOST ) ) { plen = ttydisc_findchar ( obstart , oblen ) ; } else { plen = oblen ; } if ( plen == 0 ) { if ( ttydisc_write_oproc ( tp , * obstart ) == 0 ) { obstart ++ ; oblen -- ; tp -> t_writepos = tp -> t_column ; ttyinq_reprintpos_set ( & tp -> t_inq ) ; continue ; } } else { wlen = ttyoutq_write ( & tp -> t_outq , obstart , plen ) ; obstart += wlen ; oblen -= wlen ; tp -> t_column += wlen ; tp -> t_writepos = tp -> t_column ; ttyinq_reprintpos_set ( & tp -> t_inq ) ; if ( wlen == plen ) continue ; } tp -> t_flags |= TF_HIWAT_OUT ; if ( ioflag & IO_NDELAY ) { error = EWOULDBLOCK ; goto done ; } ttydevsw_outwakeup ( tp ) ; if ( ( tp -> t_flags & TF_HIWAT_OUT ) == 0 ) continue ; error = tty_wait ( tp , & tp -> t_outwait ) ; if ( error ) goto done ; if ( tp -> t_flags & TF_ZOMBIE ) { error = EIO ; goto done ; } } while ( oblen > 0 ) ; } done : if ( ! tty_gone ( tp ) ) ttydevsw_outwakeup ( tp ) ; uio -> uio_resid += oblen ; return ( error ) ; }
Just like the old TTY implementation, we need to copy data in chunks
 into a temporary buffer.
Just like the old TTY implementation we need to copy data in chunks into a temporary buffer .
/*
	 * We don't need to check whether the process is the foreground
	 * process group or if we have a carrier. This is already done
	 * in ttydev_write().
	 */ /* Step 1: read data. */ /* Step 2: process data. */ /* Search for special characters for post processing. */ /*
				 * We're going to process a character
				 * that needs processing
				 */ /* We're going to write regular data. */ /* Watermark reached. Try to sleep. */ /*
			 * The driver may write back the data
			 * synchronously. Be sure to check the high
			 * water mark before going to sleep.
			 */ /*
	 * Add the amount of bytes that we didn't process back to the
	 * uio counters. We need to do this to make sure write() doesn't
	 * count the bytes we didn't store in the queue.
	 */