123387Smckusick /* 229107Smckusick * Copyright (c) 1982, 1986 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*39555Smarc * @(#)tty.c 7.19 (Berkeley) 11/20/89 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 277436Skre /* 287436Skre * Table giving parity for characters and indicating 2935811Smarc * character classes to tty driver. The 8th bit 3035811Smarc * indicates parity, the 7th bit indicates the character 3135811Smarc * is an alphameric or underscore (for ALTWERASE), and the 3235811Smarc * low 6 bits indicate delay type. If the low 6 bits are 0 3335811Smarc * then the character needs no special processing on output. 347436Skre */ 3539Sbill 367436Skre char partab[] = { 3735811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 3835811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 3935811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 4035811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 4135811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 4235811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 4335811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 4435811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 4535811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 4635811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 4735811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 4835811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 4935811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 5035811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 5135811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 5235811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 537436Skre /* 5435811Smarc * meta chars 557436Skre */ 5635811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 5735811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 5835811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 5935811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 6035811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 6135811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 6235811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 6335811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 6435811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 6535811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 6635811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 6735811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 6835811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 6935811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 7035811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 7135811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 727436Skre }; 737436Skre 7435811Smarc extern struct tty *constty; /* temporary virtual console */ 7535811Smarc extern char partab[], maptab[]; 7635811Smarc 77146Sbill /* 7835811Smarc * Is 'c' a line delimiter ("break" character)? 7939Sbill */ 8035811Smarc #define ttbreakc(c) (c == '\n' || CCEQ(cc[VEOF], c) || \ 8135811Smarc CCEQ(cc[VEOL], c) || CCEQ(cc[VEOL2], c)) 8239Sbill 8339Sbill ttychars(tp) 849578Ssam struct tty *tp; 8539Sbill { 8635811Smarc bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 8739Sbill } 8839Sbill 8939Sbill /* 90903Sbill * Wait for output to drain, then flush input waiting. 9139Sbill */ 9212752Ssam ttywflush(tp) 9337584Smarc struct tty *tp; 9439Sbill { 9539Sbill 9612752Ssam ttywait(tp); 9712752Ssam ttyflush(tp, FREAD); 9812752Ssam } 9912752Ssam 10035811Smarc /* 10135811Smarc * Wait for output to drain. 10235811Smarc */ 10312752Ssam ttywait(tp) 10412752Ssam register struct tty *tp; 10512752Ssam { 10637584Smarc int s = spltty(); 10712752Ssam 10813809Ssam while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 10937584Smarc (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 11037584Smarc tp->t_oproc) { 111903Sbill (*tp->t_oproc)(tp); 1125408Swnj tp->t_state |= TS_ASLEEP; 113903Sbill sleep((caddr_t)&tp->t_outq, TTOPRI); 114903Sbill } 1159859Ssam splx(s); 11639Sbill } 11739Sbill 11839Sbill /* 1199578Ssam * Flush all TTY queues 12039Sbill */ 12112752Ssam ttyflush(tp, rw) 1227625Ssam register struct tty *tp; 12339Sbill { 124903Sbill register s; 125903Sbill 12617545Skarels s = spltty(); 127903Sbill if (rw & FREAD) { 128903Sbill while (getc(&tp->t_canq) >= 0) 129903Sbill ; 13037584Smarc ttwakeup(tp); 131903Sbill } 132903Sbill if (rw & FWRITE) { 13337584Smarc wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */ 1345408Swnj tp->t_state &= ~TS_TTSTOP; 1355426Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 136903Sbill while (getc(&tp->t_outq) >= 0) 137903Sbill ; 138903Sbill } 139903Sbill if (rw & FREAD) { 140903Sbill while (getc(&tp->t_rawq) >= 0) 141903Sbill ; 1429578Ssam tp->t_rocount = 0; 143903Sbill tp->t_rocol = 0; 1449578Ssam tp->t_state &= ~TS_LOCAL; 145903Sbill } 146903Sbill splx(s); 14739Sbill } 14839Sbill 149903Sbill /* 150903Sbill * Send stop character on input overflow. 151903Sbill */ 152903Sbill ttyblock(tp) 1537625Ssam register struct tty *tp; 15439Sbill { 155903Sbill register x; 1569578Ssam 157903Sbill x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 158903Sbill if (tp->t_rawq.c_cc > TTYHOG) { 15912752Ssam ttyflush(tp, FREAD|FWRITE); 1605408Swnj tp->t_state &= ~TS_TBLOCK; 161903Sbill } 16215118Skarels /* 16315118Skarels * Block further input iff: 16415118Skarels * Current input > threshold AND input is available to user program 16515118Skarels */ 16616055Skarels if (x >= TTYHOG/2 && 16735811Smarc (!(tp->t_lflag&ICANON)) || (tp->t_canq.c_cc > 0) && 16835811Smarc tp->t_cc[VSTOP] != _POSIX_VDISABLE) { 16935811Smarc if (putc(tp->t_cc[VSTOP], &tp->t_outq)==0) { 17015118Skarels tp->t_state |= TS_TBLOCK; 17115118Skarels ttstart(tp); 17215118Skarels } 173903Sbill } 17439Sbill } 17539Sbill 17639Sbill /* 177903Sbill * Restart typewriter output following a delay 178903Sbill * timeout. 179903Sbill * The name of the routine is passed to the timeout 180903Sbill * subroutine and it is called during a clock interrupt. 181121Sbill */ 182903Sbill ttrstrt(tp) 18337584Smarc struct tty *tp; 184121Sbill { 185121Sbill 1869578Ssam if (tp == 0) 1879578Ssam panic("ttrstrt"); 1885408Swnj tp->t_state &= ~TS_TIMEOUT; 189903Sbill ttstart(tp); 190121Sbill } 191121Sbill 192121Sbill /* 193903Sbill * Start output on the typewriter. It is used from the top half 194903Sbill * after some characters have been put on the output queue, 195903Sbill * from the interrupt routine to transmit the next 196903Sbill * character, and after a timeout has finished. 19739Sbill */ 198903Sbill ttstart(tp) 19937584Smarc struct tty *tp; 20039Sbill { 20139Sbill 20232067Skarels if (tp->t_oproc) /* kludge for pty */ 203903Sbill (*tp->t_oproc)(tp); 20439Sbill } 20539Sbill 20639Sbill /* 207903Sbill * Common code for tty ioctls. 20839Sbill */ 2091780Sbill /*ARGSUSED*/ 2107625Ssam ttioctl(tp, com, data, flag) 2117625Ssam register struct tty *tp; 2127625Ssam caddr_t data; 21339Sbill { 21439Sbill extern int nldisp; 21537554Smckusick int s, error; 21639Sbill 217903Sbill /* 218903Sbill * If the ioctl involves modification, 21917545Skarels * hang if in the background. 220903Sbill */ 2217625Ssam switch (com) { 22239Sbill 22335811Smarc case TIOCSETD: 224903Sbill case TIOCFLUSH: 22535811Smarc /*case TIOCSPGRP:*/ 2269325Ssam case TIOCSTI: 22717598Sbloom case TIOCSWINSZ: 22835811Smarc case TIOCSETA: 22935811Smarc case TIOCSETAW: 23035811Smarc case TIOCSETAF: 23139407Smarc /**** these get removed **** 23235811Smarc case TIOCSETAS: 23335811Smarc case TIOCSETAWS: 23435811Smarc case TIOCSETAFS: 23539407Smarc /***************************/ 236*39555Smarc while (isbackground(u.u_procp, tp) && 23735811Smarc u.u_procp->p_pgrp->pg_jobc && 238903Sbill (u.u_procp->p_flag&SVFORK) == 0 && 23924392Skarels !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 24024392Skarels !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 24135811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU); 242903Sbill sleep((caddr_t)&lbolt, TTOPRI); 243903Sbill } 244903Sbill break; 245903Sbill } 246903Sbill 2479578Ssam /* 2489578Ssam * Process the ioctl. 2499578Ssam */ 2507625Ssam switch (com) { 251903Sbill 2528556Sroot /* get discipline number */ 25339Sbill case TIOCGETD: 2547625Ssam *(int *)data = tp->t_line; 25539Sbill break; 25639Sbill 2578556Sroot /* set line discipline */ 2587625Ssam case TIOCSETD: { 2597625Ssam register int t = *(int *)data; 26035811Smarc dev_t dev = tp->t_dev; 2619578Ssam int error = 0; 2627625Ssam 26335811Smarc if ((unsigned)t >= nldisp) 26410851Ssam return (ENXIO); 26525584Skarels if (t != tp->t_line) { 26625584Skarels s = spltty(); 26725584Skarels (*linesw[tp->t_line].l_close)(tp); 26825584Skarels error = (*linesw[t].l_open)(dev, tp); 26925584Skarels if (error) { 27035811Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp); 27125584Skarels splx(s); 27225584Skarels return (error); 27325584Skarels } 27425584Skarels tp->t_line = t; 27510851Ssam splx(s); 27610851Ssam } 27739Sbill break; 2787625Ssam } 27939Sbill 2808556Sroot /* prevent more opens on channel */ 2815614Swnj case TIOCEXCL: 2825614Swnj tp->t_state |= TS_XCLUDE; 2835614Swnj break; 2845614Swnj 2855614Swnj case TIOCNXCL: 2865614Swnj tp->t_state &= ~TS_XCLUDE; 2875614Swnj break; 2885614Swnj 28939Sbill case TIOCHPCL: 29035811Smarc tp->t_cflag |= HUPCL; 29139Sbill break; 29239Sbill 2933942Sbugs case TIOCFLUSH: { 2947625Ssam register int flags = *(int *)data; 2957625Ssam 2967625Ssam if (flags == 0) 2973942Sbugs flags = FREAD|FWRITE; 2987625Ssam else 2997625Ssam flags &= FREAD|FWRITE; 30012752Ssam ttyflush(tp, flags); 30139Sbill break; 3023944Sbugs } 30339Sbill 30437584Smarc case FIOASYNC: 30537584Smarc if (*(int *)data) 30637584Smarc tp->t_state |= TS_ASYNC; 30737584Smarc else 30837584Smarc tp->t_state &= ~TS_ASYNC; 30937584Smarc break; 31037584Smarc 31137584Smarc case FIONBIO: 31237584Smarc break; /* XXX remove */ 31337584Smarc 3148556Sroot /* return number of characters immediately available */ 3157625Ssam case FIONREAD: 3167625Ssam *(off_t *)data = ttnread(tp); 317174Sbill break; 318174Sbill 31913077Ssam case TIOCOUTQ: 32013077Ssam *(int *)data = tp->t_outq.c_cc; 32113077Ssam break; 32213077Ssam 3238589Sroot case TIOCSTOP: 32417545Skarels s = spltty(); 3259578Ssam if ((tp->t_state&TS_TTSTOP) == 0) { 3265573Swnj tp->t_state |= TS_TTSTOP; 3275573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 3285573Swnj } 3297625Ssam splx(s); 3305573Swnj break; 3315573Swnj 3328589Sroot case TIOCSTART: 33317545Skarels s = spltty(); 33435811Smarc if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 3355573Swnj tp->t_state &= ~TS_TTSTOP; 33635811Smarc tp->t_lflag &= ~FLUSHO; 3375573Swnj ttstart(tp); 3385573Swnj } 3397625Ssam splx(s); 3405573Swnj break; 3415573Swnj 3429325Ssam /* 3439325Ssam * Simulate typing of a character at the terminal. 3449325Ssam */ 3459325Ssam case TIOCSTI: 34617183Smckusick if (u.u_uid && (flag & FREAD) == 0) 34717183Smckusick return (EPERM); 348*39555Smarc if (u.u_uid && !isctty(u.u_procp, tp)) 3499325Ssam return (EACCES); 3509578Ssam (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 3519325Ssam break; 3529325Ssam 35335811Smarc case TIOCGETA: { 35435811Smarc struct termios *t = (struct termios *)data; 35512752Ssam 35635811Smarc bcopy(&tp->t_termios, t, sizeof(struct termios)); 35735811Smarc break; 35835811Smarc } 35935811Smarc 36039407Smarc /*** THIS ALL GETS REMOVED ***/ 36139407Smarc case JUNK_TIOCSETAS: 36239407Smarc case JUNK_TIOCSETAWS: 36339407Smarc case JUNK_TIOCSETAFS: 36439407Smarc ((struct termios *)data)->c_cflag |= CIGNORE; 36539407Smarc switch(com) { 36639407Smarc case JUNK_TIOCSETAS: 36739407Smarc com = TIOCSETA; 36839407Smarc break; 36939407Smarc case JUNK_TIOCSETAWS: 37039407Smarc com = TIOCSETAW; 37139407Smarc break; 37239407Smarc case JUNK_TIOCSETAFS: 37339407Smarc com = TIOCSETAF; 37439407Smarc break; 37539407Smarc } 37639407Smarc /*******************************/ 37739407Smarc /*FALLTHROGH*/ 37835811Smarc case TIOCSETA: 37935811Smarc case TIOCSETAW: 38037584Smarc case TIOCSETAF: { 38135811Smarc register struct termios *t = (struct termios *)data; 38217545Skarels s = spltty(); 38339407Smarc if (com == TIOCSETAW || com == TIOCSETAF) { 38439407Smarc ttywait(tp); 38539407Smarc if (com == TIOCSETAF); 38639407Smarc ttyflush(tp, FREAD); 38739407Smarc } 38839407Smarc if (!(t->c_cflag&CIGNORE)) { 38935811Smarc /* 39035811Smarc * set device hardware 39135811Smarc */ 39237584Smarc if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 39337584Smarc splx(s); 39435811Smarc return (error); 39537584Smarc } else { 39637584Smarc if (!(tp->t_state&TS_CARR_ON) && 39737584Smarc (tp->t_cflag&CLOCAL) && 39837584Smarc !(t->c_cflag&CLOCAL)) { 39937584Smarc tp->t_state &= ~TS_ISOPEN; 40037584Smarc tp->t_state |= TS_WOPEN; 40137584Smarc ttwakeup(tp); 40237584Smarc } 40335811Smarc tp->t_cflag = t->c_cflag; 40435811Smarc tp->t_ispeed = t->c_ispeed; 40535811Smarc tp->t_ospeed = t->c_ospeed; 40634492Skarels } 40735811Smarc ttsetwater(tp); 40812752Ssam } 40939407Smarc if (com != TIOCSETAF) { 41035811Smarc if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 41135811Smarc if (t->c_lflag&ICANON) { 41235811Smarc tp->t_lflag |= PENDIN; 41335811Smarc ttwakeup(tp); 41435811Smarc } 41535811Smarc else { 41635811Smarc struct clist tq; 41735811Smarc 41835811Smarc catq(&tp->t_rawq, &tp->t_canq); 41935811Smarc tq = tp->t_rawq; 42035811Smarc tp->t_rawq = tp->t_canq; 42135811Smarc tp->t_canq = tq; 42235811Smarc } 42312752Ssam } 42435811Smarc tp->t_iflag = t->c_iflag; 42535811Smarc tp->t_oflag = t->c_oflag; 42635811Smarc tp->t_lflag = t->c_lflag; 42735811Smarc bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 42812752Ssam splx(s); 42912752Ssam break; 43012752Ssam } 43112752Ssam 43212752Ssam /* 433*39555Smarc * Set controlling terminal. 434*39555Smarc * Session ctty vnode pointer set in vnode layer. 43534492Skarels */ 43635811Smarc case TIOCSCTTY: { 43735811Smarc register struct proc *p = u.u_procp; 43834492Skarels 439*39555Smarc if (!SESS_LEADER(p) || 440*39555Smarc (p->p_session->s_ttyvp || tp->t_session) && 441*39555Smarc (tp->t_session != p->p_session)) 44239407Smarc return (EPERM); 44335811Smarc tp->t_session = p->p_session; 444*39555Smarc tp->t_pgrp = p->p_pgrp; 445*39555Smarc p->p_session->s_ttyp = tp; 446*39555Smarc p->p_flag |= SCTTY; 44734492Skarels break; 44835811Smarc } 449*39555Smarc 45034492Skarels /* 45135811Smarc * Set terminal process group. 45217545Skarels */ 45318650Sbloom case TIOCSPGRP: { 45435811Smarc register struct proc *p = u.u_procp; 45535811Smarc register struct pgrp *pgrp = pgfind(*(int *)data); 45617545Skarels 457*39555Smarc if (!isctty(p, tp)) 458*39555Smarc return (ENOTTY); 459*39555Smarc else if (pgrp->pg_session != p->p_session) 460*39555Smarc return (EPERM); 461*39555Smarc tp->t_pgrp = pgrp; 46212752Ssam break; 46318650Sbloom } 46412752Ssam 46512752Ssam case TIOCGPGRP: 466*39555Smarc if (!isctty(u.u_procp, tp)) 467*39555Smarc return (ENOTTY); 468*39555Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 46912752Ssam break; 47012752Ssam 47117598Sbloom case TIOCSWINSZ: 47218650Sbloom if (bcmp((caddr_t)&tp->t_winsize, data, 47318650Sbloom sizeof (struct winsize))) { 47417598Sbloom tp->t_winsize = *(struct winsize *)data; 475*39555Smarc pgsignal(tp->t_pgrp, SIGWINCH); 47617598Sbloom } 47717598Sbloom break; 47817598Sbloom 47917598Sbloom case TIOCGWINSZ: 48017598Sbloom *(struct winsize *)data = tp->t_winsize; 48117598Sbloom break; 48217598Sbloom 48330534Skarels case TIOCCONS: 48430534Skarels if (*(int *)data) { 48530534Skarels if (constty != NULL) 48630534Skarels return (EBUSY); 48730534Skarels #ifndef UCONSOLE 48837554Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 48937554Smckusick return (error); 49030534Skarels #endif 49130534Skarels constty = tp; 49230534Skarels } else if (tp == constty) 49333404Skarels constty = NULL; 49430534Skarels break; 49530534Skarels 49635811Smarc #ifdef COMPAT_43 49735811Smarc case TIOCGETP: 49835811Smarc case TIOCSETP: 49935811Smarc case TIOCSETN: 50035811Smarc case TIOCGETC: 50135811Smarc case TIOCSETC: 50235811Smarc case TIOCSLTC: 50335811Smarc case TIOCGLTC: 50435811Smarc case TIOCLBIS: 50535811Smarc case TIOCLBIC: 50635811Smarc case TIOCLSET: 50735811Smarc case TIOCLGET: 50839407Smarc case OTIOCGETD: 50939407Smarc case OTIOCSETD: 51035811Smarc return(ttcompat(tp, com, data, flag)); 51135811Smarc #endif 51235811Smarc 51339Sbill default: 5148556Sroot return (-1); 51539Sbill } 5168556Sroot return (0); 51739Sbill } 5184484Swnj 5194484Swnj ttnread(tp) 5204484Swnj struct tty *tp; 5214484Swnj { 5224484Swnj int nread = 0; 5234484Swnj 52435811Smarc if (tp->t_lflag & PENDIN) 5254484Swnj ttypend(tp); 5264484Swnj nread = tp->t_canq.c_cc; 52735811Smarc if ((tp->t_lflag & ICANON) == 0) 5284484Swnj nread += tp->t_rawq.c_cc; 5294484Swnj return (nread); 5304484Swnj } 5314484Swnj 5325408Swnj ttselect(dev, rw) 5334484Swnj dev_t dev; 5345408Swnj int rw; 5354484Swnj { 5364484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5374484Swnj int nread; 53817545Skarels int s = spltty(); 5394484Swnj 5405408Swnj switch (rw) { 5414484Swnj 5424484Swnj case FREAD: 5434484Swnj nread = ttnread(tp); 54437584Smarc if (nread > 0 || 54537584Smarc (!(tp->t_cflag&CLOCAL) && !(tp->t_state&TS_CARR_ON))) 5465408Swnj goto win; 5474938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5485408Swnj tp->t_state |= TS_RCOLL; 5494484Swnj else 5504484Swnj tp->t_rsel = u.u_procp; 5515408Swnj break; 5524484Swnj 5535408Swnj case FWRITE: 55435811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 5555408Swnj goto win; 5565408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 5575408Swnj tp->t_state |= TS_WCOLL; 5585408Swnj else 5595408Swnj tp->t_wsel = u.u_procp; 5605408Swnj break; 5614484Swnj } 5625408Swnj splx(s); 5635408Swnj return (0); 5645408Swnj win: 5655408Swnj splx(s); 5665408Swnj return (1); 5674484Swnj } 5687436Skre 5697502Sroot /* 57025391Skarels * Initial open of tty, or (re)entry to line discipline. 5717502Sroot */ 5727502Sroot ttyopen(dev, tp) 5737625Ssam dev_t dev; 5747625Ssam register struct tty *tp; 5757502Sroot { 5767502Sroot 5777502Sroot tp->t_dev = dev; 57835811Smarc 5797502Sroot tp->t_state &= ~TS_WOPEN; 58017545Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 58117545Skarels tp->t_state |= TS_ISOPEN; 58217598Sbloom bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 58317545Skarels } 5848556Sroot return (0); 5857502Sroot } 5867502Sroot 5877502Sroot /* 58825391Skarels * "close" a line discipline 58925391Skarels */ 59025391Skarels ttylclose(tp) 59125391Skarels register struct tty *tp; 59225391Skarels { 59325391Skarels 59425391Skarels ttywflush(tp); 59525391Skarels } 59625391Skarels 59725391Skarels /* 5987502Sroot * clean tp on last close 5997502Sroot */ 6007502Sroot ttyclose(tp) 6017625Ssam register struct tty *tp; 6027502Sroot { 60330534Skarels if (constty == tp) 60430534Skarels constty = NULL; 60525391Skarels ttyflush(tp, FREAD|FWRITE); 606*39555Smarc tp->t_session = NULL; 607*39555Smarc tp->t_pgrp = NULL; 6087502Sroot tp->t_state = 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 62035811Smarc 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; 63625391Skarels if (tp->t_state & TS_ISOPEN) { 63735811Smarc if ((tp->t_lflag & NOHANG) == 0) { 638*39555Smarc pgsignal(tp->t_pgrp, SIGHUP); 639*39555Smarc pgsignal(tp->t_pgrp, SIGCONT); 64025391Skarels ttyflush(tp, FREAD|FWRITE); 64125391Skarels return (0); 64225391Skarels } 64325391Skarels } 64425391Skarels } else { 64525391Skarels /* 64625391Skarels * Carrier now on. 64725391Skarels */ 64825391Skarels tp->t_state |= TS_CARR_ON; 64937584Smarc ttwakeup(tp); 65025391Skarels } 65125391Skarels return (1); 65225391Skarels } 65325391Skarels 65425391Skarels /* 65525404Skarels * Default modem control routine (for other line disciplines). 65625404Skarels * Return argument flag, to turn off device on carrier drop. 65725404Skarels */ 65825415Skarels nullmodem(tp, flag) 65925415Skarels register struct tty *tp; 66025404Skarels int flag; 66125404Skarels { 66225404Skarels 66325404Skarels if (flag) 66425404Skarels tp->t_state |= TS_CARR_ON; 66539407Smarc else { 66625404Skarels tp->t_state &= ~TS_CARR_ON; 66739407Smarc if ((tp->t_lflag & NOHANG) == 0) 668*39555Smarc pgsignal(tp->t_pgrp, SIGHUP); 66939407Smarc } 67025404Skarels return (flag); 67125404Skarels } 67225404Skarels 67325404Skarels /* 6747502Sroot * reinput pending characters after state switch 67517545Skarels * call at spltty(). 6767502Sroot */ 6777502Sroot ttypend(tp) 6787625Ssam register struct tty *tp; 6797502Sroot { 6807502Sroot struct clist tq; 6817502Sroot register c; 6827502Sroot 68335811Smarc tp->t_lflag &= ~PENDIN; 6849578Ssam tp->t_state |= TS_TYPEN; 6857502Sroot tq = tp->t_rawq; 6867502Sroot tp->t_rawq.c_cc = 0; 6877502Sroot tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 6887502Sroot while ((c = getc(&tq)) >= 0) 6897502Sroot ttyinput(c, tp); 6909578Ssam tp->t_state &= ~TS_TYPEN; 6917502Sroot } 6927502Sroot 6937502Sroot /* 69435811Smarc * 6959578Ssam * Place a character on raw TTY input queue, 6969578Ssam * putting in delimiters and waking up top 6979578Ssam * half as needed. Also echo if required. 6989578Ssam * The arguments are the character and the 6999578Ssam * appropriate tty structure. 7007502Sroot */ 7017502Sroot ttyinput(c, tp) 7027625Ssam register c; 7037625Ssam register struct tty *tp; 7047502Sroot { 70535811Smarc register int iflag = tp->t_iflag; 70635811Smarc register int lflag = tp->t_lflag; 70735811Smarc register u_char *cc = tp->t_cc; 70835811Smarc int i, err; 7097502Sroot 7109578Ssam /* 7119578Ssam * If input is pending take it first. 7129578Ssam */ 71335811Smarc if (lflag&PENDIN) 7147502Sroot ttypend(tp); 71535811Smarc /* 71635811Smarc * Gather stats. 71735811Smarc */ 7187502Sroot tk_nin++; 71935811Smarc if (lflag&ICANON) { 72035811Smarc tk_cancc++; 72135811Smarc tp->t_cancc++; 72235811Smarc } else { 72335811Smarc tk_rawcc++; 72435811Smarc tp->t_rawcc++; 72535811Smarc } 7269578Ssam /* 72735811Smarc * Handle exceptional conditions (break, parity, framing). 7289578Ssam */ 72935811Smarc if (err = (c&TTY_ERRORMASK)) { 73035811Smarc c &= ~TTY_ERRORMASK; 73135811Smarc if (err&TTY_FE && !c) { /* break */ 73235811Smarc if (iflag&IGNBRK) 73335811Smarc goto endcase; 73435811Smarc else if (iflag&BRKINT && lflag&ISIG && 73535811Smarc (cc[VINTR] != _POSIX_VDISABLE)) 73635811Smarc c = cc[VINTR]; 73735811Smarc else { 73835811Smarc c = 0; 73935811Smarc if (iflag&PARMRK) 74035811Smarc goto parmrk; 74135811Smarc } 74235811Smarc } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 74335811Smarc if (iflag&IGNPAR) 74435811Smarc goto endcase; 74535811Smarc else if (iflag&PARMRK) { 74635811Smarc parmrk: 74735811Smarc putc(0377|TTY_QUOTE, &tp->t_rawq); 74835811Smarc putc(0|TTY_QUOTE, &tp->t_rawq); 74935811Smarc putc(c|TTY_QUOTE, &tp->t_rawq); 75035811Smarc goto endcase; 75135811Smarc } else 75235811Smarc c = 0; 7537502Sroot } 7549578Ssam } 7559578Ssam /* 75635811Smarc * In tandem mode, check high water mark. 7579578Ssam */ 75835811Smarc if (iflag&IXOFF) 75935811Smarc ttyblock(tp); 76035811Smarc if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 7619578Ssam c &= 0177; 7629578Ssam /* 7639578Ssam * Check for literal nexting very first 7649578Ssam */ 7659578Ssam if (tp->t_state&TS_LNCH) { 76635811Smarc c |= TTY_QUOTE; 7679578Ssam tp->t_state &= ~TS_LNCH; 7689578Ssam } 7699578Ssam /* 7709578Ssam * Scan for special characters. This code 7719578Ssam * is really just a big case statement with 7729578Ssam * non-constant cases. The bottom of the 7739578Ssam * case statement is labeled ``endcase'', so goto 7749578Ssam * it after a case match, or similar. 7759578Ssam */ 77635811Smarc /* 77735811Smarc * Control chars which aren't controlled 77835811Smarc * by ICANON, ISIG, or IXON. 77935811Smarc */ 78039407Smarc if (lflag&IEXTEN) { 78135811Smarc if (CCEQ(cc[VLNEXT],c)) { 78235811Smarc if (lflag&ECHO) { 78335811Smarc if (lflag&ECHOE) 78435811Smarc ttyout("^\b", tp); 78535811Smarc else 78635811Smarc ttyecho(c, tp); 78735811Smarc } 7889578Ssam tp->t_state |= TS_LNCH; 7899578Ssam goto endcase; 7909578Ssam } 79135811Smarc if (CCEQ(cc[VFLUSHO],c)) { 79235811Smarc if (lflag&FLUSHO) 79335811Smarc tp->t_lflag &= ~FLUSHO; 7947502Sroot else { 79512752Ssam ttyflush(tp, FWRITE); 7967502Sroot ttyecho(c, tp); 7979578Ssam if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 7987502Sroot ttyretype(tp); 79935811Smarc tp->t_lflag |= FLUSHO; 8007502Sroot } 8019578Ssam goto startoutput; 8029578Ssam } 80335811Smarc } 80435811Smarc /* 80535811Smarc * Signals. 80635811Smarc */ 80735811Smarc if (lflag&ISIG) { 80835811Smarc if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 80935811Smarc if ((lflag&NOFLSH) == 0) 81035811Smarc ttyflush(tp, FREAD|FWRITE); 81135811Smarc ttyecho(c, tp); 812*39555Smarc pgsignal(tp->t_pgrp, 813*39555Smarc CCEQ(cc[VINTR],c) ? SIGINT : SIGQUIT); 81435811Smarc goto endcase; 81535811Smarc } 81635811Smarc if (CCEQ(cc[VSUSP],c)) { 81735811Smarc if ((lflag&NOFLSH) == 0) 81812752Ssam ttyflush(tp, FREAD); 8199578Ssam ttyecho(c, tp); 820*39555Smarc pgsignal(tp->t_pgrp, SIGTSTP); 8219578Ssam goto endcase; 8229578Ssam } 82339407Smarc if (CCEQ(cc[VINFO],c)) { 82439407Smarc ttyinfo(tp); 82539407Smarc goto endcase; 82639407Smarc } 8279578Ssam } 8289578Ssam /* 8299578Ssam * Handle start/stop characters. 8309578Ssam */ 83135811Smarc if (iflag&IXON) { 83235811Smarc if (CCEQ(cc[VSTOP],c)) { 83335811Smarc if ((tp->t_state&TS_TTSTOP) == 0) { 83435811Smarc tp->t_state |= TS_TTSTOP; 83535811Smarc (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 83635811Smarc return; 83735811Smarc } 83835811Smarc if (!CCEQ(cc[VSTART], c)) 83935811Smarc return; 84035811Smarc /* 84135811Smarc * if VSTART == VSTOP then toggle 84235811Smarc */ 84335811Smarc goto endcase; 8449578Ssam } 84535811Smarc if (CCEQ(cc[VSTART], c)) 84635811Smarc goto restartoutput; 8479578Ssam } 8489578Ssam /* 84935811Smarc * IGNCR, ICRNL, & INLCR 8509578Ssam */ 85135811Smarc if (c == '\r') { 85235811Smarc if (iflag&IGNCR) 85335811Smarc goto endcase; 85435811Smarc else if (iflag&ICRNL) 85535811Smarc c = '\n'; 8569578Ssam } 85735811Smarc else if (c == '\n' && iflag&INLCR) 85835811Smarc c = '\r'; 8599578Ssam /* 86035811Smarc * Non canonical mode; don't process line editing 8619578Ssam * characters; check high water mark for wakeup. 86235811Smarc * 8639578Ssam */ 86435811Smarc if (!(lflag&ICANON)) { 8659578Ssam if (tp->t_rawq.c_cc > TTYHOG) { 86635811Smarc if (iflag&IMAXBEL) { 86735811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 86835811Smarc (void) ttyoutput(CTRL('g'), tp); 86935811Smarc } else 87035811Smarc ttyflush(tp, FREAD | FWRITE); 87135811Smarc } else { 87235811Smarc if (putc(c, &tp->t_rawq) >= 0) { 87335811Smarc ttwakeup(tp); 87435811Smarc ttyecho(c, tp); 87535811Smarc } 8767502Sroot } 8779578Ssam goto endcase; 8789578Ssam } 8799578Ssam /* 88035811Smarc * From here on down canonical mode character 8819578Ssam * processing takes place. 8829578Ssam */ 88335811Smarc /* 88435811Smarc * erase (^H / ^?) 88535811Smarc */ 88639407Smarc if (CCEQ(cc[VERASE], c)) { 8879578Ssam if (tp->t_rawq.c_cc) 8889578Ssam ttyrub(unputc(&tp->t_rawq), tp); 8899578Ssam goto endcase; 8909578Ssam } 89135811Smarc /* 89235811Smarc * kill (^U) 89335811Smarc */ 89435811Smarc if (CCEQ(cc[VKILL], c)) { 89537584Smarc if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 89637584Smarc !(lflag&ECHOPRT)) { 8979578Ssam while (tp->t_rawq.c_cc) 8989578Ssam ttyrub(unputc(&tp->t_rawq), tp); 8999578Ssam } else { 9009578Ssam ttyecho(c, tp); 90135811Smarc if (lflag&ECHOK || lflag&ECHOKE) 90235811Smarc ttyecho('\n', tp); 9039578Ssam while (getc(&tp->t_rawq) > 0) 9049578Ssam ; 9059578Ssam tp->t_rocount = 0; 9069578Ssam } 9079578Ssam tp->t_state &= ~TS_LOCAL; 9089578Ssam goto endcase; 9099578Ssam } 9109578Ssam /* 91135811Smarc * word erase (^W) 9129578Ssam */ 91335811Smarc if (CCEQ(cc[VWERASE], c)) { 91435811Smarc int ctype; 91535811Smarc 91635811Smarc #define CTYPE(c) ((lflag&ALTWERASE) ? (partab[(c)&TTY_CHARMASK]&0100) : 0) 91735811Smarc /* 91835811Smarc * erase whitespace 91935811Smarc */ 92035811Smarc while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 92135811Smarc ttyrub(c, tp); 92235811Smarc if (c == -1) 92334492Skarels goto endcase; 92435811Smarc /* 92535811Smarc * special case last char of token 92635811Smarc */ 92735811Smarc ttyrub(c, tp); 92835811Smarc c = unputc(&tp->t_rawq); 92935811Smarc if (c == -1 || c == ' ' || c == '\t') { 93035811Smarc if (c != -1) 93135811Smarc (void) putc(c, &tp->t_rawq); 93234492Skarels goto endcase; 93334492Skarels } 93435811Smarc /* 93535811Smarc * erase rest of token 93635811Smarc */ 93735811Smarc ctype = CTYPE(c); 93835811Smarc do { 93935811Smarc ttyrub(c, tp); 94035811Smarc c = unputc(&tp->t_rawq); 94135811Smarc if (c == -1) 94235811Smarc goto endcase; 94335811Smarc } while (c != ' ' && c != '\t' && CTYPE(c) == ctype); 94435811Smarc (void) putc(c, &tp->t_rawq); 94535811Smarc goto endcase; 94635811Smarc #undef CTYPE 9479578Ssam } 9489578Ssam /* 94935811Smarc * reprint line (^R) 95035811Smarc */ 95135811Smarc if (CCEQ(cc[VREPRINT], c)) { 95235811Smarc ttyretype(tp); 95335811Smarc goto endcase; 95435811Smarc } 95535811Smarc /* 9569578Ssam * Check for input buffer overflow 9579578Ssam */ 95810391Ssam if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 95935811Smarc if (iflag&IMAXBEL) { 96035811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 96135811Smarc (void) ttyoutput(CTRL('g'), tp); 96235811Smarc } else 96335811Smarc ttyflush(tp, FREAD | FWRITE); 9649578Ssam goto endcase; 96510391Ssam } 9669578Ssam /* 9679578Ssam * Put data char in q for user and 9689578Ssam * wakeup on seeing a line delimiter. 9699578Ssam */ 9709578Ssam if (putc(c, &tp->t_rawq) >= 0) { 97135811Smarc if (ttbreakc(c)) { 9729578Ssam tp->t_rocount = 0; 9739578Ssam catq(&tp->t_rawq, &tp->t_canq); 9747502Sroot ttwakeup(tp); 9759578Ssam } else if (tp->t_rocount++ == 0) 9769578Ssam tp->t_rocol = tp->t_col; 9779578Ssam if (tp->t_state&TS_ERASE) { 97835811Smarc /* 97935811Smarc * end of prterase \.../ 98035811Smarc */ 9819578Ssam tp->t_state &= ~TS_ERASE; 9829578Ssam (void) ttyoutput('/', tp); 9839578Ssam } 9849578Ssam i = tp->t_col; 9857502Sroot ttyecho(c, tp); 98635811Smarc if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 98735811Smarc /* 98835811Smarc * Place the cursor over the '^' of the ^D. 98935811Smarc */ 9909578Ssam i = MIN(2, tp->t_col - i); 9919578Ssam while (i > 0) { 9929578Ssam (void) ttyoutput('\b', tp); 9939578Ssam i--; 9949578Ssam } 9959578Ssam } 9967502Sroot } 9979578Ssam endcase: 9989578Ssam /* 99935811Smarc * IXANY means allow any character to restart output. 10009578Ssam */ 100135811Smarc if ((tp->t_state&TS_TTSTOP) && !(iflag&IXANY) 100235811Smarc && cc[VSTART] != cc[VSTOP]) 10037502Sroot return; 10049578Ssam restartoutput: 10057502Sroot tp->t_state &= ~TS_TTSTOP; 100635811Smarc tp->t_lflag &= ~FLUSHO; 10079578Ssam startoutput: 10087502Sroot ttstart(tp); 10097502Sroot } 10107502Sroot 10117502Sroot /* 10129578Ssam * Put character on TTY output queue, adding delays, 10137502Sroot * expanding tabs, and handling the CR/NL bit. 10149578Ssam * This is called both from the top half for output, 10159578Ssam * and from interrupt level for echoing. 10167502Sroot * The arguments are the character and the tty structure. 10177502Sroot * Returns < 0 if putc succeeds, otherwise returns char to resend 10187502Sroot * Must be recursive. 10197502Sroot */ 10207502Sroot ttyoutput(c, tp) 10217502Sroot register c; 10227502Sroot register struct tty *tp; 10237502Sroot { 10247502Sroot register char *colp; 10257502Sroot register ctype; 102635811Smarc register long oflag = tp->t_oflag; 102735811Smarc 102835811Smarc if (!(oflag&OPOST)) { 102935811Smarc if (tp->t_lflag&FLUSHO) 10307502Sroot return (-1); 10317502Sroot if (putc(c, &tp->t_outq)) 10327625Ssam return (c); 10337502Sroot tk_nout++; 103435811Smarc tp->t_outcc++; 10357502Sroot return (-1); 10367502Sroot } 103735811Smarc c &= TTY_CHARMASK; 10387502Sroot /* 10397502Sroot * Turn tabs to spaces as required 10407502Sroot */ 104135811Smarc if (c == '\t' && oflag&OXTABS ) { 10427502Sroot register int s; 10437502Sroot 10447502Sroot c = 8 - (tp->t_col&7); 104535811Smarc if ((tp->t_lflag&FLUSHO) == 0) { 104617545Skarels s = spltty(); /* don't interrupt tabs */ 10477502Sroot c -= b_to_q(" ", c, &tp->t_outq); 10487502Sroot tk_nout += c; 104935811Smarc tp->t_outcc += c; 10507502Sroot splx(s); 10517502Sroot } 10527502Sroot tp->t_col += c; 10537502Sroot return (c ? -1 : '\t'); 10547502Sroot } 105535811Smarc if (c == CEOT && oflag&ONOEOT) 105635811Smarc return(-1); 10577502Sroot tk_nout++; 105835811Smarc tp->t_outcc++; 10597502Sroot /* 10607502Sroot * turn <nl> to <cr><lf> if desired. 10617502Sroot */ 106235811Smarc if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 10637502Sroot return (c); 106435811Smarc if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 106535811Smarc return (c); 10667502Sroot /* 10677502Sroot * Calculate delays. 10687502Sroot * The numbers here represent clock ticks 10697502Sroot * and are not necessarily optimal for all terminals. 10709578Ssam * 10719578Ssam * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 107235811Smarc * 107335811Smarc * (actually, should THROW AWAY terminals which need delays) 10747502Sroot */ 10757502Sroot colp = &tp->t_col; 10767502Sroot ctype = partab[c]; 10777502Sroot c = 0; 10787502Sroot switch (ctype&077) { 10797502Sroot 10807502Sroot case ORDINARY: 10817502Sroot (*colp)++; 10827502Sroot 10837502Sroot case CONTROL: 10847502Sroot break; 10857502Sroot 10867502Sroot case BACKSPACE: 10877502Sroot if (*colp) 10887502Sroot (*colp)--; 10897502Sroot break; 10907502Sroot 109113821Ssam /* 109213821Ssam * This macro is close enough to the correct thing; 109313821Ssam * it should be replaced by real user settable delays 109413821Ssam * in any event... 109513821Ssam */ 109613821Ssam #define mstohz(ms) (((ms) * hz) >> 10) 10977502Sroot case NEWLINE: 10987502Sroot ctype = (tp->t_flags >> 8) & 03; 10997625Ssam if (ctype == 1) { /* tty 37 */ 110026357Skarels if (*colp > 0) { 110126357Skarels c = (((unsigned)*colp) >> 4) + 3; 110226357Skarels if ((unsigned)c > 6) 110326357Skarels c = 6; 110426357Skarels } 11059578Ssam } else if (ctype == 2) /* vt05 */ 110613821Ssam c = mstohz(100); 11077502Sroot *colp = 0; 11087502Sroot break; 11097502Sroot 11107502Sroot case TAB: 11117502Sroot ctype = (tp->t_flags >> 10) & 03; 11127625Ssam if (ctype == 1) { /* tty 37 */ 11137502Sroot c = 1 - (*colp | ~07); 11147625Ssam if (c < 5) 11157502Sroot c = 0; 11167502Sroot } 11177502Sroot *colp |= 07; 11187502Sroot (*colp)++; 11197502Sroot break; 11207502Sroot 11217502Sroot case VTAB: 11229578Ssam if (tp->t_flags&VTDELAY) /* tty 37 */ 11237502Sroot c = 0177; 11247502Sroot break; 11257502Sroot 11267502Sroot case RETURN: 11277502Sroot ctype = (tp->t_flags >> 12) & 03; 11289578Ssam if (ctype == 1) /* tn 300 */ 112913821Ssam c = mstohz(83); 11309578Ssam else if (ctype == 2) /* ti 700 */ 113113821Ssam c = mstohz(166); 11329578Ssam else if (ctype == 3) { /* concept 100 */ 11337502Sroot int i; 11349578Ssam 11357502Sroot if ((i = *colp) >= 0) 11369578Ssam for (; i < 9; i++) 11377502Sroot (void) putc(0177, &tp->t_outq); 11387502Sroot } 11397502Sroot *colp = 0; 11407502Sroot } 114135811Smarc if (c && (tp->t_lflag&FLUSHO) == 0) 114235811Smarc (void) putc(c|TTY_QUOTE, &tp->t_outq); 11437502Sroot return (-1); 11447502Sroot } 114513821Ssam #undef mstohz 11467502Sroot 11477502Sroot /* 11487502Sroot * Called from device's read routine after it has 11497502Sroot * calculated the tty-structure given as argument. 11507502Sroot */ 115137584Smarc ttread(tp, uio, flag) 11527625Ssam register struct tty *tp; 11537722Swnj struct uio *uio; 11547502Sroot { 11557502Sroot register struct clist *qp; 115635811Smarc register int c; 115735811Smarc register long lflag = tp->t_lflag; 115835811Smarc register u_char *cc = tp->t_cc; 11599859Ssam int s, first, error = 0; 11607502Sroot 11617502Sroot loop: 116237584Smarc s = spltty(); 11639578Ssam /* 116437584Smarc * take pending input first 11659578Ssam */ 116635811Smarc if (lflag&PENDIN) 11677502Sroot ttypend(tp); 116837584Smarc /* 116937584Smarc * Handle carrier. 117037584Smarc */ 117137584Smarc if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 117237584Smarc if (tp->t_state&TS_ISOPEN) { 117337584Smarc splx(s); 117437584Smarc return (0); /* EOF */ 117537728Smckusick } else if (flag & IO_NDELAY) { 117637584Smarc splx(s); 117737584Smarc return (EWOULDBLOCK); 117837584Smarc } else { 117937584Smarc /* 118037584Smarc * sleep awaiting carrier 118137584Smarc */ 118237584Smarc sleep((caddr_t)&tp->t_rawq, TTIPRI); 118337584Smarc splx(s); 118437584Smarc goto loop; 118537584Smarc } 118637584Smarc } 11879859Ssam splx(s); 11889578Ssam /* 11899578Ssam * Hang process if it's in the background. 11909578Ssam */ 1191*39555Smarc if (isbackground(u.u_procp, tp)) { 119224392Skarels if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 119324392Skarels (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 119435811Smarc u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0) 11958520Sroot return (EIO); 119635811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN); 11977502Sroot sleep((caddr_t)&lbolt, TTIPRI); 119823165Sbloom goto loop; 11997502Sroot } 12009578Ssam /* 120135811Smarc * If canonical, use the canonical queue, 120235811Smarc * else use the raw queue. 120337584Smarc * 120437584Smarc * XXX - should get rid of canonical queue. 120537584Smarc * (actually, should get rid of clists...) 12069578Ssam */ 120735811Smarc qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 12089578Ssam /* 12099578Ssam * No input, sleep on rawq awaiting hardware 12109578Ssam * receipt and notification. 12119578Ssam */ 121217545Skarels s = spltty(); 12139578Ssam if (qp->c_cc <= 0) { 121437584Smarc /** XXX ??? ask mike why TS_CARR_ON was (once) necessary here 12159578Ssam if ((tp->t_state&TS_CARR_ON) == 0 || 12169578Ssam (tp->t_state&TS_NBIO)) { 12179859Ssam splx(s); 12189578Ssam return (EWOULDBLOCK); 12197502Sroot } 122037584Smarc **/ 122137728Smckusick if (flag & IO_NDELAY) { 122237584Smarc splx(s); 122337584Smarc return (EWOULDBLOCK); 122437584Smarc } 12259578Ssam sleep((caddr_t)&tp->t_rawq, TTIPRI); 12269859Ssam splx(s); 12279578Ssam goto loop; 12289578Ssam } 12299859Ssam splx(s); 12309578Ssam /* 123135811Smarc * Input present, check for input mapping and processing. 12329578Ssam */ 12339578Ssam first = 1; 12349578Ssam while ((c = getc(qp)) >= 0) { 12359578Ssam /* 123635811Smarc * delayed suspend (^Y) 12379578Ssam */ 123835811Smarc if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 1239*39555Smarc pgsignal(tp->t_pgrp, SIGTSTP); 12409578Ssam if (first) { 12419578Ssam sleep((caddr_t)&lbolt, TTIPRI); 12429578Ssam goto loop; 12439578Ssam } 12449578Ssam break; 12457502Sroot } 12469578Ssam /* 124735811Smarc * Interpret EOF only in canonical mode. 12489578Ssam */ 124935811Smarc if (CCEQ(cc[VEOF], c) && lflag&ICANON) 12509578Ssam break; 12519578Ssam /* 12529578Ssam * Give user character. 12539578Ssam */ 125435811Smarc error = ureadc(c , uio); 12559578Ssam if (error) 12569578Ssam break; 125714938Smckusick if (uio->uio_resid == 0) 12589578Ssam break; 12599578Ssam /* 126035811Smarc * In canonical mode check for a "break character" 12619578Ssam * marking the end of a "line of input". 12629578Ssam */ 126335811Smarc if (lflag&ICANON && ttbreakc(c)) { 12649578Ssam break; 126535811Smarc } 12669578Ssam first = 0; 12677502Sroot } 12689578Ssam /* 12699578Ssam * Look to unblock output now that (presumably) 12709578Ssam * the input queue has gone down. 12719578Ssam */ 127235811Smarc if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 127335811Smarc if (cc[VSTART] != _POSIX_VDISABLE 127435811Smarc && putc(cc[VSTART], &tp->t_outq) == 0) { 12757502Sroot tp->t_state &= ~TS_TBLOCK; 12767502Sroot ttstart(tp); 12777502Sroot } 127835811Smarc } 12798520Sroot return (error); 12807502Sroot } 12817502Sroot 12827502Sroot /* 128325391Skarels * Check the output queue on tp for space for a kernel message 128425391Skarels * (from uprintf/tprintf). Allow some space over the normal 128525391Skarels * hiwater mark so we don't lose messages due to normal flow 128625391Skarels * control, but don't let the tty run amok. 128730695Skarels * Sleeps here are not interruptible, but we return prematurely 128830695Skarels * if new signals come in. 128925391Skarels */ 129025391Skarels ttycheckoutq(tp, wait) 129125391Skarels register struct tty *tp; 129225391Skarels int wait; 129325391Skarels { 129430695Skarels int hiwat, s, oldsig; 129525391Skarels 129635811Smarc hiwat = tp->t_hiwat; 129725391Skarels s = spltty(); 129830695Skarels oldsig = u.u_procp->p_sig; 129925391Skarels if (tp->t_outq.c_cc > hiwat + 200) 130029946Skarels while (tp->t_outq.c_cc > hiwat) { 130129946Skarels ttstart(tp); 130230695Skarels if (wait == 0 || u.u_procp->p_sig != oldsig) { 130329946Skarels splx(s); 130429946Skarels return (0); 130529946Skarels } 130630695Skarels timeout(wakeup, (caddr_t)&tp->t_outq, hz); 130729946Skarels tp->t_state |= TS_ASLEEP; 130830695Skarels sleep((caddr_t)&tp->t_outq, PZERO - 1); 130925391Skarels } 131025391Skarels splx(s); 131125391Skarels return (1); 131225391Skarels } 131325391Skarels 131425391Skarels /* 13157502Sroot * Called from the device's write routine after it has 13167502Sroot * calculated the tty-structure given as argument. 13177502Sroot */ 131837584Smarc ttwrite(tp, uio, flag) 13197625Ssam register struct tty *tp; 13209578Ssam register struct uio *uio; 13217502Sroot { 13227502Sroot register char *cp; 132337728Smckusick register int cc, ce; 13249578Ssam int i, hiwat, cnt, error, s; 13257502Sroot char obuf[OBUFSIZ]; 13267502Sroot 132735811Smarc hiwat = tp->t_hiwat; 13289578Ssam cnt = uio->uio_resid; 13299578Ssam error = 0; 13307502Sroot loop: 133137584Smarc s = spltty(); 133237584Smarc if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 133337584Smarc if (tp->t_state&TS_ISOPEN) { 133437584Smarc splx(s); 133537584Smarc return (EIO); 133637728Smckusick } else if (flag & IO_NDELAY) { 133737584Smarc splx(s); 133837584Smarc return (EWOULDBLOCK); 133937584Smarc } else { 134037584Smarc /* 134137584Smarc * sleep awaiting carrier 134237584Smarc */ 134337584Smarc sleep((caddr_t)&tp->t_rawq, TTIPRI); 134437584Smarc splx(s); 134537584Smarc goto loop; 134637584Smarc } 134737584Smarc } 134837584Smarc splx(s); 13499578Ssam /* 13509578Ssam * Hang the process if it's in the background. 13519578Ssam */ 1352*39555Smarc if (isbackground(u.u_procp, tp) && 135335811Smarc (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 135424392Skarels !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 135535811Smarc !(u.u_procp->p_sigmask & sigmask(SIGTTOU)) && 135635811Smarc u.u_procp->p_pgrp->pg_jobc) { 135735811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU); 13587502Sroot sleep((caddr_t)&lbolt, TTIPRI); 135921776Sbloom goto loop; 13607502Sroot } 13619578Ssam /* 13629578Ssam * Process the user's data in at most OBUFSIZ 13639578Ssam * chunks. Perform lower case simulation and 13649578Ssam * similar hacks. Keep track of high water 13659578Ssam * mark, sleep on overflow awaiting device aid 13669578Ssam * in acquiring new space. 13679578Ssam */ 13687822Sroot while (uio->uio_resid > 0) { 136932067Skarels if (tp->t_outq.c_cc > hiwat) { 137032067Skarels cc = 0; 137132067Skarels goto ovhiwat; 137232067Skarels } 13739578Ssam /* 13749578Ssam * Grab a hunk of data from the user. 13759578Ssam */ 13767822Sroot cc = uio->uio_iov->iov_len; 13777822Sroot if (cc == 0) { 13787822Sroot uio->uio_iovcnt--; 13797822Sroot uio->uio_iov++; 138021776Sbloom if (uio->uio_iovcnt <= 0) 13817822Sroot panic("ttwrite"); 13827822Sroot continue; 13837822Sroot } 13847822Sroot if (cc > OBUFSIZ) 13857822Sroot cc = OBUFSIZ; 13867502Sroot cp = obuf; 138737728Smckusick error = uiomove(cp, cc, uio); 13888520Sroot if (error) 13897502Sroot break; 139035811Smarc if (tp->t_lflag&FLUSHO) 13917502Sroot continue; 13929578Ssam /* 13939578Ssam * If nothing fancy need be done, grab those characters we 13949578Ssam * can handle without any of ttyoutput's processing and 13959578Ssam * just transfer them to the output q. For those chars 13969578Ssam * which require special processing (as indicated by the 13979578Ssam * bits in partab), call ttyoutput. After processing 13989578Ssam * a hunk of data, look for FLUSHO so ^O's will take effect 13999578Ssam * immediately. 14009578Ssam */ 14019578Ssam while (cc > 0) { 140235811Smarc if (!(tp->t_oflag&OPOST)) 14037502Sroot ce = cc; 14047502Sroot else { 140534492Skarels ce = cc - scanc((unsigned)cc, (u_char *)cp, 140634492Skarels (u_char *)partab, 077); 14079578Ssam /* 14089578Ssam * If ce is zero, then we're processing 14099578Ssam * a special character through ttyoutput. 14109578Ssam */ 14119578Ssam if (ce == 0) { 14127502Sroot tp->t_rocount = 0; 14137502Sroot if (ttyoutput(*cp, tp) >= 0) { 141421776Sbloom /* no c-lists, wait a bit */ 141521776Sbloom ttstart(tp); 141621776Sbloom sleep((caddr_t)&lbolt, TTOPRI); 141721776Sbloom if (cc != 0) { 141821776Sbloom uio->uio_iov->iov_base -= cc; 141921776Sbloom uio->uio_iov->iov_len += cc; 142021776Sbloom uio->uio_resid += cc; 142121776Sbloom uio->uio_offset -= cc; 142221776Sbloom } 142321776Sbloom goto loop; 14247502Sroot } 14259578Ssam cp++, cc--; 142635811Smarc if ((tp->t_lflag&FLUSHO) || 14279578Ssam tp->t_outq.c_cc > hiwat) 14287502Sroot goto ovhiwat; 14299578Ssam continue; 14307502Sroot } 14317502Sroot } 14329578Ssam /* 14339578Ssam * A bunch of normal characters have been found, 14349578Ssam * transfer them en masse to the output queue and 14359578Ssam * continue processing at the top of the loop. 14369578Ssam * If there are any further characters in this 14379578Ssam * <= OBUFSIZ chunk, the first should be a character 14389578Ssam * requiring special handling by ttyoutput. 14399578Ssam */ 14407502Sroot tp->t_rocount = 0; 14419578Ssam i = b_to_q(cp, ce, &tp->t_outq); 14429578Ssam ce -= i; 14439578Ssam tp->t_col += ce; 14449578Ssam cp += ce, cc -= ce, tk_nout += ce; 144535811Smarc tp->t_outcc += ce; 14469578Ssam if (i > 0) { 14479578Ssam /* out of c-lists, wait a bit */ 14487502Sroot ttstart(tp); 14497502Sroot sleep((caddr_t)&lbolt, TTOPRI); 145021776Sbloom uio->uio_iov->iov_base -= cc; 145121776Sbloom uio->uio_iov->iov_len += cc; 145221776Sbloom uio->uio_resid += cc; 145321776Sbloom uio->uio_offset -= cc; 145421776Sbloom goto loop; 14557502Sroot } 145635811Smarc if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 14577502Sroot goto ovhiwat; 14587502Sroot } 145935811Smarc ttstart(tp); 14607502Sroot } 14618520Sroot return (error); 14627502Sroot ovhiwat: 14639578Ssam if (cc != 0) { 14649578Ssam uio->uio_iov->iov_base -= cc; 14659578Ssam uio->uio_iov->iov_len += cc; 14669578Ssam uio->uio_resid += cc; 14679578Ssam uio->uio_offset -= cc; 14689578Ssam } 146932067Skarels ttstart(tp); 147032067Skarels s = spltty(); 14719578Ssam /* 147235811Smarc * This can only occur if FLUSHO is set in t_lflag, 147332067Skarels * or if ttstart/oproc is synchronous (or very fast). 14749578Ssam */ 14757502Sroot if (tp->t_outq.c_cc <= hiwat) { 14769578Ssam splx(s); 14777502Sroot goto loop; 14787502Sroot } 147937728Smckusick if (flag & IO_NDELAY) { 148017545Skarels splx(s); 14817822Sroot if (uio->uio_resid == cnt) 14828520Sroot return (EWOULDBLOCK); 14838520Sroot return (0); 14847502Sroot } 14857502Sroot tp->t_state |= TS_ASLEEP; 14867502Sroot sleep((caddr_t)&tp->t_outq, TTOPRI); 14879578Ssam splx(s); 14887502Sroot goto loop; 14897502Sroot } 14907502Sroot 14917502Sroot /* 14927502Sroot * Rubout one character from the rawq of tp 14937502Sroot * as cleanly as possible. 14947502Sroot */ 14957502Sroot ttyrub(c, tp) 14967625Ssam register c; 14977625Ssam register struct tty *tp; 14987502Sroot { 14997502Sroot register char *cp; 15007502Sroot register int savecol; 15017502Sroot int s; 15027502Sroot char *nextc(); 15037502Sroot 150435811Smarc if ((tp->t_lflag&ECHO) == 0) 15057502Sroot return; 150635811Smarc tp->t_lflag &= ~FLUSHO; 150735811Smarc if (tp->t_lflag&ECHOE) { 15087502Sroot if (tp->t_rocount == 0) { 15097502Sroot /* 15107502Sroot * Screwed by ttwrite; retype 15117502Sroot */ 15127502Sroot ttyretype(tp); 15137502Sroot return; 15147502Sroot } 151535811Smarc if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 15167502Sroot ttyrubo(tp, 2); 151735811Smarc else switch (partab[c&=0377]&077) { 15187502Sroot 15197502Sroot case ORDINARY: 152035811Smarc ttyrubo(tp, 1); 15217502Sroot break; 15227502Sroot 15237502Sroot case VTAB: 15247502Sroot case BACKSPACE: 15257502Sroot case CONTROL: 15267502Sroot case RETURN: 152735811Smarc if (tp->t_lflag&ECHOCTL) 15287502Sroot ttyrubo(tp, 2); 15297502Sroot break; 15307502Sroot 153135811Smarc case TAB: { 153235811Smarc int c; 153335811Smarc 15347502Sroot if (tp->t_rocount < tp->t_rawq.c_cc) { 15357502Sroot ttyretype(tp); 15367502Sroot return; 15377502Sroot } 153817545Skarels s = spltty(); 15397502Sroot savecol = tp->t_col; 15409578Ssam tp->t_state |= TS_CNTTB; 154135811Smarc tp->t_lflag |= FLUSHO; 15427502Sroot tp->t_col = tp->t_rocol; 15439578Ssam cp = tp->t_rawq.c_cf; 154439407Smarc if (cp) 154539407Smarc c = *cp; /* XXX FIX NEXTC */ 154635811Smarc for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 154735811Smarc ttyecho(c, tp); 154835811Smarc tp->t_lflag &= ~FLUSHO; 15499578Ssam tp->t_state &= ~TS_CNTTB; 15507502Sroot splx(s); 15517502Sroot /* 15527502Sroot * savecol will now be length of the tab 15537502Sroot */ 15547502Sroot savecol -= tp->t_col; 15557502Sroot tp->t_col += savecol; 15567502Sroot if (savecol > 8) 15577502Sroot savecol = 8; /* overflow screw */ 15587502Sroot while (--savecol >= 0) 15597502Sroot (void) ttyoutput('\b', tp); 15607502Sroot break; 156135811Smarc } 15627502Sroot 15637502Sroot default: 156437584Smarc /* XXX */ 156535811Smarc printf("ttyrub: would panic c = %d, val = %d\n", 156635811Smarc c, partab[c&=0377]&077); 156735811Smarc /*panic("ttyrub");*/ 15687502Sroot } 156935811Smarc } else if (tp->t_lflag&ECHOPRT) { 15709578Ssam if ((tp->t_state&TS_ERASE) == 0) { 15717502Sroot (void) ttyoutput('\\', tp); 15729578Ssam tp->t_state |= TS_ERASE; 15737502Sroot } 15747502Sroot ttyecho(c, tp); 15757502Sroot } else 157635811Smarc ttyecho(tp->t_cc[VERASE], tp); 15777502Sroot tp->t_rocount--; 15787502Sroot } 15797502Sroot 15807502Sroot /* 15817502Sroot * Crt back over cnt chars perhaps 15827502Sroot * erasing them. 15837502Sroot */ 15847502Sroot ttyrubo(tp, cnt) 15857625Ssam register struct tty *tp; 15867625Ssam int cnt; 15877502Sroot { 15887502Sroot 15897502Sroot while (--cnt >= 0) 159035811Smarc ttyout("\b \b", tp); 15917502Sroot } 15927502Sroot 15937502Sroot /* 15947502Sroot * Reprint the rawq line. 15957502Sroot * We assume c_cc has already been checked. 15967502Sroot */ 15977502Sroot ttyretype(tp) 15987625Ssam register struct tty *tp; 15997502Sroot { 16007502Sroot register char *cp; 16017502Sroot char *nextc(); 160235811Smarc int s, c; 16037502Sroot 160435811Smarc if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 160535811Smarc ttyecho(tp->t_cc[VREPRINT], tp); 16067502Sroot (void) ttyoutput('\n', tp); 160717545Skarels s = spltty(); 160835811Smarc /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 160935811Smarc BIT OF FIRST CHAR ****/ 161035811Smarc for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 161135811Smarc ttyecho(c, tp); 161235811Smarc } 161335811Smarc for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 161435811Smarc ttyecho(c, tp); 161535811Smarc } 16169578Ssam tp->t_state &= ~TS_ERASE; 16177502Sroot splx(s); 16187502Sroot tp->t_rocount = tp->t_rawq.c_cc; 16197502Sroot tp->t_rocol = 0; 16207502Sroot } 16217502Sroot 16227502Sroot /* 162335811Smarc * Echo a typed character to the terminal. 16247502Sroot */ 16257502Sroot ttyecho(c, tp) 16267625Ssam register c; 16277625Ssam register struct tty *tp; 16287502Sroot { 16299578Ssam if ((tp->t_state&TS_CNTTB) == 0) 163035811Smarc tp->t_lflag &= ~FLUSHO; 163135811Smarc if ((tp->t_lflag&ECHO) == 0 && !(tp->t_lflag&ECHONL && c == '\n')) 16327502Sroot return; 163335811Smarc if (tp->t_lflag&ECHOCTL) { 163435811Smarc if ((c&TTY_CHARMASK)<=037 && c!='\t' && c!='\n' || c==0177) { 16357502Sroot (void) ttyoutput('^', tp); 163635811Smarc c &= TTY_CHARMASK; 16377502Sroot if (c == 0177) 16387502Sroot c = '?'; 16397502Sroot else 16407502Sroot c += 'A' - 1; 16417502Sroot } 16427502Sroot } 164335811Smarc (void) ttyoutput(c, tp); 16447502Sroot } 16457502Sroot 16467502Sroot /* 16477502Sroot * send string cp to tp 16487502Sroot */ 16497502Sroot ttyout(cp, tp) 16507625Ssam register char *cp; 16517625Ssam register struct tty *tp; 16527502Sroot { 16537502Sroot register char c; 16547502Sroot 16557502Sroot while (c = *cp++) 16567502Sroot (void) ttyoutput(c, tp); 16577502Sroot } 16587502Sroot 16597502Sroot ttwakeup(tp) 16607502Sroot struct tty *tp; 16617502Sroot { 16627502Sroot 16637502Sroot if (tp->t_rsel) { 16647502Sroot selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 16657502Sroot tp->t_state &= ~TS_RCOLL; 16667502Sroot tp->t_rsel = 0; 16677502Sroot } 166812752Ssam if (tp->t_state & TS_ASYNC) 1669*39555Smarc pgsignal(tp->t_pgrp, SIGIO); 16707502Sroot wakeup((caddr_t)&tp->t_rawq); 16717502Sroot } 167235811Smarc 167335811Smarc /* 167435811Smarc * set tty hi and low water marks 167535811Smarc * 167635811Smarc * Try to arrange the dynamics so there's about one second 167735811Smarc * from hi to low water. 167835811Smarc * 167935811Smarc */ 168035811Smarc ttsetwater(tp) 168135811Smarc struct tty *tp; 168235811Smarc { 168335811Smarc register cps = tp->t_ospeed / 10; 168435811Smarc register x; 168535811Smarc 168635811Smarc #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 168735811Smarc tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 168835811Smarc x += cps; 168935811Smarc x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 169035811Smarc tp->t_hiwat = roundup(x, CBSIZE); 169135811Smarc #undef clamp 169235811Smarc } 169335811Smarc 169435811Smarc ttspeedtab(speed, table) 169535811Smarc struct speedtab table[]; 169635811Smarc { 169735811Smarc register int i; 169835811Smarc 169935811Smarc for (i = 0; table[i].sp_speed != -1; i++) 170035811Smarc if (table[i].sp_speed == speed) 170135811Smarc return(table[i].sp_code); 170235811Smarc return(-1); 170335811Smarc } 170439407Smarc 170539407Smarc /* 170639407Smarc * (^T) 170739407Smarc * Report on state of foreground process group. 170839407Smarc */ 170939407Smarc ttyinfo(tp) 171039407Smarc struct tty *tp; 171139407Smarc { 171239407Smarc register struct proc *p; 171339407Smarc 171439407Smarc if (ttycheckoutq(tp,0) == 0) 171539407Smarc return; 1716*39555Smarc if (tp->t_session == NULL) 1717*39555Smarc ttyprintf(tp, "kernel: not a controlling terminal\n"); 1718*39555Smarc else if (tp->t_pgrp == NULL || 1719*39555Smarc (p = tp->t_pgrp->pg_mem) == NULL) 172039407Smarc ttyprintf(tp, "kernel: no foreground process group\n"); 172139407Smarc else { 172239407Smarc int i = 0; 1723*39555Smarc 172439407Smarc for (; p != NULL; p = p->p_pgrpnxt) { 172539407Smarc ttyprintf(tp, 172639407Smarc "kernel: pid: %d state: %x wchan: %x ticks: %d\n", 172739407Smarc p->p_pid, p->p_stat, p->p_wchan, p->p_cpticks); 172839407Smarc if (++i > 6) { 172939407Smarc ttyprintf(tp, "kernel: more...\n"); 173039407Smarc break; 173139407Smarc } 173239407Smarc } 173339407Smarc } 173439407Smarc } 173539407Smarc 173639407Smarc #define TOTTY 0x2 /* XXX should be in header */ 173739407Smarc /*VARARGS2*/ 173839407Smarc ttyprintf(tp, fmt, x1) 1739*39555Smarc struct tty *tp; 174039407Smarc char *fmt; 174139407Smarc unsigned x1; 174239407Smarc { 1743*39555Smarc prf(fmt, &x1, TOTTY, (caddr_t)tp); 174439407Smarc } 1745*39555Smarc 1746*39555Smarc /* 1747*39555Smarc * Output char to tty; console putchar style. 1748*39555Smarc */ 1749*39555Smarc tputchar(c, tp) 1750*39555Smarc int c; 1751*39555Smarc struct tty *tp; 1752*39555Smarc { 1753*39555Smarc register s = spltty(); 1754*39555Smarc 1755*39555Smarc if ((tp->t_state & (TS_CARR_ON | TS_ISOPEN)) 1756*39555Smarc == (TS_CARR_ON | TS_ISOPEN)) { 1757*39555Smarc if (c == '\n') 1758*39555Smarc (void) ttyoutput('\r', tp); 1759*39555Smarc (void) ttyoutput(c, tp); 1760*39555Smarc ttstart(tp); 1761*39555Smarc splx(s); 1762*39555Smarc return (0); 1763*39555Smarc } 1764*39555Smarc splx(s); 1765*39555Smarc return (-1); 1766*39555Smarc } 1767