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 unsigned long tty_nin
= 0;
52 SYSCTL_ULONG(_kern
, OID_AUTO
, tty_nin
, CTLFLAG_RD
,
53 &tty_nin
, 0, "Total amount of bytes received");
54 static unsigned long tty_nout
= 0;
55 SYSCTL_ULONG(_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'))
82 #define TTY_STACKBUF 256
85 ttydisc_open(struct tty
*tp
)
91 ttydisc_close(struct tty
*tp
)
94 /* Clean up our flags when leaving the discipline. */
95 tp
->t_flags
&= ~(TF_STOPPED
|TF_HIWAT
|TF_ZOMBIE
);
98 * POSIX states that we must drain output and flush input on
99 * last close. Draining has already been done if possible.
101 tty_flush(tp
, FREAD
| FWRITE
);
103 if (ttyhook_hashook(tp
, close
))
108 ttydisc_read_canonical(struct tty
*tp
, struct uio
*uio
, int ioflag
)
110 char breakc
[4] = { CNL
}; /* enough to hold \n, VEOF and VEOL. */
112 size_t clen
, flen
= 0, n
= 1;
113 unsigned char lastc
= _POSIX_VDISABLE
;
115 #define BREAK_ADD(c) do { \
116 if (tp->t_termios.c_cc[c] != _POSIX_VDISABLE) \
117 breakc[n++] = tp->t_termios.c_cc[c]; \
119 /* Determine which characters we should trigger on. */
126 error
= tty_wait_background(tp
, curthread
, SIGTTIN
);
131 * Quite a tricky case: unlike the old TTY
132 * implementation, this implementation copies data back
133 * to userspace in large chunks. Unfortunately, we can't
134 * calculate the line length on beforehand if it crosses
135 * ttyinq_block boundaries, because multiple reads could
136 * then make this code read beyond the newline.
138 * This is why we limit the read to:
139 * - The size the user has requested
140 * - The blocksize (done in tty_inq.c)
141 * - The amount of bytes until the newline
143 * This causes the line length to be recalculated after
144 * each block has been copied to userspace. This will
145 * cause the TTY layer to return data in chunks using
146 * the blocksize (except the first and last blocks).
148 clen
= ttyinq_findchar(&tp
->t_inq
, breakc
, uio
->uio_resid
,
153 if (tp
->t_flags
& TF_ZOMBIE
)
155 else if (ioflag
& IO_NDELAY
)
156 return (EWOULDBLOCK
);
158 error
= tty_wait(tp
, &tp
->t_inwait
);
164 /* Don't send the EOF char back to userspace. */
165 if (CMP_CC(VEOF
, lastc
))
170 /* Read and throw away the EOF character. */
171 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
, clen
, flen
);
175 } while (uio
->uio_resid
> 0 && lastc
== _POSIX_VDISABLE
);
181 ttydisc_read_raw_no_timer(struct tty
*tp
, struct uio
*uio
, int ioflag
)
183 size_t vmin
= tp
->t_termios
.c_cc
[VMIN
];
184 ssize_t oresid
= uio
->uio_resid
;
187 MPASS(tp
->t_termios
.c_cc
[VTIME
] == 0);
190 * This routine implements the easy cases of read()s while in
191 * non-canonical mode, namely case B and D, where we don't have
196 error
= tty_wait_background(tp
, curthread
, SIGTTIN
);
200 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
,
204 if (uio
->uio_resid
== 0 || (oresid
- uio
->uio_resid
) >= vmin
)
207 /* We have to wait for more. */
208 if (tp
->t_flags
& TF_ZOMBIE
)
210 else if (ioflag
& IO_NDELAY
)
211 return (EWOULDBLOCK
);
213 error
= tty_wait(tp
, &tp
->t_inwait
);
220 ttydisc_read_raw_read_timer(struct tty
*tp
, struct uio
*uio
, int ioflag
,
223 size_t vmin
= MAX(tp
->t_termios
.c_cc
[VMIN
], 1);
224 unsigned int vtime
= tp
->t_termios
.c_cc
[VTIME
];
225 struct timeval end
, now
, left
;
228 MPASS(tp
->t_termios
.c_cc
[VTIME
] != 0);
230 /* Determine when the read should be expired. */
231 end
.tv_sec
= vtime
/ 10;
232 end
.tv_usec
= (vtime
% 10) * 100000;
234 timevaladd(&end
, &now
);
237 error
= tty_wait_background(tp
, curthread
, SIGTTIN
);
241 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
,
245 if (uio
->uio_resid
== 0 || (oresid
- uio
->uio_resid
) >= vmin
)
248 /* Calculate how long we should wait. */
250 if (timevalcmp(&now
, &end
, >))
253 timevalsub(&left
, &now
);
257 * We have to wait for more. If the timer expires, we
258 * should return a 0-byte read.
260 if (tp
->t_flags
& TF_ZOMBIE
)
262 else if (ioflag
& IO_NDELAY
)
263 return (EWOULDBLOCK
);
265 error
= tty_timedwait(tp
, &tp
->t_inwait
, hz
);
267 return (error
== EWOULDBLOCK
? 0 : error
);
274 ttydisc_read_raw_interbyte_timer(struct tty
*tp
, struct uio
*uio
, int ioflag
)
276 size_t vmin
= tp
->t_termios
.c_cc
[VMIN
];
277 ssize_t oresid
= uio
->uio_resid
;
280 MPASS(tp
->t_termios
.c_cc
[VMIN
] != 0);
281 MPASS(tp
->t_termios
.c_cc
[VTIME
] != 0);
284 * When using the interbyte timer, the timer should be started
285 * after the first byte has been received. We just call into the
286 * generic read timer code after we've received the first byte.
290 error
= tty_wait_background(tp
, curthread
, SIGTTIN
);
294 error
= ttyinq_read_uio(&tp
->t_inq
, tp
, uio
,
298 if (uio
->uio_resid
== 0 || (oresid
- uio
->uio_resid
) >= vmin
)
302 * Not enough data, but we did receive some, which means
303 * we'll now start using the interbyte timer.
305 if (oresid
!= uio
->uio_resid
)
308 /* We have to wait for more. */
309 if (tp
->t_flags
& TF_ZOMBIE
)
311 else if (ioflag
& IO_NDELAY
)
312 return (EWOULDBLOCK
);
314 error
= tty_wait(tp
, &tp
->t_inwait
);
319 return ttydisc_read_raw_read_timer(tp
, uio
, ioflag
, oresid
);
323 ttydisc_read(struct tty
*tp
, struct uio
*uio
, int ioflag
)
327 tty_lock_assert(tp
, MA_OWNED
);
329 if (uio
->uio_resid
== 0)
332 if (CMP_FLAG(l
, ICANON
))
333 error
= ttydisc_read_canonical(tp
, uio
, ioflag
);
334 else if (tp
->t_termios
.c_cc
[VTIME
] == 0)
335 error
= ttydisc_read_raw_no_timer(tp
, uio
, ioflag
);
336 else if (tp
->t_termios
.c_cc
[VMIN
] == 0)
337 error
= ttydisc_read_raw_read_timer(tp
, uio
, ioflag
,
340 error
= ttydisc_read_raw_interbyte_timer(tp
, uio
, ioflag
);
342 if (ttyinq_bytesleft(&tp
->t_inq
) >= tp
->t_inlow
||
343 ttyinq_bytescanonicalized(&tp
->t_inq
) == 0) {
344 /* Unset the input watermark when we've got enough space. */
345 tty_hiwat_in_unblock(tp
);
351 static __inline
unsigned int
352 ttydisc_findchar(const char *obstart
, unsigned int oblen
)
354 const char *c
= obstart
;
362 return (c
- obstart
);
366 ttydisc_write_oproc(struct tty
*tp
, char c
)
368 unsigned int scnt
, error
;
370 MPASS(CMP_FLAG(o
, OPOST
));
373 #define PRINT_NORMAL() ttyoutq_write_nofrag(&tp->t_outq, &c, 1)
376 /* End-of-text dropping. */
377 if (CMP_FLAG(o
, ONOEOT
))
379 return PRINT_NORMAL();
382 /* Handle backspace to fix tab expansion. */
383 if (PRINT_NORMAL() != 0)
385 if (tp
->t_column
> 0)
391 scnt
= 8 - (tp
->t_column
& 7);
392 if (CMP_FLAG(o
, TAB3
)) {
393 error
= ttyoutq_write_nofrag(&tp
->t_outq
,
396 error
= PRINT_NORMAL();
401 tp
->t_column
+= scnt
;
402 MPASS((tp
->t_column
% 8) == 0);
406 /* Newline conversion. */
407 if (CMP_FLAG(o
, ONLCR
)) {
408 /* Convert \n to \r\n. */
409 error
= ttyoutq_write_nofrag(&tp
->t_outq
, "\r\n", 2);
411 error
= PRINT_NORMAL();
416 if (CMP_FLAG(o
, ONLCR
|ONLRET
)) {
417 tp
->t_column
= tp
->t_writepos
= 0;
418 ttyinq_reprintpos_set(&tp
->t_inq
);
423 /* Carriage return to newline conversion. */
424 if (CMP_FLAG(o
, OCRNL
))
426 /* Omit carriage returns on column 0. */
427 if (CMP_FLAG(o
, ONOCR
) && tp
->t_column
== 0)
429 if (PRINT_NORMAL() != 0)
432 tp
->t_column
= tp
->t_writepos
= 0;
433 ttyinq_reprintpos_set(&tp
->t_inq
);
438 * Invisible control character. Print it, but don't
439 * increase the column count.
441 return PRINT_NORMAL();
446 * Just like the old TTY implementation, we need to copy data in chunks
447 * into a temporary buffer. One of the reasons why we need to do this,
448 * is because output processing (only TAB3 though) may allow the buffer
449 * to grow eight times.
452 ttydisc_write(struct tty
*tp
, struct uio
*uio
, int ioflag
)
454 char ob
[TTY_STACKBUF
];
457 unsigned int oblen
= 0;
459 tty_lock_assert(tp
, MA_OWNED
);
461 if (tp
->t_flags
& TF_ZOMBIE
)
465 * We don't need to check whether the process is the foreground
466 * process group or if we have a carrier. This is already done
470 while (uio
->uio_resid
> 0) {
475 /* Step 1: read data. */
477 nlen
= MIN(uio
->uio_resid
, sizeof ob
);
479 error
= uiomove(ob
, nlen
, uio
);
492 /* Step 2: process data. */
494 unsigned int plen
, wlen
;
496 /* Search for special characters for post processing. */
497 if (CMP_FLAG(o
, OPOST
)) {
498 plen
= ttydisc_findchar(obstart
, oblen
);
505 * We're going to process a character
506 * that needs processing
508 if (ttydisc_write_oproc(tp
, *obstart
) == 0) {
512 tp
->t_writepos
= tp
->t_column
;
513 ttyinq_reprintpos_set(&tp
->t_inq
);
517 /* We're going to write regular data. */
518 wlen
= ttyoutq_write(&tp
->t_outq
, obstart
, plen
);
521 tp
->t_column
+= wlen
;
523 tp
->t_writepos
= tp
->t_column
;
524 ttyinq_reprintpos_set(&tp
->t_inq
);
530 /* Watermark reached. Try to sleep. */
531 tp
->t_flags
|= TF_HIWAT_OUT
;
533 if (ioflag
& IO_NDELAY
) {
539 * The driver may write back the data
540 * synchronously. Be sure to check the high
541 * water mark before going to sleep.
543 ttydevsw_outwakeup(tp
);
544 if ((tp
->t_flags
& TF_HIWAT_OUT
) == 0)
547 error
= tty_wait(tp
, &tp
->t_outwait
);
551 if (tp
->t_flags
& TF_ZOMBIE
) {
560 ttydevsw_outwakeup(tp
);
563 * Add the amount of bytes that we didn't process back to the
564 * uio counters. We need to do this to make sure write() doesn't
565 * count the bytes we didn't store in the queue.
567 uio
->uio_resid
+= oblen
;
572 ttydisc_optimize(struct tty
*tp
)
574 tty_lock_assert(tp
, MA_OWNED
);
576 if (ttyhook_hashook(tp
, rint_bypass
)) {
577 tp
->t_flags
|= TF_BYPASS
;
578 } else if (ttyhook_hashook(tp
, rint
)) {
579 tp
->t_flags
&= ~TF_BYPASS
;
580 } else if (!CMP_FLAG(i
, ICRNL
|IGNCR
|IMAXBEL
|INLCR
|ISTRIP
|IXON
) &&
581 (!CMP_FLAG(i
, BRKINT
) || CMP_FLAG(i
, IGNBRK
)) &&
582 (!CMP_FLAG(i
, PARMRK
) ||
583 CMP_FLAG(i
, IGNPAR
|IGNBRK
) == (IGNPAR
|IGNBRK
)) &&
584 !CMP_FLAG(l
, ECHO
|ICANON
|IEXTEN
|ISIG
|PENDIN
)) {
585 tp
->t_flags
|= TF_BYPASS
;
587 tp
->t_flags
&= ~TF_BYPASS
;
592 ttydisc_modem(struct tty
*tp
, int open
)
595 tty_lock_assert(tp
, MA_OWNED
);
598 cv_broadcast(&tp
->t_dcdwait
);
601 * Ignore modem status lines when CLOCAL is turned on, but don't
602 * enter the zombie state when the TTY isn't opened, because
603 * that would cause the TTY to be in zombie state after being
606 if (!tty_opened(tp
) || CMP_FLAG(c
, CLOCAL
))
613 tp
->t_flags
|= TF_ZOMBIE
;
615 tty_signal_sessleader(tp
, SIGHUP
);
616 tty_flush(tp
, FREAD
|FWRITE
);
619 * Carrier is back again.
622 /* XXX: what should we do here? */
627 ttydisc_echo_force(struct tty
*tp
, char c
, int quote
)
630 if (CMP_FLAG(o
, OPOST
) && CTL_ECHO(c
, quote
)) {
632 * Only perform postprocessing when OPOST is turned on
633 * and the character is an unquoted BS/TB/NL/CR.
635 return ttydisc_write_oproc(tp
, c
);
636 } else if (CMP_FLAG(l
, ECHOCTL
) && CTL_PRINT(c
, quote
)) {
638 * Only use ^X notation when ECHOCTL is turned on and
639 * we've got an quoted control character.
641 * Print backspaces when echoing an end-of-file.
643 char ob
[4] = "^?\b\b";
645 /* Print ^X notation. */
649 if (!quote
&& CMP_CC(VEOF
, c
)) {
650 return ttyoutq_write_nofrag(&tp
->t_outq
, ob
, 4);
653 return ttyoutq_write_nofrag(&tp
->t_outq
, ob
, 2);
656 /* Can just be printed. */
658 return ttyoutq_write_nofrag(&tp
->t_outq
, &c
, 1);
663 ttydisc_echo(struct tty
*tp
, char c
, int quote
)
667 * Only echo characters when ECHO is turned on, or ECHONL when
668 * the character is an unquoted newline.
670 if (!CMP_FLAG(l
, ECHO
) &&
671 (!CMP_FLAG(l
, ECHONL
) || c
!= CNL
|| quote
))
674 return ttydisc_echo_force(tp
, c
, quote
);
678 ttydisc_reprint_char(void *d
, char c
, int quote
)
682 ttydisc_echo(tp
, c
, quote
);
686 ttydisc_reprint(struct tty
*tp
)
690 /* Print ^R\n, followed by the line. */
691 c
= tp
->t_termios
.c_cc
[VREPRINT
];
692 if (c
!= _POSIX_VDISABLE
)
693 ttydisc_echo(tp
, c
, 0);
694 ttydisc_echo(tp
, CNL
, 0);
695 ttyinq_reprintpos_reset(&tp
->t_inq
);
697 ttyinq_line_iterate_from_linestart(&tp
->t_inq
, ttydisc_reprint_char
, tp
);
700 struct ttydisc_recalc_length
{
706 ttydisc_recalc_charlength(void *d
, char c
, int quote
)
708 struct ttydisc_recalc_length
*data
= d
;
709 struct tty
*tp
= data
->tp
;
711 if (CTL_PRINT(c
, quote
)) {
712 if (CMP_FLAG(l
, ECHOCTL
))
714 } else if (c
== CTAB
) {
715 data
->curlen
+= 8 - (data
->curlen
& 7);
722 ttydisc_recalc_linelength(struct tty
*tp
)
724 struct ttydisc_recalc_length data
= { tp
, tp
->t_writepos
};
726 ttyinq_line_iterate_from_reprintpos(&tp
->t_inq
,
727 ttydisc_recalc_charlength
, &data
);
728 return (data
.curlen
);
732 ttydisc_rubchar(struct tty
*tp
)
736 unsigned int prevpos
, tablen
;
738 if (ttyinq_peekchar(&tp
->t_inq
, &c
, "e
) != 0)
740 ttyinq_unputchar(&tp
->t_inq
);
742 if (CMP_FLAG(l
, ECHO
)) {
744 * Remove the character from the screen. This is even
745 * safe for characters that span multiple characters
746 * (tabs, quoted, etc).
748 if (tp
->t_writepos
>= tp
->t_column
) {
749 /* Retype the sentence. */
751 } else if (CMP_FLAG(l
, ECHOE
)) {
752 if (CTL_PRINT(c
, quote
)) {
753 /* Remove ^X formatted chars. */
754 if (CMP_FLAG(l
, ECHOCTL
)) {
756 ttyoutq_write_nofrag(&tp
->t_outq
,
759 } else if (c
== ' ') {
760 /* Space character needs no rubbing. */
762 ttyoutq_write_nofrag(&tp
->t_outq
, "\b", 1);
763 } else if (c
== CTAB
) {
765 * Making backspace work with tabs is
766 * quite hard. Recalculate the length of
767 * this character and remove it.
769 * Because terminal settings could be
770 * changed while the line is being
771 * inserted, the calculations don't have
772 * to be correct. Make sure we keep the
773 * tab length within proper bounds.
775 prevpos
= ttydisc_recalc_linelength(tp
);
776 if (prevpos
>= tp
->t_column
)
779 tablen
= tp
->t_column
- prevpos
;
783 tp
->t_column
= prevpos
;
784 ttyoutq_write_nofrag(&tp
->t_outq
,
785 "\b\b\b\b\b\b\b\b", tablen
);
789 * Remove a regular character by
790 * punching a space over it.
793 ttyoutq_write_nofrag(&tp
->t_outq
, "\b \b", 3);
796 /* Don't print spaces. */
797 ttydisc_echo(tp
, tp
->t_termios
.c_cc
[VERASE
], 0);
805 ttydisc_rubword(struct tty
*tp
)
810 /* Strip whitespace first. */
812 if (ttyinq_peekchar(&tp
->t_inq
, &c
, "e
) != 0)
820 * Record whether the last character from the previous iteration
821 * was alphanumeric or not. We need this to implement ALTWERASE.
823 alnum
= CTL_ALNUM(c
);
827 if (ttyinq_peekchar(&tp
->t_inq
, &c
, "e
) != 0)
831 if (CMP_FLAG(l
, ALTWERASE
) && CTL_ALNUM(c
) != alnum
)
837 ttydisc_rint(struct tty
*tp
, char c
, int flags
)
839 int signal
, quote
= 0;
840 char ob
[3] = { 0xff, 0x00 };
843 tty_lock_assert(tp
, MA_OWNED
);
845 atomic_add_long(&tty_nin
, 1);
847 if (ttyhook_hashook(tp
, rint
))
848 return ttyhook_rint(tp
, c
, flags
);
850 if (tp
->t_flags
& TF_BYPASS
)
854 if (flags
& TRE_BREAK
) {
855 if (CMP_FLAG(i
, IGNBRK
)) {
856 /* Ignore break characters. */
858 } else if (CMP_FLAG(i
, BRKINT
)) {
859 /* Generate SIGINT on break. */
860 tty_flush(tp
, FREAD
|FWRITE
);
861 tty_signal_pgrp(tp
, SIGINT
);
867 } else if (flags
& TRE_FRAMING
||
868 (flags
& TRE_PARITY
&& CMP_FLAG(i
, INPCK
))) {
869 if (CMP_FLAG(i
, IGNPAR
)) {
870 /* Ignore bad characters. */
879 /* Allow any character to perform a wakeup. */
880 if (CMP_FLAG(i
, IXANY
))
881 tp
->t_flags
&= ~TF_STOPPED
;
883 /* Remove the top bit. */
884 if (CMP_FLAG(i
, ISTRIP
))
887 /* Skip input processing when we want to print it literally. */
888 if (tp
->t_flags
& TF_LITERAL
) {
889 tp
->t_flags
&= ~TF_LITERAL
;
894 /* Special control characters that are implementation dependent. */
895 if (CMP_FLAG(l
, IEXTEN
)) {
896 /* Accept the next character as literal. */
897 if (CMP_CC(VLNEXT
, c
)) {
898 if (CMP_FLAG(l
, ECHO
)) {
899 if (CMP_FLAG(l
, ECHOE
))
900 ttyoutq_write_nofrag(&tp
->t_outq
, "^\b", 2);
902 ttydisc_echo(tp
, c
, 0);
904 tp
->t_flags
|= TF_LITERAL
;
910 * Handle signal processing.
912 if (CMP_FLAG(l
, ISIG
)) {
913 if (CMP_FLAG(l
, ICANON
|IEXTEN
) == (ICANON
|IEXTEN
)) {
914 if (CMP_CC(VSTATUS
, c
)) {
915 tty_signal_pgrp(tp
, SIGINFO
);
921 * When compared to the old implementation, this
922 * implementation also flushes the output queue. POSIX
923 * is really brief about this, but does makes us assume
927 if (CMP_CC(VINTR
, c
)) {
929 } else if (CMP_CC(VQUIT
, c
)) {
931 } else if (CMP_CC(VSUSP
, c
)) {
937 * Echo the character before signalling the
940 if (!CMP_FLAG(l
, NOFLSH
))
941 tty_flush(tp
, FREAD
|FWRITE
);
942 ttydisc_echo(tp
, c
, 0);
943 tty_signal_pgrp(tp
, signal
);
949 * Handle start/stop characters.
951 if (CMP_FLAG(i
, IXON
)) {
952 if (CMP_CC(VSTOP
, c
)) {
953 /* Stop it if we aren't stopped yet. */
954 if ((tp
->t_flags
& TF_STOPPED
) == 0) {
955 tp
->t_flags
|= TF_STOPPED
;
960 * When VSTART == VSTOP, we should make this key
963 if (!CMP_CC(VSTART
, c
))
966 if (CMP_CC(VSTART
, c
)) {
967 tp
->t_flags
&= ~TF_STOPPED
;
972 /* Conversion of CR and NL. */
975 if (CMP_FLAG(i
, IGNCR
))
977 if (CMP_FLAG(i
, ICRNL
))
981 if (CMP_FLAG(i
, INLCR
))
986 /* Canonical line editing. */
987 if (CMP_FLAG(l
, ICANON
)) {
988 if (CMP_CC(VERASE
, c
) || CMP_CC(VERASE2
, c
)) {
991 } else if (CMP_CC(VKILL
, c
)) {
992 while (ttydisc_rubchar(tp
) == 0);
994 } else if (CMP_FLAG(l
, IEXTEN
)) {
995 if (CMP_CC(VWERASE
, c
)) {
998 } else if (CMP_CC(VREPRINT
, c
)) {
1006 if (CMP_FLAG(i
, PARMRK
) && (unsigned char)c
== 0xff) {
1007 /* Print 0xff 0xff. */
1019 if (CMP_FLAG(i
, PARMRK
)) {
1020 /* Prepend 0xff 0x00 0x.. */
1030 /* See if we can store this on the input queue. */
1031 if (ttyinq_write_nofrag(&tp
->t_inq
, ob
, ol
, quote
) != 0) {
1032 if (CMP_FLAG(i
, IMAXBEL
))
1033 ttyoutq_write_nofrag(&tp
->t_outq
, "\a", 1);
1036 * Prevent a deadlock here. It may be possible that a
1037 * user has entered so much data, there is no data
1038 * available to read(), but the buffers are full anyway.
1040 * Only enter the high watermark if the device driver
1041 * can actually transmit something.
1043 if (ttyinq_bytescanonicalized(&tp
->t_inq
) == 0)
1046 tty_hiwat_in_block(tp
);
1051 * In raw mode, we canonicalize after receiving a single
1052 * character. Otherwise, we canonicalize when we receive a
1053 * newline, VEOL or VEOF, but only when it isn't quoted.
1055 if (!CMP_FLAG(l
, ICANON
) ||
1056 (!quote
&& (c
== CNL
|| CMP_CC(VEOL
, c
) || CMP_CC(VEOF
, c
)))) {
1057 ttyinq_canonicalize(&tp
->t_inq
);
1060 ttydisc_echo(tp
, c
, quote
);
1066 ttydisc_rint_simple(struct tty
*tp
, const void *buf
, size_t len
)
1070 if (ttydisc_can_bypass(tp
))
1071 return (ttydisc_rint_bypass(tp
, buf
, len
));
1073 for (cbuf
= buf
; len
-- > 0; cbuf
++) {
1074 if (ttydisc_rint(tp
, *cbuf
, 0) != 0)
1078 return (cbuf
- (const char *)buf
);
1082 ttydisc_rint_bypass(struct tty
*tp
, const void *buf
, size_t len
)
1086 tty_lock_assert(tp
, MA_OWNED
);
1088 MPASS(tp
->t_flags
& TF_BYPASS
);
1090 atomic_add_long(&tty_nin
, len
);
1092 if (ttyhook_hashook(tp
, rint_bypass
))
1093 return ttyhook_rint_bypass(tp
, buf
, len
);
1095 ret
= ttyinq_write(&tp
->t_inq
, buf
, len
, 0);
1096 ttyinq_canonicalize(&tp
->t_inq
);
1098 tty_hiwat_in_block(tp
);
1104 ttydisc_rint_done(struct tty
*tp
)
1107 tty_lock_assert(tp
, MA_OWNED
);
1109 if (ttyhook_hashook(tp
, rint_done
))
1110 ttyhook_rint_done(tp
);
1112 /* Wake up readers. */
1113 tty_wakeup(tp
, FREAD
);
1114 /* Wake up driver for echo. */
1115 ttydevsw_outwakeup(tp
);
1119 ttydisc_rint_poll(struct tty
*tp
)
1123 tty_lock_assert(tp
, MA_OWNED
);
1125 if (ttyhook_hashook(tp
, rint_poll
))
1126 return ttyhook_rint_poll(tp
);
1129 * XXX: Still allow character input when there's no space in the
1130 * buffers, but we haven't entered the high watermark. This is
1131 * to allow backspace characters to be inserted when in
1134 l
= ttyinq_bytesleft(&tp
->t_inq
);
1135 if (l
== 0 && (tp
->t_flags
& TF_HIWAT_IN
) == 0)
1142 ttydisc_wakeup_watermark(struct tty
*tp
)
1146 c
= ttyoutq_bytesleft(&tp
->t_outq
);
1147 if (tp
->t_flags
& TF_HIWAT_OUT
) {
1148 /* Only allow us to run when we're below the watermark. */
1149 if (c
< tp
->t_outlow
)
1152 /* Reset the watermark. */
1153 tp
->t_flags
&= ~TF_HIWAT_OUT
;
1155 /* Only run when we have data at all. */
1159 tty_wakeup(tp
, FWRITE
);
1163 ttydisc_getc(struct tty
*tp
, void *buf
, size_t len
)
1166 tty_lock_assert(tp
, MA_OWNED
);
1168 if (tp
->t_flags
& TF_STOPPED
)
1171 if (ttyhook_hashook(tp
, getc_inject
))
1172 return ttyhook_getc_inject(tp
, buf
, len
);
1174 len
= ttyoutq_read(&tp
->t_outq
, buf
, len
);
1176 if (ttyhook_hashook(tp
, getc_capture
))
1177 ttyhook_getc_capture(tp
, buf
, len
);
1179 ttydisc_wakeup_watermark(tp
);
1180 atomic_add_long(&tty_nout
, len
);
1186 ttydisc_getc_uio(struct tty
*tp
, struct uio
*uio
)
1189 ssize_t obytes
= uio
->uio_resid
;
1191 char buf
[TTY_STACKBUF
];
1193 tty_lock_assert(tp
, MA_OWNED
);
1195 if (tp
->t_flags
& TF_STOPPED
)
1199 * When a TTY hook is attached, we cannot perform unbuffered
1200 * copying to userspace. Just call ttydisc_getc() and
1201 * temporarily store data in a shadow buffer.
1203 if (ttyhook_hashook(tp
, getc_capture
) ||
1204 ttyhook_hashook(tp
, getc_inject
)) {
1205 while (uio
->uio_resid
> 0) {
1206 /* Read to shadow buffer. */
1207 len
= ttydisc_getc(tp
, buf
,
1208 MIN(uio
->uio_resid
, sizeof buf
));
1212 /* Copy to userspace. */
1214 error
= uiomove(buf
, len
, uio
);
1221 error
= ttyoutq_read_uio(&tp
->t_outq
, tp
, uio
);
1223 ttydisc_wakeup_watermark(tp
);
1224 atomic_add_long(&tty_nout
, obytes
- uio
->uio_resid
);
1231 ttydisc_getc_poll(struct tty
*tp
)
1234 tty_lock_assert(tp
, MA_OWNED
);
1236 if (tp
->t_flags
& TF_STOPPED
)
1239 if (ttyhook_hashook(tp
, getc_poll
))
1240 return ttyhook_getc_poll(tp
);
1242 return ttyoutq_bytesused(&tp
->t_outq
);
1246 * XXX: not really related to the TTYDISC, but we'd better put
1247 * tty_putchar() here, because we need to perform proper output
1252 tty_putchar(struct tty
*tp
, char c
)
1254 tty_lock_assert(tp
, MA_OWNED
);
1259 ttydisc_echo_force(tp
, c
, 0);
1260 tp
->t_writepos
= tp
->t_column
;
1261 ttyinq_reprintpos_set(&tp
->t_inq
);
1263 ttydevsw_outwakeup(tp
);