1 /*- 2 * Copyright (c) 1982, 1986, 1990, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)tty.c 8.8 (Berkeley) 1/21/94 39 * $Id: tty.c,v 1.17 1995/01/05 00:01:00 ache Exp $ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/ioctl.h> 45 #include <sys/proc.h> 46 #define TTYDEFCHARS 47 #include <sys/tty.h> 48 #undef TTYDEFCHARS 49 #include <sys/file.h> 50 #include <sys/conf.h> 51 #include <sys/dkstat.h> 52 #include <sys/uio.h> 53 #include <sys/kernel.h> 54 #include <sys/vnode.h> 55 #include <sys/syslog.h> 56 #include <sys/signalvar.h> 57 #include <sys/resourcevar.h> 58 59 #include <vm/vm.h> 60 61 static int proc_compare __P((struct proc *p1, struct proc *p2)); 62 static int ttnread __P((struct tty *)); 63 static void ttyblock __P((struct tty *tp)); 64 static void ttyecho __P((int, struct tty *tp)); 65 static void ttyrubo __P((struct tty *, int)); 66 67 /* Symbolic sleep message strings. */ 68 char ttclos[] = "ttycls"; 69 char ttopen[] = "ttyopn"; 70 char ttybg[] = "ttybg"; 71 char ttybuf[] = "ttybuf"; 72 char ttyin[] = "ttyin"; 73 char ttyout[] = "ttyout"; 74 75 /* 76 * Table with character classes and parity. The 8th bit indicates parity, 77 * the 7th bit indicates the character is an alphameric or underscore (for 78 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits 79 * are 0 then the character needs no special processing on output; classes 80 * other than 0 might be translated or (not currently) require delays. 81 */ 82 #define E 0x00 /* Even parity. */ 83 #define O 0x80 /* Odd parity. */ 84 #define PARITY(c) (char_type[c] & O) 85 86 #define ALPHA 0x40 /* Alpha or underscore. */ 87 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA) 88 89 #define CCLASSMASK 0x3f 90 #define CCLASS(c) (char_type[c] & CCLASSMASK) 91 92 #define BS BACKSPACE 93 #define CC CONTROL 94 #define CR RETURN 95 #define NA ORDINARY | ALPHA 96 #define NL NEWLINE 97 #define NO ORDINARY 98 #define TB TAB 99 #define VT VTAB 100 101 char const char_type[] = { 102 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */ 103 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */ 104 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */ 105 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */ 106 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */ 107 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */ 108 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */ 109 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */ 110 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */ 111 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */ 112 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */ 113 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */ 114 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */ 115 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */ 116 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */ 117 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */ 118 /* 119 * Meta chars; should be settable per character set; 120 * for now, treat them all as normal characters. 121 */ 122 NA, NA, NA, NA, NA, NA, NA, NA, 123 NA, NA, NA, NA, NA, NA, NA, NA, 124 NA, NA, NA, NA, NA, NA, NA, NA, 125 NA, NA, NA, NA, NA, NA, NA, NA, 126 NA, NA, NA, NA, NA, NA, NA, NA, 127 NA, NA, NA, NA, NA, NA, NA, NA, 128 NA, NA, NA, NA, NA, NA, NA, NA, 129 NA, NA, NA, NA, NA, NA, NA, NA, 130 NA, NA, NA, NA, NA, NA, NA, NA, 131 NA, NA, NA, NA, NA, NA, NA, NA, 132 NA, NA, NA, NA, NA, NA, NA, NA, 133 NA, NA, NA, NA, NA, NA, NA, NA, 134 NA, NA, NA, NA, NA, NA, NA, NA, 135 NA, NA, NA, NA, NA, NA, NA, NA, 136 NA, NA, NA, NA, NA, NA, NA, NA, 137 NA, NA, NA, NA, NA, NA, NA, NA, 138 }; 139 #undef BS 140 #undef CC 141 #undef CR 142 #undef NA 143 #undef NL 144 #undef NO 145 #undef TB 146 #undef VT 147 148 /* Macros to clear/set/test flags. */ 149 #define SET(t, f) (t) |= (f) 150 #define CLR(t, f) (t) &= ~(f) 151 #define ISSET(t, f) ((t) & (f)) 152 153 /* 154 * Initial open of tty, or (re)entry to standard tty line discipline. 155 */ 156 int 157 ttyopen(device, tp) 158 dev_t device; 159 register struct tty *tp; 160 { 161 int s; 162 163 s = spltty(); 164 tp->t_dev = device; 165 if (!ISSET(tp->t_state, TS_ISOPEN)) { 166 SET(tp->t_state, TS_ISOPEN); 167 bzero(&tp->t_winsize, sizeof(tp->t_winsize)); 168 } 169 CLR(tp->t_state, TS_WOPEN); 170 171 /* 172 * Initialize or restore a cblock allocation policy suitable for 173 * the standard line discipline. 174 */ 175 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512); 176 clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + 200, 512); 177 clist_alloc_cblocks(&tp->t_rawq, TTYHOG, 512); 178 179 splx(s); 180 return (0); 181 } 182 183 /* 184 * Handle close() on a tty line: flush and set to initial state, 185 * bumping generation number so that pending read/write calls 186 * can detect recycling of the tty. 187 */ 188 int 189 ttyclose(tp) 190 register struct tty *tp; 191 { 192 extern struct tty *constty; /* Temporary virtual console. */ 193 int s; 194 195 s = spltty(); 196 if (constty == tp) 197 constty = NULL; 198 199 ttyflush(tp, FREAD | FWRITE); 200 clist_free_cblocks(&tp->t_canq); 201 clist_free_cblocks(&tp->t_outq); 202 clist_free_cblocks(&tp->t_rawq); 203 204 tp->t_gen++; 205 tp->t_pgrp = NULL; 206 tp->t_session = NULL; 207 tp->t_state = 0; 208 splx(s); 209 return (0); 210 } 211 212 #define FLUSHQ(q) { \ 213 if ((q)->c_cc) \ 214 ndflush(q, (q)->c_cc); \ 215 } 216 217 /* Is 'c' a line delimiter ("break" character)? */ 218 #define TTBREAKC(c) \ 219 ((c) == '\n' || (((c) == cc[VEOF] || \ 220 (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)) 221 222 223 /* 224 * Process input of a single character received on a tty. 225 */ 226 int 227 ttyinput(c, tp) 228 register int c; 229 register struct tty *tp; 230 { 231 register int iflag, lflag; 232 register u_char *cc; 233 int i, err; 234 235 /* 236 * If input is pending take it first. 237 */ 238 lflag = tp->t_lflag; 239 if (ISSET(lflag, PENDIN)) 240 ttypend(tp); 241 /* 242 * Gather stats. 243 */ 244 if (ISSET(lflag, ICANON)) { 245 ++tk_cancc; 246 ++tp->t_cancc; 247 } else { 248 ++tk_rawcc; 249 ++tp->t_rawcc; 250 } 251 ++tk_nin; 252 253 /* Handle exceptional conditions (break, parity, framing). */ 254 cc = tp->t_cc; 255 iflag = tp->t_iflag; 256 err = (ISSET(c, TTY_ERRORMASK)); 257 if (err) { 258 CLR(c, TTY_ERRORMASK); 259 if (ISSET(err, TTY_FE) && !c) { /* Break. */ 260 if (ISSET(iflag, IGNBRK)) 261 goto endcase; 262 else if (ISSET(iflag, BRKINT) && 263 ISSET(lflag, ISIG) && 264 (cc[VINTR] != _POSIX_VDISABLE)) 265 c = cc[VINTR]; 266 else if (ISSET(iflag, PARMRK)) 267 goto parmrk; 268 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK)) 269 || ISSET(err, TTY_FE)) { 270 if (ISSET(iflag, IGNPAR)) 271 goto endcase; 272 else if (ISSET(iflag, PARMRK)) { 273 parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); 274 (void)putc(0 | TTY_QUOTE, &tp->t_rawq); 275 (void)putc(c | TTY_QUOTE, &tp->t_rawq); 276 goto endcase; 277 } else 278 c = 0; 279 } 280 } 281 /* 282 * In tandem mode, check high water mark. 283 */ 284 if (ISSET(iflag, IXOFF)) 285 ttyblock(tp); 286 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP)) 287 CLR(c, 0x80); 288 if (!ISSET(lflag, EXTPROC)) { 289 /* 290 * Check for literal nexting very first 291 */ 292 if (ISSET(tp->t_state, TS_LNCH)) { 293 SET(c, TTY_QUOTE); 294 CLR(tp->t_state, TS_LNCH); 295 } 296 /* 297 * Scan for special characters. This code 298 * is really just a big case statement with 299 * non-constant cases. The bottom of the 300 * case statement is labeled ``endcase'', so goto 301 * it after a case match, or similar. 302 */ 303 304 /* 305 * Control chars which aren't controlled 306 * by ICANON, ISIG, or IXON. 307 */ 308 if (ISSET(lflag, IEXTEN)) { 309 if (CCEQ(cc[VLNEXT], c)) { 310 if (ISSET(lflag, ECHO)) { 311 if (ISSET(lflag, ECHOE)) { 312 (void)ttyoutput('^', tp); 313 (void)ttyoutput('\b', tp); 314 } else 315 ttyecho(c, tp); 316 } 317 SET(tp->t_state, TS_LNCH); 318 goto endcase; 319 } 320 if (CCEQ(cc[VDISCARD], c)) { 321 if (ISSET(lflag, FLUSHO)) 322 CLR(tp->t_lflag, FLUSHO); 323 else { 324 ttyflush(tp, FWRITE); 325 ttyecho(c, tp); 326 if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 327 ttyretype(tp); 328 SET(tp->t_lflag, FLUSHO); 329 } 330 goto startoutput; 331 } 332 } 333 /* 334 * Signals. 335 */ 336 if (ISSET(lflag, ISIG)) { 337 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 338 if (!ISSET(lflag, NOFLSH)) 339 ttyflush(tp, FREAD | FWRITE); 340 ttyecho(c, tp); 341 pgsignal(tp->t_pgrp, 342 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 343 goto endcase; 344 } 345 if (CCEQ(cc[VSUSP], c)) { 346 if (!ISSET(lflag, NOFLSH)) 347 ttyflush(tp, FREAD); 348 ttyecho(c, tp); 349 pgsignal(tp->t_pgrp, SIGTSTP, 1); 350 goto endcase; 351 } 352 } 353 /* 354 * Handle start/stop characters. 355 */ 356 if (ISSET(iflag, IXON)) { 357 if (CCEQ(cc[VSTOP], c)) { 358 if (!ISSET(tp->t_state, TS_TTSTOP)) { 359 SET(tp->t_state, TS_TTSTOP); 360 #ifdef sun4c /* XXX */ 361 (*tp->t_stop)(tp, 0); 362 #else 363 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 364 0); 365 #endif 366 return (0); 367 } 368 if (!CCEQ(cc[VSTART], c)) 369 return (0); 370 /* 371 * if VSTART == VSTOP then toggle 372 */ 373 goto endcase; 374 } 375 if (CCEQ(cc[VSTART], c)) 376 goto restartoutput; 377 } 378 /* 379 * IGNCR, ICRNL, & INLCR 380 */ 381 if (c == '\r') { 382 if (ISSET(iflag, IGNCR)) 383 goto endcase; 384 else if (ISSET(iflag, ICRNL)) 385 c = '\n'; 386 } else if (c == '\n' && ISSET(iflag, INLCR)) 387 c = '\r'; 388 } 389 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) { 390 /* 391 * From here on down canonical mode character 392 * processing takes place. 393 */ 394 /* 395 * erase (^H / ^?) 396 */ 397 if (CCEQ(cc[VERASE], c)) { 398 if (tp->t_rawq.c_cc) 399 ttyrub(unputc(&tp->t_rawq), tp); 400 goto endcase; 401 } 402 /* 403 * kill (^U) 404 */ 405 if (CCEQ(cc[VKILL], c)) { 406 if (ISSET(lflag, ECHOKE) && 407 tp->t_rawq.c_cc == tp->t_rocount && 408 !ISSET(lflag, ECHOPRT)) 409 while (tp->t_rawq.c_cc) 410 ttyrub(unputc(&tp->t_rawq), tp); 411 else { 412 ttyecho(c, tp); 413 if (ISSET(lflag, ECHOK) || 414 ISSET(lflag, ECHOKE)) 415 ttyecho('\n', tp); 416 FLUSHQ(&tp->t_rawq); 417 tp->t_rocount = 0; 418 } 419 CLR(tp->t_state, TS_LOCAL); 420 goto endcase; 421 } 422 /* 423 * word erase (^W) 424 */ 425 if (CCEQ(cc[VWERASE], c)) { 426 int alt = ISSET(lflag, ALTWERASE); 427 int ctype; 428 429 /* 430 * erase whitespace 431 */ 432 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 433 ttyrub(c, tp); 434 if (c == -1) 435 goto endcase; 436 /* 437 * erase last char of word and remember the 438 * next chars type (for ALTWERASE) 439 */ 440 ttyrub(c, tp); 441 c = unputc(&tp->t_rawq); 442 if (c == -1) 443 goto endcase; 444 if (c == ' ' || c == '\t') { 445 (void)putc(c, &tp->t_rawq); 446 goto endcase; 447 } 448 ctype = ISALPHA(c); 449 /* 450 * erase rest of word 451 */ 452 do { 453 ttyrub(c, tp); 454 c = unputc(&tp->t_rawq); 455 if (c == -1) 456 goto endcase; 457 } while (c != ' ' && c != '\t' && 458 (alt == 0 || ISALPHA(c) == ctype)); 459 (void)putc(c, &tp->t_rawq); 460 goto endcase; 461 } 462 /* 463 * reprint line (^R) 464 */ 465 if (CCEQ(cc[VREPRINT], c)) { 466 ttyretype(tp); 467 goto endcase; 468 } 469 /* 470 * ^T - kernel info and generate SIGINFO 471 */ 472 if (CCEQ(cc[VSTATUS], c)) { 473 if (ISSET(lflag, ISIG)) 474 pgsignal(tp->t_pgrp, SIGINFO, 1); 475 if (!ISSET(lflag, NOKERNINFO)) 476 ttyinfo(tp); 477 goto endcase; 478 } 479 } 480 /* 481 * Check for input buffer overflow 482 */ 483 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { 484 if (ISSET(iflag, IMAXBEL)) { 485 if (tp->t_outq.c_cc < tp->t_hiwat) 486 (void)ttyoutput(CTRL('g'), tp); 487 } else 488 ttyflush(tp, FREAD | FWRITE); 489 goto endcase; 490 } 491 /* 492 * Put data char in q for user and 493 * wakeup on seeing a line delimiter. 494 */ 495 if (putc(c, &tp->t_rawq) >= 0) { 496 if (!ISSET(lflag, ICANON)) { 497 ttwakeup(tp); 498 ttyecho(c, tp); 499 goto endcase; 500 } 501 if (TTBREAKC(c)) { 502 tp->t_rocount = 0; 503 catq(&tp->t_rawq, &tp->t_canq); 504 ttwakeup(tp); 505 } else if (tp->t_rocount++ == 0) 506 tp->t_rocol = tp->t_column; 507 if (ISSET(tp->t_state, TS_ERASE)) { 508 /* 509 * end of prterase \.../ 510 */ 511 CLR(tp->t_state, TS_ERASE); 512 (void)ttyoutput('/', tp); 513 } 514 i = tp->t_column; 515 ttyecho(c, tp); 516 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) { 517 /* 518 * Place the cursor over the '^' of the ^D. 519 */ 520 i = min(2, tp->t_column - i); 521 while (i > 0) { 522 (void)ttyoutput('\b', tp); 523 i--; 524 } 525 } 526 } 527 endcase: 528 /* 529 * IXANY means allow any character to restart output. 530 */ 531 if (ISSET(tp->t_state, TS_TTSTOP) && 532 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) 533 return (0); 534 restartoutput: 535 CLR(tp->t_lflag, FLUSHO); 536 CLR(tp->t_state, TS_TTSTOP); 537 startoutput: 538 return (ttstart(tp)); 539 } 540 541 /* 542 * Output a single character on a tty, doing output processing 543 * as needed (expanding tabs, newline processing, etc.). 544 * Returns < 0 if succeeds, otherwise returns char to resend. 545 * Must be recursive. 546 */ 547 int 548 ttyoutput(c, tp) 549 register int c; 550 register struct tty *tp; 551 { 552 register long oflag; 553 register int col, s; 554 555 oflag = tp->t_oflag; 556 if (!ISSET(oflag, OPOST)) { 557 if (ISSET(tp->t_lflag, FLUSHO)) 558 return (-1); 559 if (putc(c, &tp->t_outq)) 560 return (c); 561 tk_nout++; 562 tp->t_outcc++; 563 return (-1); 564 } 565 /* 566 * Do tab expansion if OXTABS is set. Special case if we external 567 * processing, we don't do the tab expansion because we'll probably 568 * get it wrong. If tab expansion needs to be done, let it happen 569 * externally. 570 */ 571 CLR(c, ~TTY_CHARMASK); 572 if (c == '\t' && 573 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) { 574 c = 8 - (tp->t_column & 7); 575 if (!ISSET(tp->t_lflag, FLUSHO)) { 576 s = spltty(); /* Don't interrupt tabs. */ 577 c -= b_to_q(" ", c, &tp->t_outq); 578 tk_nout += c; 579 tp->t_outcc += c; 580 splx(s); 581 } 582 tp->t_column += c; 583 return (c ? -1 : '\t'); 584 } 585 if (c == CEOT && ISSET(oflag, ONOEOT)) 586 return (-1); 587 588 /* 589 * Newline translation: if ONLCR is set, 590 * translate newline into "\r\n". 591 */ 592 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) { 593 tk_nout++; 594 tp->t_outcc++; 595 if (putc('\r', &tp->t_outq)) 596 return (c); 597 } 598 tk_nout++; 599 tp->t_outcc++; 600 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq)) 601 return (c); 602 603 col = tp->t_column; 604 switch (CCLASS(c)) { 605 case BACKSPACE: 606 if (col > 0) 607 --col; 608 break; 609 case CONTROL: 610 break; 611 case NEWLINE: 612 case RETURN: 613 col = 0; 614 break; 615 case ORDINARY: 616 ++col; 617 break; 618 case TAB: 619 col = (col + 8) & ~7; 620 break; 621 } 622 tp->t_column = col; 623 return (-1); 624 } 625 626 /* 627 * Ioctls for all tty devices. Called after line-discipline specific ioctl 628 * has been called to do discipline-specific functions and/or reject any 629 * of these ioctl commands. 630 */ 631 /* ARGSUSED */ 632 int 633 ttioctl(tp, cmd, data, flag) 634 register struct tty *tp; 635 int cmd, flag; 636 void *data; 637 { 638 extern struct tty *constty; /* Temporary virtual console. */ 639 extern int nlinesw; 640 register struct proc *p; 641 int s, error; 642 643 p = curproc; /* XXX */ 644 645 /* If the ioctl involves modification, hang if in the background. */ 646 switch (cmd) { 647 case TIOCFLUSH: 648 case TIOCSETA: 649 case TIOCSETD: 650 case TIOCSETAF: 651 case TIOCSETAW: 652 #ifdef notdef 653 case TIOCSPGRP: 654 #endif 655 case TIOCSTAT: 656 case TIOCSTI: 657 case TIOCSWINSZ: 658 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 659 case TIOCLBIC: 660 case TIOCLBIS: 661 case TIOCLSET: 662 case TIOCSETC: 663 case OTIOCSETD: 664 case TIOCSETN: 665 case TIOCSETP: 666 case TIOCSLTC: 667 #endif 668 while (isbackground(curproc, tp) && 669 p->p_pgrp->pg_jobc && (p->p_flag & P_PPWAIT) == 0 && 670 (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 671 (p->p_sigmask & sigmask(SIGTTOU)) == 0) { 672 pgsignal(p->p_pgrp, SIGTTOU, 1); 673 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, ttybg, 0); 674 if (error) 675 return (error); 676 } 677 break; 678 } 679 680 switch (cmd) { /* Process the ioctl. */ 681 case FIOASYNC: /* set/clear async i/o */ 682 s = spltty(); 683 if (*(int *)data) 684 SET(tp->t_state, TS_ASYNC); 685 else 686 CLR(tp->t_state, TS_ASYNC); 687 splx(s); 688 break; 689 case FIONBIO: /* set/clear non-blocking i/o */ 690 break; /* XXX: delete. */ 691 case FIONREAD: /* get # bytes to read */ 692 *(int *)data = ttnread(tp); 693 break; 694 case TIOCEXCL: /* set exclusive use of tty */ 695 s = spltty(); 696 SET(tp->t_state, TS_XCLUDE); 697 splx(s); 698 break; 699 case TIOCFLUSH: { /* flush buffers */ 700 register int flags = *(int *)data; 701 702 if (flags == 0) 703 flags = FREAD | FWRITE; 704 else 705 flags &= FREAD | FWRITE; 706 ttyflush(tp, flags); 707 break; 708 } 709 case TIOCCONS: /* become virtual console */ 710 if (*(int *)data) { 711 if (constty && constty != tp && 712 ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) == 713 (TS_CARR_ON | TS_ISOPEN)) 714 return (EBUSY); 715 #ifndef UCONSOLE 716 if (error = suser(p->p_ucred, &p->p_acflag)) 717 return (error); 718 #endif 719 constty = tp; 720 } else if (tp == constty) 721 constty = NULL; 722 break; 723 case TIOCDRAIN: /* wait till output drained */ 724 error = ttywait(tp); 725 if (error) 726 return (error); 727 break; 728 case TIOCGETA: { /* get termios struct */ 729 struct termios *t = (struct termios *)data; 730 731 bcopy(&tp->t_termios, t, sizeof(struct termios)); 732 break; 733 } 734 case TIOCGETD: /* get line discipline */ 735 *(int *)data = tp->t_line; 736 break; 737 case TIOCGWINSZ: /* get window size */ 738 *(struct winsize *)data = tp->t_winsize; 739 break; 740 case TIOCGPGRP: /* get pgrp of tty */ 741 if (!isctty(p, tp)) 742 return (ENOTTY); 743 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 744 break; 745 #ifdef TIOCHPCL 746 case TIOCHPCL: /* hang up on last close */ 747 s = spltty(); 748 SET(tp->t_cflag, HUPCL); 749 splx(s); 750 break; 751 #endif 752 case TIOCNXCL: /* reset exclusive use of tty */ 753 s = spltty(); 754 CLR(tp->t_state, TS_XCLUDE); 755 splx(s); 756 break; 757 case TIOCOUTQ: /* output queue size */ 758 *(int *)data = tp->t_outq.c_cc; 759 break; 760 case TIOCSETA: /* set termios struct */ 761 case TIOCSETAW: /* drain output, set */ 762 case TIOCSETAF: { /* drn out, fls in, set */ 763 register struct termios *t = (struct termios *)data; 764 765 s = spltty(); 766 if (cmd == TIOCSETAW || cmd == TIOCSETAF) { 767 error = ttywait(tp); 768 if (error) { 769 splx(s); 770 return (error); 771 } 772 if (cmd == TIOCSETAF) 773 ttyflush(tp, FREAD); 774 } 775 if (!ISSET(t->c_cflag, CIGNORE)) { 776 /* 777 * Set device hardware. 778 */ 779 if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 780 splx(s); 781 return (error); 782 } else { 783 if (!ISSET(tp->t_state, TS_CARR_ON) && 784 ISSET(tp->t_cflag, CLOCAL) && 785 !ISSET(t->c_cflag, CLOCAL)) { 786 CLR(tp->t_state, TS_ISOPEN); 787 SET(tp->t_state, TS_WOPEN); 788 ttwakeup(tp); 789 } 790 tp->t_cflag = t->c_cflag; 791 tp->t_ispeed = t->c_ispeed; 792 tp->t_ospeed = t->c_ospeed; 793 } 794 ttsetwater(tp); 795 } 796 if (cmd != TIOCSETAF) { 797 if (ISSET(t->c_lflag, ICANON) != 798 ISSET(tp->t_lflag, ICANON)) 799 if (ISSET(t->c_lflag, ICANON)) { 800 SET(tp->t_lflag, PENDIN); 801 ttwakeup(tp); 802 } else { 803 struct clist tq; 804 805 catq(&tp->t_rawq, &tp->t_canq); 806 tq = tp->t_rawq; 807 tp->t_rawq = tp->t_canq; 808 tp->t_canq = tq; 809 CLR(tp->t_lflag, PENDIN); 810 } 811 } 812 tp->t_iflag = t->c_iflag; 813 tp->t_oflag = t->c_oflag; 814 /* 815 * Make the EXTPROC bit read only. 816 */ 817 if (ISSET(tp->t_lflag, EXTPROC)) 818 SET(t->c_lflag, EXTPROC); 819 else 820 CLR(t->c_lflag, EXTPROC); 821 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN); 822 if (t->c_cc[VMIN] != tp->t_cc[VMIN] || 823 t->c_cc[VTIME] != tp->t_cc[VTIME]) 824 ttwakeup(tp); 825 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 826 splx(s); 827 break; 828 } 829 case TIOCSETD: { /* set line discipline */ 830 register int t = *(int *)data; 831 dev_t device = tp->t_dev; 832 833 if ((u_int)t >= nlinesw) 834 return (ENXIO); 835 if (t != tp->t_line) { 836 s = spltty(); 837 (*linesw[tp->t_line].l_close)(tp, flag); 838 error = (*linesw[t].l_open)(device, tp); 839 if (error) { 840 (void)(*linesw[tp->t_line].l_open)(device, tp); 841 splx(s); 842 return (error); 843 } 844 tp->t_line = t; 845 splx(s); 846 } 847 break; 848 } 849 case TIOCSTART: /* start output, like ^Q */ 850 s = spltty(); 851 if (ISSET(tp->t_state, TS_TTSTOP) || 852 ISSET(tp->t_lflag, FLUSHO)) { 853 CLR(tp->t_lflag, FLUSHO); 854 CLR(tp->t_state, TS_TTSTOP); 855 ttstart(tp); 856 } 857 splx(s); 858 break; 859 case TIOCSTI: /* simulate terminal input */ 860 if (p->p_ucred->cr_uid && (flag & FREAD) == 0) 861 return (EPERM); 862 if (p->p_ucred->cr_uid && !isctty(p, tp)) 863 return (EACCES); 864 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp); 865 break; 866 case TIOCSTOP: /* stop output, like ^S */ 867 s = spltty(); 868 if (!ISSET(tp->t_state, TS_TTSTOP)) { 869 SET(tp->t_state, TS_TTSTOP); 870 #ifdef sun4c /* XXX */ 871 (*tp->t_stop)(tp, 0); 872 #else 873 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 874 #endif 875 } 876 splx(s); 877 break; 878 case TIOCSCTTY: /* become controlling tty */ 879 /* Session ctty vnode pointer set in vnode layer. */ 880 if (!SESS_LEADER(p) || 881 ((p->p_session->s_ttyvp || tp->t_session) && 882 (tp->t_session != p->p_session))) 883 return (EPERM); 884 tp->t_session = p->p_session; 885 tp->t_pgrp = p->p_pgrp; 886 p->p_session->s_ttyp = tp; 887 p->p_flag |= P_CONTROLT; 888 break; 889 case TIOCSPGRP: { /* set pgrp of tty */ 890 register struct pgrp *pgrp = pgfind(*(int *)data); 891 892 if (!isctty(p, tp)) 893 return (ENOTTY); 894 else if (pgrp == NULL || pgrp->pg_session != p->p_session) 895 return (EPERM); 896 tp->t_pgrp = pgrp; 897 break; 898 } 899 case TIOCSTAT: /* simulate control-T */ 900 ttyinfo(tp); 901 break; 902 case TIOCSWINSZ: /* set window size */ 903 if (bcmp((caddr_t)&tp->t_winsize, data, 904 sizeof (struct winsize))) { 905 tp->t_winsize = *(struct winsize *)data; 906 pgsignal(tp->t_pgrp, SIGWINCH, 1); 907 } 908 break; 909 case TIOCSDRAINWAIT: 910 error = suser(p->p_ucred, &p->p_acflag); 911 if (error) 912 return (error); 913 tp->t_timeout = *(int *)data * hz; 914 wakeup((caddr_t)&tp->t_outq); 915 break; 916 case TIOCGDRAINWAIT: 917 *(int *)data = tp->t_timeout / hz; 918 break; 919 default: 920 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 921 return (ttcompat(tp, cmd, data, flag)); 922 #else 923 return (-1); 924 #endif 925 } 926 return (0); 927 } 928 929 int 930 ttselect(device, rw, p) 931 dev_t device; 932 int rw; 933 struct proc *p; 934 { 935 register struct tty *tp; 936 int nread, s; 937 938 tp = &cdevsw[major(device)].d_ttys[minor(device)]; 939 940 s = spltty(); 941 switch (rw) { 942 case FREAD: 943 nread = ttnread(tp); 944 if (nread > 0 || (!ISSET(tp->t_cflag, CLOCAL) && 945 !ISSET(tp->t_state, TS_CARR_ON))) 946 goto win; 947 selrecord(p, &tp->t_rsel); 948 break; 949 case FWRITE: 950 if (tp->t_outq.c_cc <= tp->t_lowat) { 951 win: splx(s); 952 return (1); 953 } 954 selrecord(p, &tp->t_wsel); 955 break; 956 } 957 splx(s); 958 return (0); 959 } 960 961 static int 962 ttnread(tp) 963 struct tty *tp; 964 { 965 int nread; 966 967 if (ISSET(tp->t_lflag, PENDIN)) 968 ttypend(tp); 969 nread = tp->t_canq.c_cc; 970 if (!ISSET(tp->t_lflag, ICANON)) { 971 nread += tp->t_rawq.c_cc; 972 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0) 973 nread = 0; 974 } 975 return (nread); 976 } 977 978 /* 979 * Wait for output to drain. 980 */ 981 int 982 ttywait(tp) 983 register struct tty *tp; 984 { 985 int error, s; 986 987 error = 0; 988 s = spltty(); 989 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 990 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) 991 && tp->t_oproc) { 992 (*tp->t_oproc)(tp); 993 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 994 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) { 995 SET(tp->t_state, TS_ASLEEP); 996 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, 997 ttyout, tp->t_timeout); 998 if (error) 999 break; 1000 } 1001 } 1002 splx(s); 1003 return (error); 1004 } 1005 1006 /* 1007 * Flush if successfully wait. 1008 */ 1009 int 1010 ttywflush(tp) 1011 struct tty *tp; 1012 { 1013 int error; 1014 1015 if ((error = ttywait(tp)) == 0) 1016 ttyflush(tp, FREAD); 1017 return (error); 1018 } 1019 1020 /* 1021 * Flush tty read and/or write queues, notifying anyone waiting. 1022 */ 1023 void 1024 ttyflush(tp, rw) 1025 register struct tty *tp; 1026 int rw; 1027 { 1028 register int s; 1029 1030 s = spltty(); 1031 if (rw & FWRITE) 1032 CLR(tp->t_state, TS_TTSTOP); 1033 #ifdef sun4c /* XXX */ 1034 (*tp->t_stop)(tp, rw); 1035 #else 1036 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 1037 #endif 1038 if (rw & FREAD) { 1039 FLUSHQ(&tp->t_canq); 1040 FLUSHQ(&tp->t_rawq); 1041 tp->t_rocount = 0; 1042 tp->t_rocol = 0; 1043 CLR(tp->t_state, TS_LOCAL); 1044 ttwakeup(tp); 1045 } 1046 if (rw & FWRITE) { 1047 FLUSHQ(&tp->t_outq); 1048 wakeup((caddr_t)&tp->t_outq); 1049 selwakeup(&tp->t_wsel); 1050 } 1051 splx(s); 1052 } 1053 1054 /* 1055 * Copy in the default termios characters. 1056 */ 1057 void 1058 ttychars(tp) 1059 struct tty *tp; 1060 { 1061 1062 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 1063 } 1064 1065 /* 1066 * Send stop character on input overflow. 1067 */ 1068 static void 1069 ttyblock(tp) 1070 register struct tty *tp; 1071 { 1072 register int total; 1073 1074 total = tp->t_rawq.c_cc + tp->t_canq.c_cc; 1075 if (tp->t_rawq.c_cc > TTYHOG) { 1076 ttyflush(tp, FREAD | FWRITE); 1077 CLR(tp->t_state, TS_TBLOCK); 1078 } 1079 /* 1080 * Block further input iff: current input > threshold 1081 * AND input is available to user program. 1082 */ 1083 if ((total >= TTYHOG / 2 && 1084 !ISSET(tp->t_state, TS_TBLOCK) && 1085 !ISSET(tp->t_lflag, ICANON)) || (tp->t_canq.c_cc > 0 && 1086 tp->t_cc[VSTOP] != _POSIX_VDISABLE)) { 1087 if (putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) { 1088 SET(tp->t_state, TS_TBLOCK); 1089 ttstart(tp); 1090 } 1091 } 1092 } 1093 1094 void 1095 ttrstrt(tp_arg) 1096 void *tp_arg; 1097 { 1098 struct tty *tp; 1099 int s; 1100 1101 #ifdef DIAGNOSTIC 1102 if (tp_arg == NULL) 1103 panic("ttrstrt"); 1104 #endif 1105 tp = tp_arg; 1106 s = spltty(); 1107 1108 CLR(tp->t_state, TS_TIMEOUT); 1109 ttstart(tp); 1110 1111 splx(s); 1112 } 1113 1114 int 1115 ttstart(tp) 1116 struct tty *tp; 1117 { 1118 1119 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ 1120 (*tp->t_oproc)(tp); 1121 return (0); 1122 } 1123 1124 /* 1125 * "close" a line discipline 1126 */ 1127 int 1128 ttylclose(tp, flag) 1129 struct tty *tp; 1130 int flag; 1131 { 1132 1133 if (flag & IO_NDELAY) 1134 ttyflush(tp, FREAD | FWRITE); 1135 else 1136 ttywflush(tp); 1137 return (0); 1138 } 1139 1140 /* 1141 * Handle modem control transition on a tty. 1142 * Flag indicates new state of carrier. 1143 * Returns 0 if the line should be turned off, otherwise 1. 1144 */ 1145 int 1146 ttymodem(tp, flag) 1147 register struct tty *tp; 1148 int flag; 1149 { 1150 1151 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) { 1152 /* 1153 * MDMBUF: do flow control according to carrier flag 1154 */ 1155 if (flag) { 1156 CLR(tp->t_state, TS_TTSTOP); 1157 ttstart(tp); 1158 } else if (!ISSET(tp->t_state, TS_TTSTOP)) { 1159 SET(tp->t_state, TS_TTSTOP); 1160 #ifdef sun4c /* XXX */ 1161 (*tp->t_stop)(tp, 0); 1162 #else 1163 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 1164 #endif 1165 } 1166 } else if (flag == 0) { 1167 /* 1168 * Lost carrier. 1169 */ 1170 CLR(tp->t_state, TS_CARR_ON); 1171 if (ISSET(tp->t_state, TS_ISOPEN) && 1172 !ISSET(tp->t_cflag, CLOCAL)) { 1173 if (tp->t_session && tp->t_session->s_leader) 1174 psignal(tp->t_session->s_leader, SIGHUP); 1175 ttyflush(tp, FREAD | FWRITE); 1176 return (0); 1177 } 1178 } else { 1179 /* 1180 * Carrier now on. 1181 */ 1182 SET(tp->t_state, TS_CARR_ON); 1183 ttwakeup(tp); 1184 } 1185 return (1); 1186 } 1187 1188 /* 1189 * Default modem control routine (for other line disciplines). 1190 * Return argument flag, to turn off device on carrier drop. 1191 */ 1192 int 1193 nullmodem(tp, flag) 1194 register struct tty *tp; 1195 int flag; 1196 { 1197 1198 if (flag) 1199 SET(tp->t_state, TS_CARR_ON); 1200 else { 1201 CLR(tp->t_state, TS_CARR_ON); 1202 if (!ISSET(tp->t_cflag, CLOCAL)) { 1203 if (tp->t_session && tp->t_session->s_leader) 1204 psignal(tp->t_session->s_leader, SIGHUP); 1205 return (0); 1206 } 1207 } 1208 return (1); 1209 } 1210 1211 /* 1212 * Reinput pending characters after state switch 1213 * call at spltty(). 1214 */ 1215 void 1216 ttypend(tp) 1217 register struct tty *tp; 1218 { 1219 struct clist tq; 1220 register c; 1221 1222 CLR(tp->t_lflag, PENDIN); 1223 SET(tp->t_state, TS_TYPEN); 1224 /* 1225 * XXX this assumes too much about clist internals. It may even 1226 * fail if the cblock slush pool is empty. We can't allocate more 1227 * cblocks here because we are called from an interrupt handler 1228 * and clist_alloc_cblocks() can wait. 1229 */ 1230 tq = tp->t_rawq; 1231 bzero(&tp->t_rawq, sizeof tp->t_rawq); 1232 tp->t_rawq.c_cbmax = tq.c_cbmax; 1233 tp->t_rawq.c_cbreserved = tq.c_cbreserved; 1234 while ((c = getc(&tq)) >= 0) 1235 ttyinput(c, tp); 1236 CLR(tp->t_state, TS_TYPEN); 1237 } 1238 1239 /* 1240 * Process a read call on a tty device. 1241 */ 1242 int 1243 ttread(tp, uio, flag) 1244 register struct tty *tp; 1245 struct uio *uio; 1246 int flag; 1247 { 1248 register struct clist *qp; 1249 register int c; 1250 register tcflag_t lflag; 1251 register cc_t *cc = tp->t_cc; 1252 register struct proc *p = curproc; 1253 int s, first, error = 0, carrier; 1254 int has_stime = 0, last_cc = 0; 1255 long slp = 0; /* XXX this should be renamed `timo'. */ 1256 1257 loop: 1258 s = spltty(); 1259 lflag = tp->t_lflag; 1260 /* 1261 * take pending input first 1262 */ 1263 if (ISSET(lflag, PENDIN)) { 1264 ttypend(tp); 1265 splx(s); /* reduce latency */ 1266 s = spltty(); 1267 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */ 1268 } 1269 1270 /* 1271 * Hang process if it's in the background. 1272 */ 1273 if (isbackground(p, tp)) { 1274 splx(s); 1275 if ((p->p_sigignore & sigmask(SIGTTIN)) || 1276 (p->p_sigmask & sigmask(SIGTTIN)) || 1277 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) 1278 return (EIO); 1279 pgsignal(p->p_pgrp, SIGTTIN, 1); 1280 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0); 1281 if (error) 1282 return (error); 1283 goto loop; 1284 } 1285 1286 /* 1287 * If canonical, use the canonical queue, 1288 * else use the raw queue. 1289 * 1290 * (should get rid of clists...) 1291 */ 1292 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq; 1293 1294 if (flag & IO_NDELAY) { 1295 if (qp->c_cc > 0) 1296 goto read; 1297 carrier = ISSET(tp->t_state, TS_CARR_ON) || 1298 ISSET(tp->t_cflag, CLOCAL); 1299 if ((!carrier && ISSET(tp->t_state, TS_ISOPEN)) || 1300 !ISSET(lflag, ICANON) && cc[VMIN] == 0) { 1301 splx(s); 1302 return (0); 1303 } 1304 splx(s); 1305 return (EWOULDBLOCK); 1306 } 1307 if (!ISSET(lflag, ICANON)) { 1308 int m = cc[VMIN]; 1309 long t = cc[VTIME]; 1310 struct timeval stime, timecopy; 1311 int x; 1312 1313 /* 1314 * Check each of the four combinations. 1315 * (m > 0 && t == 0) is the normal read case. 1316 * It should be fairly efficient, so we check that and its 1317 * companion case (m == 0 && t == 0) first. 1318 * For the other two cases, we compute the target sleep time 1319 * into slp. 1320 */ 1321 if (t == 0) { 1322 if (qp->c_cc < m) 1323 goto sleep; 1324 if (qp->c_cc > 0) 1325 goto read; 1326 1327 /* m, t and qp->c_cc are all 0. 0 is enough input. */ 1328 splx(s); 1329 return (0); 1330 } 1331 t *= 100000; /* time in us */ 1332 #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \ 1333 ((t1).tv_usec - (t2).tv_usec)) 1334 if (m > 0) { 1335 if (qp->c_cc <= 0) 1336 goto sleep; 1337 if (qp->c_cc >= m) 1338 goto read; 1339 x = splclock(); 1340 timecopy = time; 1341 splx(x); 1342 if (!has_stime) { 1343 /* first character, start timer */ 1344 has_stime = 1; 1345 stime = timecopy; 1346 slp = t; 1347 } else if (qp->c_cc > last_cc) { 1348 /* got a character, restart timer */ 1349 stime = timecopy; 1350 slp = t; 1351 } else { 1352 /* nothing, check expiration */ 1353 slp = t - diff(timecopy, stime); 1354 if (slp <= 0) 1355 goto read; 1356 } 1357 last_cc = qp->c_cc; 1358 } else { /* m == 0 */ 1359 if (qp->c_cc > 0) 1360 goto read; 1361 x = splclock(); 1362 timecopy = time; 1363 splx(x); 1364 if (!has_stime) { 1365 has_stime = 1; 1366 stime = timecopy; 1367 slp = t; 1368 } else { 1369 slp = t - diff(timecopy, stime); 1370 if (slp <= 0) { 1371 /* Timed out, but 0 is enough input. */ 1372 splx(s); 1373 return (0); 1374 } 1375 } 1376 } 1377 #undef diff 1378 /* 1379 * Rounding down may make us wake up just short 1380 * of the target, so we round up. 1381 * The formula is ceiling(slp * hz/1000000). 1382 * 32-bit arithmetic is enough for hz < 169. 1383 * XXX see hzto() for how to avoid overflow if hz 1384 * is large (divide by `tick' and/or arrange to 1385 * use hzto() if hz is large). 1386 */ 1387 slp = (long) (((u_long)slp * hz) + 999999) / 1000000; 1388 goto sleep; 1389 } 1390 1391 /* 1392 * If there is no input, sleep on rawq 1393 * awaiting hardware receipt and notification. 1394 * If we have data, we don't need to check for carrier. 1395 */ 1396 if (qp->c_cc <= 0) { 1397 sleep: 1398 carrier = ISSET(tp->t_state, TS_CARR_ON) || 1399 ISSET(tp->t_cflag, CLOCAL); 1400 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) { 1401 splx(s); 1402 return (0); /* EOF */ 1403 } 1404 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 1405 carrier ? ttyin : ttopen, (int)slp); 1406 splx(s); 1407 if (error == EWOULDBLOCK) 1408 error = 0; 1409 else if (error) 1410 return (error); 1411 /* 1412 * XXX what happens if another process eats some input 1413 * while we are asleep (not just here)? It would be 1414 * safest to detect changes and reset our state variables 1415 * (has_stime and last_cc). 1416 */ 1417 slp = 0; 1418 goto loop; 1419 } 1420 read: 1421 splx(s); 1422 /* 1423 * Input present, check for input mapping and processing. 1424 */ 1425 first = 1; 1426 while ((c = getc(qp)) >= 0) { 1427 /* 1428 * delayed suspend (^Y) 1429 */ 1430 if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, ISIG)) { 1431 pgsignal(tp->t_pgrp, SIGTSTP, 1); 1432 if (first) { 1433 error = ttysleep(tp, 1434 &lbolt, TTIPRI | PCATCH, ttybg, 0); 1435 if (error) 1436 break; 1437 goto loop; 1438 } 1439 break; 1440 } 1441 /* 1442 * Interpret EOF only in canonical mode. 1443 */ 1444 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) 1445 break; 1446 /* 1447 * Give user character. 1448 */ 1449 error = ureadc(c, uio); 1450 if (error) 1451 break; 1452 if (uio->uio_resid == 0) 1453 break; 1454 /* 1455 * In canonical mode check for a "break character" 1456 * marking the end of a "line of input". 1457 */ 1458 if (ISSET(lflag, ICANON) && TTBREAKC(c)) 1459 break; 1460 first = 0; 1461 } 1462 /* 1463 * Look to unblock output now that (presumably) 1464 * the input queue has gone down. 1465 */ 1466 s = spltty(); 1467 if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) { 1468 if (cc[VSTART] != _POSIX_VDISABLE && 1469 putc(cc[VSTART], &tp->t_outq) == 0) { 1470 CLR(tp->t_state, TS_TBLOCK); 1471 ttstart(tp); 1472 } 1473 } 1474 splx(s); 1475 return (error); 1476 } 1477 1478 /* 1479 * Check the output queue on tp for space for a kernel message (from uprintf 1480 * or tprintf). Allow some space over the normal hiwater mark so we don't 1481 * lose messages due to normal flow control, but don't let the tty run amok. 1482 * Sleeps here are not interruptible, but we return prematurely if new signals 1483 * arrive. 1484 */ 1485 int 1486 ttycheckoutq(tp, wait) 1487 register struct tty *tp; 1488 int wait; 1489 { 1490 int hiwat, s, oldsig; 1491 1492 hiwat = tp->t_hiwat; 1493 s = spltty(); 1494 oldsig = wait ? curproc->p_siglist : 0; 1495 if (tp->t_outq.c_cc > hiwat + 200) 1496 while (tp->t_outq.c_cc > hiwat) { 1497 ttstart(tp); 1498 if (wait == 0 || curproc->p_siglist != oldsig) { 1499 splx(s); 1500 return (0); 1501 } 1502 timeout((void (*)__P((void *)))wakeup, 1503 (void *)&tp->t_outq, hz); 1504 SET(tp->t_state, TS_ASLEEP); 1505 (void) tsleep((caddr_t)&tp->t_outq, PZERO - 1, "ttoutq", 0); 1506 } 1507 splx(s); 1508 return (1); 1509 } 1510 1511 /* 1512 * Process a write call on a tty device. 1513 */ 1514 int 1515 ttwrite(tp, uio, flag) 1516 register struct tty *tp; 1517 register struct uio *uio; 1518 int flag; 1519 { 1520 register char *cp = 0; 1521 register int cc, ce; 1522 register struct proc *p; 1523 int i, hiwat, cnt, error, s; 1524 char obuf[OBUFSIZ]; 1525 1526 hiwat = tp->t_hiwat; 1527 cnt = uio->uio_resid; 1528 error = 0; 1529 cc = 0; 1530 loop: 1531 s = spltty(); 1532 if (!ISSET(tp->t_state, TS_CARR_ON) && 1533 !ISSET(tp->t_cflag, CLOCAL)) { 1534 if (ISSET(tp->t_state, TS_ISOPEN)) { 1535 splx(s); 1536 return (EIO); 1537 } else if (flag & IO_NDELAY) { 1538 splx(s); 1539 error = EWOULDBLOCK; 1540 goto out; 1541 } else { 1542 /* Sleep awaiting carrier. */ 1543 error = ttysleep(tp, 1544 &tp->t_rawq, TTIPRI | PCATCH,ttopen, 0); 1545 splx(s); 1546 if (error) 1547 goto out; 1548 goto loop; 1549 } 1550 } 1551 splx(s); 1552 /* 1553 * Hang the process if it's in the background. 1554 */ 1555 p = curproc; 1556 if (isbackground(p, tp) && 1557 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 && 1558 (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 1559 (p->p_sigmask & sigmask(SIGTTOU)) == 0 && 1560 p->p_pgrp->pg_jobc) { 1561 pgsignal(p->p_pgrp, SIGTTOU, 1); 1562 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0); 1563 if (error) 1564 goto out; 1565 goto loop; 1566 } 1567 /* 1568 * Process the user's data in at most OBUFSIZ chunks. Perform any 1569 * output translation. Keep track of high water mark, sleep on 1570 * overflow awaiting device aid in acquiring new space. 1571 */ 1572 while (uio->uio_resid > 0 || cc > 0) { 1573 if (ISSET(tp->t_lflag, FLUSHO)) { 1574 uio->uio_resid = 0; 1575 return (0); 1576 } 1577 if (tp->t_outq.c_cc > hiwat) 1578 goto ovhiwat; 1579 /* 1580 * Grab a hunk of data from the user, unless we have some 1581 * leftover from last time. 1582 */ 1583 if (cc == 0) { 1584 cc = min(uio->uio_resid, OBUFSIZ); 1585 cp = obuf; 1586 error = uiomove(cp, cc, uio); 1587 if (error) { 1588 cc = 0; 1589 break; 1590 } 1591 } 1592 /* 1593 * If nothing fancy need be done, grab those characters we 1594 * can handle without any of ttyoutput's processing and 1595 * just transfer them to the output q. For those chars 1596 * which require special processing (as indicated by the 1597 * bits in char_type), call ttyoutput. After processing 1598 * a hunk of data, look for FLUSHO so ^O's will take effect 1599 * immediately. 1600 */ 1601 while (cc > 0) { 1602 if (!ISSET(tp->t_oflag, OPOST)) 1603 ce = cc; 1604 else { 1605 ce = cc - scanc((u_int)cc, (u_char *)cp, 1606 (u_char *)char_type, CCLASSMASK); 1607 /* 1608 * If ce is zero, then we're processing 1609 * a special character through ttyoutput. 1610 */ 1611 if (ce == 0) { 1612 tp->t_rocount = 0; 1613 if (ttyoutput(*cp, tp) >= 0) { 1614 /* No Clists, wait a bit. */ 1615 ttstart(tp); 1616 if (flag & IO_NDELAY) { 1617 error = EWOULDBLOCK; 1618 goto out; 1619 } 1620 error = ttysleep(tp, &lbolt, 1621 TTOPRI | PCATCH, ttybuf, 0); 1622 if (error) 1623 goto out; 1624 goto loop; 1625 } 1626 cp++; 1627 cc--; 1628 if (ISSET(tp->t_lflag, FLUSHO) || 1629 tp->t_outq.c_cc > hiwat) 1630 goto ovhiwat; 1631 continue; 1632 } 1633 } 1634 /* 1635 * A bunch of normal characters have been found. 1636 * Transfer them en masse to the output queue and 1637 * continue processing at the top of the loop. 1638 * If there are any further characters in this 1639 * <= OBUFSIZ chunk, the first should be a character 1640 * requiring special handling by ttyoutput. 1641 */ 1642 tp->t_rocount = 0; 1643 i = b_to_q(cp, ce, &tp->t_outq); 1644 ce -= i; 1645 tp->t_column += ce; 1646 cp += ce, cc -= ce, tk_nout += ce; 1647 tp->t_outcc += ce; 1648 if (i > 0) { 1649 /* No Clists, wait a bit. */ 1650 ttstart(tp); 1651 if (flag & IO_NDELAY) { 1652 error = EWOULDBLOCK; 1653 goto out; 1654 } 1655 error = ttysleep(tp, 1656 &lbolt, TTOPRI | PCATCH, ttybuf, 0); 1657 if (error) 1658 goto out; 1659 goto loop; 1660 } 1661 if (ISSET(tp->t_lflag, FLUSHO) || 1662 tp->t_outq.c_cc > hiwat) 1663 break; 1664 } 1665 ttstart(tp); 1666 } 1667 out: 1668 /* 1669 * If cc is nonzero, we leave the uio structure inconsistent, as the 1670 * offset and iov pointers have moved forward, but it doesn't matter 1671 * (the call will either return short or restart with a new uio). 1672 */ 1673 uio->uio_resid += cc; 1674 return (error); 1675 1676 ovhiwat: 1677 ttstart(tp); 1678 s = spltty(); 1679 /* 1680 * This can only occur if FLUSHO is set in t_lflag, 1681 * or if ttstart/oproc is synchronous (or very fast). 1682 */ 1683 if (tp->t_outq.c_cc <= hiwat) { 1684 splx(s); 1685 goto loop; 1686 } 1687 if (flag & IO_NDELAY) { 1688 splx(s); 1689 uio->uio_resid += cc; 1690 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); 1691 } 1692 SET(tp->t_state, TS_ASLEEP); 1693 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 1694 splx(s); 1695 if (error) 1696 goto out; 1697 goto loop; 1698 } 1699 1700 /* 1701 * Rubout one character from the rawq of tp 1702 * as cleanly as possible. 1703 */ 1704 void 1705 ttyrub(c, tp) 1706 register int c; 1707 register struct tty *tp; 1708 { 1709 register char *cp; 1710 register int savecol; 1711 int tabc, s; 1712 1713 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) 1714 return; 1715 CLR(tp->t_lflag, FLUSHO); 1716 if (ISSET(tp->t_lflag, ECHOE)) { 1717 if (tp->t_rocount == 0) { 1718 /* 1719 * Screwed by ttwrite; retype 1720 */ 1721 ttyretype(tp); 1722 return; 1723 } 1724 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) 1725 ttyrubo(tp, 2); 1726 else { 1727 CLR(c, ~TTY_CHARMASK); 1728 switch (CCLASS(c)) { 1729 case ORDINARY: 1730 ttyrubo(tp, 1); 1731 break; 1732 case BACKSPACE: 1733 case CONTROL: 1734 case NEWLINE: 1735 case RETURN: 1736 case VTAB: 1737 if (ISSET(tp->t_lflag, ECHOCTL)) 1738 ttyrubo(tp, 2); 1739 break; 1740 case TAB: 1741 if (tp->t_rocount < tp->t_rawq.c_cc) { 1742 ttyretype(tp); 1743 return; 1744 } 1745 s = spltty(); 1746 savecol = tp->t_column; 1747 SET(tp->t_state, TS_CNTTB); 1748 SET(tp->t_lflag, FLUSHO); 1749 tp->t_column = tp->t_rocol; 1750 cp = tp->t_rawq.c_cf; 1751 if (cp) 1752 tabc = *cp; /* XXX FIX NEXTC */ 1753 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc)) 1754 ttyecho(tabc, tp); 1755 CLR(tp->t_lflag, FLUSHO); 1756 CLR(tp->t_state, TS_CNTTB); 1757 splx(s); 1758 1759 /* savecol will now be length of the tab. */ 1760 savecol -= tp->t_column; 1761 tp->t_column += savecol; 1762 if (savecol > 8) 1763 savecol = 8; /* overflow screw */ 1764 while (--savecol >= 0) 1765 (void)ttyoutput('\b', tp); 1766 break; 1767 default: /* XXX */ 1768 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n" 1769 (void)printf(PANICSTR, c, CCLASS(c)); 1770 #ifdef notdef 1771 panic(PANICSTR, c, CCLASS(c)); 1772 #endif 1773 } 1774 } 1775 } else if (ISSET(tp->t_lflag, ECHOPRT)) { 1776 if (!ISSET(tp->t_state, TS_ERASE)) { 1777 SET(tp->t_state, TS_ERASE); 1778 (void)ttyoutput('\\', tp); 1779 } 1780 ttyecho(c, tp); 1781 } else 1782 ttyecho(tp->t_cc[VERASE], tp); 1783 --tp->t_rocount; 1784 } 1785 1786 /* 1787 * Back over cnt characters, erasing them. 1788 */ 1789 static void 1790 ttyrubo(tp, cnt) 1791 register struct tty *tp; 1792 int cnt; 1793 { 1794 1795 while (cnt-- > 0) { 1796 (void)ttyoutput('\b', tp); 1797 (void)ttyoutput(' ', tp); 1798 (void)ttyoutput('\b', tp); 1799 } 1800 } 1801 1802 /* 1803 * ttyretype -- 1804 * Reprint the rawq line. Note, it is assumed that c_cc has already 1805 * been checked. 1806 */ 1807 void 1808 ttyretype(tp) 1809 register struct tty *tp; 1810 { 1811 register char *cp; 1812 int s, c; 1813 1814 /* Echo the reprint character. */ 1815 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 1816 ttyecho(tp->t_cc[VREPRINT], tp); 1817 1818 (void)ttyoutput('\n', tp); 1819 1820 /* 1821 * XXX 1822 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE 1823 * BIT OF FIRST CHAR. 1824 */ 1825 s = spltty(); 1826 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0); 1827 cp != NULL; cp = nextc(&tp->t_canq, cp, &c)) 1828 ttyecho(c, tp); 1829 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0); 1830 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c)) 1831 ttyecho(c, tp); 1832 CLR(tp->t_state, TS_ERASE); 1833 splx(s); 1834 1835 tp->t_rocount = tp->t_rawq.c_cc; 1836 tp->t_rocol = 0; 1837 } 1838 1839 /* 1840 * Echo a typed character to the terminal. 1841 */ 1842 static void 1843 ttyecho(c, tp) 1844 register int c; 1845 register struct tty *tp; 1846 { 1847 1848 if (!ISSET(tp->t_state, TS_CNTTB)) 1849 CLR(tp->t_lflag, FLUSHO); 1850 if ((!ISSET(tp->t_lflag, ECHO) && 1851 (!ISSET(tp->t_lflag, ECHONL) || c == '\n')) || 1852 ISSET(tp->t_lflag, EXTPROC)) 1853 return; 1854 if (ISSET(tp->t_lflag, ECHOCTL) && 1855 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') || 1856 ISSET(c, TTY_CHARMASK) == 0177)) { 1857 (void)ttyoutput('^', tp); 1858 CLR(c, ~TTY_CHARMASK); 1859 if (c == 0177) 1860 c = '?'; 1861 else 1862 c += 'A' - 1; 1863 } 1864 (void)ttyoutput(c, tp); 1865 } 1866 1867 /* 1868 * Wake up any readers on a tty. 1869 */ 1870 void 1871 ttwakeup(tp) 1872 register struct tty *tp; 1873 { 1874 1875 selwakeup(&tp->t_rsel); 1876 if (ISSET(tp->t_state, TS_ASYNC)) 1877 pgsignal(tp->t_pgrp, SIGIO, 1); 1878 wakeup((caddr_t)&tp->t_rawq); 1879 } 1880 1881 /* 1882 * Look up a code for a specified speed in a conversion table; 1883 * used by drivers to map software speed values to hardware parameters. 1884 */ 1885 int 1886 ttspeedtab(speed, table) 1887 int speed; 1888 register struct speedtab *table; 1889 { 1890 1891 for ( ; table->sp_speed != -1; table++) 1892 if (table->sp_speed == speed) 1893 return (table->sp_code); 1894 return (-1); 1895 } 1896 1897 /* 1898 * Set tty hi and low water marks. 1899 * 1900 * Try to arrange the dynamics so there's about one second 1901 * from hi to low water. 1902 * 1903 */ 1904 void 1905 ttsetwater(tp) 1906 struct tty *tp; 1907 { 1908 register int cps, x; 1909 1910 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x)) 1911 1912 cps = tp->t_ospeed / 10; 1913 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT); 1914 x += cps; 1915 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT); 1916 tp->t_hiwat = roundup(x, CBSIZE); 1917 #undef CLAMP 1918 } 1919 1920 /* 1921 * Report on state of foreground process group. 1922 */ 1923 void 1924 ttyinfo(tp) 1925 register struct tty *tp; 1926 { 1927 register struct proc *p, *pick; 1928 struct timeval utime, stime; 1929 int tmp; 1930 1931 if (ttycheckoutq(tp,0) == 0) 1932 return; 1933 1934 /* Print load average. */ 1935 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 1936 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); 1937 1938 if (tp->t_session == NULL) 1939 ttyprintf(tp, "not a controlling terminal\n"); 1940 else if (tp->t_pgrp == NULL) 1941 ttyprintf(tp, "no foreground process group\n"); 1942 else if ((p = tp->t_pgrp->pg_mem) == NULL) 1943 ttyprintf(tp, "empty foreground process group\n"); 1944 else { 1945 /* Pick interesting process. */ 1946 for (pick = NULL; p != NULL; p = p->p_pgrpnxt) 1947 if (proc_compare(pick, p)) 1948 pick = p; 1949 1950 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid, 1951 pick->p_stat == SRUN ? "running" : 1952 pick->p_wmesg ? pick->p_wmesg : "iowait"); 1953 1954 calcru(pick, &utime, &stime, NULL); 1955 1956 /* Print user time. */ 1957 ttyprintf(tp, "%d.%02du ", 1958 utime.tv_sec, utime.tv_usec / 10000); 1959 1960 /* Print system time. */ 1961 ttyprintf(tp, "%d.%02ds ", 1962 stime.tv_sec, stime.tv_usec / 10000); 1963 1964 #define pgtok(a) (((a) * NBPG) / 1024) 1965 /* Print percentage cpu, resident set size. */ 1966 tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT; 1967 ttyprintf(tp, "%d%% %dk\n", 1968 tmp / 100, 1969 pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 : 1970 #ifdef pmap_resident_count 1971 pgtok(pmap_resident_count(&pick->p_vmspace->vm_pmap)) 1972 #else 1973 pgtok(pick->p_vmspace->vm_rssize) 1974 #endif 1975 ); 1976 } 1977 tp->t_rocount = 0; /* so pending input will be retyped if BS */ 1978 } 1979 1980 /* 1981 * Returns 1 if p2 is "better" than p1 1982 * 1983 * The algorithm for picking the "interesting" process is thus: 1984 * 1985 * 1) Only foreground processes are eligible - implied. 1986 * 2) Runnable processes are favored over anything else. The runner 1987 * with the highest cpu utilization is picked (p_estcpu). Ties are 1988 * broken by picking the highest pid. 1989 * 3) The sleeper with the shortest sleep time is next. With ties, 1990 * we pick out just "short-term" sleepers (P_SINTR == 0). 1991 * 4) Further ties are broken by picking the highest pid. 1992 */ 1993 #define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL)) 1994 #define TESTAB(a, b) ((a)<<1 | (b)) 1995 #define ONLYA 2 1996 #define ONLYB 1 1997 #define BOTH 3 1998 1999 static int 2000 proc_compare(p1, p2) 2001 register struct proc *p1, *p2; 2002 { 2003 2004 if (p1 == NULL) 2005 return (1); 2006 /* 2007 * see if at least one of them is runnable 2008 */ 2009 switch (TESTAB(ISRUN(p1), ISRUN(p2))) { 2010 case ONLYA: 2011 return (0); 2012 case ONLYB: 2013 return (1); 2014 case BOTH: 2015 /* 2016 * tie - favor one with highest recent cpu utilization 2017 */ 2018 if (p2->p_estcpu > p1->p_estcpu) 2019 return (1); 2020 if (p1->p_estcpu > p2->p_estcpu) 2021 return (0); 2022 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2023 } 2024 /* 2025 * weed out zombies 2026 */ 2027 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) { 2028 case ONLYA: 2029 return (1); 2030 case ONLYB: 2031 return (0); 2032 case BOTH: 2033 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2034 } 2035 /* 2036 * pick the one with the smallest sleep time 2037 */ 2038 if (p2->p_slptime > p1->p_slptime) 2039 return (0); 2040 if (p1->p_slptime > p2->p_slptime) 2041 return (1); 2042 /* 2043 * favor one sleeping in a non-interruptible sleep 2044 */ 2045 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0) 2046 return (1); 2047 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0) 2048 return (0); 2049 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2050 } 2051 2052 /* 2053 * Output char to tty; console putchar style. 2054 */ 2055 int 2056 tputchar(c, tp) 2057 int c; 2058 struct tty *tp; 2059 { 2060 register int s; 2061 2062 s = spltty(); 2063 if (ISSET(tp->t_state, 2064 TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) { 2065 splx(s); 2066 return (-1); 2067 } 2068 if (c == '\n') 2069 (void)ttyoutput('\r', tp); 2070 (void)ttyoutput(c, tp); 2071 ttstart(tp); 2072 splx(s); 2073 return (0); 2074 } 2075 2076 /* 2077 * Sleep on chan, returning ERESTART if tty changed while we napped and 2078 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If 2079 * the tty is revoked, restarting a pending call will redo validation done 2080 * at the start of the call. 2081 */ 2082 int 2083 ttysleep(tp, chan, pri, wmesg, timo) 2084 struct tty *tp; 2085 void *chan; 2086 int pri, timo; 2087 char *wmesg; 2088 { 2089 int error; 2090 short gen; 2091 2092 gen = tp->t_gen; 2093 error = tsleep(chan, pri, wmesg, timo); 2094 if (error) 2095 return (error); 2096 return (tp->t_gen == gen ? 0 : ERESTART); 2097 } 2098