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