123387Smckusick /* 240712Skarels * Copyright (c) 1982, 1986, 1990 Regents of the University of California. 323387Smckusick * All rights reserved. The Berkeley software License Agreement 423387Smckusick * specifies the terms and conditions for redistribution. 523387Smckusick * 6*45007Smarc * @(#)tty.c 7.35 (Berkeley) 07/27/90 723387Smckusick */ 839Sbill 917095Sbloom #include "param.h" 1017095Sbloom #include "systm.h" 1117095Sbloom #include "user.h" 1217095Sbloom #include "ioctl.h" 1339407Smarc #define TTYDEFCHARS 1417095Sbloom #include "tty.h" 1535811Smarc #undef TTYDEFCHARS 1617095Sbloom #include "proc.h" 1717095Sbloom #include "file.h" 1817095Sbloom #include "conf.h" 1929946Skarels #include "dkstat.h" 2017095Sbloom #include "uio.h" 2117095Sbloom #include "kernel.h" 2237728Smckusick #include "vnode.h" 2335811Smarc #include "syslog.h" 2439Sbill 2537525Smckusick #include "machine/reg.h" 2637525Smckusick 2740712Skarels /* symbolic sleep message strings */ 2840712Skarels char ttyin[] = "ttyin"; 2940712Skarels char ttyout[] = "ttyout"; 3041370Smarc char ttopen[] = "ttyopn"; 3141370Smarc char ttclos[] = "ttycls"; 3240712Skarels char ttybg[] = "ttybg"; 3340712Skarels char ttybuf[] = "ttybuf"; 3440712Skarels 357436Skre /* 367436Skre * Table giving parity for characters and indicating 3735811Smarc * character classes to tty driver. The 8th bit 3835811Smarc * indicates parity, the 7th bit indicates the character 3935811Smarc * is an alphameric or underscore (for ALTWERASE), and the 4035811Smarc * low 6 bits indicate delay type. If the low 6 bits are 0 4135811Smarc * then the character needs no special processing on output. 427436Skre */ 4339Sbill 447436Skre char partab[] = { 4535811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 4635811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 4735811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 4835811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 4935811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 5035811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 5135811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 5235811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 5335811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 5435811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 5535811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 5635811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 5735811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 5835811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 5935811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 6035811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 617436Skre /* 6235811Smarc * meta chars 637436Skre */ 6435811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 6535811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 6635811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 6735811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 6835811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 6935811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 7035811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 7135811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 7235811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 7335811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 7435811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 7535811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 7635811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 7735811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 7835811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 7935811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 807436Skre }; 817436Skre 8235811Smarc extern struct tty *constty; /* temporary virtual console */ 8335811Smarc extern char partab[], maptab[]; 8435811Smarc 85146Sbill /* 8635811Smarc * Is 'c' a line delimiter ("break" character)? 8739Sbill */ 8840712Skarels #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \ 8940712Skarels (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE) 9039Sbill 9139Sbill ttychars(tp) 929578Ssam struct tty *tp; 9339Sbill { 9435811Smarc bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 9539Sbill } 9639Sbill 9739Sbill /* 98903Sbill * Wait for output to drain, then flush input waiting. 9939Sbill */ 10012752Ssam ttywflush(tp) 10137584Smarc struct tty *tp; 10239Sbill { 10340712Skarels int error; 10439Sbill 10540712Skarels if ((error = ttywait(tp)) == 0) 10640712Skarels ttyflush(tp, FREAD); 10740712Skarels return (error); 10812752Ssam } 10912752Ssam 11035811Smarc /* 11135811Smarc * Wait for output to drain. 11235811Smarc */ 11312752Ssam ttywait(tp) 11412752Ssam register struct tty *tp; 11512752Ssam { 11640712Skarels int error = 0, s = spltty(); 11712752Ssam 11813809Ssam while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 11937584Smarc (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 12037584Smarc tp->t_oproc) { 121903Sbill (*tp->t_oproc)(tp); 1225408Swnj tp->t_state |= TS_ASLEEP; 12343377Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_outq, 12443377Smarc TTOPRI | PCATCH, ttyout, 0)) 12540712Skarels break; 126903Sbill } 1279859Ssam splx(s); 12840712Skarels return (error); 12939Sbill } 13039Sbill 13139Sbill /* 1329578Ssam * Flush all TTY queues 13339Sbill */ 13412752Ssam ttyflush(tp, rw) 1357625Ssam register struct tty *tp; 13639Sbill { 137903Sbill register s; 138903Sbill 13917545Skarels s = spltty(); 140903Sbill if (rw & FREAD) { 141903Sbill while (getc(&tp->t_canq) >= 0) 142903Sbill ; 14337584Smarc ttwakeup(tp); 144903Sbill } 145903Sbill if (rw & FWRITE) { 14637584Smarc wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */ 1475408Swnj tp->t_state &= ~TS_TTSTOP; 1485426Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 149903Sbill while (getc(&tp->t_outq) >= 0) 150903Sbill ; 151903Sbill } 152903Sbill if (rw & FREAD) { 153903Sbill while (getc(&tp->t_rawq) >= 0) 154903Sbill ; 1559578Ssam tp->t_rocount = 0; 156903Sbill tp->t_rocol = 0; 1579578Ssam tp->t_state &= ~TS_LOCAL; 158903Sbill } 159903Sbill splx(s); 16039Sbill } 16139Sbill 162903Sbill /* 163903Sbill * Send stop character on input overflow. 164903Sbill */ 165903Sbill ttyblock(tp) 1667625Ssam register struct tty *tp; 16739Sbill { 168903Sbill register x; 1699578Ssam 170903Sbill x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 171903Sbill if (tp->t_rawq.c_cc > TTYHOG) { 17212752Ssam ttyflush(tp, FREAD|FWRITE); 1735408Swnj tp->t_state &= ~TS_TBLOCK; 174903Sbill } 17515118Skarels /* 17615118Skarels * Block further input iff: 17715118Skarels * Current input > threshold AND input is available to user program 17815118Skarels */ 17942350Smckusick if (x >= TTYHOG/2 && (tp->t_state & TS_TBLOCK) == 0 && 18040712Skarels ((tp->t_lflag&ICANON) == 0) || (tp->t_canq.c_cc > 0) && 18135811Smarc tp->t_cc[VSTOP] != _POSIX_VDISABLE) { 18242350Smckusick if (putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) { 18315118Skarels tp->t_state |= TS_TBLOCK; 18415118Skarels ttstart(tp); 18515118Skarels } 186903Sbill } 18739Sbill } 18839Sbill 18939Sbill /* 190903Sbill * Restart typewriter output following a delay 191903Sbill * timeout. 192903Sbill * The name of the routine is passed to the timeout 193903Sbill * subroutine and it is called during a clock interrupt. 194121Sbill */ 195903Sbill ttrstrt(tp) 19637584Smarc struct tty *tp; 197121Sbill { 198121Sbill 19940712Skarels #ifdef DIAGNOSTIC 2009578Ssam if (tp == 0) 2019578Ssam panic("ttrstrt"); 20240712Skarels #endif 2035408Swnj tp->t_state &= ~TS_TIMEOUT; 204903Sbill ttstart(tp); 205121Sbill } 206121Sbill 207121Sbill /* 208903Sbill * Start output on the typewriter. It is used from the top half 209903Sbill * after some characters have been put on the output queue, 210903Sbill * from the interrupt routine to transmit the next 211903Sbill * character, and after a timeout has finished. 21239Sbill */ 213903Sbill ttstart(tp) 21437584Smarc struct tty *tp; 21539Sbill { 21639Sbill 21732067Skarels if (tp->t_oproc) /* kludge for pty */ 218903Sbill (*tp->t_oproc)(tp); 21939Sbill } 22039Sbill 22139Sbill /* 222903Sbill * Common code for tty ioctls. 22339Sbill */ 2241780Sbill /*ARGSUSED*/ 2257625Ssam ttioctl(tp, com, data, flag) 2267625Ssam register struct tty *tp; 2277625Ssam caddr_t data; 22839Sbill { 22939Sbill extern int nldisp; 23037554Smckusick int s, error; 23139Sbill 232903Sbill /* 233903Sbill * If the ioctl involves modification, 23417545Skarels * hang if in the background. 235903Sbill */ 2367625Ssam switch (com) { 23739Sbill 23835811Smarc case TIOCSETD: 239903Sbill case TIOCFLUSH: 24035811Smarc /*case TIOCSPGRP:*/ 2419325Ssam case TIOCSTI: 24217598Sbloom case TIOCSWINSZ: 24335811Smarc case TIOCSETA: 24435811Smarc case TIOCSETAW: 24535811Smarc case TIOCSETAF: 24640030Smarc #ifdef COMPAT_43 24740030Smarc case TIOCSETP: 24840030Smarc case TIOCSETN: 24940030Smarc case TIOCSETC: 25040030Smarc case TIOCSLTC: 25140030Smarc case TIOCLBIS: 25240030Smarc case TIOCLBIC: 25340030Smarc case TIOCLSET: 25440030Smarc case OTIOCSETD: 25540030Smarc #endif 25639555Smarc while (isbackground(u.u_procp, tp) && 25735811Smarc u.u_procp->p_pgrp->pg_jobc && 258903Sbill (u.u_procp->p_flag&SVFORK) == 0 && 25940712Skarels (u.u_procp->p_sigignore & sigmask(SIGTTOU)) == 0 && 26040712Skarels (u.u_procp->p_sigmask & sigmask(SIGTTOU)) == 0) { 26142882Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU, 1); 26243377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 26343377Smarc TTOPRI | PCATCH, ttybg, 0)) 26440712Skarels return (error); 265903Sbill } 266903Sbill break; 267903Sbill } 268903Sbill 2699578Ssam /* 2709578Ssam * Process the ioctl. 2719578Ssam */ 2727625Ssam switch (com) { 273903Sbill 2748556Sroot /* get discipline number */ 27539Sbill case TIOCGETD: 2767625Ssam *(int *)data = tp->t_line; 27739Sbill break; 27839Sbill 2798556Sroot /* set line discipline */ 2807625Ssam case TIOCSETD: { 2817625Ssam register int t = *(int *)data; 28235811Smarc dev_t dev = tp->t_dev; 2837625Ssam 28435811Smarc if ((unsigned)t >= nldisp) 28510851Ssam return (ENXIO); 28625584Skarels if (t != tp->t_line) { 28725584Skarels s = spltty(); 28825584Skarels (*linesw[tp->t_line].l_close)(tp); 28925584Skarels error = (*linesw[t].l_open)(dev, tp); 29025584Skarels if (error) { 29135811Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp); 29225584Skarels splx(s); 29325584Skarels return (error); 29425584Skarels } 29525584Skarels tp->t_line = t; 29610851Ssam splx(s); 29710851Ssam } 29839Sbill break; 2997625Ssam } 30039Sbill 3018556Sroot /* prevent more opens on channel */ 3025614Swnj case TIOCEXCL: 3035614Swnj tp->t_state |= TS_XCLUDE; 3045614Swnj break; 3055614Swnj 3065614Swnj case TIOCNXCL: 3075614Swnj tp->t_state &= ~TS_XCLUDE; 3085614Swnj break; 3095614Swnj 31039Sbill case TIOCHPCL: 31135811Smarc tp->t_cflag |= HUPCL; 31239Sbill break; 31339Sbill 3143942Sbugs case TIOCFLUSH: { 3157625Ssam register int flags = *(int *)data; 3167625Ssam 3177625Ssam if (flags == 0) 3183942Sbugs flags = FREAD|FWRITE; 3197625Ssam else 3207625Ssam flags &= FREAD|FWRITE; 32112752Ssam ttyflush(tp, flags); 32239Sbill break; 3233944Sbugs } 32439Sbill 32537584Smarc case FIOASYNC: 32637584Smarc if (*(int *)data) 32737584Smarc tp->t_state |= TS_ASYNC; 32837584Smarc else 32937584Smarc tp->t_state &= ~TS_ASYNC; 33037584Smarc break; 33137584Smarc 33237584Smarc case FIONBIO: 33337584Smarc break; /* XXX remove */ 33437584Smarc 3358556Sroot /* return number of characters immediately available */ 3367625Ssam case FIONREAD: 3377625Ssam *(off_t *)data = ttnread(tp); 338174Sbill break; 339174Sbill 34013077Ssam case TIOCOUTQ: 34113077Ssam *(int *)data = tp->t_outq.c_cc; 34213077Ssam break; 34313077Ssam 3448589Sroot case TIOCSTOP: 34517545Skarels s = spltty(); 3469578Ssam if ((tp->t_state&TS_TTSTOP) == 0) { 3475573Swnj tp->t_state |= TS_TTSTOP; 3485573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 3495573Swnj } 3507625Ssam splx(s); 3515573Swnj break; 3525573Swnj 3538589Sroot case TIOCSTART: 35417545Skarels s = spltty(); 35535811Smarc if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 3565573Swnj tp->t_state &= ~TS_TTSTOP; 35735811Smarc tp->t_lflag &= ~FLUSHO; 3585573Swnj ttstart(tp); 3595573Swnj } 3607625Ssam splx(s); 3615573Swnj break; 3625573Swnj 3639325Ssam /* 3649325Ssam * Simulate typing of a character at the terminal. 3659325Ssam */ 3669325Ssam case TIOCSTI: 36717183Smckusick if (u.u_uid && (flag & FREAD) == 0) 36817183Smckusick return (EPERM); 36939555Smarc if (u.u_uid && !isctty(u.u_procp, tp)) 3709325Ssam return (EACCES); 3719578Ssam (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 3729325Ssam break; 3739325Ssam 37435811Smarc case TIOCGETA: { 37535811Smarc struct termios *t = (struct termios *)data; 37612752Ssam 37735811Smarc bcopy(&tp->t_termios, t, sizeof(struct termios)); 37835811Smarc break; 37935811Smarc } 38035811Smarc 38135811Smarc case TIOCSETA: 38235811Smarc case TIOCSETAW: 38337584Smarc case TIOCSETAF: { 38435811Smarc register struct termios *t = (struct termios *)data; 38540712Skarels 38617545Skarels s = spltty(); 38739407Smarc if (com == TIOCSETAW || com == TIOCSETAF) { 38840712Skarels if (error = ttywait(tp)) { 38940712Skarels splx(s); 39040712Skarels return (error); 39140712Skarels } 392*45007Smarc if (com == TIOCSETAF) 39339407Smarc ttyflush(tp, FREAD); 39439407Smarc } 39540712Skarels if ((t->c_cflag&CIGNORE) == 0) { 39635811Smarc /* 39735811Smarc * set device hardware 39835811Smarc */ 39937584Smarc if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 40037584Smarc splx(s); 40135811Smarc return (error); 40237584Smarc } else { 40340712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && 40437584Smarc (tp->t_cflag&CLOCAL) && 40540712Skarels (t->c_cflag&CLOCAL) == 0) { 40637584Smarc tp->t_state &= ~TS_ISOPEN; 40737584Smarc tp->t_state |= TS_WOPEN; 40837584Smarc ttwakeup(tp); 40937584Smarc } 41035811Smarc tp->t_cflag = t->c_cflag; 41135811Smarc tp->t_ispeed = t->c_ispeed; 41235811Smarc tp->t_ospeed = t->c_ospeed; 41334492Skarels } 41435811Smarc ttsetwater(tp); 41512752Ssam } 41639407Smarc if (com != TIOCSETAF) { 41735811Smarc if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 41835811Smarc if (t->c_lflag&ICANON) { 41935811Smarc tp->t_lflag |= PENDIN; 42035811Smarc ttwakeup(tp); 42135811Smarc } 42235811Smarc else { 42335811Smarc struct clist tq; 42435811Smarc 42535811Smarc catq(&tp->t_rawq, &tp->t_canq); 42635811Smarc tq = tp->t_rawq; 42735811Smarc tp->t_rawq = tp->t_canq; 42835811Smarc tp->t_canq = tq; 42935811Smarc } 43012752Ssam } 43135811Smarc tp->t_iflag = t->c_iflag; 43235811Smarc tp->t_oflag = t->c_oflag; 43342882Smarc /* 43442882Smarc * Make the EXTPROC bit read only. 43542882Smarc */ 43642882Smarc if (tp->t_lflag&EXTPROC) 43742882Smarc t->c_lflag |= EXTPROC; 43842882Smarc else 43942882Smarc t->c_lflag &= ~EXTPROC; 44035811Smarc tp->t_lflag = t->c_lflag; 44135811Smarc bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 44212752Ssam splx(s); 44312752Ssam break; 44412752Ssam } 44512752Ssam 44612752Ssam /* 44739555Smarc * Set controlling terminal. 44839555Smarc * Session ctty vnode pointer set in vnode layer. 44934492Skarels */ 45035811Smarc case TIOCSCTTY: { 45135811Smarc register struct proc *p = u.u_procp; 45234492Skarels 45339555Smarc if (!SESS_LEADER(p) || 45439555Smarc (p->p_session->s_ttyvp || tp->t_session) && 45539555Smarc (tp->t_session != p->p_session)) 45639407Smarc return (EPERM); 45735811Smarc tp->t_session = p->p_session; 45839555Smarc tp->t_pgrp = p->p_pgrp; 45939555Smarc p->p_session->s_ttyp = tp; 46039555Smarc p->p_flag |= SCTTY; 46134492Skarels break; 46235811Smarc } 46339555Smarc 46434492Skarels /* 46535811Smarc * Set terminal process group. 46617545Skarels */ 46718650Sbloom case TIOCSPGRP: { 46835811Smarc register struct proc *p = u.u_procp; 46935811Smarc register struct pgrp *pgrp = pgfind(*(int *)data); 47017545Skarels 47139555Smarc if (!isctty(p, tp)) 47239555Smarc return (ENOTTY); 47340030Smarc else if (pgrp == NULL || pgrp->pg_session != p->p_session) 47439555Smarc return (EPERM); 47539555Smarc tp->t_pgrp = pgrp; 47612752Ssam break; 47718650Sbloom } 47812752Ssam 47912752Ssam case TIOCGPGRP: 48039555Smarc if (!isctty(u.u_procp, tp)) 48139555Smarc return (ENOTTY); 482*45007Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 48312752Ssam break; 48412752Ssam 48517598Sbloom case TIOCSWINSZ: 48618650Sbloom if (bcmp((caddr_t)&tp->t_winsize, data, 48718650Sbloom sizeof (struct winsize))) { 48817598Sbloom tp->t_winsize = *(struct winsize *)data; 48942882Smarc pgsignal(tp->t_pgrp, SIGWINCH, 1); 49017598Sbloom } 49117598Sbloom break; 49217598Sbloom 49317598Sbloom case TIOCGWINSZ: 49417598Sbloom *(struct winsize *)data = tp->t_winsize; 49517598Sbloom break; 49617598Sbloom 49730534Skarels case TIOCCONS: 49830534Skarels if (*(int *)data) { 49942141Smckusick if (constty && constty != tp && 50042141Smckusick (constty->t_state & (TS_CARR_ON|TS_ISOPEN)) == 50142141Smckusick (TS_CARR_ON|TS_ISOPEN)) 50230534Skarels return (EBUSY); 50330534Skarels #ifndef UCONSOLE 50437554Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 50537554Smckusick return (error); 50630534Skarels #endif 50730534Skarels constty = tp; 50830534Skarels } else if (tp == constty) 50933404Skarels constty = NULL; 51030534Skarels break; 51130534Skarels 51235811Smarc #ifdef COMPAT_43 51335811Smarc case TIOCGETP: 51435811Smarc case TIOCSETP: 51535811Smarc case TIOCSETN: 51635811Smarc case TIOCGETC: 51735811Smarc case TIOCSETC: 51835811Smarc case TIOCSLTC: 51935811Smarc case TIOCGLTC: 52035811Smarc case TIOCLBIS: 52135811Smarc case TIOCLBIC: 52235811Smarc case TIOCLSET: 52335811Smarc case TIOCLGET: 52439407Smarc case OTIOCGETD: 52539407Smarc case OTIOCSETD: 52643377Smarc case OTIOCCONS: 52735811Smarc return(ttcompat(tp, com, data, flag)); 52835811Smarc #endif 52935811Smarc 53039Sbill default: 5318556Sroot return (-1); 53239Sbill } 5338556Sroot return (0); 53439Sbill } 5354484Swnj 5364484Swnj ttnread(tp) 5374484Swnj struct tty *tp; 5384484Swnj { 5394484Swnj int nread = 0; 5404484Swnj 54135811Smarc if (tp->t_lflag & PENDIN) 5424484Swnj ttypend(tp); 5434484Swnj nread = tp->t_canq.c_cc; 54435811Smarc if ((tp->t_lflag & ICANON) == 0) 5454484Swnj nread += tp->t_rawq.c_cc; 5464484Swnj return (nread); 5474484Swnj } 5484484Swnj 5495408Swnj ttselect(dev, rw) 5504484Swnj dev_t dev; 5515408Swnj int rw; 5524484Swnj { 5534484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5544484Swnj int nread; 55517545Skarels int s = spltty(); 5564484Swnj 5575408Swnj switch (rw) { 5584484Swnj 5594484Swnj case FREAD: 5604484Swnj nread = ttnread(tp); 56137584Smarc if (nread > 0 || 56240712Skarels ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0)) 5635408Swnj goto win; 5644938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5655408Swnj tp->t_state |= TS_RCOLL; 5664484Swnj else 5674484Swnj tp->t_rsel = u.u_procp; 5685408Swnj break; 5694484Swnj 5705408Swnj case FWRITE: 57135811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 5725408Swnj goto win; 5735408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 5745408Swnj tp->t_state |= TS_WCOLL; 5755408Swnj else 5765408Swnj tp->t_wsel = u.u_procp; 5775408Swnj break; 5784484Swnj } 5795408Swnj splx(s); 5805408Swnj return (0); 5815408Swnj win: 5825408Swnj splx(s); 5835408Swnj return (1); 5844484Swnj } 5857436Skre 5867502Sroot /* 58725391Skarels * Initial open of tty, or (re)entry to line discipline. 5887502Sroot */ 5897502Sroot ttyopen(dev, tp) 5907625Ssam dev_t dev; 5917625Ssam register struct tty *tp; 5927502Sroot { 5937502Sroot 5947502Sroot tp->t_dev = dev; 59535811Smarc 5967502Sroot tp->t_state &= ~TS_WOPEN; 59717545Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 59817545Skarels tp->t_state |= TS_ISOPEN; 59917598Sbloom bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 60017545Skarels } 6018556Sroot return (0); 6027502Sroot } 6037502Sroot 6047502Sroot /* 60525391Skarels * "close" a line discipline 60625391Skarels */ 60725391Skarels ttylclose(tp) 60825391Skarels register struct tty *tp; 60925391Skarels { 61025391Skarels 61125391Skarels ttywflush(tp); 61225391Skarels } 61325391Skarels 61425391Skarels /* 6157502Sroot * clean tp on last close 6167502Sroot */ 6177502Sroot ttyclose(tp) 6187625Ssam register struct tty *tp; 6197502Sroot { 62030534Skarels if (constty == tp) 62130534Skarels constty = NULL; 62225391Skarels ttyflush(tp, FREAD|FWRITE); 62339555Smarc tp->t_session = NULL; 62439555Smarc tp->t_pgrp = NULL; 6257502Sroot tp->t_state = 0; 62643377Smarc tp->t_gen++; 62740712Skarels return (0); 6287502Sroot } 6297502Sroot 6307502Sroot /* 63125391Skarels * Handle modem control transition on a tty. 63225391Skarels * Flag indicates new state of carrier. 63325391Skarels * Returns 0 if the line should be turned off, otherwise 1. 63425391Skarels */ 63525391Skarels ttymodem(tp, flag) 63625391Skarels register struct tty *tp; 63725391Skarels { 63825391Skarels 63942193Smarc if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) { 64025391Skarels /* 64125391Skarels * MDMBUF: do flow control according to carrier flag 64225391Skarels */ 64325391Skarels if (flag) { 64425391Skarels tp->t_state &= ~TS_TTSTOP; 64525391Skarels ttstart(tp); 64625391Skarels } else if ((tp->t_state&TS_TTSTOP) == 0) { 64725391Skarels tp->t_state |= TS_TTSTOP; 64825391Skarels (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 64925391Skarels } 65025391Skarels } else if (flag == 0) { 65125391Skarels /* 65225391Skarels * Lost carrier. 65325391Skarels */ 65425391Skarels tp->t_state &= ~TS_CARR_ON; 65542193Smarc if (tp->t_state&TS_ISOPEN && (tp->t_cflag&CLOCAL) == 0) { 65642193Smarc if (tp->t_session && tp->t_session->s_leader) 65742193Smarc psignal(tp->t_session->s_leader, SIGHUP); 65842193Smarc ttyflush(tp, FREAD|FWRITE); 65942193Smarc return (0); 66025391Skarels } 66125391Skarels } else { 66225391Skarels /* 66325391Skarels * Carrier now on. 66425391Skarels */ 66525391Skarels tp->t_state |= TS_CARR_ON; 66637584Smarc ttwakeup(tp); 66725391Skarels } 66825391Skarels return (1); 66925391Skarels } 67025391Skarels 67125391Skarels /* 67225404Skarels * Default modem control routine (for other line disciplines). 67325404Skarels * Return argument flag, to turn off device on carrier drop. 67425404Skarels */ 67525415Skarels nullmodem(tp, flag) 67625415Skarels register struct tty *tp; 67725404Skarels int flag; 67825404Skarels { 67925404Skarels 68025404Skarels if (flag) 68125404Skarels tp->t_state |= TS_CARR_ON; 68239407Smarc else { 68325404Skarels tp->t_state &= ~TS_CARR_ON; 68442193Smarc if ((tp->t_cflag&CLOCAL) == 0) { 68542193Smarc if (tp->t_session && tp->t_session->s_leader) 68642193Smarc psignal(tp->t_session->s_leader, SIGHUP); 68742193Smarc return (0); 68842193Smarc } 68939407Smarc } 69042193Smarc return (1); 69125404Skarels } 69225404Skarels 69325404Skarels /* 6947502Sroot * reinput pending characters after state switch 69517545Skarels * call at spltty(). 6967502Sroot */ 6977502Sroot ttypend(tp) 6987625Ssam register struct tty *tp; 6997502Sroot { 7007502Sroot struct clist tq; 7017502Sroot register c; 7027502Sroot 70335811Smarc tp->t_lflag &= ~PENDIN; 7049578Ssam tp->t_state |= TS_TYPEN; 7057502Sroot tq = tp->t_rawq; 7067502Sroot tp->t_rawq.c_cc = 0; 7077502Sroot tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 7087502Sroot while ((c = getc(&tq)) >= 0) 7097502Sroot ttyinput(c, tp); 7109578Ssam tp->t_state &= ~TS_TYPEN; 7117502Sroot } 7127502Sroot 7137502Sroot /* 71435811Smarc * 7159578Ssam * Place a character on raw TTY input queue, 7169578Ssam * putting in delimiters and waking up top 7179578Ssam * half as needed. Also echo if required. 7189578Ssam * The arguments are the character and the 7199578Ssam * appropriate tty structure. 7207502Sroot */ 7217502Sroot ttyinput(c, tp) 7227625Ssam register c; 7237625Ssam register struct tty *tp; 7247502Sroot { 72535811Smarc register int iflag = tp->t_iflag; 72635811Smarc register int lflag = tp->t_lflag; 72735811Smarc register u_char *cc = tp->t_cc; 72835811Smarc int i, err; 7297502Sroot 7309578Ssam /* 7319578Ssam * If input is pending take it first. 7329578Ssam */ 73335811Smarc if (lflag&PENDIN) 7347502Sroot ttypend(tp); 73535811Smarc /* 73635811Smarc * Gather stats. 73735811Smarc */ 7387502Sroot tk_nin++; 73935811Smarc if (lflag&ICANON) { 74035811Smarc tk_cancc++; 74135811Smarc tp->t_cancc++; 74235811Smarc } else { 74335811Smarc tk_rawcc++; 74435811Smarc tp->t_rawcc++; 74535811Smarc } 7469578Ssam /* 74735811Smarc * Handle exceptional conditions (break, parity, framing). 7489578Ssam */ 74935811Smarc if (err = (c&TTY_ERRORMASK)) { 75035811Smarc c &= ~TTY_ERRORMASK; 75135811Smarc if (err&TTY_FE && !c) { /* break */ 75235811Smarc if (iflag&IGNBRK) 75335811Smarc goto endcase; 75435811Smarc else if (iflag&BRKINT && lflag&ISIG && 75535811Smarc (cc[VINTR] != _POSIX_VDISABLE)) 75635811Smarc c = cc[VINTR]; 75735811Smarc else { 75835811Smarc c = 0; 75935811Smarc if (iflag&PARMRK) 76035811Smarc goto parmrk; 76135811Smarc } 76235811Smarc } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 76335811Smarc if (iflag&IGNPAR) 76435811Smarc goto endcase; 76535811Smarc else if (iflag&PARMRK) { 76635811Smarc parmrk: 76735811Smarc putc(0377|TTY_QUOTE, &tp->t_rawq); 76835811Smarc putc(0|TTY_QUOTE, &tp->t_rawq); 76935811Smarc putc(c|TTY_QUOTE, &tp->t_rawq); 77035811Smarc goto endcase; 77135811Smarc } else 77235811Smarc c = 0; 7737502Sroot } 7749578Ssam } 7759578Ssam /* 77635811Smarc * In tandem mode, check high water mark. 7779578Ssam */ 77835811Smarc if (iflag&IXOFF) 77935811Smarc ttyblock(tp); 78035811Smarc if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 7819578Ssam c &= 0177; 78244419Smarc if ((tp->t_lflag&EXTPROC) == 0) { 78344419Smarc /* 78444419Smarc * Check for literal nexting very first 78544419Smarc */ 78644419Smarc if (tp->t_state&TS_LNCH) { 78744419Smarc c |= TTY_QUOTE; 78844419Smarc tp->t_state &= ~TS_LNCH; 78944419Smarc } 79044419Smarc /* 79144419Smarc * Scan for special characters. This code 79244419Smarc * is really just a big case statement with 79344419Smarc * non-constant cases. The bottom of the 79444419Smarc * case statement is labeled ``endcase'', so goto 79544419Smarc * it after a case match, or similar. 79644419Smarc */ 79744419Smarc 79844419Smarc /* 79944419Smarc * Control chars which aren't controlled 80044419Smarc * by ICANON, ISIG, or IXON. 80144419Smarc */ 80244419Smarc if (lflag&IEXTEN) { 80344419Smarc if (CCEQ(cc[VLNEXT], c)) { 80444419Smarc if (lflag&ECHO) { 80544419Smarc if (lflag&ECHOE) 80644419Smarc ttyoutstr("^\b", tp); 80744419Smarc else 80844419Smarc ttyecho(c, tp); 80944419Smarc } 81044419Smarc tp->t_state |= TS_LNCH; 81144419Smarc goto endcase; 81244419Smarc } 81344419Smarc if (CCEQ(cc[VDISCARD], c)) { 81444419Smarc if (lflag&FLUSHO) 81544419Smarc tp->t_lflag &= ~FLUSHO; 81644419Smarc else { 81744419Smarc ttyflush(tp, FWRITE); 81835811Smarc ttyecho(c, tp); 81944419Smarc if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 82044419Smarc ttyretype(tp); 82144419Smarc tp->t_lflag |= FLUSHO; 82244419Smarc } 82344419Smarc goto startoutput; 82435811Smarc } 8259578Ssam } 82644419Smarc /* 82744419Smarc * Signals. 82844419Smarc */ 82944419Smarc if (lflag&ISIG) { 83044419Smarc if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 83144419Smarc if ((lflag&NOFLSH) == 0) 83244419Smarc ttyflush(tp, FREAD|FWRITE); 8337502Sroot ttyecho(c, tp); 83444419Smarc pgsignal(tp->t_pgrp, 83544419Smarc CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 83644419Smarc goto endcase; 8377502Sroot } 83844419Smarc if (CCEQ(cc[VSUSP], c)) { 83944419Smarc if ((lflag&NOFLSH) == 0) 84044419Smarc ttyflush(tp, FREAD); 84144419Smarc ttyecho(c, tp); 84244419Smarc pgsignal(tp->t_pgrp, SIGTSTP, 1); 84344419Smarc goto endcase; 84444419Smarc } 8459578Ssam } 84644419Smarc /* 84744419Smarc * Handle start/stop characters. 84844419Smarc */ 84944419Smarc if (iflag&IXON) { 85044419Smarc if (CCEQ(cc[VSTOP], c)) { 85144419Smarc if ((tp->t_state&TS_TTSTOP) == 0) { 85244419Smarc tp->t_state |= TS_TTSTOP; 85344419Smarc (*cdevsw[major(tp->t_dev)].d_stop)(tp, 85444419Smarc 0); 85544419Smarc return; 85644419Smarc } 85744419Smarc if (!CCEQ(cc[VSTART], c)) 85844419Smarc return; 85944419Smarc /* 86044419Smarc * if VSTART == VSTOP then toggle 86144419Smarc */ 86244419Smarc goto endcase; 86335811Smarc } 86444419Smarc if (CCEQ(cc[VSTART], c)) 86544419Smarc goto restartoutput; 8669578Ssam } 86744419Smarc /* 86844419Smarc * IGNCR, ICRNL, & INLCR 86944419Smarc */ 87044419Smarc if (c == '\r') { 87144419Smarc if (iflag&IGNCR) 87244419Smarc goto endcase; 87344419Smarc else if (iflag&ICRNL) 87444419Smarc c = '\n'; 87544419Smarc } else if (c == '\n' && iflag&INLCR) 87644419Smarc c = '\r'; 8779578Ssam } 8789578Ssam /* 87935811Smarc * Non canonical mode; don't process line editing 8809578Ssam * characters; check high water mark for wakeup. 88135811Smarc * 8829578Ssam */ 88340712Skarels if ((lflag&ICANON) == 0) { 8849578Ssam if (tp->t_rawq.c_cc > TTYHOG) { 88535811Smarc if (iflag&IMAXBEL) { 88635811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 88735811Smarc (void) ttyoutput(CTRL('g'), tp); 88835811Smarc } else 88935811Smarc ttyflush(tp, FREAD | FWRITE); 89035811Smarc } else { 89135811Smarc if (putc(c, &tp->t_rawq) >= 0) { 89235811Smarc ttwakeup(tp); 89335811Smarc ttyecho(c, tp); 89435811Smarc } 8957502Sroot } 8969578Ssam goto endcase; 8979578Ssam } 89844419Smarc if ((tp->t_lflag&EXTPROC) == 0) { 89944419Smarc /* 90044419Smarc * From here on down canonical mode character 90144419Smarc * processing takes place. 90244419Smarc */ 90344419Smarc /* 90444419Smarc * erase (^H / ^?) 90544419Smarc */ 90644419Smarc if (CCEQ(cc[VERASE], c)) { 90744419Smarc if (tp->t_rawq.c_cc) 9089578Ssam ttyrub(unputc(&tp->t_rawq), tp); 90944419Smarc goto endcase; 9109578Ssam } 91144419Smarc /* 91244419Smarc * kill (^U) 91344419Smarc */ 91444419Smarc if (CCEQ(cc[VKILL], c)) { 91544419Smarc if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 91644419Smarc (lflag&ECHOPRT) == 0) { 91744419Smarc while (tp->t_rawq.c_cc) 91844419Smarc ttyrub(unputc(&tp->t_rawq), tp); 91944419Smarc } else { 92044419Smarc ttyecho(c, tp); 92144419Smarc if (lflag&ECHOK || lflag&ECHOKE) 92244419Smarc ttyecho('\n', tp); 92344419Smarc while (getc(&tp->t_rawq) > 0) 92444419Smarc ; 92544419Smarc tp->t_rocount = 0; 92644419Smarc } 92744419Smarc tp->t_state &= ~TS_LOCAL; 92844419Smarc goto endcase; 92944419Smarc } 93044419Smarc /* 93144419Smarc * word erase (^W) 93244419Smarc */ 93344419Smarc if (CCEQ(cc[VWERASE], c)) { 93444419Smarc int ctype; 93535811Smarc 93635811Smarc #define CTYPE(c) ((lflag&ALTWERASE) ? (partab[(c)&TTY_CHARMASK]&0100) : 0) 93744419Smarc /* 93844419Smarc * erase whitespace 93944419Smarc */ 94044419Smarc while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 94144419Smarc ttyrub(c, tp); 94244419Smarc if (c == -1) 94344419Smarc goto endcase; 94444419Smarc /* 94544419Smarc * special case last char of token 94644419Smarc */ 94735811Smarc ttyrub(c, tp); 94844419Smarc c = unputc(&tp->t_rawq); 94944419Smarc if (c == -1 || c == ' ' || c == '\t') { 95044419Smarc if (c != -1) 95144419Smarc (void) putc(c, &tp->t_rawq); 95244419Smarc goto endcase; 95344419Smarc } 95444419Smarc /* 95544419Smarc * erase rest of token 95644419Smarc */ 95744419Smarc ctype = CTYPE(c); 95844419Smarc do { 95944419Smarc ttyrub(c, tp); 96044419Smarc c = unputc(&tp->t_rawq); 96144419Smarc if (c == -1) 96244419Smarc goto endcase; 96344419Smarc } while (c != ' ' && c != '\t' && CTYPE(c) == ctype); 96444419Smarc (void) putc(c, &tp->t_rawq); 96534492Skarels goto endcase; 96644419Smarc #undef CTYPE 96744419Smarc } 96835811Smarc /* 96944419Smarc * reprint line (^R) 97035811Smarc */ 97144419Smarc if (CCEQ(cc[VREPRINT], c)) { 97244419Smarc ttyretype(tp); 97334492Skarels goto endcase; 97434492Skarels } 97535811Smarc /* 97644419Smarc * ^T - kernel info and generate SIGINFO 97735811Smarc */ 97844419Smarc if (CCEQ(cc[VSTATUS], c)) { 97944419Smarc pgsignal(tp->t_pgrp, SIGINFO, 1); 98044419Smarc if ((lflag&NOKERNINFO) == 0) 98144419Smarc ttyinfo(tp); 98244419Smarc goto endcase; 98344419Smarc } 9849578Ssam } 9859578Ssam /* 9869578Ssam * Check for input buffer overflow 9879578Ssam */ 98810391Ssam if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 98935811Smarc if (iflag&IMAXBEL) { 99035811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 99135811Smarc (void) ttyoutput(CTRL('g'), tp); 99235811Smarc } else 99335811Smarc ttyflush(tp, FREAD | FWRITE); 9949578Ssam goto endcase; 99510391Ssam } 9969578Ssam /* 9979578Ssam * Put data char in q for user and 9989578Ssam * wakeup on seeing a line delimiter. 9999578Ssam */ 10009578Ssam if (putc(c, &tp->t_rawq) >= 0) { 100135811Smarc if (ttbreakc(c)) { 10029578Ssam tp->t_rocount = 0; 10039578Ssam catq(&tp->t_rawq, &tp->t_canq); 10047502Sroot ttwakeup(tp); 10059578Ssam } else if (tp->t_rocount++ == 0) 10069578Ssam tp->t_rocol = tp->t_col; 10079578Ssam if (tp->t_state&TS_ERASE) { 100835811Smarc /* 100935811Smarc * end of prterase \.../ 101035811Smarc */ 10119578Ssam tp->t_state &= ~TS_ERASE; 10129578Ssam (void) ttyoutput('/', tp); 10139578Ssam } 10149578Ssam i = tp->t_col; 10157502Sroot ttyecho(c, tp); 101635811Smarc if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 101735811Smarc /* 101835811Smarc * Place the cursor over the '^' of the ^D. 101935811Smarc */ 10209578Ssam i = MIN(2, tp->t_col - i); 10219578Ssam while (i > 0) { 10229578Ssam (void) ttyoutput('\b', tp); 10239578Ssam i--; 10249578Ssam } 10259578Ssam } 10267502Sroot } 10279578Ssam endcase: 10289578Ssam /* 102935811Smarc * IXANY means allow any character to restart output. 10309578Ssam */ 103140712Skarels if ((tp->t_state&TS_TTSTOP) && (iflag&IXANY) == 0 && 103240712Skarels cc[VSTART] != cc[VSTOP]) 10337502Sroot return; 10349578Ssam restartoutput: 10357502Sroot tp->t_state &= ~TS_TTSTOP; 103635811Smarc tp->t_lflag &= ~FLUSHO; 10379578Ssam startoutput: 10387502Sroot ttstart(tp); 10397502Sroot } 10407502Sroot 10417502Sroot /* 10429578Ssam * Put character on TTY output queue, adding delays, 10437502Sroot * expanding tabs, and handling the CR/NL bit. 10449578Ssam * This is called both from the top half for output, 10459578Ssam * and from interrupt level for echoing. 10467502Sroot * The arguments are the character and the tty structure. 10477502Sroot * Returns < 0 if putc succeeds, otherwise returns char to resend 10487502Sroot * Must be recursive. 10497502Sroot */ 10507502Sroot ttyoutput(c, tp) 10517502Sroot register c; 10527502Sroot register struct tty *tp; 10537502Sroot { 105444419Smarc register short *colp; 10557502Sroot register ctype; 105635811Smarc register long oflag = tp->t_oflag; 105735811Smarc 105840712Skarels if ((oflag&OPOST) == 0) { 105935811Smarc if (tp->t_lflag&FLUSHO) 10607502Sroot return (-1); 10617502Sroot if (putc(c, &tp->t_outq)) 10627625Ssam return (c); 10637502Sroot tk_nout++; 106435811Smarc tp->t_outcc++; 10657502Sroot return (-1); 10667502Sroot } 106735811Smarc c &= TTY_CHARMASK; 10687502Sroot /* 10697502Sroot * Turn tabs to spaces as required 107042882Smarc * 107142882Smarc * Special case if we have external processing, we don't 107242882Smarc * do the tab expansion because we'll probably get it 107342882Smarc * wrong. If tab expansion needs to be done, let it 107442882Smarc * happen externally. 10757502Sroot */ 107642882Smarc if ((tp->t_lflag&EXTPROC) == 0 && 107742882Smarc c == '\t' && oflag&OXTABS ) { 10787502Sroot register int s; 10797502Sroot 10807502Sroot c = 8 - (tp->t_col&7); 108135811Smarc if ((tp->t_lflag&FLUSHO) == 0) { 108217545Skarels s = spltty(); /* don't interrupt tabs */ 10837502Sroot c -= b_to_q(" ", c, &tp->t_outq); 10847502Sroot tk_nout += c; 108535811Smarc tp->t_outcc += c; 10867502Sroot splx(s); 10877502Sroot } 10887502Sroot tp->t_col += c; 10897502Sroot return (c ? -1 : '\t'); 10907502Sroot } 109135811Smarc if (c == CEOT && oflag&ONOEOT) 109235811Smarc return(-1); 10937502Sroot tk_nout++; 109435811Smarc tp->t_outcc++; 10957502Sroot /* 10967502Sroot * turn <nl> to <cr><lf> if desired. 10977502Sroot */ 109835811Smarc if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 10997502Sroot return (c); 110035811Smarc if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 110135811Smarc return (c); 11027502Sroot /* 11037502Sroot * Calculate delays. 11047502Sroot * The numbers here represent clock ticks 11057502Sroot * and are not necessarily optimal for all terminals. 11069578Ssam * 11079578Ssam * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 110835811Smarc * 110935811Smarc * (actually, should THROW AWAY terminals which need delays) 11107502Sroot */ 11117502Sroot colp = &tp->t_col; 11127502Sroot ctype = partab[c]; 11137502Sroot c = 0; 11147502Sroot switch (ctype&077) { 11157502Sroot 11167502Sroot case ORDINARY: 11177502Sroot (*colp)++; 11187502Sroot 11197502Sroot case CONTROL: 11207502Sroot break; 11217502Sroot 11227502Sroot case BACKSPACE: 11237502Sroot if (*colp) 11247502Sroot (*colp)--; 11257502Sroot break; 11267502Sroot 112713821Ssam /* 112813821Ssam * This macro is close enough to the correct thing; 112913821Ssam * it should be replaced by real user settable delays 113013821Ssam * in any event... 113113821Ssam */ 113213821Ssam #define mstohz(ms) (((ms) * hz) >> 10) 11337502Sroot case NEWLINE: 11347502Sroot ctype = (tp->t_flags >> 8) & 03; 11357625Ssam if (ctype == 1) { /* tty 37 */ 113626357Skarels if (*colp > 0) { 113726357Skarels c = (((unsigned)*colp) >> 4) + 3; 113826357Skarels if ((unsigned)c > 6) 113926357Skarels c = 6; 114026357Skarels } 11419578Ssam } else if (ctype == 2) /* vt05 */ 114213821Ssam c = mstohz(100); 11437502Sroot *colp = 0; 11447502Sroot break; 11457502Sroot 11467502Sroot case TAB: 11477502Sroot ctype = (tp->t_flags >> 10) & 03; 11487625Ssam if (ctype == 1) { /* tty 37 */ 11497502Sroot c = 1 - (*colp | ~07); 11507625Ssam if (c < 5) 11517502Sroot c = 0; 11527502Sroot } 11537502Sroot *colp |= 07; 11547502Sroot (*colp)++; 11557502Sroot break; 11567502Sroot 11577502Sroot case VTAB: 11589578Ssam if (tp->t_flags&VTDELAY) /* tty 37 */ 11597502Sroot c = 0177; 11607502Sroot break; 11617502Sroot 11627502Sroot case RETURN: 11637502Sroot ctype = (tp->t_flags >> 12) & 03; 11649578Ssam if (ctype == 1) /* tn 300 */ 116513821Ssam c = mstohz(83); 11669578Ssam else if (ctype == 2) /* ti 700 */ 116713821Ssam c = mstohz(166); 11689578Ssam else if (ctype == 3) { /* concept 100 */ 11697502Sroot int i; 11709578Ssam 11717502Sroot if ((i = *colp) >= 0) 11729578Ssam for (; i < 9; i++) 11737502Sroot (void) putc(0177, &tp->t_outq); 11747502Sroot } 11757502Sroot *colp = 0; 11767502Sroot } 117735811Smarc if (c && (tp->t_lflag&FLUSHO) == 0) 117835811Smarc (void) putc(c|TTY_QUOTE, &tp->t_outq); 11797502Sroot return (-1); 11807502Sroot } 118113821Ssam #undef mstohz 11827502Sroot 11837502Sroot /* 11847502Sroot * Called from device's read routine after it has 11857502Sroot * calculated the tty-structure given as argument. 11867502Sroot */ 118737584Smarc ttread(tp, uio, flag) 11887625Ssam register struct tty *tp; 11897722Swnj struct uio *uio; 11907502Sroot { 11917502Sroot register struct clist *qp; 119235811Smarc register int c; 119341383Smarc register long lflag; 119435811Smarc register u_char *cc = tp->t_cc; 11959859Ssam int s, first, error = 0; 11967502Sroot 11977502Sroot loop: 119841383Smarc lflag = tp->t_lflag; 119937584Smarc s = spltty(); 12009578Ssam /* 120137584Smarc * take pending input first 12029578Ssam */ 120335811Smarc if (lflag&PENDIN) 12047502Sroot ttypend(tp); 12059859Ssam splx(s); 120640712Skarels 12079578Ssam /* 12089578Ssam * Hang process if it's in the background. 12099578Ssam */ 121039555Smarc if (isbackground(u.u_procp, tp)) { 121124392Skarels if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 121224392Skarels (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 121335811Smarc u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0) 12148520Sroot return (EIO); 121542882Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN, 1); 121643377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 121743377Smarc ttybg, 0)) 121840712Skarels return (error); 121923165Sbloom goto loop; 12207502Sroot } 122140712Skarels 12229578Ssam /* 122335811Smarc * If canonical, use the canonical queue, 122435811Smarc * else use the raw queue. 122537584Smarc * 122637584Smarc * XXX - should get rid of canonical queue. 122737584Smarc * (actually, should get rid of clists...) 12289578Ssam */ 122935811Smarc qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 123040712Skarels 12319578Ssam /* 123240712Skarels * If there is no input, sleep on rawq 123340712Skarels * awaiting hardware receipt and notification. 123440712Skarels * If we have data, we don't need to check for carrier. 12359578Ssam */ 123617545Skarels s = spltty(); 12379578Ssam if (qp->c_cc <= 0) { 123840712Skarels int carrier; 123940712Skarels 124040712Skarels carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL); 124140712Skarels if (!carrier && tp->t_state&TS_ISOPEN) { 12429859Ssam splx(s); 124340712Skarels return (0); /* EOF */ 12447502Sroot } 124537728Smckusick if (flag & IO_NDELAY) { 124637584Smarc splx(s); 124737584Smarc return (EWOULDBLOCK); 124837584Smarc } 124943377Smarc error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 125040712Skarels carrier ? ttyin : ttopen, 0); 12519859Ssam splx(s); 125243377Smarc if (error) 125340712Skarels return (error); 12549578Ssam goto loop; 12559578Ssam } 12569859Ssam splx(s); 125740712Skarels 12589578Ssam /* 125935811Smarc * Input present, check for input mapping and processing. 12609578Ssam */ 12619578Ssam first = 1; 12629578Ssam while ((c = getc(qp)) >= 0) { 12639578Ssam /* 126435811Smarc * delayed suspend (^Y) 12659578Ssam */ 126635811Smarc if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 126742882Smarc pgsignal(tp->t_pgrp, SIGTSTP, 1); 12689578Ssam if (first) { 126943377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 127043377Smarc TTIPRI | PCATCH, ttybg, 0)) 127140712Skarels break; 12729578Ssam goto loop; 12739578Ssam } 12749578Ssam break; 12757502Sroot } 12769578Ssam /* 127735811Smarc * Interpret EOF only in canonical mode. 12789578Ssam */ 127935811Smarc if (CCEQ(cc[VEOF], c) && lflag&ICANON) 12809578Ssam break; 12819578Ssam /* 12829578Ssam * Give user character. 12839578Ssam */ 128440712Skarels error = ureadc(c, uio); 12859578Ssam if (error) 12869578Ssam break; 128714938Smckusick if (uio->uio_resid == 0) 12889578Ssam break; 12899578Ssam /* 129035811Smarc * In canonical mode check for a "break character" 12919578Ssam * marking the end of a "line of input". 12929578Ssam */ 129340712Skarels if (lflag&ICANON && ttbreakc(c)) 12949578Ssam break; 12959578Ssam first = 0; 12967502Sroot } 12979578Ssam /* 12989578Ssam * Look to unblock output now that (presumably) 12999578Ssam * the input queue has gone down. 13009578Ssam */ 130135811Smarc if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 130235811Smarc if (cc[VSTART] != _POSIX_VDISABLE 130335811Smarc && putc(cc[VSTART], &tp->t_outq) == 0) { 13047502Sroot tp->t_state &= ~TS_TBLOCK; 13057502Sroot ttstart(tp); 13067502Sroot } 130735811Smarc } 13088520Sroot return (error); 13097502Sroot } 13107502Sroot 13117502Sroot /* 131225391Skarels * Check the output queue on tp for space for a kernel message 131325391Skarels * (from uprintf/tprintf). Allow some space over the normal 131425391Skarels * hiwater mark so we don't lose messages due to normal flow 131525391Skarels * control, but don't let the tty run amok. 131630695Skarels * Sleeps here are not interruptible, but we return prematurely 131730695Skarels * if new signals come in. 131825391Skarels */ 131925391Skarels ttycheckoutq(tp, wait) 132025391Skarels register struct tty *tp; 132125391Skarels int wait; 132225391Skarels { 132330695Skarels int hiwat, s, oldsig; 132425391Skarels 132535811Smarc hiwat = tp->t_hiwat; 132625391Skarels s = spltty(); 132730695Skarels oldsig = u.u_procp->p_sig; 132825391Skarels if (tp->t_outq.c_cc > hiwat + 200) 132929946Skarels while (tp->t_outq.c_cc > hiwat) { 133029946Skarels ttstart(tp); 133130695Skarels if (wait == 0 || u.u_procp->p_sig != oldsig) { 133229946Skarels splx(s); 133329946Skarels return (0); 133429946Skarels } 133530695Skarels timeout(wakeup, (caddr_t)&tp->t_outq, hz); 133629946Skarels tp->t_state |= TS_ASLEEP; 133730695Skarels sleep((caddr_t)&tp->t_outq, PZERO - 1); 133825391Skarels } 133925391Skarels splx(s); 134025391Skarels return (1); 134125391Skarels } 134225391Skarels 134325391Skarels /* 13447502Sroot * Called from the device's write routine after it has 13457502Sroot * calculated the tty-structure given as argument. 13467502Sroot */ 134737584Smarc ttwrite(tp, uio, flag) 13487625Ssam register struct tty *tp; 13499578Ssam register struct uio *uio; 13507502Sroot { 13517502Sroot register char *cp; 135240712Skarels register int cc = 0, ce; 13539578Ssam int i, hiwat, cnt, error, s; 13547502Sroot char obuf[OBUFSIZ]; 13557502Sroot 135635811Smarc hiwat = tp->t_hiwat; 13579578Ssam cnt = uio->uio_resid; 13589578Ssam error = 0; 13597502Sroot loop: 136037584Smarc s = spltty(); 136140712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && (tp->t_cflag&CLOCAL) == 0) { 136237584Smarc if (tp->t_state&TS_ISOPEN) { 136337584Smarc splx(s); 136437584Smarc return (EIO); 136537728Smckusick } else if (flag & IO_NDELAY) { 136637584Smarc splx(s); 136740712Skarels error = EWOULDBLOCK; 136840712Skarels goto out; 136937584Smarc } else { 137037584Smarc /* 137137584Smarc * sleep awaiting carrier 137237584Smarc */ 137343377Smarc error = ttysleep(tp, (caddr_t)&tp->t_rawq, 137443377Smarc TTIPRI | PCATCH,ttopen, 0); 137537584Smarc splx(s); 137643377Smarc if (error) 137740712Skarels goto out; 137837584Smarc goto loop; 137937584Smarc } 138037584Smarc } 138137584Smarc splx(s); 13829578Ssam /* 13839578Ssam * Hang the process if it's in the background. 13849578Ssam */ 138539555Smarc if (isbackground(u.u_procp, tp) && 138635811Smarc (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 138740712Skarels (u.u_procp->p_sigignore & sigmask(SIGTTOU)) == 0 && 138840712Skarels (u.u_procp->p_sigmask & sigmask(SIGTTOU)) == 0 && 138935811Smarc u.u_procp->p_pgrp->pg_jobc) { 139042882Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU, 1); 139143377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 139243377Smarc ttybg, 0)) 139340712Skarels goto out; 139421776Sbloom goto loop; 13957502Sroot } 13969578Ssam /* 13979578Ssam * Process the user's data in at most OBUFSIZ 139840712Skarels * chunks. Perform any output translation. 139940712Skarels * Keep track of high water mark, sleep on overflow 140040712Skarels * awaiting device aid in acquiring new space. 14019578Ssam */ 140240712Skarels while (uio->uio_resid > 0 || cc > 0) { 140340712Skarels if (tp->t_lflag&FLUSHO) { 140440712Skarels uio->uio_resid = 0; 140540712Skarels return (0); 140640712Skarels } 140740712Skarels if (tp->t_outq.c_cc > hiwat) 140832067Skarels goto ovhiwat; 14099578Ssam /* 141040712Skarels * Grab a hunk of data from the user, 141140712Skarels * unless we have some leftover from last time. 14129578Ssam */ 14137822Sroot if (cc == 0) { 141440712Skarels cc = min(uio->uio_resid, OBUFSIZ); 141540712Skarels cp = obuf; 141640712Skarels error = uiomove(cp, cc, uio); 141740712Skarels if (error) { 141840712Skarels cc = 0; 141940712Skarels break; 142040712Skarels } 14217822Sroot } 14229578Ssam /* 14239578Ssam * If nothing fancy need be done, grab those characters we 14249578Ssam * can handle without any of ttyoutput's processing and 14259578Ssam * just transfer them to the output q. For those chars 14269578Ssam * which require special processing (as indicated by the 14279578Ssam * bits in partab), call ttyoutput. After processing 14289578Ssam * a hunk of data, look for FLUSHO so ^O's will take effect 14299578Ssam * immediately. 14309578Ssam */ 14319578Ssam while (cc > 0) { 143240712Skarels if ((tp->t_oflag&OPOST) == 0) 14337502Sroot ce = cc; 14347502Sroot else { 143534492Skarels ce = cc - scanc((unsigned)cc, (u_char *)cp, 143634492Skarels (u_char *)partab, 077); 14379578Ssam /* 14389578Ssam * If ce is zero, then we're processing 14399578Ssam * a special character through ttyoutput. 14409578Ssam */ 14419578Ssam if (ce == 0) { 14427502Sroot tp->t_rocount = 0; 14437502Sroot if (ttyoutput(*cp, tp) >= 0) { 144421776Sbloom /* no c-lists, wait a bit */ 144521776Sbloom ttstart(tp); 144643377Smarc if (error = ttysleep(tp, 144743377Smarc (caddr_t)&lbolt, 144843377Smarc TTOPRI | PCATCH, ttybuf, 0)) 144940712Skarels break; 145021776Sbloom goto loop; 14517502Sroot } 14529578Ssam cp++, cc--; 145335811Smarc if ((tp->t_lflag&FLUSHO) || 14549578Ssam tp->t_outq.c_cc > hiwat) 14557502Sroot goto ovhiwat; 14569578Ssam continue; 14577502Sroot } 14587502Sroot } 14599578Ssam /* 14609578Ssam * A bunch of normal characters have been found, 14619578Ssam * transfer them en masse to the output queue and 14629578Ssam * continue processing at the top of the loop. 14639578Ssam * If there are any further characters in this 14649578Ssam * <= OBUFSIZ chunk, the first should be a character 14659578Ssam * requiring special handling by ttyoutput. 14669578Ssam */ 14677502Sroot tp->t_rocount = 0; 14689578Ssam i = b_to_q(cp, ce, &tp->t_outq); 14699578Ssam ce -= i; 14709578Ssam tp->t_col += ce; 14719578Ssam cp += ce, cc -= ce, tk_nout += ce; 147235811Smarc tp->t_outcc += ce; 14739578Ssam if (i > 0) { 14749578Ssam /* out of c-lists, wait a bit */ 14757502Sroot ttstart(tp); 147643377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 147743377Smarc TTOPRI | PCATCH, ttybuf, 0)) 147840712Skarels break; 147921776Sbloom goto loop; 14807502Sroot } 148135811Smarc if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 148240712Skarels break; 14837502Sroot } 148435811Smarc ttstart(tp); 14857502Sroot } 148640712Skarels out: 148740712Skarels /* 148840712Skarels * If cc is nonzero, we leave the uio structure inconsistent, 148940712Skarels * as the offset and iov pointers have moved forward, 149040712Skarels * but it doesn't matter (the call will either return short 149140712Skarels * or restart with a new uio). 149240712Skarels */ 149340712Skarels uio->uio_resid += cc; 14948520Sroot return (error); 149540712Skarels 14967502Sroot ovhiwat: 149732067Skarels ttstart(tp); 149832067Skarels s = spltty(); 14999578Ssam /* 150035811Smarc * This can only occur if FLUSHO is set in t_lflag, 150132067Skarels * or if ttstart/oproc is synchronous (or very fast). 15029578Ssam */ 15037502Sroot if (tp->t_outq.c_cc <= hiwat) { 15049578Ssam splx(s); 15057502Sroot goto loop; 15067502Sroot } 150737728Smckusick if (flag & IO_NDELAY) { 150817545Skarels splx(s); 150940712Skarels uio->uio_resid += cc; 15107822Sroot if (uio->uio_resid == cnt) 15118520Sroot return (EWOULDBLOCK); 15128520Sroot return (0); 15137502Sroot } 15147502Sroot tp->t_state |= TS_ASLEEP; 151543377Smarc error = ttysleep(tp, (caddr_t)&tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 15169578Ssam splx(s); 151743377Smarc if (error) 151840712Skarels goto out; 15197502Sroot goto loop; 15207502Sroot } 15217502Sroot 15227502Sroot /* 15237502Sroot * Rubout one character from the rawq of tp 15247502Sroot * as cleanly as possible. 15257502Sroot */ 15267502Sroot ttyrub(c, tp) 15277625Ssam register c; 15287625Ssam register struct tty *tp; 15297502Sroot { 15307502Sroot register char *cp; 15317502Sroot register int savecol; 15327502Sroot int s; 15337502Sroot char *nextc(); 15347502Sroot 153542882Smarc if ((tp->t_lflag&ECHO) == 0 || (tp->t_lflag&EXTPROC)) 15367502Sroot return; 153735811Smarc tp->t_lflag &= ~FLUSHO; 153835811Smarc if (tp->t_lflag&ECHOE) { 15397502Sroot if (tp->t_rocount == 0) { 15407502Sroot /* 15417502Sroot * Screwed by ttwrite; retype 15427502Sroot */ 15437502Sroot ttyretype(tp); 15447502Sroot return; 15457502Sroot } 154635811Smarc if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 15477502Sroot ttyrubo(tp, 2); 154835811Smarc else switch (partab[c&=0377]&077) { 15497502Sroot 15507502Sroot case ORDINARY: 155135811Smarc ttyrubo(tp, 1); 15527502Sroot break; 15537502Sroot 15547502Sroot case VTAB: 15557502Sroot case BACKSPACE: 15567502Sroot case CONTROL: 15577502Sroot case RETURN: 1558*45007Smarc case NEWLINE: /* XXX can't happen ? */ 155935811Smarc if (tp->t_lflag&ECHOCTL) 15607502Sroot ttyrubo(tp, 2); 15617502Sroot break; 15627502Sroot 156335811Smarc case TAB: { 156435811Smarc int c; 156535811Smarc 15667502Sroot if (tp->t_rocount < tp->t_rawq.c_cc) { 15677502Sroot ttyretype(tp); 15687502Sroot return; 15697502Sroot } 157017545Skarels s = spltty(); 15717502Sroot savecol = tp->t_col; 15729578Ssam tp->t_state |= TS_CNTTB; 157335811Smarc tp->t_lflag |= FLUSHO; 15747502Sroot tp->t_col = tp->t_rocol; 15759578Ssam cp = tp->t_rawq.c_cf; 157639407Smarc if (cp) 157739407Smarc c = *cp; /* XXX FIX NEXTC */ 157835811Smarc for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 157935811Smarc ttyecho(c, tp); 158035811Smarc tp->t_lflag &= ~FLUSHO; 15819578Ssam tp->t_state &= ~TS_CNTTB; 15827502Sroot splx(s); 15837502Sroot /* 15847502Sroot * savecol will now be length of the tab 15857502Sroot */ 15867502Sroot savecol -= tp->t_col; 15877502Sroot tp->t_col += savecol; 15887502Sroot if (savecol > 8) 15897502Sroot savecol = 8; /* overflow screw */ 15907502Sroot while (--savecol >= 0) 15917502Sroot (void) ttyoutput('\b', tp); 15927502Sroot break; 159335811Smarc } 15947502Sroot 15957502Sroot default: 159637584Smarc /* XXX */ 159735811Smarc printf("ttyrub: would panic c = %d, val = %d\n", 159835811Smarc c, partab[c&=0377]&077); 159935811Smarc /*panic("ttyrub");*/ 16007502Sroot } 160135811Smarc } else if (tp->t_lflag&ECHOPRT) { 16029578Ssam if ((tp->t_state&TS_ERASE) == 0) { 16037502Sroot (void) ttyoutput('\\', tp); 16049578Ssam tp->t_state |= TS_ERASE; 16057502Sroot } 16067502Sroot ttyecho(c, tp); 16077502Sroot } else 160835811Smarc ttyecho(tp->t_cc[VERASE], tp); 16097502Sroot tp->t_rocount--; 16107502Sroot } 16117502Sroot 16127502Sroot /* 16137502Sroot * Crt back over cnt chars perhaps 16147502Sroot * erasing them. 16157502Sroot */ 16167502Sroot ttyrubo(tp, cnt) 16177625Ssam register struct tty *tp; 16187625Ssam int cnt; 16197502Sroot { 16207502Sroot 16217502Sroot while (--cnt >= 0) 162240712Skarels ttyoutstr("\b \b", tp); 16237502Sroot } 16247502Sroot 16257502Sroot /* 16267502Sroot * Reprint the rawq line. 16277502Sroot * We assume c_cc has already been checked. 16287502Sroot */ 16297502Sroot ttyretype(tp) 16307625Ssam register struct tty *tp; 16317502Sroot { 16327502Sroot register char *cp; 16337502Sroot char *nextc(); 163435811Smarc int s, c; 16357502Sroot 163635811Smarc if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 163735811Smarc ttyecho(tp->t_cc[VREPRINT], tp); 16387502Sroot (void) ttyoutput('\n', tp); 163917545Skarels s = spltty(); 164035811Smarc /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 164135811Smarc BIT OF FIRST CHAR ****/ 164235811Smarc for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 164335811Smarc ttyecho(c, tp); 164435811Smarc } 164535811Smarc for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 164635811Smarc ttyecho(c, tp); 164735811Smarc } 16489578Ssam tp->t_state &= ~TS_ERASE; 16497502Sroot splx(s); 16507502Sroot tp->t_rocount = tp->t_rawq.c_cc; 16517502Sroot tp->t_rocol = 0; 16527502Sroot } 16537502Sroot 16547502Sroot /* 165535811Smarc * Echo a typed character to the terminal. 16567502Sroot */ 16577502Sroot ttyecho(c, tp) 16587625Ssam register c; 16597625Ssam register struct tty *tp; 16607502Sroot { 16619578Ssam if ((tp->t_state&TS_CNTTB) == 0) 166235811Smarc tp->t_lflag &= ~FLUSHO; 166342882Smarc if (((tp->t_lflag&ECHO) == 0 && ((tp->t_lflag&ECHONL) == 0 || 166442882Smarc c == '\n')) || (tp->t_lflag&EXTPROC)) 16657502Sroot return; 166635811Smarc if (tp->t_lflag&ECHOCTL) { 166740712Skarels if ((c&TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' || 166840712Skarels c == 0177) { 16697502Sroot (void) ttyoutput('^', tp); 167035811Smarc c &= TTY_CHARMASK; 16717502Sroot if (c == 0177) 16727502Sroot c = '?'; 16737502Sroot else 16747502Sroot c += 'A' - 1; 16757502Sroot } 16767502Sroot } 167735811Smarc (void) ttyoutput(c, tp); 16787502Sroot } 16797502Sroot 16807502Sroot /* 16817502Sroot * send string cp to tp 16827502Sroot */ 168340712Skarels ttyoutstr(cp, tp) 16847625Ssam register char *cp; 16857625Ssam register struct tty *tp; 16867502Sroot { 16877502Sroot register char c; 16887502Sroot 16897502Sroot while (c = *cp++) 16907502Sroot (void) ttyoutput(c, tp); 16917502Sroot } 16927502Sroot 16937502Sroot ttwakeup(tp) 16947502Sroot struct tty *tp; 16957502Sroot { 16967502Sroot 16977502Sroot if (tp->t_rsel) { 16987502Sroot selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 16997502Sroot tp->t_state &= ~TS_RCOLL; 17007502Sroot tp->t_rsel = 0; 17017502Sroot } 170212752Ssam if (tp->t_state & TS_ASYNC) 170342882Smarc pgsignal(tp->t_pgrp, SIGIO, 1); 17047502Sroot wakeup((caddr_t)&tp->t_rawq); 17057502Sroot } 170635811Smarc 170735811Smarc /* 170835811Smarc * set tty hi and low water marks 170935811Smarc * 171035811Smarc * Try to arrange the dynamics so there's about one second 171135811Smarc * from hi to low water. 171235811Smarc * 171335811Smarc */ 171435811Smarc ttsetwater(tp) 171535811Smarc struct tty *tp; 171635811Smarc { 171735811Smarc register cps = tp->t_ospeed / 10; 171835811Smarc register x; 171935811Smarc 172035811Smarc #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 172135811Smarc tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 172235811Smarc x += cps; 172335811Smarc x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 172435811Smarc tp->t_hiwat = roundup(x, CBSIZE); 172535811Smarc #undef clamp 172635811Smarc } 172735811Smarc 172835811Smarc ttspeedtab(speed, table) 172935811Smarc struct speedtab table[]; 173035811Smarc { 173135811Smarc register int i; 173235811Smarc 173335811Smarc for (i = 0; table[i].sp_speed != -1; i++) 173435811Smarc if (table[i].sp_speed == speed) 173535811Smarc return(table[i].sp_code); 173635811Smarc return(-1); 173735811Smarc } 173839407Smarc 173941177Smarc int ttyhostname = 0; 174039407Smarc /* 174139407Smarc * (^T) 174239407Smarc * Report on state of foreground process group. 174339407Smarc */ 174439407Smarc ttyinfo(tp) 174539407Smarc struct tty *tp; 174639407Smarc { 174741177Smarc register struct proc *p, *pick = NULL; 174841177Smarc register char *cp = hostname; 174941177Smarc int x, s; 175041177Smarc struct timeval utime, stime; 175142350Smckusick #define pgtok(a) (((a)*NBPG)/1024) 175239407Smarc 175339407Smarc if (ttycheckoutq(tp,0) == 0) 175439407Smarc return; 175541177Smarc /* 175641177Smarc * hostname 175741177Smarc */ 175841177Smarc if (ttyhostname) { 175941177Smarc if (*cp == '\0') 176041177Smarc ttyprintf(tp, "amnesia"); 176141177Smarc else 176241177Smarc while (*cp && *cp != '.') 176341177Smarc tputchar(*cp++, tp); 176441177Smarc tputchar(' '); 176541177Smarc } 176641177Smarc /* 176741177Smarc * load average 176841177Smarc */ 176941177Smarc x = (averunnable[0] * 100 + FSCALE/2) >> FSHIFT; 177041177Smarc ttyprintf(tp, "load: %d.", x/100); 177141177Smarc ttyoutint(x%100, 10, 2, tp); 177239555Smarc if (tp->t_session == NULL) 177341177Smarc ttyprintf(tp, " not a controlling terminal\n"); 177441177Smarc else if (tp->t_pgrp == NULL) 177541177Smarc ttyprintf(tp, " no foreground process group\n"); 177641177Smarc else if ((p = tp->t_pgrp->pg_mem) == NULL) 177741177Smarc ttyprintf(tp, " empty foreground process group\n"); 177839407Smarc else { 177941177Smarc /* pick interesting process */ 178039407Smarc for (; p != NULL; p = p->p_pgrpnxt) { 178141177Smarc if (proc_compare(pick, p)) 178241177Smarc pick = p; 178339407Smarc } 178441177Smarc ttyprintf(tp, " cmd: %s %d [%s] ", 178541177Smarc pick->p_comm, pick->p_pid, 178641177Smarc pick->p_wmesg ? pick->p_wmesg : "running"); 178741177Smarc /* 178841177Smarc * cpu time 178941177Smarc */ 179041177Smarc if (u.u_procp == pick) 179141177Smarc s = splclock(); 179241177Smarc utime = pick->p_utime; 179341177Smarc stime = pick->p_stime; 179441177Smarc if (u.u_procp == pick) 179541177Smarc splx(s); 179641177Smarc /* user time */ 179741177Smarc x = (utime.tv_usec + 5000) / 10000; /* scale to 100's */ 179841177Smarc ttyoutint(utime.tv_sec, 10, 1, tp); 179941177Smarc tputchar('.', tp); 180041177Smarc ttyoutint(x, 10, 2, tp); 180141177Smarc tputchar('u', tp); 180241177Smarc tputchar(' ', tp); 180341177Smarc /* system time */ 180441177Smarc x = (stime.tv_usec + 5000) / 10000; /* scale to 100's */ 180541177Smarc ttyoutint(stime.tv_sec, 10, 1, tp); 180641177Smarc tputchar('.', tp); 180741177Smarc ttyoutint(x, 10, 2, tp); 180841177Smarc tputchar('s', tp); 180941177Smarc tputchar(' ', tp); 181041177Smarc /* 181141177Smarc * pctcpu 181241177Smarc */ 181341177Smarc x = pick->p_pctcpu * 10000 + FSCALE/2 >> FSHIFT; 181441177Smarc ttyoutint(x/100, 10, 1, tp); 181541177Smarc #ifdef notdef /* do we really want this ??? */ 181641177Smarc tputchar('.', tp); 181741177Smarc ttyoutint(x%100, 10, 2, tp); 181841177Smarc #endif 181941177Smarc ttyprintf(tp, "%% %dk\n", pgtok(pick->p_ssize + pick->p_dsize)); 182039407Smarc } 182141177Smarc tp->t_rocount = 0; /* so pending input will be retyped if BS */ 182239407Smarc } 182339407Smarc 182441177Smarc ttyoutint(n, base, min, tp) 182541177Smarc register int n, base, min; 182641177Smarc register struct tty *tp; 182741177Smarc { 182841177Smarc char info[16]; 182941177Smarc register char *p = info; 183041177Smarc 183141177Smarc while (--min >= 0 || n) { 183241177Smarc *p++ = "0123456789abcdef"[n%base]; 183341177Smarc n /= base; 183441177Smarc } 183541177Smarc while (p > info) 183641177Smarc ttyoutput(*--p, tp); 183741177Smarc } 183841177Smarc 183941177Smarc /* 184041177Smarc * Returns 1 if p2 is "better" than p1 184141177Smarc * 184241177Smarc * The algorithm for picking the "interesting" process is thus: 184341177Smarc * 184441177Smarc * 1) (Only foreground processes are eligable - implied) 184541177Smarc * 2) Runnable processes are favored over anything 184641177Smarc * else. The runner with the highest cpu 184741177Smarc * utilization is picked (p_cpu). Ties are 184841177Smarc * broken by picking the highest pid. 184941177Smarc * 3 Next, the sleeper with the shortest sleep 185041177Smarc * time is favored. With ties, we pick out 185141177Smarc * just "short-term" sleepers (SSINTR == 0). 185241177Smarc * Further ties are broken by picking the highest 185341177Smarc * pid. 185441177Smarc * 185541177Smarc */ 185641177Smarc #define isrun(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL)) 185741177Smarc proc_compare(p1, p2) 185841177Smarc register struct proc *p1, *p2; 185941177Smarc { 186041177Smarc 186141177Smarc if (p1 == NULL) 186241177Smarc return (1); 186341177Smarc /* 186441177Smarc * see if at least one of them is runnable 186541177Smarc */ 186641177Smarc switch (isrun(p1)<<1 | isrun(p2)) { 186741177Smarc case 0x01: 186841177Smarc return (1); 186941177Smarc case 0x10: 187041177Smarc return (0); 187141177Smarc case 0x11: 187241177Smarc /* 187341177Smarc * tie - favor one with highest recent cpu utilization 187441177Smarc */ 187541177Smarc if (p2->p_cpu > p1->p_cpu) 187641177Smarc return (1); 187741177Smarc if (p1->p_cpu > p2->p_cpu) 187841177Smarc return (0); 187941177Smarc return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 188041177Smarc } 188141177Smarc /* 188241177Smarc * pick the one with the smallest sleep time 188341177Smarc */ 188441177Smarc if (p2->p_slptime > p1->p_slptime) 188541177Smarc return (0); 188641177Smarc if (p1->p_slptime > p2->p_slptime) 188741177Smarc return (1); 188841177Smarc /* 188941177Smarc * favor one sleeping in a non-interruptible sleep 189041177Smarc */ 189141177Smarc if (p1->p_flag&SSINTR && (p2->p_flag&SSINTR) == 0) 189241177Smarc return (1); 189341177Smarc if (p2->p_flag&SSINTR && (p1->p_flag&SSINTR) == 0) 189441177Smarc return (0); 189541177Smarc return(p2->p_pid > p1->p_pid); /* tie - return highest pid */ 189641177Smarc } 189739407Smarc #define TOTTY 0x2 /* XXX should be in header */ 189839407Smarc /*VARARGS2*/ 189939407Smarc ttyprintf(tp, fmt, x1) 190039555Smarc struct tty *tp; 190139407Smarc char *fmt; 190239407Smarc unsigned x1; 190339407Smarc { 190439555Smarc prf(fmt, &x1, TOTTY, (caddr_t)tp); 190539407Smarc } 190639555Smarc 190739555Smarc /* 190839555Smarc * Output char to tty; console putchar style. 190939555Smarc */ 191039555Smarc tputchar(c, tp) 191139555Smarc int c; 191239555Smarc struct tty *tp; 191339555Smarc { 191439555Smarc register s = spltty(); 191539555Smarc 191639555Smarc if ((tp->t_state & (TS_CARR_ON | TS_ISOPEN)) 191739555Smarc == (TS_CARR_ON | TS_ISOPEN)) { 191839555Smarc if (c == '\n') 191939555Smarc (void) ttyoutput('\r', tp); 192039555Smarc (void) ttyoutput(c, tp); 192139555Smarc ttstart(tp); 192239555Smarc splx(s); 192339555Smarc return (0); 192439555Smarc } 192539555Smarc splx(s); 192639555Smarc return (-1); 192739555Smarc } 192843377Smarc 192944419Smarc /* 193044419Smarc * Sleep on chan. 193144419Smarc * 193244419Smarc * Return ERESTART if tty changed while we napped. 193344419Smarc */ 193443377Smarc ttysleep(tp, chan, pri, wmesg, timo) 193543377Smarc struct tty *tp; 193643377Smarc caddr_t chan; 193743377Smarc int pri; 193843377Smarc char *wmesg; 193943377Smarc int timo; 194043377Smarc { 194143377Smarc int error; 194243377Smarc short gen = tp->t_gen; 194343377Smarc 194443377Smarc if (error = tsleep(chan, pri, wmesg, timo)) 194543377Smarc return (error); 194643377Smarc if (tp->t_gen != gen) 194743377Smarc return (ERESTART); 194843377Smarc return (0); 194943377Smarc } 1950