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*39407Smarc * @(#)tty.c 7.18 (Berkeley) 10/27/89 723387Smckusick */ 839Sbill 917095Sbloom #include "param.h" 1017095Sbloom #include "systm.h" 1117095Sbloom #include "user.h" 1217095Sbloom #include "ioctl.h" 13*39407Smarc #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: 231*39407Smarc /**** these get removed **** 23235811Smarc case TIOCSETAS: 23335811Smarc case TIOCSETAWS: 23435811Smarc case TIOCSETAFS: 235*39407Smarc /***************************/ 23635811Smarc while (u.u_procp->p_pgid != tp->t_pgid && 23735811Smarc tp == u.u_ttyp && 23835811Smarc u.u_procp->p_pgrp->pg_jobc && 239903Sbill (u.u_procp->p_flag&SVFORK) == 0 && 24024392Skarels !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 24124392Skarels !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 24235811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU); 243903Sbill sleep((caddr_t)&lbolt, TTOPRI); 244903Sbill } 245903Sbill break; 246903Sbill } 247903Sbill 2489578Ssam /* 2499578Ssam * Process the ioctl. 2509578Ssam */ 2517625Ssam switch (com) { 252903Sbill 2538556Sroot /* get discipline number */ 25439Sbill case TIOCGETD: 2557625Ssam *(int *)data = tp->t_line; 25639Sbill break; 25739Sbill 2588556Sroot /* set line discipline */ 2597625Ssam case TIOCSETD: { 2607625Ssam register int t = *(int *)data; 26135811Smarc dev_t dev = tp->t_dev; 2629578Ssam int error = 0; 2637625Ssam 26435811Smarc if ((unsigned)t >= nldisp) 26510851Ssam return (ENXIO); 26625584Skarels if (t != tp->t_line) { 26725584Skarels s = spltty(); 26825584Skarels (*linesw[tp->t_line].l_close)(tp); 26925584Skarels error = (*linesw[t].l_open)(dev, tp); 27025584Skarels if (error) { 27135811Smarc (void)(*linesw[tp->t_line].l_open)(dev, tp); 27225584Skarels splx(s); 27325584Skarels return (error); 27425584Skarels } 27525584Skarels tp->t_line = t; 27610851Ssam splx(s); 27710851Ssam } 27839Sbill break; 2797625Ssam } 28039Sbill 2818556Sroot /* prevent more opens on channel */ 2825614Swnj case TIOCEXCL: 2835614Swnj tp->t_state |= TS_XCLUDE; 2845614Swnj break; 2855614Swnj 2865614Swnj case TIOCNXCL: 2875614Swnj tp->t_state &= ~TS_XCLUDE; 2885614Swnj break; 2895614Swnj 29039Sbill case TIOCHPCL: 29135811Smarc tp->t_cflag |= HUPCL; 29239Sbill break; 29339Sbill 2943942Sbugs case TIOCFLUSH: { 2957625Ssam register int flags = *(int *)data; 2967625Ssam 2977625Ssam if (flags == 0) 2983942Sbugs flags = FREAD|FWRITE; 2997625Ssam else 3007625Ssam flags &= FREAD|FWRITE; 30112752Ssam ttyflush(tp, flags); 30239Sbill break; 3033944Sbugs } 30439Sbill 30537584Smarc case FIOASYNC: 30637584Smarc if (*(int *)data) 30737584Smarc tp->t_state |= TS_ASYNC; 30837584Smarc else 30937584Smarc tp->t_state &= ~TS_ASYNC; 31037584Smarc break; 31137584Smarc 31237584Smarc case FIONBIO: 31337584Smarc break; /* XXX remove */ 31437584Smarc 3158556Sroot /* return number of characters immediately available */ 3167625Ssam case FIONREAD: 3177625Ssam *(off_t *)data = ttnread(tp); 318174Sbill break; 319174Sbill 32013077Ssam case TIOCOUTQ: 32113077Ssam *(int *)data = tp->t_outq.c_cc; 32213077Ssam break; 32313077Ssam 3248589Sroot case TIOCSTOP: 32517545Skarels s = spltty(); 3269578Ssam if ((tp->t_state&TS_TTSTOP) == 0) { 3275573Swnj tp->t_state |= TS_TTSTOP; 3285573Swnj (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 3295573Swnj } 3307625Ssam splx(s); 3315573Swnj break; 3325573Swnj 3338589Sroot case TIOCSTART: 33417545Skarels s = spltty(); 33535811Smarc if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 3365573Swnj tp->t_state &= ~TS_TTSTOP; 33735811Smarc tp->t_lflag &= ~FLUSHO; 3385573Swnj ttstart(tp); 3395573Swnj } 3407625Ssam splx(s); 3415573Swnj break; 3425573Swnj 3439325Ssam /* 3449325Ssam * Simulate typing of a character at the terminal. 3459325Ssam */ 3469325Ssam case TIOCSTI: 34717183Smckusick if (u.u_uid && (flag & FREAD) == 0) 34817183Smckusick return (EPERM); 3499325Ssam if (u.u_uid && u.u_ttyp != tp) 3509325Ssam return (EACCES); 3519578Ssam (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 3529325Ssam break; 3539325Ssam 35435811Smarc case TIOCGETA: { 35535811Smarc struct termios *t = (struct termios *)data; 35612752Ssam 35735811Smarc bcopy(&tp->t_termios, t, sizeof(struct termios)); 35835811Smarc break; 35935811Smarc } 36035811Smarc 361*39407Smarc /*** THIS ALL GETS REMOVED ***/ 362*39407Smarc case JUNK_TIOCSETAS: 363*39407Smarc case JUNK_TIOCSETAWS: 364*39407Smarc case JUNK_TIOCSETAFS: 365*39407Smarc ((struct termios *)data)->c_cflag |= CIGNORE; 366*39407Smarc switch(com) { 367*39407Smarc case JUNK_TIOCSETAS: 368*39407Smarc com = TIOCSETA; 369*39407Smarc break; 370*39407Smarc case JUNK_TIOCSETAWS: 371*39407Smarc com = TIOCSETAW; 372*39407Smarc break; 373*39407Smarc case JUNK_TIOCSETAFS: 374*39407Smarc com = TIOCSETAF; 375*39407Smarc break; 376*39407Smarc } 377*39407Smarc /*******************************/ 378*39407Smarc /*FALLTHROGH*/ 37935811Smarc case TIOCSETA: 38035811Smarc case TIOCSETAW: 38137584Smarc case TIOCSETAF: { 38235811Smarc register struct termios *t = (struct termios *)data; 38317545Skarels s = spltty(); 384*39407Smarc if (com == TIOCSETAW || com == TIOCSETAF) { 385*39407Smarc ttywait(tp); 386*39407Smarc if (com == TIOCSETAF); 387*39407Smarc ttyflush(tp, FREAD); 388*39407Smarc } 389*39407Smarc if (!(t->c_cflag&CIGNORE)) { 39035811Smarc /* 39135811Smarc * set device hardware 39235811Smarc */ 39337584Smarc if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 39437584Smarc splx(s); 39535811Smarc return (error); 39637584Smarc } else { 39737584Smarc if (!(tp->t_state&TS_CARR_ON) && 39837584Smarc (tp->t_cflag&CLOCAL) && 39937584Smarc !(t->c_cflag&CLOCAL)) { 40037584Smarc tp->t_state &= ~TS_ISOPEN; 40137584Smarc tp->t_state |= TS_WOPEN; 40237584Smarc ttwakeup(tp); 40337584Smarc } 40435811Smarc tp->t_cflag = t->c_cflag; 40535811Smarc tp->t_ispeed = t->c_ispeed; 40635811Smarc tp->t_ospeed = t->c_ospeed; 40734492Skarels } 40835811Smarc ttsetwater(tp); 40912752Ssam } 410*39407Smarc if (com != TIOCSETAF) { 41135811Smarc if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 41235811Smarc if (t->c_lflag&ICANON) { 41335811Smarc tp->t_lflag |= PENDIN; 41435811Smarc ttwakeup(tp); 41535811Smarc } 41635811Smarc else { 41735811Smarc struct clist tq; 41835811Smarc 41935811Smarc catq(&tp->t_rawq, &tp->t_canq); 42035811Smarc tq = tp->t_rawq; 42135811Smarc tp->t_rawq = tp->t_canq; 42235811Smarc tp->t_canq = tq; 42335811Smarc } 42412752Ssam } 42535811Smarc tp->t_iflag = t->c_iflag; 42635811Smarc tp->t_oflag = t->c_oflag; 42735811Smarc tp->t_lflag = t->c_lflag; 42835811Smarc bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 42912752Ssam splx(s); 43012752Ssam break; 43112752Ssam } 43212752Ssam 43312752Ssam /* 43435811Smarc * Acquire controlling terminal. 43534492Skarels */ 43635811Smarc case TIOCSCTTY: { 43735811Smarc register struct proc *p = u.u_procp; 43834492Skarels 43935811Smarc /* RETHINK - whether non-session leader 44035811Smarc * can allocate a new ctty for a session. 44135811Smarc */ 44235811Smarc if (u.u_ttyp || 44335811Smarc (tp->t_session && tp->t_session != p->p_session) || 44435811Smarc (!tp->t_session && !SESS_LEADER(p))) 445*39407Smarc return (EPERM); 44635811Smarc u.u_ttyp = tp; 44735811Smarc u.u_ttyd = tp->t_dev; 44835811Smarc if (tp->t_pgid == 0) 44935811Smarc tp->t_pgid = p->p_pgrp->pg_id; 45035811Smarc tp->t_session = p->p_session; 45134492Skarels break; 45235811Smarc } 45334492Skarels 45434492Skarels /* 45535811Smarc * Set terminal process group. 45617545Skarels */ 45718650Sbloom case TIOCSPGRP: { 45835811Smarc register struct proc *p = u.u_procp; 45935811Smarc register struct pgrp *pgrp = pgfind(*(int *)data); 46017545Skarels 46135811Smarc if (u.u_uid && 46235811Smarc (tp != u.u_ttyp || 46335811Smarc (pgrp && pgrp->pg_session != p->p_session))) { 46435811Smarc if (u.u_ttyp == NULL) 46535811Smarc return (ENOTTY); 46635811Smarc else 46735811Smarc return (EPERM); 46835811Smarc } 46935811Smarc tp->t_pgid = *(int *)data; 47012752Ssam break; 47118650Sbloom } 47212752Ssam 47312752Ssam case TIOCGPGRP: 47435811Smarc *(int *)data = tp->t_pgid; 47512752Ssam break; 47612752Ssam 47717598Sbloom case TIOCSWINSZ: 47818650Sbloom if (bcmp((caddr_t)&tp->t_winsize, data, 47918650Sbloom sizeof (struct winsize))) { 48017598Sbloom tp->t_winsize = *(struct winsize *)data; 48135811Smarc gsignal(tp->t_pgid, SIGWINCH); 48217598Sbloom } 48317598Sbloom break; 48417598Sbloom 48517598Sbloom case TIOCGWINSZ: 48617598Sbloom *(struct winsize *)data = tp->t_winsize; 48717598Sbloom break; 48817598Sbloom 48930534Skarels case TIOCCONS: 49030534Skarels if (*(int *)data) { 49130534Skarels if (constty != NULL) 49230534Skarels return (EBUSY); 49330534Skarels #ifndef UCONSOLE 49437554Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 49537554Smckusick return (error); 49630534Skarels #endif 49730534Skarels constty = tp; 49830534Skarels } else if (tp == constty) 49933404Skarels constty = NULL; 50030534Skarels break; 50130534Skarels 50235811Smarc #ifdef COMPAT_43 50335811Smarc case TIOCGETP: 50435811Smarc case TIOCSETP: 50535811Smarc case TIOCSETN: 50635811Smarc case TIOCGETC: 50735811Smarc case TIOCSETC: 50835811Smarc case TIOCSLTC: 50935811Smarc case TIOCGLTC: 51035811Smarc case TIOCLBIS: 51135811Smarc case TIOCLBIC: 51235811Smarc case TIOCLSET: 51335811Smarc case TIOCLGET: 514*39407Smarc case OTIOCGETD: 515*39407Smarc case OTIOCSETD: 51635811Smarc return(ttcompat(tp, com, data, flag)); 51735811Smarc #endif 51835811Smarc 51939Sbill default: 5208556Sroot return (-1); 52139Sbill } 5228556Sroot return (0); 52339Sbill } 5244484Swnj 5254484Swnj ttnread(tp) 5264484Swnj struct tty *tp; 5274484Swnj { 5284484Swnj int nread = 0; 5294484Swnj 53035811Smarc if (tp->t_lflag & PENDIN) 5314484Swnj ttypend(tp); 5324484Swnj nread = tp->t_canq.c_cc; 53335811Smarc if ((tp->t_lflag & ICANON) == 0) 5344484Swnj nread += tp->t_rawq.c_cc; 5354484Swnj return (nread); 5364484Swnj } 5374484Swnj 5385408Swnj ttselect(dev, rw) 5394484Swnj dev_t dev; 5405408Swnj int rw; 5414484Swnj { 5424484Swnj register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 5434484Swnj int nread; 54417545Skarels int s = spltty(); 5454484Swnj 5465408Swnj switch (rw) { 5474484Swnj 5484484Swnj case FREAD: 5494484Swnj nread = ttnread(tp); 55037584Smarc if (nread > 0 || 55137584Smarc (!(tp->t_cflag&CLOCAL) && !(tp->t_state&TS_CARR_ON))) 5525408Swnj goto win; 5534938Swnj if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 5545408Swnj tp->t_state |= TS_RCOLL; 5554484Swnj else 5564484Swnj tp->t_rsel = u.u_procp; 5575408Swnj break; 5584484Swnj 5595408Swnj case FWRITE: 56035811Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 5615408Swnj goto win; 5625408Swnj if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 5635408Swnj tp->t_state |= TS_WCOLL; 5645408Swnj else 5655408Swnj tp->t_wsel = u.u_procp; 5665408Swnj break; 5674484Swnj } 5685408Swnj splx(s); 5695408Swnj return (0); 5705408Swnj win: 5715408Swnj splx(s); 5725408Swnj return (1); 5734484Swnj } 5747436Skre 5757502Sroot /* 57625391Skarels * Initial open of tty, or (re)entry to line discipline. 5777502Sroot */ 5787502Sroot ttyopen(dev, tp) 5797625Ssam dev_t dev; 5807625Ssam register struct tty *tp; 5817502Sroot { 5827502Sroot 5837502Sroot tp->t_dev = dev; 58435811Smarc 5857502Sroot tp->t_state &= ~TS_WOPEN; 58617545Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 58717545Skarels tp->t_state |= TS_ISOPEN; 58817598Sbloom bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 58917545Skarels } 5908556Sroot return (0); 5917502Sroot } 5927502Sroot 5937502Sroot /* 59425391Skarels * "close" a line discipline 59525391Skarels */ 59625391Skarels ttylclose(tp) 59725391Skarels register struct tty *tp; 59825391Skarels { 59925391Skarels 60025391Skarels ttywflush(tp); 60125391Skarels } 60225391Skarels 60325391Skarels /* 6047502Sroot * clean tp on last close 6057502Sroot */ 6067502Sroot ttyclose(tp) 6077625Ssam register struct tty *tp; 6087502Sroot { 60930534Skarels if (constty == tp) 61030534Skarels constty = NULL; 61125391Skarels ttyflush(tp, FREAD|FWRITE); 61235811Smarc tp->t_pgid = 0; 6137502Sroot tp->t_state = 0; 6147502Sroot } 6157502Sroot 6167502Sroot /* 61725391Skarels * Handle modem control transition on a tty. 61825391Skarels * Flag indicates new state of carrier. 61925391Skarels * Returns 0 if the line should be turned off, otherwise 1. 62025391Skarels */ 62125391Skarels ttymodem(tp, flag) 62225391Skarels register struct tty *tp; 62325391Skarels { 62425391Skarels 62535811Smarc if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag & MDMBUF)) { 62625391Skarels /* 62725391Skarels * MDMBUF: do flow control according to carrier flag 62825391Skarels */ 62925391Skarels if (flag) { 63025391Skarels tp->t_state &= ~TS_TTSTOP; 63125391Skarels ttstart(tp); 63225391Skarels } else if ((tp->t_state&TS_TTSTOP) == 0) { 63325391Skarels tp->t_state |= TS_TTSTOP; 63425391Skarels (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 63525391Skarels } 63625391Skarels } else if (flag == 0) { 63725391Skarels /* 63825391Skarels * Lost carrier. 63925391Skarels */ 64025391Skarels tp->t_state &= ~TS_CARR_ON; 64125391Skarels if (tp->t_state & TS_ISOPEN) { 64235811Smarc if ((tp->t_lflag & NOHANG) == 0) { 64335811Smarc gsignal(tp->t_pgid, SIGHUP); 64435811Smarc gsignal(tp->t_pgid, SIGCONT); 64525391Skarels ttyflush(tp, FREAD|FWRITE); 64625391Skarels return (0); 64725391Skarels } 64825391Skarels } 64925391Skarels } else { 65025391Skarels /* 65125391Skarels * Carrier now on. 65225391Skarels */ 65325391Skarels tp->t_state |= TS_CARR_ON; 65437584Smarc ttwakeup(tp); 65525391Skarels } 65625391Skarels return (1); 65725391Skarels } 65825391Skarels 65925391Skarels /* 66025404Skarels * Default modem control routine (for other line disciplines). 66125404Skarels * Return argument flag, to turn off device on carrier drop. 66225404Skarels */ 66325415Skarels nullmodem(tp, flag) 66425415Skarels register struct tty *tp; 66525404Skarels int flag; 66625404Skarels { 66725404Skarels 66825404Skarels if (flag) 66925404Skarels tp->t_state |= TS_CARR_ON; 670*39407Smarc else { 67125404Skarels tp->t_state &= ~TS_CARR_ON; 672*39407Smarc if ((tp->t_lflag & NOHANG) == 0) 673*39407Smarc gsignal(tp->t_pgid, SIGHUP); 674*39407Smarc } 67525404Skarels return (flag); 67625404Skarels } 67725404Skarels 67825404Skarels /* 6797502Sroot * reinput pending characters after state switch 68017545Skarels * call at spltty(). 6817502Sroot */ 6827502Sroot ttypend(tp) 6837625Ssam register struct tty *tp; 6847502Sroot { 6857502Sroot struct clist tq; 6867502Sroot register c; 6877502Sroot 68835811Smarc tp->t_lflag &= ~PENDIN; 6899578Ssam tp->t_state |= TS_TYPEN; 6907502Sroot tq = tp->t_rawq; 6917502Sroot tp->t_rawq.c_cc = 0; 6927502Sroot tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 6937502Sroot while ((c = getc(&tq)) >= 0) 6947502Sroot ttyinput(c, tp); 6959578Ssam tp->t_state &= ~TS_TYPEN; 6967502Sroot } 6977502Sroot 6987502Sroot /* 69935811Smarc * 7009578Ssam * Place a character on raw TTY input queue, 7019578Ssam * putting in delimiters and waking up top 7029578Ssam * half as needed. Also echo if required. 7039578Ssam * The arguments are the character and the 7049578Ssam * appropriate tty structure. 7057502Sroot */ 7067502Sroot ttyinput(c, tp) 7077625Ssam register c; 7087625Ssam register struct tty *tp; 7097502Sroot { 71035811Smarc register int iflag = tp->t_iflag; 71135811Smarc register int lflag = tp->t_lflag; 71235811Smarc register u_char *cc = tp->t_cc; 71335811Smarc int i, err; 7147502Sroot 7159578Ssam /* 7169578Ssam * If input is pending take it first. 7179578Ssam */ 71835811Smarc if (lflag&PENDIN) 7197502Sroot ttypend(tp); 72035811Smarc /* 72135811Smarc * Gather stats. 72235811Smarc */ 7237502Sroot tk_nin++; 72435811Smarc if (lflag&ICANON) { 72535811Smarc tk_cancc++; 72635811Smarc tp->t_cancc++; 72735811Smarc } else { 72835811Smarc tk_rawcc++; 72935811Smarc tp->t_rawcc++; 73035811Smarc } 7319578Ssam /* 73235811Smarc * Handle exceptional conditions (break, parity, framing). 7339578Ssam */ 73435811Smarc if (err = (c&TTY_ERRORMASK)) { 73535811Smarc c &= ~TTY_ERRORMASK; 73635811Smarc if (err&TTY_FE && !c) { /* break */ 73735811Smarc if (iflag&IGNBRK) 73835811Smarc goto endcase; 73935811Smarc else if (iflag&BRKINT && lflag&ISIG && 74035811Smarc (cc[VINTR] != _POSIX_VDISABLE)) 74135811Smarc c = cc[VINTR]; 74235811Smarc else { 74335811Smarc c = 0; 74435811Smarc if (iflag&PARMRK) 74535811Smarc goto parmrk; 74635811Smarc } 74735811Smarc } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 74835811Smarc if (iflag&IGNPAR) 74935811Smarc goto endcase; 75035811Smarc else if (iflag&PARMRK) { 75135811Smarc parmrk: 75235811Smarc putc(0377|TTY_QUOTE, &tp->t_rawq); 75335811Smarc putc(0|TTY_QUOTE, &tp->t_rawq); 75435811Smarc putc(c|TTY_QUOTE, &tp->t_rawq); 75535811Smarc goto endcase; 75635811Smarc } else 75735811Smarc c = 0; 7587502Sroot } 7599578Ssam } 7609578Ssam /* 76135811Smarc * In tandem mode, check high water mark. 7629578Ssam */ 76335811Smarc if (iflag&IXOFF) 76435811Smarc ttyblock(tp); 76535811Smarc if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 7669578Ssam c &= 0177; 7679578Ssam /* 7689578Ssam * Check for literal nexting very first 7699578Ssam */ 7709578Ssam if (tp->t_state&TS_LNCH) { 77135811Smarc c |= TTY_QUOTE; 7729578Ssam tp->t_state &= ~TS_LNCH; 7739578Ssam } 7749578Ssam /* 7759578Ssam * Scan for special characters. This code 7769578Ssam * is really just a big case statement with 7779578Ssam * non-constant cases. The bottom of the 7789578Ssam * case statement is labeled ``endcase'', so goto 7799578Ssam * it after a case match, or similar. 7809578Ssam */ 78135811Smarc /* 78235811Smarc * Control chars which aren't controlled 78335811Smarc * by ICANON, ISIG, or IXON. 78435811Smarc */ 785*39407Smarc if (lflag&IEXTEN) { 78635811Smarc if (CCEQ(cc[VLNEXT],c)) { 78735811Smarc if (lflag&ECHO) { 78835811Smarc if (lflag&ECHOE) 78935811Smarc ttyout("^\b", tp); 79035811Smarc else 79135811Smarc ttyecho(c, tp); 79235811Smarc } 7939578Ssam tp->t_state |= TS_LNCH; 7949578Ssam goto endcase; 7959578Ssam } 79635811Smarc if (CCEQ(cc[VFLUSHO],c)) { 79735811Smarc if (lflag&FLUSHO) 79835811Smarc tp->t_lflag &= ~FLUSHO; 7997502Sroot else { 80012752Ssam ttyflush(tp, FWRITE); 8017502Sroot ttyecho(c, tp); 8029578Ssam if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 8037502Sroot ttyretype(tp); 80435811Smarc tp->t_lflag |= FLUSHO; 8057502Sroot } 8069578Ssam goto startoutput; 8079578Ssam } 80835811Smarc } 80935811Smarc /* 81035811Smarc * Signals. 81135811Smarc */ 81235811Smarc if (lflag&ISIG) { 81335811Smarc if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 81435811Smarc if ((lflag&NOFLSH) == 0) 81535811Smarc ttyflush(tp, FREAD|FWRITE); 81635811Smarc ttyecho(c, tp); 81735811Smarc gsignal(tp->t_pgid, CCEQ(cc[VINTR],c) ? 81835811Smarc SIGINT : SIGQUIT); 81935811Smarc goto endcase; 82035811Smarc } 82135811Smarc if (CCEQ(cc[VSUSP],c)) { 82235811Smarc if ((lflag&NOFLSH) == 0) 82312752Ssam ttyflush(tp, FREAD); 8249578Ssam ttyecho(c, tp); 82535811Smarc gsignal(tp->t_pgid, SIGTSTP); 8269578Ssam goto endcase; 8279578Ssam } 828*39407Smarc if (CCEQ(cc[VINFO],c)) { 829*39407Smarc ttyinfo(tp); 830*39407Smarc goto endcase; 831*39407Smarc } 8329578Ssam } 8339578Ssam /* 8349578Ssam * Handle start/stop characters. 8359578Ssam */ 83635811Smarc if (iflag&IXON) { 83735811Smarc if (CCEQ(cc[VSTOP],c)) { 83835811Smarc if ((tp->t_state&TS_TTSTOP) == 0) { 83935811Smarc tp->t_state |= TS_TTSTOP; 84035811Smarc (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 84135811Smarc return; 84235811Smarc } 84335811Smarc if (!CCEQ(cc[VSTART], c)) 84435811Smarc return; 84535811Smarc /* 84635811Smarc * if VSTART == VSTOP then toggle 84735811Smarc */ 84835811Smarc goto endcase; 8499578Ssam } 85035811Smarc if (CCEQ(cc[VSTART], c)) 85135811Smarc goto restartoutput; 8529578Ssam } 8539578Ssam /* 85435811Smarc * IGNCR, ICRNL, & INLCR 8559578Ssam */ 85635811Smarc if (c == '\r') { 85735811Smarc if (iflag&IGNCR) 85835811Smarc goto endcase; 85935811Smarc else if (iflag&ICRNL) 86035811Smarc c = '\n'; 8619578Ssam } 86235811Smarc else if (c == '\n' && iflag&INLCR) 86335811Smarc c = '\r'; 8649578Ssam /* 86535811Smarc * Non canonical mode; don't process line editing 8669578Ssam * characters; check high water mark for wakeup. 86735811Smarc * 8689578Ssam */ 86935811Smarc if (!(lflag&ICANON)) { 8709578Ssam if (tp->t_rawq.c_cc > TTYHOG) { 87135811Smarc if (iflag&IMAXBEL) { 87235811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 87335811Smarc (void) ttyoutput(CTRL('g'), tp); 87435811Smarc } else 87535811Smarc ttyflush(tp, FREAD | FWRITE); 87635811Smarc } else { 87735811Smarc if (putc(c, &tp->t_rawq) >= 0) { 87835811Smarc ttwakeup(tp); 87935811Smarc ttyecho(c, tp); 88035811Smarc } 8817502Sroot } 8829578Ssam goto endcase; 8839578Ssam } 8849578Ssam /* 88535811Smarc * From here on down canonical mode character 8869578Ssam * processing takes place. 8879578Ssam */ 88835811Smarc /* 88935811Smarc * erase (^H / ^?) 89035811Smarc */ 891*39407Smarc if (CCEQ(cc[VERASE], c)) { 8929578Ssam if (tp->t_rawq.c_cc) 8939578Ssam ttyrub(unputc(&tp->t_rawq), tp); 8949578Ssam goto endcase; 8959578Ssam } 89635811Smarc /* 89735811Smarc * kill (^U) 89835811Smarc */ 89935811Smarc if (CCEQ(cc[VKILL], c)) { 90037584Smarc if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 90137584Smarc !(lflag&ECHOPRT)) { 9029578Ssam while (tp->t_rawq.c_cc) 9039578Ssam ttyrub(unputc(&tp->t_rawq), tp); 9049578Ssam } else { 9059578Ssam ttyecho(c, tp); 90635811Smarc if (lflag&ECHOK || lflag&ECHOKE) 90735811Smarc ttyecho('\n', tp); 9089578Ssam while (getc(&tp->t_rawq) > 0) 9099578Ssam ; 9109578Ssam tp->t_rocount = 0; 9119578Ssam } 9129578Ssam tp->t_state &= ~TS_LOCAL; 9139578Ssam goto endcase; 9149578Ssam } 9159578Ssam /* 91635811Smarc * word erase (^W) 9179578Ssam */ 91835811Smarc if (CCEQ(cc[VWERASE], c)) { 91935811Smarc int ctype; 92035811Smarc 92135811Smarc #define CTYPE(c) ((lflag&ALTWERASE) ? (partab[(c)&TTY_CHARMASK]&0100) : 0) 92235811Smarc /* 92335811Smarc * erase whitespace 92435811Smarc */ 92535811Smarc while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 92635811Smarc ttyrub(c, tp); 92735811Smarc if (c == -1) 92834492Skarels goto endcase; 92935811Smarc /* 93035811Smarc * special case last char of token 93135811Smarc */ 93235811Smarc ttyrub(c, tp); 93335811Smarc c = unputc(&tp->t_rawq); 93435811Smarc if (c == -1 || c == ' ' || c == '\t') { 93535811Smarc if (c != -1) 93635811Smarc (void) putc(c, &tp->t_rawq); 93734492Skarels goto endcase; 93834492Skarels } 93935811Smarc /* 94035811Smarc * erase rest of token 94135811Smarc */ 94235811Smarc ctype = CTYPE(c); 94335811Smarc do { 94435811Smarc ttyrub(c, tp); 94535811Smarc c = unputc(&tp->t_rawq); 94635811Smarc if (c == -1) 94735811Smarc goto endcase; 94835811Smarc } while (c != ' ' && c != '\t' && CTYPE(c) == ctype); 94935811Smarc (void) putc(c, &tp->t_rawq); 95035811Smarc goto endcase; 95135811Smarc #undef CTYPE 9529578Ssam } 9539578Ssam /* 95435811Smarc * reprint line (^R) 95535811Smarc */ 95635811Smarc if (CCEQ(cc[VREPRINT], c)) { 95735811Smarc ttyretype(tp); 95835811Smarc goto endcase; 95935811Smarc } 96035811Smarc /* 9619578Ssam * Check for input buffer overflow 9629578Ssam */ 96310391Ssam if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 96435811Smarc if (iflag&IMAXBEL) { 96535811Smarc if (tp->t_outq.c_cc < tp->t_hiwat) 96635811Smarc (void) ttyoutput(CTRL('g'), tp); 96735811Smarc } else 96835811Smarc ttyflush(tp, FREAD | FWRITE); 9699578Ssam goto endcase; 97010391Ssam } 9719578Ssam /* 9729578Ssam * Put data char in q for user and 9739578Ssam * wakeup on seeing a line delimiter. 9749578Ssam */ 9759578Ssam if (putc(c, &tp->t_rawq) >= 0) { 97635811Smarc if (ttbreakc(c)) { 9779578Ssam tp->t_rocount = 0; 9789578Ssam catq(&tp->t_rawq, &tp->t_canq); 9797502Sroot ttwakeup(tp); 9809578Ssam } else if (tp->t_rocount++ == 0) 9819578Ssam tp->t_rocol = tp->t_col; 9829578Ssam if (tp->t_state&TS_ERASE) { 98335811Smarc /* 98435811Smarc * end of prterase \.../ 98535811Smarc */ 9869578Ssam tp->t_state &= ~TS_ERASE; 9879578Ssam (void) ttyoutput('/', tp); 9889578Ssam } 9899578Ssam i = tp->t_col; 9907502Sroot ttyecho(c, tp); 99135811Smarc if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 99235811Smarc /* 99335811Smarc * Place the cursor over the '^' of the ^D. 99435811Smarc */ 9959578Ssam i = MIN(2, tp->t_col - i); 9969578Ssam while (i > 0) { 9979578Ssam (void) ttyoutput('\b', tp); 9989578Ssam i--; 9999578Ssam } 10009578Ssam } 10017502Sroot } 10029578Ssam endcase: 10039578Ssam /* 100435811Smarc * IXANY means allow any character to restart output. 10059578Ssam */ 100635811Smarc if ((tp->t_state&TS_TTSTOP) && !(iflag&IXANY) 100735811Smarc && cc[VSTART] != cc[VSTOP]) 10087502Sroot return; 10099578Ssam restartoutput: 10107502Sroot tp->t_state &= ~TS_TTSTOP; 101135811Smarc tp->t_lflag &= ~FLUSHO; 10129578Ssam startoutput: 10137502Sroot ttstart(tp); 10147502Sroot } 10157502Sroot 10167502Sroot /* 10179578Ssam * Put character on TTY output queue, adding delays, 10187502Sroot * expanding tabs, and handling the CR/NL bit. 10199578Ssam * This is called both from the top half for output, 10209578Ssam * and from interrupt level for echoing. 10217502Sroot * The arguments are the character and the tty structure. 10227502Sroot * Returns < 0 if putc succeeds, otherwise returns char to resend 10237502Sroot * Must be recursive. 10247502Sroot */ 10257502Sroot ttyoutput(c, tp) 10267502Sroot register c; 10277502Sroot register struct tty *tp; 10287502Sroot { 10297502Sroot register char *colp; 10307502Sroot register ctype; 103135811Smarc register long oflag = tp->t_oflag; 103235811Smarc 103335811Smarc if (!(oflag&OPOST)) { 103435811Smarc if (tp->t_lflag&FLUSHO) 10357502Sroot return (-1); 10367502Sroot if (putc(c, &tp->t_outq)) 10377625Ssam return (c); 10387502Sroot tk_nout++; 103935811Smarc tp->t_outcc++; 10407502Sroot return (-1); 10417502Sroot } 104235811Smarc c &= TTY_CHARMASK; 10437502Sroot /* 10447502Sroot * Turn tabs to spaces as required 10457502Sroot */ 104635811Smarc if (c == '\t' && oflag&OXTABS ) { 10477502Sroot register int s; 10487502Sroot 10497502Sroot c = 8 - (tp->t_col&7); 105035811Smarc if ((tp->t_lflag&FLUSHO) == 0) { 105117545Skarels s = spltty(); /* don't interrupt tabs */ 10527502Sroot c -= b_to_q(" ", c, &tp->t_outq); 10537502Sroot tk_nout += c; 105435811Smarc tp->t_outcc += c; 10557502Sroot splx(s); 10567502Sroot } 10577502Sroot tp->t_col += c; 10587502Sroot return (c ? -1 : '\t'); 10597502Sroot } 106035811Smarc if (c == CEOT && oflag&ONOEOT) 106135811Smarc return(-1); 10627502Sroot tk_nout++; 106335811Smarc tp->t_outcc++; 10647502Sroot /* 10657502Sroot * turn <nl> to <cr><lf> if desired. 10667502Sroot */ 106735811Smarc if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 10687502Sroot return (c); 106935811Smarc if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 107035811Smarc return (c); 10717502Sroot /* 10727502Sroot * Calculate delays. 10737502Sroot * The numbers here represent clock ticks 10747502Sroot * and are not necessarily optimal for all terminals. 10759578Ssam * 10769578Ssam * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 107735811Smarc * 107835811Smarc * (actually, should THROW AWAY terminals which need delays) 10797502Sroot */ 10807502Sroot colp = &tp->t_col; 10817502Sroot ctype = partab[c]; 10827502Sroot c = 0; 10837502Sroot switch (ctype&077) { 10847502Sroot 10857502Sroot case ORDINARY: 10867502Sroot (*colp)++; 10877502Sroot 10887502Sroot case CONTROL: 10897502Sroot break; 10907502Sroot 10917502Sroot case BACKSPACE: 10927502Sroot if (*colp) 10937502Sroot (*colp)--; 10947502Sroot break; 10957502Sroot 109613821Ssam /* 109713821Ssam * This macro is close enough to the correct thing; 109813821Ssam * it should be replaced by real user settable delays 109913821Ssam * in any event... 110013821Ssam */ 110113821Ssam #define mstohz(ms) (((ms) * hz) >> 10) 11027502Sroot case NEWLINE: 11037502Sroot ctype = (tp->t_flags >> 8) & 03; 11047625Ssam if (ctype == 1) { /* tty 37 */ 110526357Skarels if (*colp > 0) { 110626357Skarels c = (((unsigned)*colp) >> 4) + 3; 110726357Skarels if ((unsigned)c > 6) 110826357Skarels c = 6; 110926357Skarels } 11109578Ssam } else if (ctype == 2) /* vt05 */ 111113821Ssam c = mstohz(100); 11127502Sroot *colp = 0; 11137502Sroot break; 11147502Sroot 11157502Sroot case TAB: 11167502Sroot ctype = (tp->t_flags >> 10) & 03; 11177625Ssam if (ctype == 1) { /* tty 37 */ 11187502Sroot c = 1 - (*colp | ~07); 11197625Ssam if (c < 5) 11207502Sroot c = 0; 11217502Sroot } 11227502Sroot *colp |= 07; 11237502Sroot (*colp)++; 11247502Sroot break; 11257502Sroot 11267502Sroot case VTAB: 11279578Ssam if (tp->t_flags&VTDELAY) /* tty 37 */ 11287502Sroot c = 0177; 11297502Sroot break; 11307502Sroot 11317502Sroot case RETURN: 11327502Sroot ctype = (tp->t_flags >> 12) & 03; 11339578Ssam if (ctype == 1) /* tn 300 */ 113413821Ssam c = mstohz(83); 11359578Ssam else if (ctype == 2) /* ti 700 */ 113613821Ssam c = mstohz(166); 11379578Ssam else if (ctype == 3) { /* concept 100 */ 11387502Sroot int i; 11399578Ssam 11407502Sroot if ((i = *colp) >= 0) 11419578Ssam for (; i < 9; i++) 11427502Sroot (void) putc(0177, &tp->t_outq); 11437502Sroot } 11447502Sroot *colp = 0; 11457502Sroot } 114635811Smarc if (c && (tp->t_lflag&FLUSHO) == 0) 114735811Smarc (void) putc(c|TTY_QUOTE, &tp->t_outq); 11487502Sroot return (-1); 11497502Sroot } 115013821Ssam #undef mstohz 11517502Sroot 11527502Sroot /* 11537502Sroot * Called from device's read routine after it has 11547502Sroot * calculated the tty-structure given as argument. 11557502Sroot */ 115637584Smarc ttread(tp, uio, flag) 11577625Ssam register struct tty *tp; 11587722Swnj struct uio *uio; 11597502Sroot { 11607502Sroot register struct clist *qp; 116135811Smarc register int c; 116235811Smarc register long lflag = tp->t_lflag; 116335811Smarc register u_char *cc = tp->t_cc; 11649859Ssam int s, first, error = 0; 11657502Sroot 11667502Sroot loop: 116737584Smarc s = spltty(); 11689578Ssam /* 116937584Smarc * take pending input first 11709578Ssam */ 117135811Smarc if (lflag&PENDIN) 11727502Sroot ttypend(tp); 117337584Smarc /* 117437584Smarc * Handle carrier. 117537584Smarc */ 117637584Smarc if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 117737584Smarc if (tp->t_state&TS_ISOPEN) { 117837584Smarc splx(s); 117937584Smarc return (0); /* EOF */ 118037728Smckusick } else if (flag & IO_NDELAY) { 118137584Smarc splx(s); 118237584Smarc return (EWOULDBLOCK); 118337584Smarc } else { 118437584Smarc /* 118537584Smarc * sleep awaiting carrier 118637584Smarc */ 118737584Smarc sleep((caddr_t)&tp->t_rawq, TTIPRI); 118837584Smarc splx(s); 118937584Smarc goto loop; 119037584Smarc } 119137584Smarc } 11929859Ssam splx(s); 11939578Ssam /* 11949578Ssam * Hang process if it's in the background. 11959578Ssam */ 119635811Smarc if (u.u_ttyp == tp && u.u_procp->p_pgid != tp->t_pgid) { 119724392Skarels if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 119824392Skarels (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 119935811Smarc u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0) 12008520Sroot return (EIO); 120135811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTIN); 12027502Sroot sleep((caddr_t)&lbolt, TTIPRI); 120323165Sbloom goto loop; 12047502Sroot } 12059578Ssam /* 120635811Smarc * If canonical, use the canonical queue, 120735811Smarc * else use the raw queue. 120837584Smarc * 120937584Smarc * XXX - should get rid of canonical queue. 121037584Smarc * (actually, should get rid of clists...) 12119578Ssam */ 121235811Smarc qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 12139578Ssam /* 12149578Ssam * No input, sleep on rawq awaiting hardware 12159578Ssam * receipt and notification. 12169578Ssam */ 121717545Skarels s = spltty(); 12189578Ssam if (qp->c_cc <= 0) { 121937584Smarc /** XXX ??? ask mike why TS_CARR_ON was (once) necessary here 12209578Ssam if ((tp->t_state&TS_CARR_ON) == 0 || 12219578Ssam (tp->t_state&TS_NBIO)) { 12229859Ssam splx(s); 12239578Ssam return (EWOULDBLOCK); 12247502Sroot } 122537584Smarc **/ 122637728Smckusick if (flag & IO_NDELAY) { 122737584Smarc splx(s); 122837584Smarc return (EWOULDBLOCK); 122937584Smarc } 12309578Ssam sleep((caddr_t)&tp->t_rawq, TTIPRI); 12319859Ssam splx(s); 12329578Ssam goto loop; 12339578Ssam } 12349859Ssam splx(s); 12359578Ssam /* 123635811Smarc * Input present, check for input mapping and processing. 12379578Ssam */ 12389578Ssam first = 1; 12399578Ssam while ((c = getc(qp)) >= 0) { 12409578Ssam /* 124135811Smarc * delayed suspend (^Y) 12429578Ssam */ 124335811Smarc if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 124435811Smarc gsignal(tp->t_pgid, SIGTSTP); 12459578Ssam if (first) { 12469578Ssam sleep((caddr_t)&lbolt, TTIPRI); 12479578Ssam goto loop; 12489578Ssam } 12499578Ssam break; 12507502Sroot } 12519578Ssam /* 125235811Smarc * Interpret EOF only in canonical mode. 12539578Ssam */ 125435811Smarc if (CCEQ(cc[VEOF], c) && lflag&ICANON) 12559578Ssam break; 12569578Ssam /* 12579578Ssam * Give user character. 12589578Ssam */ 125935811Smarc error = ureadc(c , uio); 12609578Ssam if (error) 12619578Ssam break; 126214938Smckusick if (uio->uio_resid == 0) 12639578Ssam break; 12649578Ssam /* 126535811Smarc * In canonical mode check for a "break character" 12669578Ssam * marking the end of a "line of input". 12679578Ssam */ 126835811Smarc if (lflag&ICANON && ttbreakc(c)) { 12699578Ssam break; 127035811Smarc } 12719578Ssam first = 0; 12727502Sroot } 12739578Ssam /* 12749578Ssam * Look to unblock output now that (presumably) 12759578Ssam * the input queue has gone down. 12769578Ssam */ 127735811Smarc if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 127835811Smarc if (cc[VSTART] != _POSIX_VDISABLE 127935811Smarc && putc(cc[VSTART], &tp->t_outq) == 0) { 12807502Sroot tp->t_state &= ~TS_TBLOCK; 12817502Sroot ttstart(tp); 12827502Sroot } 128335811Smarc } 12848520Sroot return (error); 12857502Sroot } 12867502Sroot 12877502Sroot /* 128825391Skarels * Check the output queue on tp for space for a kernel message 128925391Skarels * (from uprintf/tprintf). Allow some space over the normal 129025391Skarels * hiwater mark so we don't lose messages due to normal flow 129125391Skarels * control, but don't let the tty run amok. 129230695Skarels * Sleeps here are not interruptible, but we return prematurely 129330695Skarels * if new signals come in. 129425391Skarels */ 129525391Skarels ttycheckoutq(tp, wait) 129625391Skarels register struct tty *tp; 129725391Skarels int wait; 129825391Skarels { 129930695Skarels int hiwat, s, oldsig; 130025391Skarels 130135811Smarc hiwat = tp->t_hiwat; 130225391Skarels s = spltty(); 130330695Skarels oldsig = u.u_procp->p_sig; 130425391Skarels if (tp->t_outq.c_cc > hiwat + 200) 130529946Skarels while (tp->t_outq.c_cc > hiwat) { 130629946Skarels ttstart(tp); 130730695Skarels if (wait == 0 || u.u_procp->p_sig != oldsig) { 130829946Skarels splx(s); 130929946Skarels return (0); 131029946Skarels } 131130695Skarels timeout(wakeup, (caddr_t)&tp->t_outq, hz); 131229946Skarels tp->t_state |= TS_ASLEEP; 131330695Skarels sleep((caddr_t)&tp->t_outq, PZERO - 1); 131425391Skarels } 131525391Skarels splx(s); 131625391Skarels return (1); 131725391Skarels } 131825391Skarels 131925391Skarels /* 13207502Sroot * Called from the device's write routine after it has 13217502Sroot * calculated the tty-structure given as argument. 13227502Sroot */ 132337584Smarc ttwrite(tp, uio, flag) 13247625Ssam register struct tty *tp; 13259578Ssam register struct uio *uio; 13267502Sroot { 13277502Sroot register char *cp; 132837728Smckusick register int cc, ce; 13299578Ssam int i, hiwat, cnt, error, s; 13307502Sroot char obuf[OBUFSIZ]; 13317502Sroot 133235811Smarc hiwat = tp->t_hiwat; 13339578Ssam cnt = uio->uio_resid; 13349578Ssam error = 0; 13357502Sroot loop: 133637584Smarc s = spltty(); 133737584Smarc if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 133837584Smarc if (tp->t_state&TS_ISOPEN) { 133937584Smarc splx(s); 134037584Smarc return (EIO); 134137728Smckusick } else if (flag & IO_NDELAY) { 134237584Smarc splx(s); 134337584Smarc return (EWOULDBLOCK); 134437584Smarc } else { 134537584Smarc /* 134637584Smarc * sleep awaiting carrier 134737584Smarc */ 134837584Smarc sleep((caddr_t)&tp->t_rawq, TTIPRI); 134937584Smarc splx(s); 135037584Smarc goto loop; 135137584Smarc } 135237584Smarc } 135337584Smarc splx(s); 13549578Ssam /* 13559578Ssam * Hang the process if it's in the background. 13569578Ssam */ 135735811Smarc if (u.u_ttyp == tp && 135835811Smarc u.u_procp->p_pgid != tp->t_pgid && 135935811Smarc (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 136024392Skarels !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 136135811Smarc !(u.u_procp->p_sigmask & sigmask(SIGTTOU)) && 136235811Smarc u.u_procp->p_pgrp->pg_jobc) { 136335811Smarc pgsignal(u.u_procp->p_pgrp, SIGTTOU); 13647502Sroot sleep((caddr_t)&lbolt, TTIPRI); 136521776Sbloom goto loop; 13667502Sroot } 13679578Ssam /* 13689578Ssam * Process the user's data in at most OBUFSIZ 13699578Ssam * chunks. Perform lower case simulation and 13709578Ssam * similar hacks. Keep track of high water 13719578Ssam * mark, sleep on overflow awaiting device aid 13729578Ssam * in acquiring new space. 13739578Ssam */ 13747822Sroot while (uio->uio_resid > 0) { 137532067Skarels if (tp->t_outq.c_cc > hiwat) { 137632067Skarels cc = 0; 137732067Skarels goto ovhiwat; 137832067Skarels } 13799578Ssam /* 13809578Ssam * Grab a hunk of data from the user. 13819578Ssam */ 13827822Sroot cc = uio->uio_iov->iov_len; 13837822Sroot if (cc == 0) { 13847822Sroot uio->uio_iovcnt--; 13857822Sroot uio->uio_iov++; 138621776Sbloom if (uio->uio_iovcnt <= 0) 13877822Sroot panic("ttwrite"); 13887822Sroot continue; 13897822Sroot } 13907822Sroot if (cc > OBUFSIZ) 13917822Sroot cc = OBUFSIZ; 13927502Sroot cp = obuf; 139337728Smckusick error = uiomove(cp, cc, uio); 13948520Sroot if (error) 13957502Sroot break; 139635811Smarc if (tp->t_lflag&FLUSHO) 13977502Sroot continue; 13989578Ssam /* 13999578Ssam * If nothing fancy need be done, grab those characters we 14009578Ssam * can handle without any of ttyoutput's processing and 14019578Ssam * just transfer them to the output q. For those chars 14029578Ssam * which require special processing (as indicated by the 14039578Ssam * bits in partab), call ttyoutput. After processing 14049578Ssam * a hunk of data, look for FLUSHO so ^O's will take effect 14059578Ssam * immediately. 14069578Ssam */ 14079578Ssam while (cc > 0) { 140835811Smarc if (!(tp->t_oflag&OPOST)) 14097502Sroot ce = cc; 14107502Sroot else { 141134492Skarels ce = cc - scanc((unsigned)cc, (u_char *)cp, 141234492Skarels (u_char *)partab, 077); 14139578Ssam /* 14149578Ssam * If ce is zero, then we're processing 14159578Ssam * a special character through ttyoutput. 14169578Ssam */ 14179578Ssam if (ce == 0) { 14187502Sroot tp->t_rocount = 0; 14197502Sroot if (ttyoutput(*cp, tp) >= 0) { 142021776Sbloom /* no c-lists, wait a bit */ 142121776Sbloom ttstart(tp); 142221776Sbloom sleep((caddr_t)&lbolt, TTOPRI); 142321776Sbloom if (cc != 0) { 142421776Sbloom uio->uio_iov->iov_base -= cc; 142521776Sbloom uio->uio_iov->iov_len += cc; 142621776Sbloom uio->uio_resid += cc; 142721776Sbloom uio->uio_offset -= cc; 142821776Sbloom } 142921776Sbloom goto loop; 14307502Sroot } 14319578Ssam cp++, cc--; 143235811Smarc if ((tp->t_lflag&FLUSHO) || 14339578Ssam tp->t_outq.c_cc > hiwat) 14347502Sroot goto ovhiwat; 14359578Ssam continue; 14367502Sroot } 14377502Sroot } 14389578Ssam /* 14399578Ssam * A bunch of normal characters have been found, 14409578Ssam * transfer them en masse to the output queue and 14419578Ssam * continue processing at the top of the loop. 14429578Ssam * If there are any further characters in this 14439578Ssam * <= OBUFSIZ chunk, the first should be a character 14449578Ssam * requiring special handling by ttyoutput. 14459578Ssam */ 14467502Sroot tp->t_rocount = 0; 14479578Ssam i = b_to_q(cp, ce, &tp->t_outq); 14489578Ssam ce -= i; 14499578Ssam tp->t_col += ce; 14509578Ssam cp += ce, cc -= ce, tk_nout += ce; 145135811Smarc tp->t_outcc += ce; 14529578Ssam if (i > 0) { 14539578Ssam /* out of c-lists, wait a bit */ 14547502Sroot ttstart(tp); 14557502Sroot sleep((caddr_t)&lbolt, TTOPRI); 145621776Sbloom uio->uio_iov->iov_base -= cc; 145721776Sbloom uio->uio_iov->iov_len += cc; 145821776Sbloom uio->uio_resid += cc; 145921776Sbloom uio->uio_offset -= cc; 146021776Sbloom goto loop; 14617502Sroot } 146235811Smarc if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 14637502Sroot goto ovhiwat; 14647502Sroot } 146535811Smarc ttstart(tp); 14667502Sroot } 14678520Sroot return (error); 14687502Sroot ovhiwat: 14699578Ssam if (cc != 0) { 14709578Ssam uio->uio_iov->iov_base -= cc; 14719578Ssam uio->uio_iov->iov_len += cc; 14729578Ssam uio->uio_resid += cc; 14739578Ssam uio->uio_offset -= cc; 14749578Ssam } 147532067Skarels ttstart(tp); 147632067Skarels s = spltty(); 14779578Ssam /* 147835811Smarc * This can only occur if FLUSHO is set in t_lflag, 147932067Skarels * or if ttstart/oproc is synchronous (or very fast). 14809578Ssam */ 14817502Sroot if (tp->t_outq.c_cc <= hiwat) { 14829578Ssam splx(s); 14837502Sroot goto loop; 14847502Sroot } 148537728Smckusick if (flag & IO_NDELAY) { 148617545Skarels splx(s); 14877822Sroot if (uio->uio_resid == cnt) 14888520Sroot return (EWOULDBLOCK); 14898520Sroot return (0); 14907502Sroot } 14917502Sroot tp->t_state |= TS_ASLEEP; 14927502Sroot sleep((caddr_t)&tp->t_outq, TTOPRI); 14939578Ssam splx(s); 14947502Sroot goto loop; 14957502Sroot } 14967502Sroot 14977502Sroot /* 14987502Sroot * Rubout one character from the rawq of tp 14997502Sroot * as cleanly as possible. 15007502Sroot */ 15017502Sroot ttyrub(c, tp) 15027625Ssam register c; 15037625Ssam register struct tty *tp; 15047502Sroot { 15057502Sroot register char *cp; 15067502Sroot register int savecol; 15077502Sroot int s; 15087502Sroot char *nextc(); 15097502Sroot 151035811Smarc if ((tp->t_lflag&ECHO) == 0) 15117502Sroot return; 151235811Smarc tp->t_lflag &= ~FLUSHO; 151335811Smarc if (tp->t_lflag&ECHOE) { 15147502Sroot if (tp->t_rocount == 0) { 15157502Sroot /* 15167502Sroot * Screwed by ttwrite; retype 15177502Sroot */ 15187502Sroot ttyretype(tp); 15197502Sroot return; 15207502Sroot } 152135811Smarc if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 15227502Sroot ttyrubo(tp, 2); 152335811Smarc else switch (partab[c&=0377]&077) { 15247502Sroot 15257502Sroot case ORDINARY: 152635811Smarc ttyrubo(tp, 1); 15277502Sroot break; 15287502Sroot 15297502Sroot case VTAB: 15307502Sroot case BACKSPACE: 15317502Sroot case CONTROL: 15327502Sroot case RETURN: 153335811Smarc if (tp->t_lflag&ECHOCTL) 15347502Sroot ttyrubo(tp, 2); 15357502Sroot break; 15367502Sroot 153735811Smarc case TAB: { 153835811Smarc int c; 153935811Smarc 15407502Sroot if (tp->t_rocount < tp->t_rawq.c_cc) { 15417502Sroot ttyretype(tp); 15427502Sroot return; 15437502Sroot } 154417545Skarels s = spltty(); 15457502Sroot savecol = tp->t_col; 15469578Ssam tp->t_state |= TS_CNTTB; 154735811Smarc tp->t_lflag |= FLUSHO; 15487502Sroot tp->t_col = tp->t_rocol; 15499578Ssam cp = tp->t_rawq.c_cf; 1550*39407Smarc if (cp) 1551*39407Smarc c = *cp; /* XXX FIX NEXTC */ 155235811Smarc for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 155335811Smarc ttyecho(c, tp); 155435811Smarc tp->t_lflag &= ~FLUSHO; 15559578Ssam tp->t_state &= ~TS_CNTTB; 15567502Sroot splx(s); 15577502Sroot /* 15587502Sroot * savecol will now be length of the tab 15597502Sroot */ 15607502Sroot savecol -= tp->t_col; 15617502Sroot tp->t_col += savecol; 15627502Sroot if (savecol > 8) 15637502Sroot savecol = 8; /* overflow screw */ 15647502Sroot while (--savecol >= 0) 15657502Sroot (void) ttyoutput('\b', tp); 15667502Sroot break; 156735811Smarc } 15687502Sroot 15697502Sroot default: 157037584Smarc /* XXX */ 157135811Smarc printf("ttyrub: would panic c = %d, val = %d\n", 157235811Smarc c, partab[c&=0377]&077); 157335811Smarc /*panic("ttyrub");*/ 15747502Sroot } 157535811Smarc } else if (tp->t_lflag&ECHOPRT) { 15769578Ssam if ((tp->t_state&TS_ERASE) == 0) { 15777502Sroot (void) ttyoutput('\\', tp); 15789578Ssam tp->t_state |= TS_ERASE; 15797502Sroot } 15807502Sroot ttyecho(c, tp); 15817502Sroot } else 158235811Smarc ttyecho(tp->t_cc[VERASE], tp); 15837502Sroot tp->t_rocount--; 15847502Sroot } 15857502Sroot 15867502Sroot /* 15877502Sroot * Crt back over cnt chars perhaps 15887502Sroot * erasing them. 15897502Sroot */ 15907502Sroot ttyrubo(tp, cnt) 15917625Ssam register struct tty *tp; 15927625Ssam int cnt; 15937502Sroot { 15947502Sroot 15957502Sroot while (--cnt >= 0) 159635811Smarc ttyout("\b \b", tp); 15977502Sroot } 15987502Sroot 15997502Sroot /* 16007502Sroot * Reprint the rawq line. 16017502Sroot * We assume c_cc has already been checked. 16027502Sroot */ 16037502Sroot ttyretype(tp) 16047625Ssam register struct tty *tp; 16057502Sroot { 16067502Sroot register char *cp; 16077502Sroot char *nextc(); 160835811Smarc int s, c; 16097502Sroot 161035811Smarc if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 161135811Smarc ttyecho(tp->t_cc[VREPRINT], tp); 16127502Sroot (void) ttyoutput('\n', tp); 161317545Skarels s = spltty(); 161435811Smarc /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 161535811Smarc BIT OF FIRST CHAR ****/ 161635811Smarc for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 161735811Smarc ttyecho(c, tp); 161835811Smarc } 161935811Smarc for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 162035811Smarc ttyecho(c, tp); 162135811Smarc } 16229578Ssam tp->t_state &= ~TS_ERASE; 16237502Sroot splx(s); 16247502Sroot tp->t_rocount = tp->t_rawq.c_cc; 16257502Sroot tp->t_rocol = 0; 16267502Sroot } 16277502Sroot 16287502Sroot /* 162935811Smarc * Echo a typed character to the terminal. 16307502Sroot */ 16317502Sroot ttyecho(c, tp) 16327625Ssam register c; 16337625Ssam register struct tty *tp; 16347502Sroot { 16359578Ssam if ((tp->t_state&TS_CNTTB) == 0) 163635811Smarc tp->t_lflag &= ~FLUSHO; 163735811Smarc if ((tp->t_lflag&ECHO) == 0 && !(tp->t_lflag&ECHONL && c == '\n')) 16387502Sroot return; 163935811Smarc if (tp->t_lflag&ECHOCTL) { 164035811Smarc if ((c&TTY_CHARMASK)<=037 && c!='\t' && c!='\n' || c==0177) { 16417502Sroot (void) ttyoutput('^', tp); 164235811Smarc c &= TTY_CHARMASK; 16437502Sroot if (c == 0177) 16447502Sroot c = '?'; 16457502Sroot else 16467502Sroot c += 'A' - 1; 16477502Sroot } 16487502Sroot } 164935811Smarc (void) ttyoutput(c, tp); 16507502Sroot } 16517502Sroot 16527502Sroot /* 16537502Sroot * send string cp to tp 16547502Sroot */ 16557502Sroot ttyout(cp, tp) 16567625Ssam register char *cp; 16577625Ssam register struct tty *tp; 16587502Sroot { 16597502Sroot register char c; 16607502Sroot 16617502Sroot while (c = *cp++) 16627502Sroot (void) ttyoutput(c, tp); 16637502Sroot } 16647502Sroot 16657502Sroot ttwakeup(tp) 16667502Sroot struct tty *tp; 16677502Sroot { 16687502Sroot 16697502Sroot if (tp->t_rsel) { 16707502Sroot selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 16717502Sroot tp->t_state &= ~TS_RCOLL; 16727502Sroot tp->t_rsel = 0; 16737502Sroot } 167412752Ssam if (tp->t_state & TS_ASYNC) 167535811Smarc gsignal(tp->t_pgid, SIGIO); 16767502Sroot wakeup((caddr_t)&tp->t_rawq); 16777502Sroot } 167835811Smarc 167935811Smarc /* 168035811Smarc * set tty hi and low water marks 168135811Smarc * 168235811Smarc * Try to arrange the dynamics so there's about one second 168335811Smarc * from hi to low water. 168435811Smarc * 168535811Smarc */ 168635811Smarc ttsetwater(tp) 168735811Smarc struct tty *tp; 168835811Smarc { 168935811Smarc register cps = tp->t_ospeed / 10; 169035811Smarc register x; 169135811Smarc 169235811Smarc #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 169335811Smarc tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 169435811Smarc x += cps; 169535811Smarc x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 169635811Smarc tp->t_hiwat = roundup(x, CBSIZE); 169735811Smarc #undef clamp 169835811Smarc } 169935811Smarc 170035811Smarc ttspeedtab(speed, table) 170135811Smarc struct speedtab table[]; 170235811Smarc { 170335811Smarc register int i; 170435811Smarc 170535811Smarc for (i = 0; table[i].sp_speed != -1; i++) 170635811Smarc if (table[i].sp_speed == speed) 170735811Smarc return(table[i].sp_code); 170835811Smarc return(-1); 170935811Smarc } 1710*39407Smarc 1711*39407Smarc /* 1712*39407Smarc * (^T) 1713*39407Smarc * Report on state of foreground process group. 1714*39407Smarc */ 1715*39407Smarc ttyinfo(tp) 1716*39407Smarc struct tty *tp; 1717*39407Smarc { 1718*39407Smarc register struct proc *p; 1719*39407Smarc struct pgrp *pg = pgfind(tp->t_pgid); 1720*39407Smarc 1721*39407Smarc if (ttycheckoutq(tp,0) == 0) 1722*39407Smarc return; 1723*39407Smarc if (pg == NULL) 1724*39407Smarc ttyprintf(tp, "kernel: no foreground process group\n"); 1725*39407Smarc else if ((p = pg->pg_mem) == NULL) 1726*39407Smarc ttyprintf(tp, "kernel: empty process group: %d\n", 1727*39407Smarc tp->t_pgid); 1728*39407Smarc else { 1729*39407Smarc int i = 0; 1730*39407Smarc for (; p != NULL; p = p->p_pgrpnxt) { 1731*39407Smarc ttyprintf(tp, 1732*39407Smarc "kernel: pid: %d state: %x wchan: %x ticks: %d\n", 1733*39407Smarc p->p_pid, p->p_stat, p->p_wchan, p->p_cpticks); 1734*39407Smarc if (++i > 6) { 1735*39407Smarc ttyprintf(tp, "kernel: more...\n"); 1736*39407Smarc break; 1737*39407Smarc } 1738*39407Smarc } 1739*39407Smarc } 1740*39407Smarc } 1741*39407Smarc 1742*39407Smarc #define TOTTY 0x2 /* XXX should be in header */ 1743*39407Smarc /*VARARGS2*/ 1744*39407Smarc ttyprintf(tp, fmt, x1) 1745*39407Smarc register struct tty *tp; 1746*39407Smarc char *fmt; 1747*39407Smarc unsigned x1; 1748*39407Smarc { 1749*39407Smarc prf(fmt, &x1, TOTTY, tp); 1750*39407Smarc } 1751