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