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