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*48439Skarels * @(#)tty.c 7.39 (Berkeley) 04/20/91 723387Smckusick */ 839Sbill 917095Sbloom #include "param.h" 1017095Sbloom #include "systm.h" 1117095Sbloom #include "ioctl.h" 1239407Smarc #define TTYDEFCHARS 1317095Sbloom #include "tty.h" 1435811Smarc #undef TTYDEFCHARS 1517095Sbloom #include "proc.h" 1617095Sbloom #include "file.h" 1717095Sbloom #include "conf.h" 1829946Skarels #include "dkstat.h" 1917095Sbloom #include "uio.h" 2017095Sbloom #include "kernel.h" 2137728Smckusick #include "vnode.h" 2235811Smarc #include "syslog.h" 2339Sbill 24*48439Skarels #include "vm/vm.h" 2537525Smckusick 2640712Skarels /* symbolic sleep message strings */ 2740712Skarels char ttyin[] = "ttyin"; 2840712Skarels char ttyout[] = "ttyout"; 2941370Smarc char ttopen[] = "ttyopn"; 3041370Smarc char ttclos[] = "ttycls"; 3140712Skarels char ttybg[] = "ttybg"; 3240712Skarels char ttybuf[] = "ttybuf"; 3340712Skarels 347436Skre /* 357436Skre * Table giving parity for characters and indicating 3635811Smarc * character classes to tty driver. The 8th bit 3735811Smarc * indicates parity, the 7th bit indicates the character 3835811Smarc * is an alphameric or underscore (for ALTWERASE), and the 3935811Smarc * low 6 bits indicate delay type. If the low 6 bits are 0 4035811Smarc * then the character needs no special processing on output. 417436Skre */ 4239Sbill 437436Skre char partab[] = { 4435811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 4535811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 4635811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 4735811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 4835811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 4935811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 5035811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 5135811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 5235811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 5335811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 5435811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 5535811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 5635811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 5735811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 5835811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 5935811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 607436Skre /* 6135811Smarc * meta chars 627436Skre */ 6335811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 6435811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 6535811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 6635811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 6735811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 6835811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 6935811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 7035811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 7135811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 7235811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 7335811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 7435811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 7535811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 7635811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 7735811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 7835811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 797436Skre }; 807436Skre 8135811Smarc extern struct tty *constty; /* temporary virtual console */ 8235811Smarc 83146Sbill /* 8435811Smarc * Is 'c' a line delimiter ("break" character)? 8539Sbill */ 8640712Skarels #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \ 8740712Skarels (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE) 8839Sbill 8939Sbill ttychars(tp) 909578Ssam struct tty *tp; 9139Sbill { 9247545Skarels 9335811Smarc bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 9439Sbill } 9539Sbill 9639Sbill /* 97903Sbill * Wait for output to drain, then flush input waiting. 9839Sbill */ 9912752Ssam ttywflush(tp) 10037584Smarc struct tty *tp; 10139Sbill { 10240712Skarels int error; 10339Sbill 10440712Skarels if ((error = ttywait(tp)) == 0) 10540712Skarels ttyflush(tp, FREAD); 10640712Skarels return (error); 10712752Ssam } 10812752Ssam 10935811Smarc /* 11035811Smarc * Wait for output to drain. 11135811Smarc */ 11212752Ssam ttywait(tp) 11312752Ssam register struct tty *tp; 11412752Ssam { 11540712Skarels int error = 0, s = spltty(); 11612752Ssam 11713809Ssam while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 11837584Smarc (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 11937584Smarc tp->t_oproc) { 120903Sbill (*tp->t_oproc)(tp); 1215408Swnj tp->t_state |= TS_ASLEEP; 12243377Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_outq, 12343377Smarc TTOPRI | PCATCH, ttyout, 0)) 12440712Skarels break; 125903Sbill } 1269859Ssam splx(s); 12740712Skarels return (error); 12839Sbill } 12939Sbill 13039Sbill /* 1319578Ssam * Flush all TTY queues 13239Sbill */ 13312752Ssam ttyflush(tp, rw) 1347625Ssam register struct tty *tp; 13539Sbill { 136903Sbill register s; 137903Sbill 13817545Skarels s = spltty(); 139903Sbill if (rw & FREAD) { 140903Sbill while (getc(&tp->t_canq) >= 0) 141903Sbill ; 14237584Smarc ttwakeup(tp); 143903Sbill } 144903Sbill if (rw & FWRITE) { 14537584Smarc wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */ 1465408Swnj tp->t_state &= ~TS_TTSTOP; 1475426Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 148903Sbill while (getc(&tp->t_outq) >= 0) 149903Sbill ; 150903Sbill } 151903Sbill if (rw & FREAD) { 152903Sbill while (getc(&tp->t_rawq) >= 0) 153903Sbill ; 1549578Ssam tp->t_rocount = 0; 155903Sbill tp->t_rocol = 0; 1569578Ssam tp->t_state &= ~TS_LOCAL; 157903Sbill } 158903Sbill splx(s); 15939Sbill } 16039Sbill 161903Sbill /* 162903Sbill * Send stop character on input overflow. 163903Sbill */ 164903Sbill ttyblock(tp) 1657625Ssam register struct tty *tp; 16639Sbill { 167903Sbill register x; 1689578Ssam 169903Sbill x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 170903Sbill if (tp->t_rawq.c_cc > TTYHOG) { 17112752Ssam ttyflush(tp, FREAD|FWRITE); 1725408Swnj tp->t_state &= ~TS_TBLOCK; 173903Sbill } 17415118Skarels /* 17515118Skarels * Block further input iff: 17615118Skarels * Current input > threshold AND input is available to user program 17715118Skarels */ 17842350Smckusick if (x >= TTYHOG/2 && (tp->t_state & TS_TBLOCK) == 0 && 17940712Skarels ((tp->t_lflag&ICANON) == 0) || (tp->t_canq.c_cc > 0) && 18035811Smarc tp->t_cc[VSTOP] != _POSIX_VDISABLE) { 18142350Smckusick if (putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) { 18215118Skarels tp->t_state |= TS_TBLOCK; 18315118Skarels ttstart(tp); 18415118Skarels } 185903Sbill } 18639Sbill } 18739Sbill 18839Sbill /* 18947545Skarels * Start output on the typewriter. It is used from the top half 19047545Skarels * after some characters have been put on the output queue, 19147545Skarels * from the interrupt routine to transmit the next 19247545Skarels * character. 193121Sbill */ 19447545Skarels ttstart(tp) 19537584Smarc struct tty *tp; 196121Sbill { 197121Sbill 19847545Skarels if (tp->t_oproc) /* kludge for pty */ 19947545Skarels (*tp->t_oproc)(tp); 20047545Skarels } 20147545Skarels 20247545Skarels ttrstrt(tp) /* XXX */ 20347545Skarels struct tty *tp; 20447545Skarels { 20547545Skarels 20640712Skarels #ifdef DIAGNOSTIC 2079578Ssam if (tp == 0) 2089578Ssam panic("ttrstrt"); 20940712Skarels #endif 2105408Swnj tp->t_state &= ~TS_TIMEOUT; 211903Sbill ttstart(tp); 212121Sbill } 213121Sbill 21439Sbill 21539Sbill /* 216903Sbill * Common code for tty ioctls. 21739Sbill */ 2181780Sbill /*ARGSUSED*/ 2197625Ssam ttioctl(tp, com, data, flag) 2207625Ssam register struct tty *tp; 2217625Ssam caddr_t data; 22239Sbill { 22347545Skarels register struct proc *p = curproc; /* XXX */ 22439Sbill extern int nldisp; 22537554Smckusick int s, error; 22639Sbill 227903Sbill /* 228903Sbill * If the ioctl involves modification, 22917545Skarels * hang if in the background. 230903Sbill */ 2317625Ssam switch (com) { 23239Sbill 23335811Smarc case TIOCSETD: 234903Sbill case TIOCFLUSH: 23535811Smarc /*case TIOCSPGRP:*/ 2369325Ssam case TIOCSTI: 23717598Sbloom case TIOCSWINSZ: 23835811Smarc case TIOCSETA: 23935811Smarc case TIOCSETAW: 24035811Smarc case TIOCSETAF: 24140030Smarc #ifdef COMPAT_43 24240030Smarc case TIOCSETP: 24340030Smarc case TIOCSETN: 24440030Smarc case TIOCSETC: 24540030Smarc case TIOCSLTC: 24640030Smarc case TIOCLBIS: 24740030Smarc case TIOCLBIC: 24840030Smarc case TIOCLSET: 24940030Smarc case OTIOCSETD: 25040030Smarc #endif 25147545Skarels while (isbackground(curproc, tp) && 25247545Skarels p->p_pgrp->pg_jobc && (p->p_flag&SPPWAIT) == 0 && 25347545Skarels (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 25447545Skarels (p->p_sigmask & sigmask(SIGTTOU)) == 0) { 25547545Skarels pgsignal(p->p_pgrp, SIGTTOU, 1); 25643377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 25743377Smarc TTOPRI | PCATCH, ttybg, 0)) 25840712Skarels return (error); 259903Sbill } 260903Sbill break; 261903Sbill } 262903Sbill 2639578Ssam /* 2649578Ssam * Process the ioctl. 2659578Ssam */ 2667625Ssam switch (com) { 267903Sbill 2688556Sroot /* get discipline number */ 26939Sbill case TIOCGETD: 2707625Ssam *(int *)data = tp->t_line; 27139Sbill break; 27239Sbill 2738556Sroot /* set line discipline */ 2747625Ssam case TIOCSETD: { 2757625Ssam register int t = *(int *)data; 27635811Smarc dev_t dev = tp->t_dev; 2777625Ssam 27835811Smarc if ((unsigned)t >= nldisp) 27910851Ssam return (ENXIO); 28025584Skarels if (t != tp->t_line) { 28125584Skarels s = spltty(); 28225584Skarels (*linesw[tp->t_line].l_close)(tp); 28325584Skarels error = (*linesw[t].l_open)(dev, tp); 28425584Skarels if (error) { 28535811Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp); 28625584Skarels splx(s); 28725584Skarels return (error); 28825584Skarels } 28925584Skarels tp->t_line = t; 29010851Ssam splx(s); 29110851Ssam } 29239Sbill break; 2937625Ssam } 29439Sbill 2958556Sroot /* prevent more opens on channel */ 2965614Swnj case TIOCEXCL: 2975614Swnj tp->t_state |= TS_XCLUDE; 2985614Swnj break; 2995614Swnj 3005614Swnj case TIOCNXCL: 3015614Swnj tp->t_state &= ~TS_XCLUDE; 3025614Swnj break; 3035614Swnj 30439Sbill case TIOCHPCL: 30535811Smarc tp->t_cflag |= HUPCL; 30639Sbill break; 30739Sbill 3083942Sbugs case TIOCFLUSH: { 3097625Ssam register int flags = *(int *)data; 3107625Ssam 3117625Ssam if (flags == 0) 3123942Sbugs flags = FREAD|FWRITE; 3137625Ssam else 3147625Ssam flags &= FREAD|FWRITE; 31512752Ssam ttyflush(tp, flags); 31639Sbill break; 3173944Sbugs } 31839Sbill 31937584Smarc case FIOASYNC: 32037584Smarc if (*(int *)data) 32137584Smarc tp->t_state |= TS_ASYNC; 32237584Smarc else 32337584Smarc tp->t_state &= ~TS_ASYNC; 32437584Smarc break; 32537584Smarc 32637584Smarc case FIONBIO: 32737584Smarc break; /* XXX remove */ 32837584Smarc 3298556Sroot /* return number of characters immediately available */ 3307625Ssam case FIONREAD: 3317625Ssam *(off_t *)data = ttnread(tp); 332174Sbill break; 333174Sbill 33413077Ssam case TIOCOUTQ: 33513077Ssam *(int *)data = tp->t_outq.c_cc; 33613077Ssam break; 33713077Ssam 3388589Sroot case TIOCSTOP: 33917545Skarels s = spltty(); 3409578Ssam if ((tp->t_state&TS_TTSTOP) == 0) { 3415573Swnj tp->t_state |= TS_TTSTOP; 3425573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 3435573Swnj } 3447625Ssam splx(s); 3455573Swnj break; 3465573Swnj 3478589Sroot case TIOCSTART: 34817545Skarels s = spltty(); 34935811Smarc if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 3505573Swnj tp->t_state &= ~TS_TTSTOP; 35135811Smarc tp->t_lflag &= ~FLUSHO; 3525573Swnj ttstart(tp); 3535573Swnj } 3547625Ssam splx(s); 3555573Swnj break; 3565573Swnj 3579325Ssam /* 3589325Ssam * Simulate typing of a character at the terminal. 3599325Ssam */ 3609325Ssam case TIOCSTI: 36147545Skarels if (p->p_ucred->cr_uid && (flag & FREAD) == 0) 36217183Smckusick return (EPERM); 36347545Skarels if (p->p_ucred->cr_uid && !isctty(p, tp)) 3649325Ssam return (EACCES); 3659578Ssam (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 3669325Ssam break; 3679325Ssam 36835811Smarc case TIOCGETA: { 36935811Smarc struct termios *t = (struct termios *)data; 37012752Ssam 37135811Smarc bcopy(&tp->t_termios, t, sizeof(struct termios)); 37235811Smarc break; 37335811Smarc } 37435811Smarc 37535811Smarc case TIOCSETA: 37635811Smarc case TIOCSETAW: 37737584Smarc case TIOCSETAF: { 37835811Smarc register struct termios *t = (struct termios *)data; 37940712Skarels 38017545Skarels s = spltty(); 38139407Smarc if (com == TIOCSETAW || com == TIOCSETAF) { 38240712Skarels if (error = ttywait(tp)) { 38340712Skarels splx(s); 38440712Skarels return (error); 38540712Skarels } 38645007Smarc if (com == TIOCSETAF) 38739407Smarc ttyflush(tp, FREAD); 38839407Smarc } 38940712Skarels if ((t->c_cflag&CIGNORE) == 0) { 39035811Smarc /* 39135811Smarc * set device hardware 39235811Smarc */ 39337584Smarc if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 39437584Smarc splx(s); 39535811Smarc return (error); 39637584Smarc } else { 39740712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && 39837584Smarc (tp->t_cflag&CLOCAL) && 39940712Skarels (t->c_cflag&CLOCAL) == 0) { 40037584Smarc tp->t_state &= ~TS_ISOPEN; 40137584Smarc tp->t_state |= TS_WOPEN; 40237584Smarc ttwakeup(tp); 40337584Smarc } 40435811Smarc tp->t_cflag = t->c_cflag; 40535811Smarc tp->t_ispeed = t->c_ispeed; 40635811Smarc tp->t_ospeed = t->c_ospeed; 40734492Skarels } 40835811Smarc ttsetwater(tp); 40912752Ssam } 41039407Smarc if (com != TIOCSETAF) { 41135811Smarc if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 41235811Smarc if (t->c_lflag&ICANON) { 41335811Smarc tp->t_lflag |= PENDIN; 41435811Smarc ttwakeup(tp); 41535811Smarc } 41635811Smarc else { 41735811Smarc struct clist tq; 41835811Smarc 41935811Smarc catq(&tp->t_rawq, &tp->t_canq); 42035811Smarc tq = tp->t_rawq; 42135811Smarc tp->t_rawq = tp->t_canq; 42235811Smarc tp->t_canq = tq; 42335811Smarc } 42412752Ssam } 42535811Smarc tp->t_iflag = t->c_iflag; 42635811Smarc tp->t_oflag = t->c_oflag; 42742882Smarc /* 42842882Smarc * Make the EXTPROC bit read only. 42942882Smarc */ 43042882Smarc if (tp->t_lflag&EXTPROC) 43142882Smarc t->c_lflag |= EXTPROC; 43242882Smarc else 43342882Smarc t->c_lflag &= ~EXTPROC; 43435811Smarc tp->t_lflag = t->c_lflag; 43535811Smarc bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 43612752Ssam splx(s); 43712752Ssam break; 43812752Ssam } 43912752Ssam 44012752Ssam /* 44139555Smarc * Set controlling terminal. 44239555Smarc * Session ctty vnode pointer set in vnode layer. 44334492Skarels */ 44447545Skarels case TIOCSCTTY: 44539555Smarc if (!SESS_LEADER(p) || 44639555Smarc (p->p_session->s_ttyvp || tp->t_session) && 44739555Smarc (tp->t_session != p->p_session)) 44839407Smarc return (EPERM); 44935811Smarc tp->t_session = p->p_session; 45039555Smarc tp->t_pgrp = p->p_pgrp; 45139555Smarc p->p_session->s_ttyp = tp; 45239555Smarc p->p_flag |= SCTTY; 45334492Skarels break; 45439555Smarc 45534492Skarels /* 45635811Smarc * Set terminal process group. 45717545Skarels */ 45818650Sbloom case TIOCSPGRP: { 45935811Smarc register struct pgrp *pgrp = pgfind(*(int *)data); 46017545Skarels 46139555Smarc if (!isctty(p, tp)) 46239555Smarc return (ENOTTY); 46340030Smarc else if (pgrp == NULL || pgrp->pg_session != p->p_session) 46439555Smarc return (EPERM); 46539555Smarc tp->t_pgrp = pgrp; 46612752Ssam break; 46718650Sbloom } 46812752Ssam 46912752Ssam case TIOCGPGRP: 47047545Skarels if (!isctty(p, tp)) 47139555Smarc return (ENOTTY); 47245007Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 47312752Ssam break; 47412752Ssam 47517598Sbloom case TIOCSWINSZ: 47618650Sbloom if (bcmp((caddr_t)&tp->t_winsize, data, 47718650Sbloom sizeof (struct winsize))) { 47817598Sbloom tp->t_winsize = *(struct winsize *)data; 47942882Smarc pgsignal(tp->t_pgrp, SIGWINCH, 1); 48017598Sbloom } 48117598Sbloom break; 48217598Sbloom 48317598Sbloom case TIOCGWINSZ: 48417598Sbloom *(struct winsize *)data = tp->t_winsize; 48517598Sbloom break; 48617598Sbloom 48730534Skarels case TIOCCONS: 48830534Skarels if (*(int *)data) { 48942141Smckusick if (constty && constty != tp && 49042141Smckusick (constty->t_state & (TS_CARR_ON|TS_ISOPEN)) == 49142141Smckusick (TS_CARR_ON|TS_ISOPEN)) 49230534Skarels return (EBUSY); 49330534Skarels #ifndef UCONSOLE 49447545Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 49537554Smckusick return (error); 49630534Skarels #endif 49730534Skarels constty = tp; 49830534Skarels } else if (tp == constty) 49933404Skarels constty = NULL; 50030534Skarels break; 50130534Skarels 502*48439Skarels case TIOCDRAIN: 503*48439Skarels if (error = ttywait(tp)) 504*48439Skarels return (error); 505*48439Skarels break; 506*48439Skarels 50747545Skarels default: 50835811Smarc #ifdef COMPAT_43 50947545Skarels return (ttcompat(tp, com, data, flag)); 51047545Skarels #else 51147545Skarels return (-1); 51235811Smarc #endif 51339Sbill } 5148556Sroot return (0); 51539Sbill } 5164484Swnj 5174484Swnj ttnread(tp) 5184484Swnj struct tty *tp; 5194484Swnj { 5204484Swnj int nread = 0; 5214484Swnj 52235811Smarc if (tp->t_lflag & PENDIN) 5234484Swnj ttypend(tp); 5244484Swnj nread = tp->t_canq.c_cc; 52535811Smarc if ((tp->t_lflag & ICANON) == 0) 5264484Swnj nread += tp->t_rawq.c_cc; 5274484Swnj return (nread); 5284484Swnj } 5294484Swnj 5305408Swnj ttselect(dev, rw) 5314484Swnj dev_t dev; 5325408Swnj int rw; 5334484Swnj { 5344484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5354484Swnj int nread; 53617545Skarels int s = spltty(); 5374484Swnj 5385408Swnj switch (rw) { 5394484Swnj 5404484Swnj case FREAD: 5414484Swnj nread = ttnread(tp); 54237584Smarc if (nread > 0 || 54340712Skarels ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0)) 5445408Swnj goto win; 5454938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5465408Swnj tp->t_state |= TS_RCOLL; 5474484Swnj else 54847545Skarels tp->t_rsel = curproc; 5495408Swnj break; 5504484Swnj 5515408Swnj case FWRITE: 55235811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 5535408Swnj goto win; 5545408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 5555408Swnj tp->t_state |= TS_WCOLL; 5565408Swnj else 55747545Skarels tp->t_wsel = curproc; 5585408Swnj break; 5594484Swnj } 5605408Swnj splx(s); 5615408Swnj return (0); 5625408Swnj win: 5635408Swnj splx(s); 5645408Swnj return (1); 5654484Swnj } 5667436Skre 5677502Sroot /* 56825391Skarels * Initial open of tty, or (re)entry to line discipline. 5697502Sroot */ 5707502Sroot ttyopen(dev, tp) 5717625Ssam dev_t dev; 5727625Ssam register struct tty *tp; 5737502Sroot { 5747502Sroot 5757502Sroot tp->t_dev = dev; 57635811Smarc 5777502Sroot tp->t_state &= ~TS_WOPEN; 57817545Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 57917545Skarels tp->t_state |= TS_ISOPEN; 58017598Sbloom bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 58117545Skarels } 5828556Sroot return (0); 5837502Sroot } 5847502Sroot 5857502Sroot /* 58625391Skarels * "close" a line discipline 58725391Skarels */ 58825391Skarels ttylclose(tp) 58925391Skarels register struct tty *tp; 59025391Skarels { 59125391Skarels 59225391Skarels ttywflush(tp); 59325391Skarels } 59425391Skarels 59525391Skarels /* 5967502Sroot * clean tp on last close 5977502Sroot */ 5987502Sroot ttyclose(tp) 5997625Ssam register struct tty *tp; 6007502Sroot { 60130534Skarels if (constty == tp) 60230534Skarels constty = NULL; 60325391Skarels ttyflush(tp, FREAD|FWRITE); 60439555Smarc tp->t_session = NULL; 60539555Smarc tp->t_pgrp = NULL; 6067502Sroot tp->t_state = 0; 60743377Smarc tp->t_gen++; 60840712Skarels return (0); 6097502Sroot } 6107502Sroot 6117502Sroot /* 61225391Skarels * Handle modem control transition on a tty. 61325391Skarels * Flag indicates new state of carrier. 61425391Skarels * Returns 0 if the line should be turned off, otherwise 1. 61525391Skarels */ 61625391Skarels ttymodem(tp, flag) 61725391Skarels register struct tty *tp; 61825391Skarels { 61925391Skarels 62042193Smarc if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) { 62125391Skarels /* 62225391Skarels * MDMBUF: do flow control according to carrier flag 62325391Skarels */ 62425391Skarels if (flag) { 62525391Skarels tp->t_state &= ~TS_TTSTOP; 62625391Skarels ttstart(tp); 62725391Skarels } else if ((tp->t_state&TS_TTSTOP) == 0) { 62825391Skarels tp->t_state |= TS_TTSTOP; 62925391Skarels (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 63025391Skarels } 63125391Skarels } else if (flag == 0) { 63225391Skarels /* 63325391Skarels * Lost carrier. 63425391Skarels */ 63525391Skarels tp->t_state &= ~TS_CARR_ON; 63642193Smarc if (tp->t_state&TS_ISOPEN && (tp->t_cflag&CLOCAL) == 0) { 63742193Smarc if (tp->t_session && tp->t_session->s_leader) 63842193Smarc psignal(tp->t_session->s_leader, SIGHUP); 63942193Smarc ttyflush(tp, FREAD|FWRITE); 64042193Smarc return (0); 64125391Skarels } 64225391Skarels } else { 64325391Skarels /* 64425391Skarels * Carrier now on. 64525391Skarels */ 64625391Skarels tp->t_state |= TS_CARR_ON; 64737584Smarc ttwakeup(tp); 64825391Skarels } 64925391Skarels return (1); 65025391Skarels } 65125391Skarels 65225391Skarels /* 65325404Skarels * Default modem control routine (for other line disciplines). 65425404Skarels * Return argument flag, to turn off device on carrier drop. 65525404Skarels */ 65625415Skarels nullmodem(tp, flag) 65725415Skarels register struct tty *tp; 65825404Skarels int flag; 65925404Skarels { 66025404Skarels 66125404Skarels if (flag) 66225404Skarels tp->t_state |= TS_CARR_ON; 66339407Smarc else { 66425404Skarels tp->t_state &= ~TS_CARR_ON; 66542193Smarc if ((tp->t_cflag&CLOCAL) == 0) { 66642193Smarc if (tp->t_session && tp->t_session->s_leader) 66742193Smarc psignal(tp->t_session->s_leader, SIGHUP); 66842193Smarc return (0); 66942193Smarc } 67039407Smarc } 67142193Smarc return (1); 67225404Skarels } 67325404Skarels 67425404Skarels /* 6757502Sroot * reinput pending characters after state switch 67617545Skarels * call at spltty(). 6777502Sroot */ 6787502Sroot ttypend(tp) 6797625Ssam register struct tty *tp; 6807502Sroot { 6817502Sroot struct clist tq; 6827502Sroot register c; 6837502Sroot 68435811Smarc tp->t_lflag &= ~PENDIN; 6859578Ssam tp->t_state |= TS_TYPEN; 6867502Sroot tq = tp->t_rawq; 6877502Sroot tp->t_rawq.c_cc = 0; 6887502Sroot tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 6897502Sroot while ((c = getc(&tq)) >= 0) 6907502Sroot ttyinput(c, tp); 6919578Ssam tp->t_state &= ~TS_TYPEN; 6927502Sroot } 6937502Sroot 6947502Sroot /* 69535811Smarc * 6969578Ssam * Place a character on raw TTY input queue, 6979578Ssam * putting in delimiters and waking up top 6989578Ssam * half as needed. Also echo if required. 6999578Ssam * The arguments are the character and the 7009578Ssam * appropriate tty structure. 7017502Sroot */ 7027502Sroot ttyinput(c, tp) 7037625Ssam register c; 7047625Ssam register struct tty *tp; 7057502Sroot { 70635811Smarc register int iflag = tp->t_iflag; 70735811Smarc register int lflag = tp->t_lflag; 70835811Smarc register u_char *cc = tp->t_cc; 70935811Smarc int i, err; 7107502Sroot 7119578Ssam /* 7129578Ssam * If input is pending take it first. 7139578Ssam */ 71435811Smarc if (lflag&PENDIN) 7157502Sroot ttypend(tp); 71635811Smarc /* 71735811Smarc * Gather stats. 71835811Smarc */ 7197502Sroot tk_nin++; 72035811Smarc if (lflag&ICANON) { 72135811Smarc tk_cancc++; 72235811Smarc tp->t_cancc++; 72335811Smarc } else { 72435811Smarc tk_rawcc++; 72535811Smarc tp->t_rawcc++; 72635811Smarc } 7279578Ssam /* 72835811Smarc * Handle exceptional conditions (break, parity, framing). 7299578Ssam */ 73035811Smarc if (err = (c&TTY_ERRORMASK)) { 73135811Smarc c &= ~TTY_ERRORMASK; 73235811Smarc if (err&TTY_FE && !c) { /* break */ 73335811Smarc if (iflag&IGNBRK) 73435811Smarc goto endcase; 73535811Smarc else if (iflag&BRKINT && lflag&ISIG && 73635811Smarc (cc[VINTR] != _POSIX_VDISABLE)) 73735811Smarc c = cc[VINTR]; 73847545Skarels else if (iflag&PARMRK) 73947545Skarels goto parmrk; 74035811Smarc } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 74135811Smarc if (iflag&IGNPAR) 74235811Smarc goto endcase; 74335811Smarc else if (iflag&PARMRK) { 74435811Smarc parmrk: 74535811Smarc putc(0377|TTY_QUOTE, &tp->t_rawq); 74635811Smarc putc(0|TTY_QUOTE, &tp->t_rawq); 74735811Smarc putc(c|TTY_QUOTE, &tp->t_rawq); 74835811Smarc goto endcase; 74935811Smarc } else 75035811Smarc c = 0; 7517502Sroot } 7529578Ssam } 7539578Ssam /* 75435811Smarc * In tandem mode, check high water mark. 7559578Ssam */ 75635811Smarc if (iflag&IXOFF) 75735811Smarc ttyblock(tp); 75835811Smarc if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 7599578Ssam c &= 0177; 76044419Smarc if ((tp->t_lflag&EXTPROC) == 0) { 76144419Smarc /* 76244419Smarc * Check for literal nexting very first 76344419Smarc */ 76444419Smarc if (tp->t_state&TS_LNCH) { 76544419Smarc c |= TTY_QUOTE; 76644419Smarc tp->t_state &= ~TS_LNCH; 76744419Smarc } 76844419Smarc /* 76944419Smarc * Scan for special characters. This code 77044419Smarc * is really just a big case statement with 77144419Smarc * non-constant cases. The bottom of the 77244419Smarc * case statement is labeled ``endcase'', so goto 77344419Smarc * it after a case match, or similar. 77444419Smarc */ 77544419Smarc 77644419Smarc /* 77744419Smarc * Control chars which aren't controlled 77844419Smarc * by ICANON, ISIG, or IXON. 77944419Smarc */ 78044419Smarc if (lflag&IEXTEN) { 78144419Smarc if (CCEQ(cc[VLNEXT], c)) { 78244419Smarc if (lflag&ECHO) { 78344419Smarc if (lflag&ECHOE) 78444419Smarc ttyoutstr("^\b", tp); 78544419Smarc else 78644419Smarc ttyecho(c, tp); 78744419Smarc } 78844419Smarc tp->t_state |= TS_LNCH; 78944419Smarc goto endcase; 79044419Smarc } 79144419Smarc if (CCEQ(cc[VDISCARD], c)) { 79244419Smarc if (lflag&FLUSHO) 79344419Smarc tp->t_lflag &= ~FLUSHO; 79444419Smarc else { 79544419Smarc ttyflush(tp, FWRITE); 79635811Smarc ttyecho(c, tp); 79744419Smarc if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 79844419Smarc ttyretype(tp); 79944419Smarc tp->t_lflag |= FLUSHO; 80044419Smarc } 80144419Smarc goto startoutput; 80235811Smarc } 8039578Ssam } 80444419Smarc /* 80544419Smarc * Signals. 80644419Smarc */ 80744419Smarc if (lflag&ISIG) { 80844419Smarc if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 80944419Smarc if ((lflag&NOFLSH) == 0) 81044419Smarc ttyflush(tp, FREAD|FWRITE); 8117502Sroot ttyecho(c, tp); 81244419Smarc pgsignal(tp->t_pgrp, 81344419Smarc CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 81444419Smarc goto endcase; 8157502Sroot } 81644419Smarc if (CCEQ(cc[VSUSP], c)) { 81744419Smarc if ((lflag&NOFLSH) == 0) 81844419Smarc ttyflush(tp, FREAD); 81944419Smarc ttyecho(c, tp); 82044419Smarc pgsignal(tp->t_pgrp, SIGTSTP, 1); 82144419Smarc goto endcase; 82244419Smarc } 8239578Ssam } 82444419Smarc /* 82544419Smarc * Handle start/stop characters. 82644419Smarc */ 82744419Smarc if (iflag&IXON) { 82844419Smarc if (CCEQ(cc[VSTOP], c)) { 82944419Smarc if ((tp->t_state&TS_TTSTOP) == 0) { 83044419Smarc tp->t_state |= TS_TTSTOP; 83144419Smarc (*cdevsw[major(tp->t_dev)].d_stop)(tp, 83244419Smarc 0); 83344419Smarc return; 83444419Smarc } 83544419Smarc if (!CCEQ(cc[VSTART], c)) 83644419Smarc return; 83744419Smarc /* 83844419Smarc * if VSTART == VSTOP then toggle 83944419Smarc */ 84044419Smarc goto endcase; 84135811Smarc } 84244419Smarc if (CCEQ(cc[VSTART], c)) 84344419Smarc goto restartoutput; 8449578Ssam } 84544419Smarc /* 84644419Smarc * IGNCR, ICRNL, & INLCR 84744419Smarc */ 84844419Smarc if (c == '\r') { 84944419Smarc if (iflag&IGNCR) 85044419Smarc goto endcase; 85144419Smarc else if (iflag&ICRNL) 85244419Smarc c = '\n'; 85344419Smarc } else if (c == '\n' && iflag&INLCR) 85444419Smarc c = '\r'; 8559578Ssam } 85647545Skarels if ((tp->t_lflag&EXTPROC) == 0 && lflag&ICANON) { 85744419Smarc /* 85844419Smarc * From here on down canonical mode character 85944419Smarc * processing takes place. 86044419Smarc */ 86144419Smarc /* 86244419Smarc * erase (^H / ^?) 86344419Smarc */ 86444419Smarc if (CCEQ(cc[VERASE], c)) { 86544419Smarc if (tp->t_rawq.c_cc) 8669578Ssam ttyrub(unputc(&tp->t_rawq), tp); 86744419Smarc goto endcase; 8689578Ssam } 86944419Smarc /* 87044419Smarc * kill (^U) 87144419Smarc */ 87244419Smarc if (CCEQ(cc[VKILL], c)) { 87344419Smarc if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 87444419Smarc (lflag&ECHOPRT) == 0) { 87544419Smarc while (tp->t_rawq.c_cc) 87644419Smarc ttyrub(unputc(&tp->t_rawq), tp); 87744419Smarc } else { 87844419Smarc ttyecho(c, tp); 87944419Smarc if (lflag&ECHOK || lflag&ECHOKE) 88044419Smarc ttyecho('\n', tp); 88144419Smarc while (getc(&tp->t_rawq) > 0) 88244419Smarc ; 88344419Smarc tp->t_rocount = 0; 88444419Smarc } 88544419Smarc tp->t_state &= ~TS_LOCAL; 88644419Smarc goto endcase; 88744419Smarc } 88844419Smarc /* 88944419Smarc * word erase (^W) 89044419Smarc */ 89144419Smarc if (CCEQ(cc[VWERASE], c)) { 89244419Smarc int ctype; 89347545Skarels int alt = lflag&ALTWERASE; 89435811Smarc 89547545Skarels #define CTYPE(c) (partab[(c)&TTY_CHARMASK]&0100) 89644419Smarc /* 89744419Smarc * erase whitespace 89844419Smarc */ 89944419Smarc while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 90044419Smarc ttyrub(c, tp); 90144419Smarc if (c == -1) 90244419Smarc goto endcase; 90344419Smarc /* 90447545Skarels * erase last char of word and remember the 90547545Skarels * next chars type (for ALTWERASE) 90644419Smarc */ 90735811Smarc ttyrub(c, tp); 90844419Smarc c = unputc(&tp->t_rawq); 90947545Skarels if (c == -1) 91044419Smarc goto endcase; 91147545Skarels ctype = CTYPE(c); 91244419Smarc /* 91347545Skarels * erase rest of word 91444419Smarc */ 91544419Smarc do { 91644419Smarc ttyrub(c, tp); 91744419Smarc c = unputc(&tp->t_rawq); 91844419Smarc if (c == -1) 91944419Smarc goto endcase; 92047545Skarels } while (c != ' ' && c != '\t' && 92147545Skarels (alt == 0 || CTYPE(c) == ctype)); 92244419Smarc (void) putc(c, &tp->t_rawq); 92334492Skarels goto endcase; 92444419Smarc #undef CTYPE 92544419Smarc } 92635811Smarc /* 92744419Smarc * reprint line (^R) 92835811Smarc */ 92944419Smarc if (CCEQ(cc[VREPRINT], c)) { 93044419Smarc ttyretype(tp); 93134492Skarels goto endcase; 93234492Skarels } 93335811Smarc /* 93444419Smarc * ^T - kernel info and generate SIGINFO 93535811Smarc */ 93644419Smarc if (CCEQ(cc[VSTATUS], c)) { 93744419Smarc pgsignal(tp->t_pgrp, SIGINFO, 1); 93844419Smarc if ((lflag&NOKERNINFO) == 0) 93944419Smarc ttyinfo(tp); 94044419Smarc goto endcase; 94144419Smarc } 9429578Ssam } 9439578Ssam /* 9449578Ssam * Check for input buffer overflow 9459578Ssam */ 94647545Skarels if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { 94735811Smarc if (iflag&IMAXBEL) { 94835811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 94935811Smarc (void) ttyoutput(CTRL('g'), tp); 95035811Smarc } else 95135811Smarc ttyflush(tp, FREAD | FWRITE); 9529578Ssam goto endcase; 95310391Ssam } 9549578Ssam /* 9559578Ssam * Put data char in q for user and 9569578Ssam * wakeup on seeing a line delimiter. 9579578Ssam */ 9589578Ssam if (putc(c, &tp->t_rawq) >= 0) { 95947545Skarels if ((lflag&ICANON) == 0) { 96047545Skarels ttwakeup(tp); 96147545Skarels ttyecho(c, tp); 96247545Skarels goto endcase; 96347545Skarels } 96435811Smarc if (ttbreakc(c)) { 9659578Ssam tp->t_rocount = 0; 9669578Ssam catq(&tp->t_rawq, &tp->t_canq); 9677502Sroot ttwakeup(tp); 9689578Ssam } else if (tp->t_rocount++ == 0) 9699578Ssam tp->t_rocol = tp->t_col; 9709578Ssam if (tp->t_state&TS_ERASE) { 97135811Smarc /* 97235811Smarc * end of prterase \.../ 97335811Smarc */ 9749578Ssam tp->t_state &= ~TS_ERASE; 9759578Ssam (void) ttyoutput('/', tp); 9769578Ssam } 9779578Ssam i = tp->t_col; 9787502Sroot ttyecho(c, tp); 97935811Smarc if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 98035811Smarc /* 98135811Smarc * Place the cursor over the '^' of the ^D. 98235811Smarc */ 9839578Ssam i = MIN(2, tp->t_col - i); 9849578Ssam while (i > 0) { 9859578Ssam (void) ttyoutput('\b', tp); 9869578Ssam i--; 9879578Ssam } 9889578Ssam } 9897502Sroot } 9909578Ssam endcase: 9919578Ssam /* 99235811Smarc * IXANY means allow any character to restart output. 9939578Ssam */ 99440712Skarels if ((tp->t_state&TS_TTSTOP) && (iflag&IXANY) == 0 && 99540712Skarels cc[VSTART] != cc[VSTOP]) 9967502Sroot return; 9979578Ssam restartoutput: 9987502Sroot tp->t_state &= ~TS_TTSTOP; 99935811Smarc tp->t_lflag &= ~FLUSHO; 10009578Ssam startoutput: 10017502Sroot ttstart(tp); 10027502Sroot } 10037502Sroot 10047502Sroot /* 10059578Ssam * Put character on TTY output queue, adding delays, 10067502Sroot * expanding tabs, and handling the CR/NL bit. 10079578Ssam * This is called both from the top half for output, 10089578Ssam * and from interrupt level for echoing. 10097502Sroot * The arguments are the character and the tty structure. 10107502Sroot * Returns < 0 if putc succeeds, otherwise returns char to resend 10117502Sroot * Must be recursive. 10127502Sroot */ 10137502Sroot ttyoutput(c, tp) 10147502Sroot register c; 10157502Sroot register struct tty *tp; 10167502Sroot { 101744419Smarc register short *colp; 10187502Sroot register ctype; 101935811Smarc register long oflag = tp->t_oflag; 102035811Smarc 102140712Skarels if ((oflag&OPOST) == 0) { 102235811Smarc if (tp->t_lflag&FLUSHO) 10237502Sroot return (-1); 10247502Sroot if (putc(c, &tp->t_outq)) 10257625Ssam return (c); 10267502Sroot tk_nout++; 102735811Smarc tp->t_outcc++; 10287502Sroot return (-1); 10297502Sroot } 103035811Smarc c &= TTY_CHARMASK; 10317502Sroot /* 10327502Sroot * Turn tabs to spaces as required 103342882Smarc * 103442882Smarc * Special case if we have external processing, we don't 103542882Smarc * do the tab expansion because we'll probably get it 103642882Smarc * wrong. If tab expansion needs to be done, let it 103742882Smarc * happen externally. 10387502Sroot */ 103947545Skarels if (c == '\t' && oflag&OXTABS && (tp->t_lflag&EXTPROC) == 0) { 10407502Sroot register int s; 10417502Sroot 10427502Sroot c = 8 - (tp->t_col&7); 104335811Smarc if ((tp->t_lflag&FLUSHO) == 0) { 104417545Skarels s = spltty(); /* don't interrupt tabs */ 10457502Sroot c -= b_to_q(" ", c, &tp->t_outq); 10467502Sroot tk_nout += c; 104735811Smarc tp->t_outcc += c; 10487502Sroot splx(s); 10497502Sroot } 10507502Sroot tp->t_col += c; 10517502Sroot return (c ? -1 : '\t'); 10527502Sroot } 105335811Smarc if (c == CEOT && oflag&ONOEOT) 105447545Skarels return (-1); 10557502Sroot tk_nout++; 105635811Smarc tp->t_outcc++; 10577502Sroot /* 10587502Sroot * turn <nl> to <cr><lf> if desired. 10597502Sroot */ 106035811Smarc if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 10617502Sroot return (c); 106235811Smarc if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 106335811Smarc return (c); 106447545Skarels 10657502Sroot colp = &tp->t_col; 10667502Sroot ctype = partab[c]; 10677502Sroot switch (ctype&077) { 10687502Sroot 10697502Sroot case ORDINARY: 10707502Sroot (*colp)++; 10717502Sroot 10727502Sroot case CONTROL: 10737502Sroot break; 10747502Sroot 10757502Sroot case BACKSPACE: 10767502Sroot if (*colp) 10777502Sroot (*colp)--; 10787502Sroot break; 10797502Sroot 10807502Sroot case NEWLINE: 10817502Sroot *colp = 0; 10827502Sroot break; 10837502Sroot 10847502Sroot case TAB: 10857502Sroot *colp |= 07; 10867502Sroot (*colp)++; 10877502Sroot break; 10887502Sroot 10897502Sroot case RETURN: 10907502Sroot *colp = 0; 10917502Sroot } 10927502Sroot return (-1); 10937502Sroot } 10947502Sroot 10957502Sroot /* 10967502Sroot * Called from device's read routine after it has 10977502Sroot * calculated the tty-structure given as argument. 10987502Sroot */ 109937584Smarc ttread(tp, uio, flag) 11007625Ssam register struct tty *tp; 11017722Swnj struct uio *uio; 11027502Sroot { 11037502Sroot register struct clist *qp; 110435811Smarc register int c; 110541383Smarc register long lflag; 110635811Smarc register u_char *cc = tp->t_cc; 110747545Skarels register struct proc *p = curproc; 11089859Ssam int s, first, error = 0; 11097502Sroot 11107502Sroot loop: 111141383Smarc lflag = tp->t_lflag; 111237584Smarc s = spltty(); 11139578Ssam /* 111437584Smarc * take pending input first 11159578Ssam */ 111635811Smarc if (lflag&PENDIN) 11177502Sroot ttypend(tp); 11189859Ssam splx(s); 111940712Skarels 11209578Ssam /* 11219578Ssam * Hang process if it's in the background. 11229578Ssam */ 112347545Skarels if (isbackground(p, tp)) { 112447545Skarels if ((p->p_sigignore & sigmask(SIGTTIN)) || 112547545Skarels (p->p_sigmask & sigmask(SIGTTIN)) || 112647545Skarels p->p_flag&SPPWAIT || p->p_pgrp->pg_jobc == 0) 11278520Sroot return (EIO); 112847545Skarels pgsignal(p->p_pgrp, SIGTTIN, 1); 112943377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 113043377Smarc ttybg, 0)) 113140712Skarels return (error); 113223165Sbloom goto loop; 11337502Sroot } 113440712Skarels 11359578Ssam /* 113635811Smarc * If canonical, use the canonical queue, 113735811Smarc * else use the raw queue. 113837584Smarc * 113947545Skarels * (should get rid of clists...) 11409578Ssam */ 114135811Smarc qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 114240712Skarels 11439578Ssam /* 114440712Skarels * If there is no input, sleep on rawq 114540712Skarels * awaiting hardware receipt and notification. 114640712Skarels * If we have data, we don't need to check for carrier. 11479578Ssam */ 114817545Skarels s = spltty(); 11499578Ssam if (qp->c_cc <= 0) { 115040712Skarels int carrier; 115140712Skarels 115240712Skarels carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL); 115340712Skarels if (!carrier && tp->t_state&TS_ISOPEN) { 11549859Ssam splx(s); 115540712Skarels return (0); /* EOF */ 11567502Sroot } 115737728Smckusick if (flag & IO_NDELAY) { 115837584Smarc splx(s); 115937584Smarc return (EWOULDBLOCK); 116037584Smarc } 116143377Smarc error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 116240712Skarels carrier ? ttyin : ttopen, 0); 11639859Ssam splx(s); 116443377Smarc if (error) 116540712Skarels return (error); 11669578Ssam goto loop; 11679578Ssam } 11689859Ssam splx(s); 116940712Skarels 11709578Ssam /* 117135811Smarc * Input present, check for input mapping and processing. 11729578Ssam */ 11739578Ssam first = 1; 11749578Ssam while ((c = getc(qp)) >= 0) { 11759578Ssam /* 117635811Smarc * delayed suspend (^Y) 11779578Ssam */ 117835811Smarc if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 117942882Smarc pgsignal(tp->t_pgrp, SIGTSTP, 1); 11809578Ssam if (first) { 118143377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 118243377Smarc TTIPRI | PCATCH, ttybg, 0)) 118340712Skarels break; 11849578Ssam goto loop; 11859578Ssam } 11869578Ssam break; 11877502Sroot } 11889578Ssam /* 118935811Smarc * Interpret EOF only in canonical mode. 11909578Ssam */ 119135811Smarc if (CCEQ(cc[VEOF], c) && lflag&ICANON) 11929578Ssam break; 11939578Ssam /* 11949578Ssam * Give user character. 11959578Ssam */ 119640712Skarels error = ureadc(c, uio); 11979578Ssam if (error) 11989578Ssam break; 119914938Smckusick if (uio->uio_resid == 0) 12009578Ssam break; 12019578Ssam /* 120235811Smarc * In canonical mode check for a "break character" 12039578Ssam * marking the end of a "line of input". 12049578Ssam */ 120540712Skarels if (lflag&ICANON && ttbreakc(c)) 12069578Ssam break; 12079578Ssam first = 0; 12087502Sroot } 12099578Ssam /* 12109578Ssam * Look to unblock output now that (presumably) 12119578Ssam * the input queue has gone down. 12129578Ssam */ 121335811Smarc if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 121447545Skarels if (cc[VSTART] != _POSIX_VDISABLE && 121547545Skarels putc(cc[VSTART], &tp->t_outq) == 0) { 12167502Sroot tp->t_state &= ~TS_TBLOCK; 12177502Sroot ttstart(tp); 12187502Sroot } 121935811Smarc } 12208520Sroot return (error); 12217502Sroot } 12227502Sroot 12237502Sroot /* 122425391Skarels * Check the output queue on tp for space for a kernel message 122525391Skarels * (from uprintf/tprintf). Allow some space over the normal 122625391Skarels * hiwater mark so we don't lose messages due to normal flow 122725391Skarels * control, but don't let the tty run amok. 122830695Skarels * Sleeps here are not interruptible, but we return prematurely 122930695Skarels * if new signals come in. 123025391Skarels */ 123125391Skarels ttycheckoutq(tp, wait) 123225391Skarels register struct tty *tp; 123325391Skarels int wait; 123425391Skarels { 123530695Skarels int hiwat, s, oldsig; 1236*48439Skarels extern int wakeup(); 123725391Skarels 123835811Smarc hiwat = tp->t_hiwat; 123925391Skarels s = spltty(); 124047545Skarels oldsig = curproc->p_sig; 124125391Skarels if (tp->t_outq.c_cc > hiwat + 200) 124229946Skarels while (tp->t_outq.c_cc > hiwat) { 124329946Skarels ttstart(tp); 124447545Skarels if (wait == 0 || curproc->p_sig != oldsig) { 124529946Skarels splx(s); 124629946Skarels return (0); 124729946Skarels } 124830695Skarels timeout(wakeup, (caddr_t)&tp->t_outq, hz); 124929946Skarels tp->t_state |= TS_ASLEEP; 125030695Skarels sleep((caddr_t)&tp->t_outq, PZERO - 1); 125125391Skarels } 125225391Skarels splx(s); 125325391Skarels return (1); 125425391Skarels } 125525391Skarels 125625391Skarels /* 12577502Sroot * Called from the device's write routine after it has 12587502Sroot * calculated the tty-structure given as argument. 12597502Sroot */ 126037584Smarc ttwrite(tp, uio, flag) 12617625Ssam register struct tty *tp; 12629578Ssam register struct uio *uio; 12637502Sroot { 12647502Sroot register char *cp; 126540712Skarels register int cc = 0, ce; 126647545Skarels register struct proc *p = curproc; 12679578Ssam int i, hiwat, cnt, error, s; 12687502Sroot char obuf[OBUFSIZ]; 12697502Sroot 127035811Smarc hiwat = tp->t_hiwat; 12719578Ssam cnt = uio->uio_resid; 12729578Ssam error = 0; 12737502Sroot loop: 127437584Smarc s = spltty(); 127540712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && (tp->t_cflag&CLOCAL) == 0) { 127637584Smarc if (tp->t_state&TS_ISOPEN) { 127737584Smarc splx(s); 127837584Smarc return (EIO); 127937728Smckusick } else if (flag & IO_NDELAY) { 128037584Smarc splx(s); 128140712Skarels error = EWOULDBLOCK; 128240712Skarels goto out; 128337584Smarc } else { 128437584Smarc /* 128537584Smarc * sleep awaiting carrier 128637584Smarc */ 128743377Smarc error = ttysleep(tp, (caddr_t)&tp->t_rawq, 128843377Smarc TTIPRI | PCATCH,ttopen, 0); 128937584Smarc splx(s); 129043377Smarc if (error) 129140712Skarels goto out; 129237584Smarc goto loop; 129337584Smarc } 129437584Smarc } 129537584Smarc splx(s); 12969578Ssam /* 12979578Ssam * Hang the process if it's in the background. 12989578Ssam */ 129947545Skarels if (isbackground(p, tp) && 130047545Skarels tp->t_lflag&TOSTOP && (p->p_flag&SPPWAIT) == 0 && 130147545Skarels (p->p_sigignore & sigmask(SIGTTOU)) == 0 && 130247545Skarels (p->p_sigmask & sigmask(SIGTTOU)) == 0 && 130347545Skarels p->p_pgrp->pg_jobc) { 130447545Skarels pgsignal(p->p_pgrp, SIGTTOU, 1); 130543377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 130643377Smarc ttybg, 0)) 130740712Skarels goto out; 130821776Sbloom goto loop; 13097502Sroot } 13109578Ssam /* 13119578Ssam * Process the user's data in at most OBUFSIZ 131240712Skarels * chunks. Perform any output translation. 131340712Skarels * Keep track of high water mark, sleep on overflow 131440712Skarels * awaiting device aid in acquiring new space. 13159578Ssam */ 131640712Skarels while (uio->uio_resid > 0 || cc > 0) { 131740712Skarels if (tp->t_lflag&FLUSHO) { 131840712Skarels uio->uio_resid = 0; 131940712Skarels return (0); 132040712Skarels } 132140712Skarels if (tp->t_outq.c_cc > hiwat) 132232067Skarels goto ovhiwat; 13239578Ssam /* 132440712Skarels * Grab a hunk of data from the user, 132540712Skarels * unless we have some leftover from last time. 13269578Ssam */ 13277822Sroot if (cc == 0) { 132840712Skarels cc = min(uio->uio_resid, OBUFSIZ); 132940712Skarels cp = obuf; 133040712Skarels error = uiomove(cp, cc, uio); 133140712Skarels if (error) { 133240712Skarels cc = 0; 133340712Skarels break; 133440712Skarels } 13357822Sroot } 13369578Ssam /* 13379578Ssam * If nothing fancy need be done, grab those characters we 13389578Ssam * can handle without any of ttyoutput's processing and 13399578Ssam * just transfer them to the output q. For those chars 13409578Ssam * which require special processing (as indicated by the 13419578Ssam * bits in partab), call ttyoutput. After processing 13429578Ssam * a hunk of data, look for FLUSHO so ^O's will take effect 13439578Ssam * immediately. 13449578Ssam */ 13459578Ssam while (cc > 0) { 134640712Skarels if ((tp->t_oflag&OPOST) == 0) 13477502Sroot ce = cc; 13487502Sroot else { 134934492Skarels ce = cc - scanc((unsigned)cc, (u_char *)cp, 135034492Skarels (u_char *)partab, 077); 13519578Ssam /* 13529578Ssam * If ce is zero, then we're processing 13539578Ssam * a special character through ttyoutput. 13549578Ssam */ 13559578Ssam if (ce == 0) { 13567502Sroot tp->t_rocount = 0; 13577502Sroot if (ttyoutput(*cp, tp) >= 0) { 135821776Sbloom /* no c-lists, wait a bit */ 135921776Sbloom ttstart(tp); 136043377Smarc if (error = ttysleep(tp, 136143377Smarc (caddr_t)&lbolt, 136243377Smarc TTOPRI | PCATCH, ttybuf, 0)) 136340712Skarels break; 136421776Sbloom goto loop; 13657502Sroot } 13669578Ssam cp++, cc--; 136735811Smarc if ((tp->t_lflag&FLUSHO) || 13689578Ssam tp->t_outq.c_cc > hiwat) 13697502Sroot goto ovhiwat; 13709578Ssam continue; 13717502Sroot } 13727502Sroot } 13739578Ssam /* 13749578Ssam * A bunch of normal characters have been found, 13759578Ssam * transfer them en masse to the output queue and 13769578Ssam * continue processing at the top of the loop. 13779578Ssam * If there are any further characters in this 13789578Ssam * <= OBUFSIZ chunk, the first should be a character 13799578Ssam * requiring special handling by ttyoutput. 13809578Ssam */ 13817502Sroot tp->t_rocount = 0; 13829578Ssam i = b_to_q(cp, ce, &tp->t_outq); 13839578Ssam ce -= i; 13849578Ssam tp->t_col += ce; 13859578Ssam cp += ce, cc -= ce, tk_nout += ce; 138635811Smarc tp->t_outcc += ce; 13879578Ssam if (i > 0) { 13889578Ssam /* out of c-lists, wait a bit */ 13897502Sroot ttstart(tp); 139043377Smarc if (error = ttysleep(tp, (caddr_t)&lbolt, 139143377Smarc TTOPRI | PCATCH, ttybuf, 0)) 139240712Skarels break; 139321776Sbloom goto loop; 13947502Sroot } 139535811Smarc if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 139640712Skarels break; 13977502Sroot } 139835811Smarc ttstart(tp); 13997502Sroot } 140040712Skarels out: 140140712Skarels /* 140240712Skarels * If cc is nonzero, we leave the uio structure inconsistent, 140340712Skarels * as the offset and iov pointers have moved forward, 140440712Skarels * but it doesn't matter (the call will either return short 140540712Skarels * or restart with a new uio). 140640712Skarels */ 140740712Skarels uio->uio_resid += cc; 14088520Sroot return (error); 140940712Skarels 14107502Sroot ovhiwat: 141132067Skarels ttstart(tp); 141232067Skarels s = spltty(); 14139578Ssam /* 141435811Smarc * This can only occur if FLUSHO is set in t_lflag, 141532067Skarels * or if ttstart/oproc is synchronous (or very fast). 14169578Ssam */ 14177502Sroot if (tp->t_outq.c_cc <= hiwat) { 14189578Ssam splx(s); 14197502Sroot goto loop; 14207502Sroot } 142137728Smckusick if (flag & IO_NDELAY) { 142217545Skarels splx(s); 142340712Skarels uio->uio_resid += cc; 14247822Sroot if (uio->uio_resid == cnt) 14258520Sroot return (EWOULDBLOCK); 14268520Sroot return (0); 14277502Sroot } 14287502Sroot tp->t_state |= TS_ASLEEP; 142943377Smarc error = ttysleep(tp, (caddr_t)&tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 14309578Ssam splx(s); 143143377Smarc if (error) 143240712Skarels goto out; 14337502Sroot goto loop; 14347502Sroot } 14357502Sroot 14367502Sroot /* 14377502Sroot * Rubout one character from the rawq of tp 14387502Sroot * as cleanly as possible. 14397502Sroot */ 14407502Sroot ttyrub(c, tp) 14417625Ssam register c; 14427625Ssam register struct tty *tp; 14437502Sroot { 14447502Sroot register char *cp; 14457502Sroot register int savecol; 14467502Sroot int s; 14477502Sroot char *nextc(); 14487502Sroot 144942882Smarc if ((tp->t_lflag&ECHO) == 0 || (tp->t_lflag&EXTPROC)) 14507502Sroot return; 145135811Smarc tp->t_lflag &= ~FLUSHO; 145235811Smarc if (tp->t_lflag&ECHOE) { 14537502Sroot if (tp->t_rocount == 0) { 14547502Sroot /* 14557502Sroot * Screwed by ttwrite; retype 14567502Sroot */ 14577502Sroot ttyretype(tp); 14587502Sroot return; 14597502Sroot } 146035811Smarc if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 14617502Sroot ttyrubo(tp, 2); 146235811Smarc else switch (partab[c&=0377]&077) { 14637502Sroot 14647502Sroot case ORDINARY: 146535811Smarc ttyrubo(tp, 1); 14667502Sroot break; 14677502Sroot 14687502Sroot case VTAB: 14697502Sroot case BACKSPACE: 14707502Sroot case CONTROL: 14717502Sroot case RETURN: 147247545Skarels case NEWLINE: 147335811Smarc if (tp->t_lflag&ECHOCTL) 14747502Sroot ttyrubo(tp, 2); 14757502Sroot break; 14767502Sroot 147735811Smarc case TAB: { 147835811Smarc int c; 147935811Smarc 14807502Sroot if (tp->t_rocount < tp->t_rawq.c_cc) { 14817502Sroot ttyretype(tp); 14827502Sroot return; 14837502Sroot } 148417545Skarels s = spltty(); 14857502Sroot savecol = tp->t_col; 14869578Ssam tp->t_state |= TS_CNTTB; 148735811Smarc tp->t_lflag |= FLUSHO; 14887502Sroot tp->t_col = tp->t_rocol; 14899578Ssam cp = tp->t_rawq.c_cf; 149039407Smarc if (cp) 149139407Smarc c = *cp; /* XXX FIX NEXTC */ 149235811Smarc for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 149335811Smarc ttyecho(c, tp); 149435811Smarc tp->t_lflag &= ~FLUSHO; 14959578Ssam tp->t_state &= ~TS_CNTTB; 14967502Sroot splx(s); 14977502Sroot /* 14987502Sroot * savecol will now be length of the tab 14997502Sroot */ 15007502Sroot savecol -= tp->t_col; 15017502Sroot tp->t_col += savecol; 15027502Sroot if (savecol > 8) 15037502Sroot savecol = 8; /* overflow screw */ 15047502Sroot while (--savecol >= 0) 15057502Sroot (void) ttyoutput('\b', tp); 15067502Sroot break; 150735811Smarc } 15087502Sroot 15097502Sroot default: 151037584Smarc /* XXX */ 151135811Smarc printf("ttyrub: would panic c = %d, val = %d\n", 151235811Smarc c, partab[c&=0377]&077); 151335811Smarc /*panic("ttyrub");*/ 15147502Sroot } 151535811Smarc } else if (tp->t_lflag&ECHOPRT) { 15169578Ssam if ((tp->t_state&TS_ERASE) == 0) { 15177502Sroot (void) ttyoutput('\\', tp); 15189578Ssam tp->t_state |= TS_ERASE; 15197502Sroot } 15207502Sroot ttyecho(c, tp); 15217502Sroot } else 152235811Smarc ttyecho(tp->t_cc[VERASE], tp); 15237502Sroot tp->t_rocount--; 15247502Sroot } 15257502Sroot 15267502Sroot /* 15277502Sroot * Crt back over cnt chars perhaps 15287502Sroot * erasing them. 15297502Sroot */ 15307502Sroot ttyrubo(tp, cnt) 15317625Ssam register struct tty *tp; 15327625Ssam int cnt; 15337502Sroot { 15347502Sroot 15357502Sroot while (--cnt >= 0) 153640712Skarels ttyoutstr("\b \b", tp); 15377502Sroot } 15387502Sroot 15397502Sroot /* 15407502Sroot * Reprint the rawq line. 15417502Sroot * We assume c_cc has already been checked. 15427502Sroot */ 15437502Sroot ttyretype(tp) 15447625Ssam register struct tty *tp; 15457502Sroot { 15467502Sroot register char *cp; 15477502Sroot char *nextc(); 154835811Smarc int s, c; 15497502Sroot 155035811Smarc if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 155135811Smarc ttyecho(tp->t_cc[VREPRINT], tp); 15527502Sroot (void) ttyoutput('\n', tp); 155317545Skarels s = spltty(); 155435811Smarc /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 155535811Smarc BIT OF FIRST CHAR ****/ 155635811Smarc for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 155735811Smarc ttyecho(c, tp); 155835811Smarc } 155935811Smarc for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 156035811Smarc ttyecho(c, tp); 156135811Smarc } 15629578Ssam tp->t_state &= ~TS_ERASE; 15637502Sroot splx(s); 15647502Sroot tp->t_rocount = tp->t_rawq.c_cc; 15657502Sroot tp->t_rocol = 0; 15667502Sroot } 15677502Sroot 15687502Sroot /* 156935811Smarc * Echo a typed character to the terminal. 15707502Sroot */ 15717502Sroot ttyecho(c, tp) 15727625Ssam register c; 15737625Ssam register struct tty *tp; 15747502Sroot { 15759578Ssam if ((tp->t_state&TS_CNTTB) == 0) 157635811Smarc tp->t_lflag &= ~FLUSHO; 157747545Skarels if (((tp->t_lflag&ECHO) == 0 && 157847545Skarels ((tp->t_lflag&ECHONL) == 0 || c == '\n')) || (tp->t_lflag&EXTPROC)) 15797502Sroot return; 158035811Smarc if (tp->t_lflag&ECHOCTL) { 158140712Skarels if ((c&TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' || 158240712Skarels c == 0177) { 15837502Sroot (void) ttyoutput('^', tp); 158435811Smarc c &= TTY_CHARMASK; 15857502Sroot if (c == 0177) 15867502Sroot c = '?'; 15877502Sroot else 15887502Sroot c += 'A' - 1; 15897502Sroot } 15907502Sroot } 159135811Smarc (void) ttyoutput(c, tp); 15927502Sroot } 15937502Sroot 15947502Sroot /* 15957502Sroot * send string cp to tp 15967502Sroot */ 159740712Skarels ttyoutstr(cp, tp) 15987625Ssam register char *cp; 15997625Ssam register struct tty *tp; 16007502Sroot { 16017502Sroot register char c; 16027502Sroot 16037502Sroot while (c = *cp++) 16047502Sroot (void) ttyoutput(c, tp); 16057502Sroot } 16067502Sroot 16077502Sroot ttwakeup(tp) 160847545Skarels register struct tty *tp; 16097502Sroot { 16107502Sroot 16117502Sroot if (tp->t_rsel) { 16127502Sroot selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 16137502Sroot tp->t_state &= ~TS_RCOLL; 16147502Sroot tp->t_rsel = 0; 16157502Sroot } 161612752Ssam if (tp->t_state & TS_ASYNC) 161742882Smarc pgsignal(tp->t_pgrp, SIGIO, 1); 16187502Sroot wakeup((caddr_t)&tp->t_rawq); 16197502Sroot } 162035811Smarc 162135811Smarc /* 1622*48439Skarels * Look up a code for a specified speed in a conversion table; 1623*48439Skarels * used by drivers to map software speed values to hardware parameters. 1624*48439Skarels */ 1625*48439Skarels ttspeedtab(speed, table) 1626*48439Skarels register struct speedtab *table; 1627*48439Skarels { 1628*48439Skarels 1629*48439Skarels for ( ; table->sp_speed != -1; table++) 1630*48439Skarels if (table->sp_speed == speed) 1631*48439Skarels return (table->sp_code); 1632*48439Skarels return (-1); 1633*48439Skarels } 1634*48439Skarels 1635*48439Skarels /* 163635811Smarc * set tty hi and low water marks 163735811Smarc * 163835811Smarc * Try to arrange the dynamics so there's about one second 163935811Smarc * from hi to low water. 164035811Smarc * 164135811Smarc */ 164235811Smarc ttsetwater(tp) 164335811Smarc struct tty *tp; 164435811Smarc { 164535811Smarc register cps = tp->t_ospeed / 10; 164635811Smarc register x; 164735811Smarc 164835811Smarc #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 164935811Smarc tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 165035811Smarc x += cps; 165135811Smarc x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 165235811Smarc tp->t_hiwat = roundup(x, CBSIZE); 165335811Smarc #undef clamp 165435811Smarc } 165535811Smarc 165639407Smarc /* 165739407Smarc * (^T) 165839407Smarc * Report on state of foreground process group. 165939407Smarc */ 166039407Smarc ttyinfo(tp) 166139407Smarc struct tty *tp; 166239407Smarc { 166341177Smarc register struct proc *p, *pick = NULL; 166441177Smarc int x, s; 166541177Smarc struct timeval utime, stime; 166642350Smckusick #define pgtok(a) (((a)*NBPG)/1024) 166739407Smarc 166839407Smarc if (ttycheckoutq(tp,0) == 0) 166939407Smarc return; 167041177Smarc /* 167141177Smarc * load average 167241177Smarc */ 167341177Smarc x = (averunnable[0] * 100 + FSCALE/2) >> FSHIFT; 167441177Smarc ttyprintf(tp, "load: %d.", x/100); 167541177Smarc ttyoutint(x%100, 10, 2, tp); 167639555Smarc if (tp->t_session == NULL) 167741177Smarc ttyprintf(tp, " not a controlling terminal\n"); 167841177Smarc else if (tp->t_pgrp == NULL) 167941177Smarc ttyprintf(tp, " no foreground process group\n"); 168041177Smarc else if ((p = tp->t_pgrp->pg_mem) == NULL) 168141177Smarc ttyprintf(tp, " empty foreground process group\n"); 168239407Smarc else { 168341177Smarc /* pick interesting process */ 168439407Smarc for (; p != NULL; p = p->p_pgrpnxt) { 168541177Smarc if (proc_compare(pick, p)) 168641177Smarc pick = p; 168739407Smarc } 168841177Smarc ttyprintf(tp, " cmd: %s %d [%s] ", 168941177Smarc pick->p_comm, pick->p_pid, 1690*48439Skarels pick->p_stat == SRUN ? "running" : 1691*48439Skarels pick->p_wmesg ? pick->p_wmesg : "iowait"); 169241177Smarc /* 169341177Smarc * cpu time 169441177Smarc */ 169547545Skarels if (curproc == pick) 169641177Smarc s = splclock(); 169741177Smarc utime = pick->p_utime; 169841177Smarc stime = pick->p_stime; 169947545Skarels if (curproc == pick) 170041177Smarc splx(s); 170141177Smarc /* user time */ 170241177Smarc x = (utime.tv_usec + 5000) / 10000; /* scale to 100's */ 170341177Smarc ttyoutint(utime.tv_sec, 10, 1, tp); 170441177Smarc tputchar('.', tp); 170541177Smarc ttyoutint(x, 10, 2, tp); 170641177Smarc tputchar('u', tp); 170741177Smarc tputchar(' ', tp); 170841177Smarc /* system time */ 170941177Smarc x = (stime.tv_usec + 5000) / 10000; /* scale to 100's */ 171041177Smarc ttyoutint(stime.tv_sec, 10, 1, tp); 171141177Smarc tputchar('.', tp); 171241177Smarc ttyoutint(x, 10, 2, tp); 171341177Smarc tputchar('s', tp); 171441177Smarc tputchar(' ', tp); 171541177Smarc /* 171641177Smarc * pctcpu 171741177Smarc */ 171841177Smarc x = pick->p_pctcpu * 10000 + FSCALE/2 >> FSHIFT; 171941177Smarc ttyoutint(x/100, 10, 1, tp); 172041177Smarc #ifdef notdef /* do we really want this ??? */ 172141177Smarc tputchar('.', tp); 172241177Smarc ttyoutint(x%100, 10, 2, tp); 172341177Smarc #endif 172447545Skarels ttyprintf(tp, "%% %dk\n", pgtok(pick->p_vmspace->vm_rssize)); 172539407Smarc } 172641177Smarc tp->t_rocount = 0; /* so pending input will be retyped if BS */ 172739407Smarc } 172839407Smarc 172941177Smarc ttyoutint(n, base, min, tp) 173041177Smarc register int n, base, min; 173141177Smarc register struct tty *tp; 173241177Smarc { 173341177Smarc char info[16]; 173441177Smarc register char *p = info; 173541177Smarc 173641177Smarc while (--min >= 0 || n) { 173741177Smarc *p++ = "0123456789abcdef"[n%base]; 173841177Smarc n /= base; 173941177Smarc } 174041177Smarc while (p > info) 174141177Smarc ttyoutput(*--p, tp); 174241177Smarc } 174341177Smarc 174441177Smarc /* 174541177Smarc * Returns 1 if p2 is "better" than p1 174641177Smarc * 174741177Smarc * The algorithm for picking the "interesting" process is thus: 174841177Smarc * 174941177Smarc * 1) (Only foreground processes are eligable - implied) 175041177Smarc * 2) Runnable processes are favored over anything 175141177Smarc * else. The runner with the highest cpu 175241177Smarc * utilization is picked (p_cpu). Ties are 175341177Smarc * broken by picking the highest pid. 175441177Smarc * 3 Next, the sleeper with the shortest sleep 175541177Smarc * time is favored. With ties, we pick out 175641177Smarc * just "short-term" sleepers (SSINTR == 0). 175741177Smarc * Further ties are broken by picking the highest 175841177Smarc * pid. 175941177Smarc * 176041177Smarc */ 176141177Smarc #define isrun(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL)) 176245723Smckusick #define TESTAB(a, b) ((a)<<1 | (b)) 176345723Smckusick #define ONLYA 2 176445723Smckusick #define ONLYB 1 176545723Smckusick #define BOTH 3 176645723Smckusick 176741177Smarc proc_compare(p1, p2) 176841177Smarc register struct proc *p1, *p2; 176941177Smarc { 177041177Smarc 177141177Smarc if (p1 == NULL) 177241177Smarc return (1); 177341177Smarc /* 177441177Smarc * see if at least one of them is runnable 177541177Smarc */ 177645723Smckusick switch (TESTAB(isrun(p1), isrun(p2))) { 177745723Smckusick case ONLYA: 177845723Smckusick return (0); 177945723Smckusick case ONLYB: 178041177Smarc return (1); 178145723Smckusick case BOTH: 178241177Smarc /* 178341177Smarc * tie - favor one with highest recent cpu utilization 178441177Smarc */ 178541177Smarc if (p2->p_cpu > p1->p_cpu) 178641177Smarc return (1); 178741177Smarc if (p1->p_cpu > p2->p_cpu) 178841177Smarc return (0); 178941177Smarc return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 179041177Smarc } 179145723Smckusick /* 179245723Smckusick * weed out zombies 179345723Smckusick */ 179445723Smckusick switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) { 179545723Smckusick case ONLYA: 179645723Smckusick return (1); 179745723Smckusick case ONLYB: 179845723Smckusick return (0); 179945723Smckusick case BOTH: 180045723Smckusick return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 180145723Smckusick } 180241177Smarc /* 180341177Smarc * pick the one with the smallest sleep time 180441177Smarc */ 180541177Smarc if (p2->p_slptime > p1->p_slptime) 180641177Smarc return (0); 180741177Smarc if (p1->p_slptime > p2->p_slptime) 180841177Smarc return (1); 180941177Smarc /* 181041177Smarc * favor one sleeping in a non-interruptible sleep 181141177Smarc */ 181241177Smarc if (p1->p_flag&SSINTR && (p2->p_flag&SSINTR) == 0) 181341177Smarc return (1); 181441177Smarc if (p2->p_flag&SSINTR && (p1->p_flag&SSINTR) == 0) 181541177Smarc return (0); 181647545Skarels return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 181741177Smarc } 181845723Smckusick 181947545Skarels /* XXX move to subr_prf.c */ 182039407Smarc #define TOTTY 0x2 /* XXX should be in header */ 182139407Smarc /*VARARGS2*/ 182239407Smarc ttyprintf(tp, fmt, x1) 182339555Smarc struct tty *tp; 182439407Smarc char *fmt; 182539407Smarc unsigned x1; 182639407Smarc { 182739555Smarc prf(fmt, &x1, TOTTY, (caddr_t)tp); 182839407Smarc } 182939555Smarc 183039555Smarc /* 183139555Smarc * Output char to tty; console putchar style. 183239555Smarc */ 183339555Smarc tputchar(c, tp) 183439555Smarc int c; 183539555Smarc struct tty *tp; 183639555Smarc { 183739555Smarc register s = spltty(); 183839555Smarc 183947545Skarels if ((tp->t_state & (TS_CARR_ON|TS_ISOPEN)) == (TS_CARR_ON|TS_ISOPEN)) { 184039555Smarc if (c == '\n') 184139555Smarc (void) ttyoutput('\r', tp); 184239555Smarc (void) ttyoutput(c, tp); 184339555Smarc ttstart(tp); 184439555Smarc splx(s); 184539555Smarc return (0); 184639555Smarc } 184739555Smarc splx(s); 184839555Smarc return (-1); 184939555Smarc } 185043377Smarc 185144419Smarc /* 185244419Smarc * Sleep on chan. 185344419Smarc * 185444419Smarc * Return ERESTART if tty changed while we napped. 185544419Smarc */ 185643377Smarc ttysleep(tp, chan, pri, wmesg, timo) 185743377Smarc struct tty *tp; 185843377Smarc caddr_t chan; 185943377Smarc int pri; 186043377Smarc char *wmesg; 186143377Smarc int timo; 186243377Smarc { 186343377Smarc int error; 186443377Smarc short gen = tp->t_gen; 186543377Smarc 186643377Smarc if (error = tsleep(chan, pri, wmesg, timo)) 186743377Smarc return (error); 186843377Smarc if (tp->t_gen != gen) 186943377Smarc return (ERESTART); 187043377Smarc return (0); 187143377Smarc } 1872