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