tty.c revision 8318
195887Sjmallett/*- 290744Sjmallett * Copyright (c) 1982, 1986, 1990, 1991, 1993 390744Sjmallett * The Regents of the University of California. All rights reserved. 490744Sjmallett * (c) UNIX System Laboratories, Inc. 590744Sjmallett * All or some portions of this file are derived from material licensed 690744Sjmallett * to the University of California by American Telephone and Telegraph 790744Sjmallett * Co. or Unix System Laboratories, Inc. and are reproduced herein with 890744Sjmallett * the permission of UNIX System Laboratories, Inc. 990744Sjmallett * 1090744Sjmallett * Redistribution and use in source and binary forms, with or without 1190744Sjmallett * modification, are permitted provided that the following conditions 1290744Sjmallett * are met: 1390744Sjmallett * 1. Redistributions of source code must retain the above copyright 1490744Sjmallett * notice, this list of conditions and the following disclaimer. 1590744Sjmallett * 2. Redistributions in binary form must reproduce the above copyright 1690744Sjmallett * notice, this list of conditions and the following disclaimer in the 1790744Sjmallett * documentation and/or other materials provided with the distribution. 1890744Sjmallett * 3. All advertising materials mentioning features or use of this software 1990744Sjmallett * must display the following acknowledgement: 2090744Sjmallett * This product includes software developed by the University of 2190744Sjmallett * California, Berkeley and its contributors. 2290744Sjmallett * 4. Neither the name of the University nor the names of its contributors 2390744Sjmallett * may be used to endorse or promote products derived from this software 2490744Sjmallett * without specific prior written permission. 2590744Sjmallett * 2690744Sjmallett * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2790744Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2895061Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2995061Sjmallett * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3095061Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31100014Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3290744Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3390744Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3490744Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3590744Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3690744Sjmallett * SUCH DAMAGE. 3790744Sjmallett * 3890744Sjmallett * @(#)tty.c 8.8 (Berkeley) 1/21/94 3990744Sjmallett * $Id: tty.c,v 1.42 1995/04/15 21:04:58 bde Exp $ 4090744Sjmallett */ 4190744Sjmallett 4290744Sjmallett#include "snp.h" 4390744Sjmallett 4490744Sjmallett#include <sys/param.h> 4590744Sjmallett#include <sys/systm.h> 4690744Sjmallett#include <sys/ioctl.h> 4790744Sjmallett#include <sys/proc.h> 4890744Sjmallett#define TTYDEFCHARS 4990744Sjmallett#include <sys/tty.h> 5090744Sjmallett#undef TTYDEFCHARS 5190744Sjmallett#include <sys/file.h> 5290744Sjmallett#include <sys/conf.h> 5390744Sjmallett#include <sys/dkstat.h> 5490744Sjmallett#include <sys/uio.h> 5590744Sjmallett#include <sys/kernel.h> 5690744Sjmallett#include <sys/vnode.h> 57218909Sbrucec#include <sys/syslog.h> 5890744Sjmallett#include <sys/signalvar.h> 5990744Sjmallett#include <sys/resourcevar.h> 6090744Sjmallett#include <sys/malloc.h> 6190744Sjmallett#if NSNP > 0 6290744Sjmallett#include <sys/snoop.h> 6390744Sjmallett#endif 6490744Sjmallett 6590744Sjmallett#include <vm/vm.h> 6690744Sjmallett 6790744Sjmallett 6890744Sjmallettstatic int proc_compare __P((struct proc *p1, struct proc *p2)); 6990744Sjmallettstatic int ttnread __P((struct tty *)); 7090744Sjmallettstatic void ttyblock __P((struct tty *tp)); 7190744Sjmallettstatic void ttyecho __P((int, struct tty *tp)); 7290744Sjmallettstatic void ttyrubo __P((struct tty *, int)); 7395887Sjmallett 7490744Sjmallett/* Symbolic sleep message strings. */ 7590744Sjmallettchar ttclos[] = "ttycls"; 7690744Sjmallettchar ttopen[] = "ttyopn"; 7790744Sjmallettchar ttybg[] = "ttybg"; 7890744Sjmallettchar ttybuf[] = "ttybuf"; 7990744Sjmallettchar ttyin[] = "ttyin"; 8090744Sjmallettchar ttyout[] = "ttyout"; 8190744Sjmallett 8290744Sjmallett/* 8390744Sjmallett * Table with character classes and parity. The 8th bit indicates parity, 8490744Sjmallett * the 7th bit indicates the character is an alphameric or underscore (for 8590744Sjmallett * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits 86100014Sjmallett * are 0 then the character needs no special processing on output; classes 87100014Sjmallett * other than 0 might be translated or (not currently) require delays. 8895887Sjmallett */ 8990744Sjmallett#define E 0x00 /* Even parity. */ 9090744Sjmallett#define O 0x80 /* Odd parity. */ 9190744Sjmallett#define PARITY(c) (char_type[c] & O) 9290744Sjmallett 9390744Sjmallett#define ALPHA 0x40 /* Alpha or underscore. */ 9490744Sjmallett#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA) 9590744Sjmallett 9690744Sjmallett#define CCLASSMASK 0x3f 9790744Sjmallett#define CCLASS(c) (char_type[c] & CCLASSMASK) 9890744Sjmallett 9990744Sjmallett#define BS BACKSPACE 10090744Sjmallett#define CC CONTROL 10190744Sjmallett#define CR RETURN 10290744Sjmallett#define NA ORDINARY | ALPHA 10399939Sjmallett#define NL NEWLINE 10490744Sjmallett#define NO ORDINARY 10590744Sjmallett#define TB TAB 10690744Sjmallett#define VT VTAB 10790744Sjmallett 10890744Sjmallettchar const char_type[] = { 10990744Sjmallett E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */ 11090744Sjmallett O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */ 11190744Sjmallett O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */ 11290744Sjmallett E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */ 11390744Sjmallett O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */ 114100014Sjmallett E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */ 11590744Sjmallett E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */ 11690744Sjmallett O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */ 11790744Sjmallett O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */ 11890744Sjmallett E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */ 11990744Sjmallett E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */ 120100014Sjmallett O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */ 12190744Sjmallett E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */ 12290744Sjmallett O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */ 12390744Sjmallett O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */ 12490744Sjmallett E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */ 12590744Sjmallett /* 12690744Sjmallett * Meta chars; should be settable per character set; 12790744Sjmallett * for now, treat them all as normal characters. 12895887Sjmallett */ 12990744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13090744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13190744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13290744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13390744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13490744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13590744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 136172261Skevlo NA, NA, NA, NA, NA, NA, NA, NA, 13790744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13890744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 13990744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 14090744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 14190744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 14290744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 14390744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 14490744Sjmallett NA, NA, NA, NA, NA, NA, NA, NA, 14595887Sjmallett}; 14690744Sjmallett#undef BS 14790744Sjmallett#undef CC 14890744Sjmallett#undef CR 14990744Sjmallett#undef NA 15090744Sjmallett#undef NL 15190744Sjmallett#undef NO 15290744Sjmallett#undef TB 15390744Sjmallett#undef VT 15490744Sjmallett 15590744Sjmallett/* Macros to clear/set/test flags. */ 15690744Sjmallett#define SET(t, f) (t) |= (f) 15790744Sjmallett#define CLR(t, f) (t) &= ~(f) 15890744Sjmallett#define ISSET(t, f) ((t) & (f)) 15990744Sjmallett 16090744Sjmallett/* 16190744Sjmallett * Initial open of tty, or (re)entry to standard tty line discipline. 162100014Sjmallett */ 16395887Sjmallettint 16490744Sjmallettttyopen(device, tp) 16590744Sjmallett dev_t device; 16690744Sjmallett register struct tty *tp; 16790744Sjmallett{ 16890744Sjmallett int s; 16990744Sjmallett 17090744Sjmallett s = spltty(); 17190744Sjmallett tp->t_dev = device; 17290744Sjmallett if (!ISSET(tp->t_state, TS_ISOPEN)) { 17390744Sjmallett SET(tp->t_state, TS_ISOPEN); 174100014Sjmallett bzero(&tp->t_winsize, sizeof(tp->t_winsize)); 17595887Sjmallett } 17690744Sjmallett CLR(tp->t_state, TS_WOPEN); 17790744Sjmallett 17890744Sjmallett /* 17990744Sjmallett * Initialize or restore a cblock allocation policy suitable for 18090744Sjmallett * the standard line discipline. 18190744Sjmallett */ 18290744Sjmallett clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512); 18390744Sjmallett clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + 200, 512); 184100014Sjmallett clist_alloc_cblocks(&tp->t_rawq, TTYHOG, TTYHOG); 18590744Sjmallett 18690744Sjmallett splx(s); 18790744Sjmallett return (0); 18890744Sjmallett} 18990744Sjmallett 19090744Sjmallett/* 19190744Sjmallett * Handle close() on a tty line: flush and set to initial state, 19290744Sjmallett * bumping generation number so that pending read/write calls 19390744Sjmallett * can detect recycling of the tty. 19495887Sjmallett */ 19590744Sjmallettint 19690744Sjmallettttyclose(tp) 19790744Sjmallett register struct tty *tp; 19890744Sjmallett{ 19990744Sjmallett int s; 20090744Sjmallett 20195095Sjmallett s = spltty(); 20290744Sjmallett if (constty == tp) 20390744Sjmallett constty = NULL; 20490744Sjmallett 205100014Sjmallett ttyflush(tp, FREAD | FWRITE); 20695887Sjmallett clist_free_cblocks(&tp->t_canq); 20790744Sjmallett clist_free_cblocks(&tp->t_outq); 20890744Sjmallett clist_free_cblocks(&tp->t_rawq); 20990744Sjmallett 21090744Sjmallett#if NSNP > 0 21190744Sjmallett if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 21290744Sjmallett snpdown((struct snoop *)tp->t_sc); 21390744Sjmallett#endif 21490744Sjmallett 21590744Sjmallett tp->t_gen++; 21690744Sjmallett tp->t_pgrp = NULL; 21790744Sjmallett tp->t_session = NULL; 21890744Sjmallett tp->t_state = 0; 21990744Sjmallett splx(s); 22090744Sjmallett return (0); 22190744Sjmallett} 22290744Sjmallett 223100014Sjmallett#define FLUSHQ(q) { \ 22495887Sjmallett if ((q)->c_cc) \ 22590744Sjmallett ndflush(q, (q)->c_cc); \ 22690744Sjmallett} 22790744Sjmallett 22890744Sjmallett/* Is 'c' a line delimiter ("break" character)? */ 22990744Sjmallett#define TTBREAKC(c) \ 23090744Sjmallett ((c) == '\n' || (((c) == cc[VEOF] || \ 23190744Sjmallett (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)) 23290744Sjmallett 23390744Sjmallett/*- 23490744Sjmallett * TODO: 23590744Sjmallett * o Fix races for sending the start char in ttyflush(). 23690744Sjmallett * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect(). 23790744Sjmallett * With luck, there will be MIN chars before select() returns(). 23890744Sjmallett * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it. 23999939Sjmallett * o Don't allow input in TS_ZOMBIE case. It would be visible through 24090744Sjmallett * FIONREAD. 24190744Sjmallett * o Do the new sio locking stuff here and use it to avoid special 24290744Sjmallett * case for EXTPROC? 24390744Sjmallett * o Lock PENDIN too? 24490744Sjmallett * o Move EXTPROC and/or PENDIN to t_state? 24590744Sjmallett * o Wrap most of ttioctl in spltty/splx. 24690744Sjmallett * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>. 247100014Sjmallett */ 24895887Sjmallett 24990744Sjmallett 25090744Sjmallett/* 25190744Sjmallett * Process input of a single character received on a tty. 25290744Sjmallett */ 25390744Sjmallettint 25490744Sjmallettttyinput(c, tp) 25590744Sjmallett register int c; 25690744Sjmallett register struct tty *tp; 25790744Sjmallett{ 25890744Sjmallett register int iflag, lflag; 25990744Sjmallett register u_char *cc; 26095887Sjmallett int i, err; 26190744Sjmallett 26290744Sjmallett /* 26395164Sjmallett * If input is pending take it first. 26490744Sjmallett */ 26590744Sjmallett lflag = tp->t_lflag; 26690744Sjmallett if (ISSET(lflag, PENDIN)) 26790744Sjmallett ttypend(tp); 26890744Sjmallett /* 26990744Sjmallett * Gather stats. 27090744Sjmallett */ 27190744Sjmallett if (ISSET(lflag, ICANON)) { 27290744Sjmallett ++tk_cancc; 27390744Sjmallett ++tp->t_cancc; 27490744Sjmallett } else { 27590744Sjmallett ++tk_rawcc; 276100014Sjmallett ++tp->t_rawcc; 27795887Sjmallett } 27890744Sjmallett ++tk_nin; 27990744Sjmallett 28090744Sjmallett /* Handle exceptional conditions (break, parity, framing). */ 28190744Sjmallett cc = tp->t_cc; 28290744Sjmallett iflag = tp->t_iflag; 28390744Sjmallett err = (ISSET(c, TTY_ERRORMASK)); 28490744Sjmallett if (err) { 28590744Sjmallett CLR(c, TTY_ERRORMASK); 28690744Sjmallett if (ISSET(err, TTY_BI)) { /* Break. */ 28790744Sjmallett if (ISSET(iflag, IGNBRK)) 28890744Sjmallett return (0); 28990744Sjmallett else if (ISSET(iflag, BRKINT) && 29090744Sjmallett ISSET(lflag, ISIG) && 29190744Sjmallett (cc[VINTR] != _POSIX_VDISABLE)) 29290744Sjmallett c = cc[VINTR]; 29390744Sjmallett else if (ISSET(iflag, PARMRK)) 29490744Sjmallett goto parmrk; 29590744Sjmallett } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK)) 29690744Sjmallett || ISSET(err, TTY_FE)) { 29790744Sjmallett if (ISSET(iflag, IGNPAR)) 29890744Sjmallett return (0); 29990744Sjmallett else if (ISSET(iflag, PARMRK)) { 30090744Sjmallettparmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); 30190744Sjmallett (void)putc(0 | TTY_QUOTE, &tp->t_rawq); 30290744Sjmallett (void)putc(c | TTY_QUOTE, &tp->t_rawq); 30390744Sjmallett goto endcase; 30490744Sjmallett } else 30590744Sjmallett c = 0; 30690744Sjmallett } 30790744Sjmallett } 30890744Sjmallett /* 309100014Sjmallett * In tandem mode, check high water mark. 31095887Sjmallett */ 31190744Sjmallett if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CRTS_IFLOW)) 31290744Sjmallett ttyblock(tp); 31390744Sjmallett if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP)) 31490744Sjmallett CLR(c, 0x80); 31590744Sjmallett if (!ISSET(lflag, EXTPROC)) { 31690744Sjmallett /* 31790744Sjmallett * Check for literal nexting very first 31890744Sjmallett */ 31990744Sjmallett if (ISSET(tp->t_state, TS_LNCH)) { 32090744Sjmallett SET(c, TTY_QUOTE); 32190744Sjmallett CLR(tp->t_state, TS_LNCH); 32290744Sjmallett } 32390744Sjmallett /* 324100014Sjmallett * Scan for special characters. This code 32590744Sjmallett * is really just a big case statement with 326100014Sjmallett * non-constant cases. The bottom of the 32790744Sjmallett * case statement is labeled ``endcase'', so goto 328100014Sjmallett * it after a case match, or similar. 32990744Sjmallett */ 33090744Sjmallett 33190744Sjmallett /* 33290744Sjmallett * Control chars which aren't controlled 33390744Sjmallett * by ICANON, ISIG, or IXON. 33490744Sjmallett */ 33590744Sjmallett if (ISSET(lflag, IEXTEN)) { 33690744Sjmallett if (CCEQ(cc[VLNEXT], c)) { 33790744Sjmallett if (ISSET(lflag, ECHO)) { 33890744Sjmallett if (ISSET(lflag, ECHOE)) { 33990744Sjmallett (void)ttyoutput('^', tp); 34090744Sjmallett (void)ttyoutput('\b', tp); 34190744Sjmallett } else 34290744Sjmallett ttyecho(c, tp); 34390744Sjmallett } 34490744Sjmallett SET(tp->t_state, TS_LNCH); 34590744Sjmallett goto endcase; 34690744Sjmallett } 34790744Sjmallett if (CCEQ(cc[VDISCARD], c)) { 34890744Sjmallett if (ISSET(lflag, FLUSHO)) 349100014Sjmallett CLR(tp->t_lflag, FLUSHO); 35095887Sjmallett else { 35190744Sjmallett ttyflush(tp, FWRITE); 35290744Sjmallett ttyecho(c, tp); 35390744Sjmallett if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 35490744Sjmallett ttyretype(tp); 355100014Sjmallett SET(tp->t_lflag, FLUSHO); 35690744Sjmallett } 35790744Sjmallett goto startoutput; 35890744Sjmallett } 35990744Sjmallett } 36090744Sjmallett /* 36190744Sjmallett * Signals. 36290744Sjmallett */ 36390744Sjmallett if (ISSET(lflag, ISIG)) { 36490744Sjmallett if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 36590744Sjmallett if (!ISSET(lflag, NOFLSH)) 366100014Sjmallett ttyflush(tp, FREAD | FWRITE); 36795887Sjmallett ttyecho(c, tp); 36890744Sjmallett pgsignal(tp->t_pgrp, 36990744Sjmallett CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 37090744Sjmallett goto endcase; 37190744Sjmallett } 37290744Sjmallett if (CCEQ(cc[VSUSP], c)) { 37390744Sjmallett if (!ISSET(lflag, NOFLSH)) 37490744Sjmallett ttyflush(tp, FREAD); 37590744Sjmallett ttyecho(c, tp); 37690744Sjmallett pgsignal(tp->t_pgrp, SIGTSTP, 1); 37790744Sjmallett goto endcase; 37890744Sjmallett } 37990744Sjmallett } 38090744Sjmallett /* 38190744Sjmallett * Handle start/stop characters. 38290744Sjmallett */ 38390744Sjmallett if (ISSET(iflag, IXON)) { 38490744Sjmallett if (CCEQ(cc[VSTOP], c)) { 38590744Sjmallett if (!ISSET(tp->t_state, TS_TTSTOP)) { 38690744Sjmallett SET(tp->t_state, TS_TTSTOP); 38795887Sjmallett#ifdef sun4c /* XXX */ 38890744Sjmallett (*tp->t_stop)(tp, 0); 38990744Sjmallett#else 39090744Sjmallett (*cdevsw[major(tp->t_dev)].d_stop)(tp, 39190744Sjmallett 0); 39290744Sjmallett#endif 39390744Sjmallett return (0); 39490744Sjmallett } 39590744Sjmallett if (!CCEQ(cc[VSTART], c)) 39690744Sjmallett return (0); 39790744Sjmallett /* 39890744Sjmallett * if VSTART == VSTOP then toggle 39990744Sjmallett */ 40090744Sjmallett goto endcase; 40190744Sjmallett } 40290744Sjmallett if (CCEQ(cc[VSTART], c)) 40390744Sjmallett goto restartoutput; 40490744Sjmallett } 40590744Sjmallett /* 40690744Sjmallett * IGNCR, ICRNL, & INLCR 40790744Sjmallett */ 40890744Sjmallett if (c == '\r') { 40990744Sjmallett if (ISSET(iflag, IGNCR)) 41090744Sjmallett return (0); 41190744Sjmallett else if (ISSET(iflag, ICRNL)) 41290744Sjmallett c = '\n'; 41390744Sjmallett } else if (c == '\n' && ISSET(iflag, INLCR)) 41490744Sjmallett c = '\r'; 41590744Sjmallett } 41690744Sjmallett if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) { 41790744Sjmallett /* 41890744Sjmallett * From here on down canonical mode character 41990744Sjmallett * processing takes place. 42090744Sjmallett */ 42190744Sjmallett /* 42290744Sjmallett * erase (^H / ^?) 42390744Sjmallett */ 42490744Sjmallett if (CCEQ(cc[VERASE], c)) { 42590744Sjmallett if (tp->t_rawq.c_cc) 42690744Sjmallett ttyrub(unputc(&tp->t_rawq), tp); 42790744Sjmallett goto endcase; 42890744Sjmallett } 42990744Sjmallett /* 43090744Sjmallett * kill (^U) 43190744Sjmallett */ 43295887Sjmallett if (CCEQ(cc[VKILL], c)) { 43390744Sjmallett if (ISSET(lflag, ECHOKE) && 43490744Sjmallett tp->t_rawq.c_cc == tp->t_rocount && 43590744Sjmallett !ISSET(lflag, ECHOPRT)) 43690744Sjmallett while (tp->t_rawq.c_cc) 43790744Sjmallett ttyrub(unputc(&tp->t_rawq), tp); 43890744Sjmallett else { 43990744Sjmallett ttyecho(c, tp); 44090744Sjmallett if (ISSET(lflag, ECHOK) || 44190744Sjmallett ISSET(lflag, ECHOKE)) 442100014Sjmallett ttyecho('\n', tp); 44390744Sjmallett FLUSHQ(&tp->t_rawq); 44490744Sjmallett tp->t_rocount = 0; 44590744Sjmallett } 446100014Sjmallett CLR(tp->t_state, TS_LOCAL); 44790744Sjmallett goto endcase; 448100014Sjmallett } 44990744Sjmallett /* 45090744Sjmallett * word erase (^W) 45190744Sjmallett */ 45290744Sjmallett if (CCEQ(cc[VWERASE], c)) { 45390744Sjmallett int alt = ISSET(lflag, ALTWERASE); 45490744Sjmallett int ctype; 45590744Sjmallett 45695887Sjmallett /* 45790744Sjmallett * erase whitespace 45890744Sjmallett */ 45990744Sjmallett while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 46090744Sjmallett ttyrub(c, tp); 46190744Sjmallett if (c == -1) 46290744Sjmallett goto endcase; 46390744Sjmallett /* 46490744Sjmallett * erase last char of word and remember the 46590744Sjmallett * next chars type (for ALTWERASE) 466100014Sjmallett */ 46790744Sjmallett ttyrub(c, tp); 46890744Sjmallett c = unputc(&tp->t_rawq); 46990744Sjmallett if (c == -1) 470100014Sjmallett goto endcase; 47190744Sjmallett if (c == ' ' || c == '\t') { 47290744Sjmallett (void)putc(c, &tp->t_rawq); 47390744Sjmallett goto endcase; 47490744Sjmallett } 47590744Sjmallett ctype = ISALPHA(c); 47690744Sjmallett /* 47790744Sjmallett * erase rest of word 47890744Sjmallett */ 47990744Sjmallett do { 48090744Sjmallett ttyrub(c, tp); 48195887Sjmallett c = unputc(&tp->t_rawq); 48290744Sjmallett if (c == -1) 48390744Sjmallett goto endcase; 48490744Sjmallett } while (c != ' ' && c != '\t' && 48590744Sjmallett (alt == 0 || ISALPHA(c) == ctype)); 48690744Sjmallett (void)putc(c, &tp->t_rawq); 48790744Sjmallett goto endcase; 48890744Sjmallett } 48990744Sjmallett /* 49090744Sjmallett * reprint line (^R) 49190744Sjmallett */ 49290744Sjmallett if (CCEQ(cc[VREPRINT], c)) { 49390744Sjmallett ttyretype(tp); 49490744Sjmallett goto endcase; 49590744Sjmallett } 49690744Sjmallett /* 49790744Sjmallett * ^T - kernel info and generate SIGINFO 49890744Sjmallett */ 49990744Sjmallett if (CCEQ(cc[VSTATUS], c)) { 50090744Sjmallett if (ISSET(lflag, ISIG)) 50190744Sjmallett pgsignal(tp->t_pgrp, SIGINFO, 1); 502129392Sstefanf if (!ISSET(lflag, NOKERNINFO)) 50390744Sjmallett ttyinfo(tp); 50490744Sjmallett goto endcase; 50590744Sjmallett } 50690744Sjmallett } 50790744Sjmallett /* 50890744Sjmallett * Check for input buffer overflow 50990744Sjmallett */ 51090744Sjmallett if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { 51190744Sjmallett if (ISSET(iflag, IMAXBEL)) { 51290744Sjmallett if (tp->t_outq.c_cc < tp->t_hiwat) 51390744Sjmallett (void)ttyoutput(CTRL('g'), tp); 51490744Sjmallett } 51590744Sjmallett goto endcase; 51690744Sjmallett } 51790744Sjmallett 51890744Sjmallett if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP) 51990744Sjmallett && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR)) 52090744Sjmallett (void)putc(0377 | TTY_QUOTE, &tp->t_rawq); 521 522 /* 523 * Put data char in q for user and 524 * wakeup on seeing a line delimiter. 525 */ 526 if (putc(c, &tp->t_rawq) >= 0) { 527 if (!ISSET(lflag, ICANON)) { 528 ttwakeup(tp); 529 ttyecho(c, tp); 530 goto endcase; 531 } 532 if (TTBREAKC(c)) { 533 tp->t_rocount = 0; 534 catq(&tp->t_rawq, &tp->t_canq); 535 ttwakeup(tp); 536 } else if (tp->t_rocount++ == 0) 537 tp->t_rocol = tp->t_column; 538 if (ISSET(tp->t_state, TS_ERASE)) { 539 /* 540 * end of prterase \.../ 541 */ 542 CLR(tp->t_state, TS_ERASE); 543 (void)ttyoutput('/', tp); 544 } 545 i = tp->t_column; 546 ttyecho(c, tp); 547 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) { 548 /* 549 * Place the cursor over the '^' of the ^D. 550 */ 551 i = min(2, tp->t_column - i); 552 while (i > 0) { 553 (void)ttyoutput('\b', tp); 554 i--; 555 } 556 } 557 } 558endcase: 559 /* 560 * IXANY means allow any character to restart output. 561 */ 562 if (ISSET(tp->t_state, TS_TTSTOP) && 563 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) 564 return (0); 565restartoutput: 566 CLR(tp->t_lflag, FLUSHO); 567 CLR(tp->t_state, TS_TTSTOP); 568startoutput: 569 return (ttstart(tp)); 570} 571 572/* 573 * Output a single character on a tty, doing output processing 574 * as needed (expanding tabs, newline processing, etc.). 575 * Returns < 0 if succeeds, otherwise returns char to resend. 576 * Must be recursive. 577 */ 578int 579ttyoutput(c, tp) 580 register int c; 581 register struct tty *tp; 582{ 583 register long oflag; 584 register int col, s; 585 586 oflag = tp->t_oflag; 587 if (!ISSET(oflag, OPOST)) { 588 if (ISSET(tp->t_lflag, FLUSHO)) 589 return (-1); 590 if (putc(c, &tp->t_outq)) 591 return (c); 592 tk_nout++; 593 tp->t_outcc++; 594 return (-1); 595 } 596 /* 597 * Do tab expansion if OXTABS is set. Special case if we external 598 * processing, we don't do the tab expansion because we'll probably 599 * get it wrong. If tab expansion needs to be done, let it happen 600 * externally. 601 */ 602 CLR(c, ~TTY_CHARMASK); 603 if (c == '\t' && 604 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) { 605 c = 8 - (tp->t_column & 7); 606 if (!ISSET(tp->t_lflag, FLUSHO)) { 607 s = spltty(); /* Don't interrupt tabs. */ 608 c -= b_to_q(" ", c, &tp->t_outq); 609 tk_nout += c; 610 tp->t_outcc += c; 611 splx(s); 612 } 613 tp->t_column += c; 614 return (c ? -1 : '\t'); 615 } 616 if (c == CEOT && ISSET(oflag, ONOEOT)) 617 return (-1); 618 619 /* 620 * Newline translation: if ONLCR is set, 621 * translate newline into "\r\n". 622 */ 623 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) { 624 tk_nout++; 625 tp->t_outcc++; 626 if (putc('\r', &tp->t_outq)) 627 return (c); 628 } 629 tk_nout++; 630 tp->t_outcc++; 631 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq)) 632 return (c); 633 634 col = tp->t_column; 635 switch (CCLASS(c)) { 636 case BACKSPACE: 637 if (col > 0) 638 --col; 639 break; 640 case CONTROL: 641 break; 642 case NEWLINE: 643 case RETURN: 644 col = 0; 645 break; 646 case ORDINARY: 647 ++col; 648 break; 649 case TAB: 650 col = (col + 8) & ~7; 651 break; 652 } 653 tp->t_column = col; 654 return (-1); 655} 656 657/* 658 * Ioctls for all tty devices. Called after line-discipline specific ioctl 659 * has been called to do discipline-specific functions and/or reject any 660 * of these ioctl commands. 661 */ 662/* ARGSUSED */ 663int 664ttioctl(tp, cmd, data, flag) 665 register struct tty *tp; 666 int cmd, flag; 667 void *data; 668{ 669 register struct proc *p; 670 int s, error; 671 672 p = curproc; /* XXX */ 673 674 /* If the ioctl involves modification, hang if in the background. */ 675 switch (cmd) { 676 case TIOCFLUSH: 677 case TIOCSETA: 678 case TIOCSETD: 679 case TIOCSETAF: 680 case TIOCSETAW: 681#ifdef notdef 682 case TIOCSPGRP: 683#endif 684 case TIOCSTAT: 685 case TIOCSTI: 686 case TIOCSWINSZ: 687#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 688 case TIOCLBIC: 689 case TIOCLBIS: 690 case TIOCLSET: 691 case TIOCSETC: 692 case OTIOCSETD: 693 case TIOCSETN: 694 case TIOCSETP: 695 case TIOCSLTC: 696#endif 697 while (isbackground(curproc, tp) && 698 p->p_pgrp->pg_jobc && (p->p_flag & P_PPWAIT) == 0 && 699 (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 700 (p->p_sigmask & sigmask(SIGTTOU)) == 0) { 701 pgsignal(p->p_pgrp, SIGTTOU, 1); 702 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, ttybg, 0); 703 if (error) 704 return (error); 705 } 706 break; 707 } 708 709 switch (cmd) { /* Process the ioctl. */ 710 case FIOASYNC: /* set/clear async i/o */ 711 s = spltty(); 712 if (*(int *)data) 713 SET(tp->t_state, TS_ASYNC); 714 else 715 CLR(tp->t_state, TS_ASYNC); 716 splx(s); 717 break; 718 case FIONBIO: /* set/clear non-blocking i/o */ 719 break; /* XXX: delete. */ 720 case FIONREAD: /* get # bytes to read */ 721 *(int *)data = ttnread(tp); 722 break; 723 case TIOCEXCL: /* set exclusive use of tty */ 724 s = spltty(); 725 SET(tp->t_state, TS_XCLUDE); 726 splx(s); 727 break; 728 case TIOCFLUSH: { /* flush buffers */ 729 register int flags = *(int *)data; 730 731 if (flags == 0) 732 flags = FREAD | FWRITE; 733 else 734 flags &= FREAD | FWRITE; 735 ttyflush(tp, flags); 736 break; 737 } 738 case TIOCCONS: /* become virtual console */ 739 if (*(int *)data) { 740 if (constty && constty != tp && 741 ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) == 742 (TS_CARR_ON | TS_ISOPEN)) 743 return (EBUSY); 744#ifndef UCONSOLE 745 if (error = suser(p->p_ucred, &p->p_acflag)) 746 return (error); 747#endif 748 constty = tp; 749 } else if (tp == constty) 750 constty = NULL; 751 break; 752 case TIOCDRAIN: /* wait till output drained */ 753 error = ttywait(tp); 754 if (error) 755 return (error); 756 break; 757 case TIOCGETA: { /* get termios struct */ 758 struct termios *t = (struct termios *)data; 759 760 bcopy(&tp->t_termios, t, sizeof(struct termios)); 761 break; 762 } 763 case TIOCGETD: /* get line discipline */ 764 *(int *)data = tp->t_line; 765 break; 766 case TIOCGWINSZ: /* get window size */ 767 *(struct winsize *)data = tp->t_winsize; 768 break; 769 case TIOCGPGRP: /* get pgrp of tty */ 770 if (!isctty(p, tp)) 771 return (ENOTTY); 772 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 773 break; 774#ifdef TIOCHPCL 775 case TIOCHPCL: /* hang up on last close */ 776 s = spltty(); 777 SET(tp->t_cflag, HUPCL); 778 splx(s); 779 break; 780#endif 781 case TIOCNXCL: /* reset exclusive use of tty */ 782 s = spltty(); 783 CLR(tp->t_state, TS_XCLUDE); 784 splx(s); 785 break; 786 case TIOCOUTQ: /* output queue size */ 787 *(int *)data = tp->t_outq.c_cc; 788 break; 789 case TIOCSETA: /* set termios struct */ 790 case TIOCSETAW: /* drain output, set */ 791 case TIOCSETAF: { /* drn out, fls in, set */ 792 register struct termios *t = (struct termios *)data; 793 794 s = spltty(); 795 if (cmd == TIOCSETAW || cmd == TIOCSETAF) { 796 error = ttywait(tp); 797 if (error) { 798 splx(s); 799 return (error); 800 } 801 if (cmd == TIOCSETAF) 802 ttyflush(tp, FREAD); 803 } 804 if (!ISSET(t->c_cflag, CIGNORE)) { 805 /* 806 * Set device hardware. 807 */ 808 if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 809 splx(s); 810 return (error); 811 } else { 812 if (!ISSET(tp->t_state, TS_CARR_ON) && 813 ISSET(tp->t_cflag, CLOCAL) && 814 !ISSET(t->c_cflag, CLOCAL)) { 815#if 0 816 CLR(tp->t_state, TS_ISOPEN); 817 SET(tp->t_state, TS_WOPEN); 818#endif 819 ttwakeup(tp); 820 } 821 tp->t_cflag = t->c_cflag; 822 tp->t_ispeed = t->c_ispeed; 823 tp->t_ospeed = t->c_ospeed; 824 } 825 ttsetwater(tp); 826 } 827 if (cmd != TIOCSETAF) { 828 if (ISSET(t->c_lflag, ICANON) != 829 ISSET(tp->t_lflag, ICANON)) 830 if (ISSET(t->c_lflag, ICANON)) { 831 SET(tp->t_lflag, PENDIN); 832 ttwakeup(tp); 833 } else { 834 struct clist tq; 835 836 catq(&tp->t_rawq, &tp->t_canq); 837 tq = tp->t_rawq; 838 tp->t_rawq = tp->t_canq; 839 tp->t_canq = tq; 840 CLR(tp->t_lflag, PENDIN); 841 } 842 } 843 tp->t_iflag = t->c_iflag; 844 tp->t_oflag = t->c_oflag; 845 /* 846 * Make the EXTPROC bit read only. 847 */ 848 if (ISSET(tp->t_lflag, EXTPROC)) 849 SET(t->c_lflag, EXTPROC); 850 else 851 CLR(t->c_lflag, EXTPROC); 852 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN); 853 if (t->c_cc[VMIN] != tp->t_cc[VMIN] || 854 t->c_cc[VTIME] != tp->t_cc[VTIME]) 855 ttwakeup(tp); 856 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 857 splx(s); 858 break; 859 } 860 case TIOCSETD: { /* set line discipline */ 861 register int t = *(int *)data; 862 dev_t device = tp->t_dev; 863 864 if ((u_int)t >= nlinesw) 865 return (ENXIO); 866 if (t != tp->t_line) { 867 s = spltty(); 868 (*linesw[tp->t_line].l_close)(tp, flag); 869 error = (*linesw[t].l_open)(device, tp); 870 if (error) { 871 (void)(*linesw[tp->t_line].l_open)(device, tp); 872 splx(s); 873 return (error); 874 } 875 tp->t_line = t; 876 splx(s); 877 } 878 break; 879 } 880 case TIOCSTART: /* start output, like ^Q */ 881 s = spltty(); 882 if (ISSET(tp->t_state, TS_TTSTOP) || 883 ISSET(tp->t_lflag, FLUSHO)) { 884 CLR(tp->t_lflag, FLUSHO); 885 CLR(tp->t_state, TS_TTSTOP); 886 ttstart(tp); 887 } 888 splx(s); 889 break; 890 case TIOCSTI: /* simulate terminal input */ 891 if (p->p_ucred->cr_uid && (flag & FREAD) == 0) 892 return (EPERM); 893 if (p->p_ucred->cr_uid && !isctty(p, tp)) 894 return (EACCES); 895 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp); 896 break; 897 case TIOCSTOP: /* stop output, like ^S */ 898 s = spltty(); 899 if (!ISSET(tp->t_state, TS_TTSTOP)) { 900 SET(tp->t_state, TS_TTSTOP); 901#ifdef sun4c /* XXX */ 902 (*tp->t_stop)(tp, 0); 903#else 904 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 905#endif 906 } 907 splx(s); 908 break; 909 case TIOCSCTTY: /* become controlling tty */ 910 /* Session ctty vnode pointer set in vnode layer. */ 911 if (!SESS_LEADER(p) || 912 ((p->p_session->s_ttyvp || tp->t_session) && 913 (tp->t_session != p->p_session))) 914 return (EPERM); 915 tp->t_session = p->p_session; 916 tp->t_pgrp = p->p_pgrp; 917 p->p_session->s_ttyp = tp; 918 p->p_flag |= P_CONTROLT; 919 break; 920 case TIOCSPGRP: { /* set pgrp of tty */ 921 register struct pgrp *pgrp = pgfind(*(int *)data); 922 923 if (!isctty(p, tp)) 924 return (ENOTTY); 925 else if (pgrp == NULL || pgrp->pg_session != p->p_session) 926 return (EPERM); 927 tp->t_pgrp = pgrp; 928 break; 929 } 930 case TIOCSTAT: /* simulate control-T */ 931 ttyinfo(tp); 932 break; 933 case TIOCSWINSZ: /* set window size */ 934 if (bcmp((caddr_t)&tp->t_winsize, data, 935 sizeof (struct winsize))) { 936 tp->t_winsize = *(struct winsize *)data; 937 pgsignal(tp->t_pgrp, SIGWINCH, 1); 938 } 939 break; 940 case TIOCSDRAINWAIT: 941 error = suser(p->p_ucred, &p->p_acflag); 942 if (error) 943 return (error); 944 tp->t_timeout = *(int *)data * hz; 945 wakeup((caddr_t)&tp->t_outq); 946 break; 947 case TIOCGDRAINWAIT: 948 *(int *)data = tp->t_timeout / hz; 949 break; 950 default: 951#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 952 return (ttcompat(tp, cmd, data, flag)); 953#else 954 return (-1); 955#endif 956 } 957 return (0); 958} 959 960int 961ttyselect(tp, rw, p) 962 struct tty *tp; 963 int rw; 964 struct proc *p; 965{ 966 int nread, s; 967 968 if (tp == NULL) 969 return (ENXIO); 970 971 s = spltty(); 972 switch (rw) { 973 case FREAD: 974 nread = ttnread(tp); 975 if (nread > 0 || (!ISSET(tp->t_cflag, CLOCAL) && 976 !ISSET(tp->t_state, TS_CARR_ON))) 977 goto win; 978 selrecord(p, &tp->t_rsel); 979 break; 980 case FWRITE: 981 if (tp->t_outq.c_cc <= tp->t_lowat) { 982win: splx(s); 983 return (1); 984 } 985 selrecord(p, &tp->t_wsel); 986 break; 987 } 988 splx(s); 989 return (0); 990} 991 992/* 993 * This is a wrapper for compatibility with the select vector used by 994 * cdevsw. It relies on a proper xxxdevtotty routine. 995 */ 996int 997ttselect(dev, rw, p) 998 dev_t dev; 999 int rw; 1000 struct proc *p; 1001{ 1002 return ttyselect((*cdevsw[major(dev)].d_devtotty)(dev), rw, p); 1003} 1004 1005/* 1006 * This is now exported to the cy driver as well; if you hack this code, 1007 * then be sure to keep /sys/i386/isa/cy.c properly advised! -jkh 1008 */ 1009static int 1010ttnread(tp) 1011 struct tty *tp; 1012{ 1013 int nread; 1014 1015 if (ISSET(tp->t_lflag, PENDIN)) 1016 ttypend(tp); 1017 nread = tp->t_canq.c_cc; 1018 if (!ISSET(tp->t_lflag, ICANON)) { 1019 nread += tp->t_rawq.c_cc; 1020 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0) 1021 nread = 0; 1022 } 1023 return (nread); 1024} 1025 1026/* 1027 * Wait for output to drain. 1028 */ 1029int 1030ttywait(tp) 1031 register struct tty *tp; 1032{ 1033 int error, s; 1034 1035 error = 0; 1036 s = spltty(); 1037 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 1038 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) 1039 && tp->t_oproc) { 1040 (*tp->t_oproc)(tp); 1041 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) && 1042 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) { 1043 SET(tp->t_state, TS_ASLEEP); 1044 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, 1045 ttyout, tp->t_timeout); 1046 if (error) 1047 break; 1048 } 1049 } 1050 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY))) 1051 error = EIO; 1052 splx(s); 1053 return (error); 1054} 1055 1056/* 1057 * Flush if successfully wait. 1058 */ 1059int 1060ttywflush(tp) 1061 struct tty *tp; 1062{ 1063 int error; 1064 1065 if ((error = ttywait(tp)) == 0) 1066 ttyflush(tp, FREAD); 1067 return (error); 1068} 1069 1070/* 1071 * Flush tty read and/or write queues, notifying anyone waiting. 1072 */ 1073void 1074ttyflush(tp, rw) 1075 register struct tty *tp; 1076 int rw; 1077{ 1078 register int s; 1079 1080 s = spltty(); 1081 if (rw & FWRITE) 1082 CLR(tp->t_state, TS_TTSTOP); 1083#ifdef sun4c /* XXX */ 1084 (*tp->t_stop)(tp, rw); 1085#else 1086 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 1087#endif 1088 if (rw & FREAD) { 1089 FLUSHQ(&tp->t_canq); 1090 FLUSHQ(&tp->t_rawq); 1091 tp->t_rocount = 0; 1092 tp->t_rocol = 0; 1093 CLR(tp->t_state, TS_LOCAL); 1094 ttwakeup(tp); 1095 } 1096 if (rw & FWRITE) { 1097 FLUSHQ(&tp->t_outq); 1098 wakeup((caddr_t)&tp->t_outq); 1099 selwakeup(&tp->t_wsel); 1100 } 1101 if ((rw & FREAD) && 1102 ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) { 1103 int queue_full = 0; 1104 1105 if (ISSET(tp->t_iflag, IXOFF) && 1106 tp->t_cc[VSTART] != _POSIX_VDISABLE && 1107 (queue_full = putc(tp->t_cc[VSTART], &tp->t_outq)) == 0 || 1108 ISSET(tp->t_cflag, CRTS_IFLOW)) { 1109 CLR(tp->t_state, TS_TBLOCK); 1110 ttstart(tp); 1111 if (queue_full) /* try again */ 1112 SET(tp->t_state, TS_TBLOCK); 1113 } 1114 } 1115 splx(s); 1116} 1117 1118/* 1119 * Copy in the default termios characters. 1120 */ 1121void 1122ttychars(tp) 1123 struct tty *tp; 1124{ 1125 1126 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 1127} 1128 1129/* 1130 * Send stop character on input overflow. 1131 */ 1132static void 1133ttyblock(tp) 1134 register struct tty *tp; 1135{ 1136 register int total; 1137 1138 total = tp->t_rawq.c_cc + tp->t_canq.c_cc; 1139 /* 1140 * Block further input iff: current input > threshold 1141 * AND input is available to user program. 1142 */ 1143 if (total >= TTYHOG / 2 && 1144 !ISSET(tp->t_state, TS_TBLOCK) && 1145 (!ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0)) { 1146 int queue_full = 0; 1147 1148 if (ISSET(tp->t_iflag, IXOFF) && 1149 tp->t_cc[VSTOP] != _POSIX_VDISABLE && 1150 (queue_full = putc(tp->t_cc[VSTOP], &tp->t_outq)) == 0 || 1151 ISSET(tp->t_cflag, CRTS_IFLOW)) { 1152 SET(tp->t_state, TS_TBLOCK); 1153 ttstart(tp); 1154 if (queue_full) /* try again */ 1155 CLR(tp->t_state, TS_TBLOCK); 1156 } 1157 } 1158} 1159 1160void 1161ttrstrt(tp_arg) 1162 void *tp_arg; 1163{ 1164 struct tty *tp; 1165 int s; 1166 1167#ifdef DIAGNOSTIC 1168 if (tp_arg == NULL) 1169 panic("ttrstrt"); 1170#endif 1171 tp = tp_arg; 1172 s = spltty(); 1173 1174 CLR(tp->t_state, TS_TIMEOUT); 1175 ttstart(tp); 1176 1177 splx(s); 1178} 1179 1180int 1181ttstart(tp) 1182 struct tty *tp; 1183{ 1184 1185 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ 1186 (*tp->t_oproc)(tp); 1187 return (0); 1188} 1189 1190/* 1191 * "close" a line discipline 1192 */ 1193int 1194ttylclose(tp, flag) 1195 struct tty *tp; 1196 int flag; 1197{ 1198 1199 if (flag & FNONBLOCK || ttywflush(tp)) 1200 ttyflush(tp, FREAD | FWRITE); 1201 return (0); 1202} 1203 1204/* 1205 * Handle modem control transition on a tty. 1206 * Flag indicates new state of carrier. 1207 * Returns 0 if the line should be turned off, otherwise 1. 1208 */ 1209int 1210ttymodem(tp, flag) 1211 register struct tty *tp; 1212 int flag; 1213{ 1214 1215 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) { 1216 /* 1217 * MDMBUF: do flow control according to carrier flag 1218 */ 1219 if (flag) { 1220 CLR(tp->t_state, TS_TTSTOP); 1221 ttstart(tp); 1222 } else if (!ISSET(tp->t_state, TS_TTSTOP)) { 1223 SET(tp->t_state, TS_TTSTOP); 1224#ifdef sun4c /* XXX */ 1225 (*tp->t_stop)(tp, 0); 1226#else 1227 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 1228#endif 1229 } 1230 } else if (flag == 0) { 1231 /* 1232 * Lost carrier. 1233 */ 1234 CLR(tp->t_state, TS_CARR_ON); 1235 if (ISSET(tp->t_state, TS_ISOPEN) && 1236 !ISSET(tp->t_cflag, CLOCAL)) { 1237 if (tp->t_session && tp->t_session->s_leader) 1238 psignal(tp->t_session->s_leader, SIGHUP); 1239 ttyflush(tp, FREAD | FWRITE); 1240 return (0); 1241 } 1242 } else { 1243 /* 1244 * Carrier now on. 1245 */ 1246 SET(tp->t_state, TS_CARR_ON); 1247 ttwakeup(tp); 1248 } 1249 return (1); 1250} 1251 1252/* 1253 * Default modem control routine (for other line disciplines). 1254 * Return argument flag, to turn off device on carrier drop. 1255 */ 1256int 1257nullmodem(tp, flag) 1258 register struct tty *tp; 1259 int flag; 1260{ 1261 1262 if (flag) 1263 SET(tp->t_state, TS_CARR_ON); 1264 else { 1265 CLR(tp->t_state, TS_CARR_ON); 1266 if (!ISSET(tp->t_cflag, CLOCAL)) { 1267 if (tp->t_session && tp->t_session->s_leader) 1268 psignal(tp->t_session->s_leader, SIGHUP); 1269 return (0); 1270 } 1271 } 1272 return (1); 1273} 1274 1275/* 1276 * Reinput pending characters after state switch 1277 * call at spltty(). 1278 */ 1279void 1280ttypend(tp) 1281 register struct tty *tp; 1282{ 1283 struct clist tq; 1284 register c; 1285 1286 CLR(tp->t_lflag, PENDIN); 1287 SET(tp->t_state, TS_TYPEN); 1288 /* 1289 * XXX this assumes too much about clist internals. It may even 1290 * fail if the cblock slush pool is empty. We can't allocate more 1291 * cblocks here because we are called from an interrupt handler 1292 * and clist_alloc_cblocks() can wait. 1293 */ 1294 tq = tp->t_rawq; 1295 bzero(&tp->t_rawq, sizeof tp->t_rawq); 1296 tp->t_rawq.c_cbmax = tq.c_cbmax; 1297 tp->t_rawq.c_cbreserved = tq.c_cbreserved; 1298 while ((c = getc(&tq)) >= 0) 1299 ttyinput(c, tp); 1300 CLR(tp->t_state, TS_TYPEN); 1301} 1302 1303/* 1304 * Process a read call on a tty device. 1305 */ 1306int 1307ttread(tp, uio, flag) 1308 register struct tty *tp; 1309 struct uio *uio; 1310 int flag; 1311{ 1312 register struct clist *qp; 1313 register int c; 1314 register tcflag_t lflag; 1315 register cc_t *cc = tp->t_cc; 1316 register struct proc *p = curproc; 1317 int s, first, error = 0, carrier; 1318 int has_stime = 0, last_cc = 0; 1319 long slp = 0; /* XXX this should be renamed `timo'. */ 1320 1321loop: 1322 s = spltty(); 1323 lflag = tp->t_lflag; 1324 /* 1325 * take pending input first 1326 */ 1327 if (ISSET(lflag, PENDIN)) { 1328 ttypend(tp); 1329 splx(s); /* reduce latency */ 1330 s = spltty(); 1331 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */ 1332 } 1333 1334 /* 1335 * Hang process if it's in the background. 1336 */ 1337 if (isbackground(p, tp)) { 1338 splx(s); 1339 if ((p->p_sigignore & sigmask(SIGTTIN)) || 1340 (p->p_sigmask & sigmask(SIGTTIN)) || 1341 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) 1342 return (EIO); 1343 pgsignal(p->p_pgrp, SIGTTIN, 1); 1344 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0); 1345 if (error) 1346 return (error); 1347 goto loop; 1348 } 1349 1350 /* 1351 * If canonical, use the canonical queue, 1352 * else use the raw queue. 1353 * 1354 * (should get rid of clists...) 1355 */ 1356 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq; 1357 1358 if (flag & IO_NDELAY) { 1359 if (qp->c_cc > 0) 1360 goto read; 1361 carrier = ISSET(tp->t_state, TS_CARR_ON) || 1362 ISSET(tp->t_cflag, CLOCAL); 1363 if ((!carrier && ISSET(tp->t_state, TS_ISOPEN)) || 1364 !ISSET(lflag, ICANON) && cc[VMIN] == 0) { 1365 splx(s); 1366 return (0); 1367 } 1368 splx(s); 1369 return (EWOULDBLOCK); 1370 } 1371 if (!ISSET(lflag, ICANON)) { 1372 int m = cc[VMIN]; 1373 long t = cc[VTIME]; 1374 struct timeval stime, timecopy; 1375 int x; 1376 1377 /* 1378 * Check each of the four combinations. 1379 * (m > 0 && t == 0) is the normal read case. 1380 * It should be fairly efficient, so we check that and its 1381 * companion case (m == 0 && t == 0) first. 1382 * For the other two cases, we compute the target sleep time 1383 * into slp. 1384 */ 1385 if (t == 0) { 1386 if (qp->c_cc < m) 1387 goto sleep; 1388 if (qp->c_cc > 0) 1389 goto read; 1390 1391 /* m, t and qp->c_cc are all 0. 0 is enough input. */ 1392 splx(s); 1393 return (0); 1394 } 1395 t *= 100000; /* time in us */ 1396#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \ 1397 ((t1).tv_usec - (t2).tv_usec)) 1398 if (m > 0) { 1399 if (qp->c_cc <= 0) 1400 goto sleep; 1401 if (qp->c_cc >= m) 1402 goto read; 1403 x = splclock(); 1404 timecopy = time; 1405 splx(x); 1406 if (!has_stime) { 1407 /* first character, start timer */ 1408 has_stime = 1; 1409 stime = timecopy; 1410 slp = t; 1411 } else if (qp->c_cc > last_cc) { 1412 /* got a character, restart timer */ 1413 stime = timecopy; 1414 slp = t; 1415 } else { 1416 /* nothing, check expiration */ 1417 slp = t - diff(timecopy, stime); 1418 if (slp <= 0) 1419 goto read; 1420 } 1421 last_cc = qp->c_cc; 1422 } else { /* m == 0 */ 1423 if (qp->c_cc > 0) 1424 goto read; 1425 x = splclock(); 1426 timecopy = time; 1427 splx(x); 1428 if (!has_stime) { 1429 has_stime = 1; 1430 stime = timecopy; 1431 slp = t; 1432 } else { 1433 slp = t - diff(timecopy, stime); 1434 if (slp <= 0) { 1435 /* Timed out, but 0 is enough input. */ 1436 splx(s); 1437 return (0); 1438 } 1439 } 1440 } 1441#undef diff 1442 /* 1443 * Rounding down may make us wake up just short 1444 * of the target, so we round up. 1445 * The formula is ceiling(slp * hz/1000000). 1446 * 32-bit arithmetic is enough for hz < 169. 1447 * XXX see hzto() for how to avoid overflow if hz 1448 * is large (divide by `tick' and/or arrange to 1449 * use hzto() if hz is large). 1450 */ 1451 slp = (long) (((u_long)slp * hz) + 999999) / 1000000; 1452 goto sleep; 1453 } 1454 1455 /* 1456 * If there is no input, sleep on rawq 1457 * awaiting hardware receipt and notification. 1458 * If we have data, we don't need to check for carrier. 1459 */ 1460 if (qp->c_cc <= 0) { 1461sleep: 1462 carrier = ISSET(tp->t_state, TS_CARR_ON) || 1463 ISSET(tp->t_cflag, CLOCAL); 1464 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) { 1465 splx(s); 1466 return (0); /* EOF */ 1467 } 1468 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, 1469 carrier ? ttyin : ttopen, (int)slp); 1470 splx(s); 1471 if (error == EWOULDBLOCK) 1472 error = 0; 1473 else if (error) 1474 return (error); 1475 /* 1476 * XXX what happens if another process eats some input 1477 * while we are asleep (not just here)? It would be 1478 * safest to detect changes and reset our state variables 1479 * (has_stime and last_cc). 1480 */ 1481 slp = 0; 1482 goto loop; 1483 } 1484read: 1485 splx(s); 1486 /* 1487 * Input present, check for input mapping and processing. 1488 */ 1489 first = 1; 1490 if (ISSET(lflag, ICANON | ISIG)) 1491 goto slowcase; 1492 for (;;) { 1493 char ibuf[IBUFSIZ]; 1494 int icc; 1495 1496 icc = min(uio->uio_resid, IBUFSIZ); 1497 icc = q_to_b(qp, ibuf, icc); 1498 if (icc <= 0) { 1499 if (first) 1500 goto loop; 1501 break; 1502 } 1503 error = uiomove(ibuf, icc, uio); 1504 /* 1505 * XXX if there was an error then we should ungetc() the 1506 * unmoved chars and reduce icc here. 1507 */ 1508#if NSNP > 0 1509 if (ISSET(tp->t_lflag, ECHO) && 1510 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 1511 snpin((struct snoop *)tp->t_sc, ibuf, icc); 1512#endif 1513 if (error) 1514 break; 1515 if (uio->uio_resid == 0) 1516 break; 1517 first = 0; 1518 } 1519 goto out; 1520slowcase: 1521 for (;;) { 1522 c = getc(qp); 1523 if (c < 0) { 1524 if (first) 1525 goto loop; 1526 break; 1527 } 1528 /* 1529 * delayed suspend (^Y) 1530 */ 1531 if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, ISIG)) { 1532 pgsignal(tp->t_pgrp, SIGTSTP, 1); 1533 if (first) { 1534 error = ttysleep(tp, 1535 &lbolt, TTIPRI | PCATCH, ttybg, 0); 1536 if (error) 1537 break; 1538 goto loop; 1539 } 1540 break; 1541 } 1542 /* 1543 * Interpret EOF only in canonical mode. 1544 */ 1545 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) 1546 break; 1547 /* 1548 * Give user character. 1549 */ 1550 error = ureadc(c, uio); 1551 if (error) 1552 /* XXX should ungetc(c, qp). */ 1553 break; 1554#if NSNP > 0 1555 /* 1556 * Only snoop directly on input in echo mode. Non-echoed 1557 * input will be snooped later iff the application echoes it. 1558 */ 1559 if (ISSET(tp->t_lflag, ECHO) && 1560 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 1561 snpinc((struct snoop *)tp->t_sc, (char)c); 1562#endif 1563 if (uio->uio_resid == 0) 1564 break; 1565 /* 1566 * In canonical mode check for a "break character" 1567 * marking the end of a "line of input". 1568 */ 1569 if (ISSET(lflag, ICANON) && TTBREAKC(c)) 1570 break; 1571 first = 0; 1572 } 1573 /* 1574 * Look to unblock input now that (presumably) 1575 * the input queue has gone down. 1576 */ 1577out: 1578 s = spltty(); 1579 if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) { 1580 int queue_full = 0; 1581 1582 if (ISSET(tp->t_iflag, IXOFF) && 1583 cc[VSTART] != _POSIX_VDISABLE && 1584 (queue_full = putc(cc[VSTART], &tp->t_outq)) == 0 || 1585 ISSET(tp->t_cflag, CRTS_IFLOW)) { 1586 CLR(tp->t_state, TS_TBLOCK); 1587 ttstart(tp); 1588 if (queue_full) /* try again */ 1589 SET(tp->t_state, TS_TBLOCK); 1590 } 1591 } 1592 splx(s); 1593 return (error); 1594} 1595 1596/* 1597 * Check the output queue on tp for space for a kernel message (from uprintf 1598 * or tprintf). Allow some space over the normal hiwater mark so we don't 1599 * lose messages due to normal flow control, but don't let the tty run amok. 1600 * Sleeps here are not interruptible, but we return prematurely if new signals 1601 * arrive. 1602 */ 1603int 1604ttycheckoutq(tp, wait) 1605 register struct tty *tp; 1606 int wait; 1607{ 1608 int hiwat, s, oldsig; 1609 1610 hiwat = tp->t_hiwat; 1611 s = spltty(); 1612 oldsig = wait ? curproc->p_siglist : 0; 1613 if (tp->t_outq.c_cc > hiwat + 200) 1614 while (tp->t_outq.c_cc > hiwat) { 1615 ttstart(tp); 1616 if (wait == 0 || curproc->p_siglist != oldsig) { 1617 splx(s); 1618 return (0); 1619 } 1620 timeout((void (*)__P((void *)))wakeup, 1621 (void *)&tp->t_outq, hz); 1622 SET(tp->t_state, TS_ASLEEP); 1623 (void) tsleep((caddr_t)&tp->t_outq, PZERO - 1, "ttoutq", 0); 1624 } 1625 splx(s); 1626 return (1); 1627} 1628 1629/* 1630 * Process a write call on a tty device. 1631 */ 1632int 1633ttwrite(tp, uio, flag) 1634 register struct tty *tp; 1635 register struct uio *uio; 1636 int flag; 1637{ 1638 register char *cp = 0; 1639 register int cc, ce; 1640 register struct proc *p; 1641 int i, hiwat, cnt, error, s; 1642 char obuf[OBUFSIZ]; 1643 1644 hiwat = tp->t_hiwat; 1645 cnt = uio->uio_resid; 1646 error = 0; 1647 cc = 0; 1648loop: 1649 s = spltty(); 1650 if (!ISSET(tp->t_state, TS_CARR_ON) && 1651 !ISSET(tp->t_cflag, CLOCAL)) { 1652 if (ISSET(tp->t_state, TS_ISOPEN)) { 1653 splx(s); 1654 return (EIO); 1655 } else if (flag & IO_NDELAY) { 1656 splx(s); 1657 error = EWOULDBLOCK; 1658 goto out; 1659 } else { 1660 /* Sleep awaiting carrier. */ 1661 error = ttysleep(tp, 1662 &tp->t_rawq, TTIPRI | PCATCH,ttopen, 0); 1663 splx(s); 1664 if (error) 1665 goto out; 1666 goto loop; 1667 } 1668 } 1669 splx(s); 1670 /* 1671 * Hang the process if it's in the background. 1672 */ 1673 p = curproc; 1674 if (isbackground(p, tp) && 1675 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 && 1676 (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 1677 (p->p_sigmask & sigmask(SIGTTOU)) == 0 && 1678 p->p_pgrp->pg_jobc) { 1679 pgsignal(p->p_pgrp, SIGTTOU, 1); 1680 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0); 1681 if (error) 1682 goto out; 1683 goto loop; 1684 } 1685 /* 1686 * Process the user's data in at most OBUFSIZ chunks. Perform any 1687 * output translation. Keep track of high water mark, sleep on 1688 * overflow awaiting device aid in acquiring new space. 1689 */ 1690 while (uio->uio_resid > 0 || cc > 0) { 1691 if (ISSET(tp->t_lflag, FLUSHO)) { 1692 uio->uio_resid = 0; 1693 return (0); 1694 } 1695 if (tp->t_outq.c_cc > hiwat) 1696 goto ovhiwat; 1697 /* 1698 * Grab a hunk of data from the user, unless we have some 1699 * leftover from last time. 1700 */ 1701 if (cc == 0) { 1702 cc = min(uio->uio_resid, OBUFSIZ); 1703 cp = obuf; 1704 error = uiomove(cp, cc, uio); 1705 if (error) { 1706 cc = 0; 1707 break; 1708 } 1709#if NSNP > 0 1710 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL) 1711 snpin((struct snoop *)tp->t_sc, cp, cc); 1712#endif 1713 } 1714 /* 1715 * If nothing fancy need be done, grab those characters we 1716 * can handle without any of ttyoutput's processing and 1717 * just transfer them to the output q. For those chars 1718 * which require special processing (as indicated by the 1719 * bits in char_type), call ttyoutput. After processing 1720 * a hunk of data, look for FLUSHO so ^O's will take effect 1721 * immediately. 1722 */ 1723 while (cc > 0) { 1724 if (!ISSET(tp->t_oflag, OPOST)) 1725 ce = cc; 1726 else { 1727 ce = cc - scanc((u_int)cc, (u_char *)cp, 1728 (u_char *)char_type, CCLASSMASK); 1729 /* 1730 * If ce is zero, then we're processing 1731 * a special character through ttyoutput. 1732 */ 1733 if (ce == 0) { 1734 tp->t_rocount = 0; 1735 if (ttyoutput(*cp, tp) >= 0) { 1736 /* No Clists, wait a bit. */ 1737 ttstart(tp); 1738 if (flag & IO_NDELAY) { 1739 error = EWOULDBLOCK; 1740 goto out; 1741 } 1742 error = ttysleep(tp, &lbolt, 1743 TTOPRI | PCATCH, ttybuf, 0); 1744 if (error) 1745 goto out; 1746 goto loop; 1747 } 1748 cp++; 1749 cc--; 1750 if (ISSET(tp->t_lflag, FLUSHO) || 1751 tp->t_outq.c_cc > hiwat) 1752 goto ovhiwat; 1753 continue; 1754 } 1755 } 1756 /* 1757 * A bunch of normal characters have been found. 1758 * Transfer them en masse to the output queue and 1759 * continue processing at the top of the loop. 1760 * If there are any further characters in this 1761 * <= OBUFSIZ chunk, the first should be a character 1762 * requiring special handling by ttyoutput. 1763 */ 1764 tp->t_rocount = 0; 1765 i = b_to_q(cp, ce, &tp->t_outq); 1766 ce -= i; 1767 tp->t_column += ce; 1768 cp += ce, cc -= ce, tk_nout += ce; 1769 tp->t_outcc += ce; 1770 if (i > 0) { 1771 /* No Clists, wait a bit. */ 1772 ttstart(tp); 1773 if (flag & IO_NDELAY) { 1774 error = EWOULDBLOCK; 1775 goto out; 1776 } 1777 error = ttysleep(tp, 1778 &lbolt, TTOPRI | PCATCH, ttybuf, 0); 1779 if (error) 1780 goto out; 1781 goto loop; 1782 } 1783 if (ISSET(tp->t_lflag, FLUSHO) || 1784 tp->t_outq.c_cc > hiwat) 1785 break; 1786 } 1787 ttstart(tp); 1788 } 1789out: 1790 /* 1791 * If cc is nonzero, we leave the uio structure inconsistent, as the 1792 * offset and iov pointers have moved forward, but it doesn't matter 1793 * (the call will either return short or restart with a new uio). 1794 */ 1795 uio->uio_resid += cc; 1796 return (error); 1797 1798ovhiwat: 1799 ttstart(tp); 1800 s = spltty(); 1801 /* 1802 * This can only occur if FLUSHO is set in t_lflag, 1803 * or if ttstart/oproc is synchronous (or very fast). 1804 */ 1805 if (tp->t_outq.c_cc <= hiwat) { 1806 splx(s); 1807 goto loop; 1808 } 1809 if (flag & IO_NDELAY) { 1810 splx(s); 1811 uio->uio_resid += cc; 1812 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); 1813 } 1814 SET(tp->t_state, TS_ASLEEP); 1815 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 1816 splx(s); 1817 if (error) 1818 goto out; 1819 goto loop; 1820} 1821 1822/* 1823 * Rubout one character from the rawq of tp 1824 * as cleanly as possible. 1825 */ 1826void 1827ttyrub(c, tp) 1828 register int c; 1829 register struct tty *tp; 1830{ 1831 register char *cp; 1832 register int savecol; 1833 int tabc, s; 1834 1835 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) 1836 return; 1837 CLR(tp->t_lflag, FLUSHO); 1838 if (ISSET(tp->t_lflag, ECHOE)) { 1839 if (tp->t_rocount == 0) { 1840 /* 1841 * Screwed by ttwrite; retype 1842 */ 1843 ttyretype(tp); 1844 return; 1845 } 1846 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) 1847 ttyrubo(tp, 2); 1848 else { 1849 CLR(c, ~TTY_CHARMASK); 1850 switch (CCLASS(c)) { 1851 case ORDINARY: 1852 ttyrubo(tp, 1); 1853 break; 1854 case BACKSPACE: 1855 case CONTROL: 1856 case NEWLINE: 1857 case RETURN: 1858 case VTAB: 1859 if (ISSET(tp->t_lflag, ECHOCTL)) 1860 ttyrubo(tp, 2); 1861 break; 1862 case TAB: 1863 if (tp->t_rocount < tp->t_rawq.c_cc) { 1864 ttyretype(tp); 1865 return; 1866 } 1867 s = spltty(); 1868 savecol = tp->t_column; 1869 SET(tp->t_state, TS_CNTTB); 1870 SET(tp->t_lflag, FLUSHO); 1871 tp->t_column = tp->t_rocol; 1872 cp = tp->t_rawq.c_cf; 1873 if (cp) 1874 tabc = *cp; /* XXX FIX NEXTC */ 1875 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc)) 1876 ttyecho(tabc, tp); 1877 CLR(tp->t_lflag, FLUSHO); 1878 CLR(tp->t_state, TS_CNTTB); 1879 splx(s); 1880 1881 /* savecol will now be length of the tab. */ 1882 savecol -= tp->t_column; 1883 tp->t_column += savecol; 1884 if (savecol > 8) 1885 savecol = 8; /* overflow screw */ 1886 while (--savecol >= 0) 1887 (void)ttyoutput('\b', tp); 1888 break; 1889 default: /* XXX */ 1890#define PANICSTR "ttyrub: would panic c = %d, val = %d\n" 1891 (void)printf(PANICSTR, c, CCLASS(c)); 1892#ifdef notdef 1893 panic(PANICSTR, c, CCLASS(c)); 1894#endif 1895 } 1896 } 1897 } else if (ISSET(tp->t_lflag, ECHOPRT)) { 1898 if (!ISSET(tp->t_state, TS_ERASE)) { 1899 SET(tp->t_state, TS_ERASE); 1900 (void)ttyoutput('\\', tp); 1901 } 1902 ttyecho(c, tp); 1903 } else 1904 ttyecho(tp->t_cc[VERASE], tp); 1905 --tp->t_rocount; 1906} 1907 1908/* 1909 * Back over cnt characters, erasing them. 1910 */ 1911static void 1912ttyrubo(tp, cnt) 1913 register struct tty *tp; 1914 int cnt; 1915{ 1916 1917 while (cnt-- > 0) { 1918 (void)ttyoutput('\b', tp); 1919 (void)ttyoutput(' ', tp); 1920 (void)ttyoutput('\b', tp); 1921 } 1922} 1923 1924/* 1925 * ttyretype -- 1926 * Reprint the rawq line. Note, it is assumed that c_cc has already 1927 * been checked. 1928 */ 1929void 1930ttyretype(tp) 1931 register struct tty *tp; 1932{ 1933 register char *cp; 1934 int s, c; 1935 1936 /* Echo the reprint character. */ 1937 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 1938 ttyecho(tp->t_cc[VREPRINT], tp); 1939 1940 (void)ttyoutput('\n', tp); 1941 1942 /* 1943 * XXX 1944 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE 1945 * BIT OF FIRST CHAR. 1946 */ 1947 s = spltty(); 1948 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0); 1949 cp != NULL; cp = nextc(&tp->t_canq, cp, &c)) 1950 ttyecho(c, tp); 1951 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0); 1952 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c)) 1953 ttyecho(c, tp); 1954 CLR(tp->t_state, TS_ERASE); 1955 splx(s); 1956 1957 tp->t_rocount = tp->t_rawq.c_cc; 1958 tp->t_rocol = 0; 1959} 1960 1961/* 1962 * Echo a typed character to the terminal. 1963 */ 1964static void 1965ttyecho(c, tp) 1966 register int c; 1967 register struct tty *tp; 1968{ 1969 1970 if (!ISSET(tp->t_state, TS_CNTTB)) 1971 CLR(tp->t_lflag, FLUSHO); 1972 if ((!ISSET(tp->t_lflag, ECHO) && 1973 (!ISSET(tp->t_lflag, ECHONL) || c == '\n')) || 1974 ISSET(tp->t_lflag, EXTPROC)) 1975 return; 1976 if (ISSET(tp->t_lflag, ECHOCTL) && 1977 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') || 1978 ISSET(c, TTY_CHARMASK) == 0177)) { 1979 (void)ttyoutput('^', tp); 1980 CLR(c, ~TTY_CHARMASK); 1981 if (c == 0177) 1982 c = '?'; 1983 else 1984 c += 'A' - 1; 1985 } 1986 (void)ttyoutput(c, tp); 1987} 1988 1989/* 1990 * Wake up any readers on a tty. 1991 */ 1992void 1993ttwakeup(tp) 1994 register struct tty *tp; 1995{ 1996 1997 selwakeup(&tp->t_rsel); 1998 if (ISSET(tp->t_state, TS_ASYNC)) 1999 pgsignal(tp->t_pgrp, SIGIO, 1); 2000 wakeup((caddr_t)&tp->t_rawq); 2001} 2002 2003/* 2004 * Look up a code for a specified speed in a conversion table; 2005 * used by drivers to map software speed values to hardware parameters. 2006 */ 2007int 2008ttspeedtab(speed, table) 2009 int speed; 2010 register struct speedtab *table; 2011{ 2012 2013 for ( ; table->sp_speed != -1; table++) 2014 if (table->sp_speed == speed) 2015 return (table->sp_code); 2016 return (-1); 2017} 2018 2019/* 2020 * Set tty hi and low water marks. 2021 * 2022 * Try to arrange the dynamics so there's about one second 2023 * from hi to low water. 2024 * 2025 */ 2026void 2027ttsetwater(tp) 2028 struct tty *tp; 2029{ 2030 register int cps, x; 2031 2032#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x)) 2033 2034 cps = tp->t_ospeed / 10; 2035 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT); 2036 x += cps; 2037 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT); 2038 tp->t_hiwat = roundup(x, CBSIZE); 2039#undef CLAMP 2040} 2041 2042/* 2043 * Report on state of foreground process group. 2044 */ 2045void 2046ttyinfo(tp) 2047 register struct tty *tp; 2048{ 2049 register struct proc *p, *pick; 2050 struct timeval utime, stime; 2051 int tmp; 2052 2053 if (ttycheckoutq(tp,0) == 0) 2054 return; 2055 2056 /* Print load average. */ 2057 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 2058 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); 2059 2060 if (tp->t_session == NULL) 2061 ttyprintf(tp, "not a controlling terminal\n"); 2062 else if (tp->t_pgrp == NULL) 2063 ttyprintf(tp, "no foreground process group\n"); 2064 else if ((p = tp->t_pgrp->pg_mem) == NULL) 2065 ttyprintf(tp, "empty foreground process group\n"); 2066 else { 2067 /* Pick interesting process. */ 2068 for (pick = NULL; p != NULL; p = p->p_pgrpnxt) 2069 if (proc_compare(pick, p)) 2070 pick = p; 2071 2072 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid, 2073 pick->p_stat == SRUN ? "running" : 2074 pick->p_wmesg ? pick->p_wmesg : "iowait"); 2075 2076 calcru(pick, &utime, &stime, NULL); 2077 2078 /* Print user time. */ 2079 ttyprintf(tp, "%d.%02du ", 2080 utime.tv_sec, utime.tv_usec / 10000); 2081 2082 /* Print system time. */ 2083 ttyprintf(tp, "%d.%02ds ", 2084 stime.tv_sec, stime.tv_usec / 10000); 2085 2086#define pgtok(a) (((a) * NBPG) / 1024) 2087 /* Print percentage cpu, resident set size. */ 2088 tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT; 2089 ttyprintf(tp, "%d%% %dk\n", 2090 tmp / 100, 2091 pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 : 2092#ifdef pmap_resident_count 2093 pgtok(pmap_resident_count(&pick->p_vmspace->vm_pmap)) 2094#else 2095 pgtok(pick->p_vmspace->vm_rssize) 2096#endif 2097 ); 2098 } 2099 tp->t_rocount = 0; /* so pending input will be retyped if BS */ 2100} 2101 2102/* 2103 * Returns 1 if p2 is "better" than p1 2104 * 2105 * The algorithm for picking the "interesting" process is thus: 2106 * 2107 * 1) Only foreground processes are eligible - implied. 2108 * 2) Runnable processes are favored over anything else. The runner 2109 * with the highest cpu utilization is picked (p_estcpu). Ties are 2110 * broken by picking the highest pid. 2111 * 3) The sleeper with the shortest sleep time is next. With ties, 2112 * we pick out just "short-term" sleepers (P_SINTR == 0). 2113 * 4) Further ties are broken by picking the highest pid. 2114 */ 2115#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL)) 2116#define TESTAB(a, b) ((a)<<1 | (b)) 2117#define ONLYA 2 2118#define ONLYB 1 2119#define BOTH 3 2120 2121static int 2122proc_compare(p1, p2) 2123 register struct proc *p1, *p2; 2124{ 2125 2126 if (p1 == NULL) 2127 return (1); 2128 /* 2129 * see if at least one of them is runnable 2130 */ 2131 switch (TESTAB(ISRUN(p1), ISRUN(p2))) { 2132 case ONLYA: 2133 return (0); 2134 case ONLYB: 2135 return (1); 2136 case BOTH: 2137 /* 2138 * tie - favor one with highest recent cpu utilization 2139 */ 2140 if (p2->p_estcpu > p1->p_estcpu) 2141 return (1); 2142 if (p1->p_estcpu > p2->p_estcpu) 2143 return (0); 2144 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2145 } 2146 /* 2147 * weed out zombies 2148 */ 2149 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) { 2150 case ONLYA: 2151 return (1); 2152 case ONLYB: 2153 return (0); 2154 case BOTH: 2155 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2156 } 2157 /* 2158 * pick the one with the smallest sleep time 2159 */ 2160 if (p2->p_slptime > p1->p_slptime) 2161 return (0); 2162 if (p1->p_slptime > p2->p_slptime) 2163 return (1); 2164 /* 2165 * favor one sleeping in a non-interruptible sleep 2166 */ 2167 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0) 2168 return (1); 2169 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0) 2170 return (0); 2171 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 2172} 2173 2174/* 2175 * Output char to tty; console putchar style. 2176 */ 2177int 2178tputchar(c, tp) 2179 int c; 2180 struct tty *tp; 2181{ 2182 register int s; 2183 2184 s = spltty(); 2185 if (ISSET(tp->t_state, 2186 TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) { 2187 splx(s); 2188 return (-1); 2189 } 2190 if (c == '\n') 2191 (void)ttyoutput('\r', tp); 2192 (void)ttyoutput(c, tp); 2193 ttstart(tp); 2194 splx(s); 2195 return (0); 2196} 2197 2198/* 2199 * Sleep on chan, returning ERESTART if tty changed while we napped and 2200 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If 2201 * the tty is revoked, restarting a pending call will redo validation done 2202 * at the start of the call. 2203 */ 2204int 2205ttysleep(tp, chan, pri, wmesg, timo) 2206 struct tty *tp; 2207 void *chan; 2208 int pri, timo; 2209 char *wmesg; 2210{ 2211 int error; 2212 short gen; 2213 2214 gen = tp->t_gen; 2215 error = tsleep(chan, pri, wmesg, timo); 2216 if (error) 2217 return (error); 2218 return (tp->t_gen == gen ? 0 : ERESTART); 2219} 2220 2221/* 2222 * XXX this is usable not useful or used. Most tty drivers have 2223 * ifdefs for using ttymalloc() but assume a different interface. 2224 */ 2225/* 2226 * Allocate a tty struct. Clists in the struct will be allocated by 2227 * ttyopen(). 2228 */ 2229struct tty * 2230ttymalloc() 2231{ 2232 struct tty *tp; 2233 2234 tp = malloc(sizeof *tp, M_TTYS, M_WAITOK); 2235 bzero(tp, sizeof *tp); 2236 return (tp); 2237} 2238 2239#if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */ 2240/* 2241 * Free a tty struct. Clists in the struct should have been freed by 2242 * ttyclose(). 2243 */ 2244void 2245ttyfree(tp) 2246 struct tty *tp; 2247{ 2248 free(tp, M_TTYS); 2249} 2250#endif /* 0 */ 2251