1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Portions of this software were developed under sponsorship from Snow
8 * B.V., the Netherlands.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/fcntl.h>
34#include <sys/filio.h>
35#include <sys/kernel.h>
36#include <sys/signal.h>
37#include <sys/sysctl.h>
38#include <sys/systm.h>
39#include <sys/tty.h>
40#include <sys/ttycom.h>
41#include <sys/ttydefaults.h>
42#include <sys/uio.h>
43#include <sys/vnode.h>
44
45#include <teken/teken.h>
46#include <teken/teken_wcwidth.h>
47
48/*
49 * Standard TTYDISC `termios' line discipline.
50 */
51
52/* Statistics. */
53static unsigned long tty_nin = 0;
54SYSCTL_ULONG(_kern, OID_AUTO, tty_nin, CTLFLAG_RD,
55	&tty_nin, 0, "Total amount of bytes received");
56static unsigned long tty_nout = 0;
57SYSCTL_ULONG(_kern, OID_AUTO, tty_nout, CTLFLAG_RD,
58	&tty_nout, 0, "Total amount of bytes transmitted");
59
60/* termios comparison macro's. */
61#define	CMP_CC(v,c) (tp->t_termios.c_cc[v] != _POSIX_VDISABLE && \
62			tp->t_termios.c_cc[v] == (c))
63#define	CMP_FLAG(field,opt) (tp->t_termios.c_ ## field ## flag & (opt))
64
65/* Characters that cannot be modified through c_cc. */
66#define CTAB	'\t'
67#define CNL	'\n'
68#define CCR	'\r'
69
70/* Character is a control character. */
71#define CTL_VALID(c)	((c) == 0x7f || (unsigned char)(c) < 0x20)
72/* Control character should be processed on echo. */
73#define CTL_ECHO(c,q)	(!(q) && ((c) == CERASE2 || (c) == CTAB || \
74    (c) == CNL || (c) == CCR))
75/* Control character should be printed using ^X notation. */
76#define CTL_PRINT(c,q)	((c) == 0x7f || ((unsigned char)(c) < 0x20 && \
77    ((q) || ((c) != CTAB && (c) != CNL))))
78/* Character is whitespace. */
79#define CTL_WHITE(c)	((c) == ' ' || (c) == CTAB)
80/* Character is alphanumeric. */
81#define CTL_ALNUM(c)	(((c) >= '0' && (c) <= '9') || \
82    ((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
83/* Character is UTF8-encoded. */
84#define CTL_UTF8(c) (!!((c) & 0x80))
85/* Character is a UTF8 continuation byte. */
86#define CTL_UTF8_CONT(c) (((c) & 0xc0) == 0x80)
87
88#define	TTY_STACKBUF	256
89#define UTF8_STACKBUF 4
90
91void
92ttydisc_open(struct tty *tp)
93{
94	ttydisc_optimize(tp);
95}
96
97void
98ttydisc_close(struct tty *tp)
99{
100
101	/* Clean up our flags when leaving the discipline. */
102	tp->t_flags &= ~(TF_STOPPED|TF_HIWAT|TF_ZOMBIE);
103	tp->t_termios.c_lflag &= ~FLUSHO;
104
105	/*
106	 * POSIX states that we must drain output and flush input on
107	 * last close.  Draining has already been done if possible.
108	 */
109	tty_flush(tp, FREAD | FWRITE);
110
111	if (ttyhook_hashook(tp, close))
112		ttyhook_close(tp);
113}
114
115/*
116 * Populate our break array; it should likely be at least 4 bytes in size to
117 * allow for \n, VEOF, and VEOL.
118 */
119static void
120ttydisc_read_break(struct tty *tp, char *breakc, size_t breaksz)
121{
122	size_t n = 0;
123
124	MPASS(breaksz != 0);
125
126	breakc[n++] = CNL;
127#define BREAK_ADD(c) do { \
128	MPASS(n < breaksz - 1);	/* NUL terminated */	\
129	if (tp->t_termios.c_cc[c] != _POSIX_VDISABLE)	\
130		breakc[n++] = tp->t_termios.c_cc[c];	\
131} while (0)
132	/* Determine which characters we should trigger on. */
133	BREAK_ADD(VEOF);
134	BREAK_ADD(VEOL);
135#undef BREAK_ADD
136
137	breakc[n] = '\0';
138}
139
140size_t
141ttydisc_bytesavail(struct tty *tp)
142{
143	size_t clen;
144	char breakc[4];
145	unsigned char lastc = _POSIX_VDISABLE;
146
147	clen = ttyinq_bytescanonicalized(&tp->t_inq);
148	if (!CMP_FLAG(l, ICANON) || clen == 0)
149		return (clen);
150
151	ttydisc_read_break(tp, &breakc[0], sizeof(breakc));
152	clen = ttyinq_findchar(&tp->t_inq, breakc, clen, &lastc);
153
154	/*
155	 * We might have a partial line canonicalized in the input queue if we,
156	 * for instance, switched to ICANON after taking some input in raw mode.
157	 * In this case, read(2) will block because we only have a partial line.
158	 */
159	if (lastc == _POSIX_VDISABLE)
160		return (0);
161
162	/* If VEOF was our terminal, it must be discarded (not counted). */
163	if (CMP_CC(VEOF, lastc))
164		clen--;
165
166	return (clen);
167}
168
169void
170ttydisc_canonicalize(struct tty *tp)
171{
172	char breakc[4];
173
174	/*
175	 * If we're in non-canonical mode, it's as easy as just canonicalizing
176	 * the current partial line.
177	 */
178	if (!CMP_FLAG(l, ICANON)) {
179		ttyinq_canonicalize(&tp->t_inq);
180		return;
181	}
182
183	/*
184	 * For canonical mode, we need to rescan the buffer for the last EOL
185	 * indicator.
186	 */
187	ttydisc_read_break(tp, &breakc[0], sizeof(breakc));
188	ttyinq_canonicalize_break(&tp->t_inq, breakc);
189}
190
191static int
192ttydisc_read_canonical(struct tty *tp, struct uio *uio, int ioflag)
193{
194	char breakc[4]; /* enough to hold \n, VEOF and VEOL. */
195	int error;
196	size_t clen, flen = 0;
197	unsigned char lastc = _POSIX_VDISABLE;
198
199	ttydisc_read_break(tp, &breakc[0], sizeof(breakc));
200
201	do {
202		error = tty_wait_background(tp, curthread, SIGTTIN);
203		if (error)
204			return (error);
205
206		/*
207		 * Quite a tricky case: unlike the old TTY
208		 * implementation, this implementation copies data back
209		 * to userspace in large chunks. Unfortunately, we can't
210		 * calculate the line length on beforehand if it crosses
211		 * ttyinq_block boundaries, because multiple reads could
212		 * then make this code read beyond the newline.
213		 *
214		 * This is why we limit the read to:
215		 * - The size the user has requested
216		 * - The blocksize (done in tty_inq.c)
217		 * - The amount of bytes until the newline
218		 *
219		 * This causes the line length to be recalculated after
220		 * each block has been copied to userspace. This will
221		 * cause the TTY layer to return data in chunks using
222		 * the blocksize (except the first and last blocks).
223		 */
224		clen = ttyinq_findchar(&tp->t_inq, breakc, uio->uio_resid + 1,
225		    &lastc);
226
227		/* No more data. */
228		if (clen == 0) {
229			if (tp->t_flags & TF_ZOMBIE)
230				return (0);
231			else if (ioflag & IO_NDELAY)
232				return (EWOULDBLOCK);
233
234			error = tty_wait(tp, &tp->t_inwait);
235			if (error)
236				return (error);
237			continue;
238		}
239
240		/*
241		 * Don't send the EOF char back to userspace.  Our above call to
242		 * ttyinq_findchar overreads by 1 character in case we would
243		 * otherwise be leaving an EOF for the next read().  We'll trim
244		 * clen back down to uio_resid whether we find our EOF or not.
245		 */
246		if (CMP_CC(VEOF, lastc))
247			flen = 1;
248
249		/*
250		 * Trim clen back down to the buffer size, since we had
251		 * intentionally over-read.
252		 */
253		clen = MIN(uio->uio_resid + flen, clen);
254		MPASS(flen <= clen);
255
256		/* Read and throw away the EOF character. */
257		error = ttyinq_read_uio(&tp->t_inq, tp, uio, clen, flen);
258		if (error)
259			return (error);
260
261	} while (uio->uio_resid > 0 && lastc == _POSIX_VDISABLE);
262
263	return (0);
264}
265
266static int
267ttydisc_read_raw_no_timer(struct tty *tp, struct uio *uio, int ioflag)
268{
269	size_t vmin = tp->t_termios.c_cc[VMIN];
270	ssize_t oresid = uio->uio_resid;
271	int error;
272
273	MPASS(tp->t_termios.c_cc[VTIME] == 0);
274
275	/*
276	 * This routine implements the easy cases of read()s while in
277	 * non-canonical mode, namely case B and D, where we don't have
278	 * any timers at all.
279	 */
280
281	for (;;) {
282		error = tty_wait_background(tp, curthread, SIGTTIN);
283		if (error)
284			return (error);
285
286		error = ttyinq_read_uio(&tp->t_inq, tp, uio,
287		    uio->uio_resid, 0);
288		if (error)
289			return (error);
290		if (uio->uio_resid == 0 || (oresid - uio->uio_resid) >= vmin)
291			return (0);
292
293		/* We have to wait for more. */
294		if (tp->t_flags & TF_ZOMBIE)
295			return (0);
296		else if (ioflag & IO_NDELAY)
297			return (EWOULDBLOCK);
298
299		error = tty_wait(tp, &tp->t_inwait);
300		if (error)
301			return (error);
302	}
303}
304
305static int
306ttydisc_read_raw_read_timer(struct tty *tp, struct uio *uio, int ioflag,
307    int oresid)
308{
309	size_t vmin = MAX(tp->t_termios.c_cc[VMIN], 1);
310	unsigned int vtime = tp->t_termios.c_cc[VTIME];
311	struct timeval end, now, left;
312	int error, hz;
313
314	MPASS(tp->t_termios.c_cc[VTIME] != 0);
315
316	/* Determine when the read should be expired. */
317	end.tv_sec = vtime / 10;
318	end.tv_usec = (vtime % 10) * 100000;
319	getmicrotime(&now);
320	timevaladd(&end, &now);
321
322	for (;;) {
323		error = tty_wait_background(tp, curthread, SIGTTIN);
324		if (error)
325			return (error);
326
327		error = ttyinq_read_uio(&tp->t_inq, tp, uio,
328		    uio->uio_resid, 0);
329		if (error)
330			return (error);
331		if (uio->uio_resid == 0 || (oresid - uio->uio_resid) >= vmin)
332			return (0);
333
334		/* Calculate how long we should wait. */
335		getmicrotime(&now);
336		if (timevalcmp(&now, &end, >))
337			return (0);
338		left = end;
339		timevalsub(&left, &now);
340		hz = tvtohz(&left);
341
342		/*
343		 * We have to wait for more. If the timer expires, we
344		 * should return a 0-byte read.
345		 */
346		if (tp->t_flags & TF_ZOMBIE)
347			return (0);
348		else if (ioflag & IO_NDELAY)
349			return (EWOULDBLOCK);
350
351		error = tty_timedwait(tp, &tp->t_inwait, hz);
352		if (error)
353			return (error == EWOULDBLOCK ? 0 : error);
354	}
355
356	return (0);
357}
358
359static int
360ttydisc_read_raw_interbyte_timer(struct tty *tp, struct uio *uio, int ioflag)
361{
362	size_t vmin = tp->t_termios.c_cc[VMIN];
363	ssize_t oresid = uio->uio_resid;
364	int error;
365
366	MPASS(tp->t_termios.c_cc[VMIN] != 0);
367	MPASS(tp->t_termios.c_cc[VTIME] != 0);
368
369	/*
370	 * When using the interbyte timer, the timer should be started
371	 * after the first byte has been received. We just call into the
372	 * generic read timer code after we've received the first byte.
373	 */
374
375	for (;;) {
376		error = tty_wait_background(tp, curthread, SIGTTIN);
377		if (error)
378			return (error);
379
380		error = ttyinq_read_uio(&tp->t_inq, tp, uio,
381		    uio->uio_resid, 0);
382		if (error)
383			return (error);
384		if (uio->uio_resid == 0 || (oresid - uio->uio_resid) >= vmin)
385			return (0);
386
387		/*
388		 * Not enough data, but we did receive some, which means
389		 * we'll now start using the interbyte timer.
390		 */
391		if (oresid != uio->uio_resid)
392			break;
393
394		/* We have to wait for more. */
395		if (tp->t_flags & TF_ZOMBIE)
396			return (0);
397		else if (ioflag & IO_NDELAY)
398			return (EWOULDBLOCK);
399
400		error = tty_wait(tp, &tp->t_inwait);
401		if (error)
402			return (error);
403	}
404
405	return ttydisc_read_raw_read_timer(tp, uio, ioflag, oresid);
406}
407
408int
409ttydisc_read(struct tty *tp, struct uio *uio, int ioflag)
410{
411	int error;
412
413	tty_assert_locked(tp);
414
415	if (uio->uio_resid == 0)
416		return (0);
417
418	if (CMP_FLAG(l, ICANON))
419		error = ttydisc_read_canonical(tp, uio, ioflag);
420	else if (tp->t_termios.c_cc[VTIME] == 0)
421		error = ttydisc_read_raw_no_timer(tp, uio, ioflag);
422	else if (tp->t_termios.c_cc[VMIN] == 0)
423		error = ttydisc_read_raw_read_timer(tp, uio, ioflag,
424		    uio->uio_resid);
425	else
426		error = ttydisc_read_raw_interbyte_timer(tp, uio, ioflag);
427
428	if (ttyinq_bytesleft(&tp->t_inq) >= tp->t_inlow ||
429	    ttyinq_bytescanonicalized(&tp->t_inq) == 0) {
430		/* Unset the input watermark when we've got enough space. */
431		tty_hiwat_in_unblock(tp);
432	}
433
434	return (error);
435}
436
437static __inline unsigned int
438ttydisc_findchar(const char *obstart, unsigned int oblen)
439{
440	const char *c = obstart;
441
442	while (oblen--) {
443		if (CTL_VALID(*c))
444			break;
445		c++;
446	}
447
448	return (c - obstart);
449}
450
451static int
452ttydisc_write_oproc(struct tty *tp, char c)
453{
454	unsigned int scnt, error;
455
456	MPASS(CMP_FLAG(o, OPOST));
457	MPASS(CTL_VALID(c));
458
459#define PRINT_NORMAL() ttyoutq_write_nofrag(&tp->t_outq, &c, 1)
460	switch (c) {
461	case CEOF:
462		/* End-of-text dropping. */
463		if (CMP_FLAG(o, ONOEOT))
464			return (0);
465		return PRINT_NORMAL();
466
467	case CERASE2:
468		/* Handle backspace to fix tab expansion. */
469		if (PRINT_NORMAL() != 0)
470			return (-1);
471		if (tp->t_column > 0)
472			tp->t_column--;
473		return (0);
474
475	case CTAB:
476		/* Tab expansion. */
477		scnt = 8 - (tp->t_column & 7);
478		if (CMP_FLAG(o, TAB3)) {
479			error = ttyoutq_write_nofrag(&tp->t_outq,
480			    "        ", scnt);
481		} else {
482			error = PRINT_NORMAL();
483		}
484		if (error)
485			return (-1);
486
487		tp->t_column += scnt;
488		MPASS((tp->t_column % 8) == 0);
489		return (0);
490
491	case CNL:
492		/* Newline conversion. */
493		if (CMP_FLAG(o, ONLCR)) {
494			/* Convert \n to \r\n. */
495			error = ttyoutq_write_nofrag(&tp->t_outq, "\r\n", 2);
496		} else {
497			error = PRINT_NORMAL();
498		}
499		if (error)
500			return (-1);
501
502		if (CMP_FLAG(o, ONLCR|ONLRET)) {
503			tp->t_column = tp->t_writepos = 0;
504			ttyinq_reprintpos_set(&tp->t_inq);
505		}
506		return (0);
507
508	case CCR:
509		/* Carriage return to newline conversion. */
510		if (CMP_FLAG(o, OCRNL))
511			c = CNL;
512		/* Omit carriage returns on column 0. */
513		if (CMP_FLAG(o, ONOCR) && tp->t_column == 0)
514			return (0);
515		if (PRINT_NORMAL() != 0)
516			return (-1);
517
518		tp->t_column = tp->t_writepos = 0;
519		ttyinq_reprintpos_set(&tp->t_inq);
520		return (0);
521	}
522
523	/*
524	 * Invisible control character. Print it, but don't
525	 * increase the column count.
526	 */
527	return PRINT_NORMAL();
528#undef PRINT_NORMAL
529}
530
531/*
532 * Just like the old TTY implementation, we need to copy data in chunks
533 * into a temporary buffer. One of the reasons why we need to do this,
534 * is because output processing (only TAB3 though) may allow the buffer
535 * to grow eight times.
536 */
537int
538ttydisc_write(struct tty *tp, struct uio *uio, int ioflag)
539{
540	char ob[TTY_STACKBUF];
541	char *obstart;
542	int error = 0;
543	unsigned int oblen = 0;
544
545	tty_assert_locked(tp);
546
547	if (tp->t_flags & TF_ZOMBIE)
548		return (EIO);
549
550	/*
551	 * We don't need to check whether the process is the foreground
552	 * process group or if we have a carrier. This is already done
553	 * in ttydev_write().
554	 */
555
556	while (uio->uio_resid > 0) {
557		unsigned int nlen;
558
559		MPASS(oblen == 0);
560
561		if (CMP_FLAG(l, FLUSHO)) {
562			uio->uio_offset += uio->uio_resid;
563			uio->uio_resid = 0;
564			return (0);
565		}
566
567		/* Step 1: read data. */
568		obstart = ob;
569		nlen = MIN(uio->uio_resid, sizeof ob);
570		tty_unlock(tp);
571		error = uiomove(ob, nlen, uio);
572		tty_lock(tp);
573		if (error != 0)
574			break;
575		oblen = nlen;
576
577		if (tty_gone(tp)) {
578			error = ENXIO;
579			break;
580		}
581
582		MPASS(oblen > 0);
583
584		/* Step 2: process data. */
585		do {
586			unsigned int plen, wlen;
587
588			if (CMP_FLAG(l, FLUSHO)) {
589				uio->uio_offset += uio->uio_resid;
590				uio->uio_resid = 0;
591				return (0);
592			}
593
594			/* Search for special characters for post processing. */
595			if (CMP_FLAG(o, OPOST)) {
596				plen = ttydisc_findchar(obstart, oblen);
597			} else {
598				plen = oblen;
599			}
600
601			if (plen == 0) {
602				/*
603				 * We're going to process a character
604				 * that needs processing
605				 */
606				if (ttydisc_write_oproc(tp, *obstart) == 0) {
607					obstart++;
608					oblen--;
609
610					tp->t_writepos = tp->t_column;
611					ttyinq_reprintpos_set(&tp->t_inq);
612					continue;
613				}
614			} else {
615				/* We're going to write regular data. */
616				wlen = ttyoutq_write(&tp->t_outq, obstart, plen);
617				obstart += wlen;
618				oblen -= wlen;
619				tp->t_column += wlen;
620
621				tp->t_writepos = tp->t_column;
622				ttyinq_reprintpos_set(&tp->t_inq);
623
624				if (wlen == plen)
625					continue;
626			}
627
628			/* Watermark reached. Try to sleep. */
629			tp->t_flags |= TF_HIWAT_OUT;
630
631			if (ioflag & IO_NDELAY) {
632				error = EWOULDBLOCK;
633				goto done;
634			}
635
636			/*
637			 * The driver may write back the data
638			 * synchronously. Be sure to check the high
639			 * water mark before going to sleep.
640			 */
641			ttydevsw_outwakeup(tp);
642			if ((tp->t_flags & TF_HIWAT_OUT) == 0)
643				continue;
644
645			error = tty_wait(tp, &tp->t_outwait);
646			if (error)
647				goto done;
648
649			if (tp->t_flags & TF_ZOMBIE) {
650				error = EIO;
651				goto done;
652			}
653		} while (oblen > 0);
654	}
655
656done:
657	if (!tty_gone(tp))
658		ttydevsw_outwakeup(tp);
659
660	/*
661	 * Add the amount of bytes that we didn't process back to the
662	 * uio counters. We need to do this to make sure write() doesn't
663	 * count the bytes we didn't store in the queue.
664	 */
665	uio->uio_resid += oblen;
666	return (error);
667}
668
669void
670ttydisc_optimize(struct tty *tp)
671{
672	tty_assert_locked(tp);
673
674	if (ttyhook_hashook(tp, rint_bypass)) {
675		tp->t_flags |= TF_BYPASS;
676	} else if (ttyhook_hashook(tp, rint)) {
677		tp->t_flags &= ~TF_BYPASS;
678	} else if (!CMP_FLAG(i, ICRNL|IGNCR|IMAXBEL|INLCR|ISTRIP|IXON) &&
679	    (!CMP_FLAG(i, BRKINT) || CMP_FLAG(i, IGNBRK)) &&
680	    (!CMP_FLAG(i, PARMRK) ||
681		CMP_FLAG(i, IGNPAR|IGNBRK) == (IGNPAR|IGNBRK)) &&
682	    !CMP_FLAG(l, ECHO|ICANON|IEXTEN|ISIG|PENDIN)) {
683		tp->t_flags |= TF_BYPASS;
684	} else {
685		tp->t_flags &= ~TF_BYPASS;
686	}
687}
688
689void
690ttydisc_modem(struct tty *tp, int open)
691{
692
693	tty_assert_locked(tp);
694
695	if (open)
696		cv_broadcast(&tp->t_dcdwait);
697
698	/*
699	 * Ignore modem status lines when CLOCAL is turned on, but don't
700	 * enter the zombie state when the TTY isn't opened, because
701	 * that would cause the TTY to be in zombie state after being
702	 * opened.
703	 */
704	if (!tty_opened(tp) || CMP_FLAG(c, CLOCAL))
705		return;
706
707	if (open == 0) {
708		/*
709		 * Lost carrier.
710		 */
711		tp->t_flags |= TF_ZOMBIE;
712
713		tty_signal_sessleader(tp, SIGHUP);
714		tty_flush(tp, FREAD|FWRITE);
715	} else {
716		/*
717		 * Carrier is back again.
718		 */
719
720		/* XXX: what should we do here? */
721	}
722}
723
724static int
725ttydisc_echo_force(struct tty *tp, char c, int quote)
726{
727
728	if (CMP_FLAG(l, FLUSHO))
729		return 0;
730
731	if (CMP_FLAG(o, OPOST) && CTL_ECHO(c, quote)) {
732		/*
733		 * Only perform postprocessing when OPOST is turned on
734		 * and the character is an unquoted BS/TB/NL/CR.
735		 */
736		return ttydisc_write_oproc(tp, c);
737	} else if (CMP_FLAG(l, ECHOCTL) && CTL_PRINT(c, quote)) {
738		/*
739		 * Only use ^X notation when ECHOCTL is turned on and
740		 * we've got an quoted control character.
741		 *
742		 * Print backspaces when echoing an end-of-file.
743		 */
744		char ob[4] = "^?\b\b";
745
746		/* Print ^X notation. */
747		if (c != 0x7f)
748			ob[1] = c + 'A' - 1;
749
750		if (!quote && CMP_CC(VEOF, c)) {
751			return ttyoutq_write_nofrag(&tp->t_outq, ob, 4);
752		} else {
753			tp->t_column += 2;
754			return ttyoutq_write_nofrag(&tp->t_outq, ob, 2);
755		}
756	} else {
757		/* Can just be printed. */
758		tp->t_column++;
759		return ttyoutq_write_nofrag(&tp->t_outq, &c, 1);
760	}
761}
762
763static int
764ttydisc_echo(struct tty *tp, char c, int quote)
765{
766
767	/*
768	 * Only echo characters when ECHO is turned on, or ECHONL when
769	 * the character is an unquoted newline.
770	 */
771	if (!CMP_FLAG(l, ECHO) &&
772	    (!CMP_FLAG(l, ECHONL) || c != CNL || quote))
773		return (0);
774
775	return ttydisc_echo_force(tp, c, quote);
776}
777
778static void
779ttydisc_reprint_char(void *d, char c, int quote)
780{
781	struct tty *tp = d;
782
783	ttydisc_echo(tp, c, quote);
784}
785
786static void
787ttydisc_reprint(struct tty *tp)
788{
789	cc_t c;
790
791	/* Print  ^R\n, followed by the line. */
792	c = tp->t_termios.c_cc[VREPRINT];
793	if (c != _POSIX_VDISABLE)
794		ttydisc_echo(tp, c, 0);
795	ttydisc_echo(tp, CNL, 0);
796	ttyinq_reprintpos_reset(&tp->t_inq);
797
798	ttyinq_line_iterate_from_linestart(&tp->t_inq, ttydisc_reprint_char, tp);
799}
800
801struct ttydisc_recalc_length {
802	struct tty *tp;
803	unsigned int curlen;
804};
805
806static void
807ttydisc_recalc_charlength(void *d, char c, int quote)
808{
809	struct ttydisc_recalc_length *data = d;
810	struct tty *tp = data->tp;
811
812	if (CTL_PRINT(c, quote)) {
813		if (CMP_FLAG(l, ECHOCTL))
814			data->curlen += 2;
815	} else if (c == CTAB) {
816		data->curlen += 8 - (data->curlen & 7);
817	} else {
818		data->curlen++;
819	}
820}
821
822static unsigned int
823ttydisc_recalc_linelength(struct tty *tp)
824{
825	struct ttydisc_recalc_length data = { tp, tp->t_writepos };
826
827	ttyinq_line_iterate_from_reprintpos(&tp->t_inq,
828	    ttydisc_recalc_charlength, &data);
829	return (data.curlen);
830}
831
832static int
833ttydisc_rubchar(struct tty *tp)
834{
835	char c;
836	int quote;
837	unsigned int prevpos, tablen;
838
839	if (ttyinq_peekchar(&tp->t_inq, &c, &quote) != 0)
840		return (-1);
841	ttyinq_unputchar(&tp->t_inq);
842
843	if (CMP_FLAG(l, ECHO)) {
844		/*
845		 * Remove the character from the screen. This is even
846		 * safe for characters that span multiple characters
847		 * (tabs, quoted, etc).
848		 */
849		if (tp->t_writepos >= tp->t_column) {
850			/* Retype the sentence. */
851			ttydisc_reprint(tp);
852		} else if (CMP_FLAG(l, ECHOE)) {
853			if (CTL_PRINT(c, quote)) {
854				/* Remove ^X formatted chars. */
855				if (CMP_FLAG(l, ECHOCTL)) {
856					tp->t_column -= 2;
857					ttyoutq_write_nofrag(&tp->t_outq,
858					    "\b\b  \b\b", 6);
859				}
860			} else if (c == ' ') {
861				/* Space character needs no rubbing. */
862				tp->t_column -= 1;
863				ttyoutq_write_nofrag(&tp->t_outq, "\b", 1);
864			} else if (c == CTAB) {
865				/*
866				 * Making backspace work with tabs is
867				 * quite hard. Recalculate the length of
868				 * this character and remove it.
869				 *
870				 * Because terminal settings could be
871				 * changed while the line is being
872				 * inserted, the calculations don't have
873				 * to be correct. Make sure we keep the
874				 * tab length within proper bounds.
875				 */
876				prevpos = ttydisc_recalc_linelength(tp);
877				if (prevpos >= tp->t_column)
878					tablen = 1;
879				else
880					tablen = tp->t_column - prevpos;
881				if (tablen > 8)
882					tablen = 8;
883
884				tp->t_column = prevpos;
885				ttyoutq_write_nofrag(&tp->t_outq,
886				    "\b\b\b\b\b\b\b\b", tablen);
887				return (0);
888			} else if ((tp->t_termios.c_iflag & IUTF8) != 0 &&
889			    CTL_UTF8(c)) {
890				uint8_t bytes[UTF8_STACKBUF] = { 0 };
891				int curidx = UTF8_STACKBUF - 1, cwidth = 1,
892				    nb = 0;
893				teken_char_t codepoint;
894
895				/* Save current byte. */
896				bytes[curidx] = c;
897				curidx--;
898				nb++;
899				/* Loop back through inq until we hit the
900				 * leading byte. */
901				while (CTL_UTF8_CONT(c) && nb < UTF8_STACKBUF) {
902					/*
903					 * Check if we've reached the beginning
904					 * of the line.
905					 */
906					if (ttyinq_peekchar(&tp->t_inq, &c,
907					    &quote) != 0)
908						break;
909					ttyinq_unputchar(&tp->t_inq);
910					bytes[curidx] = c;
911					curidx--;
912					nb++;
913				}
914				/*
915				 * Shift array so that the leading
916				 * byte ends up at idx 0.
917				 */
918				if (nb < UTF8_STACKBUF)
919					memmove(&bytes[0], &bytes[curidx + 1],
920					    nb * sizeof(uint8_t));
921				/* Check for malformed UTF8 characters. */
922				if (nb == UTF8_STACKBUF &&
923				    CTL_UTF8_CONT(bytes[0])) {
924					/*
925					 * Place all bytes back into the inq and
926					 * delete the last byte only.
927					 */
928					ttyinq_write(&tp->t_inq, bytes,
929					    UTF8_STACKBUF, 0);
930					ttyinq_unputchar(&tp->t_inq);
931				} else {
932					/* Find codepoint and width. */
933					codepoint =
934					    teken_utf8_bytes_to_codepoint(bytes,
935						nb);
936					if (codepoint ==
937						TEKEN_UTF8_INVALID_CODEPOINT ||
938					    (cwidth = teken_wcwidth(
939						 codepoint)) == -1) {
940						/*
941						 * Place all bytes back into the
942						 * inq and fall back to
943						 * default behaviour.
944						 */
945						cwidth = 1;
946						ttyinq_write(&tp->t_inq, bytes,
947						    nb, 0);
948						ttyinq_unputchar(&tp->t_inq);
949					}
950				}
951				tp->t_column -= cwidth;
952				/*
953				 * Delete character by punching
954				 * 'cwidth' spaces over it.
955				 */
956				if (cwidth == 1)
957					ttyoutq_write_nofrag(&tp->t_outq,
958					    "\b \b", 3);
959				else if (cwidth == 2)
960					ttyoutq_write_nofrag(&tp->t_outq,
961					    "\b\b  \b\b", 6);
962			} else {
963				/*
964				 * Remove a regular character by
965				 * punching a space over it.
966				 */
967				tp->t_column -= 1;
968				ttyoutq_write_nofrag(&tp->t_outq, "\b \b", 3);
969			}
970		} else {
971			/* Don't print spaces. */
972			ttydisc_echo(tp, tp->t_termios.c_cc[VERASE], 0);
973		}
974	}
975
976	return (0);
977}
978
979static void
980ttydisc_rubword(struct tty *tp)
981{
982	char c;
983	int quote, alnum;
984
985	/* Strip whitespace first. */
986	for (;;) {
987		if (ttyinq_peekchar(&tp->t_inq, &c, &quote) != 0)
988			return;
989		if (!CTL_WHITE(c))
990			break;
991		ttydisc_rubchar(tp);
992	}
993
994	/*
995	 * Record whether the last character from the previous iteration
996	 * was alphanumeric or not. We need this to implement ALTWERASE.
997	 */
998	alnum = CTL_ALNUM(c);
999	for (;;) {
1000		ttydisc_rubchar(tp);
1001
1002		if (ttyinq_peekchar(&tp->t_inq, &c, &quote) != 0)
1003			return;
1004		if (CTL_WHITE(c))
1005			return;
1006		if (CMP_FLAG(l, ALTWERASE) && CTL_ALNUM(c) != alnum)
1007			return;
1008	}
1009}
1010
1011int
1012ttydisc_rint(struct tty *tp, char c, int flags)
1013{
1014	int signal, quote = 0;
1015	char ob[3] = { 0xff, 0x00 };
1016	size_t ol;
1017
1018	tty_assert_locked(tp);
1019
1020	atomic_add_long(&tty_nin, 1);
1021
1022	if (ttyhook_hashook(tp, rint))
1023		return ttyhook_rint(tp, c, flags);
1024
1025	if (tp->t_flags & TF_BYPASS)
1026		goto processed;
1027
1028	if (flags) {
1029		if (flags & TRE_BREAK) {
1030			if (CMP_FLAG(i, IGNBRK)) {
1031				/* Ignore break characters. */
1032				return (0);
1033			} else if (CMP_FLAG(i, BRKINT)) {
1034				/* Generate SIGINT on break. */
1035				tty_flush(tp, FREAD|FWRITE);
1036				tty_signal_pgrp(tp, SIGINT);
1037				return (0);
1038			} else {
1039				/* Just print it. */
1040				goto parmrk;
1041			}
1042		} else if (flags & TRE_FRAMING ||
1043		    (flags & TRE_PARITY && CMP_FLAG(i, INPCK))) {
1044			if (CMP_FLAG(i, IGNPAR)) {
1045				/* Ignore bad characters. */
1046				return (0);
1047			} else {
1048				/* Just print it. */
1049				goto parmrk;
1050			}
1051		}
1052	}
1053
1054	/* Allow any character to perform a wakeup. */
1055	if (CMP_FLAG(i, IXANY)) {
1056		tp->t_flags &= ~TF_STOPPED;
1057		tp->t_termios.c_lflag &= ~FLUSHO;
1058	}
1059
1060	/* Remove the top bit. */
1061	if (CMP_FLAG(i, ISTRIP))
1062		c &= ~0x80;
1063
1064	/* Skip input processing when we want to print it literally. */
1065	if (tp->t_flags & TF_LITERAL) {
1066		tp->t_flags &= ~TF_LITERAL;
1067		quote = 1;
1068		goto processed;
1069	}
1070
1071	/* Special control characters that are implementation dependent. */
1072	if (CMP_FLAG(l, IEXTEN)) {
1073		/* Accept the next character as literal. */
1074		if (CMP_CC(VLNEXT, c)) {
1075			if (CMP_FLAG(l, ECHO)) {
1076				if (CMP_FLAG(l, ECHOE))
1077					ttyoutq_write_nofrag(&tp->t_outq, "^\b", 2);
1078				else
1079					ttydisc_echo(tp, c, 0);
1080			}
1081			tp->t_flags |= TF_LITERAL;
1082			return (0);
1083		}
1084		/* Discard processing */
1085		if (CMP_CC(VDISCARD, c)) {
1086			if (CMP_FLAG(l, FLUSHO)) {
1087				tp->t_termios.c_lflag &= ~FLUSHO;
1088			} else {
1089				tty_flush(tp, FWRITE);
1090				ttydisc_echo(tp, c, 0);
1091				if (tp->t_inq.ti_end > 0)
1092					ttydisc_reprint(tp);
1093				tp->t_termios.c_lflag |= FLUSHO;
1094			}
1095		}
1096	}
1097
1098	/*
1099	 * Handle signal processing.
1100	 */
1101	if (CMP_FLAG(l, ISIG)) {
1102		if (CMP_FLAG(l, ICANON|IEXTEN) == (ICANON|IEXTEN)) {
1103			if (CMP_CC(VSTATUS, c)) {
1104				tty_signal_pgrp(tp, SIGINFO);
1105				return (0);
1106			}
1107		}
1108
1109		/*
1110		 * When compared to the old implementation, this
1111		 * implementation also flushes the output queue. POSIX
1112		 * is really brief about this, but does makes us assume
1113		 * we have to do so.
1114		 */
1115		signal = 0;
1116		if (CMP_CC(VINTR, c)) {
1117			signal = SIGINT;
1118		} else if (CMP_CC(VQUIT, c)) {
1119			signal = SIGQUIT;
1120		} else if (CMP_CC(VSUSP, c)) {
1121			signal = SIGTSTP;
1122		}
1123
1124		if (signal != 0) {
1125			/*
1126			 * Echo the character before signalling the
1127			 * processes.
1128			 */
1129			if (!CMP_FLAG(l, NOFLSH))
1130				tty_flush(tp, FREAD|FWRITE);
1131			ttydisc_echo(tp, c, 0);
1132			tty_signal_pgrp(tp, signal);
1133			return (0);
1134		}
1135	}
1136
1137	/*
1138	 * Handle start/stop characters.
1139	 */
1140	if (CMP_FLAG(i, IXON)) {
1141		if (CMP_CC(VSTOP, c)) {
1142			/* Stop it if we aren't stopped yet. */
1143			if ((tp->t_flags & TF_STOPPED) == 0) {
1144				tp->t_flags |= TF_STOPPED;
1145				return (0);
1146			}
1147			/*
1148			 * Fallthrough:
1149			 * When VSTART == VSTOP, we should make this key
1150			 * toggle it.
1151			 */
1152			if (!CMP_CC(VSTART, c))
1153				return (0);
1154		}
1155		if (CMP_CC(VSTART, c)) {
1156			tp->t_flags &= ~TF_STOPPED;
1157			return (0);
1158		}
1159	}
1160
1161	/* Conversion of CR and NL. */
1162	switch (c) {
1163	case CCR:
1164		if (CMP_FLAG(i, IGNCR))
1165			return (0);
1166		if (CMP_FLAG(i, ICRNL))
1167			c = CNL;
1168		break;
1169	case CNL:
1170		if (CMP_FLAG(i, INLCR))
1171			c = CCR;
1172		break;
1173	}
1174
1175	/* Canonical line editing. */
1176	if (CMP_FLAG(l, ICANON)) {
1177		if (CMP_CC(VERASE, c) || CMP_CC(VERASE2, c)) {
1178			ttydisc_rubchar(tp);
1179			return (0);
1180		} else if (CMP_CC(VKILL, c)) {
1181			while (ttydisc_rubchar(tp) == 0);
1182			return (0);
1183		} else if (CMP_FLAG(l, IEXTEN)) {
1184			if (CMP_CC(VWERASE, c)) {
1185				ttydisc_rubword(tp);
1186				return (0);
1187			} else if (CMP_CC(VREPRINT, c)) {
1188				ttydisc_reprint(tp);
1189				return (0);
1190			}
1191		}
1192	}
1193
1194processed:
1195	if (CMP_FLAG(i, PARMRK) && (unsigned char)c == 0xff) {
1196		/* Print 0xff 0xff. */
1197		ob[1] = 0xff;
1198		ol = 2;
1199		quote = 1;
1200	} else {
1201		ob[0] = c;
1202		ol = 1;
1203	}
1204
1205	goto print;
1206
1207parmrk:
1208	if (CMP_FLAG(i, PARMRK)) {
1209		/* Prepend 0xff 0x00 0x.. */
1210		ob[2] = c;
1211		ol = 3;
1212		quote = 1;
1213	} else {
1214		ob[0] = c;
1215		ol = 1;
1216	}
1217
1218print:
1219	/* See if we can store this on the input queue. */
1220	if (ttyinq_write_nofrag(&tp->t_inq, ob, ol, quote) != 0) {
1221		if (CMP_FLAG(i, IMAXBEL))
1222			ttyoutq_write_nofrag(&tp->t_outq, "\a", 1);
1223
1224		/*
1225		 * Prevent a deadlock here. It may be possible that a
1226		 * user has entered so much data, there is no data
1227		 * available to read(), but the buffers are full anyway.
1228		 *
1229		 * Only enter the high watermark if the device driver
1230		 * can actually transmit something.
1231		 */
1232		if (ttyinq_bytescanonicalized(&tp->t_inq) == 0)
1233			return (0);
1234
1235		tty_hiwat_in_block(tp);
1236		return (-1);
1237	}
1238
1239	/*
1240	 * In raw mode, we canonicalize after receiving a single
1241	 * character. Otherwise, we canonicalize when we receive a
1242	 * newline, VEOL or VEOF, but only when it isn't quoted.
1243	 */
1244	if (!CMP_FLAG(l, ICANON) ||
1245	    (!quote && (c == CNL || CMP_CC(VEOL, c) || CMP_CC(VEOF, c)))) {
1246		ttyinq_canonicalize(&tp->t_inq);
1247	}
1248
1249	ttydisc_echo(tp, c, quote);
1250
1251	return (0);
1252}
1253
1254size_t
1255ttydisc_rint_simple(struct tty *tp, const void *buf, size_t len)
1256{
1257	const char *cbuf;
1258
1259	if (ttydisc_can_bypass(tp))
1260		return (ttydisc_rint_bypass(tp, buf, len));
1261
1262	for (cbuf = buf; len-- > 0; cbuf++) {
1263		if (ttydisc_rint(tp, *cbuf, 0) != 0)
1264			break;
1265	}
1266
1267	return (cbuf - (const char *)buf);
1268}
1269
1270size_t
1271ttydisc_rint_bypass(struct tty *tp, const void *buf, size_t len)
1272{
1273	size_t ret;
1274
1275	tty_assert_locked(tp);
1276
1277	MPASS(tp->t_flags & TF_BYPASS);
1278
1279	atomic_add_long(&tty_nin, len);
1280
1281	if (ttyhook_hashook(tp, rint_bypass))
1282		return ttyhook_rint_bypass(tp, buf, len);
1283
1284	ret = ttyinq_write(&tp->t_inq, buf, len, 0);
1285	ttyinq_canonicalize(&tp->t_inq);
1286	if (ret < len)
1287		tty_hiwat_in_block(tp);
1288
1289	return (ret);
1290}
1291
1292void
1293ttydisc_rint_done(struct tty *tp)
1294{
1295
1296	tty_assert_locked(tp);
1297
1298	if (ttyhook_hashook(tp, rint_done))
1299		ttyhook_rint_done(tp);
1300
1301	/* Wake up readers. */
1302	tty_wakeup(tp, FREAD);
1303	/* Wake up driver for echo. */
1304	ttydevsw_outwakeup(tp);
1305}
1306
1307size_t
1308ttydisc_rint_poll(struct tty *tp)
1309{
1310	size_t l;
1311
1312	tty_assert_locked(tp);
1313
1314	if (ttyhook_hashook(tp, rint_poll))
1315		return ttyhook_rint_poll(tp);
1316
1317	/*
1318	 * XXX: Still allow character input when there's no space in the
1319	 * buffers, but we haven't entered the high watermark. This is
1320	 * to allow backspace characters to be inserted when in
1321	 * canonical mode.
1322	 */
1323	l = ttyinq_bytesleft(&tp->t_inq);
1324	if (l == 0 && (tp->t_flags & TF_HIWAT_IN) == 0)
1325		return (1);
1326
1327	return (l);
1328}
1329
1330static void
1331ttydisc_wakeup_watermark(struct tty *tp)
1332{
1333	size_t c;
1334
1335	c = ttyoutq_bytesleft(&tp->t_outq);
1336	if (tp->t_flags & TF_HIWAT_OUT) {
1337		/* Only allow us to run when we're below the watermark. */
1338		if (c < tp->t_outlow)
1339			return;
1340
1341		/* Reset the watermark. */
1342		tp->t_flags &= ~TF_HIWAT_OUT;
1343	} else {
1344		/* Only run when we have data at all. */
1345		if (c == 0)
1346			return;
1347	}
1348	tty_wakeup(tp, FWRITE);
1349}
1350
1351size_t
1352ttydisc_getc(struct tty *tp, void *buf, size_t len)
1353{
1354
1355	tty_assert_locked(tp);
1356
1357	if (tp->t_flags & TF_STOPPED)
1358		return (0);
1359
1360	if (ttyhook_hashook(tp, getc_inject))
1361		return ttyhook_getc_inject(tp, buf, len);
1362
1363	len = ttyoutq_read(&tp->t_outq, buf, len);
1364
1365	if (ttyhook_hashook(tp, getc_capture))
1366		ttyhook_getc_capture(tp, buf, len);
1367
1368	ttydisc_wakeup_watermark(tp);
1369	atomic_add_long(&tty_nout, len);
1370
1371	return (len);
1372}
1373
1374int
1375ttydisc_getc_uio(struct tty *tp, struct uio *uio)
1376{
1377	int error = 0;
1378	ssize_t obytes = uio->uio_resid;
1379	size_t len;
1380	char buf[TTY_STACKBUF];
1381
1382	tty_assert_locked(tp);
1383
1384	if (tp->t_flags & TF_STOPPED)
1385		return (0);
1386
1387	/*
1388	 * When a TTY hook is attached, we cannot perform unbuffered
1389	 * copying to userspace. Just call ttydisc_getc() and
1390	 * temporarily store data in a shadow buffer.
1391	 */
1392	if (ttyhook_hashook(tp, getc_capture) ||
1393	    ttyhook_hashook(tp, getc_inject)) {
1394		while (uio->uio_resid > 0) {
1395			/* Read to shadow buffer. */
1396			len = ttydisc_getc(tp, buf,
1397			    MIN(uio->uio_resid, sizeof buf));
1398			if (len == 0)
1399				break;
1400
1401			/* Copy to userspace. */
1402			tty_unlock(tp);
1403			error = uiomove(buf, len, uio);
1404			tty_lock(tp);
1405
1406			if (error != 0)
1407				break;
1408		}
1409	} else {
1410		error = ttyoutq_read_uio(&tp->t_outq, tp, uio);
1411
1412		ttydisc_wakeup_watermark(tp);
1413		atomic_add_long(&tty_nout, obytes - uio->uio_resid);
1414	}
1415
1416	return (error);
1417}
1418
1419size_t
1420ttydisc_getc_poll(struct tty *tp)
1421{
1422
1423	tty_assert_locked(tp);
1424
1425	if (tp->t_flags & TF_STOPPED)
1426		return (0);
1427
1428	if (ttyhook_hashook(tp, getc_poll))
1429		return ttyhook_getc_poll(tp);
1430
1431	return ttyoutq_bytesused(&tp->t_outq);
1432}
1433
1434/*
1435 * XXX: not really related to the TTYDISC, but we'd better put
1436 * tty_putchar() here, because we need to perform proper output
1437 * processing.
1438 */
1439
1440int
1441tty_putstrn(struct tty *tp, const char *p, size_t n)
1442{
1443	size_t i;
1444
1445	tty_assert_locked(tp);
1446
1447	if (tty_gone(tp))
1448		return (-1);
1449
1450	for (i = 0; i < n; i++)
1451		ttydisc_echo_force(tp, p[i], 0);
1452
1453	tp->t_writepos = tp->t_column;
1454	ttyinq_reprintpos_set(&tp->t_inq);
1455
1456	ttydevsw_outwakeup(tp);
1457	return (0);
1458}
1459
1460int
1461tty_putchar(struct tty *tp, char c)
1462{
1463	return (tty_putstrn(tp, &c, 1));
1464}
1465