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