1 /* tty_pty.c 4.12 82/01/14 */ 2 3 /* 4 * Pseudo-teletype Driver 5 * (Actually two drivers, requiring two entries in 'cdevsw') 6 */ 7 #include "pty.h" 8 9 #if NPTY > 0 10 #include "../h/param.h" 11 #include "../h/systm.h" 12 #include "../h/tty.h" 13 #include "../h/dir.h" 14 #include "../h/user.h" 15 #include "../h/conf.h" 16 #include "../h/buf.h" 17 #include "../h/file.h" 18 #include "../h/proc.h" 19 #undef NPTY 20 21 #define NPTY 16 22 23 #define BUFSIZ 100 /* Chunk size iomoved from user */ 24 25 /* 26 * pts == /dev/tty[pP]? 27 * ptc == /dev/ptp[pP]? 28 */ 29 struct tty pt_tty[NPTY]; 30 struct pt_ioctl { 31 int pti_flags; 32 struct clist pti_ioctl, pti_ioans; 33 int pti_gensym; 34 struct proc *pti_selr, *pti_selw; 35 } pt_ioctl[NPTY]; 36 37 #define PTCRCOLL 0x01 38 #define PTCWCOLL 0x02 39 40 /*ARGSUSED*/ 41 ptsopen(dev, flag) 42 dev_t dev; 43 { 44 register struct tty *tp; 45 46 if (minor(dev) >= NPTY) { 47 u.u_error = ENXIO; 48 return; 49 } 50 tp = &pt_tty[minor(dev)]; 51 if ((tp->t_state & TS_ISOPEN) == 0) { 52 ttychars(tp); /* Set up default chars */ 53 tp->t_flags = 0; /* No features (nor raw mode) */ 54 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) { 55 u.u_error = EBUSY; 56 return; 57 } 58 if (tp->t_oproc) /* Ctrlr still around. */ 59 tp->t_state |= TS_CARR_ON; 60 while ((tp->t_state & TS_CARR_ON) == 0) { 61 tp->t_state |= TS_WOPEN; 62 sleep((caddr_t)&tp->t_rawq, TTIPRI); 63 } 64 (*linesw[tp->t_line].l_open)(dev, tp); 65 } 66 67 ptsclose(dev) 68 dev_t dev; 69 { 70 register struct tty *tp; 71 72 tp = &pt_tty[minor(dev)]; 73 (*linesw[tp->t_line].l_close)(tp); 74 } 75 76 ptsread(dev) 77 dev_t dev; 78 { 79 register struct tty *tp; 80 register struct pt_ioctl *pti; 81 82 tp = &pt_tty[minor(dev)]; 83 if (tp->t_oproc) { 84 (*linesw[tp->t_line].l_read)(tp); 85 wakeup((caddr_t)&tp->t_rawq.c_cf); 86 if (tp->t_rawq.c_cc < TTYHOG/2 && 87 (pti = &pt_ioctl[minor(tp->t_dev)])->pti_selw) { 88 selwakeup(pti->pti_selw, pti->pti_flags & PTCWCOLL); 89 pti->pti_selw = 0; 90 pti->pti_flags &= ~PTCWCOLL; 91 } 92 } 93 } 94 95 /* 96 * Write to pseudo-tty. 97 * Wakeups of controlling tty will happen 98 * indirectly, when tty driver calls ptsstart. 99 */ 100 ptswrite(dev) 101 dev_t dev; 102 { 103 register struct tty *tp; 104 105 tp = &pt_tty[minor(dev)]; 106 if (tp->t_oproc) 107 (*linesw[tp->t_line].l_write)(tp); 108 } 109 110 /* 111 * Start output on pseudo-tty. 112 * Wake up process selecting or sleeping for input from controlling tty. 113 */ 114 ptsstart(tp) 115 struct tty *tp; 116 { 117 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 118 119 if (tp->t_state & TS_TTSTOP) 120 return; 121 if (pti->pti_selr) { 122 selwakeup(pti->pti_selr, pti->pti_flags & PTCRCOLL); 123 pti->pti_selr = 0; 124 pti->pti_flags &= ~PTCRCOLL; 125 } 126 wakeup((caddr_t)&tp->t_outq.c_cf); 127 } 128 129 /*ARGSUSED*/ 130 ptcopen(dev, flag) 131 dev_t dev; 132 int flag; 133 { 134 register struct tty *tp; 135 136 if (minor(dev) >= NPTY) { 137 u.u_error = ENXIO; 138 return; 139 } 140 tp = &pt_tty[minor(dev)]; 141 if (tp->t_oproc) { 142 u.u_error = EIO; 143 return; 144 } 145 tp->t_oproc = ptsstart; 146 if (tp->t_state & TS_WOPEN) 147 wakeup((caddr_t)&tp->t_rawq); 148 tp->t_state |= TS_CARR_ON; 149 } 150 151 ptcclose(dev) 152 dev_t dev; 153 { 154 register struct tty *tp; 155 156 tp = &pt_tty[minor(dev)]; 157 if (tp->t_state & TS_ISOPEN) 158 gsignal(tp->t_pgrp, SIGHUP); 159 tp->t_state &= ~TS_CARR_ON; /* virtual carrier gone */ 160 flushtty(tp, FREAD|FWRITE); 161 tp->t_oproc = 0; /* mark closed */ 162 } 163 164 ptcread(dev) 165 dev_t dev; 166 { 167 register struct tty *tp; 168 169 tp = &pt_tty[minor(dev)]; 170 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 171 return; 172 while (tp->t_outq.c_cc == 0 || (tp->t_state&TS_TTSTOP)) 173 sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 174 while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0) 175 ; 176 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 177 if (tp->t_state&TS_ASLEEP) { 178 tp->t_state &= ~TS_ASLEEP; 179 wakeup((caddr_t)&tp->t_outq); 180 } 181 if (tp->t_wsel) { 182 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 183 tp->t_wsel = 0; 184 tp->t_state &= ~TS_WCOLL; 185 } 186 } 187 } 188 189 ptcselect(dev, rw) 190 dev_t dev; 191 int rw; 192 { 193 register struct tty *tp = &pt_tty[minor(dev)]; 194 struct pt_ioctl *pti; 195 struct proc *p; 196 197 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 198 return (1); 199 switch (rw) { 200 201 case FREAD: 202 if (tp->t_outq.c_cc) 203 return (1); 204 pti = &pt_ioctl[minor(dev)]; 205 if ((p = pti->pti_selr) && p->p_wchan == (caddr_t)&selwait) 206 pti->pti_flags |= PTCRCOLL; 207 else 208 pti->pti_selr = u.u_procp; 209 return (0); 210 211 case FWRITE: 212 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG/2) 213 return (1); 214 pti = &pt_ioctl[minor(dev)]; 215 if ((p = pti->pti_selw) && p->p_wchan == (caddr_t)&selwait) 216 pti->pti_flags |= PTCWCOLL; 217 else 218 pti->pti_selw = u.u_procp; 219 } 220 } 221 222 ptcwrite(dev) 223 dev_t dev; 224 { 225 register struct tty *tp; 226 register char *cp, *ce; 227 register int cc; 228 char locbuf[BUFSIZ]; 229 int cnt = 0; 230 231 tp = &pt_tty[minor(dev)]; 232 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 233 return; 234 while (u.u_count) { 235 cc = MIN(u.u_count, BUFSIZ); 236 cp = locbuf; 237 iomove(cp, (unsigned)cc, B_WRITE); 238 if (u.u_error) 239 break; 240 ce = cp + cc; 241 while (cp < ce) { 242 while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { 243 wakeup((caddr_t)&tp->t_rawq); 244 if (tp->t_state & TS_NBIO) { 245 u.u_count += ce - cp; 246 if (cnt == 0) 247 u.u_error = EWOULDBLOCK; 248 return; 249 } 250 /* Better than just flushing it! */ 251 /* Wait for something to be read */ 252 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 253 } 254 (*linesw[tp->t_line].l_rint)(*cp++, tp); 255 cnt++; 256 } 257 } 258 } 259 260 /*ARGSUSED*/ 261 ptyioctl(dev, cmd, addr, flag) 262 caddr_t addr; 263 dev_t dev; 264 { 265 register struct tty *tp; 266 267 tp = &pt_tty[minor(dev)]; 268 /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 269 if (cdevsw[major(dev)].d_open == ptcopen && cmd == TIOCSETP) 270 while (getc(&tp->t_outq) >= 0); 271 if (ttioctl(tp, cmd, addr, dev) == 0) 272 u.u_error = ENOTTY; 273 } 274 #endif 275