tty.c revision 5396
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.16 1994/12/04 01:01:45 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 61static int proc_compare __P((struct proc *p1, struct proc *p2)); 62static int ttnread __P((struct tty *)); 63static void ttyblock __P((struct tty *tp)); 64static void ttyecho __P((int, struct tty *tp)); 65static void ttyrubo __P((struct tty *, int)); 66 67/* Symbolic sleep message strings. */ 68char ttclos[] = "ttycls"; 69char ttopen[] = "ttyopn"; 70char ttybg[] = "ttybg"; 71char ttybuf[] = "ttybuf"; 72char ttyin[] = "ttyin"; 73char 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 101char 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 */ 156int 157ttyopen(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 */ 188int 189ttyclose(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 */ 226int 227ttyinput(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)) { 273parmrk: (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 } 527endcase: 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); 534restartoutput: 535 CLR(tp->t_lflag, FLUSHO); 536 CLR(tp->t_state, TS_TTSTOP); 537startoutput: 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 */ 547int 548ttyoutput(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 */ 632int 633ttioctl(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 != 0) { 912 splx(s); 913 return (EPERM); 914 } 915 tp->t_timeout = *(int *)data * hz; 916 wakeup((caddr_t)&tp->t_outq); 917 break; 918 case TIOCGDRAINWAIT: 919 *(int *)data = tp->t_timeout / hz; 920 break; 921 default: 922#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 923 return (ttcompat(tp, cmd, data, flag)); 924#else 925 return (-1); 926#endif 927 } 928 return (0); 929} 930 931int 932ttselect(device, rw, p) 933 dev_t device; 934 int rw; 935 struct proc *p; 936{ 937 register struct tty *tp; 938 int nread, s; 939 940 tp = &cdevsw[major(device)].d_ttys[minor(device)]; 941 942 s = spltty(); 943 switch (rw) { 944 case FREAD: 945 nread = ttnread(tp); 946 if (nread > 0 || (!ISSET(tp->t_cflag, CLOCAL) && 947 !ISSET(tp->t_state, TS_CARR_ON))) 948 goto win; 949 selrecord(p, &tp->t_rsel); 950 break; 951 case FWRITE: 952 if (tp->t_outq.c_cc <= tp->t_lowat) { 953win: splx(s); 954 return (1); 955 } 956 selrecord(p, &tp->t_wsel); 957 break; 958 } 959 splx(s); 960 return (0); 961} 962 963static int 964ttnread(tp) 965 struct tty *tp; 966{ 967 int nread; 968 969 if (ISSET(tp->t_lflag, PENDIN)) 970 ttypend(tp); 971 nread = tp->t_canq.c_cc; 972 if (!ISSET(tp->t_lflag, ICANON)) { 973 nread += tp->t_rawq.c_cc; 974 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0) 975 nread = 0; 976 } 977 return (nread); 978} 979 980/* 981 * Wait for output to drain. 982 */ 983int 984ttywait(tp) 985 register struct tty *tp; 986{ 987 int error, s; 988 989 error = 0; 990 s = spltty(); 991 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 992 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) 993 && tp->t_oproc) { 994 (*tp->t_oproc)(tp); 995 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 996 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) { 997 SET(tp->t_state, TS_ASLEEP); 998 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, 999 ttyout, tp->t_timeout); 1000 if (error) 1001 break; 1002 } 1003 } 1004 splx(s); 1005 return (error); 1006} 1007 1008/* 1009 * Flush if successfully wait. 1010 */ 1011int 1012ttywflush(tp) 1013 struct tty *tp; 1014{ 1015 int error; 1016 1017 if ((error = ttywait(tp)) == 0) 1018 ttyflush(tp, FREAD); 1019 return (error); 1020} 1021 1022/* 1023 * Flush tty read and/or write queues, notifying anyone waiting. 1024 */ 1025void 1026ttyflush(tp, rw) 1027 register struct tty *tp; 1028 int rw; 1029{ 1030 register int s; 1031 1032 s = spltty(); 1033 if (rw & FWRITE) 1034 CLR(tp->t_state, TS_TTSTOP); 1035#ifdef sun4c /* XXX */ 1036 (*tp->t_stop)(tp, rw); 1037#else 1038 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 1039#endif 1040 if (rw & FREAD) { 1041 FLUSHQ(&tp->t_canq); 1042 FLUSHQ(&tp->t_rawq); 1043 tp->t_rocount = 0; 1044 tp->t_rocol = 0; 1045 CLR(tp->t_state, TS_LOCAL); 1046 ttwakeup(tp); 1047 } 1048 if (rw & FWRITE) { 1049 FLUSHQ(&tp->t_outq); 1050 wakeup((caddr_t)&tp->t_outq); 1051 selwakeup(&tp->t_wsel); 1052 } 1053 splx(s); 1054} 1055 1056/* 1057 * Copy in the default termios characters. 1058 */ 1059void 1060ttychars(tp) 1061 struct tty *tp; 1062{ 1063 1064 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 1065} 1066 1067/* 1068 * Send stop character on input overflow. 1069 */ 1070static void 1071ttyblock(tp) 1072 register struct tty *tp; 1073{ 1074 register int total; 1075 1076 total = tp->t_rawq.c_cc + tp->t_canq.c_cc; 1077 if (tp->t_rawq.c_cc > TTYHOG) { 1078 ttyflush(tp, FREAD | FWRITE); 1079 CLR(tp->t_state, TS_TBLOCK); 1080 } 1081 /* 1082 * Block further input iff: current input > threshold 1083 * AND input is available to user program. 1084 */ 1085 if ((total >= TTYHOG / 2 && 1086 !ISSET(tp->t_state, TS_TBLOCK) && 1087 !ISSET(tp->t_lflag, ICANON)) || (tp->t_canq.c_cc > 0 && 1088 tp->t_cc[VSTOP] != _POSIX_VDISABLE)) { 1089 if (putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) { 1090 SET(tp->t_state, TS_TBLOCK); 1091 ttstart(tp); 1092 } 1093 } 1094} 1095 1096void 1097ttrstrt(tp_arg) 1098 void *tp_arg; 1099{ 1100 struct tty *tp; 1101 int s; 1102 1103#ifdef DIAGNOSTIC 1104 if (tp_arg == NULL) 1105 panic("ttrstrt"); 1106#endif 1107 tp = tp_arg; 1108 s = spltty(); 1109 1110 CLR(tp->t_state, TS_TIMEOUT); 1111 ttstart(tp); 1112 1113 splx(s); 1114} 1115 1116int 1117ttstart(tp) 1118 struct tty *tp; 1119{ 1120 1121 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ 1122 (*tp->t_oproc)(tp); 1123 return (0); 1124} 1125 1126/* 1127 * "close" a line discipline 1128 */ 1129int 1130ttylclose(tp, flag) 1131 struct tty *tp; 1132 int flag; 1133{ 1134 1135 if (flag & IO_NDELAY) 1136 ttyflush(tp, FREAD | FWRITE); 1137 else 1138 ttywflush(tp); 1139 return (0); 1140} 1141 1142/* 1143 * Handle modem control transition on a tty. 1144 * Flag indicates new state of carrier. 1145 * Returns 0 if the line should be turned off, otherwise 1. 1146 */ 1147int 1148ttymodem(tp, flag) 1149 register struct tty *tp; 1150 int flag; 1151{ 1152 1153 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) { 1154 /* 1155 * MDMBUF: do flow control according to carrier flag 1156 */ 1157 if (flag) { 1158 CLR(tp->t_state, TS_TTSTOP); 1159 ttstart(tp); 1160 } else if (!ISSET(tp->t_state, TS_TTSTOP)) { 1161 SET(tp->t_state, TS_TTSTOP); 1162#ifdef sun4c /* XXX */ 1163 (*tp->t_stop)(tp, 0); 1164#else 1165 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 1166#endif 1167 } 1168 } else if (flag == 0) { 1169 /* 1170 * Lost carrier. 1171 */ 1172 CLR(tp->t_state, TS_CARR_ON); 1173 if (ISSET(tp->t_state, TS_ISOPEN) && 1174 !ISSET(tp->t_cflag, CLOCAL)) { 1175 if (tp->t_session && tp->t_session->s_leader) 1176 psignal(tp->t_session->s_leader, SIGHUP); 1177 ttyflush(tp, FREAD | FWRITE); 1178 return (0); 1179 } 1180 } else { 1181 /* 1182 * Carrier now on. 1183 */ 1184 SET(tp->t_state, TS_CARR_ON); 1185 ttwakeup(tp); 1186 } 1187 return (1); 1188} 1189 1190/* 1191 * Default modem control routine (for other line disciplines). 1192 * Return argument flag, to turn off device on carrier drop. 1193 */ 1194int 1195nullmodem(tp, flag) 1196 register struct tty *tp; 1197 int flag; 1198{ 1199 1200 if (flag) 1201 SET(tp->t_state, TS_CARR_ON); 1202 else { 1203 CLR(tp->t_state, TS_CARR_ON); 1204 if (!ISSET(tp->t_cflag, CLOCAL)) { 1205 if (tp->t_session && tp->t_session->s_leader) 1206 psignal(tp->t_session->s_leader, SIGHUP); 1207 return (0); 1208 } 1209 } 1210 return (1); 1211} 1212 1213/* 1214 * Reinput pending characters after state switch 1215 * call at spltty(). 1216 */ 1217void 1218ttypend(tp) 1219 register struct tty *tp; 1220{ 1221 struct clist tq; 1222 register c; 1223 1224 CLR(tp->t_lflag, PENDIN); 1225 SET(tp->t_state, TS_TYPEN); 1226 /* 1227 * XXX this assumes too much about clist internals. It may even 1228 * fail if the cblock slush pool is empty. We can't allocate more 1229 * cblocks here because we are called from an interrupt handler 1230 * and clist_alloc_cblocks() can wait. 1231 */ 1232 tq = tp->t_rawq; 1233 bzero(&tp->t_rawq, sizeof tp->t_rawq); 1234 tp->t_rawq.c_cbmax = tq.c_cbmax; 1235 tp->t_rawq.c_cbreserved = tq.c_cbreserved; 1236 while ((c = getc(&tq)) >= 0) 1237 ttyinput(c, tp); 1238 CLR(tp->t_state, TS_TYPEN); 1239} 1240 1241/* 1242 * Process a read call on a tty device. 1243 */ 1244int 1245ttread(tp, uio, flag) 1246 register struct tty *tp; 1247 struct uio *uio; 1248 int flag; 1249{ 1250 register struct clist *qp; 1251 register int c; 1252 register tcflag_t lflag; 1253 register cc_t *cc = tp->t_cc; 1254 register struct proc *p = curproc; 1255 int s, first, error = 0, carrier; 1256 int has_stime = 0, last_cc = 0; 1257 long slp = 0; /* XXX this should be renamed `timo'. */ 1258 1259loop: 1260 s = spltty(); 1261 lflag = tp->t_lflag; 1262 /* 1263 * take pending input first 1264 */ 1265 if (ISSET(lflag, PENDIN)) { 1266 ttypend(tp); 1267 splx(s); /* reduce latency */ 1268 s = spltty(); 1269 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */ 1270 } 1271 1272 /* 1273 * Hang process if it's in the background. 1274 */ 1275 if (isbackground(p, tp)) { 1276 splx(s); 1277 if ((p->p_sigignore & sigmask(SIGTTIN)) || 1278 (p->p_sigmask & sigmask(SIGTTIN)) || 1279 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) 1280 return (EIO); 1281 pgsignal(p->p_pgrp, SIGTTIN, 1); 1282 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0); 1283 if (error) 1284 return (error); 1285 goto loop; 1286 } 1287 1288 /* 1289 * If canonical, use the canonical queue, 1290 * else use the raw queue. 1291 * 1292 * (should get rid of clists...) 1293 */ 1294 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq; 1295 1296 if (flag & IO_NDELAY) { 1297 if (qp->c_cc > 0) 1298 goto read; 1299 carrier = ISSET(tp->t_state, TS_CARR_ON) || 1300 ISSET(tp->t_cflag, CLOCAL); 1301 if ((!carrier && ISSET(tp->t_state, TS_ISOPEN)) || 1302 !ISSET(lflag, ICANON) && cc[VMIN] == 0) { 1303 splx(s); 1304 return (0); 1305 } 1306 splx(s); 1307 return (EWOULDBLOCK); 1308 } 1309 if (!ISSET(lflag, ICANON)) { 1310 int m = cc[VMIN]; 1311 long t = cc[VTIME]; 1312 struct timeval stime, timecopy; 1313 int x; 1314 1315 /* 1316 * Check each of the four combinations. 1317 * (m > 0 && t == 0) is the normal read case. 1318 * It should be fairly efficient, so we check that and its 1319 * companion case (m == 0 && t == 0) first. 1320 * For the other two cases, we compute the target sleep time 1321 * into slp. 1322 */ 1323 if (t == 0) { 1324 if (qp->c_cc < m) 1325 goto sleep; 1326 if (qp->c_cc > 0) 1327 goto read; 1328 1329 /* m, t and qp->c_cc are all 0. 0 is enough input. */ 1330 splx(s); 1331 return (0); 1332 } 1333 t *= 100000; /* time in us */ 1334#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \ 1335 ((t1).tv_usec - (t2).tv_usec)) 1336 if (m > 0) { 1337 if (qp->c_cc <= 0) 1338 goto sleep; 1339 if (qp->c_cc >= m) 1340 goto read; 1341 x = splclock(); 1342 timecopy = time; 1343 splx(x); 1344 if (!has_stime) { 1345 /* first character, start timer */ 1346 has_stime = 1; 1347 stime = timecopy; 1348 slp = t; 1349 } else if (qp->c_cc > last_cc) { 1350 /* got a character, restart timer */ 1351 stime = timecopy; 1352 slp = t; 1353 } else { 1354 /* nothing, check expiration */ 1355 slp = t - diff(timecopy, stime); 1356 if (slp <= 0) 1357 goto read; 1358 } 1359 last_cc = qp->c_cc; 1360 } else { /* m == 0 */ 1361 if (qp->c_cc > 0) 1362 goto read; 1363 x = splclock(); 1364 timecopy = time; 1365 splx(x); 1366 if (!has_stime) { 1367 has_stime = 1; 1368 stime = timecopy; 1369 slp = t; 1370 } else { 1371 slp = t - diff(timecopy, stime); 1372 if (slp <= 0) { 1373 /* Timed out, but 0 is enough input. */ 1374 splx(s); 1375 return (0); 1376 } 1377 } 1378 } 1379#undef diff 1380 /* 1381 * Rounding down may make us wake up just short 1382 * of the target, so we round up. 1383 * The formula is ceiling(slp * hz/1000000). 1384 * 32-bit arithmetic is enough for hz < 169. 1385 * XXX see hzto() for how to avoid overflow if hz 1386 * is large (divide by `tick' and/or arrange to 1387 * use hzto() if hz is large). 1388 */ 1389 slp = (long) (((u_long)slp * hz) + 999999) / 1000000; 1390 goto sleep; 1391 } 1392 1393 /* 1394 * If there is no input, sleep on rawq 1395 * awaiting hardware receipt and notification. 1396 * If we have data, we don't need to check for carrier. 1397 */ 1398 if (qp->c_cc <= 0) { 1399sleep: 1400 carrier = ISSET(tp->t_state, TS_CARR_ON) || 1401 ISSET(tp->t_cflag, CLOCAL); 1402 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) { 1403 splx(s); 1404 return (0); /* EOF */ 1405 } 1406 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 1407 carrier ? ttyin : ttopen, (int)slp); 1408 splx(s); 1409 if (error == EWOULDBLOCK) 1410 error = 0; 1411 else if (error) 1412 return (error); 1413 /* 1414 * XXX what happens if another process eats some input 1415 * while we are asleep (not just here)? It would be 1416 * safest to detect changes and reset our state variables 1417 * (has_stime and last_cc). 1418 */ 1419 slp = 0; 1420 goto loop; 1421 } 1422read: 1423 splx(s); 1424 /* 1425 * Input present, check for input mapping and processing. 1426 */ 1427 first = 1; 1428 while ((c = getc(qp)) >= 0) { 1429 /* 1430 * delayed suspend (^Y) 1431 */ 1432 if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, ISIG)) { 1433 pgsignal(tp->t_pgrp, SIGTSTP, 1); 1434 if (first) { 1435 error = ttysleep(tp, 1436 &lbolt, TTIPRI | PCATCH, ttybg, 0); 1437 if (error) 1438 break; 1439 goto loop; 1440 } 1441 break; 1442 } 1443 /* 1444 * Interpret EOF only in canonical mode. 1445 */ 1446 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) 1447 break; 1448 /* 1449 * Give user character. 1450 */ 1451 error = ureadc(c, uio); 1452 if (error) 1453 break; 1454 if (uio->uio_resid == 0) 1455 break; 1456 /* 1457 * In canonical mode check for a "break character" 1458 * marking the end of a "line of input". 1459 */ 1460 if (ISSET(lflag, ICANON) && TTBREAKC(c)) 1461 break; 1462 first = 0; 1463 } 1464 /* 1465 * Look to unblock output now that (presumably) 1466 * the input queue has gone down. 1467 */ 1468 s = spltty(); 1469 if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) { 1470 if (cc[VSTART] != _POSIX_VDISABLE && 1471 putc(cc[VSTART], &tp->t_outq) == 0) { 1472 CLR(tp->t_state, TS_TBLOCK); 1473 ttstart(tp); 1474 } 1475 } 1476 splx(s); 1477 return (error); 1478} 1479 1480/* 1481 * Check the output queue on tp for space for a kernel message (from uprintf 1482 * or tprintf). Allow some space over the normal hiwater mark so we don't 1483 * lose messages due to normal flow control, but don't let the tty run amok. 1484 * Sleeps here are not interruptible, but we return prematurely if new signals 1485 * arrive. 1486 */ 1487int 1488ttycheckoutq(tp, wait) 1489 register struct tty *tp; 1490 int wait; 1491{ 1492 int hiwat, s, oldsig; 1493 1494 hiwat = tp->t_hiwat; 1495 s = spltty(); 1496 oldsig = wait ? curproc->p_siglist : 0; 1497 if (tp->t_outq.c_cc > hiwat + 200) 1498 while (tp->t_outq.c_cc > hiwat) { 1499 ttstart(tp); 1500 if (wait == 0 || curproc->p_siglist != oldsig) { 1501 splx(s); 1502 return (0); 1503 } 1504 timeout((void (*)__P((void *)))wakeup, 1505 (void *)&tp->t_outq, hz); 1506 SET(tp->t_state, TS_ASLEEP); 1507 (void) tsleep((caddr_t)&tp->t_outq, PZERO - 1, "ttoutq", 0); 1508 } 1509 splx(s); 1510 return (1); 1511} 1512 1513/* 1514 * Process a write call on a tty device. 1515 */ 1516int 1517ttwrite(tp, uio, flag) 1518 register struct tty *tp; 1519 register struct uio *uio; 1520 int flag; 1521{ 1522 register char *cp = 0; 1523 register int cc, ce; 1524 register struct proc *p; 1525 int i, hiwat, cnt, error, s; 1526 char obuf[OBUFSIZ]; 1527 1528 hiwat = tp->t_hiwat; 1529 cnt = uio->uio_resid; 1530 error = 0; 1531 cc = 0; 1532loop: 1533 s = spltty(); 1534 if (!ISSET(tp->t_state, TS_CARR_ON) && 1535 !ISSET(tp->t_cflag, CLOCAL)) { 1536 if (ISSET(tp->t_state, TS_ISOPEN)) { 1537 splx(s); 1538 return (EIO); 1539 } else if (flag & IO_NDELAY) { 1540 splx(s); 1541 error = EWOULDBLOCK; 1542 goto out; 1543 } else { 1544 /* Sleep awaiting carrier. */ 1545 error = ttysleep(tp, 1546 &tp->t_rawq, TTIPRI | PCATCH,ttopen, 0); 1547 splx(s); 1548 if (error) 1549 goto out; 1550 goto loop; 1551 } 1552 } 1553 splx(s); 1554 /* 1555 * Hang the process if it's in the background. 1556 */ 1557 p = curproc; 1558 if (isbackground(p, tp) && 1559 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 && 1560 (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 1561 (p->p_sigmask & sigmask(SIGTTOU)) == 0 && 1562 p->p_pgrp->pg_jobc) { 1563 pgsignal(p->p_pgrp, SIGTTOU, 1); 1564 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0); 1565 if (error) 1566 goto out; 1567 goto loop; 1568 } 1569 /* 1570 * Process the user's data in at most OBUFSIZ chunks. Perform any 1571 * output translation. Keep track of high water mark, sleep on 1572 * overflow awaiting device aid in acquiring new space. 1573 */ 1574 while (uio->uio_resid > 0 || cc > 0) { 1575 if (ISSET(tp->t_lflag, FLUSHO)) { 1576 uio->uio_resid = 0; 1577 return (0); 1578 } 1579 if (tp->t_outq.c_cc > hiwat) 1580 goto ovhiwat; 1581 /* 1582 * Grab a hunk of data from the user, unless we have some 1583 * leftover from last time. 1584 */ 1585 if (cc == 0) { 1586 cc = min(uio->uio_resid, OBUFSIZ); 1587 cp = obuf; 1588 error = uiomove(cp, cc, uio); 1589 if (error) { 1590 cc = 0; 1591 break; 1592 } 1593 } 1594 /* 1595 * If nothing fancy need be done, grab those characters we 1596 * can handle without any of ttyoutput's processing and 1597 * just transfer them to the output q. For those chars 1598 * which require special processing (as indicated by the 1599 * bits in char_type), call ttyoutput. After processing 1600 * a hunk of data, look for FLUSHO so ^O's will take effect 1601 * immediately. 1602 */ 1603 while (cc > 0) { 1604 if (!ISSET(tp->t_oflag, OPOST)) 1605 ce = cc; 1606 else { 1607 ce = cc - scanc((u_int)cc, (u_char *)cp, 1608 (u_char *)char_type, CCLASSMASK); 1609 /* 1610 * If ce is zero, then we're processing 1611 * a special character through ttyoutput. 1612 */ 1613 if (ce == 0) { 1614 tp->t_rocount = 0; 1615 if (ttyoutput(*cp, tp) >= 0) { 1616 /* No Clists, wait a bit. */ 1617 ttstart(tp); 1618 if (flag & IO_NDELAY) { 1619 error = EWOULDBLOCK; 1620 goto out; 1621 } 1622 error = ttysleep(tp, &lbolt, 1623 TTOPRI | PCATCH, ttybuf, 0); 1624 if (error) 1625 goto out; 1626 goto loop; 1627 } 1628 cp++; 1629 cc--; 1630 if (ISSET(tp->t_lflag, FLUSHO) || 1631 tp->t_outq.c_cc > hiwat) 1632 goto ovhiwat; 1633 continue; 1634 } 1635 } 1636 /* 1637 * A bunch of normal characters have been found. 1638 * Transfer them en masse to the output queue and 1639 * continue processing at the top of the loop. 1640 * If there are any further characters in this 1641 * <= OBUFSIZ chunk, the first should be a character 1642 * requiring special handling by ttyoutput. 1643 */ 1644 tp->t_rocount = 0; 1645 i = b_to_q(cp, ce, &tp->t_outq); 1646 ce -= i; 1647 tp->t_column += ce; 1648 cp += ce, cc -= ce, tk_nout += ce; 1649 tp->t_outcc += ce; 1650 if (i > 0) { 1651 /* No Clists, wait a bit. */ 1652 ttstart(tp); 1653 if (flag & IO_NDELAY) { 1654 error = EWOULDBLOCK; 1655 goto out; 1656 } 1657 error = ttysleep(tp, 1658 &lbolt, TTOPRI | PCATCH, ttybuf, 0); 1659 if (error) 1660 goto out; 1661 goto loop; 1662 } 1663 if (ISSET(tp->t_lflag, FLUSHO) || 1664 tp->t_outq.c_cc > hiwat) 1665 break; 1666 } 1667 ttstart(tp); 1668 } 1669out: 1670 /* 1671 * If cc is nonzero, we leave the uio structure inconsistent, as the 1672 * offset and iov pointers have moved forward, but it doesn't matter 1673 * (the call will either return short or restart with a new uio). 1674 */ 1675 uio->uio_resid += cc; 1676 return (error); 1677 1678ovhiwat: 1679 ttstart(tp); 1680 s = spltty(); 1681 /* 1682 * This can only occur if FLUSHO is set in t_lflag, 1683 * or if ttstart/oproc is synchronous (or very fast). 1684 */ 1685 if (tp->t_outq.c_cc <= hiwat) { 1686 splx(s); 1687 goto loop; 1688 } 1689 if (flag & IO_NDELAY) { 1690 splx(s); 1691 uio->uio_resid += cc; 1692 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); 1693 } 1694 SET(tp->t_state, TS_ASLEEP); 1695 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 1696 splx(s); 1697 if (error) 1698 goto out; 1699 goto loop; 1700} 1701 1702/* 1703 * Rubout one character from the rawq of tp 1704 * as cleanly as possible. 1705 */ 1706void 1707ttyrub(c, tp) 1708 register int c; 1709 register struct tty *tp; 1710{ 1711 register char *cp; 1712 register int savecol; 1713 int tabc, s; 1714 1715 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) 1716 return; 1717 CLR(tp->t_lflag, FLUSHO); 1718 if (ISSET(tp->t_lflag, ECHOE)) { 1719 if (tp->t_rocount == 0) { 1720 /* 1721 * Screwed by ttwrite; retype 1722 */ 1723 ttyretype(tp); 1724 return; 1725 } 1726 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) 1727 ttyrubo(tp, 2); 1728 else { 1729 CLR(c, ~TTY_CHARMASK); 1730 switch (CCLASS(c)) { 1731 case ORDINARY: 1732 ttyrubo(tp, 1); 1733 break; 1734 case BACKSPACE: 1735 case CONTROL: 1736 case NEWLINE: 1737 case RETURN: 1738 case VTAB: 1739 if (ISSET(tp->t_lflag, ECHOCTL)) 1740 ttyrubo(tp, 2); 1741 break; 1742 case TAB: 1743 if (tp->t_rocount < tp->t_rawq.c_cc) { 1744 ttyretype(tp); 1745 return; 1746 } 1747 s = spltty(); 1748 savecol = tp->t_column; 1749 SET(tp->t_state, TS_CNTTB); 1750 SET(tp->t_lflag, FLUSHO); 1751 tp->t_column = tp->t_rocol; 1752 cp = tp->t_rawq.c_cf; 1753 if (cp) 1754 tabc = *cp; /* XXX FIX NEXTC */ 1755 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc)) 1756 ttyecho(tabc, tp); 1757 CLR(tp->t_lflag, FLUSHO); 1758 CLR(tp->t_state, TS_CNTTB); 1759 splx(s); 1760 1761 /* savecol will now be length of the tab. */ 1762 savecol -= tp->t_column; 1763 tp->t_column += savecol; 1764 if (savecol > 8) 1765 savecol = 8; /* overflow screw */ 1766 while (--savecol >= 0) 1767 (void)ttyoutput('\b', tp); 1768 break; 1769 default: /* XXX */ 1770#define PANICSTR "ttyrub: would panic c = %d, val = %d\n" 1771 (void)printf(PANICSTR, c, CCLASS(c)); 1772#ifdef notdef 1773 panic(PANICSTR, c, CCLASS(c)); 1774#endif 1775 } 1776 } 1777 } else if (ISSET(tp->t_lflag, ECHOPRT)) { 1778 if (!ISSET(tp->t_state, TS_ERASE)) { 1779 SET(tp->t_state, TS_ERASE); 1780 (void)ttyoutput('\\', tp); 1781 } 1782 ttyecho(c, tp); 1783 } else 1784 ttyecho(tp->t_cc[VERASE], tp); 1785 --tp->t_rocount; 1786} 1787 1788/* 1789 * Back over cnt characters, erasing them. 1790 */ 1791static void 1792ttyrubo(tp, cnt) 1793 register struct tty *tp; 1794 int cnt; 1795{ 1796 1797 while (cnt-- > 0) { 1798 (void)ttyoutput('\b', tp); 1799 (void)ttyoutput(' ', tp); 1800 (void)ttyoutput('\b', tp); 1801 } 1802} 1803 1804/* 1805 * ttyretype -- 1806 * Reprint the rawq line. Note, it is assumed that c_cc has already 1807 * been checked. 1808 */ 1809void 1810ttyretype(tp) 1811 register struct tty *tp; 1812{ 1813 register char *cp; 1814 int s, c; 1815 1816 /* Echo the reprint character. */ 1817 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 1818 ttyecho(tp->t_cc[VREPRINT], tp); 1819 1820 (void)ttyoutput('\n', tp); 1821 1822 /* 1823 * XXX 1824 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE 1825 * BIT OF FIRST CHAR. 1826 */ 1827 s = spltty(); 1828 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0); 1829 cp != NULL; cp = nextc(&tp->t_canq, cp, &c)) 1830 ttyecho(c, tp); 1831 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0); 1832 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c)) 1833 ttyecho(c, tp); 1834 CLR(tp->t_state, TS_ERASE); 1835 splx(s); 1836 1837 tp->t_rocount = tp->t_rawq.c_cc; 1838 tp->t_rocol = 0; 1839} 1840 1841/* 1842 * Echo a typed character to the terminal. 1843 */ 1844static void 1845ttyecho(c, tp) 1846 register int c; 1847 register struct tty *tp; 1848{ 1849 1850 if (!ISSET(tp->t_state, TS_CNTTB)) 1851 CLR(tp->t_lflag, FLUSHO); 1852 if ((!ISSET(tp->t_lflag, ECHO) && 1853 (!ISSET(tp->t_lflag, ECHONL) || c == '\n')) || 1854 ISSET(tp->t_lflag, EXTPROC)) 1855 return; 1856 if (ISSET(tp->t_lflag, ECHOCTL) && 1857 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') || 1858 ISSET(c, TTY_CHARMASK) == 0177)) { 1859 (void)ttyoutput('^', tp); 1860 CLR(c, ~TTY_CHARMASK); 1861 if (c == 0177) 1862 c = '?'; 1863 else 1864 c += 'A' - 1; 1865 } 1866 (void)ttyoutput(c, tp); 1867} 1868 1869/* 1870 * Wake up any readers on a tty. 1871 */ 1872void 1873ttwakeup(tp) 1874 register struct tty *tp; 1875{ 1876 1877 selwakeup(&tp->t_rsel); 1878 if (ISSET(tp->t_state, TS_ASYNC)) 1879 pgsignal(tp->t_pgrp, SIGIO, 1); 1880 wakeup((caddr_t)&tp->t_rawq); 1881} 1882 1883/* 1884 * Look up a code for a specified speed in a conversion table; 1885 * used by drivers to map software speed values to hardware parameters. 1886 */ 1887int 1888ttspeedtab(speed, table) 1889 int speed; 1890 register struct speedtab *table; 1891{ 1892 1893 for ( ; table->sp_speed != -1; table++) 1894 if (table->sp_speed == speed) 1895 return (table->sp_code); 1896 return (-1); 1897} 1898 1899/* 1900 * Set tty hi and low water marks. 1901 * 1902 * Try to arrange the dynamics so there's about one second 1903 * from hi to low water. 1904 * 1905 */ 1906void 1907ttsetwater(tp) 1908 struct tty *tp; 1909{ 1910 register int cps, x; 1911 1912#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x)) 1913 1914 cps = tp->t_ospeed / 10; 1915 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT); 1916 x += cps; 1917 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT); 1918 tp->t_hiwat = roundup(x, CBSIZE); 1919#undef CLAMP 1920} 1921 1922/* 1923 * Report on state of foreground process group. 1924 */ 1925void 1926ttyinfo(tp) 1927 register struct tty *tp; 1928{ 1929 register struct proc *p, *pick; 1930 struct timeval utime, stime; 1931 int tmp; 1932 1933 if (ttycheckoutq(tp,0) == 0) 1934 return; 1935 1936 /* Print load average. */ 1937 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 1938 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); 1939 1940 if (tp->t_session == NULL) 1941 ttyprintf(tp, "not a controlling terminal\n"); 1942 else if (tp->t_pgrp == NULL) 1943 ttyprintf(tp, "no foreground process group\n"); 1944 else if ((p = tp->t_pgrp->pg_mem) == NULL) 1945 ttyprintf(tp, "empty foreground process group\n"); 1946 else { 1947 /* Pick interesting process. */ 1948 for (pick = NULL; p != NULL; p = p->p_pgrpnxt) 1949 if (proc_compare(pick, p)) 1950 pick = p; 1951 1952 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid, 1953 pick->p_stat == SRUN ? "running" : 1954 pick->p_wmesg ? pick->p_wmesg : "iowait"); 1955 1956 calcru(pick, &utime, &stime, NULL); 1957 1958 /* Print user time. */ 1959 ttyprintf(tp, "%d.%02du ", 1960 utime.tv_sec, utime.tv_usec / 10000); 1961 1962 /* Print system time. */ 1963 ttyprintf(tp, "%d.%02ds ", 1964 stime.tv_sec, stime.tv_usec / 10000); 1965 1966#define pgtok(a) (((a) * NBPG) / 1024) 1967 /* Print percentage cpu, resident set size. */ 1968 tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT; 1969 ttyprintf(tp, "%d%% %dk\n", 1970 tmp / 100, 1971 pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 : 1972#ifdef pmap_resident_count 1973 pgtok(pmap_resident_count(&pick->p_vmspace->vm_pmap)) 1974#else 1975 pgtok(pick->p_vmspace->vm_rssize) 1976#endif 1977 ); 1978 } 1979 tp->t_rocount = 0; /* so pending input will be retyped if BS */ 1980} 1981 1982/* 1983 * Returns 1 if p2 is "better" than p1 1984 * 1985 * The algorithm for picking the "interesting" process is thus: 1986 * 1987 * 1) Only foreground processes are eligible - implied. 1988 * 2) Runnable processes are favored over anything else. The runner 1989 * with the highest cpu utilization is picked (p_estcpu). Ties are 1990 * broken by picking the highest pid. 1991 * 3) The sleeper with the shortest sleep time is next. With ties, 1992 * we pick out just "short-term" sleepers (P_SINTR == 0). 1993 * 4) Further ties are broken by picking the highest pid. 1994 */ 1995#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL)) 1996#define TESTAB(a, b) ((a)<<1 | (b)) 1997#define ONLYA 2 1998#define ONLYB 1 1999#define BOTH 3 2000 2001static int 2002proc_compare(p1, p2) 2003 register struct proc *p1, *p2; 2004{ 2005 2006 if (p1 == NULL) 2007 return (1); 2008 /* 2009 * see if at least one of them is runnable 2010 */ 2011 switch (TESTAB(ISRUN(p1), ISRUN(p2))) { 2012 case ONLYA: 2013 return (0); 2014 case ONLYB: 2015 return (1); 2016 case BOTH: 2017 /* 2018 * tie - favor one with highest recent cpu utilization 2019 */ 2020 if (p2->p_estcpu > p1->p_estcpu) 2021 return (1); 2022 if (p1->p_estcpu > p2->p_estcpu) 2023 return (0); 2024 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2025 } 2026 /* 2027 * weed out zombies 2028 */ 2029 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) { 2030 case ONLYA: 2031 return (1); 2032 case ONLYB: 2033 return (0); 2034 case BOTH: 2035 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2036 } 2037 /* 2038 * pick the one with the smallest sleep time 2039 */ 2040 if (p2->p_slptime > p1->p_slptime) 2041 return (0); 2042 if (p1->p_slptime > p2->p_slptime) 2043 return (1); 2044 /* 2045 * favor one sleeping in a non-interruptible sleep 2046 */ 2047 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0) 2048 return (1); 2049 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0) 2050 return (0); 2051 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2052} 2053 2054/* 2055 * Output char to tty; console putchar style. 2056 */ 2057int 2058tputchar(c, tp) 2059 int c; 2060 struct tty *tp; 2061{ 2062 register int s; 2063 2064 s = spltty(); 2065 if (ISSET(tp->t_state, 2066 TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) { 2067 splx(s); 2068 return (-1); 2069 } 2070 if (c == '\n') 2071 (void)ttyoutput('\r', tp); 2072 (void)ttyoutput(c, tp); 2073 ttstart(tp); 2074 splx(s); 2075 return (0); 2076} 2077 2078/* 2079 * Sleep on chan, returning ERESTART if tty changed while we napped and 2080 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If 2081 * the tty is revoked, restarting a pending call will redo validation done 2082 * at the start of the call. 2083 */ 2084int 2085ttysleep(tp, chan, pri, wmesg, timo) 2086 struct tty *tp; 2087 void *chan; 2088 int pri, timo; 2089 char *wmesg; 2090{ 2091 int error; 2092 short gen; 2093 2094 gen = tp->t_gen; 2095 error = tsleep(chan, pri, wmesg, timo); 2096 if (error) 2097 return (error); 2098 return (tp->t_gen == gen ? 0 : ERESTART); 2099} 2100