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