123387Smckusick /* 2*40712Skarels * 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*40712Skarels * @(#)tty.c 7.21 (Berkeley) 04/03/90 723387Smckusick */ 839Sbill 917095Sbloom #include "param.h" 1017095Sbloom #include "systm.h" 1117095Sbloom #include "user.h" 1217095Sbloom #include "ioctl.h" 1339407Smarc #define TTYDEFCHARS 1417095Sbloom #include "tty.h" 1535811Smarc #undef TTYDEFCHARS 1617095Sbloom #include "proc.h" 1717095Sbloom #include "file.h" 1817095Sbloom #include "conf.h" 1929946Skarels #include "dkstat.h" 2017095Sbloom #include "uio.h" 2117095Sbloom #include "kernel.h" 2237728Smckusick #include "vnode.h" 2335811Smarc #include "syslog.h" 2439Sbill 2537525Smckusick #include "machine/reg.h" 2637525Smckusick 27*40712Skarels /* symbolic sleep message strings */ 28*40712Skarels char ttyin[] = "ttyin"; 29*40712Skarels char ttyout[] = "ttyout"; 30*40712Skarels char ttopen[] = "ttopen"; 31*40712Skarels char ttclos[] = "ttclos"; 32*40712Skarels char ttybg[] = "ttybg"; 33*40712Skarels char ttybuf[] = "ttybuf"; 34*40712Skarels 357436Skre /* 367436Skre * Table giving parity for characters and indicating 3735811Smarc * character classes to tty driver. The 8th bit 3835811Smarc * indicates parity, the 7th bit indicates the character 3935811Smarc * is an alphameric or underscore (for ALTWERASE), and the 4035811Smarc * low 6 bits indicate delay type. If the low 6 bits are 0 4135811Smarc * then the character needs no special processing on output. 427436Skre */ 4339Sbill 447436Skre char partab[] = { 4535811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 4635811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 4735811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 4835811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 4935811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 5035811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 5135811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 5235811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 5335811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 5435811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 5535811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 5635811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 5735811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 5835811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 5935811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 6035811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 617436Skre /* 6235811Smarc * meta chars 637436Skre */ 6435811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 6535811Smarc 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 6635811Smarc 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 6735811Smarc 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 6835811Smarc 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 6935811Smarc 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 7035811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 7135811Smarc 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 7235811Smarc 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 7335811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 7435811Smarc 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 7535811Smarc 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 7635811Smarc 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 7735811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 7835811Smarc 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 7935811Smarc 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 807436Skre }; 817436Skre 8235811Smarc extern struct tty *constty; /* temporary virtual console */ 8335811Smarc extern char partab[], maptab[]; 8435811Smarc 85146Sbill /* 8635811Smarc * Is 'c' a line delimiter ("break" character)? 8739Sbill */ 88*40712Skarels #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \ 89*40712Skarels (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE) 9039Sbill 9139Sbill ttychars(tp) 929578Ssam struct tty *tp; 9339Sbill { 9435811Smarc bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 9539Sbill } 9639Sbill 9739Sbill /* 98903Sbill * Wait for output to drain, then flush input waiting. 9939Sbill */ 10012752Ssam ttywflush(tp) 10137584Smarc struct tty *tp; 10239Sbill { 103*40712Skarels int error; 10439Sbill 105*40712Skarels if ((error = ttywait(tp)) == 0) 106*40712Skarels ttyflush(tp, FREAD); 107*40712Skarels return (error); 10812752Ssam } 10912752Ssam 11035811Smarc /* 11135811Smarc * Wait for output to drain. 11235811Smarc */ 11312752Ssam ttywait(tp) 11412752Ssam register struct tty *tp; 11512752Ssam { 116*40712Skarels int error = 0, s = spltty(); 11712752Ssam 11813809Ssam while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 11937584Smarc (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 12037584Smarc tp->t_oproc) { 121903Sbill (*tp->t_oproc)(tp); 1225408Swnj tp->t_state |= TS_ASLEEP; 123*40712Skarels if (error = tsleep((caddr_t)&tp->t_outq, TTOPRI | PCATCH, 124*40712Skarels ttyout, 0)) 125*40712Skarels break; 126903Sbill } 1279859Ssam splx(s); 128*40712Skarels return (error); 12939Sbill } 13039Sbill 13139Sbill /* 1329578Ssam * Flush all TTY queues 13339Sbill */ 13412752Ssam ttyflush(tp, rw) 1357625Ssam register struct tty *tp; 13639Sbill { 137903Sbill register s; 138903Sbill 13917545Skarels s = spltty(); 140903Sbill if (rw & FREAD) { 141903Sbill while (getc(&tp->t_canq) >= 0) 142903Sbill ; 14337584Smarc ttwakeup(tp); 144903Sbill } 145903Sbill if (rw & FWRITE) { 14637584Smarc wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */ 1475408Swnj tp->t_state &= ~TS_TTSTOP; 1485426Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 149903Sbill while (getc(&tp->t_outq) >= 0) 150903Sbill ; 151903Sbill } 152903Sbill if (rw & FREAD) { 153903Sbill while (getc(&tp->t_rawq) >= 0) 154903Sbill ; 1559578Ssam tp->t_rocount = 0; 156903Sbill tp->t_rocol = 0; 1579578Ssam tp->t_state &= ~TS_LOCAL; 158903Sbill } 159903Sbill splx(s); 16039Sbill } 16139Sbill 162903Sbill /* 163903Sbill * Send stop character on input overflow. 164903Sbill */ 165903Sbill ttyblock(tp) 1667625Ssam register struct tty *tp; 16739Sbill { 168903Sbill register x; 1699578Ssam 170903Sbill x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 171903Sbill if (tp->t_rawq.c_cc > TTYHOG) { 17212752Ssam ttyflush(tp, FREAD|FWRITE); 1735408Swnj tp->t_state &= ~TS_TBLOCK; 174903Sbill } 17515118Skarels /* 17615118Skarels * Block further input iff: 17715118Skarels * Current input > threshold AND input is available to user program 17815118Skarels */ 17916055Skarels if (x >= TTYHOG/2 && 180*40712Skarels ((tp->t_lflag&ICANON) == 0) || (tp->t_canq.c_cc > 0) && 18135811Smarc tp->t_cc[VSTOP] != _POSIX_VDISABLE) { 18235811Smarc if (putc(tp->t_cc[VSTOP], &tp->t_outq)==0) { 18315118Skarels tp->t_state |= TS_TBLOCK; 18415118Skarels ttstart(tp); 18515118Skarels } 186903Sbill } 18739Sbill } 18839Sbill 18939Sbill /* 190903Sbill * Restart typewriter output following a delay 191903Sbill * timeout. 192903Sbill * The name of the routine is passed to the timeout 193903Sbill * subroutine and it is called during a clock interrupt. 194121Sbill */ 195903Sbill ttrstrt(tp) 19637584Smarc struct tty *tp; 197121Sbill { 198121Sbill 199*40712Skarels #ifdef DIAGNOSTIC 2009578Ssam if (tp == 0) 2019578Ssam panic("ttrstrt"); 202*40712Skarels #endif 2035408Swnj tp->t_state &= ~TS_TIMEOUT; 204903Sbill ttstart(tp); 205121Sbill } 206121Sbill 207121Sbill /* 208903Sbill * Start output on the typewriter. It is used from the top half 209903Sbill * after some characters have been put on the output queue, 210903Sbill * from the interrupt routine to transmit the next 211903Sbill * character, and after a timeout has finished. 21239Sbill */ 213903Sbill ttstart(tp) 21437584Smarc struct tty *tp; 21539Sbill { 21639Sbill 21732067Skarels if (tp->t_oproc) /* kludge for pty */ 218903Sbill (*tp->t_oproc)(tp); 21939Sbill } 22039Sbill 22139Sbill /* 222903Sbill * Common code for tty ioctls. 22339Sbill */ 2241780Sbill /*ARGSUSED*/ 2257625Ssam ttioctl(tp, com, data, flag) 2267625Ssam register struct tty *tp; 2277625Ssam caddr_t data; 22839Sbill { 22939Sbill extern int nldisp; 23037554Smckusick int s, error; 23139Sbill 232903Sbill /* 233903Sbill * If the ioctl involves modification, 23417545Skarels * hang if in the background. 235903Sbill */ 2367625Ssam switch (com) { 23739Sbill 23835811Smarc case TIOCSETD: 239903Sbill case TIOCFLUSH: 24035811Smarc /*case TIOCSPGRP:*/ 2419325Ssam case TIOCSTI: 24217598Sbloom case TIOCSWINSZ: 24335811Smarc case TIOCSETA: 24435811Smarc case TIOCSETAW: 24535811Smarc case TIOCSETAF: 24639407Smarc /**** these get removed **** 24735811Smarc case TIOCSETAS: 24835811Smarc case TIOCSETAWS: 24935811Smarc case TIOCSETAFS: 25039407Smarc /***************************/ 25140030Smarc #ifdef COMPAT_43 25240030Smarc case TIOCSETP: 25340030Smarc case TIOCSETN: 25440030Smarc case TIOCSETC: 25540030Smarc case TIOCSLTC: 25640030Smarc case TIOCLBIS: 25740030Smarc case TIOCLBIC: 25840030Smarc case TIOCLSET: 25940030Smarc case OTIOCSETD: 26040030Smarc #endif 26139555Smarc while (isbackground(u.u_procp, tp) && 26235811Smarc u.u_procp->p_pgrp->pg_jobc && 263903Sbill (u.u_procp->p_flag&SVFORK) == 0 && 264*40712Skarels (u.u_procp->p_sigignore & sigmask(SIGTTOU)) == 0 && 265*40712Skarels (u.u_procp->p_sigmask & sigmask(SIGTTOU)) == 0) { 26635811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU); 267*40712Skarels if (error = tsleep((caddr_t)&lbolt, TTOPRI | PCATCH, 268*40712Skarels ttybg, 0)) 269*40712Skarels return (error); 270903Sbill } 271903Sbill break; 272903Sbill } 273903Sbill 2749578Ssam /* 2759578Ssam * Process the ioctl. 2769578Ssam */ 2777625Ssam switch (com) { 278903Sbill 2798556Sroot /* get discipline number */ 28039Sbill case TIOCGETD: 2817625Ssam *(int *)data = tp->t_line; 28239Sbill break; 28339Sbill 2848556Sroot /* set line discipline */ 2857625Ssam case TIOCSETD: { 2867625Ssam register int t = *(int *)data; 28735811Smarc dev_t dev = tp->t_dev; 2887625Ssam 28935811Smarc if ((unsigned)t >= nldisp) 29010851Ssam return (ENXIO); 29125584Skarels if (t != tp->t_line) { 29225584Skarels s = spltty(); 29325584Skarels (*linesw[tp->t_line].l_close)(tp); 29425584Skarels error = (*linesw[t].l_open)(dev, tp); 29525584Skarels if (error) { 29635811Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp); 29725584Skarels splx(s); 29825584Skarels return (error); 29925584Skarels } 30025584Skarels tp->t_line = t; 30110851Ssam splx(s); 30210851Ssam } 30339Sbill break; 3047625Ssam } 30539Sbill 3068556Sroot /* prevent more opens on channel */ 3075614Swnj case TIOCEXCL: 3085614Swnj tp->t_state |= TS_XCLUDE; 3095614Swnj break; 3105614Swnj 3115614Swnj case TIOCNXCL: 3125614Swnj tp->t_state &= ~TS_XCLUDE; 3135614Swnj break; 3145614Swnj 31539Sbill case TIOCHPCL: 31635811Smarc tp->t_cflag |= HUPCL; 31739Sbill break; 31839Sbill 3193942Sbugs case TIOCFLUSH: { 3207625Ssam register int flags = *(int *)data; 3217625Ssam 3227625Ssam if (flags == 0) 3233942Sbugs flags = FREAD|FWRITE; 3247625Ssam else 3257625Ssam flags &= FREAD|FWRITE; 32612752Ssam ttyflush(tp, flags); 32739Sbill break; 3283944Sbugs } 32939Sbill 33037584Smarc case FIOASYNC: 33137584Smarc if (*(int *)data) 33237584Smarc tp->t_state |= TS_ASYNC; 33337584Smarc else 33437584Smarc tp->t_state &= ~TS_ASYNC; 33537584Smarc break; 33637584Smarc 33737584Smarc case FIONBIO: 33837584Smarc break; /* XXX remove */ 33937584Smarc 3408556Sroot /* return number of characters immediately available */ 3417625Ssam case FIONREAD: 3427625Ssam *(off_t *)data = ttnread(tp); 343174Sbill break; 344174Sbill 34513077Ssam case TIOCOUTQ: 34613077Ssam *(int *)data = tp->t_outq.c_cc; 34713077Ssam break; 34813077Ssam 3498589Sroot case TIOCSTOP: 35017545Skarels s = spltty(); 3519578Ssam if ((tp->t_state&TS_TTSTOP) == 0) { 3525573Swnj tp->t_state |= TS_TTSTOP; 3535573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 3545573Swnj } 3557625Ssam splx(s); 3565573Swnj break; 3575573Swnj 3588589Sroot case TIOCSTART: 35917545Skarels s = spltty(); 36035811Smarc if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 3615573Swnj tp->t_state &= ~TS_TTSTOP; 36235811Smarc tp->t_lflag &= ~FLUSHO; 3635573Swnj ttstart(tp); 3645573Swnj } 3657625Ssam splx(s); 3665573Swnj break; 3675573Swnj 3689325Ssam /* 3699325Ssam * Simulate typing of a character at the terminal. 3709325Ssam */ 3719325Ssam case TIOCSTI: 37217183Smckusick if (u.u_uid && (flag & FREAD) == 0) 37317183Smckusick return (EPERM); 37439555Smarc if (u.u_uid && !isctty(u.u_procp, tp)) 3759325Ssam return (EACCES); 3769578Ssam (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 3779325Ssam break; 3789325Ssam 37935811Smarc case TIOCGETA: { 38035811Smarc struct termios *t = (struct termios *)data; 38112752Ssam 38235811Smarc bcopy(&tp->t_termios, t, sizeof(struct termios)); 38335811Smarc break; 38435811Smarc } 38535811Smarc 38639407Smarc /*** THIS ALL GETS REMOVED ***/ 38739407Smarc case JUNK_TIOCSETAS: 38839407Smarc case JUNK_TIOCSETAWS: 38939407Smarc case JUNK_TIOCSETAFS: 39039407Smarc ((struct termios *)data)->c_cflag |= CIGNORE; 39139407Smarc switch(com) { 39239407Smarc case JUNK_TIOCSETAS: 39339407Smarc com = TIOCSETA; 39439407Smarc break; 39539407Smarc case JUNK_TIOCSETAWS: 39639407Smarc com = TIOCSETAW; 39739407Smarc break; 39839407Smarc case JUNK_TIOCSETAFS: 39939407Smarc com = TIOCSETAF; 40039407Smarc break; 40139407Smarc } 40239407Smarc /*******************************/ 40339407Smarc /*FALLTHROGH*/ 40435811Smarc case TIOCSETA: 40535811Smarc case TIOCSETAW: 40637584Smarc case TIOCSETAF: { 40735811Smarc register struct termios *t = (struct termios *)data; 408*40712Skarels 40917545Skarels s = spltty(); 41039407Smarc if (com == TIOCSETAW || com == TIOCSETAF) { 411*40712Skarels if (error = ttywait(tp)) { 412*40712Skarels splx(s); 413*40712Skarels return (error); 414*40712Skarels } 41539407Smarc if (com == TIOCSETAF); 41639407Smarc ttyflush(tp, FREAD); 41739407Smarc } 418*40712Skarels if ((t->c_cflag&CIGNORE) == 0) { 41935811Smarc /* 42035811Smarc * set device hardware 42135811Smarc */ 42237584Smarc if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 42337584Smarc splx(s); 42435811Smarc return (error); 42537584Smarc } else { 426*40712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && 42737584Smarc (tp->t_cflag&CLOCAL) && 428*40712Skarels (t->c_cflag&CLOCAL) == 0) { 42937584Smarc tp->t_state &= ~TS_ISOPEN; 43037584Smarc tp->t_state |= TS_WOPEN; 43137584Smarc ttwakeup(tp); 43237584Smarc } 43335811Smarc tp->t_cflag = t->c_cflag; 43435811Smarc tp->t_ispeed = t->c_ispeed; 43535811Smarc tp->t_ospeed = t->c_ospeed; 43634492Skarels } 43735811Smarc ttsetwater(tp); 43812752Ssam } 43939407Smarc if (com != TIOCSETAF) { 44035811Smarc if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 44135811Smarc if (t->c_lflag&ICANON) { 44235811Smarc tp->t_lflag |= PENDIN; 44335811Smarc ttwakeup(tp); 44435811Smarc } 44535811Smarc else { 44635811Smarc struct clist tq; 44735811Smarc 44835811Smarc catq(&tp->t_rawq, &tp->t_canq); 44935811Smarc tq = tp->t_rawq; 45035811Smarc tp->t_rawq = tp->t_canq; 45135811Smarc tp->t_canq = tq; 45235811Smarc } 45312752Ssam } 45435811Smarc tp->t_iflag = t->c_iflag; 45535811Smarc tp->t_oflag = t->c_oflag; 45635811Smarc tp->t_lflag = t->c_lflag; 45735811Smarc bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 45812752Ssam splx(s); 45912752Ssam break; 46012752Ssam } 46112752Ssam 46212752Ssam /* 46339555Smarc * Set controlling terminal. 46439555Smarc * Session ctty vnode pointer set in vnode layer. 46534492Skarels */ 46635811Smarc case TIOCSCTTY: { 46735811Smarc register struct proc *p = u.u_procp; 46834492Skarels 46939555Smarc if (!SESS_LEADER(p) || 47039555Smarc (p->p_session->s_ttyvp || tp->t_session) && 47139555Smarc (tp->t_session != p->p_session)) 47239407Smarc return (EPERM); 47335811Smarc tp->t_session = p->p_session; 47439555Smarc tp->t_pgrp = p->p_pgrp; 47539555Smarc p->p_session->s_ttyp = tp; 47639555Smarc p->p_flag |= SCTTY; 47734492Skarels break; 47835811Smarc } 47939555Smarc 48034492Skarels /* 48135811Smarc * Set terminal process group. 48217545Skarels */ 48318650Sbloom case TIOCSPGRP: { 48435811Smarc register struct proc *p = u.u_procp; 48535811Smarc register struct pgrp *pgrp = pgfind(*(int *)data); 48617545Skarels 48739555Smarc if (!isctty(p, tp)) 48839555Smarc return (ENOTTY); 48940030Smarc else if (pgrp == NULL || pgrp->pg_session != p->p_session) 49039555Smarc return (EPERM); 49139555Smarc tp->t_pgrp = pgrp; 49212752Ssam break; 49318650Sbloom } 49412752Ssam 49512752Ssam case TIOCGPGRP: 49639555Smarc if (!isctty(u.u_procp, tp)) 49739555Smarc return (ENOTTY); 49839555Smarc *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 49912752Ssam break; 50012752Ssam 50117598Sbloom case TIOCSWINSZ: 50218650Sbloom if (bcmp((caddr_t)&tp->t_winsize, data, 50318650Sbloom sizeof (struct winsize))) { 50417598Sbloom tp->t_winsize = *(struct winsize *)data; 50539555Smarc pgsignal(tp->t_pgrp, SIGWINCH); 50617598Sbloom } 50717598Sbloom break; 50817598Sbloom 50917598Sbloom case TIOCGWINSZ: 51017598Sbloom *(struct winsize *)data = tp->t_winsize; 51117598Sbloom break; 51217598Sbloom 51330534Skarels case TIOCCONS: 51430534Skarels if (*(int *)data) { 51530534Skarels if (constty != NULL) 51630534Skarels return (EBUSY); 51730534Skarels #ifndef UCONSOLE 51837554Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 51937554Smckusick return (error); 52030534Skarels #endif 52130534Skarels constty = tp; 52230534Skarels } else if (tp == constty) 52333404Skarels constty = NULL; 52430534Skarels break; 52530534Skarels 52635811Smarc #ifdef COMPAT_43 52735811Smarc case TIOCGETP: 52835811Smarc case TIOCSETP: 52935811Smarc case TIOCSETN: 53035811Smarc case TIOCGETC: 53135811Smarc case TIOCSETC: 53235811Smarc case TIOCSLTC: 53335811Smarc case TIOCGLTC: 53435811Smarc case TIOCLBIS: 53535811Smarc case TIOCLBIC: 53635811Smarc case TIOCLSET: 53735811Smarc case TIOCLGET: 53839407Smarc case OTIOCGETD: 53939407Smarc case OTIOCSETD: 54035811Smarc return(ttcompat(tp, com, data, flag)); 54135811Smarc #endif 54235811Smarc 54339Sbill default: 5448556Sroot return (-1); 54539Sbill } 5468556Sroot return (0); 54739Sbill } 5484484Swnj 5494484Swnj ttnread(tp) 5504484Swnj struct tty *tp; 5514484Swnj { 5524484Swnj int nread = 0; 5534484Swnj 55435811Smarc if (tp->t_lflag & PENDIN) 5554484Swnj ttypend(tp); 5564484Swnj nread = tp->t_canq.c_cc; 55735811Smarc if ((tp->t_lflag & ICANON) == 0) 5584484Swnj nread += tp->t_rawq.c_cc; 5594484Swnj return (nread); 5604484Swnj } 5614484Swnj 5625408Swnj ttselect(dev, rw) 5634484Swnj dev_t dev; 5645408Swnj int rw; 5654484Swnj { 5664484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5674484Swnj int nread; 56817545Skarels int s = spltty(); 5694484Swnj 5705408Swnj switch (rw) { 5714484Swnj 5724484Swnj case FREAD: 5734484Swnj nread = ttnread(tp); 57437584Smarc if (nread > 0 || 575*40712Skarels ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0)) 5765408Swnj goto win; 5774938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5785408Swnj tp->t_state |= TS_RCOLL; 5794484Swnj else 5804484Swnj tp->t_rsel = u.u_procp; 5815408Swnj break; 5824484Swnj 5835408Swnj case FWRITE: 58435811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 5855408Swnj goto win; 5865408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 5875408Swnj tp->t_state |= TS_WCOLL; 5885408Swnj else 5895408Swnj tp->t_wsel = u.u_procp; 5905408Swnj break; 5914484Swnj } 5925408Swnj splx(s); 5935408Swnj return (0); 5945408Swnj win: 5955408Swnj splx(s); 5965408Swnj return (1); 5974484Swnj } 5987436Skre 5997502Sroot /* 60025391Skarels * Initial open of tty, or (re)entry to line discipline. 6017502Sroot */ 6027502Sroot ttyopen(dev, tp) 6037625Ssam dev_t dev; 6047625Ssam register struct tty *tp; 6057502Sroot { 6067502Sroot 6077502Sroot tp->t_dev = dev; 60835811Smarc 6097502Sroot tp->t_state &= ~TS_WOPEN; 61017545Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 61117545Skarels tp->t_state |= TS_ISOPEN; 61217598Sbloom bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 61317545Skarels } 6148556Sroot return (0); 6157502Sroot } 6167502Sroot 6177502Sroot /* 61825391Skarels * "close" a line discipline 61925391Skarels */ 62025391Skarels ttylclose(tp) 62125391Skarels register struct tty *tp; 62225391Skarels { 62325391Skarels 62425391Skarels ttywflush(tp); 62525391Skarels } 62625391Skarels 62725391Skarels /* 6287502Sroot * clean tp on last close 6297502Sroot */ 6307502Sroot ttyclose(tp) 6317625Ssam register struct tty *tp; 6327502Sroot { 63330534Skarels if (constty == tp) 63430534Skarels constty = NULL; 63525391Skarels ttyflush(tp, FREAD|FWRITE); 63639555Smarc tp->t_session = NULL; 63739555Smarc tp->t_pgrp = NULL; 6387502Sroot tp->t_state = 0; 639*40712Skarels return (0); 6407502Sroot } 6417502Sroot 6427502Sroot /* 64325391Skarels * Handle modem control transition on a tty. 64425391Skarels * Flag indicates new state of carrier. 64525391Skarels * Returns 0 if the line should be turned off, otherwise 1. 64625391Skarels */ 64725391Skarels ttymodem(tp, flag) 64825391Skarels register struct tty *tp; 64925391Skarels { 65025391Skarels 65135811Smarc if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag & MDMBUF)) { 65225391Skarels /* 65325391Skarels * MDMBUF: do flow control according to carrier flag 65425391Skarels */ 65525391Skarels if (flag) { 65625391Skarels tp->t_state &= ~TS_TTSTOP; 65725391Skarels ttstart(tp); 65825391Skarels } else if ((tp->t_state&TS_TTSTOP) == 0) { 65925391Skarels tp->t_state |= TS_TTSTOP; 66025391Skarels (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 66125391Skarels } 66225391Skarels } else if (flag == 0) { 66325391Skarels /* 66425391Skarels * Lost carrier. 66525391Skarels */ 66625391Skarels tp->t_state &= ~TS_CARR_ON; 66725391Skarels if (tp->t_state & TS_ISOPEN) { 66835811Smarc if ((tp->t_lflag & NOHANG) == 0) { 66939555Smarc pgsignal(tp->t_pgrp, SIGHUP); 67039555Smarc pgsignal(tp->t_pgrp, SIGCONT); 67125391Skarels ttyflush(tp, FREAD|FWRITE); 67225391Skarels return (0); 67325391Skarels } 67425391Skarels } 67525391Skarels } else { 67625391Skarels /* 67725391Skarels * Carrier now on. 67825391Skarels */ 67925391Skarels tp->t_state |= TS_CARR_ON; 68037584Smarc ttwakeup(tp); 68125391Skarels } 68225391Skarels return (1); 68325391Skarels } 68425391Skarels 68525391Skarels /* 68625404Skarels * Default modem control routine (for other line disciplines). 68725404Skarels * Return argument flag, to turn off device on carrier drop. 68825404Skarels */ 68925415Skarels nullmodem(tp, flag) 69025415Skarels register struct tty *tp; 69125404Skarels int flag; 69225404Skarels { 69325404Skarels 69425404Skarels if (flag) 69525404Skarels tp->t_state |= TS_CARR_ON; 69639407Smarc else { 69725404Skarels tp->t_state &= ~TS_CARR_ON; 69839407Smarc if ((tp->t_lflag & NOHANG) == 0) 69939555Smarc pgsignal(tp->t_pgrp, SIGHUP); 70039407Smarc } 70125404Skarels return (flag); 70225404Skarels } 70325404Skarels 70425404Skarels /* 7057502Sroot * reinput pending characters after state switch 70617545Skarels * call at spltty(). 7077502Sroot */ 7087502Sroot ttypend(tp) 7097625Ssam register struct tty *tp; 7107502Sroot { 7117502Sroot struct clist tq; 7127502Sroot register c; 7137502Sroot 71435811Smarc tp->t_lflag &= ~PENDIN; 7159578Ssam tp->t_state |= TS_TYPEN; 7167502Sroot tq = tp->t_rawq; 7177502Sroot tp->t_rawq.c_cc = 0; 7187502Sroot tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 7197502Sroot while ((c = getc(&tq)) >= 0) 7207502Sroot ttyinput(c, tp); 7219578Ssam tp->t_state &= ~TS_TYPEN; 7227502Sroot } 7237502Sroot 7247502Sroot /* 72535811Smarc * 7269578Ssam * Place a character on raw TTY input queue, 7279578Ssam * putting in delimiters and waking up top 7289578Ssam * half as needed. Also echo if required. 7299578Ssam * The arguments are the character and the 7309578Ssam * appropriate tty structure. 7317502Sroot */ 7327502Sroot ttyinput(c, tp) 7337625Ssam register c; 7347625Ssam register struct tty *tp; 7357502Sroot { 73635811Smarc register int iflag = tp->t_iflag; 73735811Smarc register int lflag = tp->t_lflag; 73835811Smarc register u_char *cc = tp->t_cc; 73935811Smarc int i, err; 7407502Sroot 7419578Ssam /* 7429578Ssam * If input is pending take it first. 7439578Ssam */ 74435811Smarc if (lflag&PENDIN) 7457502Sroot ttypend(tp); 74635811Smarc /* 74735811Smarc * Gather stats. 74835811Smarc */ 7497502Sroot tk_nin++; 75035811Smarc if (lflag&ICANON) { 75135811Smarc tk_cancc++; 75235811Smarc tp->t_cancc++; 75335811Smarc } else { 75435811Smarc tk_rawcc++; 75535811Smarc tp->t_rawcc++; 75635811Smarc } 7579578Ssam /* 75835811Smarc * Handle exceptional conditions (break, parity, framing). 7599578Ssam */ 76035811Smarc if (err = (c&TTY_ERRORMASK)) { 76135811Smarc c &= ~TTY_ERRORMASK; 76235811Smarc if (err&TTY_FE && !c) { /* break */ 76335811Smarc if (iflag&IGNBRK) 76435811Smarc goto endcase; 76535811Smarc else if (iflag&BRKINT && lflag&ISIG && 76635811Smarc (cc[VINTR] != _POSIX_VDISABLE)) 76735811Smarc c = cc[VINTR]; 76835811Smarc else { 76935811Smarc c = 0; 77035811Smarc if (iflag&PARMRK) 77135811Smarc goto parmrk; 77235811Smarc } 77335811Smarc } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 77435811Smarc if (iflag&IGNPAR) 77535811Smarc goto endcase; 77635811Smarc else if (iflag&PARMRK) { 77735811Smarc parmrk: 77835811Smarc putc(0377|TTY_QUOTE, &tp->t_rawq); 77935811Smarc putc(0|TTY_QUOTE, &tp->t_rawq); 78035811Smarc putc(c|TTY_QUOTE, &tp->t_rawq); 78135811Smarc goto endcase; 78235811Smarc } else 78335811Smarc c = 0; 7847502Sroot } 7859578Ssam } 7869578Ssam /* 78735811Smarc * In tandem mode, check high water mark. 7889578Ssam */ 78935811Smarc if (iflag&IXOFF) 79035811Smarc ttyblock(tp); 79135811Smarc if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 7929578Ssam c &= 0177; 7939578Ssam /* 7949578Ssam * Check for literal nexting very first 7959578Ssam */ 7969578Ssam if (tp->t_state&TS_LNCH) { 79735811Smarc c |= TTY_QUOTE; 7989578Ssam tp->t_state &= ~TS_LNCH; 7999578Ssam } 8009578Ssam /* 8019578Ssam * Scan for special characters. This code 8029578Ssam * is really just a big case statement with 8039578Ssam * non-constant cases. The bottom of the 8049578Ssam * case statement is labeled ``endcase'', so goto 8059578Ssam * it after a case match, or similar. 8069578Ssam */ 80735811Smarc /* 80835811Smarc * Control chars which aren't controlled 80935811Smarc * by ICANON, ISIG, or IXON. 81035811Smarc */ 81139407Smarc if (lflag&IEXTEN) { 812*40712Skarels if (CCEQ(cc[VLNEXT], c)) { 81335811Smarc if (lflag&ECHO) { 81435811Smarc if (lflag&ECHOE) 815*40712Skarels ttyoutstr("^\b", tp); 81635811Smarc else 81735811Smarc ttyecho(c, tp); 81835811Smarc } 8199578Ssam tp->t_state |= TS_LNCH; 8209578Ssam goto endcase; 8219578Ssam } 822*40712Skarels if (CCEQ(cc[VFLUSHO], c)) { 82335811Smarc if (lflag&FLUSHO) 82435811Smarc tp->t_lflag &= ~FLUSHO; 8257502Sroot else { 82612752Ssam ttyflush(tp, FWRITE); 8277502Sroot ttyecho(c, tp); 8289578Ssam if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 8297502Sroot ttyretype(tp); 83035811Smarc tp->t_lflag |= FLUSHO; 8317502Sroot } 8329578Ssam goto startoutput; 8339578Ssam } 83435811Smarc } 83535811Smarc /* 83635811Smarc * Signals. 83735811Smarc */ 83835811Smarc if (lflag&ISIG) { 83935811Smarc if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 84035811Smarc if ((lflag&NOFLSH) == 0) 84135811Smarc ttyflush(tp, FREAD|FWRITE); 84235811Smarc ttyecho(c, tp); 84339555Smarc pgsignal(tp->t_pgrp, 844*40712Skarels CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT); 84535811Smarc goto endcase; 84635811Smarc } 847*40712Skarels if (CCEQ(cc[VSUSP], c)) { 84835811Smarc if ((lflag&NOFLSH) == 0) 84912752Ssam ttyflush(tp, FREAD); 8509578Ssam ttyecho(c, tp); 85139555Smarc pgsignal(tp->t_pgrp, SIGTSTP); 8529578Ssam goto endcase; 8539578Ssam } 854*40712Skarels if (CCEQ(cc[VINFO], c)) { 855*40712Skarels pgsignal(tp->t_pgrp, SIGINFO); 856*40712Skarels if ((lflag&NOKERNINFO) == 0) 857*40712Skarels ttyinfo(tp); 85839407Smarc goto endcase; 85939407Smarc } 8609578Ssam } 8619578Ssam /* 8629578Ssam * Handle start/stop characters. 8639578Ssam */ 86435811Smarc if (iflag&IXON) { 865*40712Skarels if (CCEQ(cc[VSTOP], c)) { 86635811Smarc if ((tp->t_state&TS_TTSTOP) == 0) { 86735811Smarc tp->t_state |= TS_TTSTOP; 86835811Smarc (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 86935811Smarc return; 87035811Smarc } 87135811Smarc if (!CCEQ(cc[VSTART], c)) 87235811Smarc return; 87335811Smarc /* 87435811Smarc * if VSTART == VSTOP then toggle 87535811Smarc */ 87635811Smarc goto endcase; 8779578Ssam } 87835811Smarc if (CCEQ(cc[VSTART], c)) 87935811Smarc goto restartoutput; 8809578Ssam } 8819578Ssam /* 88235811Smarc * IGNCR, ICRNL, & INLCR 8839578Ssam */ 88435811Smarc if (c == '\r') { 88535811Smarc if (iflag&IGNCR) 88635811Smarc goto endcase; 88735811Smarc else if (iflag&ICRNL) 88835811Smarc c = '\n'; 8899578Ssam } 89035811Smarc else if (c == '\n' && iflag&INLCR) 89135811Smarc c = '\r'; 8929578Ssam /* 89335811Smarc * Non canonical mode; don't process line editing 8949578Ssam * characters; check high water mark for wakeup. 89535811Smarc * 8969578Ssam */ 897*40712Skarels if ((lflag&ICANON) == 0) { 8989578Ssam if (tp->t_rawq.c_cc > TTYHOG) { 89935811Smarc if (iflag&IMAXBEL) { 90035811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 90135811Smarc (void) ttyoutput(CTRL('g'), tp); 90235811Smarc } else 90335811Smarc ttyflush(tp, FREAD | FWRITE); 90435811Smarc } else { 90535811Smarc if (putc(c, &tp->t_rawq) >= 0) { 90635811Smarc ttwakeup(tp); 90735811Smarc ttyecho(c, tp); 90835811Smarc } 9097502Sroot } 9109578Ssam goto endcase; 9119578Ssam } 9129578Ssam /* 91335811Smarc * From here on down canonical mode character 9149578Ssam * processing takes place. 9159578Ssam */ 91635811Smarc /* 91735811Smarc * erase (^H / ^?) 91835811Smarc */ 91939407Smarc if (CCEQ(cc[VERASE], c)) { 9209578Ssam if (tp->t_rawq.c_cc) 9219578Ssam ttyrub(unputc(&tp->t_rawq), tp); 9229578Ssam goto endcase; 9239578Ssam } 92435811Smarc /* 92535811Smarc * kill (^U) 92635811Smarc */ 92735811Smarc if (CCEQ(cc[VKILL], c)) { 92837584Smarc if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 929*40712Skarels (lflag&ECHOPRT) == 0) { 9309578Ssam while (tp->t_rawq.c_cc) 9319578Ssam ttyrub(unputc(&tp->t_rawq), tp); 9329578Ssam } else { 9339578Ssam ttyecho(c, tp); 93435811Smarc if (lflag&ECHOK || lflag&ECHOKE) 93535811Smarc ttyecho('\n', tp); 9369578Ssam while (getc(&tp->t_rawq) > 0) 9379578Ssam ; 9389578Ssam tp->t_rocount = 0; 9399578Ssam } 9409578Ssam tp->t_state &= ~TS_LOCAL; 9419578Ssam goto endcase; 9429578Ssam } 9439578Ssam /* 94435811Smarc * word erase (^W) 9459578Ssam */ 94635811Smarc if (CCEQ(cc[VWERASE], c)) { 94735811Smarc int ctype; 94835811Smarc 94935811Smarc #define CTYPE(c) ((lflag&ALTWERASE) ? (partab[(c)&TTY_CHARMASK]&0100) : 0) 95035811Smarc /* 95135811Smarc * erase whitespace 95235811Smarc */ 95335811Smarc while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 95435811Smarc ttyrub(c, tp); 95535811Smarc if (c == -1) 95634492Skarels goto endcase; 95735811Smarc /* 95835811Smarc * special case last char of token 95935811Smarc */ 96035811Smarc ttyrub(c, tp); 96135811Smarc c = unputc(&tp->t_rawq); 96235811Smarc if (c == -1 || c == ' ' || c == '\t') { 96335811Smarc if (c != -1) 96435811Smarc (void) putc(c, &tp->t_rawq); 96534492Skarels goto endcase; 96634492Skarels } 96735811Smarc /* 96835811Smarc * erase rest of token 96935811Smarc */ 97035811Smarc ctype = CTYPE(c); 97135811Smarc do { 97235811Smarc ttyrub(c, tp); 97335811Smarc c = unputc(&tp->t_rawq); 97435811Smarc if (c == -1) 97535811Smarc goto endcase; 97635811Smarc } while (c != ' ' && c != '\t' && CTYPE(c) == ctype); 97735811Smarc (void) putc(c, &tp->t_rawq); 97835811Smarc goto endcase; 97935811Smarc #undef CTYPE 9809578Ssam } 9819578Ssam /* 98235811Smarc * reprint line (^R) 98335811Smarc */ 98435811Smarc if (CCEQ(cc[VREPRINT], c)) { 98535811Smarc ttyretype(tp); 98635811Smarc goto endcase; 98735811Smarc } 98835811Smarc /* 9899578Ssam * Check for input buffer overflow 9909578Ssam */ 99110391Ssam if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 99235811Smarc if (iflag&IMAXBEL) { 99335811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 99435811Smarc (void) ttyoutput(CTRL('g'), tp); 99535811Smarc } else 99635811Smarc ttyflush(tp, FREAD | FWRITE); 9979578Ssam goto endcase; 99810391Ssam } 9999578Ssam /* 10009578Ssam * Put data char in q for user and 10019578Ssam * wakeup on seeing a line delimiter. 10029578Ssam */ 10039578Ssam if (putc(c, &tp->t_rawq) >= 0) { 100435811Smarc if (ttbreakc(c)) { 10059578Ssam tp->t_rocount = 0; 10069578Ssam catq(&tp->t_rawq, &tp->t_canq); 10077502Sroot ttwakeup(tp); 10089578Ssam } else if (tp->t_rocount++ == 0) 10099578Ssam tp->t_rocol = tp->t_col; 10109578Ssam if (tp->t_state&TS_ERASE) { 101135811Smarc /* 101235811Smarc * end of prterase \.../ 101335811Smarc */ 10149578Ssam tp->t_state &= ~TS_ERASE; 10159578Ssam (void) ttyoutput('/', tp); 10169578Ssam } 10179578Ssam i = tp->t_col; 10187502Sroot ttyecho(c, tp); 101935811Smarc if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 102035811Smarc /* 102135811Smarc * Place the cursor over the '^' of the ^D. 102235811Smarc */ 10239578Ssam i = MIN(2, tp->t_col - i); 10249578Ssam while (i > 0) { 10259578Ssam (void) ttyoutput('\b', tp); 10269578Ssam i--; 10279578Ssam } 10289578Ssam } 10297502Sroot } 10309578Ssam endcase: 10319578Ssam /* 103235811Smarc * IXANY means allow any character to restart output. 10339578Ssam */ 1034*40712Skarels if ((tp->t_state&TS_TTSTOP) && (iflag&IXANY) == 0 && 1035*40712Skarels cc[VSTART] != cc[VSTOP]) 10367502Sroot return; 10379578Ssam restartoutput: 10387502Sroot tp->t_state &= ~TS_TTSTOP; 103935811Smarc tp->t_lflag &= ~FLUSHO; 10409578Ssam startoutput: 10417502Sroot ttstart(tp); 10427502Sroot } 10437502Sroot 10447502Sroot /* 10459578Ssam * Put character on TTY output queue, adding delays, 10467502Sroot * expanding tabs, and handling the CR/NL bit. 10479578Ssam * This is called both from the top half for output, 10489578Ssam * and from interrupt level for echoing. 10497502Sroot * The arguments are the character and the tty structure. 10507502Sroot * Returns < 0 if putc succeeds, otherwise returns char to resend 10517502Sroot * Must be recursive. 10527502Sroot */ 10537502Sroot ttyoutput(c, tp) 10547502Sroot register c; 10557502Sroot register struct tty *tp; 10567502Sroot { 10577502Sroot register char *colp; 10587502Sroot register ctype; 105935811Smarc register long oflag = tp->t_oflag; 106035811Smarc 1061*40712Skarels if ((oflag&OPOST) == 0) { 106235811Smarc if (tp->t_lflag&FLUSHO) 10637502Sroot return (-1); 10647502Sroot if (putc(c, &tp->t_outq)) 10657625Ssam return (c); 10667502Sroot tk_nout++; 106735811Smarc tp->t_outcc++; 10687502Sroot return (-1); 10697502Sroot } 107035811Smarc c &= TTY_CHARMASK; 10717502Sroot /* 10727502Sroot * Turn tabs to spaces as required 10737502Sroot */ 107435811Smarc if (c == '\t' && oflag&OXTABS ) { 10757502Sroot register int s; 10767502Sroot 10777502Sroot c = 8 - (tp->t_col&7); 107835811Smarc if ((tp->t_lflag&FLUSHO) == 0) { 107917545Skarels s = spltty(); /* don't interrupt tabs */ 10807502Sroot c -= b_to_q(" ", c, &tp->t_outq); 10817502Sroot tk_nout += c; 108235811Smarc tp->t_outcc += c; 10837502Sroot splx(s); 10847502Sroot } 10857502Sroot tp->t_col += c; 10867502Sroot return (c ? -1 : '\t'); 10877502Sroot } 108835811Smarc if (c == CEOT && oflag&ONOEOT) 108935811Smarc return(-1); 10907502Sroot tk_nout++; 109135811Smarc tp->t_outcc++; 10927502Sroot /* 10937502Sroot * turn <nl> to <cr><lf> if desired. 10947502Sroot */ 109535811Smarc if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 10967502Sroot return (c); 109735811Smarc if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 109835811Smarc return (c); 10997502Sroot /* 11007502Sroot * Calculate delays. 11017502Sroot * The numbers here represent clock ticks 11027502Sroot * and are not necessarily optimal for all terminals. 11039578Ssam * 11049578Ssam * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 110535811Smarc * 110635811Smarc * (actually, should THROW AWAY terminals which need delays) 11077502Sroot */ 11087502Sroot colp = &tp->t_col; 11097502Sroot ctype = partab[c]; 11107502Sroot c = 0; 11117502Sroot switch (ctype&077) { 11127502Sroot 11137502Sroot case ORDINARY: 11147502Sroot (*colp)++; 11157502Sroot 11167502Sroot case CONTROL: 11177502Sroot break; 11187502Sroot 11197502Sroot case BACKSPACE: 11207502Sroot if (*colp) 11217502Sroot (*colp)--; 11227502Sroot break; 11237502Sroot 112413821Ssam /* 112513821Ssam * This macro is close enough to the correct thing; 112613821Ssam * it should be replaced by real user settable delays 112713821Ssam * in any event... 112813821Ssam */ 112913821Ssam #define mstohz(ms) (((ms) * hz) >> 10) 11307502Sroot case NEWLINE: 11317502Sroot ctype = (tp->t_flags >> 8) & 03; 11327625Ssam if (ctype == 1) { /* tty 37 */ 113326357Skarels if (*colp > 0) { 113426357Skarels c = (((unsigned)*colp) >> 4) + 3; 113526357Skarels if ((unsigned)c > 6) 113626357Skarels c = 6; 113726357Skarels } 11389578Ssam } else if (ctype == 2) /* vt05 */ 113913821Ssam c = mstohz(100); 11407502Sroot *colp = 0; 11417502Sroot break; 11427502Sroot 11437502Sroot case TAB: 11447502Sroot ctype = (tp->t_flags >> 10) & 03; 11457625Ssam if (ctype == 1) { /* tty 37 */ 11467502Sroot c = 1 - (*colp | ~07); 11477625Ssam if (c < 5) 11487502Sroot c = 0; 11497502Sroot } 11507502Sroot *colp |= 07; 11517502Sroot (*colp)++; 11527502Sroot break; 11537502Sroot 11547502Sroot case VTAB: 11559578Ssam if (tp->t_flags&VTDELAY) /* tty 37 */ 11567502Sroot c = 0177; 11577502Sroot break; 11587502Sroot 11597502Sroot case RETURN: 11607502Sroot ctype = (tp->t_flags >> 12) & 03; 11619578Ssam if (ctype == 1) /* tn 300 */ 116213821Ssam c = mstohz(83); 11639578Ssam else if (ctype == 2) /* ti 700 */ 116413821Ssam c = mstohz(166); 11659578Ssam else if (ctype == 3) { /* concept 100 */ 11667502Sroot int i; 11679578Ssam 11687502Sroot if ((i = *colp) >= 0) 11699578Ssam for (; i < 9; i++) 11707502Sroot (void) putc(0177, &tp->t_outq); 11717502Sroot } 11727502Sroot *colp = 0; 11737502Sroot } 117435811Smarc if (c && (tp->t_lflag&FLUSHO) == 0) 117535811Smarc (void) putc(c|TTY_QUOTE, &tp->t_outq); 11767502Sroot return (-1); 11777502Sroot } 117813821Ssam #undef mstohz 11797502Sroot 11807502Sroot /* 11817502Sroot * Called from device's read routine after it has 11827502Sroot * calculated the tty-structure given as argument. 11837502Sroot */ 118437584Smarc ttread(tp, uio, flag) 11857625Ssam register struct tty *tp; 11867722Swnj struct uio *uio; 11877502Sroot { 11887502Sroot register struct clist *qp; 118935811Smarc register int c; 119035811Smarc register long lflag = tp->t_lflag; 119135811Smarc register u_char *cc = tp->t_cc; 11929859Ssam int s, first, error = 0; 11937502Sroot 11947502Sroot loop: 119537584Smarc s = spltty(); 11969578Ssam /* 119737584Smarc * take pending input first 11989578Ssam */ 119935811Smarc if (lflag&PENDIN) 12007502Sroot ttypend(tp); 12019859Ssam splx(s); 1202*40712Skarels 12039578Ssam /* 12049578Ssam * Hang process if it's in the background. 12059578Ssam */ 120639555Smarc if (isbackground(u.u_procp, tp)) { 120724392Skarels if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 120824392Skarels (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 120935811Smarc u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0) 12108520Sroot return (EIO); 121135811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN); 1212*40712Skarels if (error = tsleep((caddr_t)&lbolt, TTIPRI | PCATCH, ttybg, 0)) 1213*40712Skarels return (error); 121423165Sbloom goto loop; 12157502Sroot } 1216*40712Skarels 12179578Ssam /* 121835811Smarc * If canonical, use the canonical queue, 121935811Smarc * else use the raw queue. 122037584Smarc * 122137584Smarc * XXX - should get rid of canonical queue. 122237584Smarc * (actually, should get rid of clists...) 12239578Ssam */ 122435811Smarc qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 1225*40712Skarels 12269578Ssam /* 1227*40712Skarels * If there is no input, sleep on rawq 1228*40712Skarels * awaiting hardware receipt and notification. 1229*40712Skarels * If we have data, we don't need to check for carrier. 12309578Ssam */ 123117545Skarels s = spltty(); 12329578Ssam if (qp->c_cc <= 0) { 1233*40712Skarels int carrier; 1234*40712Skarels 1235*40712Skarels carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL); 1236*40712Skarels if (!carrier && tp->t_state&TS_ISOPEN) { 12379859Ssam splx(s); 1238*40712Skarels return (0); /* EOF */ 12397502Sroot } 124037728Smckusick if (flag & IO_NDELAY) { 124137584Smarc splx(s); 124237584Smarc return (EWOULDBLOCK); 124337584Smarc } 1244*40712Skarels error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 1245*40712Skarels carrier ? ttyin : ttopen, 0); 12469859Ssam splx(s); 1247*40712Skarels if (error) 1248*40712Skarels return (error); 12499578Ssam goto loop; 12509578Ssam } 12519859Ssam splx(s); 1252*40712Skarels 12539578Ssam /* 125435811Smarc * Input present, check for input mapping and processing. 12559578Ssam */ 12569578Ssam first = 1; 12579578Ssam while ((c = getc(qp)) >= 0) { 12589578Ssam /* 125935811Smarc * delayed suspend (^Y) 12609578Ssam */ 126135811Smarc if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 126239555Smarc pgsignal(tp->t_pgrp, SIGTSTP); 12639578Ssam if (first) { 1264*40712Skarels if (error = tsleep((caddr_t)&lbolt, 1265*40712Skarels TTIPRI | PCATCH, ttybg, 0)) 1266*40712Skarels break; 12679578Ssam goto loop; 12689578Ssam } 12699578Ssam break; 12707502Sroot } 12719578Ssam /* 127235811Smarc * Interpret EOF only in canonical mode. 12739578Ssam */ 127435811Smarc if (CCEQ(cc[VEOF], c) && lflag&ICANON) 12759578Ssam break; 12769578Ssam /* 12779578Ssam * Give user character. 12789578Ssam */ 1279*40712Skarels error = ureadc(c, uio); 12809578Ssam if (error) 12819578Ssam break; 128214938Smckusick if (uio->uio_resid == 0) 12839578Ssam break; 12849578Ssam /* 128535811Smarc * In canonical mode check for a "break character" 12869578Ssam * marking the end of a "line of input". 12879578Ssam */ 1288*40712Skarels if (lflag&ICANON && ttbreakc(c)) 12899578Ssam break; 12909578Ssam first = 0; 12917502Sroot } 12929578Ssam /* 12939578Ssam * Look to unblock output now that (presumably) 12949578Ssam * the input queue has gone down. 12959578Ssam */ 129635811Smarc if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 129735811Smarc if (cc[VSTART] != _POSIX_VDISABLE 129835811Smarc && putc(cc[VSTART], &tp->t_outq) == 0) { 12997502Sroot tp->t_state &= ~TS_TBLOCK; 13007502Sroot ttstart(tp); 13017502Sroot } 130235811Smarc } 13038520Sroot return (error); 13047502Sroot } 13057502Sroot 13067502Sroot /* 130725391Skarels * Check the output queue on tp for space for a kernel message 130825391Skarels * (from uprintf/tprintf). Allow some space over the normal 130925391Skarels * hiwater mark so we don't lose messages due to normal flow 131025391Skarels * control, but don't let the tty run amok. 131130695Skarels * Sleeps here are not interruptible, but we return prematurely 131230695Skarels * if new signals come in. 131325391Skarels */ 131425391Skarels ttycheckoutq(tp, wait) 131525391Skarels register struct tty *tp; 131625391Skarels int wait; 131725391Skarels { 131830695Skarels int hiwat, s, oldsig; 131925391Skarels 132035811Smarc hiwat = tp->t_hiwat; 132125391Skarels s = spltty(); 132230695Skarels oldsig = u.u_procp->p_sig; 132325391Skarels if (tp->t_outq.c_cc > hiwat + 200) 132429946Skarels while (tp->t_outq.c_cc > hiwat) { 132529946Skarels ttstart(tp); 132630695Skarels if (wait == 0 || u.u_procp->p_sig != oldsig) { 132729946Skarels splx(s); 132829946Skarels return (0); 132929946Skarels } 133030695Skarels timeout(wakeup, (caddr_t)&tp->t_outq, hz); 133129946Skarels tp->t_state |= TS_ASLEEP; 133230695Skarels sleep((caddr_t)&tp->t_outq, PZERO - 1); 133325391Skarels } 133425391Skarels splx(s); 133525391Skarels return (1); 133625391Skarels } 133725391Skarels 133825391Skarels /* 13397502Sroot * Called from the device's write routine after it has 13407502Sroot * calculated the tty-structure given as argument. 13417502Sroot */ 134237584Smarc ttwrite(tp, uio, flag) 13437625Ssam register struct tty *tp; 13449578Ssam register struct uio *uio; 13457502Sroot { 13467502Sroot register char *cp; 1347*40712Skarels register int cc = 0, ce; 13489578Ssam int i, hiwat, cnt, error, s; 13497502Sroot char obuf[OBUFSIZ]; 13507502Sroot 135135811Smarc hiwat = tp->t_hiwat; 13529578Ssam cnt = uio->uio_resid; 13539578Ssam error = 0; 13547502Sroot loop: 135537584Smarc s = spltty(); 1356*40712Skarels if ((tp->t_state&TS_CARR_ON) == 0 && (tp->t_cflag&CLOCAL) == 0) { 135737584Smarc if (tp->t_state&TS_ISOPEN) { 135837584Smarc splx(s); 135937584Smarc return (EIO); 136037728Smckusick } else if (flag & IO_NDELAY) { 136137584Smarc splx(s); 1362*40712Skarels error = EWOULDBLOCK; 1363*40712Skarels goto out; 136437584Smarc } else { 136537584Smarc /* 136637584Smarc * sleep awaiting carrier 136737584Smarc */ 1368*40712Skarels error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 1369*40712Skarels ttopen, 0); 137037584Smarc splx(s); 1371*40712Skarels if (error) 1372*40712Skarels goto out; 137337584Smarc goto loop; 137437584Smarc } 137537584Smarc } 137637584Smarc splx(s); 13779578Ssam /* 13789578Ssam * Hang the process if it's in the background. 13799578Ssam */ 138039555Smarc if (isbackground(u.u_procp, tp) && 138135811Smarc (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1382*40712Skarels (u.u_procp->p_sigignore & sigmask(SIGTTOU)) == 0 && 1383*40712Skarels (u.u_procp->p_sigmask & sigmask(SIGTTOU)) == 0 && 138435811Smarc u.u_procp->p_pgrp->pg_jobc) { 138535811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU); 1386*40712Skarels if (error = tsleep((caddr_t)&lbolt, TTIPRI | PCATCH, ttybg, 0)) 1387*40712Skarels goto out; 138821776Sbloom goto loop; 13897502Sroot } 13909578Ssam /* 13919578Ssam * Process the user's data in at most OBUFSIZ 1392*40712Skarels * chunks. Perform any output translation. 1393*40712Skarels * Keep track of high water mark, sleep on overflow 1394*40712Skarels * awaiting device aid in acquiring new space. 13959578Ssam */ 1396*40712Skarels while (uio->uio_resid > 0 || cc > 0) { 1397*40712Skarels if (tp->t_lflag&FLUSHO) { 1398*40712Skarels uio->uio_resid = 0; 1399*40712Skarels return (0); 1400*40712Skarels } 1401*40712Skarels if (tp->t_outq.c_cc > hiwat) 140232067Skarels goto ovhiwat; 14039578Ssam /* 1404*40712Skarels * Grab a hunk of data from the user, 1405*40712Skarels * unless we have some leftover from last time. 14069578Ssam */ 14077822Sroot if (cc == 0) { 1408*40712Skarels cc = min(uio->uio_resid, OBUFSIZ); 1409*40712Skarels cp = obuf; 1410*40712Skarels error = uiomove(cp, cc, uio); 1411*40712Skarels if (error) { 1412*40712Skarels cc = 0; 1413*40712Skarels break; 1414*40712Skarels } 14157822Sroot } 14169578Ssam /* 14179578Ssam * If nothing fancy need be done, grab those characters we 14189578Ssam * can handle without any of ttyoutput's processing and 14199578Ssam * just transfer them to the output q. For those chars 14209578Ssam * which require special processing (as indicated by the 14219578Ssam * bits in partab), call ttyoutput. After processing 14229578Ssam * a hunk of data, look for FLUSHO so ^O's will take effect 14239578Ssam * immediately. 14249578Ssam */ 14259578Ssam while (cc > 0) { 1426*40712Skarels if ((tp->t_oflag&OPOST) == 0) 14277502Sroot ce = cc; 14287502Sroot else { 142934492Skarels ce = cc - scanc((unsigned)cc, (u_char *)cp, 143034492Skarels (u_char *)partab, 077); 14319578Ssam /* 14329578Ssam * If ce is zero, then we're processing 14339578Ssam * a special character through ttyoutput. 14349578Ssam */ 14359578Ssam if (ce == 0) { 14367502Sroot tp->t_rocount = 0; 14377502Sroot if (ttyoutput(*cp, tp) >= 0) { 143821776Sbloom /* no c-lists, wait a bit */ 143921776Sbloom ttstart(tp); 1440*40712Skarels if (error = tsleep((caddr_t)&lbolt, 1441*40712Skarels TTOPRI | PCATCH, ttybuf, 0)) 1442*40712Skarels break; 144321776Sbloom goto loop; 14447502Sroot } 14459578Ssam cp++, cc--; 144635811Smarc if ((tp->t_lflag&FLUSHO) || 14479578Ssam tp->t_outq.c_cc > hiwat) 14487502Sroot goto ovhiwat; 14499578Ssam continue; 14507502Sroot } 14517502Sroot } 14529578Ssam /* 14539578Ssam * A bunch of normal characters have been found, 14549578Ssam * transfer them en masse to the output queue and 14559578Ssam * continue processing at the top of the loop. 14569578Ssam * If there are any further characters in this 14579578Ssam * <= OBUFSIZ chunk, the first should be a character 14589578Ssam * requiring special handling by ttyoutput. 14599578Ssam */ 14607502Sroot tp->t_rocount = 0; 14619578Ssam i = b_to_q(cp, ce, &tp->t_outq); 14629578Ssam ce -= i; 14639578Ssam tp->t_col += ce; 14649578Ssam cp += ce, cc -= ce, tk_nout += ce; 146535811Smarc tp->t_outcc += ce; 14669578Ssam if (i > 0) { 14679578Ssam /* out of c-lists, wait a bit */ 14687502Sroot ttstart(tp); 1469*40712Skarels if (error = tsleep((caddr_t)&lbolt, 1470*40712Skarels TTOPRI | PCATCH, ttybuf, 0)) 1471*40712Skarels break; 147221776Sbloom goto loop; 14737502Sroot } 147435811Smarc if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 1475*40712Skarels break; 14767502Sroot } 147735811Smarc ttstart(tp); 14787502Sroot } 1479*40712Skarels out: 1480*40712Skarels /* 1481*40712Skarels * If cc is nonzero, we leave the uio structure inconsistent, 1482*40712Skarels * as the offset and iov pointers have moved forward, 1483*40712Skarels * but it doesn't matter (the call will either return short 1484*40712Skarels * or restart with a new uio). 1485*40712Skarels */ 1486*40712Skarels uio->uio_resid += cc; 14878520Sroot return (error); 1488*40712Skarels 14897502Sroot ovhiwat: 149032067Skarels ttstart(tp); 149132067Skarels s = spltty(); 14929578Ssam /* 149335811Smarc * This can only occur if FLUSHO is set in t_lflag, 149432067Skarels * or if ttstart/oproc is synchronous (or very fast). 14959578Ssam */ 14967502Sroot if (tp->t_outq.c_cc <= hiwat) { 14979578Ssam splx(s); 14987502Sroot goto loop; 14997502Sroot } 150037728Smckusick if (flag & IO_NDELAY) { 150117545Skarels splx(s); 1502*40712Skarels uio->uio_resid += cc; 15037822Sroot if (uio->uio_resid == cnt) 15048520Sroot return (EWOULDBLOCK); 15058520Sroot return (0); 15067502Sroot } 15077502Sroot tp->t_state |= TS_ASLEEP; 1508*40712Skarels error = tsleep((caddr_t)&tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 15099578Ssam splx(s); 1510*40712Skarels if (error) 1511*40712Skarels goto out; 15127502Sroot goto loop; 15137502Sroot } 15147502Sroot 15157502Sroot /* 15167502Sroot * Rubout one character from the rawq of tp 15177502Sroot * as cleanly as possible. 15187502Sroot */ 15197502Sroot ttyrub(c, tp) 15207625Ssam register c; 15217625Ssam register struct tty *tp; 15227502Sroot { 15237502Sroot register char *cp; 15247502Sroot register int savecol; 15257502Sroot int s; 15267502Sroot char *nextc(); 15277502Sroot 152835811Smarc if ((tp->t_lflag&ECHO) == 0) 15297502Sroot return; 153035811Smarc tp->t_lflag &= ~FLUSHO; 153135811Smarc if (tp->t_lflag&ECHOE) { 15327502Sroot if (tp->t_rocount == 0) { 15337502Sroot /* 15347502Sroot * Screwed by ttwrite; retype 15357502Sroot */ 15367502Sroot ttyretype(tp); 15377502Sroot return; 15387502Sroot } 153935811Smarc if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 15407502Sroot ttyrubo(tp, 2); 154135811Smarc else switch (partab[c&=0377]&077) { 15427502Sroot 15437502Sroot case ORDINARY: 154435811Smarc ttyrubo(tp, 1); 15457502Sroot break; 15467502Sroot 15477502Sroot case VTAB: 15487502Sroot case BACKSPACE: 15497502Sroot case CONTROL: 15507502Sroot case RETURN: 155135811Smarc if (tp->t_lflag&ECHOCTL) 15527502Sroot ttyrubo(tp, 2); 15537502Sroot break; 15547502Sroot 155535811Smarc case TAB: { 155635811Smarc int c; 155735811Smarc 15587502Sroot if (tp->t_rocount < tp->t_rawq.c_cc) { 15597502Sroot ttyretype(tp); 15607502Sroot return; 15617502Sroot } 156217545Skarels s = spltty(); 15637502Sroot savecol = tp->t_col; 15649578Ssam tp->t_state |= TS_CNTTB; 156535811Smarc tp->t_lflag |= FLUSHO; 15667502Sroot tp->t_col = tp->t_rocol; 15679578Ssam cp = tp->t_rawq.c_cf; 156839407Smarc if (cp) 156939407Smarc c = *cp; /* XXX FIX NEXTC */ 157035811Smarc for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 157135811Smarc ttyecho(c, tp); 157235811Smarc tp->t_lflag &= ~FLUSHO; 15739578Ssam tp->t_state &= ~TS_CNTTB; 15747502Sroot splx(s); 15757502Sroot /* 15767502Sroot * savecol will now be length of the tab 15777502Sroot */ 15787502Sroot savecol -= tp->t_col; 15797502Sroot tp->t_col += savecol; 15807502Sroot if (savecol > 8) 15817502Sroot savecol = 8; /* overflow screw */ 15827502Sroot while (--savecol >= 0) 15837502Sroot (void) ttyoutput('\b', tp); 15847502Sroot break; 158535811Smarc } 15867502Sroot 15877502Sroot default: 158837584Smarc /* XXX */ 158935811Smarc printf("ttyrub: would panic c = %d, val = %d\n", 159035811Smarc c, partab[c&=0377]&077); 159135811Smarc /*panic("ttyrub");*/ 15927502Sroot } 159335811Smarc } else if (tp->t_lflag&ECHOPRT) { 15949578Ssam if ((tp->t_state&TS_ERASE) == 0) { 15957502Sroot (void) ttyoutput('\\', tp); 15969578Ssam tp->t_state |= TS_ERASE; 15977502Sroot } 15987502Sroot ttyecho(c, tp); 15997502Sroot } else 160035811Smarc ttyecho(tp->t_cc[VERASE], tp); 16017502Sroot tp->t_rocount--; 16027502Sroot } 16037502Sroot 16047502Sroot /* 16057502Sroot * Crt back over cnt chars perhaps 16067502Sroot * erasing them. 16077502Sroot */ 16087502Sroot ttyrubo(tp, cnt) 16097625Ssam register struct tty *tp; 16107625Ssam int cnt; 16117502Sroot { 16127502Sroot 16137502Sroot while (--cnt >= 0) 1614*40712Skarels ttyoutstr("\b \b", tp); 16157502Sroot } 16167502Sroot 16177502Sroot /* 16187502Sroot * Reprint the rawq line. 16197502Sroot * We assume c_cc has already been checked. 16207502Sroot */ 16217502Sroot ttyretype(tp) 16227625Ssam register struct tty *tp; 16237502Sroot { 16247502Sroot register char *cp; 16257502Sroot char *nextc(); 162635811Smarc int s, c; 16277502Sroot 162835811Smarc if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 162935811Smarc ttyecho(tp->t_cc[VREPRINT], tp); 16307502Sroot (void) ttyoutput('\n', tp); 163117545Skarels s = spltty(); 163235811Smarc /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 163335811Smarc BIT OF FIRST CHAR ****/ 163435811Smarc for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 163535811Smarc ttyecho(c, tp); 163635811Smarc } 163735811Smarc for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 163835811Smarc ttyecho(c, tp); 163935811Smarc } 16409578Ssam tp->t_state &= ~TS_ERASE; 16417502Sroot splx(s); 16427502Sroot tp->t_rocount = tp->t_rawq.c_cc; 16437502Sroot tp->t_rocol = 0; 16447502Sroot } 16457502Sroot 16467502Sroot /* 164735811Smarc * Echo a typed character to the terminal. 16487502Sroot */ 16497502Sroot ttyecho(c, tp) 16507625Ssam register c; 16517625Ssam register struct tty *tp; 16527502Sroot { 16539578Ssam if ((tp->t_state&TS_CNTTB) == 0) 165435811Smarc tp->t_lflag &= ~FLUSHO; 1655*40712Skarels if ((tp->t_lflag&ECHO) == 0 && ((tp->t_lflag&ECHONL) == 0 || c == '\n')) 16567502Sroot return; 165735811Smarc if (tp->t_lflag&ECHOCTL) { 1658*40712Skarels if ((c&TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' || 1659*40712Skarels c == 0177) { 16607502Sroot (void) ttyoutput('^', tp); 166135811Smarc c &= TTY_CHARMASK; 16627502Sroot if (c == 0177) 16637502Sroot c = '?'; 16647502Sroot else 16657502Sroot c += 'A' - 1; 16667502Sroot } 16677502Sroot } 166835811Smarc (void) ttyoutput(c, tp); 16697502Sroot } 16707502Sroot 16717502Sroot /* 16727502Sroot * send string cp to tp 16737502Sroot */ 1674*40712Skarels ttyoutstr(cp, tp) 16757625Ssam register char *cp; 16767625Ssam register struct tty *tp; 16777502Sroot { 16787502Sroot register char c; 16797502Sroot 16807502Sroot while (c = *cp++) 16817502Sroot (void) ttyoutput(c, tp); 16827502Sroot } 16837502Sroot 16847502Sroot ttwakeup(tp) 16857502Sroot struct tty *tp; 16867502Sroot { 16877502Sroot 16887502Sroot if (tp->t_rsel) { 16897502Sroot selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 16907502Sroot tp->t_state &= ~TS_RCOLL; 16917502Sroot tp->t_rsel = 0; 16927502Sroot } 169312752Ssam if (tp->t_state & TS_ASYNC) 169439555Smarc pgsignal(tp->t_pgrp, SIGIO); 16957502Sroot wakeup((caddr_t)&tp->t_rawq); 16967502Sroot } 169735811Smarc 169835811Smarc /* 169935811Smarc * set tty hi and low water marks 170035811Smarc * 170135811Smarc * Try to arrange the dynamics so there's about one second 170235811Smarc * from hi to low water. 170335811Smarc * 170435811Smarc */ 170535811Smarc ttsetwater(tp) 170635811Smarc struct tty *tp; 170735811Smarc { 170835811Smarc register cps = tp->t_ospeed / 10; 170935811Smarc register x; 171035811Smarc 171135811Smarc #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 171235811Smarc tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 171335811Smarc x += cps; 171435811Smarc x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 171535811Smarc tp->t_hiwat = roundup(x, CBSIZE); 171635811Smarc #undef clamp 171735811Smarc } 171835811Smarc 171935811Smarc ttspeedtab(speed, table) 172035811Smarc struct speedtab table[]; 172135811Smarc { 172235811Smarc register int i; 172335811Smarc 172435811Smarc for (i = 0; table[i].sp_speed != -1; i++) 172535811Smarc if (table[i].sp_speed == speed) 172635811Smarc return(table[i].sp_code); 172735811Smarc return(-1); 172835811Smarc } 172939407Smarc 173039407Smarc /* 173139407Smarc * (^T) 173239407Smarc * Report on state of foreground process group. 173339407Smarc */ 173439407Smarc ttyinfo(tp) 173539407Smarc struct tty *tp; 173639407Smarc { 173739407Smarc register struct proc *p; 173839407Smarc 173939407Smarc if (ttycheckoutq(tp,0) == 0) 174039407Smarc return; 174139555Smarc if (tp->t_session == NULL) 174239555Smarc ttyprintf(tp, "kernel: not a controlling terminal\n"); 174339555Smarc else if (tp->t_pgrp == NULL || 174439555Smarc (p = tp->t_pgrp->pg_mem) == NULL) 174539407Smarc ttyprintf(tp, "kernel: no foreground process group\n"); 174639407Smarc else { 174739407Smarc int i = 0; 174839555Smarc 174939407Smarc for (; p != NULL; p = p->p_pgrpnxt) { 175039407Smarc ttyprintf(tp, 175139407Smarc "kernel: pid: %d state: %x wchan: %x ticks: %d\n", 175239407Smarc p->p_pid, p->p_stat, p->p_wchan, p->p_cpticks); 175339407Smarc if (++i > 6) { 175439407Smarc ttyprintf(tp, "kernel: more...\n"); 175539407Smarc break; 175639407Smarc } 175739407Smarc } 175839407Smarc } 175939407Smarc } 176039407Smarc 176139407Smarc #define TOTTY 0x2 /* XXX should be in header */ 176239407Smarc /*VARARGS2*/ 176339407Smarc ttyprintf(tp, fmt, x1) 176439555Smarc struct tty *tp; 176539407Smarc char *fmt; 176639407Smarc unsigned x1; 176739407Smarc { 176839555Smarc prf(fmt, &x1, TOTTY, (caddr_t)tp); 176939407Smarc } 177039555Smarc 177139555Smarc /* 177239555Smarc * Output char to tty; console putchar style. 177339555Smarc */ 177439555Smarc tputchar(c, tp) 177539555Smarc int c; 177639555Smarc struct tty *tp; 177739555Smarc { 177839555Smarc register s = spltty(); 177939555Smarc 178039555Smarc if ((tp->t_state & (TS_CARR_ON | TS_ISOPEN)) 178139555Smarc == (TS_CARR_ON | TS_ISOPEN)) { 178239555Smarc if (c == '\n') 178339555Smarc (void) ttyoutput('\r', tp); 178439555Smarc (void) ttyoutput(c, tp); 178539555Smarc ttstart(tp); 178639555Smarc splx(s); 178739555Smarc return (0); 178839555Smarc } 178939555Smarc splx(s); 179039555Smarc return (-1); 179139555Smarc } 1792