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