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