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*47545Skarels * @(#)tty.c 7.38 (Berkeley) 03/17/91 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 84146Sbill /* 8535811Smarc * Is 'c' a line delimiter ("break" character)? 8639Sbill */ 8740712Skarels #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \ 8840712Skarels (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE) 8939Sbill 9039Sbill ttychars(tp) 919578Ssam struct tty *tp; 9239Sbill { 93*47545Skarels 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 /* 190*47545Skarels * Start output on the typewriter. It is used from the top half 191*47545Skarels * after some characters have been put on the output queue, 192*47545Skarels * from the interrupt routine to transmit the next 193*47545Skarels * character. 194121Sbill */ 195*47545Skarels ttstart(tp) 19637584Smarc struct tty *tp; 197121Sbill { 198121Sbill 199*47545Skarels if (tp->t_oproc) /* kludge for pty */ 200*47545Skarels (*tp->t_oproc)(tp); 201*47545Skarels } 202*47545Skarels 203*47545Skarels ttrstrt(tp) /* XXX */ 204*47545Skarels struct tty *tp; 205*47545Skarels { 206*47545Skarels 20740712Skarels #ifdef DIAGNOSTIC 2089578Ssam if (tp == 0) 2099578Ssam panic("ttrstrt"); 21040712Skarels #endif 2115408Swnj tp->t_state &= ~TS_TIMEOUT; 212903Sbill ttstart(tp); 213121Sbill } 214121Sbill 21539Sbill 21639Sbill /* 217903Sbill * Common code for tty ioctls. 21839Sbill */ 2191780Sbill /*ARGSUSED*/ 2207625Ssam ttioctl(tp, com, data, flag) 2217625Ssam register struct tty *tp; 2227625Ssam caddr_t data; 22339Sbill { 224*47545Skarels register struct proc *p = curproc; /* XXX */ 22539Sbill extern int nldisp; 22637554Smckusick int s, error; 22739Sbill 228903Sbill /* 229903Sbill * If the ioctl involves modification, 23017545Skarels * hang if in the background. 231903Sbill */ 2327625Ssam switch (com) { 23339Sbill 23435811Smarc case TIOCSETD: 235903Sbill case TIOCFLUSH: 23635811Smarc /*case TIOCSPGRP:*/ 2379325Ssam case TIOCSTI: 23817598Sbloom case TIOCSWINSZ: 23935811Smarc case TIOCSETA: 24035811Smarc case TIOCSETAW: 24135811Smarc case TIOCSETAF: 24240030Smarc #ifdef COMPAT_43 24340030Smarc case TIOCSETP: 24440030Smarc case TIOCSETN: 24540030Smarc case TIOCSETC: 24640030Smarc case TIOCSLTC: 24740030Smarc case TIOCLBIS: 24840030Smarc case TIOCLBIC: 24940030Smarc case TIOCLSET: 25040030Smarc case OTIOCSETD: 25140030Smarc #endif 252*47545Skarels while (isbackground(curproc, tp) && 253*47545Skarels p->p_pgrp->pg_jobc && (p->p_flag&SPPWAIT) == 0 && 254*47545Skarels (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 255*47545Skarels (p->p_sigmask & sigmask(SIGTTOU)) == 0) { 256*47545Skarels pgsignal(p->p_pgrp, SIGTTOU, 1); 25743377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 25843377Smarc TTOPRI | PCATCH, ttybg, 0)) 25940712Skarels return (error); 260903Sbill } 261903Sbill break; 262903Sbill } 263903Sbill 2649578Ssam /* 2659578Ssam * Process the ioctl. 2669578Ssam */ 2677625Ssam switch (com) { 268903Sbill 2698556Sroot /* get discipline number */ 27039Sbill case TIOCGETD: 2717625Ssam *(int *)data = tp->t_line; 27239Sbill break; 27339Sbill 2748556Sroot /* set line discipline */ 2757625Ssam case TIOCSETD: { 2767625Ssam register int t = *(int *)data; 27735811Smarc dev_t dev = tp->t_dev; 2787625Ssam 27935811Smarc if ((unsigned)t >= nldisp) 28010851Ssam return (ENXIO); 28125584Skarels if (t != tp->t_line) { 28225584Skarels s = spltty(); 28325584Skarels (*linesw[tp->t_line].l_close)(tp); 28425584Skarels error = (*linesw[t].l_open)(dev, tp); 28525584Skarels if (error) { 28635811Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp); 28725584Skarels splx(s); 28825584Skarels return (error); 28925584Skarels } 29025584Skarels tp->t_line = t; 29110851Ssam splx(s); 29210851Ssam } 29339Sbill break; 2947625Ssam } 29539Sbill 2968556Sroot /* prevent more opens on channel */ 2975614Swnj case TIOCEXCL: 2985614Swnj tp->t_state |= TS_XCLUDE; 2995614Swnj break; 3005614Swnj 3015614Swnj case TIOCNXCL: 3025614Swnj tp->t_state &= ~TS_XCLUDE; 3035614Swnj break; 3045614Swnj 30539Sbill case TIOCHPCL: 30635811Smarc tp->t_cflag |= HUPCL; 30739Sbill break; 30839Sbill 3093942Sbugs case TIOCFLUSH: { 3107625Ssam register int flags = *(int *)data; 3117625Ssam 3127625Ssam if (flags == 0) 3133942Sbugs flags = FREAD|FWRITE; 3147625Ssam else 3157625Ssam flags &= FREAD|FWRITE; 31612752Ssam ttyflush(tp, flags); 31739Sbill break; 3183944Sbugs } 31939Sbill 32037584Smarc case FIOASYNC: 32137584Smarc if (*(int *)data) 32237584Smarc tp->t_state |= TS_ASYNC; 32337584Smarc else 32437584Smarc tp->t_state &= ~TS_ASYNC; 32537584Smarc break; 32637584Smarc 32737584Smarc case FIONBIO: 32837584Smarc break; /* XXX remove */ 32937584Smarc 3308556Sroot /* return number of characters immediately available */ 3317625Ssam case FIONREAD: 3327625Ssam *(off_t *)data = ttnread(tp); 333174Sbill break; 334174Sbill 33513077Ssam case TIOCOUTQ: 33613077Ssam *(int *)data = tp->t_outq.c_cc; 33713077Ssam break; 33813077Ssam 3398589Sroot case TIOCSTOP: 34017545Skarels s = spltty(); 3419578Ssam if ((tp->t_state&TS_TTSTOP) == 0) { 3425573Swnj tp->t_state |= TS_TTSTOP; 3435573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 3445573Swnj } 3457625Ssam splx(s); 3465573Swnj break; 3475573Swnj 3488589Sroot case TIOCSTART: 34917545Skarels s = spltty(); 35035811Smarc if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 3515573Swnj tp->t_state &= ~TS_TTSTOP; 35235811Smarc tp->t_lflag &= ~FLUSHO; 3535573Swnj ttstart(tp); 3545573Swnj } 3557625Ssam splx(s); 3565573Swnj break; 3575573Swnj 3589325Ssam /* 3599325Ssam * Simulate typing of a character at the terminal. 3609325Ssam */ 3619325Ssam case TIOCSTI: 362*47545Skarels if (p->p_ucred->cr_uid && (flag & FREAD) == 0) 36317183Smckusick return (EPERM); 364*47545Skarels if (p->p_ucred->cr_uid && !isctty(p, tp)) 3659325Ssam return (EACCES); 3669578Ssam (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 3679325Ssam break; 3689325Ssam 36935811Smarc case TIOCGETA: { 37035811Smarc struct termios *t = (struct termios *)data; 37112752Ssam 37235811Smarc bcopy(&tp->t_termios, t, sizeof(struct termios)); 37335811Smarc break; 37435811Smarc } 37535811Smarc 37635811Smarc case TIOCSETA: 37735811Smarc case TIOCSETAW: 37837584Smarc case TIOCSETAF: { 37935811Smarc register struct termios *t = (struct termios *)data; 38040712Skarels 38117545Skarels s = spltty(); 38239407Smarc if (com == TIOCSETAW || com == TIOCSETAF) { 38340712Skarels if (error = ttywait(tp)) { 38440712Skarels splx(s); 38540712Skarels return (error); 38640712Skarels } 38745007Smarc if (com == TIOCSETAF) 38839407Smarc ttyflush(tp, FREAD); 38939407Smarc } 39040712Skarels if ((t->c_cflag&CIGNORE) == 0) { 39135811Smarc /* 39235811Smarc * set device hardware 39335811Smarc */ 39437584Smarc if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 39537584Smarc splx(s); 39635811Smarc return (error); 39737584Smarc } else { 39840712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && 39937584Smarc (tp->t_cflag&CLOCAL) && 40040712Skarels (t->c_cflag&CLOCAL) == 0) { 40137584Smarc tp->t_state &= ~TS_ISOPEN; 40237584Smarc tp->t_state |= TS_WOPEN; 40337584Smarc ttwakeup(tp); 40437584Smarc } 40535811Smarc tp->t_cflag = t->c_cflag; 40635811Smarc tp->t_ispeed = t->c_ispeed; 40735811Smarc tp->t_ospeed = t->c_ospeed; 40834492Skarels } 40935811Smarc ttsetwater(tp); 41012752Ssam } 41139407Smarc if (com != TIOCSETAF) { 41235811Smarc if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 41335811Smarc if (t->c_lflag&ICANON) { 41435811Smarc tp->t_lflag |= PENDIN; 41535811Smarc ttwakeup(tp); 41635811Smarc } 41735811Smarc else { 41835811Smarc struct clist tq; 41935811Smarc 42035811Smarc catq(&tp->t_rawq, &tp->t_canq); 42135811Smarc tq = tp->t_rawq; 42235811Smarc tp->t_rawq = tp->t_canq; 42335811Smarc tp->t_canq = tq; 42435811Smarc } 42512752Ssam } 42635811Smarc tp->t_iflag = t->c_iflag; 42735811Smarc tp->t_oflag = t->c_oflag; 42842882Smarc /* 42942882Smarc * Make the EXTPROC bit read only. 43042882Smarc */ 43142882Smarc if (tp->t_lflag&EXTPROC) 43242882Smarc t->c_lflag |= EXTPROC; 43342882Smarc else 43442882Smarc t->c_lflag &= ~EXTPROC; 43535811Smarc tp->t_lflag = t->c_lflag; 43635811Smarc bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 43712752Ssam splx(s); 43812752Ssam break; 43912752Ssam } 44012752Ssam 44112752Ssam /* 44239555Smarc * Set controlling terminal. 44339555Smarc * Session ctty vnode pointer set in vnode layer. 44434492Skarels */ 445*47545Skarels case TIOCSCTTY: 44639555Smarc if (!SESS_LEADER(p) || 44739555Smarc (p->p_session->s_ttyvp || tp->t_session) && 44839555Smarc (tp->t_session != p->p_session)) 44939407Smarc return (EPERM); 45035811Smarc tp->t_session = p->p_session; 45139555Smarc tp->t_pgrp = p->p_pgrp; 45239555Smarc p->p_session->s_ttyp = tp; 45339555Smarc p->p_flag |= SCTTY; 45434492Skarels break; 45539555Smarc 45634492Skarels /* 45735811Smarc * Set terminal process group. 45817545Skarels */ 45918650Sbloom case TIOCSPGRP: { 46035811Smarc register struct pgrp *pgrp = pgfind(*(int *)data); 46117545Skarels 46239555Smarc if (!isctty(p, tp)) 46339555Smarc return (ENOTTY); 46440030Smarc else if (pgrp == NULL || pgrp->pg_session != p->p_session) 46539555Smarc return (EPERM); 46639555Smarc tp->t_pgrp = pgrp; 46712752Ssam break; 46818650Sbloom } 46912752Ssam 47012752Ssam case TIOCGPGRP: 471*47545Skarels if (!isctty(p, tp)) 47239555Smarc return (ENOTTY); 47345007Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 47412752Ssam break; 47512752Ssam 47617598Sbloom case TIOCSWINSZ: 47718650Sbloom if (bcmp((caddr_t)&tp->t_winsize, data, 47818650Sbloom sizeof (struct winsize))) { 47917598Sbloom tp->t_winsize = *(struct winsize *)data; 48042882Smarc pgsignal(tp->t_pgrp, SIGWINCH, 1); 48117598Sbloom } 48217598Sbloom break; 48317598Sbloom 48417598Sbloom case TIOCGWINSZ: 48517598Sbloom *(struct winsize *)data = tp->t_winsize; 48617598Sbloom break; 48717598Sbloom 48830534Skarels case TIOCCONS: 48930534Skarels if (*(int *)data) { 49042141Smckusick if (constty && constty != tp && 49142141Smckusick (constty->t_state & (TS_CARR_ON|TS_ISOPEN)) == 49242141Smckusick (TS_CARR_ON|TS_ISOPEN)) 49330534Skarels return (EBUSY); 49430534Skarels #ifndef UCONSOLE 495*47545Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 49637554Smckusick return (error); 49730534Skarels #endif 49830534Skarels constty = tp; 49930534Skarels } else if (tp == constty) 50033404Skarels constty = NULL; 50130534Skarels break; 50230534Skarels 503*47545Skarels default: 50435811Smarc #ifdef COMPAT_43 505*47545Skarels return (ttcompat(tp, com, data, flag)); 506*47545Skarels #else 507*47545Skarels return (-1); 50835811Smarc #endif 50939Sbill } 5108556Sroot return (0); 51139Sbill } 5124484Swnj 5134484Swnj ttnread(tp) 5144484Swnj struct tty *tp; 5154484Swnj { 5164484Swnj int nread = 0; 5174484Swnj 51835811Smarc if (tp->t_lflag & PENDIN) 5194484Swnj ttypend(tp); 5204484Swnj nread = tp->t_canq.c_cc; 52135811Smarc if ((tp->t_lflag & ICANON) == 0) 5224484Swnj nread += tp->t_rawq.c_cc; 5234484Swnj return (nread); 5244484Swnj } 5254484Swnj 5265408Swnj ttselect(dev, rw) 5274484Swnj dev_t dev; 5285408Swnj int rw; 5294484Swnj { 5304484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5314484Swnj int nread; 53217545Skarels int s = spltty(); 5334484Swnj 5345408Swnj switch (rw) { 5354484Swnj 5364484Swnj case FREAD: 5374484Swnj nread = ttnread(tp); 53837584Smarc if (nread > 0 || 53940712Skarels ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0)) 5405408Swnj goto win; 5414938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5425408Swnj tp->t_state |= TS_RCOLL; 5434484Swnj else 544*47545Skarels tp->t_rsel = curproc; 5455408Swnj break; 5464484Swnj 5475408Swnj case FWRITE: 54835811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 5495408Swnj goto win; 5505408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 5515408Swnj tp->t_state |= TS_WCOLL; 5525408Swnj else 553*47545Skarels tp->t_wsel = curproc; 5545408Swnj break; 5554484Swnj } 5565408Swnj splx(s); 5575408Swnj return (0); 5585408Swnj win: 5595408Swnj splx(s); 5605408Swnj return (1); 5614484Swnj } 5627436Skre 5637502Sroot /* 56425391Skarels * Initial open of tty, or (re)entry to line discipline. 5657502Sroot */ 5667502Sroot ttyopen(dev, tp) 5677625Ssam dev_t dev; 5687625Ssam register struct tty *tp; 5697502Sroot { 5707502Sroot 5717502Sroot tp->t_dev = dev; 57235811Smarc 5737502Sroot tp->t_state &= ~TS_WOPEN; 57417545Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 57517545Skarels tp->t_state |= TS_ISOPEN; 57617598Sbloom bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 57717545Skarels } 5788556Sroot return (0); 5797502Sroot } 5807502Sroot 5817502Sroot /* 58225391Skarels * "close" a line discipline 58325391Skarels */ 58425391Skarels ttylclose(tp) 58525391Skarels register struct tty *tp; 58625391Skarels { 58725391Skarels 58825391Skarels ttywflush(tp); 58925391Skarels } 59025391Skarels 59125391Skarels /* 5927502Sroot * clean tp on last close 5937502Sroot */ 5947502Sroot ttyclose(tp) 5957625Ssam register struct tty *tp; 5967502Sroot { 59730534Skarels if (constty == tp) 59830534Skarels constty = NULL; 59925391Skarels ttyflush(tp, FREAD|FWRITE); 60039555Smarc tp->t_session = NULL; 60139555Smarc tp->t_pgrp = NULL; 6027502Sroot tp->t_state = 0; 60343377Smarc tp->t_gen++; 60440712Skarels return (0); 6057502Sroot } 6067502Sroot 6077502Sroot /* 60825391Skarels * Handle modem control transition on a tty. 60925391Skarels * Flag indicates new state of carrier. 61025391Skarels * Returns 0 if the line should be turned off, otherwise 1. 61125391Skarels */ 61225391Skarels ttymodem(tp, flag) 61325391Skarels register struct tty *tp; 61425391Skarels { 61525391Skarels 61642193Smarc if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) { 61725391Skarels /* 61825391Skarels * MDMBUF: do flow control according to carrier flag 61925391Skarels */ 62025391Skarels if (flag) { 62125391Skarels tp->t_state &= ~TS_TTSTOP; 62225391Skarels ttstart(tp); 62325391Skarels } else if ((tp->t_state&TS_TTSTOP) == 0) { 62425391Skarels tp->t_state |= TS_TTSTOP; 62525391Skarels (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 62625391Skarels } 62725391Skarels } else if (flag == 0) { 62825391Skarels /* 62925391Skarels * Lost carrier. 63025391Skarels */ 63125391Skarels tp->t_state &= ~TS_CARR_ON; 63242193Smarc if (tp->t_state&TS_ISOPEN && (tp->t_cflag&CLOCAL) == 0) { 63342193Smarc if (tp->t_session && tp->t_session->s_leader) 63442193Smarc psignal(tp->t_session->s_leader, SIGHUP); 63542193Smarc ttyflush(tp, FREAD|FWRITE); 63642193Smarc return (0); 63725391Skarels } 63825391Skarels } else { 63925391Skarels /* 64025391Skarels * Carrier now on. 64125391Skarels */ 64225391Skarels tp->t_state |= TS_CARR_ON; 64337584Smarc ttwakeup(tp); 64425391Skarels } 64525391Skarels return (1); 64625391Skarels } 64725391Skarels 64825391Skarels /* 64925404Skarels * Default modem control routine (for other line disciplines). 65025404Skarels * Return argument flag, to turn off device on carrier drop. 65125404Skarels */ 65225415Skarels nullmodem(tp, flag) 65325415Skarels register struct tty *tp; 65425404Skarels int flag; 65525404Skarels { 65625404Skarels 65725404Skarels if (flag) 65825404Skarels tp->t_state |= TS_CARR_ON; 65939407Smarc else { 66025404Skarels tp->t_state &= ~TS_CARR_ON; 66142193Smarc if ((tp->t_cflag&CLOCAL) == 0) { 66242193Smarc if (tp->t_session && tp->t_session->s_leader) 66342193Smarc psignal(tp->t_session->s_leader, SIGHUP); 66442193Smarc return (0); 66542193Smarc } 66639407Smarc } 66742193Smarc return (1); 66825404Skarels } 66925404Skarels 67025404Skarels /* 6717502Sroot * reinput pending characters after state switch 67217545Skarels * call at spltty(). 6737502Sroot */ 6747502Sroot ttypend(tp) 6757625Ssam register struct tty *tp; 6767502Sroot { 6777502Sroot struct clist tq; 6787502Sroot register c; 6797502Sroot 68035811Smarc tp->t_lflag &= ~PENDIN; 6819578Ssam tp->t_state |= TS_TYPEN; 6827502Sroot tq = tp->t_rawq; 6837502Sroot tp->t_rawq.c_cc = 0; 6847502Sroot tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 6857502Sroot while ((c = getc(&tq)) >= 0) 6867502Sroot ttyinput(c, tp); 6879578Ssam tp->t_state &= ~TS_TYPEN; 6887502Sroot } 6897502Sroot 6907502Sroot /* 69135811Smarc * 6929578Ssam * Place a character on raw TTY input queue, 6939578Ssam * putting in delimiters and waking up top 6949578Ssam * half as needed. Also echo if required. 6959578Ssam * The arguments are the character and the 6969578Ssam * appropriate tty structure. 6977502Sroot */ 6987502Sroot ttyinput(c, tp) 6997625Ssam register c; 7007625Ssam register struct tty *tp; 7017502Sroot { 70235811Smarc register int iflag = tp->t_iflag; 70335811Smarc register int lflag = tp->t_lflag; 70435811Smarc register u_char *cc = tp->t_cc; 70535811Smarc int i, err; 7067502Sroot 7079578Ssam /* 7089578Ssam * If input is pending take it first. 7099578Ssam */ 71035811Smarc if (lflag&PENDIN) 7117502Sroot ttypend(tp); 71235811Smarc /* 71335811Smarc * Gather stats. 71435811Smarc */ 7157502Sroot tk_nin++; 71635811Smarc if (lflag&ICANON) { 71735811Smarc tk_cancc++; 71835811Smarc tp->t_cancc++; 71935811Smarc } else { 72035811Smarc tk_rawcc++; 72135811Smarc tp->t_rawcc++; 72235811Smarc } 7239578Ssam /* 72435811Smarc * Handle exceptional conditions (break, parity, framing). 7259578Ssam */ 72635811Smarc if (err = (c&TTY_ERRORMASK)) { 72735811Smarc c &= ~TTY_ERRORMASK; 72835811Smarc if (err&TTY_FE && !c) { /* break */ 72935811Smarc if (iflag&IGNBRK) 73035811Smarc goto endcase; 73135811Smarc else if (iflag&BRKINT && lflag&ISIG && 73235811Smarc (cc[VINTR] != _POSIX_VDISABLE)) 73335811Smarc c = cc[VINTR]; 734*47545Skarels else if (iflag&PARMRK) 735*47545Skarels goto parmrk; 73635811Smarc } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 73735811Smarc if (iflag&IGNPAR) 73835811Smarc goto endcase; 73935811Smarc else if (iflag&PARMRK) { 74035811Smarc parmrk: 74135811Smarc putc(0377|TTY_QUOTE, &tp->t_rawq); 74235811Smarc putc(0|TTY_QUOTE, &tp->t_rawq); 74335811Smarc putc(c|TTY_QUOTE, &tp->t_rawq); 74435811Smarc goto endcase; 74535811Smarc } else 74635811Smarc c = 0; 7477502Sroot } 7489578Ssam } 7499578Ssam /* 75035811Smarc * In tandem mode, check high water mark. 7519578Ssam */ 75235811Smarc if (iflag&IXOFF) 75335811Smarc ttyblock(tp); 75435811Smarc if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 7559578Ssam c &= 0177; 75644419Smarc if ((tp->t_lflag&EXTPROC) == 0) { 75744419Smarc /* 75844419Smarc * Check for literal nexting very first 75944419Smarc */ 76044419Smarc if (tp->t_state&TS_LNCH) { 76144419Smarc c |= TTY_QUOTE; 76244419Smarc tp->t_state &= ~TS_LNCH; 76344419Smarc } 76444419Smarc /* 76544419Smarc * Scan for special characters. This code 76644419Smarc * is really just a big case statement with 76744419Smarc * non-constant cases. The bottom of the 76844419Smarc * case statement is labeled ``endcase'', so goto 76944419Smarc * it after a case match, or similar. 77044419Smarc */ 77144419Smarc 77244419Smarc /* 77344419Smarc * Control chars which aren't controlled 77444419Smarc * by ICANON, ISIG, or IXON. 77544419Smarc */ 77644419Smarc if (lflag&IEXTEN) { 77744419Smarc if (CCEQ(cc[VLNEXT], c)) { 77844419Smarc if (lflag&ECHO) { 77944419Smarc if (lflag&ECHOE) 78044419Smarc ttyoutstr("^\b", tp); 78144419Smarc else 78244419Smarc ttyecho(c, tp); 78344419Smarc } 78444419Smarc tp->t_state |= TS_LNCH; 78544419Smarc goto endcase; 78644419Smarc } 78744419Smarc if (CCEQ(cc[VDISCARD], c)) { 78844419Smarc if (lflag&FLUSHO) 78944419Smarc tp->t_lflag &= ~FLUSHO; 79044419Smarc else { 79144419Smarc ttyflush(tp, FWRITE); 79235811Smarc ttyecho(c, tp); 79344419Smarc if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 79444419Smarc ttyretype(tp); 79544419Smarc tp->t_lflag |= FLUSHO; 79644419Smarc } 79744419Smarc goto startoutput; 79835811Smarc } 7999578Ssam } 80044419Smarc /* 80144419Smarc * Signals. 80244419Smarc */ 80344419Smarc if (lflag&ISIG) { 80444419Smarc if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 80544419Smarc if ((lflag&NOFLSH) == 0) 80644419Smarc ttyflush(tp, FREAD|FWRITE); 8077502Sroot ttyecho(c, tp); 80844419Smarc pgsignal(tp->t_pgrp, 80944419Smarc CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 81044419Smarc goto endcase; 8117502Sroot } 81244419Smarc if (CCEQ(cc[VSUSP], c)) { 81344419Smarc if ((lflag&NOFLSH) == 0) 81444419Smarc ttyflush(tp, FREAD); 81544419Smarc ttyecho(c, tp); 81644419Smarc pgsignal(tp->t_pgrp, SIGTSTP, 1); 81744419Smarc goto endcase; 81844419Smarc } 8199578Ssam } 82044419Smarc /* 82144419Smarc * Handle start/stop characters. 82244419Smarc */ 82344419Smarc if (iflag&IXON) { 82444419Smarc if (CCEQ(cc[VSTOP], c)) { 82544419Smarc if ((tp->t_state&TS_TTSTOP) == 0) { 82644419Smarc tp->t_state |= TS_TTSTOP; 82744419Smarc (*cdevsw[major(tp->t_dev)].d_stop)(tp, 82844419Smarc 0); 82944419Smarc return; 83044419Smarc } 83144419Smarc if (!CCEQ(cc[VSTART], c)) 83244419Smarc return; 83344419Smarc /* 83444419Smarc * if VSTART == VSTOP then toggle 83544419Smarc */ 83644419Smarc goto endcase; 83735811Smarc } 83844419Smarc if (CCEQ(cc[VSTART], c)) 83944419Smarc goto restartoutput; 8409578Ssam } 84144419Smarc /* 84244419Smarc * IGNCR, ICRNL, & INLCR 84344419Smarc */ 84444419Smarc if (c == '\r') { 84544419Smarc if (iflag&IGNCR) 84644419Smarc goto endcase; 84744419Smarc else if (iflag&ICRNL) 84844419Smarc c = '\n'; 84944419Smarc } else if (c == '\n' && iflag&INLCR) 85044419Smarc c = '\r'; 8519578Ssam } 852*47545Skarels if ((tp->t_lflag&EXTPROC) == 0 && lflag&ICANON) { 85344419Smarc /* 85444419Smarc * From here on down canonical mode character 85544419Smarc * processing takes place. 85644419Smarc */ 85744419Smarc /* 85844419Smarc * erase (^H / ^?) 85944419Smarc */ 86044419Smarc if (CCEQ(cc[VERASE], c)) { 86144419Smarc if (tp->t_rawq.c_cc) 8629578Ssam ttyrub(unputc(&tp->t_rawq), tp); 86344419Smarc goto endcase; 8649578Ssam } 86544419Smarc /* 86644419Smarc * kill (^U) 86744419Smarc */ 86844419Smarc if (CCEQ(cc[VKILL], c)) { 86944419Smarc if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 87044419Smarc (lflag&ECHOPRT) == 0) { 87144419Smarc while (tp->t_rawq.c_cc) 87244419Smarc ttyrub(unputc(&tp->t_rawq), tp); 87344419Smarc } else { 87444419Smarc ttyecho(c, tp); 87544419Smarc if (lflag&ECHOK || lflag&ECHOKE) 87644419Smarc ttyecho('\n', tp); 87744419Smarc while (getc(&tp->t_rawq) > 0) 87844419Smarc ; 87944419Smarc tp->t_rocount = 0; 88044419Smarc } 88144419Smarc tp->t_state &= ~TS_LOCAL; 88244419Smarc goto endcase; 88344419Smarc } 88444419Smarc /* 88544419Smarc * word erase (^W) 88644419Smarc */ 88744419Smarc if (CCEQ(cc[VWERASE], c)) { 88844419Smarc int ctype; 889*47545Skarels int alt = lflag&ALTWERASE; 89035811Smarc 891*47545Skarels #define CTYPE(c) (partab[(c)&TTY_CHARMASK]&0100) 89244419Smarc /* 89344419Smarc * erase whitespace 89444419Smarc */ 89544419Smarc while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 89644419Smarc ttyrub(c, tp); 89744419Smarc if (c == -1) 89844419Smarc goto endcase; 89944419Smarc /* 900*47545Skarels * erase last char of word and remember the 901*47545Skarels * next chars type (for ALTWERASE) 90244419Smarc */ 90335811Smarc ttyrub(c, tp); 90444419Smarc c = unputc(&tp->t_rawq); 905*47545Skarels if (c == -1) 90644419Smarc goto endcase; 907*47545Skarels ctype = CTYPE(c); 90844419Smarc /* 909*47545Skarels * erase rest of word 91044419Smarc */ 91144419Smarc do { 91244419Smarc ttyrub(c, tp); 91344419Smarc c = unputc(&tp->t_rawq); 91444419Smarc if (c == -1) 91544419Smarc goto endcase; 916*47545Skarels } while (c != ' ' && c != '\t' && 917*47545Skarels (alt == 0 || CTYPE(c) == ctype)); 91844419Smarc (void) putc(c, &tp->t_rawq); 91934492Skarels goto endcase; 92044419Smarc #undef CTYPE 92144419Smarc } 92235811Smarc /* 92344419Smarc * reprint line (^R) 92435811Smarc */ 92544419Smarc if (CCEQ(cc[VREPRINT], c)) { 92644419Smarc ttyretype(tp); 92734492Skarels goto endcase; 92834492Skarels } 92935811Smarc /* 93044419Smarc * ^T - kernel info and generate SIGINFO 93135811Smarc */ 93244419Smarc if (CCEQ(cc[VSTATUS], c)) { 93344419Smarc pgsignal(tp->t_pgrp, SIGINFO, 1); 93444419Smarc if ((lflag&NOKERNINFO) == 0) 93544419Smarc ttyinfo(tp); 93644419Smarc goto endcase; 93744419Smarc } 9389578Ssam } 9399578Ssam /* 9409578Ssam * Check for input buffer overflow 9419578Ssam */ 942*47545Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { 94335811Smarc if (iflag&IMAXBEL) { 94435811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 94535811Smarc (void) ttyoutput(CTRL('g'), tp); 94635811Smarc } else 94735811Smarc ttyflush(tp, FREAD | FWRITE); 9489578Ssam goto endcase; 94910391Ssam } 9509578Ssam /* 9519578Ssam * Put data char in q for user and 9529578Ssam * wakeup on seeing a line delimiter. 9539578Ssam */ 9549578Ssam if (putc(c, &tp->t_rawq) >= 0) { 955*47545Skarels if ((lflag&ICANON) == 0) { 956*47545Skarels ttwakeup(tp); 957*47545Skarels ttyecho(c, tp); 958*47545Skarels goto endcase; 959*47545Skarels } 96035811Smarc if (ttbreakc(c)) { 9619578Ssam tp->t_rocount = 0; 9629578Ssam catq(&tp->t_rawq, &tp->t_canq); 9637502Sroot ttwakeup(tp); 9649578Ssam } else if (tp->t_rocount++ == 0) 9659578Ssam tp->t_rocol = tp->t_col; 9669578Ssam if (tp->t_state&TS_ERASE) { 96735811Smarc /* 96835811Smarc * end of prterase \.../ 96935811Smarc */ 9709578Ssam tp->t_state &= ~TS_ERASE; 9719578Ssam (void) ttyoutput('/', tp); 9729578Ssam } 9739578Ssam i = tp->t_col; 9747502Sroot ttyecho(c, tp); 97535811Smarc if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 97635811Smarc /* 97735811Smarc * Place the cursor over the '^' of the ^D. 97835811Smarc */ 9799578Ssam i = MIN(2, tp->t_col - i); 9809578Ssam while (i > 0) { 9819578Ssam (void) ttyoutput('\b', tp); 9829578Ssam i--; 9839578Ssam } 9849578Ssam } 9857502Sroot } 9869578Ssam endcase: 9879578Ssam /* 98835811Smarc * IXANY means allow any character to restart output. 9899578Ssam */ 99040712Skarels if ((tp->t_state&TS_TTSTOP) && (iflag&IXANY) == 0 && 99140712Skarels cc[VSTART] != cc[VSTOP]) 9927502Sroot return; 9939578Ssam restartoutput: 9947502Sroot tp->t_state &= ~TS_TTSTOP; 99535811Smarc tp->t_lflag &= ~FLUSHO; 9969578Ssam startoutput: 9977502Sroot ttstart(tp); 9987502Sroot } 9997502Sroot 10007502Sroot /* 10019578Ssam * Put character on TTY output queue, adding delays, 10027502Sroot * expanding tabs, and handling the CR/NL bit. 10039578Ssam * This is called both from the top half for output, 10049578Ssam * and from interrupt level for echoing. 10057502Sroot * The arguments are the character and the tty structure. 10067502Sroot * Returns < 0 if putc succeeds, otherwise returns char to resend 10077502Sroot * Must be recursive. 10087502Sroot */ 10097502Sroot ttyoutput(c, tp) 10107502Sroot register c; 10117502Sroot register struct tty *tp; 10127502Sroot { 101344419Smarc register short *colp; 10147502Sroot register ctype; 101535811Smarc register long oflag = tp->t_oflag; 101635811Smarc 101740712Skarels if ((oflag&OPOST) == 0) { 101835811Smarc if (tp->t_lflag&FLUSHO) 10197502Sroot return (-1); 10207502Sroot if (putc(c, &tp->t_outq)) 10217625Ssam return (c); 10227502Sroot tk_nout++; 102335811Smarc tp->t_outcc++; 10247502Sroot return (-1); 10257502Sroot } 102635811Smarc c &= TTY_CHARMASK; 10277502Sroot /* 10287502Sroot * Turn tabs to spaces as required 102942882Smarc * 103042882Smarc * Special case if we have external processing, we don't 103142882Smarc * do the tab expansion because we'll probably get it 103242882Smarc * wrong. If tab expansion needs to be done, let it 103342882Smarc * happen externally. 10347502Sroot */ 1035*47545Skarels if (c == '\t' && oflag&OXTABS && (tp->t_lflag&EXTPROC) == 0) { 10367502Sroot register int s; 10377502Sroot 10387502Sroot c = 8 - (tp->t_col&7); 103935811Smarc if ((tp->t_lflag&FLUSHO) == 0) { 104017545Skarels s = spltty(); /* don't interrupt tabs */ 10417502Sroot c -= b_to_q(" ", c, &tp->t_outq); 10427502Sroot tk_nout += c; 104335811Smarc tp->t_outcc += c; 10447502Sroot splx(s); 10457502Sroot } 10467502Sroot tp->t_col += c; 10477502Sroot return (c ? -1 : '\t'); 10487502Sroot } 104935811Smarc if (c == CEOT && oflag&ONOEOT) 1050*47545Skarels return (-1); 10517502Sroot tk_nout++; 105235811Smarc tp->t_outcc++; 10537502Sroot /* 10547502Sroot * turn <nl> to <cr><lf> if desired. 10557502Sroot */ 105635811Smarc if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 10577502Sroot return (c); 105835811Smarc if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 105935811Smarc return (c); 1060*47545Skarels 10617502Sroot colp = &tp->t_col; 10627502Sroot ctype = partab[c]; 10637502Sroot switch (ctype&077) { 10647502Sroot 10657502Sroot case ORDINARY: 10667502Sroot (*colp)++; 10677502Sroot 10687502Sroot case CONTROL: 10697502Sroot break; 10707502Sroot 10717502Sroot case BACKSPACE: 10727502Sroot if (*colp) 10737502Sroot (*colp)--; 10747502Sroot break; 10757502Sroot 10767502Sroot case NEWLINE: 10777502Sroot *colp = 0; 10787502Sroot break; 10797502Sroot 10807502Sroot case TAB: 10817502Sroot *colp |= 07; 10827502Sroot (*colp)++; 10837502Sroot break; 10847502Sroot 10857502Sroot case RETURN: 10867502Sroot *colp = 0; 10877502Sroot } 10887502Sroot return (-1); 10897502Sroot } 10907502Sroot 10917502Sroot /* 10927502Sroot * Called from device's read routine after it has 10937502Sroot * calculated the tty-structure given as argument. 10947502Sroot */ 109537584Smarc ttread(tp, uio, flag) 10967625Ssam register struct tty *tp; 10977722Swnj struct uio *uio; 10987502Sroot { 10997502Sroot register struct clist *qp; 110035811Smarc register int c; 110141383Smarc register long lflag; 110235811Smarc register u_char *cc = tp->t_cc; 1103*47545Skarels register struct proc *p = curproc; 11049859Ssam int s, first, error = 0; 11057502Sroot 11067502Sroot loop: 110741383Smarc lflag = tp->t_lflag; 110837584Smarc s = spltty(); 11099578Ssam /* 111037584Smarc * take pending input first 11119578Ssam */ 111235811Smarc if (lflag&PENDIN) 11137502Sroot ttypend(tp); 11149859Ssam splx(s); 111540712Skarels 11169578Ssam /* 11179578Ssam * Hang process if it's in the background. 11189578Ssam */ 1119*47545Skarels if (isbackground(p, tp)) { 1120*47545Skarels if ((p->p_sigignore & sigmask(SIGTTIN)) || 1121*47545Skarels (p->p_sigmask & sigmask(SIGTTIN)) || 1122*47545Skarels p->p_flag&SPPWAIT || p->p_pgrp->pg_jobc == 0) 11238520Sroot return (EIO); 1124*47545Skarels pgsignal(p->p_pgrp, SIGTTIN, 1); 112543377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 112643377Smarc ttybg, 0)) 112740712Skarels return (error); 112823165Sbloom goto loop; 11297502Sroot } 113040712Skarels 11319578Ssam /* 113235811Smarc * If canonical, use the canonical queue, 113335811Smarc * else use the raw queue. 113437584Smarc * 1135*47545Skarels * (should get rid of clists...) 11369578Ssam */ 113735811Smarc qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 113840712Skarels 11399578Ssam /* 114040712Skarels * If there is no input, sleep on rawq 114140712Skarels * awaiting hardware receipt and notification. 114240712Skarels * If we have data, we don't need to check for carrier. 11439578Ssam */ 114417545Skarels s = spltty(); 11459578Ssam if (qp->c_cc <= 0) { 114640712Skarels int carrier; 114740712Skarels 114840712Skarels carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL); 114940712Skarels if (!carrier && tp->t_state&TS_ISOPEN) { 11509859Ssam splx(s); 115140712Skarels return (0); /* EOF */ 11527502Sroot } 115337728Smckusick if (flag & IO_NDELAY) { 115437584Smarc splx(s); 115537584Smarc return (EWOULDBLOCK); 115637584Smarc } 115743377Smarc error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 115840712Skarels carrier ? ttyin : ttopen, 0); 11599859Ssam splx(s); 116043377Smarc if (error) 116140712Skarels return (error); 11629578Ssam goto loop; 11639578Ssam } 11649859Ssam splx(s); 116540712Skarels 11669578Ssam /* 116735811Smarc * Input present, check for input mapping and processing. 11689578Ssam */ 11699578Ssam first = 1; 11709578Ssam while ((c = getc(qp)) >= 0) { 11719578Ssam /* 117235811Smarc * delayed suspend (^Y) 11739578Ssam */ 117435811Smarc if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 117542882Smarc pgsignal(tp->t_pgrp, SIGTSTP, 1); 11769578Ssam if (first) { 117743377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 117843377Smarc TTIPRI | PCATCH, ttybg, 0)) 117940712Skarels break; 11809578Ssam goto loop; 11819578Ssam } 11829578Ssam break; 11837502Sroot } 11849578Ssam /* 118535811Smarc * Interpret EOF only in canonical mode. 11869578Ssam */ 118735811Smarc if (CCEQ(cc[VEOF], c) && lflag&ICANON) 11889578Ssam break; 11899578Ssam /* 11909578Ssam * Give user character. 11919578Ssam */ 119240712Skarels error = ureadc(c, uio); 11939578Ssam if (error) 11949578Ssam break; 119514938Smckusick if (uio->uio_resid == 0) 11969578Ssam break; 11979578Ssam /* 119835811Smarc * In canonical mode check for a "break character" 11999578Ssam * marking the end of a "line of input". 12009578Ssam */ 120140712Skarels if (lflag&ICANON && ttbreakc(c)) 12029578Ssam break; 12039578Ssam first = 0; 12047502Sroot } 12059578Ssam /* 12069578Ssam * Look to unblock output now that (presumably) 12079578Ssam * the input queue has gone down. 12089578Ssam */ 120935811Smarc if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 1210*47545Skarels if (cc[VSTART] != _POSIX_VDISABLE && 1211*47545Skarels putc(cc[VSTART], &tp->t_outq) == 0) { 12127502Sroot tp->t_state &= ~TS_TBLOCK; 12137502Sroot ttstart(tp); 12147502Sroot } 121535811Smarc } 12168520Sroot return (error); 12177502Sroot } 12187502Sroot 12197502Sroot /* 122025391Skarels * Check the output queue on tp for space for a kernel message 122125391Skarels * (from uprintf/tprintf). Allow some space over the normal 122225391Skarels * hiwater mark so we don't lose messages due to normal flow 122325391Skarels * control, but don't let the tty run amok. 122430695Skarels * Sleeps here are not interruptible, but we return prematurely 122530695Skarels * if new signals come in. 122625391Skarels */ 122725391Skarels ttycheckoutq(tp, wait) 122825391Skarels register struct tty *tp; 122925391Skarels int wait; 123025391Skarels { 123130695Skarels int hiwat, s, oldsig; 123225391Skarels 123335811Smarc hiwat = tp->t_hiwat; 123425391Skarels s = spltty(); 1235*47545Skarels oldsig = curproc->p_sig; 123625391Skarels if (tp->t_outq.c_cc > hiwat + 200) 123729946Skarels while (tp->t_outq.c_cc > hiwat) { 123829946Skarels ttstart(tp); 1239*47545Skarels if (wait == 0 || curproc->p_sig != oldsig) { 124029946Skarels splx(s); 124129946Skarels return (0); 124229946Skarels } 124330695Skarels timeout(wakeup, (caddr_t)&tp->t_outq, hz); 124429946Skarels tp->t_state |= TS_ASLEEP; 124530695Skarels sleep((caddr_t)&tp->t_outq, PZERO - 1); 124625391Skarels } 124725391Skarels splx(s); 124825391Skarels return (1); 124925391Skarels } 125025391Skarels 125125391Skarels /* 12527502Sroot * Called from the device's write routine after it has 12537502Sroot * calculated the tty-structure given as argument. 12547502Sroot */ 125537584Smarc ttwrite(tp, uio, flag) 12567625Ssam register struct tty *tp; 12579578Ssam register struct uio *uio; 12587502Sroot { 12597502Sroot register char *cp; 126040712Skarels register int cc = 0, ce; 1261*47545Skarels register struct proc *p = curproc; 12629578Ssam int i, hiwat, cnt, error, s; 12637502Sroot char obuf[OBUFSIZ]; 12647502Sroot 126535811Smarc hiwat = tp->t_hiwat; 12669578Ssam cnt = uio->uio_resid; 12679578Ssam error = 0; 12687502Sroot loop: 126937584Smarc s = spltty(); 127040712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && (tp->t_cflag&CLOCAL) == 0) { 127137584Smarc if (tp->t_state&TS_ISOPEN) { 127237584Smarc splx(s); 127337584Smarc return (EIO); 127437728Smckusick } else if (flag & IO_NDELAY) { 127537584Smarc splx(s); 127640712Skarels error = EWOULDBLOCK; 127740712Skarels goto out; 127837584Smarc } else { 127937584Smarc /* 128037584Smarc * sleep awaiting carrier 128137584Smarc */ 128243377Smarc error = ttysleep(tp, (caddr_t)&tp->t_rawq, 128343377Smarc TTIPRI | PCATCH,ttopen, 0); 128437584Smarc splx(s); 128543377Smarc if (error) 128640712Skarels goto out; 128737584Smarc goto loop; 128837584Smarc } 128937584Smarc } 129037584Smarc splx(s); 12919578Ssam /* 12929578Ssam * Hang the process if it's in the background. 12939578Ssam */ 1294*47545Skarels if (isbackground(p, tp) && 1295*47545Skarels tp->t_lflag&TOSTOP && (p->p_flag&SPPWAIT) == 0 && 1296*47545Skarels (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 1297*47545Skarels (p->p_sigmask & sigmask(SIGTTOU)) == 0 && 1298*47545Skarels p->p_pgrp->pg_jobc) { 1299*47545Skarels pgsignal(p->p_pgrp, SIGTTOU, 1); 130043377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 130143377Smarc ttybg, 0)) 130240712Skarels goto out; 130321776Sbloom goto loop; 13047502Sroot } 13059578Ssam /* 13069578Ssam * Process the user's data in at most OBUFSIZ 130740712Skarels * chunks. Perform any output translation. 130840712Skarels * Keep track of high water mark, sleep on overflow 130940712Skarels * awaiting device aid in acquiring new space. 13109578Ssam */ 131140712Skarels while (uio->uio_resid > 0 || cc > 0) { 131240712Skarels if (tp->t_lflag&FLUSHO) { 131340712Skarels uio->uio_resid = 0; 131440712Skarels return (0); 131540712Skarels } 131640712Skarels if (tp->t_outq.c_cc > hiwat) 131732067Skarels goto ovhiwat; 13189578Ssam /* 131940712Skarels * Grab a hunk of data from the user, 132040712Skarels * unless we have some leftover from last time. 13219578Ssam */ 13227822Sroot if (cc == 0) { 132340712Skarels cc = min(uio->uio_resid, OBUFSIZ); 132440712Skarels cp = obuf; 132540712Skarels error = uiomove(cp, cc, uio); 132640712Skarels if (error) { 132740712Skarels cc = 0; 132840712Skarels break; 132940712Skarels } 13307822Sroot } 13319578Ssam /* 13329578Ssam * If nothing fancy need be done, grab those characters we 13339578Ssam * can handle without any of ttyoutput's processing and 13349578Ssam * just transfer them to the output q. For those chars 13359578Ssam * which require special processing (as indicated by the 13369578Ssam * bits in partab), call ttyoutput. After processing 13379578Ssam * a hunk of data, look for FLUSHO so ^O's will take effect 13389578Ssam * immediately. 13399578Ssam */ 13409578Ssam while (cc > 0) { 134140712Skarels if ((tp->t_oflag&OPOST) == 0) 13427502Sroot ce = cc; 13437502Sroot else { 134434492Skarels ce = cc - scanc((unsigned)cc, (u_char *)cp, 134534492Skarels (u_char *)partab, 077); 13469578Ssam /* 13479578Ssam * If ce is zero, then we're processing 13489578Ssam * a special character through ttyoutput. 13499578Ssam */ 13509578Ssam if (ce == 0) { 13517502Sroot tp->t_rocount = 0; 13527502Sroot if (ttyoutput(*cp, tp) >= 0) { 135321776Sbloom /* no c-lists, wait a bit */ 135421776Sbloom ttstart(tp); 135543377Smarc if (error = ttysleep(tp, 135643377Smarc (caddr_t)&lbolt, 135743377Smarc TTOPRI | PCATCH, ttybuf, 0)) 135840712Skarels break; 135921776Sbloom goto loop; 13607502Sroot } 13619578Ssam cp++, cc--; 136235811Smarc if ((tp->t_lflag&FLUSHO) || 13639578Ssam tp->t_outq.c_cc > hiwat) 13647502Sroot goto ovhiwat; 13659578Ssam continue; 13667502Sroot } 13677502Sroot } 13689578Ssam /* 13699578Ssam * A bunch of normal characters have been found, 13709578Ssam * transfer them en masse to the output queue and 13719578Ssam * continue processing at the top of the loop. 13729578Ssam * If there are any further characters in this 13739578Ssam * <= OBUFSIZ chunk, the first should be a character 13749578Ssam * requiring special handling by ttyoutput. 13759578Ssam */ 13767502Sroot tp->t_rocount = 0; 13779578Ssam i = b_to_q(cp, ce, &tp->t_outq); 13789578Ssam ce -= i; 13799578Ssam tp->t_col += ce; 13809578Ssam cp += ce, cc -= ce, tk_nout += ce; 138135811Smarc tp->t_outcc += ce; 13829578Ssam if (i > 0) { 13839578Ssam /* out of c-lists, wait a bit */ 13847502Sroot ttstart(tp); 138543377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 138643377Smarc TTOPRI | PCATCH, ttybuf, 0)) 138740712Skarels break; 138821776Sbloom goto loop; 13897502Sroot } 139035811Smarc if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 139140712Skarels break; 13927502Sroot } 139335811Smarc ttstart(tp); 13947502Sroot } 139540712Skarels out: 139640712Skarels /* 139740712Skarels * If cc is nonzero, we leave the uio structure inconsistent, 139840712Skarels * as the offset and iov pointers have moved forward, 139940712Skarels * but it doesn't matter (the call will either return short 140040712Skarels * or restart with a new uio). 140140712Skarels */ 140240712Skarels uio->uio_resid += cc; 14038520Sroot return (error); 140440712Skarels 14057502Sroot ovhiwat: 140632067Skarels ttstart(tp); 140732067Skarels s = spltty(); 14089578Ssam /* 140935811Smarc * This can only occur if FLUSHO is set in t_lflag, 141032067Skarels * or if ttstart/oproc is synchronous (or very fast). 14119578Ssam */ 14127502Sroot if (tp->t_outq.c_cc <= hiwat) { 14139578Ssam splx(s); 14147502Sroot goto loop; 14157502Sroot } 141637728Smckusick if (flag & IO_NDELAY) { 141717545Skarels splx(s); 141840712Skarels uio->uio_resid += cc; 14197822Sroot if (uio->uio_resid == cnt) 14208520Sroot return (EWOULDBLOCK); 14218520Sroot return (0); 14227502Sroot } 14237502Sroot tp->t_state |= TS_ASLEEP; 142443377Smarc error = ttysleep(tp, (caddr_t)&tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 14259578Ssam splx(s); 142643377Smarc if (error) 142740712Skarels goto out; 14287502Sroot goto loop; 14297502Sroot } 14307502Sroot 14317502Sroot /* 14327502Sroot * Rubout one character from the rawq of tp 14337502Sroot * as cleanly as possible. 14347502Sroot */ 14357502Sroot ttyrub(c, tp) 14367625Ssam register c; 14377625Ssam register struct tty *tp; 14387502Sroot { 14397502Sroot register char *cp; 14407502Sroot register int savecol; 14417502Sroot int s; 14427502Sroot char *nextc(); 14437502Sroot 144442882Smarc if ((tp->t_lflag&ECHO) == 0 || (tp->t_lflag&EXTPROC)) 14457502Sroot return; 144635811Smarc tp->t_lflag &= ~FLUSHO; 144735811Smarc if (tp->t_lflag&ECHOE) { 14487502Sroot if (tp->t_rocount == 0) { 14497502Sroot /* 14507502Sroot * Screwed by ttwrite; retype 14517502Sroot */ 14527502Sroot ttyretype(tp); 14537502Sroot return; 14547502Sroot } 145535811Smarc if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 14567502Sroot ttyrubo(tp, 2); 145735811Smarc else switch (partab[c&=0377]&077) { 14587502Sroot 14597502Sroot case ORDINARY: 146035811Smarc ttyrubo(tp, 1); 14617502Sroot break; 14627502Sroot 14637502Sroot case VTAB: 14647502Sroot case BACKSPACE: 14657502Sroot case CONTROL: 14667502Sroot case RETURN: 1467*47545Skarels case NEWLINE: 146835811Smarc if (tp->t_lflag&ECHOCTL) 14697502Sroot ttyrubo(tp, 2); 14707502Sroot break; 14717502Sroot 147235811Smarc case TAB: { 147335811Smarc int c; 147435811Smarc 14757502Sroot if (tp->t_rocount < tp->t_rawq.c_cc) { 14767502Sroot ttyretype(tp); 14777502Sroot return; 14787502Sroot } 147917545Skarels s = spltty(); 14807502Sroot savecol = tp->t_col; 14819578Ssam tp->t_state |= TS_CNTTB; 148235811Smarc tp->t_lflag |= FLUSHO; 14837502Sroot tp->t_col = tp->t_rocol; 14849578Ssam cp = tp->t_rawq.c_cf; 148539407Smarc if (cp) 148639407Smarc c = *cp; /* XXX FIX NEXTC */ 148735811Smarc for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 148835811Smarc ttyecho(c, tp); 148935811Smarc tp->t_lflag &= ~FLUSHO; 14909578Ssam tp->t_state &= ~TS_CNTTB; 14917502Sroot splx(s); 14927502Sroot /* 14937502Sroot * savecol will now be length of the tab 14947502Sroot */ 14957502Sroot savecol -= tp->t_col; 14967502Sroot tp->t_col += savecol; 14977502Sroot if (savecol > 8) 14987502Sroot savecol = 8; /* overflow screw */ 14997502Sroot while (--savecol >= 0) 15007502Sroot (void) ttyoutput('\b', tp); 15017502Sroot break; 150235811Smarc } 15037502Sroot 15047502Sroot default: 150537584Smarc /* XXX */ 150635811Smarc printf("ttyrub: would panic c = %d, val = %d\n", 150735811Smarc c, partab[c&=0377]&077); 150835811Smarc /*panic("ttyrub");*/ 15097502Sroot } 151035811Smarc } else if (tp->t_lflag&ECHOPRT) { 15119578Ssam if ((tp->t_state&TS_ERASE) == 0) { 15127502Sroot (void) ttyoutput('\\', tp); 15139578Ssam tp->t_state |= TS_ERASE; 15147502Sroot } 15157502Sroot ttyecho(c, tp); 15167502Sroot } else 151735811Smarc ttyecho(tp->t_cc[VERASE], tp); 15187502Sroot tp->t_rocount--; 15197502Sroot } 15207502Sroot 15217502Sroot /* 15227502Sroot * Crt back over cnt chars perhaps 15237502Sroot * erasing them. 15247502Sroot */ 15257502Sroot ttyrubo(tp, cnt) 15267625Ssam register struct tty *tp; 15277625Ssam int cnt; 15287502Sroot { 15297502Sroot 15307502Sroot while (--cnt >= 0) 153140712Skarels ttyoutstr("\b \b", tp); 15327502Sroot } 15337502Sroot 15347502Sroot /* 15357502Sroot * Reprint the rawq line. 15367502Sroot * We assume c_cc has already been checked. 15377502Sroot */ 15387502Sroot ttyretype(tp) 15397625Ssam register struct tty *tp; 15407502Sroot { 15417502Sroot register char *cp; 15427502Sroot char *nextc(); 154335811Smarc int s, c; 15447502Sroot 154535811Smarc if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 154635811Smarc ttyecho(tp->t_cc[VREPRINT], tp); 15477502Sroot (void) ttyoutput('\n', tp); 154817545Skarels s = spltty(); 154935811Smarc /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 155035811Smarc BIT OF FIRST CHAR ****/ 155135811Smarc for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 155235811Smarc ttyecho(c, tp); 155335811Smarc } 155435811Smarc for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 155535811Smarc ttyecho(c, tp); 155635811Smarc } 15579578Ssam tp->t_state &= ~TS_ERASE; 15587502Sroot splx(s); 15597502Sroot tp->t_rocount = tp->t_rawq.c_cc; 15607502Sroot tp->t_rocol = 0; 15617502Sroot } 15627502Sroot 15637502Sroot /* 156435811Smarc * Echo a typed character to the terminal. 15657502Sroot */ 15667502Sroot ttyecho(c, tp) 15677625Ssam register c; 15687625Ssam register struct tty *tp; 15697502Sroot { 15709578Ssam if ((tp->t_state&TS_CNTTB) == 0) 157135811Smarc tp->t_lflag &= ~FLUSHO; 1572*47545Skarels if (((tp->t_lflag&ECHO) == 0 && 1573*47545Skarels ((tp->t_lflag&ECHONL) == 0 || c == '\n')) || (tp->t_lflag&EXTPROC)) 15747502Sroot return; 157535811Smarc if (tp->t_lflag&ECHOCTL) { 157640712Skarels if ((c&TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' || 157740712Skarels c == 0177) { 15787502Sroot (void) ttyoutput('^', tp); 157935811Smarc c &= TTY_CHARMASK; 15807502Sroot if (c == 0177) 15817502Sroot c = '?'; 15827502Sroot else 15837502Sroot c += 'A' - 1; 15847502Sroot } 15857502Sroot } 158635811Smarc (void) ttyoutput(c, tp); 15877502Sroot } 15887502Sroot 15897502Sroot /* 15907502Sroot * send string cp to tp 15917502Sroot */ 159240712Skarels ttyoutstr(cp, tp) 15937625Ssam register char *cp; 15947625Ssam register struct tty *tp; 15957502Sroot { 15967502Sroot register char c; 15977502Sroot 15987502Sroot while (c = *cp++) 15997502Sroot (void) ttyoutput(c, tp); 16007502Sroot } 16017502Sroot 16027502Sroot ttwakeup(tp) 1603*47545Skarels register struct tty *tp; 16047502Sroot { 16057502Sroot 16067502Sroot if (tp->t_rsel) { 16077502Sroot selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 16087502Sroot tp->t_state &= ~TS_RCOLL; 16097502Sroot tp->t_rsel = 0; 16107502Sroot } 161112752Ssam if (tp->t_state & TS_ASYNC) 161242882Smarc pgsignal(tp->t_pgrp, SIGIO, 1); 16137502Sroot wakeup((caddr_t)&tp->t_rawq); 16147502Sroot } 161535811Smarc 161635811Smarc /* 161735811Smarc * set tty hi and low water marks 161835811Smarc * 161935811Smarc * Try to arrange the dynamics so there's about one second 162035811Smarc * from hi to low water. 162135811Smarc * 162235811Smarc */ 162335811Smarc ttsetwater(tp) 162435811Smarc struct tty *tp; 162535811Smarc { 162635811Smarc register cps = tp->t_ospeed / 10; 162735811Smarc register x; 162835811Smarc 162935811Smarc #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 163035811Smarc tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 163135811Smarc x += cps; 163235811Smarc x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 163335811Smarc tp->t_hiwat = roundup(x, CBSIZE); 163435811Smarc #undef clamp 163535811Smarc } 163635811Smarc 163739407Smarc /* 163839407Smarc * (^T) 163939407Smarc * Report on state of foreground process group. 164039407Smarc */ 164139407Smarc ttyinfo(tp) 164239407Smarc struct tty *tp; 164339407Smarc { 164441177Smarc register struct proc *p, *pick = NULL; 164541177Smarc int x, s; 164641177Smarc struct timeval utime, stime; 164742350Smckusick #define pgtok(a) (((a)*NBPG)/1024) 164839407Smarc 164939407Smarc if (ttycheckoutq(tp,0) == 0) 165039407Smarc return; 165141177Smarc /* 165241177Smarc * load average 165341177Smarc */ 165441177Smarc x = (averunnable[0] * 100 + FSCALE/2) >> FSHIFT; 165541177Smarc ttyprintf(tp, "load: %d.", x/100); 165641177Smarc ttyoutint(x%100, 10, 2, tp); 165739555Smarc if (tp->t_session == NULL) 165841177Smarc ttyprintf(tp, " not a controlling terminal\n"); 165941177Smarc else if (tp->t_pgrp == NULL) 166041177Smarc ttyprintf(tp, " no foreground process group\n"); 166141177Smarc else if ((p = tp->t_pgrp->pg_mem) == NULL) 166241177Smarc ttyprintf(tp, " empty foreground process group\n"); 166339407Smarc else { 166441177Smarc /* pick interesting process */ 166539407Smarc for (; p != NULL; p = p->p_pgrpnxt) { 166641177Smarc if (proc_compare(pick, p)) 166741177Smarc pick = p; 166839407Smarc } 166941177Smarc ttyprintf(tp, " cmd: %s %d [%s] ", 167041177Smarc pick->p_comm, pick->p_pid, 167141177Smarc pick->p_wmesg ? pick->p_wmesg : "running"); 167241177Smarc /* 167341177Smarc * cpu time 167441177Smarc */ 1675*47545Skarels if (curproc == pick) 167641177Smarc s = splclock(); 167741177Smarc utime = pick->p_utime; 167841177Smarc stime = pick->p_stime; 1679*47545Skarels if (curproc == pick) 168041177Smarc splx(s); 168141177Smarc /* user time */ 168241177Smarc x = (utime.tv_usec + 5000) / 10000; /* scale to 100's */ 168341177Smarc ttyoutint(utime.tv_sec, 10, 1, tp); 168441177Smarc tputchar('.', tp); 168541177Smarc ttyoutint(x, 10, 2, tp); 168641177Smarc tputchar('u', tp); 168741177Smarc tputchar(' ', tp); 168841177Smarc /* system time */ 168941177Smarc x = (stime.tv_usec + 5000) / 10000; /* scale to 100's */ 169041177Smarc ttyoutint(stime.tv_sec, 10, 1, tp); 169141177Smarc tputchar('.', tp); 169241177Smarc ttyoutint(x, 10, 2, tp); 169341177Smarc tputchar('s', tp); 169441177Smarc tputchar(' ', tp); 169541177Smarc /* 169641177Smarc * pctcpu 169741177Smarc */ 169841177Smarc x = pick->p_pctcpu * 10000 + FSCALE/2 >> FSHIFT; 169941177Smarc ttyoutint(x/100, 10, 1, tp); 170041177Smarc #ifdef notdef /* do we really want this ??? */ 170141177Smarc tputchar('.', tp); 170241177Smarc ttyoutint(x%100, 10, 2, tp); 170341177Smarc #endif 1704*47545Skarels ttyprintf(tp, "%% %dk\n", pgtok(pick->p_vmspace->vm_rssize)); 170539407Smarc } 170641177Smarc tp->t_rocount = 0; /* so pending input will be retyped if BS */ 170739407Smarc } 170839407Smarc 170941177Smarc ttyoutint(n, base, min, tp) 171041177Smarc register int n, base, min; 171141177Smarc register struct tty *tp; 171241177Smarc { 171341177Smarc char info[16]; 171441177Smarc register char *p = info; 171541177Smarc 171641177Smarc while (--min >= 0 || n) { 171741177Smarc *p++ = "0123456789abcdef"[n%base]; 171841177Smarc n /= base; 171941177Smarc } 172041177Smarc while (p > info) 172141177Smarc ttyoutput(*--p, tp); 172241177Smarc } 172341177Smarc 172441177Smarc /* 172541177Smarc * Returns 1 if p2 is "better" than p1 172641177Smarc * 172741177Smarc * The algorithm for picking the "interesting" process is thus: 172841177Smarc * 172941177Smarc * 1) (Only foreground processes are eligable - implied) 173041177Smarc * 2) Runnable processes are favored over anything 173141177Smarc * else. The runner with the highest cpu 173241177Smarc * utilization is picked (p_cpu). Ties are 173341177Smarc * broken by picking the highest pid. 173441177Smarc * 3 Next, the sleeper with the shortest sleep 173541177Smarc * time is favored. With ties, we pick out 173641177Smarc * just "short-term" sleepers (SSINTR == 0). 173741177Smarc * Further ties are broken by picking the highest 173841177Smarc * pid. 173941177Smarc * 174041177Smarc */ 174141177Smarc #define isrun(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL)) 174245723Smckusick #define TESTAB(a, b) ((a)<<1 | (b)) 174345723Smckusick #define ONLYA 2 174445723Smckusick #define ONLYB 1 174545723Smckusick #define BOTH 3 174645723Smckusick 174741177Smarc proc_compare(p1, p2) 174841177Smarc register struct proc *p1, *p2; 174941177Smarc { 175041177Smarc 175141177Smarc if (p1 == NULL) 175241177Smarc return (1); 175341177Smarc /* 175441177Smarc * see if at least one of them is runnable 175541177Smarc */ 175645723Smckusick switch (TESTAB(isrun(p1), isrun(p2))) { 175745723Smckusick case ONLYA: 175845723Smckusick return (0); 175945723Smckusick case ONLYB: 176041177Smarc return (1); 176145723Smckusick case BOTH: 176241177Smarc /* 176341177Smarc * tie - favor one with highest recent cpu utilization 176441177Smarc */ 176541177Smarc if (p2->p_cpu > p1->p_cpu) 176641177Smarc return (1); 176741177Smarc if (p1->p_cpu > p2->p_cpu) 176841177Smarc return (0); 176941177Smarc return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 177041177Smarc } 177145723Smckusick /* 177245723Smckusick * weed out zombies 177345723Smckusick */ 177445723Smckusick switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) { 177545723Smckusick case ONLYA: 177645723Smckusick return (1); 177745723Smckusick case ONLYB: 177845723Smckusick return (0); 177945723Smckusick case BOTH: 178045723Smckusick return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 178145723Smckusick } 178241177Smarc /* 178341177Smarc * pick the one with the smallest sleep time 178441177Smarc */ 178541177Smarc if (p2->p_slptime > p1->p_slptime) 178641177Smarc return (0); 178741177Smarc if (p1->p_slptime > p2->p_slptime) 178841177Smarc return (1); 178941177Smarc /* 179041177Smarc * favor one sleeping in a non-interruptible sleep 179141177Smarc */ 179241177Smarc if (p1->p_flag&SSINTR && (p2->p_flag&SSINTR) == 0) 179341177Smarc return (1); 179441177Smarc if (p2->p_flag&SSINTR && (p1->p_flag&SSINTR) == 0) 179541177Smarc return (0); 1796*47545Skarels return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 179741177Smarc } 179845723Smckusick 1799*47545Skarels /* XXX move to subr_prf.c */ 180039407Smarc #define TOTTY 0x2 /* XXX should be in header */ 180139407Smarc /*VARARGS2*/ 180239407Smarc ttyprintf(tp, fmt, x1) 180339555Smarc struct tty *tp; 180439407Smarc char *fmt; 180539407Smarc unsigned x1; 180639407Smarc { 180739555Smarc prf(fmt, &x1, TOTTY, (caddr_t)tp); 180839407Smarc } 180939555Smarc 181039555Smarc /* 181139555Smarc * Output char to tty; console putchar style. 181239555Smarc */ 181339555Smarc tputchar(c, tp) 181439555Smarc int c; 181539555Smarc struct tty *tp; 181639555Smarc { 181739555Smarc register s = spltty(); 181839555Smarc 1819*47545Skarels if ((tp->t_state & (TS_CARR_ON|TS_ISOPEN)) == (TS_CARR_ON|TS_ISOPEN)) { 182039555Smarc if (c == '\n') 182139555Smarc (void) ttyoutput('\r', tp); 182239555Smarc (void) ttyoutput(c, tp); 182339555Smarc ttstart(tp); 182439555Smarc splx(s); 182539555Smarc return (0); 182639555Smarc } 182739555Smarc splx(s); 182839555Smarc return (-1); 182939555Smarc } 183043377Smarc 183144419Smarc /* 183244419Smarc * Sleep on chan. 183344419Smarc * 183444419Smarc * Return ERESTART if tty changed while we napped. 183544419Smarc */ 183643377Smarc ttysleep(tp, chan, pri, wmesg, timo) 183743377Smarc struct tty *tp; 183843377Smarc caddr_t chan; 183943377Smarc int pri; 184043377Smarc char *wmesg; 184143377Smarc int timo; 184243377Smarc { 184343377Smarc int error; 184443377Smarc short gen = tp->t_gen; 184543377Smarc 184643377Smarc if (error = tsleep(chan, pri, wmesg, timo)) 184743377Smarc return (error); 184843377Smarc if (tp->t_gen != gen) 184943377Smarc return (ERESTART); 185043377Smarc return (0); 185143377Smarc } 1852