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