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