1 /* tty_pty.c 4.18 82/03/11 */ 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 pt_flags; 32 int pt_gensym; 33 struct proc *pt_selr, *pt_selw; 34 int pt_send; 35 } pt_ioctl[NPTY]; 36 37 #define PF_RCOLL 0x01 38 #define PF_WCOLL 0x02 39 #define PF_NBIO 0x04 40 #define PF_PKT 0x08 /* packet mode */ 41 #define PF_STOPPED 0x10 /* user told stopped */ 42 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 43 #define PF_NOSTOP 0x40 44 45 /*ARGSUSED*/ 46 ptsopen(dev, flag) 47 dev_t dev; 48 { 49 register struct tty *tp; 50 51 if (minor(dev) >= NPTY) { 52 u.u_error = ENXIO; 53 return; 54 } 55 tp = &pt_tty[minor(dev)]; 56 if ((tp->t_state & TS_ISOPEN) == 0) { 57 ttychars(tp); /* Set up default chars */ 58 tp->t_flags = 0; /* No features (nor raw mode) */ 59 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) { 60 u.u_error = EBUSY; 61 return; 62 } 63 if (tp->t_oproc) /* Ctrlr still around. */ 64 tp->t_state |= TS_CARR_ON; 65 while ((tp->t_state & TS_CARR_ON) == 0) { 66 tp->t_state |= TS_WOPEN; 67 sleep((caddr_t)&tp->t_rawq, TTIPRI); 68 } 69 (*linesw[tp->t_line].l_open)(dev, tp); 70 } 71 72 ptsclose(dev) 73 dev_t dev; 74 { 75 register struct tty *tp; 76 77 tp = &pt_tty[minor(dev)]; 78 (*linesw[tp->t_line].l_close)(tp); 79 } 80 81 ptsread(dev) 82 dev_t dev; 83 { 84 register struct tty *tp = &pt_tty[minor(dev)]; 85 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 86 87 again: 88 if (pti->pt_flags & PF_REMOTE) { 89 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 90 if (u.u_signal[SIGTTIN] == SIG_IGN || 91 u.u_signal[SIGTTIN] == SIG_HOLD || 92 /* 93 (u.u_procp->p_flag&SDETACH) || 94 */ 95 u.u_procp->p_flag&SVFORK) 96 return; 97 gsignal(u.u_procp->p_pgrp, SIGTTIN); 98 sleep((caddr_t)&lbolt, TTIPRI); 99 } 100 if (tp->t_rawq.c_cc == 0) { 101 if (tp->t_state & TS_NBIO) { 102 u.u_error = EWOULDBLOCK; 103 return; 104 } 105 sleep((caddr_t)&tp->t_rawq, TTIPRI); 106 goto again; 107 } 108 while (tp->t_rawq.c_cc > 1 && passc(getc(&tp->t_rawq)) >= 0) 109 ; 110 if (tp->t_rawq.c_cc == 1) 111 (void) getc(&tp->t_rawq); 112 if (tp->t_rawq.c_cc) 113 return; 114 } else 115 if (tp->t_oproc) 116 (*linesw[tp->t_line].l_read)(tp); 117 wakeup((caddr_t)&tp->t_rawq.c_cf); 118 if (pti->pt_selw) { 119 selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 120 pti->pt_selw = 0; 121 pti->pt_flags &= ~PF_WCOLL; 122 } 123 } 124 125 /* 126 * Write to pseudo-tty. 127 * Wakeups of controlling tty will happen 128 * indirectly, when tty driver calls ptsstart. 129 */ 130 ptswrite(dev) 131 dev_t dev; 132 { 133 register struct tty *tp; 134 135 tp = &pt_tty[minor(dev)]; 136 if (tp->t_oproc) 137 (*linesw[tp->t_line].l_write)(tp); 138 } 139 140 /* 141 * Start output on pseudo-tty. 142 * Wake up process selecting or sleeping for input from controlling tty. 143 */ 144 ptsstart(tp) 145 struct tty *tp; 146 { 147 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 148 149 if (tp->t_state & TS_TTSTOP) 150 return; 151 if (pti->pt_flags & PF_STOPPED) { 152 pti->pt_flags &= ~PF_STOPPED; 153 pti->pt_send = TIOCPKT_START; 154 } 155 ptcwakeup(tp); 156 } 157 158 ptcwakeup(tp) 159 struct tty *tp; 160 { 161 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 162 163 if (pti->pt_selr) { 164 selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 165 pti->pt_selr = 0; 166 pti->pt_flags &= ~PF_RCOLL; 167 } 168 wakeup((caddr_t)&tp->t_outq.c_cf); 169 } 170 171 /*ARGSUSED*/ 172 ptcopen(dev, flag) 173 dev_t dev; 174 int flag; 175 { 176 register struct tty *tp; 177 struct pt_ioctl *pti; 178 179 if (minor(dev) >= NPTY) { 180 u.u_error = ENXIO; 181 return; 182 } 183 tp = &pt_tty[minor(dev)]; 184 if (tp->t_oproc) { 185 u.u_error = EIO; 186 return; 187 } 188 tp->t_oproc = ptsstart; 189 if (tp->t_state & TS_WOPEN) 190 wakeup((caddr_t)&tp->t_rawq); 191 tp->t_state |= TS_CARR_ON; 192 pti = &pt_ioctl[minor(dev)]; 193 pti->pt_flags = 0; 194 pti->pt_send = 0; 195 } 196 197 ptcclose(dev) 198 dev_t dev; 199 { 200 register struct tty *tp; 201 202 tp = &pt_tty[minor(dev)]; 203 if (tp->t_state & TS_ISOPEN) 204 gsignal(tp->t_pgrp, SIGHUP); 205 tp->t_state &= ~TS_CARR_ON; /* virtual carrier gone */ 206 flushtty(tp, FREAD|FWRITE); 207 tp->t_oproc = 0; /* mark closed */ 208 } 209 210 ptcread(dev) 211 dev_t dev; 212 { 213 register struct tty *tp; 214 struct pt_ioctl *pti; 215 216 tp = &pt_tty[minor(dev)]; 217 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 218 return; 219 pti = &pt_ioctl[minor(dev)]; 220 if (pti->pt_flags & PF_PKT) { 221 if (pti->pt_send) { 222 passc(pti->pt_send); 223 pti->pt_send = 0; 224 return; 225 } 226 passc(0); 227 } 228 while (tp->t_outq.c_cc == 0 || (tp->t_state&TS_TTSTOP)) { 229 if (pti->pt_flags&PF_NBIO) { 230 u.u_error = EWOULDBLOCK; 231 return; 232 } 233 sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 234 } 235 while (tp->t_outq.c_cc && passc(getc(&tp->t_outq)) >= 0) 236 ; 237 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 238 if (tp->t_state&TS_ASLEEP) { 239 tp->t_state &= ~TS_ASLEEP; 240 wakeup((caddr_t)&tp->t_outq); 241 } 242 if (tp->t_wsel) { 243 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 244 tp->t_wsel = 0; 245 tp->t_state &= ~TS_WCOLL; 246 } 247 } 248 } 249 250 ptsstop(tp, flush) 251 register struct tty *tp; 252 int flush; 253 { 254 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 255 256 /* note: FLUSHREAD and FLUSHWRITE already ok */ 257 if (flush == 0) { 258 flush = TIOCPKT_STOP; 259 pti->pt_flags |= PF_STOPPED; 260 } else { 261 pti->pt_flags &= ~PF_STOPPED; 262 } 263 pti->pt_send |= flush; 264 ptcwakeup(tp); 265 } 266 267 ptcselect(dev, rw) 268 dev_t dev; 269 int rw; 270 { 271 register struct tty *tp = &pt_tty[minor(dev)]; 272 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 273 struct proc *p; 274 int s; 275 276 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 277 return (1); 278 s = spl5(); 279 switch (rw) { 280 281 case FREAD: 282 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 283 splx(s); 284 return (1); 285 } 286 if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 287 pti->pt_flags |= PF_RCOLL; 288 else 289 pti->pt_selr = u.u_procp; 290 break; 291 292 case FWRITE: 293 if ((pti->pt_flags & PF_REMOTE) == 0 || tp->t_rawq.c_cc == 0) { 294 splx(s); 295 return (1); 296 } 297 if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 298 pti->pt_flags |= PF_WCOLL; 299 else 300 pti->pt_selw = u.u_procp; 301 break; 302 } 303 splx(s); 304 return (0); 305 } 306 307 ptcwrite(dev) 308 dev_t dev; 309 { 310 register struct tty *tp; 311 register char *cp, *ce; 312 register int cc; 313 char locbuf[BUFSIZ]; 314 int cnt = 0; 315 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 316 317 tp = &pt_tty[minor(dev)]; 318 if ((tp->t_state&(TS_CARR_ON|TS_ISOPEN)) == 0) 319 return; 320 do { 321 cc = MIN(u.u_count, BUFSIZ); 322 cp = locbuf; 323 iomove(cp, (unsigned)cc, B_WRITE); 324 if (u.u_error) 325 break; 326 ce = cp + cc; 327 again: 328 if (pti->pt_flags & PF_REMOTE) { 329 if (tp->t_rawq.c_cc) { 330 if (pti->pt_flags & PF_NBIO) { 331 u.u_count += ce - cp; 332 u.u_error = EWOULDBLOCK; 333 return; 334 } 335 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 336 goto again; 337 } 338 b_to_q(cp, cc, &tp->t_rawq); 339 putc(0, &tp->t_rawq); 340 wakeup((caddr_t)&tp->t_rawq); 341 return; 342 } 343 while (cp < ce) { 344 while (tp->t_delct && tp->t_rawq.c_cc >= TTYHOG - 2) { 345 wakeup((caddr_t)&tp->t_rawq); 346 if (tp->t_state & TS_NBIO) { 347 u.u_count += ce - cp; 348 if (cnt == 0) 349 u.u_error = EWOULDBLOCK; 350 return; 351 } 352 /* Better than just flushing it! */ 353 /* Wait for something to be read */ 354 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 355 goto again; 356 } 357 (*linesw[tp->t_line].l_rint)(*cp++, tp); 358 cnt++; 359 } 360 } while (u.u_count); 361 } 362 363 /*ARGSUSED*/ 364 ptyioctl(dev, cmd, addr, flag) 365 caddr_t addr; 366 dev_t dev; 367 { 368 register struct tty *tp = &pt_tty[minor(dev)]; 369 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 370 371 /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 372 if (cdevsw[major(dev)].d_open == ptcopen) { 373 if (cmd == TIOCPKT) { 374 int packet; 375 if (copyin((caddr_t)addr, &packet, sizeof (packet))) { 376 u.u_error = EFAULT; 377 return; 378 } 379 if (packet) 380 pti->pt_flags |= PF_PKT; 381 else 382 pti->pt_flags &= ~PF_PKT; 383 return; 384 } 385 if (cmd == TIOCREMOTE) { 386 int remote; 387 if (copyin((caddr_t)addr, &remote, sizeof (remote))) { 388 u.u_error = EFAULT; 389 return; 390 } 391 if (remote) 392 pti->pt_flags |= PF_REMOTE; 393 else 394 pti->pt_flags &= ~PF_REMOTE; 395 flushtty(tp, FREAD|FWRITE); 396 return; 397 } 398 if (cmd == FIONBIO) { 399 int nbio; 400 if (copyin(addr, &nbio, sizeof (nbio))) { 401 u.u_error = EFAULT; 402 return; 403 } 404 if (nbio) 405 pti->pt_flags |= PF_NBIO; 406 else 407 pti->pt_flags &= ~PF_NBIO; 408 return; 409 } 410 if (cmd == TIOCSETP) 411 while (getc(&tp->t_outq) >= 0); 412 } 413 if (ttioctl(tp, cmd, addr, dev) == 0) 414 u.u_error = ENOTTY; 415 { int stop = (tp->t_un.t_chr.t_stopc == ('s'&037) && 416 tp->t_un.t_chr.t_startc == ('q'&037)); 417 if (pti->pt_flags & PF_NOSTOP) { 418 if (stop) { 419 pti->pt_send &= TIOCPKT_NOSTOP; 420 pti->pt_send |= TIOCPKT_DOSTOP; 421 pti->pt_flags &= ~PF_NOSTOP; 422 ptcwakeup(tp); 423 } 424 } else { 425 if (stop == 0) { 426 pti->pt_send &= ~TIOCPKT_DOSTOP; 427 pti->pt_send |= TIOCPKT_NOSTOP; 428 pti->pt_flags |= PF_NOSTOP; 429 ptcwakeup(tp); 430 } 431 } 432 } 433 } 434 #endif 435