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