1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)tty_pty.c 6.17 (Berkeley) 11/14/85 7 */ 8 9 /* 10 * Pseudo-teletype Driver 11 * (Actually two drivers, requiring two entries in 'cdevsw') 12 */ 13 #include "pty.h" 14 15 #if NPTY > 0 16 #include "param.h" 17 #include "systm.h" 18 #include "ioctl.h" 19 #include "tty.h" 20 #include "dir.h" 21 #include "user.h" 22 #include "conf.h" 23 #include "file.h" 24 #include "proc.h" 25 #include "uio.h" 26 #include "kernel.h" 27 28 #if NPTY == 1 29 #undef NPTY 30 #define NPTY 32 /* crude XXX */ 31 #endif 32 33 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 34 35 /* 36 * pts == /dev/tty[pqrs]? 37 * ptc == /dev/pty[pqrs]? 38 */ 39 struct tty pt_tty[NPTY]; 40 struct pt_ioctl { 41 int pt_flags; 42 int pt_gensym; 43 struct proc *pt_selr, *pt_selw; 44 u_char pt_send; 45 u_char pt_ucntl; 46 } pt_ioctl[NPTY]; 47 int npty = NPTY; /* for pstat -t */ 48 49 #define PF_RCOLL 0x01 50 #define PF_WCOLL 0x02 51 #define PF_NBIO 0x04 52 #define PF_PKT 0x08 /* packet mode */ 53 #define PF_STOPPED 0x10 /* user told stopped */ 54 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 55 #define PF_NOSTOP 0x40 56 #define PF_UCNTL 0x80 /* user control mode */ 57 58 /*ARGSUSED*/ 59 ptsopen(dev, flag) 60 dev_t dev; 61 { 62 register struct tty *tp; 63 int error; 64 65 #ifdef lint 66 npty = npty; 67 #endif 68 if (minor(dev) >= NPTY) 69 return (ENXIO); 70 tp = &pt_tty[minor(dev)]; 71 if ((tp->t_state & TS_ISOPEN) == 0) { 72 ttychars(tp); /* Set up default chars */ 73 tp->t_ispeed = tp->t_ospeed = EXTB; 74 tp->t_flags = 0; /* No features (nor raw mode) */ 75 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 76 return (EBUSY); 77 if (tp->t_oproc) /* Ctrlr still around. */ 78 tp->t_state |= TS_CARR_ON; 79 while ((tp->t_state & TS_CARR_ON) == 0) { 80 tp->t_state |= TS_WOPEN; 81 sleep((caddr_t)&tp->t_rawq, TTIPRI); 82 } 83 error = (*linesw[tp->t_line].l_open)(dev, tp); 84 ptcwakeup(tp, FREAD|FWRITE); 85 return (error); 86 } 87 88 ptsclose(dev) 89 dev_t dev; 90 { 91 register struct tty *tp; 92 93 tp = &pt_tty[minor(dev)]; 94 (*linesw[tp->t_line].l_close)(tp); 95 ttyclose(tp); 96 ptcwakeup(tp, FREAD|FWRITE); 97 } 98 99 ptsread(dev, uio) 100 dev_t dev; 101 struct uio *uio; 102 { 103 register struct tty *tp = &pt_tty[minor(dev)]; 104 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 105 int error = 0; 106 107 again: 108 if (pti->pt_flags & PF_REMOTE) { 109 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 110 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 111 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 112 u.u_procp->p_flag&SVFORK) 113 return (EIO); 114 gsignal(u.u_procp->p_pgrp, SIGTTIN); 115 sleep((caddr_t)&lbolt, TTIPRI); 116 } 117 if (tp->t_canq.c_cc == 0) { 118 if (tp->t_state & TS_NBIO) 119 return (EWOULDBLOCK); 120 sleep((caddr_t)&tp->t_canq, TTIPRI); 121 goto again; 122 } 123 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 124 if (ureadc(getc(&tp->t_canq), uio) < 0) { 125 error = EFAULT; 126 break; 127 } 128 if (tp->t_canq.c_cc == 1) 129 (void) getc(&tp->t_canq); 130 if (tp->t_canq.c_cc) 131 return (error); 132 } else 133 if (tp->t_oproc) 134 error = (*linesw[tp->t_line].l_read)(tp, uio); 135 ptcwakeup(tp, FWRITE); 136 return (error); 137 } 138 139 /* 140 * Write to pseudo-tty. 141 * Wakeups of controlling tty will happen 142 * indirectly, when tty driver calls ptsstart. 143 */ 144 ptswrite(dev, uio) 145 dev_t dev; 146 struct uio *uio; 147 { 148 register struct tty *tp; 149 150 tp = &pt_tty[minor(dev)]; 151 if (tp->t_oproc == 0) 152 return (EIO); 153 return ((*linesw[tp->t_line].l_write)(tp, uio)); 154 } 155 156 /* 157 * Start output on pseudo-tty. 158 * Wake up process selecting or sleeping for input from controlling tty. 159 */ 160 ptsstart(tp) 161 struct tty *tp; 162 { 163 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 164 165 if (tp->t_state & TS_TTSTOP) 166 return; 167 if (pti->pt_flags & PF_STOPPED) { 168 pti->pt_flags &= ~PF_STOPPED; 169 pti->pt_send = TIOCPKT_START; 170 } 171 ptcwakeup(tp, FREAD); 172 } 173 174 ptcwakeup(tp, flag) 175 struct tty *tp; 176 { 177 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 178 179 if (flag & FREAD) { 180 if (pti->pt_selr) { 181 selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 182 pti->pt_selr = 0; 183 pti->pt_flags &= ~PF_RCOLL; 184 } 185 wakeup((caddr_t)&tp->t_outq.c_cf); 186 } 187 if (flag & FWRITE) { 188 if (pti->pt_selw) { 189 selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 190 pti->pt_selw = 0; 191 pti->pt_flags &= ~PF_WCOLL; 192 } 193 wakeup((caddr_t)&tp->t_rawq.c_cf); 194 } 195 } 196 197 /*ARGSUSED*/ 198 ptcopen(dev, flag) 199 dev_t dev; 200 int flag; 201 { 202 register struct tty *tp; 203 struct pt_ioctl *pti; 204 205 if (minor(dev) >= NPTY) 206 return (ENXIO); 207 tp = &pt_tty[minor(dev)]; 208 if (tp->t_oproc) 209 return (EIO); 210 tp->t_oproc = ptsstart; 211 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 212 tp->t_state |= TS_CARR_ON; 213 pti = &pt_ioctl[minor(dev)]; 214 pti->pt_flags = 0; 215 pti->pt_send = 0; 216 pti->pt_ucntl = 0; 217 return (0); 218 } 219 220 ptcclose(dev) 221 dev_t dev; 222 { 223 register struct tty *tp; 224 225 tp = &pt_tty[minor(dev)]; 226 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 227 tp->t_oproc = 0; /* mark closed */ 228 } 229 230 ptcread(dev, uio) 231 dev_t dev; 232 struct uio *uio; 233 { 234 register struct tty *tp = &pt_tty[minor(dev)]; 235 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 236 char buf[BUFSIZ]; 237 int error = 0, cc; 238 239 /* 240 * We want to block until the slave 241 * is open, and there's something to read; 242 * but if we lost the slave or we're NBIO, 243 * then return the appropriate error instead. 244 */ 245 for (;;) { 246 if (tp->t_state&TS_ISOPEN) { 247 if (pti->pt_flags&PF_PKT && pti->pt_send) { 248 error = ureadc(pti->pt_send, uio); 249 if (error) 250 return (error); 251 pti->pt_send = 0; 252 return (0); 253 } 254 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 255 error = ureadc(pti->pt_ucntl, uio); 256 if (error) 257 return (error); 258 pti->pt_ucntl = 0; 259 return (0); 260 } 261 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 262 break; 263 } 264 if ((tp->t_state&TS_CARR_ON) == 0) 265 return (EIO); 266 if (pti->pt_flags&PF_NBIO) 267 return (EWOULDBLOCK); 268 sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 269 } 270 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 271 error = ureadc(0, uio); 272 while (uio->uio_resid > 0 && error == 0) { 273 cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 274 if (cc <= 0) 275 break; 276 error = uiomove(buf, cc, UIO_READ, uio); 277 } 278 if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 279 if (tp->t_state&TS_ASLEEP) { 280 tp->t_state &= ~TS_ASLEEP; 281 wakeup((caddr_t)&tp->t_outq); 282 } 283 if (tp->t_wsel) { 284 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 285 tp->t_wsel = 0; 286 tp->t_state &= ~TS_WCOLL; 287 } 288 } 289 return (error); 290 } 291 292 ptsstop(tp, flush) 293 register struct tty *tp; 294 int flush; 295 { 296 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 297 int flag; 298 299 /* note: FLUSHREAD and FLUSHWRITE already ok */ 300 if (flush == 0) { 301 flush = TIOCPKT_STOP; 302 pti->pt_flags |= PF_STOPPED; 303 } else 304 pti->pt_flags &= ~PF_STOPPED; 305 pti->pt_send |= flush; 306 /* change of perspective */ 307 flag = 0; 308 if (flush & FREAD) 309 flag |= FWRITE; 310 if (flush & FWRITE) 311 flag |= FREAD; 312 ptcwakeup(tp, flag); 313 } 314 315 ptcselect(dev, rw) 316 dev_t dev; 317 int rw; 318 { 319 register struct tty *tp = &pt_tty[minor(dev)]; 320 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 321 struct proc *p; 322 int s; 323 324 if ((tp->t_state&TS_CARR_ON) == 0) 325 return (1); 326 s = spl5(); 327 switch (rw) { 328 329 case FREAD: 330 if ((tp->t_state&TS_ISOPEN) && 331 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 332 splx(s); 333 return (1); 334 } 335 /* FALLTHROUGH */ 336 337 case 0: /* exceptional */ 338 if ((tp->t_state&TS_ISOPEN) && 339 (pti->pt_flags&PF_PKT && pti->pt_send || 340 pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) { 341 splx(s); 342 return (1); 343 } 344 if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 345 pti->pt_flags |= PF_RCOLL; 346 else 347 pti->pt_selr = u.u_procp; 348 break; 349 350 351 case FWRITE: 352 if ((tp->t_state&TS_ISOPEN) && 353 ((pti->pt_flags&PF_REMOTE) == 0 || tp->t_canq.c_cc == 0)) { 354 splx(s); 355 return (1); 356 } 357 if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 358 pti->pt_flags |= PF_WCOLL; 359 else 360 pti->pt_selw = u.u_procp; 361 break; 362 363 } 364 splx(s); 365 return (0); 366 } 367 368 ptcwrite(dev, uio) 369 dev_t dev; 370 register struct uio *uio; 371 { 372 register struct tty *tp = &pt_tty[minor(dev)]; 373 register struct iovec *iov; 374 register char *cp; 375 register int cc = 0; 376 char locbuf[BUFSIZ]; 377 int cnt = 0; 378 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 379 int error = 0; 380 381 again: 382 if ((tp->t_state&TS_ISOPEN) == 0) 383 goto block; 384 if (pti->pt_flags & PF_REMOTE) { 385 if (tp->t_canq.c_cc) 386 goto block; 387 while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 388 iov = uio->uio_iov; 389 if (iov->iov_len == 0) { 390 uio->uio_iovcnt--; 391 uio->uio_iov++; 392 continue; 393 } 394 if (cc == 0) { 395 cc = MIN(iov->iov_len, BUFSIZ); 396 cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 397 cp = locbuf; 398 error = uiomove(cp, cc, UIO_WRITE, uio); 399 if (error) 400 return (error); 401 /* check again for safety */ 402 if ((tp->t_state&TS_ISOPEN) == 0) 403 return (EIO); 404 } 405 if (cc) 406 (void) b_to_q(cp, cc, &tp->t_canq); 407 cc = 0; 408 } 409 (void) putc(0, &tp->t_canq); 410 ttwakeup(tp); 411 wakeup((caddr_t)&tp->t_canq); 412 return (0); 413 } 414 while (uio->uio_iovcnt > 0) { 415 iov = uio->uio_iov; 416 if (cc == 0) { 417 if (iov->iov_len == 0) { 418 uio->uio_iovcnt--; 419 uio->uio_iov++; 420 continue; 421 } 422 cc = MIN(iov->iov_len, BUFSIZ); 423 cp = locbuf; 424 error = uiomove(cp, cc, UIO_WRITE, uio); 425 if (error) 426 return (error); 427 /* check again for safety */ 428 if ((tp->t_state&TS_ISOPEN) == 0) 429 return (EIO); 430 } 431 while (cc > 0) { 432 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 433 (tp->t_canq.c_cc > 0)) { 434 wakeup((caddr_t)&tp->t_rawq); 435 goto block; 436 } 437 (*linesw[tp->t_line].l_rint)(*cp++, tp); 438 cnt++; 439 cc--; 440 } 441 cc = 0; 442 } 443 return (0); 444 block: 445 /* 446 * Come here to wait for slave to open, for space 447 * in outq, or space in rawq. 448 */ 449 if ((tp->t_state&TS_CARR_ON) == 0) 450 return (EIO); 451 if (pti->pt_flags & PF_NBIO) { 452 iov->iov_base -= cc; 453 iov->iov_len += cc; 454 uio->uio_resid += cc; 455 uio->uio_offset -= cc; 456 if (cnt == 0) 457 return (EWOULDBLOCK); 458 return (0); 459 } 460 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 461 goto again; 462 } 463 464 /*ARGSUSED*/ 465 ptyioctl(dev, cmd, data, flag) 466 caddr_t data; 467 dev_t dev; 468 { 469 register struct tty *tp = &pt_tty[minor(dev)]; 470 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 471 int stop, error; 472 extern ttyinput(); 473 474 /* 475 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 476 * ttywflush(tp) will hang if there are characters in the outq. 477 */ 478 if (cdevsw[major(dev)].d_open == ptcopen) 479 switch (cmd) { 480 481 case TIOCPKT: 482 if (*(int *)data) { 483 if (pti->pt_flags & PF_UCNTL) 484 return (EINVAL); 485 pti->pt_flags |= PF_PKT; 486 } else 487 pti->pt_flags &= ~PF_PKT; 488 return (0); 489 490 case TIOCUCNTL: 491 if (*(int *)data) { 492 if (pti->pt_flags & PF_PKT) 493 return (EINVAL); 494 pti->pt_flags |= PF_UCNTL; 495 } else 496 pti->pt_flags &= ~PF_UCNTL; 497 return (0); 498 499 case TIOCREMOTE: 500 if (*(int *)data) 501 pti->pt_flags |= PF_REMOTE; 502 else 503 pti->pt_flags &= ~PF_REMOTE; 504 ttyflush(tp, FREAD|FWRITE); 505 return (0); 506 507 case FIONBIO: 508 if (*(int *)data) 509 pti->pt_flags |= PF_NBIO; 510 else 511 pti->pt_flags &= ~PF_NBIO; 512 return (0); 513 514 case TIOCSETP: 515 case TIOCSETN: 516 case TIOCSETD: 517 while (getc(&tp->t_outq) >= 0) 518 ; 519 break; 520 } 521 error = ttioctl(tp, cmd, data, flag); 522 /* 523 * Since we use the tty queues internally, 524 * pty's can't be switched to disciplines which overwrite 525 * the queues. We can't tell anything about the discipline 526 * from here... 527 */ 528 if (linesw[tp->t_line].l_rint != ttyinput) { 529 (*linesw[tp->t_line].l_close)(tp); 530 tp->t_line = 0; 531 (void)(*linesw[tp->t_line].l_open)(dev, tp); 532 error = ENOTTY; 533 } 534 if (error < 0) { 535 if (pti->pt_flags & PF_UCNTL && 536 (cmd & ~0xff) == _IO(u,0)) { 537 if (cmd & 0xff) { 538 pti->pt_ucntl = (u_char)cmd; 539 ptcwakeup(tp, FREAD); 540 } 541 return (0); 542 } 543 error = ENOTTY; 544 } 545 stop = (tp->t_flags & RAW) == 0 && 546 tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); 547 if (pti->pt_flags & PF_NOSTOP) { 548 if (stop) { 549 pti->pt_send &= ~TIOCPKT_NOSTOP; 550 pti->pt_send |= TIOCPKT_DOSTOP; 551 pti->pt_flags &= ~PF_NOSTOP; 552 ptcwakeup(tp, FREAD); 553 } 554 } else { 555 if (!stop) { 556 pti->pt_send &= ~TIOCPKT_DOSTOP; 557 pti->pt_send |= TIOCPKT_NOSTOP; 558 pti->pt_flags |= PF_NOSTOP; 559 ptcwakeup(tp, FREAD); 560 } 561 } 562 return (error); 563 } 564 #endif 565