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