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