2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
5 * Portions of this software were developed under sponsorship from Snow
6 * B.V., the Netherlands.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/fcntl.h>
35 #include <sys/filio.h>
36 #include <sys/kernel.h>
37 #include <sys/signal.h>
38 #include <sys/sysctl.h>
39 #include <sys/systm.h>
41 #include <sys/ttycom.h>
42 #include <sys/ttydefaults.h>
44 #include <sys/vnode.h>
47 * Standard TTYDISC `termios' line discipline.
51 static long tty_nin
= 0;
52 SYSCTL_LONG(_kern
, OID_AUTO
, tty_nin
, CTLFLAG_RD
,
53 &tty_nin
, 0, "Total amount of bytes received");
54 static long tty_nout
= 0;
55 SYSCTL_LONG(_kern
, OID_AUTO
, tty_nout
, CTLFLAG_RD
,
56 &tty_nout
, 0, "Total amount of bytes transmitted");
58 /* termios comparison macro's. */
59 #define CMP_CC(v,c) (tp->t_termios.c_cc[v] != _POSIX_VDISABLE && \
60 tp->t_termios.c_cc[v] == (c))
61 #define CMP_FLAG(field,opt) (tp->t_termios.c_ ## field ## flag & (opt))
63 /* Characters that cannot be modified through c_cc. */
68 /* Character is a control character. */
69 #define CTL_VALID(c) ((c) == 0x7f || (unsigned char)(c) < 0x20)
70 /* Control character should be processed on echo. */
71 #define CTL_ECHO(c,q) (!(q) && ((c) == CERASE2 || (c) == CTAB || \
72 (c) == CNL || (c) == CCR))
73 /* Control character should be printed using ^X notation. */
74 #define CTL_PRINT(c,q) ((c) == 0x7f || ((unsigned char)(c) < 0x20 && \
75 ((q) || ((c) != CTAB && (c) != CNL))))
76 /* Character is whitespace. */
77 #define CTL_WHITE(c) ((c) == ' ' || (c) == CTAB)
78 /* Character is alphanumeric. */
79 #define CTL_ALNUM(c) (((c) >= '0' && (c) <= '9') || \
80 ((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
83 ttydisc_open(struct tty
*tp
)
89 ttydisc_close(struct tty
*tp
)
92 /* Clean up our flags when leaving the discipline. */
93 tp
->t_flags
&= ~(TF_STOPPED
|TF_HIWAT
|TF_ZOMBIE
);
95 /* POSIX states we should flush when close() is called. */
96 ttyinq_flush(&tp
->t_inq
);
97 ttyoutq_flush(&tp
->t_outq
);
100 ttydevsw_inwakeup(tp
);
101 ttydevsw_outwakeup(tp
);
106 ttydisc_read_canonical(struct tty
*tp
, struct uio
*uio
, int ioflag
)
108 char breakc
[4] = { CNL
}; /* enough to hold \n, VEOF and VEOL. */
110 size_t clen
, flen
= 0, n
= 1;
111 unsigned char lastc
= _POSIX_VDISABLE
;
113 #define BREAK_ADD(c) do { \
114 if (tp->t_termios.c_cc[c] != _POSIX_VDISABLE) \
115 breakc[n++] = tp->t_termios.c_cc[c]; \
117 /* Determine which characters we should trigger on. */
125 * Quite a tricky case: unlike the old TTY
126 * implementation, this implementation copies data back
127 * to userspace in large chunks. Unfortunately, we can't
128 * calculate the line length on beforehand if it crosses
129 * ttyinq_block boundaries, because multiple reads could
130 * then make this code read beyond the newline.
132 * This is why we limit the read to:
133 * - The size the user has requested
134 * - The blocksize (done in tty_inq.c)
135 * - The amount of bytes until the newline
137 * This causes the line length to be recalculated after
138 * each block has been copied to userspace. This will
139 * cause the TTY layer to return data in chunks using
140 * the blocksize (except the first and last blocks).
142 clen
= ttyinq_findchar(&tp
->t_inq
, breakc
, uio
->uio_resid
,
147 if (ioflag
& IO_NDELAY
)
148 return (EWOULDBLOCK
);
149 else if (tp
->t_flags
& TF_ZOMBIE
)
152 error
= tty_wait(tp
, &tp
->t_inwait
);
158 /* Don't send the EOF char back to userspace. */
159 if (CMP_CC(VEOF
, lastc
))
164 /* Read and throw away the EOF character. */
165 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
, clen
, flen
);
169 } while (uio
->uio_resid
> 0 && lastc
== _POSIX_VDISABLE
);
175 ttydisc_read_raw_no_timer(struct tty
*tp
, struct uio
*uio
, int ioflag
)
177 size_t vmin
= tp
->t_termios
.c_cc
[VMIN
];
178 int oresid
= uio
->uio_resid
;
181 MPASS(tp
->t_termios
.c_cc
[VTIME
] == 0);
184 * This routine implements the easy cases of read()s while in
185 * non-canonical mode, namely case B and D, where we don't have
190 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
,
194 if (uio
->uio_resid
== 0 || (oresid
- uio
->uio_resid
) >= vmin
)
197 /* We have to wait for more. */
198 if (ioflag
& IO_NDELAY
)
199 return (EWOULDBLOCK
);
200 else if (tp
->t_flags
& TF_ZOMBIE
)
203 error
= tty_wait(tp
, &tp
->t_inwait
);
210 ttydisc_read_raw_read_timer(struct tty
*tp
, struct uio
*uio
, int ioflag
,
213 size_t vmin
= MAX(tp
->t_termios
.c_cc
[VMIN
], 1);
214 unsigned int vtime
= tp
->t_termios
.c_cc
[VTIME
];
215 struct timeval end
, now
, left
;
218 MPASS(tp
->t_termios
.c_cc
[VTIME
] != 0);
220 /* Determine when the read should be expired. */
221 end
.tv_sec
= vtime
/ 10;
222 end
.tv_usec
= (vtime
% 10) * 100000;
224 timevaladd(&end
, &now
);
227 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
,
231 if (uio
->uio_resid
== 0 || (oresid
- uio
->uio_resid
) >= vmin
)
234 /* Calculate how long we should wait. */
236 if (timevalcmp(&now
, &end
, >))
239 timevalsub(&left
, &now
);
243 * We have to wait for more. If the timer expires, we
244 * should return a 0-byte read.
246 if (ioflag
& IO_NDELAY
)
247 return (EWOULDBLOCK
);
248 else if (tp
->t_flags
& TF_ZOMBIE
)
251 error
= tty_timedwait(tp
, &tp
->t_inwait
, hz
);
253 return (error
== EWOULDBLOCK
? 0 : error
);
260 ttydisc_read_raw_interbyte_timer(struct tty
*tp
, struct uio
*uio
, int ioflag
)
262 size_t vmin
= tp
->t_termios
.c_cc
[VMIN
];
263 int oresid
= uio
->uio_resid
;
266 MPASS(tp
->t_termios
.c_cc
[VMIN
] != 0);
267 MPASS(tp
->t_termios
.c_cc
[VTIME
] != 0);
270 * When using the interbyte timer, the timer should be started
271 * after the first byte has been received. We just call into the
272 * generic read timer code after we've received the first byte.
276 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
,
280 if (uio
->uio_resid
== 0 || (oresid
- uio
->uio_resid
) >= vmin
)
284 * Not enough data, but we did receive some, which means
285 * we'll now start using the interbyte timer.
287 if (oresid
!= uio
->uio_resid
)
290 /* We have to wait for more. */
291 if (ioflag
& IO_NDELAY
)
292 return (EWOULDBLOCK
);
293 else if (tp
->t_flags
& TF_ZOMBIE
)
296 error
= tty_wait(tp
, &tp
->t_inwait
);
301 return ttydisc_read_raw_read_timer(tp
, uio
, ioflag
, oresid
);
305 ttydisc_read(struct tty
*tp
, struct uio
*uio
, int ioflag
)
309 tty_lock_assert(tp
, MA_OWNED
);
311 if (uio
->uio_resid
== 0)
314 if (CMP_FLAG(l
, ICANON
))
315 error
= ttydisc_read_canonical(tp
, uio
, ioflag
);
316 else if (tp
->t_termios
.c_cc
[VTIME
] == 0)
317 error
= ttydisc_read_raw_no_timer(tp
, uio
, ioflag
);
318 else if (tp
->t_termios
.c_cc
[VMIN
] == 0)
319 error
= ttydisc_read_raw_read_timer(tp
, uio
, ioflag
,
322 error
= ttydisc_read_raw_interbyte_timer(tp
, uio
, ioflag
);
324 if (ttyinq_bytesleft(&tp
->t_inq
) >= tp
->t_inlow
||
325 ttyinq_bytescanonicalized(&tp
->t_inq
) == 0) {
326 /* Unset the input watermark when we've got enough space. */
327 tty_hiwat_in_unblock(tp
);
333 static __inline
unsigned int
334 ttydisc_findchar(const char *obstart
, unsigned int oblen
)
336 const char *c
= obstart
;
344 return (c
- obstart
);
348 ttydisc_write_oproc(struct tty
*tp
, char c
)
350 unsigned int scnt
, error
;
352 MPASS(CMP_FLAG(o
, OPOST
));
355 #define PRINT_NORMAL() ttyoutq_write_nofrag(&tp->t_outq, &c, 1)
358 /* End-of-text dropping. */
359 if (CMP_FLAG(o
, ONOEOT
))
361 return PRINT_NORMAL();
364 /* Handle backspace to fix tab expansion. */
365 if (PRINT_NORMAL() != 0)
367 if (tp
->t_column
> 0)
373 scnt
= 8 - (tp
->t_column
& 7);
374 if (CMP_FLAG(o
, TAB3
)) {
375 error
= ttyoutq_write_nofrag(&tp
->t_outq
,
378 error
= PRINT_NORMAL();
383 tp
->t_column
+= scnt
;
384 MPASS((tp
->t_column
% 8) == 0);
388 /* Newline conversion. */
389 if (CMP_FLAG(o
, ONLCR
)) {
390 /* Convert \n to \r\n. */
391 error
= ttyoutq_write_nofrag(&tp
->t_outq
, "\r\n", 2);
393 error
= PRINT_NORMAL();
398 if (CMP_FLAG(o
, ONLCR
|ONLRET
)) {
399 tp
->t_column
= tp
->t_writepos
= 0;
400 ttyinq_reprintpos_set(&tp
->t_inq
);
405 /* Carriage return to newline conversion. */
406 if (CMP_FLAG(o
, OCRNL
))
408 /* Omit carriage returns on column 0. */
409 if (CMP_FLAG(o
, ONOCR
) && tp
->t_column
== 0)
411 if (PRINT_NORMAL() != 0)
414 tp
->t_column
= tp
->t_writepos
= 0;
415 ttyinq_reprintpos_set(&tp
->t_inq
);
420 * Invisible control character. Print it, but don't
421 * increase the column count.
423 return PRINT_NORMAL();
428 * Just like the old TTY implementation, we need to copy data in chunks
429 * into a temporary buffer. One of the reasons why we need to do this,
430 * is because output processing (only TAB3 though) may allow the buffer
431 * to grow eight times.
434 ttydisc_write(struct tty
*tp
, struct uio
*uio
, int ioflag
)
439 unsigned int oblen
= 0;
441 tty_lock_assert(tp
, MA_OWNED
);
443 if (tp
->t_flags
& TF_ZOMBIE
)
447 * We don't need to check whether the process is the foreground
448 * process group or if we have a carrier. This is already done
452 while (uio
->uio_resid
> 0) {
457 /* Step 1: read data. */
462 nlen
= MIN(uio
->uio_resid
, sizeof ob
);
463 error
= uiomove(ob
, nlen
, uio
);
476 /* Step 2: process data. */
478 unsigned int plen
, wlen
;
480 /* Search for special characters for post processing. */
481 if (CMP_FLAG(o
, OPOST
)) {
482 plen
= ttydisc_findchar(obstart
, oblen
);
489 * We're going to process a character
490 * that needs processing
492 if (ttydisc_write_oproc(tp
, *obstart
) == 0) {
496 tp
->t_writepos
= tp
->t_column
;
497 ttyinq_reprintpos_set(&tp
->t_inq
);
501 /* We're going to write regular data. */
502 wlen
= ttyoutq_write(&tp
->t_outq
, obstart
, plen
);
505 tp
->t_column
+= wlen
;
507 tp
->t_writepos
= tp
->t_column
;
508 ttyinq_reprintpos_set(&tp
->t_inq
);
514 /* Watermark reached. Try to sleep. */
515 tp
->t_flags
|= TF_HIWAT_OUT
;
517 if (ioflag
& IO_NDELAY
) {
523 * The driver may write back the data
524 * synchronously. Be sure to check the high
525 * water mark before going to sleep.
527 ttydevsw_outwakeup(tp
);
528 if ((tp
->t_flags
& TF_HIWAT_OUT
) == 0)
531 error
= tty_wait(tp
, &tp
->t_outwait
);
535 if (tp
->t_flags
& TF_ZOMBIE
) {
543 ttydevsw_outwakeup(tp
);
546 * Add the amount of bytes that we didn't process back to the
547 * uio counters. We need to do this to make sure write() doesn't
548 * count the bytes we didn't store in the queue.
550 uio
->uio_resid
+= oblen
;
555 ttydisc_optimize(struct tty
*tp
)
557 tty_lock_assert(tp
, MA_OWNED
);
559 if (!CMP_FLAG(i
, ICRNL
|IGNCR
|IMAXBEL
|INLCR
|ISTRIP
|IXON
) &&
560 (!CMP_FLAG(i
, BRKINT
) || CMP_FLAG(i
, IGNBRK
)) &&
561 (!CMP_FLAG(i
, PARMRK
) ||
562 CMP_FLAG(i
, IGNPAR
|IGNBRK
) == (IGNPAR
|IGNBRK
)) &&
563 !CMP_FLAG(l
, ECHO
|ICANON
|IEXTEN
|ISIG
|PENDIN
)) {
564 tp
->t_flags
|= TF_BYPASS
;
566 tp
->t_flags
&= ~TF_BYPASS
;
571 ttydisc_modem(struct tty
*tp
, int open
)
574 tty_lock_assert(tp
, MA_OWNED
);
577 cv_broadcast(&tp
->t_dcdwait
);
580 * Ignore modem status lines when CLOCAL is turned on, but don't
581 * enter the zombie state when the TTY isn't opened, because
582 * that would cause the TTY to be in zombie state after being
585 if (!tty_opened(tp
) || CMP_FLAG(c
, CLOCAL
))
592 tp
->t_flags
|= TF_ZOMBIE
;
594 tty_signal_sessleader(tp
, SIGHUP
);
595 tty_flush(tp
, FREAD
|FWRITE
);
598 * Carrier is back again.
601 /* XXX: what should we do here? */
606 ttydisc_echo_force(struct tty
*tp
, char c
, int quote
)
609 if (CMP_FLAG(o
, OPOST
) && CTL_ECHO(c
, quote
)) {
611 * Only perform postprocessing when OPOST is turned on
612 * and the character is an unquoted BS/TB/NL/CR.
614 return ttydisc_write_oproc(tp
, c
);
615 } else if (CMP_FLAG(l
, ECHOCTL
) && CTL_PRINT(c
, quote
)) {
617 * Only use ^X notation when ECHOCTL is turned on and
618 * we've got an quoted control character.
620 char ob
[2] = { '^', '?' };
622 /* Print ^X notation. */
627 return ttyoutq_write_nofrag(&tp
->t_outq
, ob
, 2);
629 /* Can just be printed. */
631 return ttyoutq_write_nofrag(&tp
->t_outq
, &c
, 1);
636 ttydisc_echo(struct tty
*tp
, char c
, int quote
)
640 * Only echo characters when ECHO is turned on, or ECHONL when
641 * the character is an unquoted newline.
643 if (!CMP_FLAG(l
, ECHO
) &&
644 (!CMP_FLAG(l
, ECHONL
) || c
!= CNL
|| quote
))
647 return ttydisc_echo_force(tp
, c
, quote
);
652 ttydisc_reprint_char(void *d
, char c
, int quote
)
656 ttydisc_echo(tp
, c
, quote
);
660 ttydisc_reprint(struct tty
*tp
)
664 /* Print ^R\n, followed by the line. */
665 c
= tp
->t_termios
.c_cc
[VREPRINT
];
666 if (c
!= _POSIX_VDISABLE
)
667 ttydisc_echo(tp
, c
, 0);
668 ttydisc_echo(tp
, CNL
, 0);
669 ttyinq_reprintpos_reset(&tp
->t_inq
);
671 ttyinq_line_iterate_from_linestart(&tp
->t_inq
, ttydisc_reprint_char
, tp
);
674 struct ttydisc_recalc_length
{
680 ttydisc_recalc_charlength(void *d
, char c
, int quote
)
682 struct ttydisc_recalc_length
*data
= d
;
683 struct tty
*tp
= data
->tp
;
685 if (CTL_PRINT(c
, quote
)) {
686 if (CMP_FLAG(l
, ECHOCTL
))
688 } else if (c
== CTAB
) {
689 data
->curlen
+= 8 - (data
->curlen
& 7);
696 ttydisc_recalc_linelength(struct tty
*tp
)
698 struct ttydisc_recalc_length data
= { tp
, tp
->t_writepos
};
700 ttyinq_line_iterate_from_reprintpos(&tp
->t_inq
,
701 ttydisc_recalc_charlength
, &data
);
702 return (data
.curlen
);
706 ttydisc_rubchar(struct tty
*tp
)
710 unsigned int prevpos
, tablen
;
712 if (ttyinq_peekchar(&tp
->t_inq
, &c
, "e
) != 0)
714 ttyinq_unputchar(&tp
->t_inq
);
716 if (CMP_FLAG(l
, ECHO
)) {
718 * Remove the character from the screen. This is even
719 * safe for characters that span multiple characters
720 * (tabs, quoted, etc).
722 if (tp
->t_writepos
>= tp
->t_column
) {
723 /* Retype the sentence. */
725 } else if (CMP_FLAG(l
, ECHOE
)) {
726 if (CTL_PRINT(c
, quote
)) {
727 /* Remove ^X formatted chars. */
728 if (CMP_FLAG(l
, ECHOCTL
)) {
730 ttyoutq_write_nofrag(&tp
->t_outq
,
733 } else if (c
== ' ') {
734 /* Space character needs no rubbing. */
736 ttyoutq_write_nofrag(&tp
->t_outq
, "\b", 1);
737 } else if (c
== CTAB
) {
739 * Making backspace work with tabs is
740 * quite hard. Recalculate the length of
741 * this character and remove it.
743 * Because terminal settings could be
744 * changed while the line is being
745 * inserted, the calculations don't have
746 * to be correct. Make sure we keep the
747 * tab length within proper bounds.
749 prevpos
= ttydisc_recalc_linelength(tp
);
750 if (prevpos
>= tp
->t_column
)
753 tablen
= tp
->t_column
- prevpos
;
757 tp
->t_column
= prevpos
;
758 ttyoutq_write_nofrag(&tp
->t_outq
,
759 "\b\b\b\b\b\b\b\b", tablen
);
763 * Remove a regular character by
764 * punching a space over it.
767 ttyoutq_write_nofrag(&tp
->t_outq
, "\b \b", 3);
770 /* Don't print spaces. */
771 ttydisc_echo(tp
, tp
->t_termios
.c_cc
[VERASE
], 0);
779 ttydisc_rubword(struct tty
*tp
)
784 /* Strip whitespace first. */
786 if (ttyinq_peekchar(&tp
->t_inq
, &c
, "e
) != 0)
794 * Record whether the last character from the previous iteration
795 * was alphanumeric or not. We need this to implement ALTWERASE.
797 alnum
= CTL_ALNUM(c
);
801 if (ttyinq_peekchar(&tp
->t_inq
, &c
, "e
) != 0)
805 if (CMP_FLAG(l
, ALTWERASE
) && CTL_ALNUM(c
) != alnum
)
811 ttydisc_rint(struct tty
*tp
, char c
, int flags
)
813 int signal
, quote
= 0;
814 char ob
[3] = { 0xff, 0x00 };
817 tty_lock_assert(tp
, MA_OWNED
);
819 atomic_add_long(&tty_nin
, 1);
821 if (tp
->t_flags
& TF_BYPASS
)
825 if (flags
& TRE_BREAK
) {
826 if (CMP_FLAG(i
, IGNBRK
)) {
827 /* Ignore break characters. */
829 } else if (CMP_FLAG(i
, BRKINT
)) {
830 /* Generate SIGINT on break. */
831 tty_flush(tp
, FREAD
|FWRITE
);
832 tty_signal_pgrp(tp
, SIGINT
);
838 } else if (flags
& TRE_FRAMING
||
839 (flags
& TRE_PARITY
&& CMP_FLAG(i
, INPCK
))) {
840 if (CMP_FLAG(i
, IGNPAR
)) {
841 /* Ignore bad characters. */
850 /* Allow any character to perform a wakeup. */
851 if (CMP_FLAG(i
, IXANY
))
852 tp
->t_flags
&= ~TF_STOPPED
;
854 /* Remove the top bit. */
855 if (CMP_FLAG(i
, ISTRIP
))
858 /* Skip input processing when we want to print it literally. */
859 if (tp
->t_flags
& TF_LITERAL
) {
860 tp
->t_flags
&= ~TF_LITERAL
;
865 /* Special control characters that are implementation dependent. */
866 if (CMP_FLAG(l
, IEXTEN
)) {
867 /* Accept the next character as literal. */
868 if (CMP_CC(VLNEXT
, c
)) {
869 if (CMP_FLAG(l
, ECHO
)) {
870 if (CMP_FLAG(l
, ECHOE
))
871 ttyoutq_write_nofrag(&tp
->t_outq
, "^\b", 2);
873 ttydisc_echo(tp
, c
, 0);
875 tp
->t_flags
|= TF_LITERAL
;
881 * Handle signal processing.
883 if (CMP_FLAG(l
, ISIG
)) {
884 if (CMP_FLAG(l
, ICANON
|IEXTEN
) == (ICANON
|IEXTEN
)) {
885 if (CMP_CC(VSTATUS
, c
)) {
886 tty_signal_pgrp(tp
, SIGINFO
);
892 * When compared to the old implementation, this
893 * implementation also flushes the output queue. POSIX
894 * is really brief about this, but does makes us assume
898 if (CMP_CC(VINTR
, c
)) {
900 } else if (CMP_CC(VQUIT
, c
)) {
902 } else if (CMP_CC(VSUSP
, c
)) {
908 * Echo the character before signalling the
911 if (!CMP_FLAG(l
, NOFLSH
))
912 tty_flush(tp
, FREAD
|FWRITE
);
913 ttydisc_echo(tp
, c
, 0);
914 tty_signal_pgrp(tp
, signal
);
920 * Handle start/stop characters.
922 if (CMP_FLAG(i
, IXON
)) {
923 if (CMP_CC(VSTOP
, c
)) {
924 /* Stop it if we aren't stopped yet. */
925 if ((tp
->t_flags
& TF_STOPPED
) == 0) {
926 tp
->t_flags
|= TF_STOPPED
;
931 * When VSTART == VSTOP, we should make this key
934 if (!CMP_CC(VSTART
, c
))
937 if (CMP_CC(VSTART
, c
)) {
938 tp
->t_flags
&= ~TF_STOPPED
;
943 /* Conversion of CR and NL. */
946 if (CMP_FLAG(i
, IGNCR
))
948 if (CMP_FLAG(i
, ICRNL
))
952 if (CMP_FLAG(i
, INLCR
))
957 /* Canonical line editing. */
958 if (CMP_FLAG(l
, ICANON
)) {
959 if (CMP_CC(VERASE
, c
) || CMP_CC(VERASE2
, c
)) {
962 } else if (CMP_CC(VKILL
, c
)) {
963 while (ttydisc_rubchar(tp
) == 0);
965 } else if (CMP_FLAG(l
, IEXTEN
)) {
966 if (CMP_CC(VWERASE
, c
)) {
969 } else if (CMP_CC(VREPRINT
, c
)) {
977 if (CMP_FLAG(i
, PARMRK
) && (unsigned char)c
== 0xff) {
978 /* Print 0xff 0xff. */
990 if (CMP_FLAG(i
, PARMRK
)) {
991 /* Prepend 0xff 0x00 0x.. */
1001 /* See if we can store this on the input queue. */
1002 if (ttyinq_write_nofrag(&tp
->t_inq
, ob
, ol
, quote
) != 0) {
1003 if (CMP_FLAG(i
, IMAXBEL
))
1004 ttyoutq_write_nofrag(&tp
->t_outq
, "\a", 1);
1007 * Prevent a deadlock here. It may be possible that a
1008 * user has entered so much data, there is no data
1009 * available to read(), but the buffers are full anyway.
1011 * Only enter the high watermark if the device driver
1012 * can actually transmit something.
1014 if (ttyinq_bytescanonicalized(&tp
->t_inq
) == 0)
1017 tty_hiwat_in_block(tp
);
1022 * In raw mode, we canonicalize after receiving a single
1023 * character. Otherwise, we canonicalize when we receive a
1024 * newline, VEOL or VEOF, but only when it isn't quoted.
1026 if (!CMP_FLAG(l
, ICANON
) ||
1027 (!quote
&& (c
== CNL
|| CMP_CC(VEOL
, c
) || CMP_CC(VEOF
, c
)))) {
1028 ttyinq_canonicalize(&tp
->t_inq
);
1031 ttydisc_echo(tp
, c
, quote
);
1037 ttydisc_rint_bypass(struct tty
*tp
, char *buf
, size_t len
)
1041 tty_lock_assert(tp
, MA_OWNED
);
1043 MPASS(tp
->t_flags
& TF_BYPASS
);
1045 atomic_add_long(&tty_nin
, len
);
1047 ret
= ttyinq_write(&tp
->t_inq
, buf
, len
, 0);
1048 ttyinq_canonicalize(&tp
->t_inq
);
1054 ttydisc_rint_done(struct tty
*tp
)
1057 tty_lock_assert(tp
, MA_OWNED
);
1059 /* Wake up readers. */
1060 tty_wakeup(tp
, FREAD
);
1061 /* Wake up driver for echo. */
1062 ttydevsw_outwakeup(tp
);
1066 ttydisc_wakeup_watermark(struct tty
*tp
)
1070 c
= ttyoutq_bytesleft(&tp
->t_outq
);
1071 if (tp
->t_flags
& TF_HIWAT_OUT
) {
1072 /* Only allow us to run when we're below the watermark. */
1073 if (c
< tp
->t_outlow
)
1076 /* Reset the watermark. */
1077 tp
->t_flags
&= ~TF_HIWAT_OUT
;
1079 /* Only run when we have data at all. */
1083 tty_wakeup(tp
, FWRITE
);
1087 ttydisc_getc(struct tty
*tp
, void *buf
, size_t len
)
1090 tty_lock_assert(tp
, MA_OWNED
);
1092 if (tp
->t_flags
& TF_STOPPED
)
1095 len
= ttyoutq_read(&tp
->t_outq
, buf
, len
);
1096 ttydisc_wakeup_watermark(tp
);
1098 atomic_add_long(&tty_nout
, len
);
1104 ttydisc_getc_uio(struct tty
*tp
, struct uio
*uio
)
1107 int obytes
= uio
->uio_resid
;
1109 tty_lock_assert(tp
, MA_OWNED
);
1111 if (tp
->t_flags
& TF_STOPPED
)
1114 error
= ttyoutq_read_uio(&tp
->t_outq
, tp
, uio
);
1115 ttydisc_wakeup_watermark(tp
);
1117 atomic_add_long(&tty_nout
, obytes
- uio
->uio_resid
);
1123 * XXX: not really related to the TTYDISC, but we'd better put
1124 * tty_putchar() here, because we need to perform proper output
1129 tty_putchar(struct tty
*tp
, char c
)
1131 tty_lock_assert(tp
, MA_OWNED
);
1136 ttydisc_echo_force(tp
, c
, 0);
1137 tp
->t_writepos
= tp
->t_column
;
1138 ttyinq_reprintpos_set(&tp
->t_inq
);
1140 ttydevsw_outwakeup(tp
);