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