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