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