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