tty.c revision 116182
1139743Simp/*- 239213Sgibbs * Copyright (c) 1982, 1986, 1990, 1991, 1993 3111206Sken * The Regents of the University of California. All rights reserved. 439213Sgibbs * (c) UNIX System Laboratories, Inc. 539213Sgibbs * All or some portions of this file are derived from material licensed 639213Sgibbs * to the University of California by American Telephone and Telegraph 739213Sgibbs * Co. or Unix System Laboratories, Inc. and are reproduced herein with 839213Sgibbs * the permission of UNIX System Laboratories, Inc. 939213Sgibbs * 1039213Sgibbs * Copyright (c) 2002 Networks Associates Technologies, Inc. 1139213Sgibbs * All rights reserved. 1239213Sgibbs * 1339213Sgibbs * Portions of this software were developed for the FreeBSD Project by 1439213Sgibbs * ThinkSec AS and NAI Labs, the Security Research Division of Network 1539213Sgibbs * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 1639213Sgibbs * ("CBOSS"), as part of the DARPA CHATS research program. 1739213Sgibbs * 1839213Sgibbs * Redistribution and use in source and binary forms, with or without 1939213Sgibbs * modification, are permitted provided that the following conditions 2039213Sgibbs * are met: 2139213Sgibbs * 1. Redistributions of source code must retain the above copyright 2239213Sgibbs * notice, this list of conditions and the following disclaimer. 2339213Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 2439213Sgibbs * notice, this list of conditions and the following disclaimer in the 2539213Sgibbs * documentation and/or other materials provided with the distribution. 2639213Sgibbs * 3. All advertising materials mentioning features or use of this software 27116162Sobrien * must display the following acknowledgement: 28139743Simp * This product includes software developed by the University of 2939213Sgibbs * California, Berkeley and its contributors. 3039213Sgibbs * 4. Neither the name of the University nor the names of its contributors 3139213Sgibbs * may be used to endorse or promote products derived from this software 3239213Sgibbs * without specific prior written permission. 3339213Sgibbs * 3439213Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 3539213Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3639213Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3739213Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3839213Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3939213Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4039213Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4139213Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4239213Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4339213Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4439213Sgibbs * SUCH DAMAGE. 4539213Sgibbs * 4639213Sgibbs * @(#)tty.c 8.8 (Berkeley) 1/21/94 4739213Sgibbs */ 48116162Sobrien 49116162Sobrien/*- 50116162Sobrien * TODO: 5140020Sken * o Fix races for sending the start char in ttyflush(). 5239213Sgibbs * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect(). 5339213Sgibbs * With luck, there will be MIN chars before select() returns(). 5439213Sgibbs * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it. 5539213Sgibbs * o Don't allow input in TS_ZOMBIE case. It would be visible through 5660041Sphk * FIONREAD. 5751836Sphk * o Do the new sio locking stuff here and use it to avoid special 5851836Sphk * case for EXTPROC? 5939213Sgibbs * o Lock PENDIN too? 6039213Sgibbs * o Move EXTPROC and/or PENDIN to t_state? 61105421Snjl * o Wrap most of ttioctl in spltty/splx. 6260422Sken * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>. 6339213Sgibbs * o Send STOP if IXOFF is toggled off while TS_TBLOCK is set. 6439213Sgibbs * o Don't allow certain termios flags to affect disciplines other 65119708Sken * than TTYDISC. Cancel their effects before switch disciplines 66120599Sphk * and ignore them if they are set while we are in another 6739213Sgibbs * discipline. 6839213Sgibbs * o Now that historical speed conversions are handled here, don't 6939213Sgibbs * do them in drivers. 7039213Sgibbs * o Check for TS_CARR_ON being set while everything is closed and not 7139213Sgibbs * waiting for carrier. TS_CARR_ON isn't cleared if nothing is open, 7239213Sgibbs * so it would live until the next open even if carrier drops. 73168752Sscottl * o Restore TS_WOPEN since it is useful in pstat. It must be cleared 7439213Sgibbs * only when _all_ openers leave open(). 7539213Sgibbs */ 7639213Sgibbs 7739213Sgibbs#include <sys/cdefs.h> 7839213Sgibbs__FBSDID("$FreeBSD: head/sys/kern/tty.c 116182 2003-06-11 00:56:59Z obrien $"); 7939213Sgibbs 8039213Sgibbs#include "opt_compat.h" 8139213Sgibbs#include "opt_tty.h" 8239213Sgibbs 8339213Sgibbs#include <sys/param.h> 8439213Sgibbs#include <sys/systm.h> 8539213Sgibbs#include <sys/filio.h> 8639213Sgibbs#include <sys/lock.h> 87111206Sken#include <sys/mutex.h> 88111206Sken#include <sys/namei.h> 89111206Sken#include <sys/sx.h> 90111206Sken#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 91111206Sken#include <sys/ioctl_compat.h> 92111206Sken#endif 9339213Sgibbs#include <sys/proc.h> 9439213Sgibbs#define TTYDEFCHARS 9539213Sgibbs#include <sys/tty.h> 96120884Sthomas#undef TTYDEFCHARS 97120884Sthomas#include <sys/fcntl.h> 98120884Sthomas#include <sys/conf.h> 99120884Sthomas#include <sys/poll.h> 100120884Sthomas#include <sys/kernel.h> 101120884Sthomas#include <sys/vnode.h> 102120884Sthomas#include <sys/signalvar.h> 103120884Sthomas#include <sys/resourcevar.h> 104120884Sthomas#include <sys/malloc.h> 105120884Sthomas#include <sys/filedesc.h> 106120884Sthomas#include <sys/sysctl.h> 107168752Sscottl 108168752Sscottl#include <vm/vm.h> 10939213Sgibbs#include <vm/pmap.h> 11039213Sgibbs#include <vm/vm_map.h> 11139213Sgibbs 11239213SgibbsMALLOC_DEFINE(M_TTYS, "ttys", "tty data structures"); 11339213Sgibbs 11439213Sgibbslong tk_cancc; 11539213Sgibbslong tk_nin; 11639213Sgibbslong tk_nout; 11739213Sgibbslong tk_rawcc; 11839213Sgibbs 11939213Sgibbsstatic int proc_compare(struct proc *p1, struct proc *p2); 12039213Sgibbsstatic int ttnread(struct tty *tp); 12139213Sgibbsstatic void ttyecho(int c, struct tty *tp); 12239213Sgibbsstatic int ttyoutput(int c, struct tty *tp); 12339213Sgibbsstatic void ttypend(struct tty *tp); 12439213Sgibbsstatic void ttyretype(struct tty *tp); 12539213Sgibbsstatic void ttyrub(int c, struct tty *tp); 12639213Sgibbsstatic void ttyrubo(struct tty *tp, int cnt); 12739213Sgibbsstatic void ttyunblock(struct tty *tp); 12839213Sgibbsstatic int ttywflush(struct tty *tp); 129111206Skenstatic int filt_ttyread(struct knote *kn, long hint); 130111206Skenstatic void filt_ttyrdetach(struct knote *kn); 131111206Skenstatic int filt_ttywrite(struct knote *kn, long hint); 132111206Skenstatic void filt_ttywdetach(struct knote *kn); 133111206Sken 134111206Sken/* 135111206Sken * Table with character classes and parity. The 8th bit indicates parity, 136111206Sken * the 7th bit indicates the character is an alphameric or underscore (for 137111206Sken * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits 138111206Sken * are 0 then the character needs no special processing on output; classes 13939213Sgibbs * other than 0 might be translated or (not currently) require delays. 14039213Sgibbs */ 14139213Sgibbs#define E 0x00 /* Even parity. */ 14239213Sgibbs#define O 0x80 /* Odd parity. */ 14339213Sgibbs#define PARITY(c) (char_type[c] & O) 14439213Sgibbs 14539213Sgibbs#define ALPHA 0x40 /* Alpha or underscore. */ 14639213Sgibbs#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA) 14746581Sken 14859249Sphk#define CCLASSMASK 0x3f 14960938Sjake#define CCLASS(c) (char_type[c] & CCLASSMASK) 15039213Sgibbs 15139213Sgibbs#define BS BACKSPACE 15239213Sgibbs#define CC CONTROL 15360938Sjake#define CR RETURN 15439213Sgibbs#define NA ORDINARY | ALPHA 15539213Sgibbs#define NL NEWLINE 15639213Sgibbs#define NO ORDINARY 157111206Sken#define TB TAB 158112262Sphk#define VT VTAB 159119708Sken 160111206Skenstatic u_char const char_type[] = { 161111206Sken E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */ 162111206Sken O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */ 163111206Sken O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */ 164125975Sphk E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */ 16539213Sgibbs O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */ 16639213Sgibbs E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */ 167111206Sken E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */ 168111206Sken O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */ 169111206Sken O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */ 170111206Sken E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */ 171111206Sken E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */ 172111206Sken O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */ 173111206Sken E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */ 174111206Sken O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */ 175111206Sken O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */ 176111206Sken E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */ 17739213Sgibbs /* 17839213Sgibbs * Meta chars; should be settable per character set; 17939213Sgibbs * for now, treat them all as normal characters. 18039213Sgibbs */ 18139213Sgibbs NA, NA, NA, NA, NA, NA, NA, NA, 18239213Sgibbs NA, NA, NA, NA, NA, NA, NA, NA, 183111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 184111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 185111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 186111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 187111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 18839213Sgibbs NA, NA, NA, NA, NA, NA, NA, NA, 189111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 190111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 191111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 192111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 193111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 194111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 195111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 196111206Sken NA, NA, NA, NA, NA, NA, NA, NA, 197111206Sken}; 198111206Sken#undef BS 19939213Sgibbs#undef CC 20039213Sgibbs#undef CR 20139213Sgibbs#undef NA 20239213Sgibbs#undef NL 20339213Sgibbs#undef NO 20439213Sgibbs#undef TB 20539213Sgibbs#undef VT 20639213Sgibbs 20754451Sken/* Macros to clear/set/test flags. */ 20839213Sgibbs#define SET(t, f) (t) |= (f) 20940262Sken#define CLR(t, f) (t) &= ~(f) 21040262Sken#define ISSET(t, f) ((t) & (f)) 21167752Sken 21267752Sken#undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */ 21367752Sken#define MAX_INPUT TTYHOG /* XXX limit is usually larger for !ICANON */ 21467752Sken 21540262Sken/* 21640262Sken * list of struct tty where pstat(8) can pick it up with sysctl 21739213Sgibbs */ 21839213Sgibbsstatic SLIST_HEAD(, tty) tty_list; 21939213Sgibbs 220120599Sphkstatic int drainwait = 5*60; 221120599SphkSYSCTL_INT(_kern, OID_AUTO, drainwait, CTLFLAG_RW, &drainwait, 222120599Sphk 0, "Output drain timeout in seconds"); 223120599Sphk 22439213Sgibbs/* 22539213Sgibbs * Initial open of tty, or (re)entry to standard tty line discipline. 22639213Sgibbs */ 22739213Sgibbsint 22839213Sgibbsttyopen(dev_t device, struct tty *tp) 22940603Sken{ 23039213Sgibbs int s; 23139213Sgibbs 232111206Sken s = spltty(); 23339213Sgibbs tp->t_dev = device; 23439213Sgibbs if (!ISSET(tp->t_state, TS_ISOPEN)) { 23539213Sgibbs SET(tp->t_state, TS_ISOPEN); 23639213Sgibbs if (ISSET(tp->t_cflag, CLOCAL)) 23739213Sgibbs SET(tp->t_state, TS_CONNECTED); 23839213Sgibbs bzero(&tp->t_winsize, sizeof(tp->t_winsize)); 23939213Sgibbs } 24039213Sgibbs /* XXX don't hang forever on output */ 24139213Sgibbs if (tp->t_timeout < 0) 242111206Sken tp->t_timeout = drainwait*hz; 24339213Sgibbs ttsetwater(tp); 24439213Sgibbs splx(s); 24539213Sgibbs return (0); 246111206Sken} 247111206Sken 248111206Sken/* 249111206Sken * Handle close() on a tty line: flush and set to initial state, 250111206Sken * bumping generation number so that pending read/write calls 251111206Sken * can detect recycling of the tty. 25239213Sgibbs * XXX our caller should have done `spltty(); l_close(); ttyclose();' 25339213Sgibbs * and l_close() should have flushed, but we repeat the spltty() and 25439213Sgibbs * the flush in case there are buggy callers. 255111206Sken */ 256111206Skenint 25739213Sgibbsttyclose(struct tty *tp) 258111206Sken{ 25939213Sgibbs int s; 260111206Sken 26139213Sgibbs funsetown(&tp->t_sigio); 26239213Sgibbs s = spltty(); 26339213Sgibbs if (constty == tp) 26439213Sgibbs constty = NULL; 26539213Sgibbs 26639213Sgibbs ttyflush(tp, FREAD | FWRITE); 26739213Sgibbs clist_free_cblocks(&tp->t_canq); 26839213Sgibbs clist_free_cblocks(&tp->t_outq); 26939213Sgibbs clist_free_cblocks(&tp->t_rawq); 27039213Sgibbs 27139213Sgibbs tp->t_gen++; 27239213Sgibbs tp->t_line = TTYDISC; 27339213Sgibbs tp->t_pgrp = NULL; 27439213Sgibbs tp->t_session = NULL; 27539213Sgibbs tp->t_state = 0; 27639213Sgibbs splx(s); 277111206Sken return (0); 278105421Snjl} 279105421Snjl 28060422Sken#define FLUSHQ(q) { \ 28160422Sken if ((q)->c_cc) \ 28260422Sken ndflush(q, (q)->c_cc); \ 28360422Sken} 28460422Sken 28560422Sken/* Is 'c' a line delimiter ("break" character)? */ 28639213Sgibbs#define TTBREAKC(c, lflag) \ 28739213Sgibbs ((c) == '\n' || (((c) == cc[VEOF] || \ 28839213Sgibbs (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \ 28939213Sgibbs (c) != _POSIX_VDISABLE)) 29039213Sgibbs 29139213Sgibbs/* 29239213Sgibbs * Process input of a single character received on a tty. 29372119Speter */ 29439213Sgibbsint 29539213Sgibbsttyinput(int c, struct tty *tp) 29646747Sken{ 29739213Sgibbs tcflag_t iflag, lflag; 29839213Sgibbs cc_t *cc; 29946747Sken int i, err; 30039213Sgibbs 30139213Sgibbs /* 30239213Sgibbs * If input is pending take it first. 30339213Sgibbs */ 30439213Sgibbs lflag = tp->t_lflag; 30539213Sgibbs if (ISSET(lflag, PENDIN)) 30639213Sgibbs ttypend(tp); 30739213Sgibbs /* 30839213Sgibbs * Gather stats. 309111206Sken */ 31039213Sgibbs if (ISSET(lflag, ICANON)) { 31139213Sgibbs ++tk_cancc; 312111206Sken ++tp->t_cancc; 31339213Sgibbs } else { 31439213Sgibbs ++tk_rawcc; 31539213Sgibbs ++tp->t_rawcc; 31639213Sgibbs } 31739213Sgibbs ++tk_nin; 31839213Sgibbs 31939213Sgibbs /* 32039213Sgibbs * Block further input iff: 321168752Sscottl * current input > threshold AND input is available to user program 322168752Sscottl * AND input flow control is enabled and not yet invoked. 32346581Sken * The 3 is slop for PARMRK. 32460938Sjake */ 32560938Sjake iflag = tp->t_iflag; 32639213Sgibbs if (tp->t_rawq.c_cc + tp->t_canq.c_cc > tp->t_ihiwat - 3 && 32739213Sgibbs (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) && 328168752Sscottl (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) && 32960938Sjake !ISSET(tp->t_state, TS_TBLOCK)) 330168752Sscottl ttyblock(tp); 33139213Sgibbs 332169562Sscottl /* Handle exceptional conditions (break, parity, framing). */ 333169562Sscottl cc = tp->t_cc; 334104880Sphk err = (ISSET(c, TTY_ERRORMASK)); 33539213Sgibbs if (err) { 33639213Sgibbs CLR(c, TTY_ERRORMASK); 33739213Sgibbs if (ISSET(err, TTY_BI)) { 33839213Sgibbs if (ISSET(iflag, IGNBRK)) 339168752Sscottl return (0); 340168752Sscottl if (ISSET(iflag, BRKINT)) { 341168752Sscottl ttyflush(tp, FREAD | FWRITE); 34239213Sgibbs if (tp->t_pgrp != NULL) { 34339213Sgibbs PGRP_LOCK(tp->t_pgrp); 34439213Sgibbs pgsignal(tp->t_pgrp, SIGINT, 1); 34539213Sgibbs PGRP_UNLOCK(tp->t_pgrp); 346169605Sscottl } 34739213Sgibbs goto endcase; 34839213Sgibbs } 34939213Sgibbs if (ISSET(iflag, PARMRK)) 35039213Sgibbs goto parmrk; 35139213Sgibbs } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK)) 35239213Sgibbs || ISSET(err, TTY_FE)) { 35339213Sgibbs if (ISSET(iflag, IGNPAR)) 35439213Sgibbs return (0); 35540603Sken else if (ISSET(iflag, PARMRK)) { 35640603Skenparmrk: 35740603Sken if (tp->t_rawq.c_cc + tp->t_canq.c_cc > 35840603Sken MAX_INPUT - 3) 35940603Sken goto input_overflow; 36040603Sken (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); 36140603Sken (void)putc(0 | TTY_QUOTE, &tp->t_rawq); 36240603Sken (void)putc(c | TTY_QUOTE, &tp->t_rawq); 36340603Sken goto endcase; 364169605Sscottl } else 36540603Sken c = 0; 36640603Sken } 36740603Sken } 36840603Sken 36940603Sken if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP)) 37040603Sken CLR(c, 0x80); 37140603Sken if (!ISSET(lflag, EXTPROC)) { 37240603Sken /* 373112946Sphk * Check for literal nexting very first 37440603Sken */ 37540603Sken if (ISSET(tp->t_state, TS_LNCH)) { 37640603Sken SET(c, TTY_QUOTE); 37740603Sken CLR(tp->t_state, TS_LNCH); 37840603Sken } 37940603Sken /* 38040603Sken * Scan for special characters. This code 38140603Sken * is really just a big case statement with 38240603Sken * non-constant cases. The bottom of the 38340603Sken * case statement is labeled ``endcase'', so goto 384152565Sjdp * it after a case match, or similar. 385164906Smjacob */ 38640603Sken 38740603Sken /* 38840603Sken * Control chars which aren't controlled 38939213Sgibbs * by ICANON, ISIG, or IXON. 39039213Sgibbs */ 39139213Sgibbs if (ISSET(lflag, IEXTEN)) { 39239213Sgibbs if (CCEQ(cc[VLNEXT], c)) { 39339213Sgibbs if (ISSET(lflag, ECHO)) { 39439213Sgibbs if (ISSET(lflag, ECHOE)) { 395164906Smjacob (void)ttyoutput('^', tp); 39640603Sken (void)ttyoutput('\b', tp); 397120884Sthomas } else 398120884Sthomas ttyecho(c, tp); 399164906Smjacob } 400112668Sken SET(tp->t_state, TS_LNCH); 401112668Sken goto endcase; 40239213Sgibbs } 40339213Sgibbs if (CCEQ(cc[VDISCARD], c)) { 40439213Sgibbs if (ISSET(lflag, FLUSHO)) 40539213Sgibbs CLR(tp->t_lflag, FLUSHO); 40639213Sgibbs else { 40739213Sgibbs ttyflush(tp, FWRITE); 40839213Sgibbs ttyecho(c, tp); 40939213Sgibbs if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 41039213Sgibbs ttyretype(tp); 41139213Sgibbs SET(tp->t_lflag, FLUSHO); 41239213Sgibbs } 41339213Sgibbs goto startoutput; 41439213Sgibbs } 41539213Sgibbs } 41639213Sgibbs /* 41739213Sgibbs * Signals. 41839213Sgibbs */ 41939213Sgibbs if (ISSET(lflag, ISIG)) { 42039213Sgibbs if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 42139213Sgibbs if (!ISSET(lflag, NOFLSH)) 42239213Sgibbs ttyflush(tp, FREAD | FWRITE); 42339213Sgibbs ttyecho(c, tp); 42439213Sgibbs if (tp->t_pgrp != NULL) { 42539213Sgibbs PGRP_LOCK(tp->t_pgrp); 42639213Sgibbs pgsignal(tp->t_pgrp, 42739213Sgibbs CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 42839213Sgibbs PGRP_UNLOCK(tp->t_pgrp); 42939213Sgibbs } 43039213Sgibbs goto endcase; 431168752Sscottl } 43239213Sgibbs if (CCEQ(cc[VSUSP], c)) { 43339213Sgibbs if (!ISSET(lflag, NOFLSH)) 43439213Sgibbs ttyflush(tp, FREAD); 43539213Sgibbs ttyecho(c, tp); 43639213Sgibbs if (tp->t_pgrp != NULL) { 43739213Sgibbs PGRP_LOCK(tp->t_pgrp); 43839213Sgibbs pgsignal(tp->t_pgrp, SIGTSTP, 1); 43939213Sgibbs PGRP_UNLOCK(tp->t_pgrp); 44039213Sgibbs } 44139213Sgibbs goto endcase; 44239213Sgibbs } 44339213Sgibbs } 44439213Sgibbs /* 44539213Sgibbs * Handle start/stop characters. 44639213Sgibbs */ 44739213Sgibbs if (ISSET(iflag, IXON)) { 44839213Sgibbs if (CCEQ(cc[VSTOP], c)) { 44939213Sgibbs if (!ISSET(tp->t_state, TS_TTSTOP)) { 45039213Sgibbs SET(tp->t_state, TS_TTSTOP); 45139213Sgibbs (*tp->t_stop)(tp, 0); 452168752Sscottl return (0); 45339213Sgibbs } 45439213Sgibbs if (!CCEQ(cc[VSTART], c)) 45539213Sgibbs return (0); 45639213Sgibbs /* 457168752Sscottl * if VSTART == VSTOP then toggle 45839213Sgibbs */ 45939213Sgibbs goto endcase; 46039213Sgibbs } 461168752Sscottl if (CCEQ(cc[VSTART], c)) 46260938Sjake goto restartoutput; 46339213Sgibbs } 464168752Sscottl /* 465168752Sscottl * IGNCR, ICRNL, & INLCR 466164906Smjacob */ 46739213Sgibbs if (c == '\r') { 46839213Sgibbs if (ISSET(iflag, IGNCR)) 469168786Sscottl return (0); 470125975Sphk else if (ISSET(iflag, ICRNL)) 471168786Sscottl c = '\n'; 47240603Sken } else if (c == '\n' && ISSET(iflag, INLCR)) 47339213Sgibbs c = '\r'; 47439213Sgibbs } 47539213Sgibbs if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) { 47639213Sgibbs /* 47739213Sgibbs * From here on down canonical mode character 47839213Sgibbs * processing takes place. 47939213Sgibbs */ 48039213Sgibbs /* 48139213Sgibbs * erase or erase2 (^H / ^?) 48239213Sgibbs */ 48339213Sgibbs if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c) ) { 48439213Sgibbs if (tp->t_rawq.c_cc) 48539213Sgibbs ttyrub(unputc(&tp->t_rawq), tp); 48639213Sgibbs goto endcase; 48739213Sgibbs } 48839213Sgibbs /* 48979177Smjacob * kill (^U) 49079177Smjacob */ 49139213Sgibbs if (CCEQ(cc[VKILL], c)) { 49256148Smjacob if (ISSET(lflag, ECHOKE) && 49356148Smjacob tp->t_rawq.c_cc == tp->t_rocount && 49439213Sgibbs !ISSET(lflag, ECHOPRT)) 49539213Sgibbs while (tp->t_rawq.c_cc) 49639213Sgibbs ttyrub(unputc(&tp->t_rawq), tp); 49739213Sgibbs else { 49839213Sgibbs ttyecho(c, tp); 49939213Sgibbs if (ISSET(lflag, ECHOK) || 50039213Sgibbs ISSET(lflag, ECHOKE)) 50140603Sken ttyecho('\n', tp); 50240603Sken FLUSHQ(&tp->t_rawq); 50340603Sken tp->t_rocount = 0; 50440603Sken } 50540603Sken CLR(tp->t_state, TS_LOCAL); 50639213Sgibbs goto endcase; 50739213Sgibbs } 50839213Sgibbs /* 50939213Sgibbs * word erase (^W) 51039213Sgibbs */ 51139213Sgibbs if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) { 51239213Sgibbs int ctype; 51339213Sgibbs 51439213Sgibbs /* 51539213Sgibbs * erase whitespace 51639213Sgibbs */ 51739213Sgibbs while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 51839213Sgibbs ttyrub(c, tp); 51939213Sgibbs if (c == -1) 52039213Sgibbs goto endcase; 52139213Sgibbs /* 52239213Sgibbs * erase last char of word and remember the 52339213Sgibbs * next chars type (for ALTWERASE) 52439213Sgibbs */ 52539213Sgibbs ttyrub(c, tp); 52671999Sphk c = unputc(&tp->t_rawq); 52739213Sgibbs if (c == -1) 52847413Sgibbs goto endcase; 52939213Sgibbs if (c == ' ' || c == '\t') { 53039213Sgibbs (void)putc(c, &tp->t_rawq); 53147413Sgibbs goto endcase; 53239213Sgibbs } 53339213Sgibbs ctype = ISALPHA(c); 53439213Sgibbs /* 53539213Sgibbs * erase rest of word 536119708Sken */ 537119708Sken do { 538119708Sken ttyrub(c, tp); 539119708Sken c = unputc(&tp->t_rawq); 540119708Sken if (c == -1) 541119708Sken goto endcase; 542119708Sken } while (c != ' ' && c != '\t' && 543119708Sken (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype)); 544168752Sscottl (void)putc(c, &tp->t_rawq); 545168752Sscottl goto endcase; 546168752Sscottl } 547119708Sken /* 548119708Sken * reprint line (^R) 549119708Sken */ 550119708Sken if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) { 551119708Sken ttyretype(tp); 552119708Sken goto endcase; 553119708Sken } 554120884Sthomas /* 555119708Sken * ^T - kernel info and generate SIGINFO 556119708Sken */ 557119708Sken if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) { 558119708Sken if (ISSET(lflag, ISIG) && tp->t_pgrp != NULL) { 559119708Sken PGRP_LOCK(tp->t_pgrp); 560119708Sken pgsignal(tp->t_pgrp, SIGINFO, 1); 561160345Sdelphij PGRP_UNLOCK(tp->t_pgrp); 562168752Sscottl } 563119708Sken if (!ISSET(lflag, NOKERNINFO)) 564119708Sken ttyinfo(tp); 565119708Sken goto endcase; 566119708Sken } 567119708Sken } 568119708Sken /* 569119708Sken * Check for input buffer overflow 570119708Sken */ 571119708Sken if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) { 572119708Skeninput_overflow: 573119708Sken if (ISSET(iflag, IMAXBEL)) { 574119708Sken if (tp->t_outq.c_cc < tp->t_ohiwat) 575119708Sken (void)ttyoutput(CTRL('g'), tp); 576168752Sscottl } 577119708Sken goto endcase; 578119708Sken } 579111206Sken 580111206Sken if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP) 581111206Sken && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR)) 582111206Sken (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); 583111206Sken 584111206Sken /* 585111206Sken * Put data char in q for user and 586111206Sken * wakeup on seeing a line delimiter. 587111206Sken */ 588111206Sken if (putc(c, &tp->t_rawq) >= 0) { 589111206Sken if (!ISSET(lflag, ICANON)) { 590111206Sken ttwakeup(tp); 591111206Sken ttyecho(c, tp); 592111206Sken goto endcase; 593111206Sken } 594111206Sken if (TTBREAKC(c, lflag)) { 595111206Sken tp->t_rocount = 0; 596111206Sken catq(&tp->t_rawq, &tp->t_canq); 597111206Sken ttwakeup(tp); 598111206Sken } else if (tp->t_rocount++ == 0) 599111206Sken tp->t_rocol = tp->t_column; 600111206Sken if (ISSET(tp->t_state, TS_ERASE)) { 601111206Sken /* 602111206Sken * end of prterase \.../ 603111206Sken */ 604111206Sken CLR(tp->t_state, TS_ERASE); 605111206Sken (void)ttyoutput('/', tp); 606111206Sken } 607111206Sken i = tp->t_column; 608111206Sken ttyecho(c, tp); 609111206Sken if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) { 610111206Sken /* 611111206Sken * Place the cursor over the '^' of the ^D. 612111206Sken */ 613111206Sken i = imin(2, tp->t_column - i); 614111206Sken while (i > 0) { 615111206Sken (void)ttyoutput('\b', tp); 61639213Sgibbs i--; 61739213Sgibbs } 61839213Sgibbs } 61939213Sgibbs } 620118105Snjlendcase: 62139213Sgibbs /* 622119708Sken * IXANY means allow any character to restart output. 62339213Sgibbs */ 62439213Sgibbs if (ISSET(tp->t_state, TS_TTSTOP) && 62539213Sgibbs !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) 62639213Sgibbs return (0); 62739213Sgibbsrestartoutput: 62839213Sgibbs CLR(tp->t_lflag, FLUSHO); 62939213Sgibbs CLR(tp->t_state, TS_TTSTOP); 63039213Sgibbsstartoutput: 63139213Sgibbs return (ttstart(tp)); 63239213Sgibbs} 63339213Sgibbs 63439213Sgibbs/* 63539213Sgibbs * Output a single character on a tty, doing output processing 63639213Sgibbs * as needed (expanding tabs, newline processing, etc.). 63739213Sgibbs * Returns < 0 if succeeds, otherwise returns char to resend. 63839213Sgibbs * Must be recursive. 63939213Sgibbs */ 64039213Sgibbsstatic int 64139213Sgibbsttyoutput(int c, struct tty *tp) 64239213Sgibbs{ 64339213Sgibbs tcflag_t oflag; 64439213Sgibbs int col, s; 645111206Sken 64639213Sgibbs oflag = tp->t_oflag; 64759249Sphk if (!ISSET(oflag, OPOST)) { 64839213Sgibbs if (ISSET(tp->t_lflag, FLUSHO)) 64939213Sgibbs return (-1); 65039213Sgibbs if (putc(c, &tp->t_outq)) 65139213Sgibbs return (c); 65239213Sgibbs tk_nout++; 65339213Sgibbs tp->t_outcc++; 65439213Sgibbs return (-1); 65539213Sgibbs } 65639213Sgibbs /* 65739213Sgibbs * Do tab expansion if OXTABS is set. Special case if we external 65839213Sgibbs * processing, we don't do the tab expansion because we'll probably 65939213Sgibbs * get it wrong. If tab expansion needs to be done, let it happen 66039213Sgibbs * externally. 66139213Sgibbs */ 66239213Sgibbs CLR(c, ~TTY_CHARMASK); 66339213Sgibbs if (c == '\t' && 66439213Sgibbs ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) { 66539213Sgibbs c = 8 - (tp->t_column & 7); 66639213Sgibbs if (!ISSET(tp->t_lflag, FLUSHO)) { 66739213Sgibbs s = spltty(); /* Don't interrupt tabs. */ 66839213Sgibbs c -= b_to_q(" ", c, &tp->t_outq); 669118105Snjl tk_nout += c; 670118105Snjl tp->t_outcc += c; 671118105Snjl splx(s); 672118105Snjl } 673118105Snjl tp->t_column += c; 674118105Snjl return (c ? -1 : '\t'); 675118105Snjl } 676119708Sken if (c == CEOT && ISSET(oflag, ONOEOT)) 677111206Sken return (-1); 678111206Sken 679111206Sken /* 680111206Sken * Newline translation: if ONLCR is set, 681111206Sken * translate newline into "\r\n". 682111206Sken */ 683111206Sken if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) { 68439213Sgibbs tk_nout++; 685111206Sken tp->t_outcc++; 686111206Sken if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq)) 687111206Sken return (c); 688111206Sken } 689111206Sken /* If OCRNL is set, translate "\r" into "\n". */ 690111206Sken else if (c == '\r' && ISSET(tp->t_oflag, OCRNL)) 691111206Sken c = '\n'; 692111206Sken /* If ONOCR is set, don't transmit CRs when on column 0. */ 693111206Sken else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0) 694111206Sken return (-1); 695111206Sken 696111206Sken tk_nout++; 697111206Sken tp->t_outcc++; 69839213Sgibbs if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq)) 69939213Sgibbs return (c); 70039213Sgibbs 70139213Sgibbs col = tp->t_column; 70239213Sgibbs switch (CCLASS(c)) { 70356148Smjacob case BACKSPACE: 70439213Sgibbs if (col > 0) 70539213Sgibbs --col; 70639213Sgibbs break; 70739213Sgibbs case CONTROL: 70839213Sgibbs break; 709168752Sscottl case NEWLINE: 710125975Sphk if (ISSET(tp->t_oflag, ONLCR | ONLRET)) 711125975Sphk col = 0; 71239213Sgibbs break; 71339213Sgibbs case RETURN: 71443819Sken col = 0; 71543819Sken break; 716125975Sphk case ORDINARY: 717125975Sphk ++col; 718125975Sphk break; 719125975Sphk case TAB: 720125975Sphk col = (col + 8) & ~7; 721125975Sphk break; 722125975Sphk } 723168752Sscottl tp->t_column = col; 724125975Sphk return (-1); 725168752Sscottl} 72639213Sgibbs 72739213Sgibbs/* 72839213Sgibbs * Ioctls for all tty devices. Called after line-discipline specific ioctl 72939213Sgibbs * has been called to do discipline-specific functions and/or reject any 73039213Sgibbs * of these ioctl commands. 731169605Sscottl */ 732169605Sscottl/* ARGSUSED */ 73339213Sgibbsint 73439213Sgibbsttioctl(struct tty *tp, u_long cmd, void *data, int flag) 73539213Sgibbs{ 73639213Sgibbs struct proc *p; 73739213Sgibbs struct thread *td; 73839213Sgibbs struct pgrp *pgrp; 73939213Sgibbs int s, error; 74039213Sgibbs 74139213Sgibbs td = curthread; /* XXX */ 74239213Sgibbs p = td->td_proc; 74339213Sgibbs 74439213Sgibbs /* If the ioctl involves modification, hang if in the background. */ 74539213Sgibbs switch (cmd) { 74639213Sgibbs case TIOCCBRK: 74739213Sgibbs case TIOCCONS: 74839213Sgibbs case TIOCDRAIN: 74939213Sgibbs case TIOCEXCL: 75039213Sgibbs case TIOCFLUSH: 75139213Sgibbs#ifdef TIOCHPCL 75239213Sgibbs case TIOCHPCL: 75339213Sgibbs#endif 75439213Sgibbs case TIOCNXCL: 75539213Sgibbs case TIOCSBRK: 75639213Sgibbs case TIOCSCTTY: 75739213Sgibbs case TIOCSDRAINWAIT: 75839213Sgibbs case TIOCSETA: 759168752Sscottl case TIOCSETAF: 76039213Sgibbs case TIOCSETAW: 76139213Sgibbs case TIOCSETD: 76239213Sgibbs case TIOCSPGRP: 76339213Sgibbs case TIOCSTART: 76439213Sgibbs case TIOCSTAT: 76539213Sgibbs case TIOCSTI: 76639213Sgibbs case TIOCSTOP: 76739213Sgibbs case TIOCSWINSZ: 76839213Sgibbs#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 76939213Sgibbs case TIOCLBIC: 770168752Sscottl case TIOCLBIS: 77139213Sgibbs case TIOCLSET: 77239213Sgibbs case TIOCSETC: 77339213Sgibbs case OTIOCSETD: 77439213Sgibbs case TIOCSETN: 77539213Sgibbs case TIOCSETP: 77639213Sgibbs case TIOCSLTC: 77739213Sgibbs#endif 77839213Sgibbs sx_slock(&proctree_lock); 77939213Sgibbs PROC_LOCK(p); 78039213Sgibbs while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) && 78139213Sgibbs !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) && 78239213Sgibbs !SIGISMEMBER(td->td_sigmask, SIGTTOU)) { 78339213Sgibbs pgrp = p->p_pgrp; 78439213Sgibbs PROC_UNLOCK(p); 78539213Sgibbs if (pgrp->pg_jobc == 0) { 78639213Sgibbs sx_sunlock(&proctree_lock); 78739213Sgibbs return (EIO); 78839213Sgibbs } 78939213Sgibbs PGRP_LOCK(pgrp); 79039213Sgibbs sx_sunlock(&proctree_lock); 79139213Sgibbs pgsignal(pgrp, SIGTTOU, 1); 79239213Sgibbs PGRP_UNLOCK(pgrp); 79339213Sgibbs error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1", 79439213Sgibbs 0); 79539213Sgibbs if (error) 79639213Sgibbs return (error); 79739213Sgibbs sx_slock(&proctree_lock); 79839213Sgibbs PROC_LOCK(p); 79939213Sgibbs } 80039213Sgibbs PROC_UNLOCK(p); 80139213Sgibbs sx_sunlock(&proctree_lock); 80239213Sgibbs break; 80339213Sgibbs } 80439213Sgibbs 80539213Sgibbs switch (cmd) { /* Process the ioctl. */ 80639213Sgibbs case FIOASYNC: /* set/clear async i/o */ 80739213Sgibbs s = spltty(); 80839213Sgibbs if (*(int *)data) 80939213Sgibbs SET(tp->t_state, TS_ASYNC); 81039213Sgibbs else 81139213Sgibbs CLR(tp->t_state, TS_ASYNC); 81239213Sgibbs splx(s); 81339213Sgibbs break; 81439213Sgibbs case FIONBIO: /* set/clear non-blocking i/o */ 81539213Sgibbs break; /* XXX: delete. */ 81639213Sgibbs case FIONREAD: /* get # bytes to read */ 81767928Sken s = spltty(); 81839213Sgibbs *(int *)data = ttnread(tp); 81939213Sgibbs splx(s); 82039213Sgibbs break; 82139213Sgibbs 82239213Sgibbs case FIOSETOWN: 82339213Sgibbs /* 82439213Sgibbs * Policy -- Don't allow FIOSETOWN on someone else's 82539213Sgibbs * controlling tty 82639213Sgibbs */ 82739213Sgibbs if (tp->t_session != NULL && !isctty(p, tp)) 82839213Sgibbs return (ENOTTY); 82939213Sgibbs 83039213Sgibbs error = fsetown(*(int *)data, &tp->t_sigio); 83139213Sgibbs if (error) 83239213Sgibbs return (error); 83339213Sgibbs break; 83439213Sgibbs case FIOGETOWN: 83539213Sgibbs if (tp->t_session != NULL && !isctty(p, tp)) 83639213Sgibbs return (ENOTTY); 83739213Sgibbs *(int *)data = fgetown(&tp->t_sigio); 83839213Sgibbs break; 83939213Sgibbs 84039213Sgibbs case TIOCEXCL: /* set exclusive use of tty */ 84139213Sgibbs s = spltty(); 84239213Sgibbs SET(tp->t_state, TS_XCLUDE); 84339213Sgibbs splx(s); 84439213Sgibbs break; 84539213Sgibbs case TIOCFLUSH: { /* flush buffers */ 84639213Sgibbs int flags = *(int *)data; 84739213Sgibbs 84839213Sgibbs if (flags == 0) 84939213Sgibbs flags = FREAD | FWRITE; 85039213Sgibbs else 85139213Sgibbs flags &= FREAD | FWRITE; 85239213Sgibbs ttyflush(tp, flags); 85339213Sgibbs break; 85439213Sgibbs } 85539213Sgibbs case TIOCCONS: /* become virtual console */ 85639213Sgibbs if (*(int *)data) { 85739213Sgibbs struct nameidata nid; 85839213Sgibbs 85939213Sgibbs if (constty && constty != tp && 86039213Sgibbs ISSET(constty->t_state, TS_CONNECTED)) 86139213Sgibbs return (EBUSY); 86239213Sgibbs 86339213Sgibbs /* Ensure user can open the real console. */ 86439213Sgibbs NDINIT(&nid, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, 86539213Sgibbs "/dev/console", td); 86639213Sgibbs if ((error = namei(&nid)) != 0) 86739213Sgibbs return (error); 86839213Sgibbs NDFREE(&nid, NDF_ONLY_PNBUF); 86939213Sgibbs error = VOP_ACCESS(nid.ni_vp, VREAD, td->td_ucred, td); 87039213Sgibbs vput(nid.ni_vp); 87139213Sgibbs if (error) 87239213Sgibbs return (error); 87339213Sgibbs 87439213Sgibbs constty = tp; 87539213Sgibbs } else if (tp == constty) 87639213Sgibbs constty = NULL; 87739213Sgibbs break; 87839213Sgibbs case TIOCDRAIN: /* wait till output drained */ 87939213Sgibbs error = ttywait(tp); 88039213Sgibbs if (error) 88139213Sgibbs return (error); 88239213Sgibbs break; 88339213Sgibbs case TIOCGETA: { /* get termios struct */ 884168752Sscottl struct termios *t = (struct termios *)data; 885168752Sscottl 886168752Sscottl bcopy(&tp->t_termios, t, sizeof(struct termios)); 887168752Sscottl break; 888168752Sscottl } 889168752Sscottl case TIOCGETD: /* get line discipline */ 890168752Sscottl *(int *)data = tp->t_line; 89139213Sgibbs break; 89239213Sgibbs case TIOCGWINSZ: /* get window size */ 893168752Sscottl *(struct winsize *)data = tp->t_winsize; 89439213Sgibbs break; 89539213Sgibbs case TIOCGPGRP: /* get pgrp of tty */ 89639213Sgibbs if (!isctty(p, tp)) 89739213Sgibbs return (ENOTTY); 89839213Sgibbs *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 89939213Sgibbs break; 90039213Sgibbs#ifdef TIOCHPCL 90139213Sgibbs case TIOCHPCL: /* hang up on last close */ 90239213Sgibbs s = spltty(); 90339213Sgibbs SET(tp->t_cflag, HUPCL); 90439213Sgibbs splx(s); 90539213Sgibbs break; 90639213Sgibbs#endif 90739213Sgibbs case TIOCNXCL: /* reset exclusive use of tty */ 90839213Sgibbs s = spltty(); 90939213Sgibbs CLR(tp->t_state, TS_XCLUDE); 91039213Sgibbs splx(s); 91139213Sgibbs break; 91239213Sgibbs case TIOCOUTQ: /* output queue size */ 91339213Sgibbs *(int *)data = tp->t_outq.c_cc; 91439213Sgibbs break; 91539213Sgibbs case TIOCSETA: /* set termios struct */ 91639213Sgibbs case TIOCSETAW: /* drain output, set */ 91739213Sgibbs case TIOCSETAF: { /* drn out, fls in, set */ 91839213Sgibbs struct termios *t = (struct termios *)data; 91939213Sgibbs 92039213Sgibbs if (t->c_ispeed == 0) 92139213Sgibbs t->c_ispeed = t->c_ospeed; 92239213Sgibbs if (t->c_ispeed == 0) 92339213Sgibbs t->c_ispeed = tp->t_ospeed; 92439213Sgibbs if (t->c_ispeed == 0) 92539213Sgibbs return (EINVAL); 92639213Sgibbs s = spltty(); 92739213Sgibbs if (cmd == TIOCSETAW || cmd == TIOCSETAF) { 92839213Sgibbs error = ttywait(tp); 92939213Sgibbs if (error) { 93067928Sken splx(s); 93139213Sgibbs return (error); 93239213Sgibbs } 93339213Sgibbs if (cmd == TIOCSETAF) 93439213Sgibbs ttyflush(tp, FREAD); 93539213Sgibbs } 93639213Sgibbs if (!ISSET(t->c_cflag, CIGNORE)) { 93739213Sgibbs /* 93839213Sgibbs * Set device hardware. 93939213Sgibbs */ 94039213Sgibbs if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 94139213Sgibbs splx(s); 94239213Sgibbs return (error); 94339213Sgibbs } 94439213Sgibbs if (ISSET(t->c_cflag, CLOCAL) && 94539213Sgibbs !ISSET(tp->t_cflag, CLOCAL)) { 94639213Sgibbs /* 94739213Sgibbs * XXX disconnections would be too hard to 94839213Sgibbs * get rid of without this kludge. The only 94939213Sgibbs * way to get rid of controlling terminals 95039213Sgibbs * is to exit from the session leader. 95139213Sgibbs */ 95239213Sgibbs CLR(tp->t_state, TS_ZOMBIE); 95339213Sgibbs 95439213Sgibbs wakeup(TSA_CARR_ON(tp)); 955168752Sscottl ttwakeup(tp); 956168752Sscottl ttwwakeup(tp); 957168752Sscottl } 958168752Sscottl if ((ISSET(tp->t_state, TS_CARR_ON) || 959168752Sscottl ISSET(t->c_cflag, CLOCAL)) && 96039213Sgibbs !ISSET(tp->t_state, TS_ZOMBIE)) 96139213Sgibbs SET(tp->t_state, TS_CONNECTED); 96239213Sgibbs else 96339213Sgibbs CLR(tp->t_state, TS_CONNECTED); 96439213Sgibbs tp->t_cflag = t->c_cflag; 96539213Sgibbs tp->t_ispeed = t->c_ispeed; 96639213Sgibbs if (t->c_ospeed != 0) 96739213Sgibbs tp->t_ospeed = t->c_ospeed; 96839213Sgibbs ttsetwater(tp); 96939213Sgibbs } 970120599Sphk if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) && 97139213Sgibbs cmd != TIOCSETAF) { 97239213Sgibbs if (ISSET(t->c_lflag, ICANON)) 97339213Sgibbs SET(tp->t_lflag, PENDIN); 974101940Snjl else { 97539213Sgibbs /* 976120599Sphk * XXX we really shouldn't allow toggling 97739213Sgibbs * ICANON while we're in a non-termios line 97839213Sgibbs * discipline. Now we have to worry about 97939213Sgibbs * panicing for a null queue. 98039213Sgibbs */ 98139213Sgibbs if (tp->t_canq.c_cbreserved > 0 && 982168752Sscottl tp->t_rawq.c_cbreserved > 0) { 983168752Sscottl catq(&tp->t_rawq, &tp->t_canq); 984168752Sscottl /* 985168752Sscottl * XXX the queue limits may be 986168752Sscottl * different, so the old queue 98740603Sken * swapping method no longer works. 988168752Sscottl */ 989168752Sscottl catq(&tp->t_canq, &tp->t_rawq); 99039213Sgibbs } 99140603Sken CLR(tp->t_lflag, PENDIN); 99239213Sgibbs } 993168752Sscottl ttwakeup(tp); 994168752Sscottl } 995168752Sscottl tp->t_iflag = t->c_iflag; 99639213Sgibbs tp->t_oflag = t->c_oflag; 99741297Sken /* 99839213Sgibbs * Make the EXTPROC bit read only. 999168752Sscottl */ 1000168752Sscottl if (ISSET(tp->t_lflag, EXTPROC)) 1001168752Sscottl SET(t->c_lflag, EXTPROC); 1002168752Sscottl else 1003168752Sscottl CLR(t->c_lflag, EXTPROC); 100441297Sken tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN); 100540020Sken if (t->c_cc[VMIN] != tp->t_cc[VMIN] || 1006111206Sken t->c_cc[VTIME] != tp->t_cc[VTIME]) 1007111206Sken ttwakeup(tp); 1008111206Sken bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 100951836Sphk splx(s); 1010111206Sken break; 101140020Sken } 1012168752Sscottl case TIOCSETD: { /* set line discipline */ 1013168752Sscottl int t = *(int *)data; 101439213Sgibbs dev_t device = tp->t_dev; 101539213Sgibbs 1016168752Sscottl if ((u_int)t >= nlinesw) 101739213Sgibbs return (ENXIO); 101839213Sgibbs if (t != tp->t_line) { 101939213Sgibbs s = spltty(); 1020120599Sphk (*linesw[tp->t_line].l_close)(tp, flag); 102139213Sgibbs error = (*linesw[t].l_open)(device, tp); 102239213Sgibbs if (error) { 102339213Sgibbs (void)(*linesw[tp->t_line].l_open)(device, tp); 102439213Sgibbs splx(s); 1025120599Sphk return (error); 102639213Sgibbs } 102739213Sgibbs tp->t_line = t; 102839213Sgibbs splx(s); 102939213Sgibbs } 103039213Sgibbs break; 1031168752Sscottl } 1032168752Sscottl case TIOCSTART: /* start output, like ^Q */ 103339213Sgibbs s = spltty(); 103439213Sgibbs if (ISSET(tp->t_state, TS_TTSTOP) || 103539213Sgibbs ISSET(tp->t_lflag, FLUSHO)) { 103639213Sgibbs CLR(tp->t_lflag, FLUSHO); 103739213Sgibbs CLR(tp->t_state, TS_TTSTOP); 103839213Sgibbs ttstart(tp); 1039111206Sken } 104039213Sgibbs splx(s); 1041125975Sphk break; 104239213Sgibbs case TIOCSTI: /* simulate terminal input */ 1043111206Sken if ((flag & FREAD) == 0 && suser(td)) 1044111206Sken return (EPERM); 1045111206Sken if (!isctty(p, tp) && suser(td)) 1046168752Sscottl return (EACCES); 1047111206Sken s = spltty(); 1048168752Sscottl (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp); 104939213Sgibbs splx(s); 105039213Sgibbs break; 105139213Sgibbs case TIOCSTOP: /* stop output, like ^S */ 105239213Sgibbs s = spltty(); 105339213Sgibbs if (!ISSET(tp->t_state, TS_TTSTOP)) { 105439213Sgibbs SET(tp->t_state, TS_TTSTOP); 105539213Sgibbs (*tp->t_stop)(tp, 0); 105639213Sgibbs } 105739213Sgibbs splx(s); 105839213Sgibbs break; 105939213Sgibbs case TIOCSCTTY: /* become controlling tty */ 106039213Sgibbs /* Session ctty vnode pointer set in vnode layer. */ 106139213Sgibbs sx_slock(&proctree_lock); 106239213Sgibbs if (!SESS_LEADER(p) || 106339213Sgibbs ((p->p_session->s_ttyvp || tp->t_session) && 106439213Sgibbs (tp->t_session != p->p_session))) { 106539213Sgibbs sx_sunlock(&proctree_lock); 106639213Sgibbs return (EPERM); 106739213Sgibbs } 106839213Sgibbs tp->t_session = p->p_session; 106959249Sphk tp->t_pgrp = p->p_pgrp; 1070112262Sphk SESS_LOCK(p->p_session); 107139213Sgibbs p->p_session->s_ttyp = tp; 107239213Sgibbs SESS_UNLOCK(p->p_session); 107339213Sgibbs PROC_LOCK(p); 107439213Sgibbs p->p_flag |= P_CONTROLT; 107539213Sgibbs PROC_UNLOCK(p); 107639213Sgibbs sx_sunlock(&proctree_lock); 107739213Sgibbs break; 107839213Sgibbs case TIOCSPGRP: { /* set pgrp of tty */ 107939213Sgibbs sx_slock(&proctree_lock); 108039213Sgibbs pgrp = pgfind(*(int *)data); 108139213Sgibbs if (!isctty(p, tp)) { 108239213Sgibbs if (pgrp != NULL) 108339213Sgibbs PGRP_UNLOCK(pgrp); 108439213Sgibbs sx_sunlock(&proctree_lock); 108539213Sgibbs return (ENOTTY); 108639213Sgibbs } 108739213Sgibbs if (pgrp == NULL) { 108839213Sgibbs sx_sunlock(&proctree_lock); 108939213Sgibbs return (EPERM); 109039213Sgibbs } 109139213Sgibbs PGRP_UNLOCK(pgrp); 109239213Sgibbs if (pgrp->pg_session != p->p_session) { 109339213Sgibbs sx_sunlock(&proctree_lock); 109439213Sgibbs return (EPERM); 109539213Sgibbs } 109639213Sgibbs sx_sunlock(&proctree_lock); 109739213Sgibbs tp->t_pgrp = pgrp; 109839213Sgibbs break; 109939213Sgibbs } 110039213Sgibbs case TIOCSTAT: /* simulate control-T */ 110145442Sgibbs s = spltty(); 110239213Sgibbs ttyinfo(tp); 110339213Sgibbs splx(s); 110439213Sgibbs break; 110539213Sgibbs case TIOCSWINSZ: /* set window size */ 110639213Sgibbs if (bcmp((caddr_t)&tp->t_winsize, data, 110739213Sgibbs sizeof (struct winsize))) { 110839213Sgibbs tp->t_winsize = *(struct winsize *)data; 110939213Sgibbs if (tp->t_pgrp != NULL) { 111039213Sgibbs PGRP_LOCK(tp->t_pgrp); 111139213Sgibbs pgsignal(tp->t_pgrp, SIGWINCH, 1); 111239213Sgibbs PGRP_UNLOCK(tp->t_pgrp); 111346581Sken } 111446581Sken } 111539213Sgibbs break; 111639213Sgibbs case TIOCSDRAINWAIT: 111739213Sgibbs error = suser(td); 111839213Sgibbs if (error) 111939213Sgibbs return (error); 112039213Sgibbs tp->t_timeout = *(int *)data * hz; 112139213Sgibbs wakeup(TSA_OCOMPLETE(tp)); 112239213Sgibbs wakeup(TSA_OLOWAT(tp)); 112339213Sgibbs break; 112439213Sgibbs case TIOCGDRAINWAIT: 112539213Sgibbs *(int *)data = tp->t_timeout / hz; 112639213Sgibbs break; 112739213Sgibbs default: 112839213Sgibbs#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 112939213Sgibbs return (ttcompat(tp, cmd, data, flag)); 113039213Sgibbs#else 113139213Sgibbs return (ENOIOCTL); 113239213Sgibbs#endif 113339213Sgibbs } 113439213Sgibbs return (0); 113539213Sgibbs} 113639213Sgibbs 113739213Sgibbsint 113839213Sgibbsttypoll(dev_t dev, int events, struct thread *td) 113939213Sgibbs{ 114039213Sgibbs int s; 114139213Sgibbs int revents = 0; 114239213Sgibbs struct tty *tp; 114339213Sgibbs 114439213Sgibbs tp = dev->si_tty; 114539213Sgibbs if (tp == NULL) /* XXX used to return ENXIO, but that means true! */ 114639213Sgibbs return ((events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)) 114739213Sgibbs | POLLHUP); 114839213Sgibbs 114939213Sgibbs s = spltty(); 115039213Sgibbs if (events & (POLLIN | POLLRDNORM)) { 115139213Sgibbs if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE)) 115239213Sgibbs revents |= events & (POLLIN | POLLRDNORM); 115339213Sgibbs else 115439213Sgibbs selrecord(td, &tp->t_rsel); 115539213Sgibbs } 115639213Sgibbs if (events & (POLLOUT | POLLWRNORM)) { 1157168752Sscottl if ((tp->t_outq.c_cc <= tp->t_olowat && 1158168752Sscottl ISSET(tp->t_state, TS_CONNECTED)) 1159168752Sscottl || ISSET(tp->t_state, TS_ZOMBIE)) 1160168752Sscottl revents |= events & (POLLOUT | POLLWRNORM); 1161168752Sscottl else 1162168752Sscottl selrecord(td, &tp->t_wsel); 1163168752Sscottl } 1164168752Sscottl splx(s); 1165112262Sphk return (revents); 116639213Sgibbs} 116739213Sgibbs 1168112262Sphkstatic struct filterops ttyread_filtops = 116939213Sgibbs { 1, NULL, filt_ttyrdetach, filt_ttyread }; 1170168752Sscottlstatic struct filterops ttywrite_filtops = 1171168752Sscottl { 1, NULL, filt_ttywdetach, filt_ttywrite }; 1172168752Sscottl 117339213Sgibbsint 117439213Sgibbsttykqfilter(dev_t dev, struct knote *kn) 117539213Sgibbs{ 117639213Sgibbs struct tty *tp = dev->si_tty; 117739213Sgibbs struct klist *klist; 117839213Sgibbs int s; 117939213Sgibbs 118039213Sgibbs switch (kn->kn_filter) { 118139213Sgibbs case EVFILT_READ: 118239213Sgibbs klist = &tp->t_rsel.si_note; 118359249Sphk kn->kn_fop = &ttyread_filtops; 118439213Sgibbs break; 118539213Sgibbs case EVFILT_WRITE: 118645442Sgibbs klist = &tp->t_wsel.si_note; 118739213Sgibbs kn->kn_fop = &ttywrite_filtops; 118839213Sgibbs break; 118939213Sgibbs default: 119039213Sgibbs return (1); 119139213Sgibbs } 119245845Sgibbs 119339213Sgibbs kn->kn_hook = (caddr_t)dev; 119439213Sgibbs 119539213Sgibbs s = spltty(); 119639213Sgibbs SLIST_INSERT_HEAD(klist, kn, kn_selnext); 119739213Sgibbs splx(s); 119839213Sgibbs 119939213Sgibbs return (0); 120039213Sgibbs} 120139213Sgibbs 120239213Sgibbsstatic void 120339213Sgibbsfilt_ttyrdetach(struct knote *kn) 120439213Sgibbs{ 120539213Sgibbs struct tty *tp = ((dev_t)kn->kn_hook)->si_tty; 120639213Sgibbs int s = spltty(); 120739213Sgibbs 1208168752Sscottl SLIST_REMOVE(&tp->t_rsel.si_note, kn, knote, kn_selnext); 120939213Sgibbs splx(s); 121039213Sgibbs} 121139213Sgibbs 121239213Sgibbsstatic int 1213168752Sscottlfilt_ttyread(struct knote *kn, long hint) 121439213Sgibbs{ 121539213Sgibbs struct tty *tp = ((dev_t)kn->kn_hook)->si_tty; 121639213Sgibbs 121739213Sgibbs kn->kn_data = ttnread(tp); 121839213Sgibbs if (ISSET(tp->t_state, TS_ZOMBIE)) { 121939213Sgibbs kn->kn_flags |= EV_EOF; 122039213Sgibbs return (1); 122139213Sgibbs } 122239213Sgibbs return (kn->kn_data > 0); 122339213Sgibbs} 122439213Sgibbs 122539213Sgibbsstatic void 122639213Sgibbsfilt_ttywdetach(struct knote *kn) 122739213Sgibbs{ 122839213Sgibbs struct tty *tp = ((dev_t)kn->kn_hook)->si_tty; 122939213Sgibbs int s = spltty(); 123039213Sgibbs 123139213Sgibbs SLIST_REMOVE(&tp->t_wsel.si_note, kn, knote, kn_selnext); 123239213Sgibbs splx(s); 123339213Sgibbs} 123439213Sgibbs 123539213Sgibbsstatic int 123639213Sgibbsfilt_ttywrite(struct knote *kn, long hint) 123739213Sgibbs{ 123839213Sgibbs struct tty *tp = ((dev_t)kn->kn_hook)->si_tty; 123939213Sgibbs 124039213Sgibbs kn->kn_data = tp->t_outq.c_cc; 124139213Sgibbs if (ISSET(tp->t_state, TS_ZOMBIE)) 124239213Sgibbs return (1); 124339213Sgibbs return (kn->kn_data <= tp->t_olowat && 124439213Sgibbs ISSET(tp->t_state, TS_CONNECTED)); 124539213Sgibbs} 124639213Sgibbs 124739213Sgibbs/* 124839213Sgibbs * Must be called at spltty(). 124939213Sgibbs */ 125039213Sgibbsstatic int 125139213Sgibbsttnread(struct tty *tp) 125239213Sgibbs{ 125339213Sgibbs int nread; 125439213Sgibbs 125539213Sgibbs if (ISSET(tp->t_lflag, PENDIN)) 125639213Sgibbs ttypend(tp); 125739213Sgibbs nread = tp->t_canq.c_cc; 125839213Sgibbs if (!ISSET(tp->t_lflag, ICANON)) { 125939213Sgibbs nread += tp->t_rawq.c_cc; 126059249Sphk if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0) 1261112262Sphk nread = 0; 126239213Sgibbs } 126339213Sgibbs return (nread); 126439213Sgibbs} 126539213Sgibbs 126639213Sgibbs/* 126739213Sgibbs * Wait for output to drain. 126839213Sgibbs */ 126939213Sgibbsint 127039213Sgibbsttywait(struct tty *tp) 127139213Sgibbs{ 127239213Sgibbs int error, s; 127339213Sgibbs 1274168752Sscottl error = 0; 1275168752Sscottl s = spltty(); 1276168752Sscottl while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 127739213Sgibbs ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) { 127839213Sgibbs (*tp->t_oproc)(tp); 127939213Sgibbs if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 128039213Sgibbs ISSET(tp->t_state, TS_CONNECTED)) { 128139213Sgibbs SET(tp->t_state, TS_SO_OCOMPLETE); 128239213Sgibbs error = ttysleep(tp, TSA_OCOMPLETE(tp), 1283168752Sscottl TTOPRI | PCATCH, "ttywai", 1284168752Sscottl tp->t_timeout); 1285168752Sscottl if (error) { 128639213Sgibbs if (error == EWOULDBLOCK) 128739213Sgibbs error = EIO; 128839213Sgibbs break; 128939213Sgibbs } 129039213Sgibbs } else 129139213Sgibbs break; 129239213Sgibbs } 129339213Sgibbs if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY))) 129439213Sgibbs error = EIO; 129539213Sgibbs splx(s); 129639213Sgibbs return (error); 129739213Sgibbs} 129839213Sgibbs 129939213Sgibbs/* 130039213Sgibbs * Flush if successfully wait. 130139213Sgibbs */ 130239213Sgibbsstatic int 130339213Sgibbsttywflush(struct tty *tp) 130439213Sgibbs{ 130539213Sgibbs int error; 130639213Sgibbs 130739213Sgibbs if ((error = ttywait(tp)) == 0) 130839213Sgibbs ttyflush(tp, FREAD); 130939213Sgibbs return (error); 131039213Sgibbs} 131139213Sgibbs 131239213Sgibbs/* 131339213Sgibbs * Flush tty read and/or write queues, notifying anyone waiting. 1314125975Sphk */ 131539213Sgibbsvoid 131639213Sgibbsttyflush(struct tty *tp, int rw) 131739213Sgibbs{ 131839213Sgibbs int s; 131939213Sgibbs 132039213Sgibbs s = spltty(); 132139213Sgibbs#if 0 132242017Seivindagain: 132339213Sgibbs#endif 132439213Sgibbs if (rw & FWRITE) { 132539213Sgibbs FLUSHQ(&tp->t_outq); 132639213Sgibbs CLR(tp->t_state, TS_TTSTOP); 132739213Sgibbs } 132839213Sgibbs (*tp->t_stop)(tp, rw); 132939213Sgibbs if (rw & FREAD) { 133039213Sgibbs FLUSHQ(&tp->t_canq); 133139213Sgibbs FLUSHQ(&tp->t_rawq); 133239213Sgibbs CLR(tp->t_lflag, PENDIN); 133339213Sgibbs tp->t_rocount = 0; 133446581Sken tp->t_rocol = 0; 133539213Sgibbs CLR(tp->t_state, TS_LOCAL); 133639213Sgibbs ttwakeup(tp); 133739213Sgibbs if (ISSET(tp->t_state, TS_TBLOCK)) { 133839213Sgibbs if (rw & FWRITE) 133939213Sgibbs FLUSHQ(&tp->t_outq); 134039213Sgibbs ttyunblock(tp); 134145442Sgibbs 134239213Sgibbs /* 134339213Sgibbs * Don't let leave any state that might clobber the 134439213Sgibbs * next line discipline (although we should do more 134546581Sken * to send the START char). Not clearing the state 134646581Sken * may have caused the "putc to a clist with no 134746581Sken * reserved cblocks" panic/printf. 134846581Sken */ 134939213Sgibbs CLR(tp->t_state, TS_TBLOCK); 135039213Sgibbs 135139213Sgibbs#if 0 /* forget it, sleeping isn't always safe and we don't know when it is */ 1352168752Sscottl if (ISSET(tp->t_iflag, IXOFF)) { 1353168752Sscottl /* 135439213Sgibbs * XXX wait a bit in the hope that the stop 135539213Sgibbs * character (if any) will go out. Waiting 135639213Sgibbs * isn't good since it allows races. This 135739213Sgibbs * will be fixed when the stop character is 135839213Sgibbs * put in a special queue. Don't bother with 135939213Sgibbs * the checks in ttywait() since the timeout 136039213Sgibbs * will save us. 136139213Sgibbs */ 136239213Sgibbs SET(tp->t_state, TS_SO_OCOMPLETE); 136339213Sgibbs ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI, 136439213Sgibbs "ttyfls", hz / 10); 136539213Sgibbs /* 136659249Sphk * Don't try sending the stop character again. 136739213Sgibbs */ 136839213Sgibbs CLR(tp->t_state, TS_TBLOCK); 136939213Sgibbs goto again; 137039213Sgibbs } 1371120599Sphk#endif 137239213Sgibbs } 137376362Sphk } 137476362Sphk if (rw & FWRITE) { 137539213Sgibbs FLUSHQ(&tp->t_outq); 137639213Sgibbs ttwwakeup(tp); 1377168752Sscottl } 137839213Sgibbs splx(s); 137939213Sgibbs} 138039213Sgibbs 138139213Sgibbs/* 138239213Sgibbs * Copy in the default termios characters. 138339213Sgibbs */ 138439213Sgibbsvoid 138539213Sgibbstermioschars(struct termios *t) 1386168752Sscottl{ 138776362Sphk 138876362Sphk bcopy(ttydefchars, t->c_cc, sizeof t->c_cc); 138939213Sgibbs} 139039213Sgibbs 1391111206Sken/* 1392111206Sken * Old interface. 1393111206Sken */ 1394111206Skenvoid 1395111206Skenttychars(struct tty *tp) 1396111206Sken{ 1397111206Sken 1398111206Sken termioschars(&tp->t_termios); 1399111206Sken} 1400168752Sscottl 1401111206Sken/* 1402111206Sken * Handle input high water. Send stop character for the IXOFF case. Turn 1403111206Sken * on our input flow control bit and propagate the changes to the driver. 1404111206Sken * XXX the stop character should be put in a special high priority queue. 1405111206Sken */ 140639213Sgibbsvoid 140739213Sgibbsttyblock(struct tty *tp) 140839213Sgibbs{ 1409112946Sphk 141039213Sgibbs SET(tp->t_state, TS_TBLOCK); 141139213Sgibbs if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE && 141239213Sgibbs putc(tp->t_cc[VSTOP], &tp->t_outq) != 0) 141339213Sgibbs CLR(tp->t_state, TS_TBLOCK); /* try again later */ 141439213Sgibbs ttstart(tp); 141539213Sgibbs} 141639213Sgibbs 141739213Sgibbs/* 141839213Sgibbs * Handle input low water. Send start character for the IXOFF case. Turn 141939213Sgibbs * off our input flow control bit and propagate the changes to the driver. 1420168752Sscottl * XXX the start character should be put in a special high priority queue. 142139213Sgibbs */ 142239213Sgibbsstatic void 142339213Sgibbsttyunblock(struct tty *tp) 142439213Sgibbs{ 142539213Sgibbs 142639213Sgibbs CLR(tp->t_state, TS_TBLOCK); 142739213Sgibbs if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE && 142859249Sphk putc(tp->t_cc[VSTART], &tp->t_outq) != 0) 142939213Sgibbs SET(tp->t_state, TS_TBLOCK); /* try again later */ 143039213Sgibbs ttstart(tp); 143139213Sgibbs} 143239213Sgibbs 143339213Sgibbs#ifdef notyet 143439213Sgibbs/* Not used by any current (i386) drivers. */ 143539213Sgibbs/* 143639213Sgibbs * Restart after an inter-char delay. 143739213Sgibbs */ 143839213Sgibbsvoid 143959249Sphkttrstrt(void *tp_arg) 144039213Sgibbs{ 144139213Sgibbs struct tty *tp; 144239213Sgibbs int s; 144339213Sgibbs 144439213Sgibbs KASSERT(tp_arg != NULL, ("ttrstrt")); 144539213Sgibbs 144639213Sgibbs tp = tp_arg; 144739213Sgibbs s = spltty(); 144839213Sgibbs 144939213Sgibbs CLR(tp->t_state, TS_TIMEOUT); 145059249Sphk ttstart(tp); 145139213Sgibbs 1452125975Sphk splx(s); 145339213Sgibbs} 145439213Sgibbs#endif 145539213Sgibbs 145639213Sgibbsint 145791062Sphkttstart(struct tty *tp) 145859249Sphk{ 145939213Sgibbs 146039213Sgibbs if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ 1461121209Sphk (*tp->t_oproc)(tp); 1462121209Sphk return (0); 146359249Sphk} 146459249Sphk 146559249Sphk/* 146639213Sgibbs * "close" a line discipline 146739213Sgibbs */ 146839213Sgibbsint 146939213Sgibbsttylclose(struct tty *tp, int flag) 147039213Sgibbs{ 147139213Sgibbs 147239213Sgibbs if (flag & FNONBLOCK || ttywflush(tp)) 1473112262Sphk ttyflush(tp, FREAD | FWRITE); 147439213Sgibbs return (0); 147539213Sgibbs} 147639213Sgibbs 147739213Sgibbs/* 147839213Sgibbs * Handle modem control transition on a tty. 147939213Sgibbs * Flag indicates new state of carrier. 148039213Sgibbs * Returns 0 if the line should be turned off, otherwise 1. 148139213Sgibbs */ 148259249Sphkint 148339213Sgibbsttymodem(struct tty *tp, int flag) 148439213Sgibbs{ 148539213Sgibbs 148639213Sgibbs if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) { 148739213Sgibbs /* 148839213Sgibbs * MDMBUF: do flow control according to carrier flag 148939213Sgibbs * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP 149039213Sgibbs * works if IXON and IXANY are clear. 149139213Sgibbs */ 149239213Sgibbs if (flag) { 149339213Sgibbs CLR(tp->t_state, TS_CAR_OFLOW); 149439213Sgibbs CLR(tp->t_state, TS_TTSTOP); 149539213Sgibbs ttstart(tp); 1496169562Sscottl } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) { 149739213Sgibbs SET(tp->t_state, TS_CAR_OFLOW); 149839213Sgibbs SET(tp->t_state, TS_TTSTOP); 1499164906Smjacob (*tp->t_stop)(tp, 0); 1500164906Smjacob } 150139213Sgibbs } else if (flag == 0) { 150239213Sgibbs /* 150339213Sgibbs * Lost carrier. 150439213Sgibbs */ 150539213Sgibbs CLR(tp->t_state, TS_CARR_ON); 150639213Sgibbs if (ISSET(tp->t_state, TS_ISOPEN) && 150739213Sgibbs !ISSET(tp->t_cflag, CLOCAL)) { 150839213Sgibbs SET(tp->t_state, TS_ZOMBIE); 150939213Sgibbs CLR(tp->t_state, TS_CONNECTED); 151039213Sgibbs if (tp->t_session) { 151139213Sgibbs sx_slock(&proctree_lock); 151239213Sgibbs if (tp->t_session->s_leader) { 151339213Sgibbs struct proc *p; 151439213Sgibbs 151539213Sgibbs p = tp->t_session->s_leader; 151639213Sgibbs PROC_LOCK(p); 151739213Sgibbs psignal(p, SIGHUP); 151839213Sgibbs PROC_UNLOCK(p); 151939213Sgibbs } 152039213Sgibbs sx_sunlock(&proctree_lock); 152139213Sgibbs } 152239213Sgibbs ttyflush(tp, FREAD | FWRITE); 152339213Sgibbs return (0); 152439213Sgibbs } 152539213Sgibbs } else { 152639213Sgibbs /* 152739213Sgibbs * Carrier now on. 152839213Sgibbs */ 152939213Sgibbs SET(tp->t_state, TS_CARR_ON); 153039213Sgibbs if (!ISSET(tp->t_state, TS_ZOMBIE)) 153139213Sgibbs SET(tp->t_state, TS_CONNECTED); 153239213Sgibbs wakeup(TSA_CARR_ON(tp)); 153339213Sgibbs ttwakeup(tp); 153459249Sphk ttwwakeup(tp); 153539213Sgibbs } 153639213Sgibbs return (1); 153759249Sphk} 153839213Sgibbs 153939213Sgibbs/* 154039213Sgibbs * Reinput pending characters after state switch 154139213Sgibbs * call at spltty(). 154239213Sgibbs */ 154339213Sgibbsstatic void 154439213Sgibbsttypend(struct tty *tp) 154539213Sgibbs{ 154639213Sgibbs struct clist tq; 154746747Sken int c; 154874840Sken 154974840Sken CLR(tp->t_lflag, PENDIN); 155039213Sgibbs SET(tp->t_state, TS_TYPEN); 155139213Sgibbs /* 155239213Sgibbs * XXX this assumes too much about clist internals. It may even 155339213Sgibbs * fail if the cblock slush pool is empty. We can't allocate more 155439213Sgibbs * cblocks here because we are called from an interrupt handler 155539213Sgibbs * and clist_alloc_cblocks() can wait. 155639213Sgibbs */ 155739213Sgibbs tq = tp->t_rawq; 155839213Sgibbs bzero(&tp->t_rawq, sizeof tp->t_rawq); 1559164906Smjacob tp->t_rawq.c_cbmax = tq.c_cbmax; 1560164906Smjacob tp->t_rawq.c_cbreserved = tq.c_cbreserved; 1561112946Sphk while ((c = getc(&tq)) >= 0) 156259249Sphk ttyinput(c, tp); 156359249Sphk CLR(tp->t_state, TS_TYPEN); 156459249Sphk} 156539213Sgibbs 156639213Sgibbs/* 156739213Sgibbs * Process a read call on a tty device. 156839213Sgibbs */ 156939213Sgibbsint 157039213Sgibbsttread(struct tty *tp, struct uio *uio, int flag) 157139213Sgibbs{ 157259249Sphk struct clist *qp; 157359249Sphk int c; 157459249Sphk tcflag_t lflag; 1575104456Sphk cc_t *cc = tp->t_cc; 1576104456Sphk struct thread *td; 1577104456Sphk struct proc *p; 1578104456Sphk int s, first, error = 0; 1579104456Sphk int has_stime = 0, last_cc = 0; 158059249Sphk long slp = 0; /* XXX this should be renamed `timo'. */ 158139213Sgibbs struct timeval stime; 158239213Sgibbs struct pgrp *pg; 158339213Sgibbs 158439213Sgibbs td = curthread; 1585112262Sphk p = td->td_proc; 158639213Sgibbsloop: 158739213Sgibbs s = spltty(); 158839213Sgibbs lflag = tp->t_lflag; 158939213Sgibbs /* 1590157806Smaxim * take pending input first 159139213Sgibbs */ 159239213Sgibbs if (ISSET(lflag, PENDIN)) { 159339213Sgibbs ttypend(tp); 159439213Sgibbs splx(s); /* reduce latency */ 159539213Sgibbs s = spltty(); 159639213Sgibbs lflag = tp->t_lflag; /* XXX ttypend() clobbers it */ 159739213Sgibbs } 159839213Sgibbs 159939213Sgibbs /* 160039213Sgibbs * Hang process if it's in the background. 160139213Sgibbs */ 160239213Sgibbs if (isbackground(p, tp)) { 160339213Sgibbs splx(s); 160439213Sgibbs sx_slock(&proctree_lock); 160539213Sgibbs PROC_LOCK(p); 160639213Sgibbs if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) || 160739213Sgibbs SIGISMEMBER(td->td_sigmask, SIGTTIN) || 160839213Sgibbs (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) { 160939213Sgibbs PROC_UNLOCK(p); 161039213Sgibbs sx_sunlock(&proctree_lock); 161139213Sgibbs return (EIO); 161239213Sgibbs } 161339213Sgibbs pg = p->p_pgrp; 161439213Sgibbs PROC_UNLOCK(p); 161539213Sgibbs PGRP_LOCK(pg); 161639213Sgibbs sx_sunlock(&proctree_lock); 161739213Sgibbs pgsignal(pg, SIGTTIN, 1); 161839213Sgibbs PGRP_UNLOCK(pg); 161939213Sgibbs error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0); 162039213Sgibbs if (error) 162139213Sgibbs return (error); 162239213Sgibbs goto loop; 162339213Sgibbs } 162439213Sgibbs 162541514Sarchie if (ISSET(tp->t_state, TS_ZOMBIE)) { 162640020Sken splx(s); 162740020Sken return (0); /* EOF */ 162839213Sgibbs } 162939213Sgibbs 163039213Sgibbs /* 163139213Sgibbs * If canonical, use the canonical queue, 163239213Sgibbs * else use the raw queue. 163339213Sgibbs * 163439213Sgibbs * (should get rid of clists...) 163574840Sken */ 163674840Sken qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq; 163739213Sgibbs 163839213Sgibbs if (flag & IO_NDELAY) { 163939213Sgibbs if (qp->c_cc > 0) 164039213Sgibbs goto read; 164139213Sgibbs if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) { 164239213Sgibbs splx(s); 164339213Sgibbs return (0); 164439213Sgibbs } 164539213Sgibbs splx(s); 164639213Sgibbs return (EWOULDBLOCK); 164739213Sgibbs } 164839213Sgibbs if (!ISSET(lflag, ICANON)) { 164939213Sgibbs int m = cc[VMIN]; 165039213Sgibbs long t = cc[VTIME]; 165139213Sgibbs struct timeval timecopy; 165239213Sgibbs 165339213Sgibbs /* 165439213Sgibbs * Check each of the four combinations. 165539213Sgibbs * (m > 0 && t == 0) is the normal read case. 165639213Sgibbs * It should be fairly efficient, so we check that and its 165739213Sgibbs * companion case (m == 0 && t == 0) first. 165839213Sgibbs * For the other two cases, we compute the target sleep time 165939213Sgibbs * into slp. 166039213Sgibbs */ 166139213Sgibbs if (t == 0) { 166239213Sgibbs if (qp->c_cc < m) 166339213Sgibbs goto sleep; 166439213Sgibbs if (qp->c_cc > 0) 166539213Sgibbs goto read; 166639213Sgibbs 166739213Sgibbs /* m, t and qp->c_cc are all 0. 0 is enough input. */ 166839213Sgibbs splx(s); 166939213Sgibbs return (0); 167039213Sgibbs } 167139213Sgibbs t *= 100000; /* time in us */ 167239213Sgibbs#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \ 167339213Sgibbs ((t1).tv_usec - (t2).tv_usec)) 167439213Sgibbs if (m > 0) { 167539213Sgibbs if (qp->c_cc <= 0) 167639213Sgibbs goto sleep; 167739213Sgibbs if (qp->c_cc >= m) 167839213Sgibbs goto read; 167939213Sgibbs getmicrotime(&timecopy); 168039213Sgibbs if (!has_stime) { 168146581Sken /* first character, start timer */ 168246581Sken has_stime = 1; 168346581Sken stime = timecopy; 168446581Sken slp = t; 168539213Sgibbs } else if (qp->c_cc > last_cc) { 168646581Sken /* got a character, restart timer */ 168774840Sken stime = timecopy; 168874840Sken slp = t; 168974840Sken } else { 169074840Sken /* nothing, check expiration */ 169174840Sken slp = t - diff(timecopy, stime); 169274840Sken if (slp <= 0) 169374840Sken goto read; 169474840Sken } 169541514Sarchie last_cc = qp->c_cc; 169641514Sarchie } else { /* m == 0 */ 169739213Sgibbs if (qp->c_cc > 0) 169839213Sgibbs goto read; 169974840Sken getmicrotime(&timecopy); 170074840Sken if (!has_stime) { 170182850Sken has_stime = 1; 170282850Sken stime = timecopy; 170382850Sken slp = t; 170482850Sken } else { 170582850Sken slp = t - diff(timecopy, stime); 170682850Sken if (slp <= 0) { 170782850Sken /* Timed out, but 0 is enough input. */ 170882850Sken splx(s); 170982850Sken return (0); 171082850Sken } 171174840Sken } 171239213Sgibbs } 171339213Sgibbs#undef diff 171439213Sgibbs /* 171539213Sgibbs * Rounding down may make us wake up just short 171639213Sgibbs * of the target, so we round up. 171739213Sgibbs * The formula is ceiling(slp * hz/1000000). 171839213Sgibbs * 32-bit arithmetic is enough for hz < 169. 171939213Sgibbs * XXX see tvtohz() for how to avoid overflow if hz 172039213Sgibbs * is large (divide by `tick' and/or arrange to 172139213Sgibbs * use tvtohz() if hz is large). 172239213Sgibbs */ 172339213Sgibbs slp = (long) (((u_long)slp * hz) + 999999) / 1000000; 172439213Sgibbs goto sleep; 172539213Sgibbs } 172639213Sgibbs if (qp->c_cc <= 0) { 172739213Sgibbssleep: 172839213Sgibbs /* 172940020Sken * There is no input, or not enough input and we can block. 173040020Sken */ 173140020Sken error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, 173240020Sken ISSET(tp->t_state, TS_CONNECTED) ? 1733164906Smjacob "ttyin" : "ttyhup", (int)slp); 1734164906Smjacob splx(s); 1735164906Smjacob if (error == EWOULDBLOCK) 173640020Sken error = 0; 1737164906Smjacob else if (error) 1738164906Smjacob return (error); 173939213Sgibbs /* 174040603Sken * XXX what happens if another process eats some input 174139213Sgibbs * while we are asleep (not just here)? It would be 174239213Sgibbs * safest to detect changes and reset our state variables 174340020Sken * (has_stime and last_cc). 174440020Sken */ 174539213Sgibbs slp = 0; 174640603Sken goto loop; 174739213Sgibbs } 174840603Skenread: 174939213Sgibbs splx(s); 175039213Sgibbs /* 175140020Sken * Input present, check for input mapping and processing. 175239213Sgibbs */ 175339213Sgibbs first = 1; 175439213Sgibbs if (ISSET(lflag, ICANON | ISIG)) 1755169562Sscottl goto slowcase; 175642378Smjacob for (;;) { 175739213Sgibbs char ibuf[IBUFSIZ]; 175842378Smjacob int icc; 175942378Smjacob 1760119708Sken icc = imin(uio->uio_resid, IBUFSIZ); 1761119708Sken icc = q_to_b(qp, ibuf, icc); 1762119708Sken if (icc <= 0) { 1763119708Sken if (first) 1764119708Sken goto loop; 176542378Smjacob break; 176640020Sken } 176742378Smjacob error = uiomove(ibuf, icc, uio); 176842378Smjacob /* 176942378Smjacob * XXX if there was an error then we should ungetc() the 177042378Smjacob * unmoved chars and reduce icc here. 177142378Smjacob */ 177242378Smjacob if (error) 177342378Smjacob break; 177442378Smjacob if (uio->uio_resid == 0) 177542378Smjacob break; 1776168752Sscottl first = 0; 177742378Smjacob } 177839213Sgibbs goto out; 177939213Sgibbsslowcase: 178039213Sgibbs for (;;) { 178139213Sgibbs c = getc(qp); 178239213Sgibbs if (c < 0) { 178339213Sgibbs if (first) 178439213Sgibbs goto loop; 178539213Sgibbs break; 178639213Sgibbs } 178739213Sgibbs /* 178842378Smjacob * delayed suspend (^Y) 178942378Smjacob */ 179039213Sgibbs if (CCEQ(cc[VDSUSP], c) && 179139213Sgibbs ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) { 179239213Sgibbs if (tp->t_pgrp != NULL) { 179339213Sgibbs PGRP_LOCK(tp->t_pgrp); 1794111206Sken pgsignal(tp->t_pgrp, SIGTSTP, 1); 1795111206Sken PGRP_UNLOCK(tp->t_pgrp); 1796111206Sken } 1797111206Sken if (first) { 1798111206Sken error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, 1799111206Sken "ttybg3", 0); 1800111206Sken if (error) 1801111206Sken break; 1802111206Sken goto loop; 1803111206Sken } 1804111206Sken break; 1805111206Sken } 1806111206Sken /* 1807111206Sken * Interpret EOF only in canonical mode. 1808111206Sken */ 180939213Sgibbs if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) 1810111206Sken break; 1811111206Sken /* 1812111206Sken * Give user character. 1813111206Sken */ 1814111206Sken error = ureadc(c, uio); 1815111206Sken if (error) 1816111206Sken /* XXX should ungetc(c, qp). */ 1817111206Sken break; 1818111206Sken if (uio->uio_resid == 0) 1819111206Sken break; 1820111206Sken /* 1821111206Sken * In canonical mode check for a "break character" 1822111206Sken * marking the end of a "line of input". 1823111206Sken */ 1824120599Sphk if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag)) 182539213Sgibbs break; 182639213Sgibbs first = 0; 182739213Sgibbs } 182839213Sgibbs 1829168752Sscottlout: 183039213Sgibbs /* 1831120599Sphk * Look to unblock input now that (presumably) 183239213Sgibbs * the input queue has gone down. 183339213Sgibbs */ 183439213Sgibbs s = spltty(); 1835168752Sscottl if (ISSET(tp->t_state, TS_TBLOCK) && 183639213Sgibbs tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat) 183739213Sgibbs ttyunblock(tp); 183839213Sgibbs splx(s); 183939213Sgibbs 184039213Sgibbs return (error); 184140020Sken} 184239213Sgibbs 1843168752Sscottl/* 1844168752Sscottl * Check the output queue on tp for space for a kernel message (from uprintf 1845168752Sscottl * or tprintf). Allow some space over the normal hiwater mark so we don't 1846168752Sscottl * lose messages due to normal flow control, but don't let the tty run amok. 1847168752Sscottl * Sleeps here are not interruptible, but we return prematurely if new signals 184839213Sgibbs * arrive. 1849111206Sken */ 1850111206Skenint 1851111206Skenttycheckoutq(struct tty *tp, int wait) 1852144135Sken{ 1853144135Sken int hiwat, s; 1854144135Sken sigset_t oldmask; 1855144135Sken struct thread *td; 1856144135Sken struct proc *p; 1857111206Sken 1858111206Sken td = curthread; 1859111206Sken p = td->td_proc; 1860144135Sken hiwat = tp->t_ohiwat; 1861144135Sken SIGEMPTYSET(oldmask); 1862111206Sken s = spltty(); 1863111206Sken if (wait) { 1864168752Sscottl PROC_LOCK(p); 1865168752Sscottl oldmask = td->td_siglist; 1866168752Sscottl PROC_UNLOCK(p); 1867168752Sscottl } 1868168752Sscottl if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) 1869168752Sscottl while (tp->t_outq.c_cc > hiwat) { 1870168752Sscottl ttstart(tp); 187140020Sken if (tp->t_outq.c_cc <= hiwat) 1872141031Ssobomax break; 187339213Sgibbs if (!wait) { 187439213Sgibbs splx(s); 187539213Sgibbs return (0); 187639213Sgibbs } 187739213Sgibbs PROC_LOCK(p); 187839213Sgibbs if (!SIGSETEQ(td->td_siglist, oldmask)) { 1879111206Sken PROC_UNLOCK(p); 1880111206Sken splx(s); 188139213Sgibbs return (0); 1882111206Sken } 1883169562Sscottl PROC_UNLOCK(p); 1884111206Sken SET(tp->t_state, TS_SO_OLOWAT); 188539213Sgibbs tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz); 1886168752Sscottl } 188739213Sgibbs splx(s); 188839213Sgibbs return (1); 188939213Sgibbs} 1890111206Sken 189139213Sgibbs/* 1892169562Sscottl * Process a write call on a tty device. 1893168752Sscottl */ 189439213Sgibbsint 189539213Sgibbsttwrite(struct tty *tp, struct uio *uio, int flag) 1896111206Sken{ 1897111206Sken char *cp = NULL; 1898111206Sken int cc, ce; 1899111206Sken struct thread *td; 1900111206Sken struct proc *p; 1901169562Sscottl int i, hiwat, cnt, error, s; 1902168752Sscottl char obuf[OBUFSIZ]; 1903168752Sscottl 190439213Sgibbs hiwat = tp->t_ohiwat; 1905168752Sscottl cnt = uio->uio_resid; 1906111206Sken error = 0; 1907111206Sken cc = 0; 1908111206Sken td = curthread; 1909111206Sken p = td->td_proc; 1910111206Skenloop: 1911111206Sken s = spltty(); 1912111206Sken if (ISSET(tp->t_state, TS_ZOMBIE)) { 1913111206Sken splx(s); 1914111206Sken if (uio->uio_resid == cnt) 1915111206Sken error = EIO; 1916111206Sken goto out; 1917111206Sken } 1918111206Sken if (!ISSET(tp->t_state, TS_CONNECTED)) { 1919111206Sken if (flag & IO_NDELAY) { 1920111206Sken splx(s); 1921111206Sken error = EWOULDBLOCK; 1922111206Sken goto out; 1923111206Sken } 1924111206Sken error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 1925111206Sken "ttydcd", 0); 1926111206Sken splx(s); 1927111206Sken if (error) 1928111206Sken goto out; 1929111206Sken goto loop; 1930111206Sken } 1931111206Sken splx(s); 1932111206Sken /* 1933111206Sken * Hang the process if it's in the background. 1934111206Sken */ 1935111206Sken sx_slock(&proctree_lock); 1936111206Sken PROC_LOCK(p); 1937111206Sken if (isbackground(p, tp) && 1938111206Sken ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) && 1939111206Sken !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) && 1940111206Sken !SIGISMEMBER(td->td_sigmask, SIGTTOU)) { 1941111206Sken if (p->p_pgrp->pg_jobc == 0) { 1942111206Sken PROC_UNLOCK(p); 1943111206Sken sx_sunlock(&proctree_lock); 1944111206Sken error = EIO; 1945111206Sken goto out; 1946111206Sken } 1947111206Sken PROC_UNLOCK(p); 1948111206Sken PGRP_LOCK(p->p_pgrp); 1949111206Sken sx_sunlock(&proctree_lock); 1950111206Sken pgsignal(p->p_pgrp, SIGTTOU, 1); 1951111206Sken PGRP_UNLOCK(p->p_pgrp); 1952111206Sken error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0); 1953111206Sken if (error) 1954111206Sken goto out; 1955111206Sken goto loop; 1956111206Sken } else { 1957111206Sken PROC_UNLOCK(p); 1958111206Sken sx_sunlock(&proctree_lock); 1959111206Sken } 1960111206Sken /* 1961111206Sken * Process the user's data in at most OBUFSIZ chunks. Perform any 1962111206Sken * output translation. Keep track of high water mark, sleep on 1963111206Sken * overflow awaiting device aid in acquiring new space. 1964111206Sken */ 1965111206Sken while (uio->uio_resid > 0 || cc > 0) { 196639213Sgibbs if (ISSET(tp->t_lflag, FLUSHO)) { 1967168752Sscottl uio->uio_resid = 0; 196839213Sgibbs return (0); 196939213Sgibbs } 197039213Sgibbs if (tp->t_outq.c_cc > hiwat) 197139213Sgibbs goto ovhiwat; 197239213Sgibbs /* 197339213Sgibbs * Grab a hunk of data from the user, unless we have some 1974111206Sken * leftover from last time. 1975111206Sken */ 197639213Sgibbs if (cc == 0) { 1977111206Sken cc = imin(uio->uio_resid, OBUFSIZ); 1978169562Sscottl cp = obuf; 1979111206Sken error = uiomove(cp, cc, uio); 198039213Sgibbs if (error) { 1981168752Sscottl cc = 0; 198239213Sgibbs break; 198339213Sgibbs } 198439213Sgibbs } 1985111206Sken /* 198639213Sgibbs * If nothing fancy need be done, grab those characters we 1987169562Sscottl * can handle without any of ttyoutput's processing and 1988168752Sscottl * just transfer them to the output q. For those chars 198939213Sgibbs * which require special processing (as indicated by the 199039213Sgibbs * bits in char_type), call ttyoutput. After processing 1991111206Sken * a hunk of data, look for FLUSHO so ^O's will take effect 1992111206Sken * immediately. 1993111206Sken */ 1994111206Sken while (cc > 0) { 1995111206Sken if (!ISSET(tp->t_oflag, OPOST)) 1996169562Sscottl ce = cc; 1997168752Sscottl else { 1998168752Sscottl ce = cc - scanc((u_int)cc, (u_char *)cp, 199939213Sgibbs char_type, CCLASSMASK); 2000168752Sscottl /* 200139213Sgibbs * If ce is zero, then we're processing 200239213Sgibbs * a special character through ttyoutput. 200339213Sgibbs */ 200439213Sgibbs if (ce == 0) { 200539213Sgibbs tp->t_rocount = 0; 200639213Sgibbs if (ttyoutput(*cp, tp) >= 0) { 200739213Sgibbs /* No Clists, wait a bit. */ 2008168752Sscottl ttstart(tp); 200939213Sgibbs if (flag & IO_NDELAY) { 201039213Sgibbs error = EWOULDBLOCK; 201139213Sgibbs goto out; 201239213Sgibbs } 201339213Sgibbs error = ttysleep(tp, &lbolt, 201439213Sgibbs TTOPRI|PCATCH, 2015111206Sken "ttybf1", 0); 2016111206Sken if (error) 201739213Sgibbs goto out; 2018111206Sken goto loop; 2019169562Sscottl } 2020111206Sken cp++; 202139213Sgibbs cc--; 2022168752Sscottl if (ISSET(tp->t_lflag, FLUSHO) || 2023168752Sscottl tp->t_outq.c_cc > hiwat) 2024168752Sscottl goto ovhiwat; 2025168752Sscottl continue; 2026168752Sscottl } 2027111206Sken } 202839213Sgibbs /* 2029169562Sscottl * A bunch of normal characters have been found. 2030168752Sscottl * Transfer them en masse to the output queue and 203139213Sgibbs * continue processing at the top of the loop. 203239213Sgibbs * If there are any further characters in this 2033111206Sken * <= OBUFSIZ chunk, the first should be a character 2034111206Sken * requiring special handling by ttyoutput. 2035111206Sken */ 2036111206Sken tp->t_rocount = 0; 2037111206Sken i = b_to_q(cp, ce, &tp->t_outq); 2038169562Sscottl ce -= i; 2039168752Sscottl tp->t_column += ce; 2040168752Sscottl cp += ce, cc -= ce, tk_nout += ce; 204139213Sgibbs tp->t_outcc += ce; 2042168752Sscottl if (i > 0) { 204339213Sgibbs /* No Clists, wait a bit. */ 2044168752Sscottl ttstart(tp); 204539213Sgibbs if (flag & IO_NDELAY) { 204639213Sgibbs error = EWOULDBLOCK; 2047141031Ssobomax goto out; 2048141031Ssobomax } 2049141031Ssobomax error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, 205039213Sgibbs "ttybf2", 0); 205139213Sgibbs if (error) 205239213Sgibbs goto out; 205339213Sgibbs goto loop; 205439213Sgibbs } 205539213Sgibbs if (ISSET(tp->t_lflag, FLUSHO) || 205639213Sgibbs tp->t_outq.c_cc > hiwat) 2057168752Sscottl break; 2058169562Sscottl } 2059168752Sscottl ttstart(tp); 2060168752Sscottl } 206139213Sgibbsout: 206239213Sgibbs /* 206339213Sgibbs * If cc is nonzero, we leave the uio structure inconsistent, as the 206439213Sgibbs * offset and iov pointers have moved forward, but it doesn't matter 206539213Sgibbs * (the call will either return short or restart with a new uio). 206639213Sgibbs */ 206739213Sgibbs uio->uio_resid += cc; 206839213Sgibbs return (error); 206939213Sgibbs 207039213Sgibbsovhiwat: 2071169562Sscottl ttstart(tp); 2072168752Sscottl s = spltty(); 207339213Sgibbs /* 207439213Sgibbs * This can only occur if FLUSHO is set in t_lflag, 207539213Sgibbs * or if ttstart/oproc is synchronous (or very fast). 207639213Sgibbs */ 207739213Sgibbs if (tp->t_outq.c_cc <= hiwat) { 207839213Sgibbs splx(s); 207939213Sgibbs goto loop; 208039213Sgibbs } 208139213Sgibbs if (flag & IO_NDELAY) { 208239213Sgibbs splx(s); 2083169562Sscottl uio->uio_resid += cc; 2084168752Sscottl return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); 208539213Sgibbs } 208639213Sgibbs SET(tp->t_state, TS_SO_OLOWAT); 208739213Sgibbs error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttywri", 208839213Sgibbs tp->t_timeout); 208939213Sgibbs splx(s); 209039213Sgibbs if (error == EWOULDBLOCK) 209139213Sgibbs error = EIO; 209239213Sgibbs if (error) 2093168752Sscottl goto out; 2094141031Ssobomax goto loop; 2095141031Ssobomax} 2096141031Ssobomax 2097141031Ssobomax/* 2098141031Ssobomax * Rubout one character from the rawq of tp 2099141031Ssobomax * as cleanly as possible. 210039213Sgibbs */ 2101169562Sscottlstatic void 210239213Sgibbsttyrub(int c, struct tty *tp) 210339213Sgibbs{ 210439213Sgibbs char *cp; 210539213Sgibbs int savecol; 210639213Sgibbs int tabc, s; 210739213Sgibbs 210839213Sgibbs if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) 2109169562Sscottl return; 2110168752Sscottl CLR(tp->t_lflag, FLUSHO); 2111168752Sscottl if (ISSET(tp->t_lflag, ECHOE)) { 2112168752Sscottl if (tp->t_rocount == 0) { 211339213Sgibbs /* 211439213Sgibbs * Screwed by ttwrite; retype 211539213Sgibbs */ 2116111206Sken ttyretype(tp); 2117111206Sken return; 211839213Sgibbs } 2119169562Sscottl if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) 2120168752Sscottl ttyrubo(tp, 2); 212139213Sgibbs else { 212239213Sgibbs CLR(c, ~TTY_CHARMASK); 212339213Sgibbs switch (CCLASS(c)) { 212439213Sgibbs case ORDINARY: 212539213Sgibbs ttyrubo(tp, 1); 212639213Sgibbs break; 212739213Sgibbs case BACKSPACE: 212839213Sgibbs case CONTROL: 212939213Sgibbs case NEWLINE: 213039213Sgibbs case RETURN: 213190868Smike case VTAB: 213239213Sgibbs if (ISSET(tp->t_lflag, ECHOCTL)) 2133169562Sscottl ttyrubo(tp, 2); 2134168752Sscottl break; 213539213Sgibbs case TAB: 213639213Sgibbs if (tp->t_rocount < tp->t_rawq.c_cc) { 213739213Sgibbs ttyretype(tp); 213839213Sgibbs return; 2139111206Sken } 2140111206Sken s = spltty(); 214139213Sgibbs savecol = tp->t_column; 214239213Sgibbs SET(tp->t_state, TS_CNTTB); 214339213Sgibbs SET(tp->t_lflag, FLUSHO); 214439213Sgibbs tp->t_column = tp->t_rocol; 214539213Sgibbs cp = tp->t_rawq.c_cf; 214639213Sgibbs if (cp) 2147169562Sscottl tabc = *cp; /* XXX FIX NEXTC */ 2148169562Sscottl for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc)) 2149168752Sscottl ttyecho(tabc, tp); 2150168752Sscottl CLR(tp->t_lflag, FLUSHO); 215139213Sgibbs CLR(tp->t_state, TS_CNTTB); 215239213Sgibbs splx(s); 215339213Sgibbs 215439213Sgibbs /* savecol will now be length of the tab. */ 215539213Sgibbs savecol -= tp->t_column; 215639213Sgibbs tp->t_column += savecol; 215739213Sgibbs if (savecol > 8) 215839213Sgibbs savecol = 8; /* overflow screw */ 215939213Sgibbs while (--savecol >= 0) 216039213Sgibbs (void)ttyoutput('\b', tp); 2161169562Sscottl break; 2162169562Sscottl default: /* XXX */ 2163168752Sscottl#define PANICSTR "ttyrub: would panic c = %d, val = %d\n" 216439213Sgibbs (void)printf(PANICSTR, c, CCLASS(c)); 216539213Sgibbs#ifdef notdef 216639213Sgibbs panic(PANICSTR, c, CCLASS(c)); 216739213Sgibbs#endif 2168111206Sken } 2169111206Sken } 217039213Sgibbs } else if (ISSET(tp->t_lflag, ECHOPRT)) { 2171169562Sscottl if (!ISSET(tp->t_state, TS_ERASE)) { 2172169562Sscottl SET(tp->t_state, TS_ERASE); 2173168752Sscottl (void)ttyoutput('\\', tp); 217439213Sgibbs } 217539213Sgibbs ttyecho(c, tp); 217639213Sgibbs } else { 217739213Sgibbs ttyecho(tp->t_cc[VERASE], tp); 217839213Sgibbs /* 217939213Sgibbs * This code may be executed not only when an ERASE key 218039213Sgibbs * is pressed, but also when ^U (KILL) or ^W (WERASE) are. 218139213Sgibbs * So, I didn't think it was worthwhile to pass the extra 218239213Sgibbs * information (which would need an extra parameter, 218339213Sgibbs * changing every call) needed to distinguish the ERASE2 218439213Sgibbs * case from the ERASE. 218539213Sgibbs */ 218639213Sgibbs } 218739213Sgibbs --tp->t_rocount; 218839213Sgibbs} 218939213Sgibbs 219039213Sgibbs/* 219139213Sgibbs * Back over cnt characters, erasing them. 219239213Sgibbs */ 219339213Sgibbsstatic void 2194169562Sscottlttyrubo(struct tty *tp, int cnt) 2195169562Sscottl{ 2196168752Sscottl 219739213Sgibbs while (cnt-- > 0) { 219839213Sgibbs (void)ttyoutput('\b', tp); 219939213Sgibbs (void)ttyoutput(' ', tp); 220039213Sgibbs (void)ttyoutput('\b', tp); 220139213Sgibbs } 220239213Sgibbs} 220339213Sgibbs 220439213Sgibbs/* 220539213Sgibbs * ttyretype -- 220639213Sgibbs * Reprint the rawq line. Note, it is assumed that c_cc has already 220739213Sgibbs * been checked. 220839213Sgibbs */ 220939213Sgibbsstatic void 221039213Sgibbsttyretype(struct tty *tp) 221139213Sgibbs{ 221239213Sgibbs char *cp; 221339213Sgibbs int s, c; 221439213Sgibbs 221539213Sgibbs /* Echo the reprint character. */ 2216169562Sscottl if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 2217169562Sscottl ttyecho(tp->t_cc[VREPRINT], tp); 2218168752Sscottl 221939213Sgibbs (void)ttyoutput('\n', tp); 222039213Sgibbs 222139213Sgibbs /* 222239213Sgibbs * XXX 222339213Sgibbs * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE 222439213Sgibbs * BIT OF FIRST CHAR. 222539213Sgibbs */ 2226111206Sken s = spltty(); 2227111206Sken for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0); 2228111206Sken cp != NULL; cp = nextc(&tp->t_canq, cp, &c)) 222939213Sgibbs ttyecho(c, tp); 2230169562Sscottl for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0); 2231169562Sscottl cp != NULL; cp = nextc(&tp->t_rawq, cp, &c)) 2232168752Sscottl ttyecho(c, tp); 223339213Sgibbs CLR(tp->t_state, TS_ERASE); 223439213Sgibbs splx(s); 223539213Sgibbs 223639213Sgibbs tp->t_rocount = tp->t_rawq.c_cc; 223739213Sgibbs tp->t_rocol = 0; 223839213Sgibbs} 223939213Sgibbs 224039213Sgibbs/* 224139213Sgibbs * Echo a typed character to the terminal. 224239213Sgibbs */ 2243111206Skenstatic void 2244111206Skenttyecho(int c, struct tty *tp) 2245111206Sken{ 224639213Sgibbs 2247169562Sscottl if (!ISSET(tp->t_state, TS_CNTTB)) 2248169562Sscottl CLR(tp->t_lflag, FLUSHO); 2249168752Sscottl if ((!ISSET(tp->t_lflag, ECHO) && 225039213Sgibbs (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) || 225139213Sgibbs ISSET(tp->t_lflag, EXTPROC)) 225239213Sgibbs return; 225339213Sgibbs if (ISSET(tp->t_lflag, ECHOCTL) && 225439213Sgibbs ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') || 225539213Sgibbs ISSET(c, TTY_CHARMASK) == 0177)) { 225639213Sgibbs (void)ttyoutput('^', tp); 225739213Sgibbs CLR(c, ~TTY_CHARMASK); 225839213Sgibbs if (c == 0177) 225939213Sgibbs c = '?'; 226039213Sgibbs else 226139213Sgibbs c += 'A' - 1; 2262168752Sscottl } 226339213Sgibbs (void)ttyoutput(c, tp); 2264169562Sscottl} 2265169562Sscottl 226639213Sgibbs/* 226739213Sgibbs * Wake up any readers on a tty. 226839213Sgibbs */ 226939213Sgibbsvoid 2270111206Skenttwakeup(struct tty *tp) 227139213Sgibbs{ 227239213Sgibbs 227339213Sgibbs if (SEL_WAITING(&tp->t_rsel)) 227439213Sgibbs selwakeup(&tp->t_rsel); 227539213Sgibbs if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL) 2276169562Sscottl pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL)); 2277168752Sscottl wakeup(TSA_HUP_OR_INPUT(tp)); 2278168752Sscottl KNOTE(&tp->t_rsel.si_note, 0); 227939213Sgibbs} 228039213Sgibbs 228139213Sgibbs/* 228239213Sgibbs * Wake up any writers on a tty. 228339213Sgibbs */ 228439213Sgibbsvoid 228539213Sgibbsttwwakeup(struct tty *tp) 2286169562Sscottl{ 228739213Sgibbs 2288168752Sscottl if (SEL_WAITING(&tp->t_wsel) && tp->t_outq.c_cc <= tp->t_olowat) 228939213Sgibbs selwakeup(&tp->t_wsel); 229039213Sgibbs if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL) 229139213Sgibbs pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL)); 229239213Sgibbs if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) == 2293111206Sken TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) { 2294111206Sken CLR(tp->t_state, TS_SO_OCOMPLETE); 229539213Sgibbs wakeup(TSA_OCOMPLETE(tp)); 2296169562Sscottl } 2297168752Sscottl if (ISSET(tp->t_state, TS_SO_OLOWAT) && 229839213Sgibbs tp->t_outq.c_cc <= tp->t_olowat) { 229939213Sgibbs CLR(tp->t_state, TS_SO_OLOWAT); 230039213Sgibbs wakeup(TSA_OLOWAT(tp)); 230139213Sgibbs } 230239213Sgibbs KNOTE(&tp->t_wsel.si_note, 0); 230339213Sgibbs} 230439213Sgibbs 230539213Sgibbs/* 230639213Sgibbs * Look up a code for a specified speed in a conversion table; 230739213Sgibbs * used by drivers to map software speed values to hardware parameters. 230839213Sgibbs */ 230939213Sgibbsint 231039213Sgibbsttspeedtab(int speed, struct speedtab *table) 231139213Sgibbs{ 231239213Sgibbs 231339213Sgibbs for ( ; table->sp_speed != -1; table++) 231439213Sgibbs if (table->sp_speed == speed) 231539213Sgibbs return (table->sp_code); 231639213Sgibbs return (-1); 231739213Sgibbs} 2318169562Sscottl 231939213Sgibbs/* 2320168752Sscottl * Set input and output watermarks and buffer sizes. For input, the 232139213Sgibbs * high watermark is about one second's worth of input above empty, the 232239213Sgibbs * low watermark is slightly below high water, and the buffer size is a 232339213Sgibbs * driver-dependent amount above high water. For output, the watermarks 232439213Sgibbs * are near the ends of the buffer, with about 1 second's worth of input 2325111206Sken * between them. All this only applies to the standard line discipline. 2326111206Sken */ 232739213Sgibbsvoid 2328169562Sscottlttsetwater(struct tty *tp) 2329168752Sscottl{ 233039213Sgibbs int cps, ttmaxhiwat, x; 233139213Sgibbs 233239213Sgibbs /* Input. */ 233339213Sgibbs clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512); 233439213Sgibbs switch (tp->t_ispeedwat) { 233539213Sgibbs case (speed_t)-1: 233639213Sgibbs cps = tp->t_ispeed / 10; 2337169562Sscottl break; 2338168752Sscottl case 0: 233939213Sgibbs /* 234039213Sgibbs * This case is for old drivers that don't know about 234139213Sgibbs * t_ispeedwat. Arrange for them to get the old buffer 234239213Sgibbs * sizes and watermarks. 2343111206Sken */ 2344111206Sken cps = TTYHOG - 2 * 256; 2345111206Sken tp->t_ififosize = 2 * 256; 234639213Sgibbs break; 2347168752Sscottl default: 2348169562Sscottl cps = tp->t_ispeedwat / 10; 2349168752Sscottl break; 2350168752Sscottl } 2351168752Sscottl tp->t_ihiwat = cps; 235239213Sgibbs tp->t_ilowat = 7 * cps / 8; 235339213Sgibbs x = cps + tp->t_ififosize; 235439213Sgibbs clist_alloc_cblocks(&tp->t_rawq, x, x); 2355111206Sken 235639213Sgibbs /* Output. */ 2357169562Sscottl switch (tp->t_ospeedwat) { 2358168752Sscottl case (speed_t)-1: 235939213Sgibbs cps = tp->t_ospeed / 10; 236039213Sgibbs ttmaxhiwat = 2 * TTMAXHIWAT; 2361111206Sken break; 2362111206Sken case 0: 2363111206Sken cps = tp->t_ospeed / 10; 236439213Sgibbs ttmaxhiwat = TTMAXHIWAT; 2365111206Sken break; 236639213Sgibbs default: 2367111206Sken cps = tp->t_ospeedwat / 10; 2368111206Sken ttmaxhiwat = 8 * TTMAXHIWAT; 2369111206Sken break; 2370169562Sscottl } 2371168752Sscottl#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x)) 237239213Sgibbs tp->t_olowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT); 237339213Sgibbs x += cps; 237439213Sgibbs x = CLAMP(x, ttmaxhiwat, TTMINHIWAT); /* XXX clamps are too magic */ 237539213Sgibbs tp->t_ohiwat = roundup(x, CBSIZE); /* XXX for compat */ 237639213Sgibbs x = imax(tp->t_ohiwat, TTMAXHIWAT); /* XXX for compat/safety */ 2377111206Sken x += OBUFSIZ + 100; 2378111206Sken clist_alloc_cblocks(&tp->t_outq, x, x); 237939213Sgibbs#undef CLAMP 2380168752Sscottl} 2381169562Sscottl 2382168752Sscottl/* 2383168752Sscottl * Report on state of foreground process group. 2384168752Sscottl */ 238539213Sgibbsvoid 238639213Sgibbsttyinfo(struct tty *tp) 238739213Sgibbs{ 2388111206Sken struct proc *p, *pick; 238939213Sgibbs struct timeval utime, stime; 2390169562Sscottl const char *stmp, *sprefix; 2391168752Sscottl long ltmp; 239239213Sgibbs int tmp; 239339213Sgibbs struct thread *td; 2394111206Sken 2395111206Sken if (ttycheckoutq(tp,0) == 0) 239639213Sgibbs return; 2397111206Sken 239839213Sgibbs /* Print load average. */ 2399111206Sken tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 2400111206Sken ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); 2401111206Sken 2402169562Sscottl if (tp->t_session == NULL) 2403168752Sscottl ttyprintf(tp, "not a controlling terminal\n"); 240439213Sgibbs else if (tp->t_pgrp == NULL) 240539213Sgibbs ttyprintf(tp, "no foreground process group\n"); 240639213Sgibbs else { 240739213Sgibbs PGRP_LOCK(tp->t_pgrp); 240839213Sgibbs if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) { 2409111206Sken PGRP_UNLOCK(tp->t_pgrp); 2410111206Sken ttyprintf(tp, "empty foreground process group\n"); 241139213Sgibbs } else { 2412168752Sscottl mtx_lock_spin(&sched_lock); 2413169562Sscottl 2414168752Sscottl /* Pick interesting process. */ 2415168752Sscottl for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist)) 2416168752Sscottl if (proc_compare(pick, p)) 241739213Sgibbs pick = p; 241839213Sgibbs PGRP_UNLOCK(tp->t_pgrp); 241939213Sgibbs 2420111206Sken td = FIRST_THREAD_IN_PROC(pick); 242139213Sgibbs sprefix = ""; 2422169562Sscottl if (pick->p_flag & P_THREADED) { 2423168752Sscottl stmp = "KSE" ; /* XXXKSE */ 242439213Sgibbs } else { 242539213Sgibbs if (td) { 2426111206Sken if (TD_ON_RUNQ(td) || 2427111206Sken (TD_IS_RUNNING(td))) { 2428111206Sken stmp = "running"; 2429111206Sken } else if (TD_ON_LOCK(td)) { 243039213Sgibbs stmp = td->td_lockname; 2431111206Sken sprefix = "*"; 2432111206Sken } else if (td->td_wmesg) { 243339213Sgibbs stmp = td->td_wmesg; 2434111206Sken } else { 2435111206Sken stmp = "iowait"; 2436111206Sken } 2437168752Sscottl } else { 2438169562Sscottl stmp = "threadless"; 243939213Sgibbs panic("ttyinfo: no thread!?"); 244039213Sgibbs } 244139213Sgibbs } 244239213Sgibbs calcru(pick, &utime, &stime, NULL); 2443111206Sken if (pick->p_state == PRS_NEW || 2444111206Sken pick->p_state == PRS_ZOMBIE) { 244539213Sgibbs ltmp = 0; 2446168752Sscottl } else { 2447169562Sscottl ltmp = pgtok( 2448168752Sscottl vmspace_resident_count(pick->p_vmspace)); 2449168752Sscottl } 2450168752Sscottl mtx_unlock_spin(&sched_lock); 245139213Sgibbs 245239213Sgibbs ttyprintf(tp, " cmd: %s %d [%s%s] ", pick->p_comm, 245339213Sgibbs pick->p_pid, sprefix, stmp); 2454111206Sken 245539213Sgibbs /* Print user time. */ 2456169562Sscottl ttyprintf(tp, "%ld.%02ldu ", 2457168752Sscottl utime.tv_sec, utime.tv_usec / 10000); 245839213Sgibbs 245939213Sgibbs /* Print system time. */ 2460111206Sken ttyprintf(tp, "%ld.%02lds ", 2461111206Sken (long)stime.tv_sec, stime.tv_usec / 10000); 2462111206Sken 246339213Sgibbs /* Print percentage cpu, resident set size. */ 2464111206Sken ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp); 246539213Sgibbs 2466111206Sken } 2467111206Sken } 2468111206Sken tp->t_rocount = 0; /* so pending input will be retyped if BS */ 2469168752Sscottl} 2470169562Sscottl 247139213Sgibbs/* 247239213Sgibbs * Returns 1 if p2 is "better" than p1 247339213Sgibbs * 247439213Sgibbs * The algorithm for picking the "interesting" process is thus: 2475111206Sken * 2476111206Sken * 1) Only foreground processes are eligible - implied. 247739213Sgibbs * 2) Runnable processes are favored over anything else. The runner 2478168752Sscottl * with the highest cpu utilization is picked (p_estcpu). Ties are 2479169562Sscottl * broken by picking the highest pid. 2480168752Sscottl * 3) The sleeper with the shortest sleep time is next. With ties, 2481168752Sscottl * we pick out just "short-term" sleepers (P_SINTR == 0). 2482168752Sscottl * 4) Further ties are broken by picking the highest pid. 248339213Sgibbs */ 248439213Sgibbs#define ISRUN(p, val) \ 248539213Sgibbsdo { \ 2486111206Sken struct thread *td; \ 248739213Sgibbs val = 0; \ 2488169562Sscottl FOREACH_THREAD_IN_PROC(p, td) { \ 2489168752Sscottl if (TD_ON_RUNQ(td) || \ 249039213Sgibbs TD_IS_RUNNING(td)) { \ 249139213Sgibbs val = 1; \ 2492111206Sken break; \ 2493111206Sken } \ 2494111206Sken } \ 249539213Sgibbs} while (0) 2496111206Sken 249739213Sgibbs#define TESTAB(a, b) ((a)<<1 | (b)) 2498111206Sken#define ONLYA 2 2499111206Sken#define ONLYB 1 2500111206Sken#define BOTH 3 2501169562Sscottl 2502168752Sscottlstatic int 250339213Sgibbsproc_compare(struct proc *p1, struct proc *p2) 250439213Sgibbs{ 250539213Sgibbs 250639213Sgibbs int esta, estb; 2507111206Sken struct ksegrp *kg; 2508111206Sken mtx_assert(&sched_lock, MA_OWNED); 250939213Sgibbs if (p1 == NULL) 2510168752Sscottl return (1); 2511169562Sscottl 2512168752Sscottl ISRUN(p1, esta); 2513168752Sscottl ISRUN(p2, estb); 2514168752Sscottl 251539213Sgibbs /* 251639213Sgibbs * see if at least one of them is runnable 251739213Sgibbs */ 2518111206Sken switch (TESTAB(esta, estb)) { 251939213Sgibbs case ONLYA: 2520169562Sscottl return (0); 2521168752Sscottl case ONLYB: 252239213Sgibbs return (1); 252339213Sgibbs case BOTH: 2524111206Sken /* 2525111206Sken * tie - favor one with highest recent cpu utilization 2526111206Sken */ 2527111206Sken esta = estb = 0; 2528111206Sken FOREACH_KSEGRP_IN_PROC(p1,kg) { 2529111206Sken esta += kg->kg_estcpu; 2530111206Sken } 2531169562Sscottl FOREACH_KSEGRP_IN_PROC(p2,kg) { 2532168752Sscottl estb += kg->kg_estcpu; 253339213Sgibbs } 253439213Sgibbs if (estb > esta) 253539213Sgibbs return (1); 253639213Sgibbs if (esta > estb) 2537111206Sken return (0); 2538111206Sken return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 253939213Sgibbs } 2540168752Sscottl /* 2541169562Sscottl * weed out zombies 2542168752Sscottl */ 2543168752Sscottl switch (TESTAB(p1->p_state == PRS_ZOMBIE, p2->p_state == PRS_ZOMBIE)) { 2544168752Sscottl case ONLYA: 254539213Sgibbs return (1); 254639213Sgibbs case ONLYB: 254739213Sgibbs return (0); 2548111206Sken case BOTH: 254939213Sgibbs return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2550169562Sscottl } 2551168752Sscottl 255239213Sgibbs#if 0 /* XXXKSE */ 255339213Sgibbs /* 2554111206Sken * pick the one with the smallest sleep time 2555111206Sken */ 2556111206Sken if (p2->p_slptime > p1->p_slptime) 2557111206Sken return (0); 2558111206Sken if (p1->p_slptime > p2->p_slptime) 2559111206Sken return (1); 2560111206Sken /* 2561169562Sscottl * favor one sleeping in a non-interruptible sleep 2562168752Sscottl */ 256339213Sgibbs if (p1->p_sflag & PS_SINTR && (p2->p_sflag & PS_SINTR) == 0) 256439213Sgibbs return (1); 256539213Sgibbs if (p2->p_sflag & PS_SINTR && (p1->p_sflag & PS_SINTR) == 0) 256639213Sgibbs return (0); 2567111206Sken#endif 2568111206Sken return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 256939213Sgibbs} 2570111206Sken 2571169562Sscottl/* 2572111206Sken * Output char to tty; console putchar style. 2573111206Sken */ 2574168752Sscottlint 2575168752Sscottltputchar(int c, struct tty *tp) 2576168752Sscottl{ 2577168752Sscottl int s; 2578111206Sken 257939213Sgibbs s = spltty(); 2580169562Sscottl if (!ISSET(tp->t_state, TS_CONNECTED)) { 2581168752Sscottl splx(s); 258239213Sgibbs return (-1); 258339213Sgibbs } 2584111206Sken if (c == '\n') 2585111206Sken (void)ttyoutput('\r', tp); 2586111206Sken (void)ttyoutput(c, tp); 2587111206Sken ttstart(tp); 2588111206Sken splx(s); 2589111206Sken return (0); 2590111206Sken} 2591169562Sscottl 2592168752Sscottl/* 259339213Sgibbs * Sleep on chan, returning ERESTART if tty changed while we napped and 259439213Sgibbs * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If 259539213Sgibbs * the tty is revoked, restarting a pending call will redo validation done 2596168752Sscottl * at the start of the call. 259739213Sgibbs */ 2598168752Sscottlint 259939213Sgibbsttysleep(struct tty *tp, void *chan, int pri, char *wmesg, int timo) 260039213Sgibbs{ 2601168752Sscottl int error; 260239213Sgibbs int gen; 2603168752Sscottl 260439213Sgibbs gen = tp->t_gen; 260539213Sgibbs error = tsleep(chan, pri, wmesg, timo); 2606168752Sscottl if (error) 2607111206Sken return (error); 2608168752Sscottl return (tp->t_gen == gen ? 0 : ERESTART); 260939213Sgibbs} 2610111206Sken 2611168752Sscottl/* 2612111206Sken * Allocate a tty struct. Clists in the struct will be allocated by 2613168752Sscottl * ttyopen(). 2614111206Sken */ 261539213Sgibbsstruct tty * 2616168752Sscottlttymalloc(struct tty *tp) 261739213Sgibbs{ 2618168752Sscottl 261939213Sgibbs if (tp) 262039213Sgibbs return(tp); 2621168752Sscottl tp = malloc(sizeof *tp, M_TTYS, M_WAITOK | M_ZERO); 262239213Sgibbs ttyregister(tp); 2623168752Sscottl return (tp); 262439213Sgibbs} 262539213Sgibbs 2626168752Sscottl#if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */ 262739213Sgibbs/* 2628168752Sscottl * Free a tty struct. Clists in the struct should have been freed by 262939213Sgibbs * ttyclose(). 263039213Sgibbs */ 2631168752Sscottlvoid 263239213Sgibbsttyfree(struct tty *tp) 2633168752Sscottl{ 263439213Sgibbs free(tp, M_TTYS); 263539213Sgibbs} 263639213Sgibbs#endif /* 0 */ 263739213Sgibbs 263839213Sgibbsvoid 263939213Sgibbsttyregister(struct tty *tp) 264039213Sgibbs{ 264139213Sgibbs tp->t_timeout = -1; 264239213Sgibbs SLIST_INSERT_HEAD(&tty_list, tp, t_list); 264339213Sgibbs} 264439213Sgibbs 264539213Sgibbsstatic int 264639213Sgibbssysctl_kern_ttys(SYSCTL_HANDLER_ARGS) 2647105421Snjl{ 2648168752Sscottl struct tty *tp; 2649105421Snjl struct xtty xt; 2650168752Sscottl int error; 2651105421Snjl 2652105421Snjl SLIST_FOREACH(tp, &tty_list, t_list) { 2653168752Sscottl bzero(&xt, sizeof xt); 2654105421Snjl xt.xt_size = sizeof xt; 2655168752Sscottl#define XT_COPY(field) xt.xt_##field = tp->t_##field 2656105421Snjl xt.xt_rawcc = tp->t_rawq.c_cc; 265760422Sken xt.xt_cancc = tp->t_canq.c_cc; 265860422Sken xt.xt_outcc = tp->t_outq.c_cc; 265960422Sken XT_COPY(line); 266060422Sken if (tp->t_dev) 266160422Sken xt.xt_dev = dev2udev(tp->t_dev); 266260422Sken XT_COPY(state); 2663168752Sscottl XT_COPY(flags); 266460422Sken XT_COPY(timeout); 266560422Sken if (tp->t_pgrp) 266660422Sken xt.xt_pgid = tp->t_pgrp->pg_id; 266760422Sken if (tp->t_session) 2668168752Sscottl xt.xt_sid = tp->t_session->s_sid; 266960422Sken XT_COPY(termios); 2670104456Sphk XT_COPY(winsize); 267160422Sken XT_COPY(column); 267260422Sken XT_COPY(rocount); 267360422Sken XT_COPY(rocol); 267460422Sken XT_COPY(ififosize); 267560422Sken XT_COPY(ihiwat); 2676168752Sscottl XT_COPY(ilowat); 267760422Sken XT_COPY(ispeedwat); 2678168752Sscottl XT_COPY(ohiwat); 267960422Sken XT_COPY(olowat); 268060422Sken XT_COPY(ospeedwat); 268160422Sken#undef XT_COPY 268239213Sgibbs error = SYSCTL_OUT(req, &xt, sizeof xt); 2683168752Sscottl if (error) 268439213Sgibbs return (error); 2685168752Sscottl } 268639213Sgibbs return (0); 268739213Sgibbs} 268839213Sgibbs 2689168752SscottlSYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD, 2690168752Sscottl 0, 0, sysctl_kern_ttys, "S,xtty", "All ttys"); 2691168752SscottlSYSCTL_LONG(_kern, OID_AUTO, tty_nin, CTLFLAG_RD, 269239213Sgibbs &tk_nin, 0, "Total TTY in characters"); 2693104456SphkSYSCTL_LONG(_kern, OID_AUTO, tty_nout, CTLFLAG_RD, 2694104456Sphk &tk_nout, 0, "Total TTY out characters"); 2695104456Sphk 2696168752Sscottlvoid 269739213Sgibbsnottystop(struct tty *tp, int rw) 269839213Sgibbs{ 269939213Sgibbs 270039213Sgibbs return; 270139213Sgibbs} 270239213Sgibbs 270339213Sgibbsint 270439213Sgibbsttyread(dev_t dev, struct uio *uio, int flag) 270539213Sgibbs{ 270639213Sgibbs struct tty *tp; 270739213Sgibbs 270839213Sgibbs tp = dev->si_tty; 270939213Sgibbs if (tp == NULL) 271039213Sgibbs return (ENODEV); 271139213Sgibbs return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 271239213Sgibbs} 271339213Sgibbs 271439213Sgibbsint 271539213Sgibbsttywrite(dev_t dev, struct uio *uio, int flag) 271639213Sgibbs{ 271739213Sgibbs struct tty *tp; 271839213Sgibbs 271939213Sgibbs tp = dev->si_tty; 272039213Sgibbs if (tp == NULL) 272139213Sgibbs return (ENODEV); 272239213Sgibbs return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 272339213Sgibbs} 272439213Sgibbs