tty.c revision 59052
1249997Swkoszek/*- 2250015Swkoszek * Copyright (c) 1982, 1986, 1990, 1991, 1993 3249997Swkoszek * The Regents of the University of California. All rights reserved. 4250015Swkoszek * (c) UNIX System Laboratories, Inc. 5249997Swkoszek * All or some portions of this file are derived from material licensed 6250015Swkoszek * to the University of California by American Telephone and Telegraph 7250015Swkoszek * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8250015Swkoszek * the permission of UNIX System Laboratories, Inc. 9250015Swkoszek * 10250015Swkoszek * Redistribution and use in source and binary forms, with or without 11250015Swkoszek * modification, are permitted provided that the following conditions 12250015Swkoszek * are met: 13250015Swkoszek * 1. Redistributions of source code must retain the above copyright 14250015Swkoszek * notice, this list of conditions and the following disclaimer. 15250015Swkoszek * 2. Redistributions in binary form must reproduce the above copyright 16249997Swkoszek * notice, this list of conditions and the following disclaimer in the 17250015Swkoszek * documentation and/or other materials provided with the distribution. 18250015Swkoszek * 3. All advertising materials mentioning features or use of this software 19250015Swkoszek * must display the following acknowledgement: 20250015Swkoszek * This product includes software developed by the University of 21250015Swkoszek * California, Berkeley and its contributors. 22249997Swkoszek * 4. Neither the name of the University nor the names of its contributors 23250015Swkoszek * may be used to endorse or promote products derived from this software 24250015Swkoszek * without specific prior written permission. 25249997Swkoszek * 26250015Swkoszek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27249997Swkoszek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28249997Swkoszek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29250015Swkoszek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30250015Swkoszek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31249997Swkoszek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32249997Swkoszek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33249997Swkoszek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34249997Swkoszek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35249997Swkoszek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36249997Swkoszek * SUCH DAMAGE. 37249997Swkoszek * 38249997Swkoszek * @(#)tty.c 8.8 (Berkeley) 1/21/94 39249997Swkoszek * $FreeBSD: head/sys/kern/tty.c 59052 2000-04-05 18:38:21Z archie $ 40249997Swkoszek */ 41249997Swkoszek 42249997Swkoszek/*- 43249997Swkoszek * TODO: 44249997Swkoszek * o Fix races for sending the start char in ttyflush(). 45249997Swkoszek * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect(). 46249997Swkoszek * With luck, there will be MIN chars before select() returns(). 47249997Swkoszek * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it. 48249997Swkoszek * o Don't allow input in TS_ZOMBIE case. It would be visible through 49249997Swkoszek * FIONREAD. 50249997Swkoszek * o Do the new sio locking stuff here and use it to avoid special 51249997Swkoszek * case for EXTPROC? 52249997Swkoszek * o Lock PENDIN too? 53249997Swkoszek * o Move EXTPROC and/or PENDIN to t_state? 54249997Swkoszek * o Wrap most of ttioctl in spltty/splx. 55249997Swkoszek * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>. 56249997Swkoszek * o Send STOP if IXOFF is toggled off while TS_TBLOCK is set. 57249997Swkoszek * o Don't allow certain termios flags to affect disciplines other 58249997Swkoszek * than TTYDISC. Cancel their effects before switch disciplines 59249997Swkoszek * and ignore them if they are set while we are in another 60249997Swkoszek * discipline. 61249997Swkoszek * o Now that historical speed conversions are handled here, don't 62249997Swkoszek * do them in drivers. 63249997Swkoszek * o Check for TS_CARR_ON being set while everything is closed and not 64249997Swkoszek * waiting for carrier. TS_CARR_ON isn't cleared if nothing is open, 65249997Swkoszek * so it would live until the next open even if carrier drops. 66249997Swkoszek * o Restore TS_WOPEN since it is useful in pstat. It must be cleared 67249997Swkoszek * only when _all_ openers leave open(). 68249997Swkoszek */ 69249997Swkoszek 70249997Swkoszek#include "snp.h" 71249997Swkoszek#include "opt_compat.h" 72249997Swkoszek#include "opt_uconsole.h" 73249997Swkoszek 74249997Swkoszek#include <sys/param.h> 75249997Swkoszek#include <sys/systm.h> 76249997Swkoszek#include <sys/filio.h> 77249997Swkoszek#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 78249997Swkoszek#include <sys/ioctl_compat.h> 79249997Swkoszek#endif 80249997Swkoszek#include <sys/proc.h> 81249997Swkoszek#define TTYDEFCHARS 82249997Swkoszek#include <sys/tty.h> 83249997Swkoszek#undef TTYDEFCHARS 84249997Swkoszek#include <sys/fcntl.h> 85249997Swkoszek#include <sys/conf.h> 86249997Swkoszek#include <sys/dkstat.h> 87249997Swkoszek#include <sys/poll.h> 88249997Swkoszek#include <sys/kernel.h> 89249997Swkoszek#include <sys/vnode.h> 90249997Swkoszek#include <sys/signalvar.h> 91249997Swkoszek#include <sys/resourcevar.h> 92249997Swkoszek#include <sys/malloc.h> 93249997Swkoszek#include <sys/filedesc.h> 94249997Swkoszek#if NSNP > 0 95249997Swkoszek#include <sys/snoop.h> 96249997Swkoszek#endif 97249997Swkoszek#include <sys/sysctl.h> 98249997Swkoszek 99249997Swkoszek#include <vm/vm.h> 100249997Swkoszek#include <sys/lock.h> 101249997Swkoszek#include <vm/pmap.h> 102249997Swkoszek#include <vm/vm_map.h> 103249997Swkoszek 104249997SwkoszekMALLOC_DEFINE(M_TTYS, "ttys", "tty data structures"); 105249997Swkoszek 106249997Swkoszekstatic int proc_compare __P((struct proc *p1, struct proc *p2)); 107249997Swkoszekstatic int ttnread __P((struct tty *tp)); 108249997Swkoszekstatic void ttyecho __P((int c, struct tty *tp)); 109249997Swkoszekstatic int ttyoutput __P((int c, register struct tty *tp)); 110249997Swkoszekstatic void ttypend __P((struct tty *tp)); 111249997Swkoszekstatic void ttyretype __P((struct tty *tp)); 112249997Swkoszekstatic void ttyrub __P((int c, struct tty *tp)); 113249997Swkoszekstatic void ttyrubo __P((struct tty *tp, int cnt)); 114249997Swkoszekstatic void ttyunblock __P((struct tty *tp)); 115249997Swkoszekstatic int ttywflush __P((struct tty *tp)); 116249997Swkoszek 117249997Swkoszek/* 118249997Swkoszek * Table with character classes and parity. The 8th bit indicates parity, 119249997Swkoszek * the 7th bit indicates the character is an alphameric or underscore (for 120249997Swkoszek * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits 121249997Swkoszek * are 0 then the character needs no special processing on output; classes 122249997Swkoszek * other than 0 might be translated or (not currently) require delays. 123249997Swkoszek */ 124249997Swkoszek#define E 0x00 /* Even parity. */ 125249997Swkoszek#define O 0x80 /* Odd parity. */ 126249997Swkoszek#define PARITY(c) (char_type[c] & O) 127249997Swkoszek 128249997Swkoszek#define ALPHA 0x40 /* Alpha or underscore. */ 129249997Swkoszek#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA) 130249997Swkoszek 131249997Swkoszek#define CCLASSMASK 0x3f 132249997Swkoszek#define CCLASS(c) (char_type[c] & CCLASSMASK) 133249997Swkoszek 134249997Swkoszek#define BS BACKSPACE 135249997Swkoszek#define CC CONTROL 136249997Swkoszek#define CR RETURN 137249997Swkoszek#define NA ORDINARY | ALPHA 138249997Swkoszek#define NL NEWLINE 139249997Swkoszek#define NO ORDINARY 140249997Swkoszek#define TB TAB 141249997Swkoszek#define VT VTAB 142249997Swkoszek 143249997Swkoszekstatic u_char const char_type[] = { 144249997Swkoszek E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */ 145249997Swkoszek O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */ 146249997Swkoszek O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */ 147249997Swkoszek E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */ 148249997Swkoszek O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */ 149249997Swkoszek E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */ 150249997Swkoszek E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */ 151249997Swkoszek O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */ 152249997Swkoszek O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */ 153249997Swkoszek E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */ 154249997Swkoszek E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */ 155249997Swkoszek O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */ 156249997Swkoszek E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */ 157249997Swkoszek O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */ 158249997Swkoszek O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */ 159249997Swkoszek E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */ 160249997Swkoszek /* 161249997Swkoszek * Meta chars; should be settable per character set; 162249997Swkoszek * for now, treat them all as normal characters. 163249997Swkoszek */ 164249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 165249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 166249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 167249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 168249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 169249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 170249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 171249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 172249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 173249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 174249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 175249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 176249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 177249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 178249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 179249997Swkoszek NA, NA, NA, NA, NA, NA, NA, NA, 180249997Swkoszek}; 181249997Swkoszek#undef BS 182249997Swkoszek#undef CC 183249997Swkoszek#undef CR 184249997Swkoszek#undef NA 185249997Swkoszek#undef NL 186249997Swkoszek#undef NO 187249997Swkoszek#undef TB 188249997Swkoszek#undef VT 189249997Swkoszek 190249997Swkoszek/* Macros to clear/set/test flags. */ 191249997Swkoszek#define SET(t, f) (t) |= (f) 192249997Swkoszek#define CLR(t, f) (t) &= ~(f) 193249997Swkoszek#define ISSET(t, f) ((t) & (f)) 194249997Swkoszek 195249997Swkoszek#undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */ 196249997Swkoszek#define MAX_INPUT TTYHOG /* XXX limit is usually larger for !ICANON */ 197249997Swkoszek 198249997Swkoszek/* 199249997Swkoszek * list of struct tty where pstat(8) can pick it up with sysctl 200249997Swkoszek */ 201249997Swkoszekstatic SLIST_HEAD(, tty) tty_list; 202249997Swkoszek 203249997Swkoszek/* 204249997Swkoszek * Initial open of tty, or (re)entry to standard tty line discipline. 205249997Swkoszek */ 206249997Swkoszekint 207249997Swkoszekttyopen(device, tp) 208249997Swkoszek dev_t device; 209249997Swkoszek register struct tty *tp; 210249997Swkoszek{ 211249997Swkoszek int s; 212249997Swkoszek 213249997Swkoszek s = spltty(); 214249997Swkoszek tp->t_dev = device; 215249997Swkoszek if (!ISSET(tp->t_state, TS_ISOPEN)) { 216249997Swkoszek SET(tp->t_state, TS_ISOPEN); 217249997Swkoszek if (ISSET(tp->t_cflag, CLOCAL)) 218249997Swkoszek SET(tp->t_state, TS_CONNECTED); 219249997Swkoszek bzero(&tp->t_winsize, sizeof(tp->t_winsize)); 220249997Swkoszek } 221249997Swkoszek ttsetwater(tp); 222249997Swkoszek splx(s); 223249997Swkoszek return (0); 224249997Swkoszek} 225249997Swkoszek 226249997Swkoszek/* 227249997Swkoszek * Handle close() on a tty line: flush and set to initial state, 228249997Swkoszek * bumping generation number so that pending read/write calls 229249997Swkoszek * can detect recycling of the tty. 230249997Swkoszek * XXX our caller should have done `spltty(); l_close(); ttyclose();' 231249997Swkoszek * and l_close() should have flushed, but we repeat the spltty() and 232249997Swkoszek * the flush in case there are buggy callers. 233249997Swkoszek */ 234249997Swkoszekint 235249997Swkoszekttyclose(tp) 236249997Swkoszek register struct tty *tp; 237249997Swkoszek{ 238249997Swkoszek int s; 239249997Swkoszek 240249997Swkoszek funsetown(tp->t_sigio); 241249997Swkoszek s = spltty(); 242249997Swkoszek if (constty == tp) 243249997Swkoszek constty = NULL; 244249997Swkoszek 245249997Swkoszek ttyflush(tp, FREAD | FWRITE); 246249997Swkoszek clist_free_cblocks(&tp->t_canq); 247249997Swkoszek clist_free_cblocks(&tp->t_outq); 248249997Swkoszek clist_free_cblocks(&tp->t_rawq); 249249997Swkoszek 250249997Swkoszek#if NSNP > 0 251249997Swkoszek if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 252249997Swkoszek snpdown((struct snoop *)tp->t_sc); 253249997Swkoszek#endif 254249997Swkoszek 255249997Swkoszek tp->t_gen++; 256249997Swkoszek tp->t_line = TTYDISC; 257249997Swkoszek tp->t_pgrp = NULL; 258249997Swkoszek tp->t_session = NULL; 259249997Swkoszek tp->t_state = 0; 260249997Swkoszek splx(s); 261249997Swkoszek return (0); 262249997Swkoszek} 263249997Swkoszek 264249997Swkoszek#define FLUSHQ(q) { \ 265249997Swkoszek if ((q)->c_cc) \ 266249997Swkoszek ndflush(q, (q)->c_cc); \ 267249997Swkoszek} 268249997Swkoszek 269249997Swkoszek/* Is 'c' a line delimiter ("break" character)? */ 270265690Sian#define TTBREAKC(c, lflag) \ 271265690Sian ((c) == '\n' || (((c) == cc[VEOF] || \ 272265690Sian (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \ 273265690Sian (c) != _POSIX_VDISABLE)) 274249997Swkoszek 275249997Swkoszek/* 276249997Swkoszek * Process input of a single character received on a tty. 277249997Swkoszek */ 278265690Sianint 279265690Sianttyinput(c, tp) 280265690Sian register int c; 281265690Sian register struct tty *tp; 282265690Sian{ 283265690Sian register tcflag_t iflag, lflag; 284265690Sian register cc_t *cc; 285265690Sian int i, err; 286249997Swkoszek 287265690Sian /* 288265690Sian * If input is pending take it first. 289265690Sian */ 290265690Sian lflag = tp->t_lflag; 291265690Sian if (ISSET(lflag, PENDIN)) 292265690Sian ttypend(tp); 293265690Sian /* 294265690Sian * Gather stats. 295249997Swkoszek */ 296249997Swkoszek if (ISSET(lflag, ICANON)) { 297249997Swkoszek ++tk_cancc; 298265690Sian ++tp->t_cancc; 299249997Swkoszek } else { 300249997Swkoszek ++tk_rawcc; 301249997Swkoszek ++tp->t_rawcc; 302249997Swkoszek } 303249997Swkoszek ++tk_nin; 304249997Swkoszek 305249997Swkoszek /* 306249997Swkoszek * Block further input iff: 307265690Sian * current input > threshold AND input is available to user program 308249997Swkoszek * AND input flow control is enabled and not yet invoked. 309249997Swkoszek * The 3 is slop for PARMRK. 310249997Swkoszek */ 311249997Swkoszek iflag = tp->t_iflag; 312249997Swkoszek if (tp->t_rawq.c_cc + tp->t_canq.c_cc > tp->t_ihiwat - 3 && 313249997Swkoszek (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) && 314249997Swkoszek (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) && 315265690Sian !ISSET(tp->t_state, TS_TBLOCK)) 316265690Sian ttyblock(tp); 317265690Sian 318249997Swkoszek /* Handle exceptional conditions (break, parity, framing). */ 319265690Sian cc = tp->t_cc; 320249997Swkoszek err = (ISSET(c, TTY_ERRORMASK)); 321249997Swkoszek if (err) { 322249997Swkoszek CLR(c, TTY_ERRORMASK); 323249997Swkoszek if (ISSET(err, TTY_BI)) { 324249997Swkoszek if (ISSET(iflag, IGNBRK)) 325249997Swkoszek return (0); 326249997Swkoszek if (ISSET(iflag, BRKINT)) { 327249997Swkoszek ttyflush(tp, FREAD | FWRITE); 328249997Swkoszek pgsignal(tp->t_pgrp, SIGINT, 1); 329249997Swkoszek goto endcase; 330249997Swkoszek } 331249997Swkoszek if (ISSET(iflag, PARMRK)) 332249997Swkoszek goto parmrk; 333249997Swkoszek } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK)) 334249997Swkoszek || ISSET(err, TTY_FE)) { 335249997Swkoszek if (ISSET(iflag, IGNPAR)) 336249997Swkoszek return (0); 337249997Swkoszek else if (ISSET(iflag, PARMRK)) { 338249997Swkoszekparmrk: 339249997Swkoszek if (tp->t_rawq.c_cc + tp->t_canq.c_cc > 340249997Swkoszek MAX_INPUT - 3) 341249997Swkoszek goto input_overflow; 342249997Swkoszek (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); 343249997Swkoszek (void)putc(0 | TTY_QUOTE, &tp->t_rawq); 344249997Swkoszek (void)putc(c | TTY_QUOTE, &tp->t_rawq); 345249997Swkoszek goto endcase; 346249997Swkoszek } else 347249997Swkoszek c = 0; 348249997Swkoszek } 349249997Swkoszek } 350249997Swkoszek 351249997Swkoszek if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP)) 352249997Swkoszek CLR(c, 0x80); 353249997Swkoszek if (!ISSET(lflag, EXTPROC)) { 354249997Swkoszek /* 355249997Swkoszek * Check for literal nexting very first 356249997Swkoszek */ 357249997Swkoszek if (ISSET(tp->t_state, TS_LNCH)) { 358249997Swkoszek SET(c, TTY_QUOTE); 359249997Swkoszek CLR(tp->t_state, TS_LNCH); 360249997Swkoszek } 361249997Swkoszek /* 362249997Swkoszek * Scan for special characters. This code 363249997Swkoszek * is really just a big case statement with 364249997Swkoszek * non-constant cases. The bottom of the 365249997Swkoszek * case statement is labeled ``endcase'', so goto 366249997Swkoszek * it after a case match, or similar. 367249997Swkoszek */ 368249997Swkoszek 369249997Swkoszek /* 370249997Swkoszek * Control chars which aren't controlled 371249997Swkoszek * by ICANON, ISIG, or IXON. 372249997Swkoszek */ 373249997Swkoszek if (ISSET(lflag, IEXTEN)) { 374249997Swkoszek if (CCEQ(cc[VLNEXT], c)) { 375249997Swkoszek if (ISSET(lflag, ECHO)) { 376249997Swkoszek if (ISSET(lflag, ECHOE)) { 377249997Swkoszek (void)ttyoutput('^', tp); 378249997Swkoszek (void)ttyoutput('\b', tp); 379249997Swkoszek } else 380249997Swkoszek ttyecho(c, tp); 381249997Swkoszek } 382249997Swkoszek SET(tp->t_state, TS_LNCH); 383249997Swkoszek goto endcase; 384249997Swkoszek } 385249997Swkoszek if (CCEQ(cc[VDISCARD], c)) { 386249997Swkoszek if (ISSET(lflag, FLUSHO)) 387249997Swkoszek CLR(tp->t_lflag, FLUSHO); 388249997Swkoszek else { 389249997Swkoszek ttyflush(tp, FWRITE); 390249997Swkoszek ttyecho(c, tp); 391249997Swkoszek if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 392249997Swkoszek ttyretype(tp); 393249997Swkoszek SET(tp->t_lflag, FLUSHO); 394249997Swkoszek } 395249997Swkoszek goto startoutput; 396249997Swkoszek } 397249997Swkoszek } 398249997Swkoszek /* 399249997Swkoszek * Signals. 400249997Swkoszek */ 401249997Swkoszek if (ISSET(lflag, ISIG)) { 402249997Swkoszek if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 403249997Swkoszek if (!ISSET(lflag, NOFLSH)) 404249997Swkoszek ttyflush(tp, FREAD | FWRITE); 405249997Swkoszek ttyecho(c, tp); 406249997Swkoszek pgsignal(tp->t_pgrp, 407249997Swkoszek CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 408249997Swkoszek goto endcase; 409249997Swkoszek } 410249997Swkoszek if (CCEQ(cc[VSUSP], c)) { 411249997Swkoszek if (!ISSET(lflag, NOFLSH)) 412249997Swkoszek ttyflush(tp, FREAD); 413249997Swkoszek ttyecho(c, tp); 414249997Swkoszek pgsignal(tp->t_pgrp, SIGTSTP, 1); 415249997Swkoszek goto endcase; 416249997Swkoszek } 417249997Swkoszek } 418265690Sian /* 419249997Swkoszek * Handle start/stop characters. 420265690Sian */ 421249997Swkoszek if (ISSET(iflag, IXON)) { 422249997Swkoszek if (CCEQ(cc[VSTOP], c)) { 423249997Swkoszek if (!ISSET(tp->t_state, TS_TTSTOP)) { 424249997Swkoszek SET(tp->t_state, TS_TTSTOP); 425249997Swkoszek (*tp->t_stop)(tp, 0); 426249997Swkoszek return (0); 427249997Swkoszek } 428249997Swkoszek if (!CCEQ(cc[VSTART], c)) 429249997Swkoszek return (0); 430249997Swkoszek /* 431249997Swkoszek * if VSTART == VSTOP then toggle 432249997Swkoszek */ 433249997Swkoszek goto endcase; 434249997Swkoszek } 435249997Swkoszek if (CCEQ(cc[VSTART], c)) 436249997Swkoszek goto restartoutput; 437249997Swkoszek } 438249997Swkoszek /* 439249997Swkoszek * IGNCR, ICRNL, & INLCR 440249997Swkoszek */ 441249997Swkoszek if (c == '\r') { 442249997Swkoszek if (ISSET(iflag, IGNCR)) 443249997Swkoszek return (0); 444249997Swkoszek else if (ISSET(iflag, ICRNL)) 445249997Swkoszek c = '\n'; 446249997Swkoszek } else if (c == '\n' && ISSET(iflag, INLCR)) 447249997Swkoszek c = '\r'; 448249997Swkoszek } 449249997Swkoszek if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) { 450249997Swkoszek /* 451249997Swkoszek * From here on down canonical mode character 452249997Swkoszek * processing takes place. 453249997Swkoszek */ 454249997Swkoszek /* 455249997Swkoszek * erase (^H / ^?) 456249997Swkoszek */ 457249997Swkoszek if (CCEQ(cc[VERASE], c)) { 458249997Swkoszek if (tp->t_rawq.c_cc) 459249997Swkoszek ttyrub(unputc(&tp->t_rawq), tp); 460249997Swkoszek goto endcase; 461249997Swkoszek } 462249997Swkoszek /* 463249997Swkoszek * kill (^U) 464249997Swkoszek */ 465249997Swkoszek if (CCEQ(cc[VKILL], c)) { 466249997Swkoszek if (ISSET(lflag, ECHOKE) && 467249997Swkoszek tp->t_rawq.c_cc == tp->t_rocount && 468249997Swkoszek !ISSET(lflag, ECHOPRT)) 469249997Swkoszek while (tp->t_rawq.c_cc) 470249997Swkoszek ttyrub(unputc(&tp->t_rawq), tp); 471249997Swkoszek else { 472249997Swkoszek ttyecho(c, tp); 473249997Swkoszek if (ISSET(lflag, ECHOK) || 474249997Swkoszek ISSET(lflag, ECHOKE)) 475249997Swkoszek ttyecho('\n', tp); 476249997Swkoszek FLUSHQ(&tp->t_rawq); 477249997Swkoszek tp->t_rocount = 0; 478249997Swkoszek } 479249997Swkoszek CLR(tp->t_state, TS_LOCAL); 480249997Swkoszek goto endcase; 481249997Swkoszek } 482249997Swkoszek /* 483249997Swkoszek * word erase (^W) 484249997Swkoszek */ 485249997Swkoszek if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) { 486249997Swkoszek int ctype; 487249997Swkoszek 488249997Swkoszek /* 489249997Swkoszek * erase whitespace 490249997Swkoszek */ 491249997Swkoszek while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 492249997Swkoszek ttyrub(c, tp); 493249997Swkoszek if (c == -1) 494249997Swkoszek goto endcase; 495249997Swkoszek /* 496249997Swkoszek * erase last char of word and remember the 497249997Swkoszek * next chars type (for ALTWERASE) 498249997Swkoszek */ 499249997Swkoszek ttyrub(c, tp); 500249997Swkoszek c = unputc(&tp->t_rawq); 501249997Swkoszek if (c == -1) 502249997Swkoszek goto endcase; 503249997Swkoszek if (c == ' ' || c == '\t') { 504249997Swkoszek (void)putc(c, &tp->t_rawq); 505249997Swkoszek goto endcase; 506249997Swkoszek } 507249997Swkoszek ctype = ISALPHA(c); 508249997Swkoszek /* 509249997Swkoszek * erase rest of word 510249997Swkoszek */ 511249997Swkoszek do { 512249997Swkoszek ttyrub(c, tp); 513249997Swkoszek c = unputc(&tp->t_rawq); 514249997Swkoszek if (c == -1) 515249997Swkoszek goto endcase; 516249997Swkoszek } while (c != ' ' && c != '\t' && 517249997Swkoszek (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype)); 518249997Swkoszek (void)putc(c, &tp->t_rawq); 519249997Swkoszek goto endcase; 520249997Swkoszek } 521249997Swkoszek /* 522249997Swkoszek * reprint line (^R) 523249997Swkoszek */ 524249997Swkoszek if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) { 525249997Swkoszek ttyretype(tp); 526249997Swkoszek goto endcase; 527249997Swkoszek } 528249997Swkoszek /* 529249997Swkoszek * ^T - kernel info and generate SIGINFO 530249997Swkoszek */ 531249997Swkoszek if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) { 532249997Swkoszek if (ISSET(lflag, ISIG)) 533249997Swkoszek pgsignal(tp->t_pgrp, SIGINFO, 1); 534249997Swkoszek if (!ISSET(lflag, NOKERNINFO)) 535261410Sian ttyinfo(tp); 536261410Sian goto endcase; 537261410Sian } 538261410Sian } 539249997Swkoszek /* 540249997Swkoszek * Check for input buffer overflow 541249997Swkoszek */ 542249997Swkoszek if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) { 543249997Swkoszekinput_overflow: 544249997Swkoszek if (ISSET(iflag, IMAXBEL)) { 545249997Swkoszek if (tp->t_outq.c_cc < tp->t_ohiwat) 546249997Swkoszek (void)ttyoutput(CTRL('g'), tp); 547249997Swkoszek } 548249997Swkoszek goto endcase; 549249997Swkoszek } 550249997Swkoszek 551249997Swkoszek if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP) 552249997Swkoszek && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR)) 553249997Swkoszek (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); 554249997Swkoszek 555249997Swkoszek /* 556249997Swkoszek * Put data char in q for user and 557249997Swkoszek * wakeup on seeing a line delimiter. 558249997Swkoszek */ 559249997Swkoszek if (putc(c, &tp->t_rawq) >= 0) { 560249997Swkoszek if (!ISSET(lflag, ICANON)) { 561249997Swkoszek ttwakeup(tp); 562249997Swkoszek ttyecho(c, tp); 563249997Swkoszek goto endcase; 564249997Swkoszek } 565249997Swkoszek if (TTBREAKC(c, lflag)) { 566249997Swkoszek tp->t_rocount = 0; 567249997Swkoszek catq(&tp->t_rawq, &tp->t_canq); 568249997Swkoszek ttwakeup(tp); 569249997Swkoszek } else if (tp->t_rocount++ == 0) 570249997Swkoszek tp->t_rocol = tp->t_column; 571249997Swkoszek if (ISSET(tp->t_state, TS_ERASE)) { 572249997Swkoszek /* 573249997Swkoszek * end of prterase \.../ 574249997Swkoszek */ 575249997Swkoszek CLR(tp->t_state, TS_ERASE); 576249997Swkoszek (void)ttyoutput('/', tp); 577249997Swkoszek } 578249997Swkoszek i = tp->t_column; 579249997Swkoszek ttyecho(c, tp); 580249997Swkoszek if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) { 581249997Swkoszek /* 582249997Swkoszek * Place the cursor over the '^' of the ^D. 583249997Swkoszek */ 584249997Swkoszek i = imin(2, tp->t_column - i); 585249997Swkoszek while (i > 0) { 586249997Swkoszek (void)ttyoutput('\b', tp); 587249997Swkoszek i--; 588249997Swkoszek } 589249997Swkoszek } 590249997Swkoszek } 591249997Swkoszekendcase: 592249997Swkoszek /* 593249997Swkoszek * IXANY means allow any character to restart output. 594249997Swkoszek */ 595249997Swkoszek if (ISSET(tp->t_state, TS_TTSTOP) && 596249997Swkoszek !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) 597249997Swkoszek return (0); 598249997Swkoszekrestartoutput: 599249997Swkoszek CLR(tp->t_lflag, FLUSHO); 600249997Swkoszek CLR(tp->t_state, TS_TTSTOP); 601249997Swkoszekstartoutput: 602249997Swkoszek return (ttstart(tp)); 603249997Swkoszek} 604249997Swkoszek 605249997Swkoszek/* 606249997Swkoszek * Output a single character on a tty, doing output processing 607249997Swkoszek * as needed (expanding tabs, newline processing, etc.). 608249997Swkoszek * Returns < 0 if succeeds, otherwise returns char to resend. 609249997Swkoszek * Must be recursive. 610249997Swkoszek */ 611249997Swkoszekstatic int 612249997Swkoszekttyoutput(c, tp) 613249997Swkoszek register int c; 614249997Swkoszek register struct tty *tp; 615249997Swkoszek{ 616249997Swkoszek register tcflag_t oflag; 617249997Swkoszek register int col, s; 618249997Swkoszek 619249997Swkoszek oflag = tp->t_oflag; 620249997Swkoszek if (!ISSET(oflag, OPOST)) { 621249997Swkoszek if (ISSET(tp->t_lflag, FLUSHO)) 622249997Swkoszek return (-1); 623249997Swkoszek if (putc(c, &tp->t_outq)) 624249997Swkoszek return (c); 625249997Swkoszek tk_nout++; 626249997Swkoszek tp->t_outcc++; 627249997Swkoszek return (-1); 628249997Swkoszek } 629249997Swkoszek /* 630249997Swkoszek * Do tab expansion if OXTABS is set. Special case if we external 631249997Swkoszek * processing, we don't do the tab expansion because we'll probably 632249997Swkoszek * get it wrong. If tab expansion needs to be done, let it happen 633249997Swkoszek * externally. 634249997Swkoszek */ 635249997Swkoszek CLR(c, ~TTY_CHARMASK); 636249997Swkoszek if (c == '\t' && 637249997Swkoszek ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) { 638249997Swkoszek c = 8 - (tp->t_column & 7); 639249997Swkoszek if (!ISSET(tp->t_lflag, FLUSHO)) { 640249997Swkoszek s = spltty(); /* Don't interrupt tabs. */ 641249997Swkoszek c -= b_to_q(" ", c, &tp->t_outq); 642249997Swkoszek tk_nout += c; 643249997Swkoszek tp->t_outcc += c; 644249997Swkoszek splx(s); 645249997Swkoszek } 646249997Swkoszek tp->t_column += c; 647249997Swkoszek return (c ? -1 : '\t'); 648249997Swkoszek } 649249997Swkoszek if (c == CEOT && ISSET(oflag, ONOEOT)) 650249997Swkoszek return (-1); 651249997Swkoszek 652249997Swkoszek /* 653249997Swkoszek * Newline translation: if ONLCR is set, 654249997Swkoszek * translate newline into "\r\n". 655249997Swkoszek */ 656249997Swkoszek if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) { 657249997Swkoszek tk_nout++; 658249997Swkoszek tp->t_outcc++; 659249997Swkoszek if (putc('\r', &tp->t_outq)) 660249997Swkoszek return (c); 661249997Swkoszek } 662249997Swkoszek tk_nout++; 663249997Swkoszek tp->t_outcc++; 664249997Swkoszek if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq)) 665249997Swkoszek return (c); 666249997Swkoszek 667249997Swkoszek col = tp->t_column; 668249997Swkoszek switch (CCLASS(c)) { 669 case BACKSPACE: 670 if (col > 0) 671 --col; 672 break; 673 case CONTROL: 674 break; 675 case NEWLINE: 676 case RETURN: 677 col = 0; 678 break; 679 case ORDINARY: 680 ++col; 681 break; 682 case TAB: 683 col = (col + 8) & ~7; 684 break; 685 } 686 tp->t_column = col; 687 return (-1); 688} 689 690/* 691 * Ioctls for all tty devices. Called after line-discipline specific ioctl 692 * has been called to do discipline-specific functions and/or reject any 693 * of these ioctl commands. 694 */ 695/* ARGSUSED */ 696int 697ttioctl(tp, cmd, data, flag) 698 register struct tty *tp; 699 u_long cmd; 700 int flag; 701 void *data; 702{ 703 register struct proc *p; 704 int s, error; 705 706 p = curproc; /* XXX */ 707 708 /* If the ioctl involves modification, hang if in the background. */ 709 switch (cmd) { 710 case TIOCCBRK: 711 case TIOCCONS: 712 case TIOCDRAIN: 713 case TIOCEXCL: 714 case TIOCFLUSH: 715#ifdef TIOCHPCL 716 case TIOCHPCL: 717#endif 718 case TIOCNXCL: 719 case TIOCSBRK: 720 case TIOCSCTTY: 721 case TIOCSDRAINWAIT: 722 case TIOCSETA: 723 case TIOCSETAF: 724 case TIOCSETAW: 725 case TIOCSETD: 726 case TIOCSPGRP: 727 case TIOCSTART: 728 case TIOCSTAT: 729 case TIOCSTI: 730 case TIOCSTOP: 731 case TIOCSWINSZ: 732#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 733 case TIOCLBIC: 734 case TIOCLBIS: 735 case TIOCLSET: 736 case TIOCSETC: 737 case OTIOCSETD: 738 case TIOCSETN: 739 case TIOCSETP: 740 case TIOCSLTC: 741#endif 742 while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) && 743 !SIGISMEMBER(p->p_sigignore, SIGTTOU) && 744 !SIGISMEMBER(p->p_sigmask, SIGTTOU)) { 745 if (p->p_pgrp->pg_jobc == 0) 746 return (EIO); 747 pgsignal(p->p_pgrp, SIGTTOU, 1); 748 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1", 749 0); 750 if (error) 751 return (error); 752 } 753 break; 754 } 755 756 switch (cmd) { /* Process the ioctl. */ 757 case FIOASYNC: /* set/clear async i/o */ 758 s = spltty(); 759 if (*(int *)data) 760 SET(tp->t_state, TS_ASYNC); 761 else 762 CLR(tp->t_state, TS_ASYNC); 763 splx(s); 764 break; 765 case FIONBIO: /* set/clear non-blocking i/o */ 766 break; /* XXX: delete. */ 767 case FIONREAD: /* get # bytes to read */ 768 s = spltty(); 769 *(int *)data = ttnread(tp); 770 splx(s); 771 break; 772 773 case FIOSETOWN: 774 /* 775 * Policy -- Don't allow FIOSETOWN on someone else's 776 * controlling tty 777 */ 778 if (tp->t_session != NULL && !isctty(p, tp)) 779 return (ENOTTY); 780 781 error = fsetown(*(int *)data, &tp->t_sigio); 782 if (error) 783 return (error); 784 break; 785 case FIOGETOWN: 786 if (tp->t_session != NULL && !isctty(p, tp)) 787 return (ENOTTY); 788 *(int *)data = fgetown(tp->t_sigio); 789 break; 790 791 case TIOCEXCL: /* set exclusive use of tty */ 792 s = spltty(); 793 SET(tp->t_state, TS_XCLUDE); 794 splx(s); 795 break; 796 case TIOCFLUSH: { /* flush buffers */ 797 register int flags = *(int *)data; 798 799 if (flags == 0) 800 flags = FREAD | FWRITE; 801 else 802 flags &= FREAD | FWRITE; 803 ttyflush(tp, flags); 804 break; 805 } 806 case TIOCCONS: /* become virtual console */ 807 if (*(int *)data) { 808 if (constty && constty != tp && 809 ISSET(constty->t_state, TS_CONNECTED)) 810 return (EBUSY); 811#ifndef UCONSOLE 812 if ((error = suser(p)) != 0) 813 return (error); 814#endif 815 constty = tp; 816 } else if (tp == constty) 817 constty = NULL; 818 break; 819 case TIOCDRAIN: /* wait till output drained */ 820 error = ttywait(tp); 821 if (error) 822 return (error); 823 break; 824 case TIOCGETA: { /* get termios struct */ 825 struct termios *t = (struct termios *)data; 826 827 bcopy(&tp->t_termios, t, sizeof(struct termios)); 828 break; 829 } 830 case TIOCGETD: /* get line discipline */ 831 *(int *)data = tp->t_line; 832 break; 833 case TIOCGWINSZ: /* get window size */ 834 *(struct winsize *)data = tp->t_winsize; 835 break; 836 case TIOCGPGRP: /* get pgrp of tty */ 837 if (!isctty(p, tp)) 838 return (ENOTTY); 839 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 840 break; 841#ifdef TIOCHPCL 842 case TIOCHPCL: /* hang up on last close */ 843 s = spltty(); 844 SET(tp->t_cflag, HUPCL); 845 splx(s); 846 break; 847#endif 848 case TIOCNXCL: /* reset exclusive use of tty */ 849 s = spltty(); 850 CLR(tp->t_state, TS_XCLUDE); 851 splx(s); 852 break; 853 case TIOCOUTQ: /* output queue size */ 854 *(int *)data = tp->t_outq.c_cc; 855 break; 856 case TIOCSETA: /* set termios struct */ 857 case TIOCSETAW: /* drain output, set */ 858 case TIOCSETAF: { /* drn out, fls in, set */ 859 register struct termios *t = (struct termios *)data; 860 861 if (t->c_ispeed == 0) 862 t->c_ispeed = t->c_ospeed; 863 if (t->c_ispeed == 0) 864 t->c_ispeed = tp->t_ospeed; 865 if (t->c_ispeed == 0) 866 return (EINVAL); 867 s = spltty(); 868 if (cmd == TIOCSETAW || cmd == TIOCSETAF) { 869 error = ttywait(tp); 870 if (error) { 871 splx(s); 872 return (error); 873 } 874 if (cmd == TIOCSETAF) 875 ttyflush(tp, FREAD); 876 } 877 if (!ISSET(t->c_cflag, CIGNORE)) { 878 /* 879 * Set device hardware. 880 */ 881 if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 882 splx(s); 883 return (error); 884 } 885 if (ISSET(t->c_cflag, CLOCAL) && 886 !ISSET(tp->t_cflag, CLOCAL)) { 887 /* 888 * XXX disconnections would be too hard to 889 * get rid of without this kludge. The only 890 * way to get rid of controlling terminals 891 * is to exit from the session leader. 892 */ 893 CLR(tp->t_state, TS_ZOMBIE); 894 895 wakeup(TSA_CARR_ON(tp)); 896 ttwakeup(tp); 897 ttwwakeup(tp); 898 } 899 if ((ISSET(tp->t_state, TS_CARR_ON) || 900 ISSET(t->c_cflag, CLOCAL)) && 901 !ISSET(tp->t_state, TS_ZOMBIE)) 902 SET(tp->t_state, TS_CONNECTED); 903 else 904 CLR(tp->t_state, TS_CONNECTED); 905 tp->t_cflag = t->c_cflag; 906 tp->t_ispeed = t->c_ispeed; 907 if (t->c_ospeed != 0) 908 tp->t_ospeed = t->c_ospeed; 909 ttsetwater(tp); 910 } 911 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) && 912 cmd != TIOCSETAF) { 913 if (ISSET(t->c_lflag, ICANON)) 914 SET(tp->t_lflag, PENDIN); 915 else { 916 /* 917 * XXX we really shouldn't allow toggling 918 * ICANON while we're in a non-termios line 919 * discipline. Now we have to worry about 920 * panicing for a null queue. 921 */ 922 if (tp->t_canq.c_cbreserved > 0 && 923 tp->t_rawq.c_cbreserved > 0) { 924 catq(&tp->t_rawq, &tp->t_canq); 925 /* 926 * XXX the queue limits may be 927 * different, so the old queue 928 * swapping method no longer works. 929 */ 930 catq(&tp->t_canq, &tp->t_rawq); 931 } 932 CLR(tp->t_lflag, PENDIN); 933 } 934 ttwakeup(tp); 935 } 936 tp->t_iflag = t->c_iflag; 937 tp->t_oflag = t->c_oflag; 938 /* 939 * Make the EXTPROC bit read only. 940 */ 941 if (ISSET(tp->t_lflag, EXTPROC)) 942 SET(t->c_lflag, EXTPROC); 943 else 944 CLR(t->c_lflag, EXTPROC); 945 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN); 946 if (t->c_cc[VMIN] != tp->t_cc[VMIN] || 947 t->c_cc[VTIME] != tp->t_cc[VTIME]) 948 ttwakeup(tp); 949 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 950 splx(s); 951 break; 952 } 953 case TIOCSETD: { /* set line discipline */ 954 register int t = *(int *)data; 955 dev_t device = tp->t_dev; 956 957 if ((u_int)t >= nlinesw) 958 return (ENXIO); 959 if (t != tp->t_line) { 960 s = spltty(); 961 (*linesw[tp->t_line].l_close)(tp, flag); 962 error = (*linesw[t].l_open)(device, tp); 963 if (error) { 964 (void)(*linesw[tp->t_line].l_open)(device, tp); 965 splx(s); 966 return (error); 967 } 968 tp->t_line = t; 969 splx(s); 970 } 971 break; 972 } 973 case TIOCSTART: /* start output, like ^Q */ 974 s = spltty(); 975 if (ISSET(tp->t_state, TS_TTSTOP) || 976 ISSET(tp->t_lflag, FLUSHO)) { 977 CLR(tp->t_lflag, FLUSHO); 978 CLR(tp->t_state, TS_TTSTOP); 979 ttstart(tp); 980 } 981 splx(s); 982 break; 983 case TIOCSTI: /* simulate terminal input */ 984 if ((flag & FREAD) == 0 && suser(p)) 985 return (EPERM); 986 if (!isctty(p, tp) && suser(p)) 987 return (EACCES); 988 s = spltty(); 989 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp); 990 splx(s); 991 break; 992 case TIOCSTOP: /* stop output, like ^S */ 993 s = spltty(); 994 if (!ISSET(tp->t_state, TS_TTSTOP)) { 995 SET(tp->t_state, TS_TTSTOP); 996 (*tp->t_stop)(tp, 0); 997 } 998 splx(s); 999 break; 1000 case TIOCSCTTY: /* become controlling tty */ 1001 /* Session ctty vnode pointer set in vnode layer. */ 1002 if (!SESS_LEADER(p) || 1003 ((p->p_session->s_ttyvp || tp->t_session) && 1004 (tp->t_session != p->p_session))) 1005 return (EPERM); 1006 tp->t_session = p->p_session; 1007 tp->t_pgrp = p->p_pgrp; 1008 p->p_session->s_ttyp = tp; 1009 p->p_flag |= P_CONTROLT; 1010 break; 1011 case TIOCSPGRP: { /* set pgrp of tty */ 1012 register struct pgrp *pgrp = pgfind(*(int *)data); 1013 1014 if (!isctty(p, tp)) 1015 return (ENOTTY); 1016 else if (pgrp == NULL || pgrp->pg_session != p->p_session) 1017 return (EPERM); 1018 tp->t_pgrp = pgrp; 1019 break; 1020 } 1021 case TIOCSTAT: /* simulate control-T */ 1022 s = spltty(); 1023 ttyinfo(tp); 1024 splx(s); 1025 break; 1026 case TIOCSWINSZ: /* set window size */ 1027 if (bcmp((caddr_t)&tp->t_winsize, data, 1028 sizeof (struct winsize))) { 1029 tp->t_winsize = *(struct winsize *)data; 1030 pgsignal(tp->t_pgrp, SIGWINCH, 1); 1031 } 1032 break; 1033 case TIOCSDRAINWAIT: 1034 error = suser(p); 1035 if (error) 1036 return (error); 1037 tp->t_timeout = *(int *)data * hz; 1038 wakeup(TSA_OCOMPLETE(tp)); 1039 wakeup(TSA_OLOWAT(tp)); 1040 break; 1041 case TIOCGDRAINWAIT: 1042 *(int *)data = tp->t_timeout / hz; 1043 break; 1044 default: 1045#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1046 return (ttcompat(tp, cmd, data, flag)); 1047#else 1048 return (ENOIOCTL); 1049#endif 1050 } 1051 return (0); 1052} 1053 1054int 1055ttypoll(dev, events, p) 1056 dev_t dev; 1057 int events; 1058 struct proc *p; 1059{ 1060 int s; 1061 int revents = 0; 1062 struct tty *tp; 1063 1064 tp = dev->si_tty; 1065 if (tp == NULL) /* XXX used to return ENXIO, but that means true! */ 1066 return ((events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)) 1067 | POLLHUP); 1068 1069 s = spltty(); 1070 if (events & (POLLIN | POLLRDNORM)) { 1071 if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE)) 1072 revents |= events & (POLLIN | POLLRDNORM); 1073 else 1074 selrecord(p, &tp->t_rsel); 1075 } 1076 if (events & (POLLOUT | POLLWRNORM)) { 1077 if ((tp->t_outq.c_cc <= tp->t_olowat && 1078 ISSET(tp->t_state, TS_CONNECTED)) 1079 || ISSET(tp->t_state, TS_ZOMBIE)) 1080 revents |= events & (POLLOUT | POLLWRNORM); 1081 else 1082 selrecord(p, &tp->t_wsel); 1083 } 1084 splx(s); 1085 return (revents); 1086} 1087 1088/* 1089 * Must be called at spltty(). 1090 */ 1091static int 1092ttnread(tp) 1093 struct tty *tp; 1094{ 1095 int nread; 1096 1097 if (ISSET(tp->t_lflag, PENDIN)) 1098 ttypend(tp); 1099 nread = tp->t_canq.c_cc; 1100 if (!ISSET(tp->t_lflag, ICANON)) { 1101 nread += tp->t_rawq.c_cc; 1102 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0) 1103 nread = 0; 1104 } 1105 return (nread); 1106} 1107 1108/* 1109 * Wait for output to drain. 1110 */ 1111int 1112ttywait(tp) 1113 register struct tty *tp; 1114{ 1115 int error, s; 1116 1117 error = 0; 1118 s = spltty(); 1119 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 1120 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) { 1121 (*tp->t_oproc)(tp); 1122 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 1123 ISSET(tp->t_state, TS_CONNECTED)) { 1124 SET(tp->t_state, TS_SO_OCOMPLETE); 1125 error = ttysleep(tp, TSA_OCOMPLETE(tp), 1126 TTOPRI | PCATCH, "ttywai", 1127 tp->t_timeout); 1128 if (error) { 1129 if (error == EWOULDBLOCK) 1130 error = EIO; 1131 break; 1132 } 1133 } else 1134 break; 1135 } 1136 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY))) 1137 error = EIO; 1138 splx(s); 1139 return (error); 1140} 1141 1142/* 1143 * Flush if successfully wait. 1144 */ 1145static int 1146ttywflush(tp) 1147 struct tty *tp; 1148{ 1149 int error; 1150 1151 if ((error = ttywait(tp)) == 0) 1152 ttyflush(tp, FREAD); 1153 return (error); 1154} 1155 1156/* 1157 * Flush tty read and/or write queues, notifying anyone waiting. 1158 */ 1159void 1160ttyflush(tp, rw) 1161 register struct tty *tp; 1162 int rw; 1163{ 1164 register int s; 1165 1166 s = spltty(); 1167#if 0 1168again: 1169#endif 1170 if (rw & FWRITE) { 1171 FLUSHQ(&tp->t_outq); 1172 CLR(tp->t_state, TS_TTSTOP); 1173 } 1174 (*tp->t_stop)(tp, rw); 1175 if (rw & FREAD) { 1176 FLUSHQ(&tp->t_canq); 1177 FLUSHQ(&tp->t_rawq); 1178 CLR(tp->t_lflag, PENDIN); 1179 tp->t_rocount = 0; 1180 tp->t_rocol = 0; 1181 CLR(tp->t_state, TS_LOCAL); 1182 ttwakeup(tp); 1183 if (ISSET(tp->t_state, TS_TBLOCK)) { 1184 if (rw & FWRITE) 1185 FLUSHQ(&tp->t_outq); 1186 ttyunblock(tp); 1187 1188 /* 1189 * Don't let leave any state that might clobber the 1190 * next line discipline (although we should do more 1191 * to send the START char). Not clearing the state 1192 * may have caused the "putc to a clist with no 1193 * reserved cblocks" panic/printf. 1194 */ 1195 CLR(tp->t_state, TS_TBLOCK); 1196 1197#if 0 /* forget it, sleeping isn't always safe and we don't know when it is */ 1198 if (ISSET(tp->t_iflag, IXOFF)) { 1199 /* 1200 * XXX wait a bit in the hope that the stop 1201 * character (if any) will go out. Waiting 1202 * isn't good since it allows races. This 1203 * will be fixed when the stop character is 1204 * put in a special queue. Don't bother with 1205 * the checks in ttywait() since the timeout 1206 * will save us. 1207 */ 1208 SET(tp->t_state, TS_SO_OCOMPLETE); 1209 ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI, 1210 "ttyfls", hz / 10); 1211 /* 1212 * Don't try sending the stop character again. 1213 */ 1214 CLR(tp->t_state, TS_TBLOCK); 1215 goto again; 1216 } 1217#endif 1218 } 1219 } 1220 if (rw & FWRITE) { 1221 FLUSHQ(&tp->t_outq); 1222 ttwwakeup(tp); 1223 } 1224 splx(s); 1225} 1226 1227/* 1228 * Copy in the default termios characters. 1229 */ 1230void 1231termioschars(t) 1232 struct termios *t; 1233{ 1234 1235 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc); 1236} 1237 1238/* 1239 * Old interface. 1240 */ 1241void 1242ttychars(tp) 1243 struct tty *tp; 1244{ 1245 1246 termioschars(&tp->t_termios); 1247} 1248 1249/* 1250 * Handle input high water. Send stop character for the IXOFF case. Turn 1251 * on our input flow control bit and propagate the changes to the driver. 1252 * XXX the stop character should be put in a special high priority queue. 1253 */ 1254void 1255ttyblock(tp) 1256 struct tty *tp; 1257{ 1258 1259 SET(tp->t_state, TS_TBLOCK); 1260 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE && 1261 putc(tp->t_cc[VSTOP], &tp->t_outq) != 0) 1262 CLR(tp->t_state, TS_TBLOCK); /* try again later */ 1263 ttstart(tp); 1264} 1265 1266/* 1267 * Handle input low water. Send start character for the IXOFF case. Turn 1268 * off our input flow control bit and propagate the changes to the driver. 1269 * XXX the start character should be put in a special high priority queue. 1270 */ 1271static void 1272ttyunblock(tp) 1273 struct tty *tp; 1274{ 1275 1276 CLR(tp->t_state, TS_TBLOCK); 1277 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE && 1278 putc(tp->t_cc[VSTART], &tp->t_outq) != 0) 1279 SET(tp->t_state, TS_TBLOCK); /* try again later */ 1280 ttstart(tp); 1281} 1282 1283#ifdef notyet 1284/* Not used by any current (i386) drivers. */ 1285/* 1286 * Restart after an inter-char delay. 1287 */ 1288void 1289ttrstrt(tp_arg) 1290 void *tp_arg; 1291{ 1292 struct tty *tp; 1293 int s; 1294 1295 KASSERT(tp_arg != NULL, ("ttrstrt")); 1296 1297 tp = tp_arg; 1298 s = spltty(); 1299 1300 CLR(tp->t_state, TS_TIMEOUT); 1301 ttstart(tp); 1302 1303 splx(s); 1304} 1305#endif 1306 1307int 1308ttstart(tp) 1309 struct tty *tp; 1310{ 1311 1312 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ 1313 (*tp->t_oproc)(tp); 1314 return (0); 1315} 1316 1317/* 1318 * "close" a line discipline 1319 */ 1320int 1321ttylclose(tp, flag) 1322 struct tty *tp; 1323 int flag; 1324{ 1325 1326 if (flag & FNONBLOCK || ttywflush(tp)) 1327 ttyflush(tp, FREAD | FWRITE); 1328 return (0); 1329} 1330 1331/* 1332 * Handle modem control transition on a tty. 1333 * Flag indicates new state of carrier. 1334 * Returns 0 if the line should be turned off, otherwise 1. 1335 */ 1336int 1337ttymodem(tp, flag) 1338 register struct tty *tp; 1339 int flag; 1340{ 1341 1342 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) { 1343 /* 1344 * MDMBUF: do flow control according to carrier flag 1345 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP 1346 * works if IXON and IXANY are clear. 1347 */ 1348 if (flag) { 1349 CLR(tp->t_state, TS_CAR_OFLOW); 1350 CLR(tp->t_state, TS_TTSTOP); 1351 ttstart(tp); 1352 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) { 1353 SET(tp->t_state, TS_CAR_OFLOW); 1354 SET(tp->t_state, TS_TTSTOP); 1355 (*tp->t_stop)(tp, 0); 1356 } 1357 } else if (flag == 0) { 1358 /* 1359 * Lost carrier. 1360 */ 1361 CLR(tp->t_state, TS_CARR_ON); 1362 if (ISSET(tp->t_state, TS_ISOPEN) && 1363 !ISSET(tp->t_cflag, CLOCAL)) { 1364 SET(tp->t_state, TS_ZOMBIE); 1365 CLR(tp->t_state, TS_CONNECTED); 1366 if (tp->t_session && tp->t_session->s_leader) 1367 psignal(tp->t_session->s_leader, SIGHUP); 1368 ttyflush(tp, FREAD | FWRITE); 1369 return (0); 1370 } 1371 } else { 1372 /* 1373 * Carrier now on. 1374 */ 1375 SET(tp->t_state, TS_CARR_ON); 1376 if (!ISSET(tp->t_state, TS_ZOMBIE)) 1377 SET(tp->t_state, TS_CONNECTED); 1378 wakeup(TSA_CARR_ON(tp)); 1379 ttwakeup(tp); 1380 ttwwakeup(tp); 1381 } 1382 return (1); 1383} 1384 1385/* 1386 * Reinput pending characters after state switch 1387 * call at spltty(). 1388 */ 1389static void 1390ttypend(tp) 1391 register struct tty *tp; 1392{ 1393 struct clist tq; 1394 register int c; 1395 1396 CLR(tp->t_lflag, PENDIN); 1397 SET(tp->t_state, TS_TYPEN); 1398 /* 1399 * XXX this assumes too much about clist internals. It may even 1400 * fail if the cblock slush pool is empty. We can't allocate more 1401 * cblocks here because we are called from an interrupt handler 1402 * and clist_alloc_cblocks() can wait. 1403 */ 1404 tq = tp->t_rawq; 1405 bzero(&tp->t_rawq, sizeof tp->t_rawq); 1406 tp->t_rawq.c_cbmax = tq.c_cbmax; 1407 tp->t_rawq.c_cbreserved = tq.c_cbreserved; 1408 while ((c = getc(&tq)) >= 0) 1409 ttyinput(c, tp); 1410 CLR(tp->t_state, TS_TYPEN); 1411} 1412 1413/* 1414 * Process a read call on a tty device. 1415 */ 1416int 1417ttread(tp, uio, flag) 1418 register struct tty *tp; 1419 struct uio *uio; 1420 int flag; 1421{ 1422 register struct clist *qp; 1423 register int c; 1424 register tcflag_t lflag; 1425 register cc_t *cc = tp->t_cc; 1426 register struct proc *p = curproc; 1427 int s, first, error = 0; 1428 int has_stime = 0, last_cc = 0; 1429 long slp = 0; /* XXX this should be renamed `timo'. */ 1430 struct timeval stime; 1431 1432loop: 1433 s = spltty(); 1434 lflag = tp->t_lflag; 1435 /* 1436 * take pending input first 1437 */ 1438 if (ISSET(lflag, PENDIN)) { 1439 ttypend(tp); 1440 splx(s); /* reduce latency */ 1441 s = spltty(); 1442 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */ 1443 } 1444 1445 /* 1446 * Hang process if it's in the background. 1447 */ 1448 if (isbackground(p, tp)) { 1449 splx(s); 1450 if (SIGISMEMBER(p->p_sigignore, SIGTTIN) || 1451 SIGISMEMBER(p->p_sigmask, SIGTTIN) || 1452 (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) 1453 return (EIO); 1454 pgsignal(p->p_pgrp, SIGTTIN, 1); 1455 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0); 1456 if (error) 1457 return (error); 1458 goto loop; 1459 } 1460 1461 if (ISSET(tp->t_state, TS_ZOMBIE)) { 1462 splx(s); 1463 return (0); /* EOF */ 1464 } 1465 1466 /* 1467 * If canonical, use the canonical queue, 1468 * else use the raw queue. 1469 * 1470 * (should get rid of clists...) 1471 */ 1472 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq; 1473 1474 if (flag & IO_NDELAY) { 1475 if (qp->c_cc > 0) 1476 goto read; 1477 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) { 1478 splx(s); 1479 return (0); 1480 } 1481 splx(s); 1482 return (EWOULDBLOCK); 1483 } 1484 if (!ISSET(lflag, ICANON)) { 1485 int m = cc[VMIN]; 1486 long t = cc[VTIME]; 1487 struct timeval timecopy; 1488 1489 /* 1490 * Check each of the four combinations. 1491 * (m > 0 && t == 0) is the normal read case. 1492 * It should be fairly efficient, so we check that and its 1493 * companion case (m == 0 && t == 0) first. 1494 * For the other two cases, we compute the target sleep time 1495 * into slp. 1496 */ 1497 if (t == 0) { 1498 if (qp->c_cc < m) 1499 goto sleep; 1500 if (qp->c_cc > 0) 1501 goto read; 1502 1503 /* m, t and qp->c_cc are all 0. 0 is enough input. */ 1504 splx(s); 1505 return (0); 1506 } 1507 t *= 100000; /* time in us */ 1508#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \ 1509 ((t1).tv_usec - (t2).tv_usec)) 1510 if (m > 0) { 1511 if (qp->c_cc <= 0) 1512 goto sleep; 1513 if (qp->c_cc >= m) 1514 goto read; 1515 getmicrotime(&timecopy); 1516 if (!has_stime) { 1517 /* first character, start timer */ 1518 has_stime = 1; 1519 stime = timecopy; 1520 slp = t; 1521 } else if (qp->c_cc > last_cc) { 1522 /* got a character, restart timer */ 1523 stime = timecopy; 1524 slp = t; 1525 } else { 1526 /* nothing, check expiration */ 1527 slp = t - diff(timecopy, stime); 1528 if (slp <= 0) 1529 goto read; 1530 } 1531 last_cc = qp->c_cc; 1532 } else { /* m == 0 */ 1533 if (qp->c_cc > 0) 1534 goto read; 1535 getmicrotime(&timecopy); 1536 if (!has_stime) { 1537 has_stime = 1; 1538 stime = timecopy; 1539 slp = t; 1540 } else { 1541 slp = t - diff(timecopy, stime); 1542 if (slp <= 0) { 1543 /* Timed out, but 0 is enough input. */ 1544 splx(s); 1545 return (0); 1546 } 1547 } 1548 } 1549#undef diff 1550 /* 1551 * Rounding down may make us wake up just short 1552 * of the target, so we round up. 1553 * The formula is ceiling(slp * hz/1000000). 1554 * 32-bit arithmetic is enough for hz < 169. 1555 * XXX see tvtohz() for how to avoid overflow if hz 1556 * is large (divide by `tick' and/or arrange to 1557 * use tvtohz() if hz is large). 1558 */ 1559 slp = (long) (((u_long)slp * hz) + 999999) / 1000000; 1560 goto sleep; 1561 } 1562 if (qp->c_cc <= 0) { 1563sleep: 1564 /* 1565 * There is no input, or not enough input and we can block. 1566 */ 1567 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, 1568 ISSET(tp->t_state, TS_CONNECTED) ? 1569 "ttyin" : "ttyhup", (int)slp); 1570 splx(s); 1571 if (error == EWOULDBLOCK) 1572 error = 0; 1573 else if (error) 1574 return (error); 1575 /* 1576 * XXX what happens if another process eats some input 1577 * while we are asleep (not just here)? It would be 1578 * safest to detect changes and reset our state variables 1579 * (has_stime and last_cc). 1580 */ 1581 slp = 0; 1582 goto loop; 1583 } 1584read: 1585 splx(s); 1586 /* 1587 * Input present, check for input mapping and processing. 1588 */ 1589 first = 1; 1590 if (ISSET(lflag, ICANON | ISIG)) 1591 goto slowcase; 1592 for (;;) { 1593 char ibuf[IBUFSIZ]; 1594 int icc; 1595 1596 icc = imin(uio->uio_resid, IBUFSIZ); 1597 icc = q_to_b(qp, ibuf, icc); 1598 if (icc <= 0) { 1599 if (first) 1600 goto loop; 1601 break; 1602 } 1603 error = uiomove(ibuf, icc, uio); 1604 /* 1605 * XXX if there was an error then we should ungetc() the 1606 * unmoved chars and reduce icc here. 1607 */ 1608#if NSNP > 0 1609 if (ISSET(tp->t_lflag, ECHO) && 1610 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 1611 snpin((struct snoop *)tp->t_sc, ibuf, icc); 1612#endif 1613 if (error) 1614 break; 1615 if (uio->uio_resid == 0) 1616 break; 1617 first = 0; 1618 } 1619 goto out; 1620slowcase: 1621 for (;;) { 1622 c = getc(qp); 1623 if (c < 0) { 1624 if (first) 1625 goto loop; 1626 break; 1627 } 1628 /* 1629 * delayed suspend (^Y) 1630 */ 1631 if (CCEQ(cc[VDSUSP], c) && 1632 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) { 1633 pgsignal(tp->t_pgrp, SIGTSTP, 1); 1634 if (first) { 1635 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, 1636 "ttybg3", 0); 1637 if (error) 1638 break; 1639 goto loop; 1640 } 1641 break; 1642 } 1643 /* 1644 * Interpret EOF only in canonical mode. 1645 */ 1646 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) 1647 break; 1648 /* 1649 * Give user character. 1650 */ 1651 error = ureadc(c, uio); 1652 if (error) 1653 /* XXX should ungetc(c, qp). */ 1654 break; 1655#if NSNP > 0 1656 /* 1657 * Only snoop directly on input in echo mode. Non-echoed 1658 * input will be snooped later iff the application echoes it. 1659 */ 1660 if (ISSET(tp->t_lflag, ECHO) && 1661 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 1662 snpinc((struct snoop *)tp->t_sc, (char)c); 1663#endif 1664 if (uio->uio_resid == 0) 1665 break; 1666 /* 1667 * In canonical mode check for a "break character" 1668 * marking the end of a "line of input". 1669 */ 1670 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag)) 1671 break; 1672 first = 0; 1673 } 1674 1675out: 1676 /* 1677 * Look to unblock input now that (presumably) 1678 * the input queue has gone down. 1679 */ 1680 s = spltty(); 1681 if (ISSET(tp->t_state, TS_TBLOCK) && 1682 tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat) 1683 ttyunblock(tp); 1684 splx(s); 1685 1686 return (error); 1687} 1688 1689/* 1690 * Check the output queue on tp for space for a kernel message (from uprintf 1691 * or tprintf). Allow some space over the normal hiwater mark so we don't 1692 * lose messages due to normal flow control, but don't let the tty run amok. 1693 * Sleeps here are not interruptible, but we return prematurely if new signals 1694 * arrive. 1695 */ 1696int 1697ttycheckoutq(tp, wait) 1698 register struct tty *tp; 1699 int wait; 1700{ 1701 int hiwat, s; 1702 sigset_t oldmask; 1703 1704 hiwat = tp->t_ohiwat; 1705 SIGEMPTYSET(oldmask); 1706 s = spltty(); 1707 if (wait) 1708 oldmask = curproc->p_siglist; 1709 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) 1710 while (tp->t_outq.c_cc > hiwat) { 1711 ttstart(tp); 1712 if (tp->t_outq.c_cc <= hiwat) 1713 break; 1714 if (!(wait && SIGSETEQ(curproc->p_siglist, oldmask))) { 1715 splx(s); 1716 return (0); 1717 } 1718 SET(tp->t_state, TS_SO_OLOWAT); 1719 tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz); 1720 } 1721 splx(s); 1722 return (1); 1723} 1724 1725/* 1726 * Process a write call on a tty device. 1727 */ 1728int 1729ttwrite(tp, uio, flag) 1730 register struct tty *tp; 1731 register struct uio *uio; 1732 int flag; 1733{ 1734 register char *cp = NULL; 1735 register int cc, ce; 1736 register struct proc *p; 1737 int i, hiwat, cnt, error, s; 1738 char obuf[OBUFSIZ]; 1739 1740 hiwat = tp->t_ohiwat; 1741 cnt = uio->uio_resid; 1742 error = 0; 1743 cc = 0; 1744loop: 1745 s = spltty(); 1746 if (ISSET(tp->t_state, TS_ZOMBIE)) { 1747 splx(s); 1748 if (uio->uio_resid == cnt) 1749 error = EIO; 1750 goto out; 1751 } 1752 if (!ISSET(tp->t_state, TS_CONNECTED)) { 1753 if (flag & IO_NDELAY) { 1754 splx(s); 1755 error = EWOULDBLOCK; 1756 goto out; 1757 } 1758 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 1759 "ttydcd", 0); 1760 splx(s); 1761 if (error) 1762 goto out; 1763 goto loop; 1764 } 1765 splx(s); 1766 /* 1767 * Hang the process if it's in the background. 1768 */ 1769 p = curproc; 1770 if (isbackground(p, tp) && 1771 ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) && 1772 !SIGISMEMBER(p->p_sigignore, SIGTTOU) && 1773 !SIGISMEMBER(p->p_sigmask, SIGTTOU)) { 1774 if (p->p_pgrp->pg_jobc == 0) { 1775 error = EIO; 1776 goto out; 1777 } 1778 pgsignal(p->p_pgrp, SIGTTOU, 1); 1779 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0); 1780 if (error) 1781 goto out; 1782 goto loop; 1783 } 1784 /* 1785 * Process the user's data in at most OBUFSIZ chunks. Perform any 1786 * output translation. Keep track of high water mark, sleep on 1787 * overflow awaiting device aid in acquiring new space. 1788 */ 1789 while (uio->uio_resid > 0 || cc > 0) { 1790 if (ISSET(tp->t_lflag, FLUSHO)) { 1791 uio->uio_resid = 0; 1792 return (0); 1793 } 1794 if (tp->t_outq.c_cc > hiwat) 1795 goto ovhiwat; 1796 /* 1797 * Grab a hunk of data from the user, unless we have some 1798 * leftover from last time. 1799 */ 1800 if (cc == 0) { 1801 cc = imin(uio->uio_resid, OBUFSIZ); 1802 cp = obuf; 1803 error = uiomove(cp, cc, uio); 1804 if (error) { 1805 cc = 0; 1806 break; 1807 } 1808#if NSNP > 0 1809 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 1810 snpin((struct snoop *)tp->t_sc, cp, cc); 1811#endif 1812 } 1813 /* 1814 * If nothing fancy need be done, grab those characters we 1815 * can handle without any of ttyoutput's processing and 1816 * just transfer them to the output q. For those chars 1817 * which require special processing (as indicated by the 1818 * bits in char_type), call ttyoutput. After processing 1819 * a hunk of data, look for FLUSHO so ^O's will take effect 1820 * immediately. 1821 */ 1822 while (cc > 0) { 1823 if (!ISSET(tp->t_oflag, OPOST)) 1824 ce = cc; 1825 else { 1826 ce = cc - scanc((u_int)cc, (u_char *)cp, 1827 char_type, CCLASSMASK); 1828 /* 1829 * If ce is zero, then we're processing 1830 * a special character through ttyoutput. 1831 */ 1832 if (ce == 0) { 1833 tp->t_rocount = 0; 1834 if (ttyoutput(*cp, tp) >= 0) { 1835 /* No Clists, wait a bit. */ 1836 ttstart(tp); 1837 if (flag & IO_NDELAY) { 1838 error = EWOULDBLOCK; 1839 goto out; 1840 } 1841 error = ttysleep(tp, &lbolt, 1842 TTOPRI|PCATCH, 1843 "ttybf1", 0); 1844 if (error) 1845 goto out; 1846 goto loop; 1847 } 1848 cp++; 1849 cc--; 1850 if (ISSET(tp->t_lflag, FLUSHO) || 1851 tp->t_outq.c_cc > hiwat) 1852 goto ovhiwat; 1853 continue; 1854 } 1855 } 1856 /* 1857 * A bunch of normal characters have been found. 1858 * Transfer them en masse to the output queue and 1859 * continue processing at the top of the loop. 1860 * If there are any further characters in this 1861 * <= OBUFSIZ chunk, the first should be a character 1862 * requiring special handling by ttyoutput. 1863 */ 1864 tp->t_rocount = 0; 1865 i = b_to_q(cp, ce, &tp->t_outq); 1866 ce -= i; 1867 tp->t_column += ce; 1868 cp += ce, cc -= ce, tk_nout += ce; 1869 tp->t_outcc += ce; 1870 if (i > 0) { 1871 /* No Clists, wait a bit. */ 1872 ttstart(tp); 1873 if (flag & IO_NDELAY) { 1874 error = EWOULDBLOCK; 1875 goto out; 1876 } 1877 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, 1878 "ttybf2", 0); 1879 if (error) 1880 goto out; 1881 goto loop; 1882 } 1883 if (ISSET(tp->t_lflag, FLUSHO) || 1884 tp->t_outq.c_cc > hiwat) 1885 break; 1886 } 1887 ttstart(tp); 1888 } 1889out: 1890 /* 1891 * If cc is nonzero, we leave the uio structure inconsistent, as the 1892 * offset and iov pointers have moved forward, but it doesn't matter 1893 * (the call will either return short or restart with a new uio). 1894 */ 1895 uio->uio_resid += cc; 1896 return (error); 1897 1898ovhiwat: 1899 ttstart(tp); 1900 s = spltty(); 1901 /* 1902 * This can only occur if FLUSHO is set in t_lflag, 1903 * or if ttstart/oproc is synchronous (or very fast). 1904 */ 1905 if (tp->t_outq.c_cc <= hiwat) { 1906 splx(s); 1907 goto loop; 1908 } 1909 if (flag & IO_NDELAY) { 1910 splx(s); 1911 uio->uio_resid += cc; 1912 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); 1913 } 1914 SET(tp->t_state, TS_SO_OLOWAT); 1915 error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttywri", 1916 tp->t_timeout); 1917 splx(s); 1918 if (error == EWOULDBLOCK) 1919 error = EIO; 1920 if (error) 1921 goto out; 1922 goto loop; 1923} 1924 1925/* 1926 * Rubout one character from the rawq of tp 1927 * as cleanly as possible. 1928 */ 1929static void 1930ttyrub(c, tp) 1931 register int c; 1932 register struct tty *tp; 1933{ 1934 register char *cp; 1935 register int savecol; 1936 int tabc, s; 1937 1938 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) 1939 return; 1940 CLR(tp->t_lflag, FLUSHO); 1941 if (ISSET(tp->t_lflag, ECHOE)) { 1942 if (tp->t_rocount == 0) { 1943 /* 1944 * Screwed by ttwrite; retype 1945 */ 1946 ttyretype(tp); 1947 return; 1948 } 1949 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) 1950 ttyrubo(tp, 2); 1951 else { 1952 CLR(c, ~TTY_CHARMASK); 1953 switch (CCLASS(c)) { 1954 case ORDINARY: 1955 ttyrubo(tp, 1); 1956 break; 1957 case BACKSPACE: 1958 case CONTROL: 1959 case NEWLINE: 1960 case RETURN: 1961 case VTAB: 1962 if (ISSET(tp->t_lflag, ECHOCTL)) 1963 ttyrubo(tp, 2); 1964 break; 1965 case TAB: 1966 if (tp->t_rocount < tp->t_rawq.c_cc) { 1967 ttyretype(tp); 1968 return; 1969 } 1970 s = spltty(); 1971 savecol = tp->t_column; 1972 SET(tp->t_state, TS_CNTTB); 1973 SET(tp->t_lflag, FLUSHO); 1974 tp->t_column = tp->t_rocol; 1975 cp = tp->t_rawq.c_cf; 1976 if (cp) 1977 tabc = *cp; /* XXX FIX NEXTC */ 1978 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc)) 1979 ttyecho(tabc, tp); 1980 CLR(tp->t_lflag, FLUSHO); 1981 CLR(tp->t_state, TS_CNTTB); 1982 splx(s); 1983 1984 /* savecol will now be length of the tab. */ 1985 savecol -= tp->t_column; 1986 tp->t_column += savecol; 1987 if (savecol > 8) 1988 savecol = 8; /* overflow screw */ 1989 while (--savecol >= 0) 1990 (void)ttyoutput('\b', tp); 1991 break; 1992 default: /* XXX */ 1993#define PANICSTR "ttyrub: would panic c = %d, val = %d\n" 1994 (void)printf(PANICSTR, c, CCLASS(c)); 1995#ifdef notdef 1996 panic(PANICSTR, c, CCLASS(c)); 1997#endif 1998 } 1999 } 2000 } else if (ISSET(tp->t_lflag, ECHOPRT)) { 2001 if (!ISSET(tp->t_state, TS_ERASE)) { 2002 SET(tp->t_state, TS_ERASE); 2003 (void)ttyoutput('\\', tp); 2004 } 2005 ttyecho(c, tp); 2006 } else 2007 ttyecho(tp->t_cc[VERASE], tp); 2008 --tp->t_rocount; 2009} 2010 2011/* 2012 * Back over cnt characters, erasing them. 2013 */ 2014static void 2015ttyrubo(tp, cnt) 2016 register struct tty *tp; 2017 int cnt; 2018{ 2019 2020 while (cnt-- > 0) { 2021 (void)ttyoutput('\b', tp); 2022 (void)ttyoutput(' ', tp); 2023 (void)ttyoutput('\b', tp); 2024 } 2025} 2026 2027/* 2028 * ttyretype -- 2029 * Reprint the rawq line. Note, it is assumed that c_cc has already 2030 * been checked. 2031 */ 2032static void 2033ttyretype(tp) 2034 register struct tty *tp; 2035{ 2036 register char *cp; 2037 int s, c; 2038 2039 /* Echo the reprint character. */ 2040 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 2041 ttyecho(tp->t_cc[VREPRINT], tp); 2042 2043 (void)ttyoutput('\n', tp); 2044 2045 /* 2046 * XXX 2047 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE 2048 * BIT OF FIRST CHAR. 2049 */ 2050 s = spltty(); 2051 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0); 2052 cp != NULL; cp = nextc(&tp->t_canq, cp, &c)) 2053 ttyecho(c, tp); 2054 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0); 2055 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c)) 2056 ttyecho(c, tp); 2057 CLR(tp->t_state, TS_ERASE); 2058 splx(s); 2059 2060 tp->t_rocount = tp->t_rawq.c_cc; 2061 tp->t_rocol = 0; 2062} 2063 2064/* 2065 * Echo a typed character to the terminal. 2066 */ 2067static void 2068ttyecho(c, tp) 2069 register int c; 2070 register struct tty *tp; 2071{ 2072 2073 if (!ISSET(tp->t_state, TS_CNTTB)) 2074 CLR(tp->t_lflag, FLUSHO); 2075 if ((!ISSET(tp->t_lflag, ECHO) && 2076 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) || 2077 ISSET(tp->t_lflag, EXTPROC)) 2078 return; 2079 if (ISSET(tp->t_lflag, ECHOCTL) && 2080 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') || 2081 ISSET(c, TTY_CHARMASK) == 0177)) { 2082 (void)ttyoutput('^', tp); 2083 CLR(c, ~TTY_CHARMASK); 2084 if (c == 0177) 2085 c = '?'; 2086 else 2087 c += 'A' - 1; 2088 } 2089 (void)ttyoutput(c, tp); 2090} 2091 2092/* 2093 * Wake up any readers on a tty. 2094 */ 2095void 2096ttwakeup(tp) 2097 register struct tty *tp; 2098{ 2099 2100 if (tp->t_rsel.si_pid != 0) 2101 selwakeup(&tp->t_rsel); 2102 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL) 2103 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL)); 2104 wakeup(TSA_HUP_OR_INPUT(tp)); 2105} 2106 2107/* 2108 * Wake up any writers on a tty. 2109 */ 2110void 2111ttwwakeup(tp) 2112 register struct tty *tp; 2113{ 2114 2115 if (tp->t_wsel.si_pid != 0 && tp->t_outq.c_cc <= tp->t_olowat) 2116 selwakeup(&tp->t_wsel); 2117 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL) 2118 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL)); 2119 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) == 2120 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) { 2121 CLR(tp->t_state, TS_SO_OCOMPLETE); 2122 wakeup(TSA_OCOMPLETE(tp)); 2123 } 2124 if (ISSET(tp->t_state, TS_SO_OLOWAT) && 2125 tp->t_outq.c_cc <= tp->t_olowat) { 2126 CLR(tp->t_state, TS_SO_OLOWAT); 2127 wakeup(TSA_OLOWAT(tp)); 2128 } 2129} 2130 2131/* 2132 * Look up a code for a specified speed in a conversion table; 2133 * used by drivers to map software speed values to hardware parameters. 2134 */ 2135int 2136ttspeedtab(speed, table) 2137 int speed; 2138 register struct speedtab *table; 2139{ 2140 2141 for ( ; table->sp_speed != -1; table++) 2142 if (table->sp_speed == speed) 2143 return (table->sp_code); 2144 return (-1); 2145} 2146 2147/* 2148 * Set input and output watermarks and buffer sizes. For input, the 2149 * high watermark is about one second's worth of input above empty, the 2150 * low watermark is slightly below high water, and the buffer size is a 2151 * driver-dependent amount above high water. For output, the watermarks 2152 * are near the ends of the buffer, with about 1 second's worth of input 2153 * between them. All this only applies to the standard line discipline. 2154 */ 2155void 2156ttsetwater(tp) 2157 struct tty *tp; 2158{ 2159 register int cps, ttmaxhiwat, x; 2160 2161 /* Input. */ 2162 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512); 2163 switch (tp->t_ispeedwat) { 2164 case (speed_t)-1: 2165 cps = tp->t_ispeed / 10; 2166 break; 2167 case 0: 2168 /* 2169 * This case is for old drivers that don't know about 2170 * t_ispeedwat. Arrange for them to get the old buffer 2171 * sizes and watermarks. 2172 */ 2173 cps = TTYHOG - 2 * 256; 2174 tp->t_ififosize = 2 * 256; 2175 break; 2176 default: 2177 cps = tp->t_ispeedwat / 10; 2178 break; 2179 } 2180 tp->t_ihiwat = cps; 2181 tp->t_ilowat = 7 * cps / 8; 2182 x = cps + tp->t_ififosize; 2183 clist_alloc_cblocks(&tp->t_rawq, x, x); 2184 2185 /* Output. */ 2186 switch (tp->t_ospeedwat) { 2187 case (speed_t)-1: 2188 cps = tp->t_ospeed / 10; 2189 ttmaxhiwat = 2 * TTMAXHIWAT; 2190 break; 2191 case 0: 2192 cps = tp->t_ospeed / 10; 2193 ttmaxhiwat = TTMAXHIWAT; 2194 break; 2195 default: 2196 cps = tp->t_ospeedwat / 10; 2197 ttmaxhiwat = 8 * TTMAXHIWAT; 2198 break; 2199 } 2200#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x)) 2201 tp->t_olowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT); 2202 x += cps; 2203 x = CLAMP(x, ttmaxhiwat, TTMINHIWAT); /* XXX clamps are too magic */ 2204 tp->t_ohiwat = roundup(x, CBSIZE); /* XXX for compat */ 2205 x = imax(tp->t_ohiwat, TTMAXHIWAT); /* XXX for compat/safety */ 2206 x += OBUFSIZ + 100; 2207 clist_alloc_cblocks(&tp->t_outq, x, x); 2208#undef CLAMP 2209} 2210 2211/* 2212 * Report on state of foreground process group. 2213 */ 2214void 2215ttyinfo(tp) 2216 register struct tty *tp; 2217{ 2218 register struct proc *p, *pick; 2219 struct timeval utime, stime; 2220 int tmp; 2221 2222 if (ttycheckoutq(tp,0) == 0) 2223 return; 2224 2225 /* Print load average. */ 2226 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 2227 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); 2228 2229 if (tp->t_session == NULL) 2230 ttyprintf(tp, "not a controlling terminal\n"); 2231 else if (tp->t_pgrp == NULL) 2232 ttyprintf(tp, "no foreground process group\n"); 2233 else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) 2234 ttyprintf(tp, "empty foreground process group\n"); 2235 else { 2236 /* Pick interesting process. */ 2237 for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist)) 2238 if (proc_compare(pick, p)) 2239 pick = p; 2240 2241 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid, 2242 pick->p_stat == SRUN ? "running" : 2243 pick->p_wmesg ? pick->p_wmesg : "iowait"); 2244 2245 if (pick->p_flag & P_INMEM) { 2246 calcru(pick, &utime, &stime, NULL); 2247 2248 /* Print user time. */ 2249 ttyprintf(tp, "%ld.%02ldu ", 2250 utime.tv_sec, utime.tv_usec / 10000); 2251 2252 /* Print system time. */ 2253 ttyprintf(tp, "%ld.%02lds ", 2254 stime.tv_sec, stime.tv_usec / 10000); 2255 } else 2256 ttyprintf(tp, "?.??u ?.??s "); 2257 2258 /* Print percentage cpu, resident set size. */ 2259 tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT; 2260 ttyprintf(tp, "%d%% %ldk\n", 2261 tmp / 100, 2262 pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 : 2263 (long)pgtok(vmspace_resident_count(pick->p_vmspace))); 2264 } 2265 tp->t_rocount = 0; /* so pending input will be retyped if BS */ 2266} 2267 2268/* 2269 * Returns 1 if p2 is "better" than p1 2270 * 2271 * The algorithm for picking the "interesting" process is thus: 2272 * 2273 * 1) Only foreground processes are eligible - implied. 2274 * 2) Runnable processes are favored over anything else. The runner 2275 * with the highest cpu utilization is picked (p_estcpu). Ties are 2276 * broken by picking the highest pid. 2277 * 3) The sleeper with the shortest sleep time is next. With ties, 2278 * we pick out just "short-term" sleepers (P_SINTR == 0). 2279 * 4) Further ties are broken by picking the highest pid. 2280 */ 2281#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL)) 2282#define TESTAB(a, b) ((a)<<1 | (b)) 2283#define ONLYA 2 2284#define ONLYB 1 2285#define BOTH 3 2286 2287static int 2288proc_compare(p1, p2) 2289 register struct proc *p1, *p2; 2290{ 2291 2292 if (p1 == NULL) 2293 return (1); 2294 /* 2295 * see if at least one of them is runnable 2296 */ 2297 switch (TESTAB(ISRUN(p1), ISRUN(p2))) { 2298 case ONLYA: 2299 return (0); 2300 case ONLYB: 2301 return (1); 2302 case BOTH: 2303 /* 2304 * tie - favor one with highest recent cpu utilization 2305 */ 2306 if (p2->p_estcpu > p1->p_estcpu) 2307 return (1); 2308 if (p1->p_estcpu > p2->p_estcpu) 2309 return (0); 2310 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2311 } 2312 /* 2313 * weed out zombies 2314 */ 2315 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) { 2316 case ONLYA: 2317 return (1); 2318 case ONLYB: 2319 return (0); 2320 case BOTH: 2321 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2322 } 2323 /* 2324 * pick the one with the smallest sleep time 2325 */ 2326 if (p2->p_slptime > p1->p_slptime) 2327 return (0); 2328 if (p1->p_slptime > p2->p_slptime) 2329 return (1); 2330 /* 2331 * favor one sleeping in a non-interruptible sleep 2332 */ 2333 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0) 2334 return (1); 2335 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0) 2336 return (0); 2337 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2338} 2339 2340/* 2341 * Output char to tty; console putchar style. 2342 */ 2343int 2344tputchar(c, tp) 2345 int c; 2346 struct tty *tp; 2347{ 2348 register int s; 2349 2350 s = spltty(); 2351 if (!ISSET(tp->t_state, TS_CONNECTED)) { 2352 splx(s); 2353 return (-1); 2354 } 2355 if (c == '\n') 2356 (void)ttyoutput('\r', tp); 2357 (void)ttyoutput(c, tp); 2358 ttstart(tp); 2359 splx(s); 2360 return (0); 2361} 2362 2363/* 2364 * Sleep on chan, returning ERESTART if tty changed while we napped and 2365 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If 2366 * the tty is revoked, restarting a pending call will redo validation done 2367 * at the start of the call. 2368 */ 2369int 2370ttysleep(tp, chan, pri, wmesg, timo) 2371 struct tty *tp; 2372 void *chan; 2373 int pri, timo; 2374 char *wmesg; 2375{ 2376 int error; 2377 int gen; 2378 2379 gen = tp->t_gen; 2380 error = tsleep(chan, pri, wmesg, timo); 2381 if (error) 2382 return (error); 2383 return (tp->t_gen == gen ? 0 : ERESTART); 2384} 2385 2386/* 2387 * Allocate a tty struct. Clists in the struct will be allocated by 2388 * ttyopen(). 2389 */ 2390struct tty * 2391ttymalloc(tp) 2392 struct tty *tp; 2393{ 2394 2395 if (tp) 2396 return(tp); 2397 tp = malloc(sizeof *tp, M_TTYS, M_WAITOK); 2398 bzero(tp, sizeof *tp); 2399 ttyregister(tp); 2400 return (tp); 2401} 2402 2403#if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */ 2404/* 2405 * Free a tty struct. Clists in the struct should have been freed by 2406 * ttyclose(). 2407 */ 2408void 2409ttyfree(tp) 2410 struct tty *tp; 2411{ 2412 free(tp, M_TTYS); 2413} 2414#endif /* 0 */ 2415 2416void 2417ttyregister(tp) 2418 struct tty *tp; 2419{ 2420 SLIST_INSERT_HEAD(&tty_list, tp, t_list); 2421} 2422 2423static int 2424sysctl_kern_ttys SYSCTL_HANDLER_ARGS 2425{ 2426 int error; 2427 struct tty *tp, t; 2428 SLIST_FOREACH(tp, &tty_list, t_list) { 2429 t = *tp; 2430 if (t.t_dev) 2431 t.t_dev = (dev_t)dev2udev(t.t_dev); 2432 error = SYSCTL_OUT(req, (caddr_t)&t, sizeof(t)); 2433 if (error) 2434 return (error); 2435 } 2436 return (0); 2437} 2438 2439SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD, 2440 0, 0, sysctl_kern_ttys, "S,tty", "All struct ttys"); 2441 2442void 2443nottystop(tp, rw) 2444 struct tty *tp; 2445 int rw; 2446{ 2447 2448 return; 2449} 2450 2451int 2452ttyread(dev, uio, flag) 2453 dev_t dev; 2454 struct uio *uio; 2455 int flag; 2456{ 2457 struct tty *tp; 2458 2459 tp = dev->si_tty; 2460 if (tp == NULL) 2461 return (ENODEV); 2462 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 2463} 2464 2465int 2466ttywrite(dev, uio, flag) 2467 dev_t dev; 2468 struct uio *uio; 2469 int flag; 2470{ 2471 struct tty *tp; 2472 2473 tp = dev->si_tty; 2474 if (tp == NULL) 2475 return (ENODEV); 2476 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 2477} 2478