182 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 183 return (EBUSY); 184 if (tp->t_oproc) /* Ctrlr still around. */ 185 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 186 while ((tp->t_state & TS_CARR_ON) == 0) { 187 if (flag&FNONBLOCK) 188 break; 189 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 190 "ptsopn", 0); 191 if (error) 192 return (error); 193 } 194 error = (*linesw[tp->t_line].l_open)(dev, tp); 195 if (error == 0) 196 ptcwakeup(tp, FREAD|FWRITE); 197 return (error); 198} 199 200static int 201ptsclose(dev, flag, mode, p) 202 dev_t dev; 203 int flag, mode; 204 struct proc *p; 205{ 206 register struct tty *tp; 207 int err; 208 209 tp = &pt_tty[minor(dev)]; 210 err = (*linesw[tp->t_line].l_close)(tp, flag); 211 ptsstop(tp, FREAD|FWRITE); 212 (void) ttyclose(tp); 213 return (err); 214} 215 216static int 217ptsread(dev, uio, flag) 218 dev_t dev; 219 struct uio *uio; 220 int flag; 221{ 222 struct proc *p = curproc; 223 register struct tty *tp = &pt_tty[minor(dev)]; 224 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 225 int error = 0; 226 227again: 228 if (pti->pt_flags & PF_REMOTE) { 229 while (isbackground(p, tp)) { 230 if ((p->p_sigignore & sigmask(SIGTTIN)) || 231 (p->p_sigmask & sigmask(SIGTTIN)) || 232 p->p_pgrp->pg_jobc == 0 || 233 p->p_flag & P_PPWAIT) 234 return (EIO); 235 pgsignal(p->p_pgrp, SIGTTIN, 1); 236 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg", 237 0); 238 if (error) 239 return (error); 240 } 241 if (tp->t_canq.c_cc == 0) { 242 if (flag & IO_NDELAY) 243 return (EWOULDBLOCK); 244 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH, 245 "ptsin", 0); 246 if (error) 247 return (error); 248 goto again; 249 } 250 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 251 if (ureadc(getc(&tp->t_canq), uio) < 0) { 252 error = EFAULT; 253 break; 254 } 255 if (tp->t_canq.c_cc == 1) 256 (void) getc(&tp->t_canq); 257 if (tp->t_canq.c_cc) 258 return (error); 259 } else 260 if (tp->t_oproc) 261 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 262 ptcwakeup(tp, FWRITE); 263 return (error); 264} 265 266/* 267 * Write to pseudo-tty. 268 * Wakeups of controlling tty will happen 269 * indirectly, when tty driver calls ptsstart. 270 */ 271static int 272ptswrite(dev, uio, flag) 273 dev_t dev; 274 struct uio *uio; 275 int flag; 276{ 277 register struct tty *tp; 278 279 tp = &pt_tty[minor(dev)]; 280 if (tp->t_oproc == 0) 281 return (EIO); 282 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 283} 284 285/* 286 * Start output on pseudo-tty. 287 * Wake up process selecting or sleeping for input from controlling tty. 288 */ 289static void 290ptsstart(tp) 291 struct tty *tp; 292{ 293 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 294 295 if (tp->t_state & TS_TTSTOP) 296 return; 297 if (pti->pt_flags & PF_STOPPED) { 298 pti->pt_flags &= ~PF_STOPPED; 299 pti->pt_send = TIOCPKT_START; 300 } 301 ptcwakeup(tp, FREAD); 302} 303 304static void 305ptcwakeup(tp, flag) 306 struct tty *tp; 307 int flag; 308{ 309 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 310 311 if (flag & FREAD) { 312 selwakeup(&pti->pt_selr); 313 wakeup(TSA_PTC_READ(tp)); 314 } 315 if (flag & FWRITE) { 316 selwakeup(&pti->pt_selw); 317 wakeup(TSA_PTC_WRITE(tp)); 318 } 319} 320 321static int 322ptcopen(dev, flag, devtype, p) 323 dev_t dev; 324 int flag, devtype; 325 struct proc *p; 326{ 327 register struct tty *tp; 328 struct pt_ioctl *pti; 329 330 if (minor(dev) >= npty) 331 return (ENXIO); 332 tp = &pt_tty[minor(dev)]; 333 if (tp->t_oproc) 334 return (EIO); 335 tp->t_oproc = ptsstart; 336#ifdef sun4c 337 tp->t_stop = ptsstop; 338#endif 339 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 340 tp->t_lflag &= ~EXTPROC; 341 pti = &pt_ioctl[minor(dev)]; 342 pti->pt_flags = 0; 343 pti->pt_send = 0; 344 pti->pt_ucntl = 0; 345 return (0); 346} 347 348static int 349ptcclose(dev, flags, fmt, p) 350 dev_t dev; 351 int flags; 352 int fmt; 353 struct proc *p; 354{ 355 register struct tty *tp; 356 357 tp = &pt_tty[minor(dev)]; 358 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 359 360 /* 361 * XXX MDMBUF makes no sense for ptys but would inhibit the above 362 * l_modem(). CLOCAL makes sense but isn't supported. Special 363 * l_modem()s that ignore carrier drop make no sense for ptys but 364 * may be in use because other parts of the line discipline make 365 * sense for ptys. Recover by doing everything that a normal 366 * ttymodem() would have done except for sending a SIGHUP. 367 */ 368 if (tp->t_state & TS_ISOPEN) { 369 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 370 tp->t_state |= TS_ZOMBIE; 371 ttyflush(tp, FREAD | FWRITE); 372 } 373 374 tp->t_oproc = 0; /* mark closed */ 375 return (0); 376} 377 378static int 379ptcread(dev, uio, flag) 380 dev_t dev; 381 struct uio *uio; 382 int flag; 383{ 384 register struct tty *tp = &pt_tty[minor(dev)]; 385 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 386 char buf[BUFSIZ]; 387 int error = 0, cc; 388 389 /* 390 * We want to block until the slave 391 * is open, and there's something to read; 392 * but if we lost the slave or we're NBIO, 393 * then return the appropriate error instead. 394 */ 395 for (;;) { 396 if (tp->t_state&TS_ISOPEN) { 397 if (pti->pt_flags&PF_PKT && pti->pt_send) { 398 error = ureadc((int)pti->pt_send, uio); 399 if (error) 400 return (error); 401 if (pti->pt_send & TIOCPKT_IOCTL) { 402 cc = min(uio->uio_resid, 403 sizeof(tp->t_termios)); 404 uiomove((caddr_t)&tp->t_termios, cc, 405 uio); 406 } 407 pti->pt_send = 0; 408 return (0); 409 } 410 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 411 error = ureadc((int)pti->pt_ucntl, uio); 412 if (error) 413 return (error); 414 pti->pt_ucntl = 0; 415 return (0); 416 } 417 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 418 break; 419 } 420 if ((tp->t_state & TS_CONNECTED) == 0) 421 return (0); /* EOF */ 422 if (flag & IO_NDELAY) 423 return (EWOULDBLOCK); 424 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0); 425 if (error) 426 return (error); 427 } 428 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 429 error = ureadc(0, uio); 430 while (uio->uio_resid > 0 && error == 0) { 431 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 432 if (cc <= 0) 433 break; 434 error = uiomove(buf, cc, uio); 435 } 436 ttwwakeup(tp); 437 return (error); 438} 439 440static void 441ptsstop(tp, flush) 442 register struct tty *tp; 443 int flush; 444{ 445 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 446 int flag; 447 448 /* note: FLUSHREAD and FLUSHWRITE already ok */ 449 if (flush == 0) { 450 flush = TIOCPKT_STOP; 451 pti->pt_flags |= PF_STOPPED; 452 } else 453 pti->pt_flags &= ~PF_STOPPED; 454 pti->pt_send |= flush; 455 /* change of perspective */ 456 flag = 0; 457 if (flush & FREAD) 458 flag |= FWRITE; 459 if (flush & FWRITE) 460 flag |= FREAD; 461 ptcwakeup(tp, flag); 462} 463 464static int 465ptcpoll(dev, events, p) 466 dev_t dev; 467 int events; 468 struct proc *p; 469{ 470 register struct tty *tp = &pt_tty[minor(dev)]; 471 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 472 int revents = 0; 473 int s; 474 475 if ((tp->t_state & TS_CONNECTED) == 0) 476 return (seltrue(dev, events, p) | POLLHUP); 477 478 /* 479 * Need to block timeouts (ttrstart). 480 */ 481 s = spltty(); 482 483 if (events & (POLLIN | POLLRDNORM)) 484 if ((tp->t_state & TS_ISOPEN) && 485 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 486 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 487 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 488 revents |= events & (POLLIN | POLLRDNORM); 489 490 if (events & (POLLOUT | POLLWRNORM)) 491 if (tp->t_state & TS_ISOPEN && 492 ((pti->pt_flags & PF_REMOTE) ? 493 (tp->t_canq.c_cc == 0) : 494 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 495 (tp->t_canq.c_cc == 0 && (tp->t_iflag & ICANON))))) 496 revents |= events & (POLLOUT | POLLWRNORM); 497 498 if (events & POLLHUP) 499 if ((tp->t_state & TS_CARR_ON) == 0) 500 revents |= POLLHUP; 501 502 if (revents == 0) { 503 if (events & (POLLIN | POLLRDNORM)) 504 selrecord(p, &pti->pt_selr); 505 506 if (events & (POLLOUT | POLLWRNORM)) 507 selrecord(p, &pti->pt_selw); 508 } 509 splx(s); 510 511 return (revents); 512} 513 514static int 515ptcwrite(dev, uio, flag) 516 dev_t dev; 517 register struct uio *uio; 518 int flag; 519{ 520 register struct tty *tp = &pt_tty[minor(dev)]; 521 register u_char *cp = 0; 522 register int cc = 0; 523 u_char locbuf[BUFSIZ]; 524 int cnt = 0; 525 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 526 int error = 0; 527 528again: 529 if ((tp->t_state&TS_ISOPEN) == 0) 530 goto block; 531 if (pti->pt_flags & PF_REMOTE) { 532 if (tp->t_canq.c_cc) 533 goto block; 534 while ((uio->uio_resid > 0 || cc > 0) && 535 tp->t_canq.c_cc < TTYHOG - 1) { 536 if (cc == 0) { 537 cc = min(uio->uio_resid, BUFSIZ); 538 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 539 cp = locbuf; 540 error = uiomove((caddr_t)cp, cc, uio); 541 if (error) 542 return (error); 543 /* check again for safety */ 544 if ((tp->t_state & TS_ISOPEN) == 0) { 545 /* adjust as usual */ 546 uio->uio_resid += cc; 547 return (EIO); 548 } 549 } 550 if (cc > 0) { 551 cc = b_to_q((char *)cp, cc, &tp->t_canq); 552 /* 553 * XXX we don't guarantee that the canq size 554 * is >= TTYHOG, so the above b_to_q() may 555 * leave some bytes uncopied. However, space 556 * is guaranteed for the null terminator if 557 * we don't fail here since (TTYHOG - 1) is 558 * not a multiple of CBSIZE. 559 */ 560 if (cc > 0) 561 break; 562 } 563 } 564 /* adjust for data copied in but not written */ 565 uio->uio_resid += cc; 566 (void) putc(0, &tp->t_canq); 567 ttwakeup(tp); 568 wakeup(TSA_PTS_READ(tp)); 569 return (0); 570 } 571 while (uio->uio_resid > 0 || cc > 0) { 572 if (cc == 0) { 573 cc = min(uio->uio_resid, BUFSIZ); 574 cp = locbuf; 575 error = uiomove((caddr_t)cp, cc, uio); 576 if (error) 577 return (error); 578 /* check again for safety */ 579 if ((tp->t_state & TS_ISOPEN) == 0) { 580 /* adjust for data copied in but not written */ 581 uio->uio_resid += cc; 582 return (EIO); 583 } 584 } 585 while (cc > 0) { 586 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 587 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 588 wakeup(TSA_HUP_OR_INPUT(tp)); 589 goto block; 590 } 591 (*linesw[tp->t_line].l_rint)(*cp++, tp); 592 cnt++; 593 cc--; 594 } 595 cc = 0; 596 } 597 return (0); 598block: 599 /* 600 * Come here to wait for slave to open, for space 601 * in outq, or space in rawq, or an empty canq. 602 */ 603 if ((tp->t_state & TS_CONNECTED) == 0) { 604 /* adjust for data copied in but not written */ 605 uio->uio_resid += cc; 606 return (EIO); 607 } 608 if (flag & IO_NDELAY) { 609 /* adjust for data copied in but not written */ 610 uio->uio_resid += cc; 611 if (cnt == 0) 612 return (EWOULDBLOCK); 613 return (0); 614 } 615 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 616 if (error) { 617 /* adjust for data copied in but not written */ 618 uio->uio_resid += cc; 619 return (error); 620 } 621 goto again; 622} 623 624static struct tty * 625ptydevtotty(dev) 626 dev_t dev; 627{ 628 if (minor(dev) >= npty) 629 return (NULL); 630 631 return &pt_tty[minor(dev)]; 632} 633 634/*ARGSUSED*/ 635static int 636ptyioctl(dev, cmd, data, flag, p) 637 dev_t dev; 638 u_long cmd; 639 caddr_t data; 640 int flag; 641 struct proc *p; 642{ 643 register struct tty *tp = &pt_tty[minor(dev)]; 644 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 645 register u_char *cc = tp->t_cc; 646 int stop, error; 647 648 /* 649 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 650 * ttywflush(tp) will hang if there are characters in the outq. 651 */ 652 if (cmd == TIOCEXT) { 653 /* 654 * When the EXTPROC bit is being toggled, we need 655 * to send an TIOCPKT_IOCTL if the packet driver 656 * is turned on. 657 */ 658 if (*(int *)data) { 659 if (pti->pt_flags & PF_PKT) { 660 pti->pt_send |= TIOCPKT_IOCTL; 661 ptcwakeup(tp, FREAD); 662 } 663 tp->t_lflag |= EXTPROC; 664 } else { 665 if ((tp->t_lflag & EXTPROC) && 666 (pti->pt_flags & PF_PKT)) { 667 pti->pt_send |= TIOCPKT_IOCTL; 668 ptcwakeup(tp, FREAD); 669 } 670 tp->t_lflag &= ~EXTPROC; 671 } 672 return(0); 673 } else 674 if (cdevsw[major(dev)]->d_open == ptcopen) 675 switch (cmd) { 676 677 case TIOCGPGRP: 678 /* 679 * We avoid calling ttioctl on the controller since, 680 * in that case, tp must be the controlling terminal. 681 */ 682 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 683 return (0); 684 685 case TIOCPKT: 686 if (*(int *)data) { 687 if (pti->pt_flags & PF_UCNTL) 688 return (EINVAL); 689 pti->pt_flags |= PF_PKT; 690 } else 691 pti->pt_flags &= ~PF_PKT; 692 return (0); 693 694 case TIOCUCNTL: 695 if (*(int *)data) { 696 if (pti->pt_flags & PF_PKT) 697 return (EINVAL); 698 pti->pt_flags |= PF_UCNTL; 699 } else 700 pti->pt_flags &= ~PF_UCNTL; 701 return (0); 702 703 case TIOCREMOTE: 704 if (*(int *)data) 705 pti->pt_flags |= PF_REMOTE; 706 else 707 pti->pt_flags &= ~PF_REMOTE; 708 ttyflush(tp, FREAD|FWRITE); 709 return (0); 710 711#ifdef COMPAT_43 712 case TIOCSETP: 713 case TIOCSETN: 714#endif 715 case TIOCSETD: 716 case TIOCSETA: 717 case TIOCSETAW: 718 case TIOCSETAF: 719 ndflush(&tp->t_outq, tp->t_outq.c_cc); 720 break; 721 722 case TIOCSIG: 723 if (*(unsigned int *)data >= NSIG || 724 *(unsigned int *)data == 0) 725 return(EINVAL); 726 if ((tp->t_lflag&NOFLSH) == 0) 727 ttyflush(tp, FREAD|FWRITE); 728 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 729 if ((*(unsigned int *)data == SIGINFO) && 730 ((tp->t_lflag&NOKERNINFO) == 0)) 731 ttyinfo(tp); 732 return(0); 733 } 734 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 735 if (error == ENOIOCTL) 736 error = ttioctl(tp, cmd, data, flag); 737 if (error == ENOIOCTL) { 738 if (pti->pt_flags & PF_UCNTL && 739 (cmd & ~0xff) == UIOCCMD(0)) { 740 if (cmd & 0xff) { 741 pti->pt_ucntl = (u_char)cmd; 742 ptcwakeup(tp, FREAD); 743 } 744 return (0); 745 } 746 error = ENOTTY; 747 } 748 /* 749 * If external processing and packet mode send ioctl packet. 750 */ 751 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 752 switch(cmd) { 753 case TIOCSETA: 754 case TIOCSETAW: 755 case TIOCSETAF: 756#ifdef COMPAT_43 757 case TIOCSETP: 758 case TIOCSETN: 759#endif 760#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 761 case TIOCSETC: 762 case TIOCSLTC: 763 case TIOCLBIS: 764 case TIOCLBIC: 765 case TIOCLSET: 766#endif 767 pti->pt_send |= TIOCPKT_IOCTL; 768 ptcwakeup(tp, FREAD); 769 default: 770 break; 771 } 772 } 773 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 774 && CCEQ(cc[VSTART], CTRL('q')); 775 if (pti->pt_flags & PF_NOSTOP) { 776 if (stop) { 777 pti->pt_send &= ~TIOCPKT_NOSTOP; 778 pti->pt_send |= TIOCPKT_DOSTOP; 779 pti->pt_flags &= ~PF_NOSTOP; 780 ptcwakeup(tp, FREAD); 781 } 782 } else { 783 if (!stop) { 784 pti->pt_send &= ~TIOCPKT_DOSTOP; 785 pti->pt_send |= TIOCPKT_NOSTOP; 786 pti->pt_flags |= PF_NOSTOP; 787 ptcwakeup(tp, FREAD); 788 } 789 } 790 return (error); 791} 792 793static int ptc_devsw_installed; 794 795static void ptc_drvinit __P((void *unused)); 796static void 797ptc_drvinit(unused) 798 void *unused; 799{ 800#ifdef DEVFS 801 int i,j,k; 802#endif 803 dev_t dev; 804 805 if( ! ptc_devsw_installed ) { 806 dev = makedev(CDEV_MAJOR_S, 0); 807 cdevsw_add(&dev, &pts_cdevsw, NULL); 808 dev = makedev(CDEV_MAJOR_C, 0); 809 cdevsw_add(&dev, &ptc_cdevsw, NULL); 810 ptc_devsw_installed = 1; 811#ifdef DEVFS 812 for ( i = 0 ; i<NPTY ; i++ ) { 813 j = i / 32; 814 k = i % 32; 815 devfs_token_pts[i] = 816 devfs_add_devswf(&pts_cdevsw,i, 817 DV_CHR,0,0,0666, 818 "tty%c%r",jnames[j],k); 819 devfs_token_ptc[i] = 820 devfs_add_devswf(&ptc_cdevsw,i, 821 DV_CHR,0,0,0666, 822 "pty%c%r",jnames[j],k); 823 } 824#endif 825 } 826} 827 828SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
| 186 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 187 return (EBUSY); 188 if (tp->t_oproc) /* Ctrlr still around. */ 189 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 190 while ((tp->t_state & TS_CARR_ON) == 0) { 191 if (flag&FNONBLOCK) 192 break; 193 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, 194 "ptsopn", 0); 195 if (error) 196 return (error); 197 } 198 error = (*linesw[tp->t_line].l_open)(dev, tp); 199 if (error == 0) 200 ptcwakeup(tp, FREAD|FWRITE); 201 return (error); 202} 203 204static int 205ptsclose(dev, flag, mode, p) 206 dev_t dev; 207 int flag, mode; 208 struct proc *p; 209{ 210 register struct tty *tp; 211 int err; 212 213 tp = &pt_tty[minor(dev)]; 214 err = (*linesw[tp->t_line].l_close)(tp, flag); 215 ptsstop(tp, FREAD|FWRITE); 216 (void) ttyclose(tp); 217 return (err); 218} 219 220static int 221ptsread(dev, uio, flag) 222 dev_t dev; 223 struct uio *uio; 224 int flag; 225{ 226 struct proc *p = curproc; 227 register struct tty *tp = &pt_tty[minor(dev)]; 228 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 229 int error = 0; 230 231again: 232 if (pti->pt_flags & PF_REMOTE) { 233 while (isbackground(p, tp)) { 234 if ((p->p_sigignore & sigmask(SIGTTIN)) || 235 (p->p_sigmask & sigmask(SIGTTIN)) || 236 p->p_pgrp->pg_jobc == 0 || 237 p->p_flag & P_PPWAIT) 238 return (EIO); 239 pgsignal(p->p_pgrp, SIGTTIN, 1); 240 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg", 241 0); 242 if (error) 243 return (error); 244 } 245 if (tp->t_canq.c_cc == 0) { 246 if (flag & IO_NDELAY) 247 return (EWOULDBLOCK); 248 error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH, 249 "ptsin", 0); 250 if (error) 251 return (error); 252 goto again; 253 } 254 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 255 if (ureadc(getc(&tp->t_canq), uio) < 0) { 256 error = EFAULT; 257 break; 258 } 259 if (tp->t_canq.c_cc == 1) 260 (void) getc(&tp->t_canq); 261 if (tp->t_canq.c_cc) 262 return (error); 263 } else 264 if (tp->t_oproc) 265 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 266 ptcwakeup(tp, FWRITE); 267 return (error); 268} 269 270/* 271 * Write to pseudo-tty. 272 * Wakeups of controlling tty will happen 273 * indirectly, when tty driver calls ptsstart. 274 */ 275static int 276ptswrite(dev, uio, flag) 277 dev_t dev; 278 struct uio *uio; 279 int flag; 280{ 281 register struct tty *tp; 282 283 tp = &pt_tty[minor(dev)]; 284 if (tp->t_oproc == 0) 285 return (EIO); 286 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 287} 288 289/* 290 * Start output on pseudo-tty. 291 * Wake up process selecting or sleeping for input from controlling tty. 292 */ 293static void 294ptsstart(tp) 295 struct tty *tp; 296{ 297 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 298 299 if (tp->t_state & TS_TTSTOP) 300 return; 301 if (pti->pt_flags & PF_STOPPED) { 302 pti->pt_flags &= ~PF_STOPPED; 303 pti->pt_send = TIOCPKT_START; 304 } 305 ptcwakeup(tp, FREAD); 306} 307 308static void 309ptcwakeup(tp, flag) 310 struct tty *tp; 311 int flag; 312{ 313 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 314 315 if (flag & FREAD) { 316 selwakeup(&pti->pt_selr); 317 wakeup(TSA_PTC_READ(tp)); 318 } 319 if (flag & FWRITE) { 320 selwakeup(&pti->pt_selw); 321 wakeup(TSA_PTC_WRITE(tp)); 322 } 323} 324 325static int 326ptcopen(dev, flag, devtype, p) 327 dev_t dev; 328 int flag, devtype; 329 struct proc *p; 330{ 331 register struct tty *tp; 332 struct pt_ioctl *pti; 333 334 if (minor(dev) >= npty) 335 return (ENXIO); 336 tp = &pt_tty[minor(dev)]; 337 if (tp->t_oproc) 338 return (EIO); 339 tp->t_oproc = ptsstart; 340#ifdef sun4c 341 tp->t_stop = ptsstop; 342#endif 343 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 344 tp->t_lflag &= ~EXTPROC; 345 pti = &pt_ioctl[minor(dev)]; 346 pti->pt_flags = 0; 347 pti->pt_send = 0; 348 pti->pt_ucntl = 0; 349 return (0); 350} 351 352static int 353ptcclose(dev, flags, fmt, p) 354 dev_t dev; 355 int flags; 356 int fmt; 357 struct proc *p; 358{ 359 register struct tty *tp; 360 361 tp = &pt_tty[minor(dev)]; 362 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 363 364 /* 365 * XXX MDMBUF makes no sense for ptys but would inhibit the above 366 * l_modem(). CLOCAL makes sense but isn't supported. Special 367 * l_modem()s that ignore carrier drop make no sense for ptys but 368 * may be in use because other parts of the line discipline make 369 * sense for ptys. Recover by doing everything that a normal 370 * ttymodem() would have done except for sending a SIGHUP. 371 */ 372 if (tp->t_state & TS_ISOPEN) { 373 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); 374 tp->t_state |= TS_ZOMBIE; 375 ttyflush(tp, FREAD | FWRITE); 376 } 377 378 tp->t_oproc = 0; /* mark closed */ 379 return (0); 380} 381 382static int 383ptcread(dev, uio, flag) 384 dev_t dev; 385 struct uio *uio; 386 int flag; 387{ 388 register struct tty *tp = &pt_tty[minor(dev)]; 389 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 390 char buf[BUFSIZ]; 391 int error = 0, cc; 392 393 /* 394 * We want to block until the slave 395 * is open, and there's something to read; 396 * but if we lost the slave or we're NBIO, 397 * then return the appropriate error instead. 398 */ 399 for (;;) { 400 if (tp->t_state&TS_ISOPEN) { 401 if (pti->pt_flags&PF_PKT && pti->pt_send) { 402 error = ureadc((int)pti->pt_send, uio); 403 if (error) 404 return (error); 405 if (pti->pt_send & TIOCPKT_IOCTL) { 406 cc = min(uio->uio_resid, 407 sizeof(tp->t_termios)); 408 uiomove((caddr_t)&tp->t_termios, cc, 409 uio); 410 } 411 pti->pt_send = 0; 412 return (0); 413 } 414 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 415 error = ureadc((int)pti->pt_ucntl, uio); 416 if (error) 417 return (error); 418 pti->pt_ucntl = 0; 419 return (0); 420 } 421 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 422 break; 423 } 424 if ((tp->t_state & TS_CONNECTED) == 0) 425 return (0); /* EOF */ 426 if (flag & IO_NDELAY) 427 return (EWOULDBLOCK); 428 error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0); 429 if (error) 430 return (error); 431 } 432 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 433 error = ureadc(0, uio); 434 while (uio->uio_resid > 0 && error == 0) { 435 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ)); 436 if (cc <= 0) 437 break; 438 error = uiomove(buf, cc, uio); 439 } 440 ttwwakeup(tp); 441 return (error); 442} 443 444static void 445ptsstop(tp, flush) 446 register struct tty *tp; 447 int flush; 448{ 449 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 450 int flag; 451 452 /* note: FLUSHREAD and FLUSHWRITE already ok */ 453 if (flush == 0) { 454 flush = TIOCPKT_STOP; 455 pti->pt_flags |= PF_STOPPED; 456 } else 457 pti->pt_flags &= ~PF_STOPPED; 458 pti->pt_send |= flush; 459 /* change of perspective */ 460 flag = 0; 461 if (flush & FREAD) 462 flag |= FWRITE; 463 if (flush & FWRITE) 464 flag |= FREAD; 465 ptcwakeup(tp, flag); 466} 467 468static int 469ptcpoll(dev, events, p) 470 dev_t dev; 471 int events; 472 struct proc *p; 473{ 474 register struct tty *tp = &pt_tty[minor(dev)]; 475 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 476 int revents = 0; 477 int s; 478 479 if ((tp->t_state & TS_CONNECTED) == 0) 480 return (seltrue(dev, events, p) | POLLHUP); 481 482 /* 483 * Need to block timeouts (ttrstart). 484 */ 485 s = spltty(); 486 487 if (events & (POLLIN | POLLRDNORM)) 488 if ((tp->t_state & TS_ISOPEN) && 489 ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) || 490 ((pti->pt_flags & PF_PKT) && pti->pt_send) || 491 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) 492 revents |= events & (POLLIN | POLLRDNORM); 493 494 if (events & (POLLOUT | POLLWRNORM)) 495 if (tp->t_state & TS_ISOPEN && 496 ((pti->pt_flags & PF_REMOTE) ? 497 (tp->t_canq.c_cc == 0) : 498 ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) || 499 (tp->t_canq.c_cc == 0 && (tp->t_iflag & ICANON))))) 500 revents |= events & (POLLOUT | POLLWRNORM); 501 502 if (events & POLLHUP) 503 if ((tp->t_state & TS_CARR_ON) == 0) 504 revents |= POLLHUP; 505 506 if (revents == 0) { 507 if (events & (POLLIN | POLLRDNORM)) 508 selrecord(p, &pti->pt_selr); 509 510 if (events & (POLLOUT | POLLWRNORM)) 511 selrecord(p, &pti->pt_selw); 512 } 513 splx(s); 514 515 return (revents); 516} 517 518static int 519ptcwrite(dev, uio, flag) 520 dev_t dev; 521 register struct uio *uio; 522 int flag; 523{ 524 register struct tty *tp = &pt_tty[minor(dev)]; 525 register u_char *cp = 0; 526 register int cc = 0; 527 u_char locbuf[BUFSIZ]; 528 int cnt = 0; 529 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 530 int error = 0; 531 532again: 533 if ((tp->t_state&TS_ISOPEN) == 0) 534 goto block; 535 if (pti->pt_flags & PF_REMOTE) { 536 if (tp->t_canq.c_cc) 537 goto block; 538 while ((uio->uio_resid > 0 || cc > 0) && 539 tp->t_canq.c_cc < TTYHOG - 1) { 540 if (cc == 0) { 541 cc = min(uio->uio_resid, BUFSIZ); 542 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc); 543 cp = locbuf; 544 error = uiomove((caddr_t)cp, cc, uio); 545 if (error) 546 return (error); 547 /* check again for safety */ 548 if ((tp->t_state & TS_ISOPEN) == 0) { 549 /* adjust as usual */ 550 uio->uio_resid += cc; 551 return (EIO); 552 } 553 } 554 if (cc > 0) { 555 cc = b_to_q((char *)cp, cc, &tp->t_canq); 556 /* 557 * XXX we don't guarantee that the canq size 558 * is >= TTYHOG, so the above b_to_q() may 559 * leave some bytes uncopied. However, space 560 * is guaranteed for the null terminator if 561 * we don't fail here since (TTYHOG - 1) is 562 * not a multiple of CBSIZE. 563 */ 564 if (cc > 0) 565 break; 566 } 567 } 568 /* adjust for data copied in but not written */ 569 uio->uio_resid += cc; 570 (void) putc(0, &tp->t_canq); 571 ttwakeup(tp); 572 wakeup(TSA_PTS_READ(tp)); 573 return (0); 574 } 575 while (uio->uio_resid > 0 || cc > 0) { 576 if (cc == 0) { 577 cc = min(uio->uio_resid, BUFSIZ); 578 cp = locbuf; 579 error = uiomove((caddr_t)cp, cc, uio); 580 if (error) 581 return (error); 582 /* check again for safety */ 583 if ((tp->t_state & TS_ISOPEN) == 0) { 584 /* adjust for data copied in but not written */ 585 uio->uio_resid += cc; 586 return (EIO); 587 } 588 } 589 while (cc > 0) { 590 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 591 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) { 592 wakeup(TSA_HUP_OR_INPUT(tp)); 593 goto block; 594 } 595 (*linesw[tp->t_line].l_rint)(*cp++, tp); 596 cnt++; 597 cc--; 598 } 599 cc = 0; 600 } 601 return (0); 602block: 603 /* 604 * Come here to wait for slave to open, for space 605 * in outq, or space in rawq, or an empty canq. 606 */ 607 if ((tp->t_state & TS_CONNECTED) == 0) { 608 /* adjust for data copied in but not written */ 609 uio->uio_resid += cc; 610 return (EIO); 611 } 612 if (flag & IO_NDELAY) { 613 /* adjust for data copied in but not written */ 614 uio->uio_resid += cc; 615 if (cnt == 0) 616 return (EWOULDBLOCK); 617 return (0); 618 } 619 error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0); 620 if (error) { 621 /* adjust for data copied in but not written */ 622 uio->uio_resid += cc; 623 return (error); 624 } 625 goto again; 626} 627 628static struct tty * 629ptydevtotty(dev) 630 dev_t dev; 631{ 632 if (minor(dev) >= npty) 633 return (NULL); 634 635 return &pt_tty[minor(dev)]; 636} 637 638/*ARGSUSED*/ 639static int 640ptyioctl(dev, cmd, data, flag, p) 641 dev_t dev; 642 u_long cmd; 643 caddr_t data; 644 int flag; 645 struct proc *p; 646{ 647 register struct tty *tp = &pt_tty[minor(dev)]; 648 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 649 register u_char *cc = tp->t_cc; 650 int stop, error; 651 652 /* 653 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 654 * ttywflush(tp) will hang if there are characters in the outq. 655 */ 656 if (cmd == TIOCEXT) { 657 /* 658 * When the EXTPROC bit is being toggled, we need 659 * to send an TIOCPKT_IOCTL if the packet driver 660 * is turned on. 661 */ 662 if (*(int *)data) { 663 if (pti->pt_flags & PF_PKT) { 664 pti->pt_send |= TIOCPKT_IOCTL; 665 ptcwakeup(tp, FREAD); 666 } 667 tp->t_lflag |= EXTPROC; 668 } else { 669 if ((tp->t_lflag & EXTPROC) && 670 (pti->pt_flags & PF_PKT)) { 671 pti->pt_send |= TIOCPKT_IOCTL; 672 ptcwakeup(tp, FREAD); 673 } 674 tp->t_lflag &= ~EXTPROC; 675 } 676 return(0); 677 } else 678 if (cdevsw[major(dev)]->d_open == ptcopen) 679 switch (cmd) { 680 681 case TIOCGPGRP: 682 /* 683 * We avoid calling ttioctl on the controller since, 684 * in that case, tp must be the controlling terminal. 685 */ 686 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 687 return (0); 688 689 case TIOCPKT: 690 if (*(int *)data) { 691 if (pti->pt_flags & PF_UCNTL) 692 return (EINVAL); 693 pti->pt_flags |= PF_PKT; 694 } else 695 pti->pt_flags &= ~PF_PKT; 696 return (0); 697 698 case TIOCUCNTL: 699 if (*(int *)data) { 700 if (pti->pt_flags & PF_PKT) 701 return (EINVAL); 702 pti->pt_flags |= PF_UCNTL; 703 } else 704 pti->pt_flags &= ~PF_UCNTL; 705 return (0); 706 707 case TIOCREMOTE: 708 if (*(int *)data) 709 pti->pt_flags |= PF_REMOTE; 710 else 711 pti->pt_flags &= ~PF_REMOTE; 712 ttyflush(tp, FREAD|FWRITE); 713 return (0); 714 715#ifdef COMPAT_43 716 case TIOCSETP: 717 case TIOCSETN: 718#endif 719 case TIOCSETD: 720 case TIOCSETA: 721 case TIOCSETAW: 722 case TIOCSETAF: 723 ndflush(&tp->t_outq, tp->t_outq.c_cc); 724 break; 725 726 case TIOCSIG: 727 if (*(unsigned int *)data >= NSIG || 728 *(unsigned int *)data == 0) 729 return(EINVAL); 730 if ((tp->t_lflag&NOFLSH) == 0) 731 ttyflush(tp, FREAD|FWRITE); 732 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 733 if ((*(unsigned int *)data == SIGINFO) && 734 ((tp->t_lflag&NOKERNINFO) == 0)) 735 ttyinfo(tp); 736 return(0); 737 } 738 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 739 if (error == ENOIOCTL) 740 error = ttioctl(tp, cmd, data, flag); 741 if (error == ENOIOCTL) { 742 if (pti->pt_flags & PF_UCNTL && 743 (cmd & ~0xff) == UIOCCMD(0)) { 744 if (cmd & 0xff) { 745 pti->pt_ucntl = (u_char)cmd; 746 ptcwakeup(tp, FREAD); 747 } 748 return (0); 749 } 750 error = ENOTTY; 751 } 752 /* 753 * If external processing and packet mode send ioctl packet. 754 */ 755 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 756 switch(cmd) { 757 case TIOCSETA: 758 case TIOCSETAW: 759 case TIOCSETAF: 760#ifdef COMPAT_43 761 case TIOCSETP: 762 case TIOCSETN: 763#endif 764#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 765 case TIOCSETC: 766 case TIOCSLTC: 767 case TIOCLBIS: 768 case TIOCLBIC: 769 case TIOCLSET: 770#endif 771 pti->pt_send |= TIOCPKT_IOCTL; 772 ptcwakeup(tp, FREAD); 773 default: 774 break; 775 } 776 } 777 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 778 && CCEQ(cc[VSTART], CTRL('q')); 779 if (pti->pt_flags & PF_NOSTOP) { 780 if (stop) { 781 pti->pt_send &= ~TIOCPKT_NOSTOP; 782 pti->pt_send |= TIOCPKT_DOSTOP; 783 pti->pt_flags &= ~PF_NOSTOP; 784 ptcwakeup(tp, FREAD); 785 } 786 } else { 787 if (!stop) { 788 pti->pt_send &= ~TIOCPKT_DOSTOP; 789 pti->pt_send |= TIOCPKT_NOSTOP; 790 pti->pt_flags |= PF_NOSTOP; 791 ptcwakeup(tp, FREAD); 792 } 793 } 794 return (error); 795} 796 797static int ptc_devsw_installed; 798 799static void ptc_drvinit __P((void *unused)); 800static void 801ptc_drvinit(unused) 802 void *unused; 803{ 804#ifdef DEVFS 805 int i,j,k; 806#endif 807 dev_t dev; 808 809 if( ! ptc_devsw_installed ) { 810 dev = makedev(CDEV_MAJOR_S, 0); 811 cdevsw_add(&dev, &pts_cdevsw, NULL); 812 dev = makedev(CDEV_MAJOR_C, 0); 813 cdevsw_add(&dev, &ptc_cdevsw, NULL); 814 ptc_devsw_installed = 1; 815#ifdef DEVFS 816 for ( i = 0 ; i<NPTY ; i++ ) { 817 j = i / 32; 818 k = i % 32; 819 devfs_token_pts[i] = 820 devfs_add_devswf(&pts_cdevsw,i, 821 DV_CHR,0,0,0666, 822 "tty%c%r",jnames[j],k); 823 devfs_token_ptc[i] = 824 devfs_add_devswf(&ptc_cdevsw,i, 825 DV_CHR,0,0,0666, 826 "pty%c%r",jnames[j],k); 827 } 828#endif 829 } 830} 831 832SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
|