1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 * Copyright 2015, Joyent, Inc. 5 */ 6 7 /* 8 * Copyright (c) 1983 Regents of the University of California. 9 * All rights reserved. The Berkeley software License Agreement 10 * specifies the terms and conditions for redistribution. 11 */ 12 13 /* 14 * PTY - Stream "pseudo-terminal" device. For each "manager" side it connects 15 * to a "subsidiary" side. 16 */ 17 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/filio.h> 22 #include <sys/ioccom.h> 23 #include <sys/termios.h> 24 #include <sys/termio.h> 25 #include <sys/ttold.h> 26 #include <sys/stropts.h> 27 #include <sys/stream.h> 28 #include <sys/tty.h> 29 #include <sys/user.h> 30 #include <sys/conf.h> 31 #include <sys/file.h> 32 #include <sys/vnode.h> 33 #include <sys/proc.h> 34 #include <sys/uio.h> 35 #include <sys/errno.h> 36 #include <sys/strsubr.h> 37 #include <sys/poll.h> 38 #include <sys/sysmacros.h> 39 #include <sys/debug.h> 40 #include <sys/procset.h> 41 #include <sys/cred.h> 42 #include <sys/ptyvar.h> 43 #include <sys/suntty.h> 44 #include <sys/stat.h> 45 46 #include <sys/conf.h> 47 #include <sys/ddi.h> 48 #include <sys/sunddi.h> 49 50 extern int npty; /* number of pseudo-ttys configured in */ 51 extern struct pty *pty_softc; 52 extern struct pollhead ptcph; /* poll head for ptcpoll() use */ 53 54 int ptcopen(dev_t *, int, int, struct cred *); 55 int ptcclose(dev_t, int, int, struct cred *); 56 int ptcwrite(dev_t, struct uio *, struct cred *); 57 int ptcread(dev_t, struct uio *, struct cred *); 58 int ptcioctl(dev_t, int, intptr_t, int, struct cred *, int *); 59 int ptcpoll(dev_t, short, int, short *, struct pollhead **); 60 61 static int ptc_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 62 static int ptc_attach(dev_info_t *, ddi_attach_cmd_t); 63 static dev_info_t *ptc_dip; /* for dev-to-dip conversions */ 64 65 static void ptc_init(void), ptc_uninit(void); 66 67 static int makemsg(ssize_t count, struct uio *uiop, 68 struct pty *pty, mblk_t **mpp); 69 70 struct cb_ops ptc_cb_ops = { 71 ptcopen, /* open */ 72 ptcclose, /* close */ 73 nodev, /* strategy */ 74 nodev, /* print */ 75 nodev, /* dump */ 76 ptcread, /* read */ 77 ptcwrite, /* write */ 78 ptcioctl, /* ioctl */ 79 nodev, /* devmap */ 80 nodev, /* mmap */ 81 nodev, /* segmap */ 82 ptcpoll, /* poll */ 83 ddi_prop_op, /* prop_op */ 84 0, /* streamtab */ 85 D_NEW | D_MP /* Driver compatibility flag */ 86 }; 87 88 struct dev_ops ptc_ops = { 89 DEVO_REV, /* devo_rev */ 90 0, /* refcnt */ 91 ptc_info, /* info */ 92 nulldev, /* identify */ 93 nulldev, /* probe */ 94 ptc_attach, /* attach */ 95 nodev, /* detach */ 96 nodev, /* reset */ 97 &ptc_cb_ops, /* driver operations */ 98 (struct bus_ops *)0, /* bus operations */ 99 NULL, /* power */ 100 ddi_quiesce_not_supported, /* devo_quiesce */ 101 }; 102 103 #include <sys/types.h> 104 #include <sys/conf.h> 105 #include <sys/param.h> 106 #include <sys/systm.h> 107 #include <sys/errno.h> 108 #include <sys/modctl.h> 109 110 extern int dseekneg_flag; 111 extern struct mod_ops mod_driverops; 112 extern struct dev_ops ptc_ops; 113 114 /* 115 * Module linkage information for the kernel. 116 */ 117 118 static struct modldrv modldrv = { 119 &mod_driverops, 120 "tty pseudo driver control 'ptc'", 121 &ptc_ops, 122 }; 123 124 static struct modlinkage modlinkage = { 125 MODREV_1, 126 &modldrv, 127 NULL 128 }; 129 130 int 131 _init() 132 { 133 int rc; 134 135 if ((rc = mod_install(&modlinkage)) == 0) 136 ptc_init(); 137 return (rc); 138 } 139 140 141 int 142 _fini() 143 { 144 int rc; 145 146 if ((rc = mod_remove(&modlinkage)) == 0) 147 ptc_uninit(); 148 return (rc); 149 } 150 151 int 152 _info(struct modinfo *modinfop) 153 { 154 return (mod_info(&modlinkage, modinfop)); 155 } 156 157 static char *pty_banks = PTY_BANKS; 158 static char *pty_digits = PTY_DIGITS; 159 160 /* ARGSUSED */ 161 static int 162 ptc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 163 { 164 char name[8]; 165 int pty_num; 166 char *pty_digit = pty_digits; 167 char *pty_bank = pty_banks; 168 169 for (pty_num = 0; pty_num < npty; pty_num++) { 170 (void) sprintf(name, "pty%c%c", *pty_bank, *pty_digit); 171 if (ddi_create_minor_node(devi, name, S_IFCHR, 172 pty_num, DDI_PSEUDO, 0) == DDI_FAILURE) { 173 ddi_remove_minor_node(devi, NULL); 174 return (-1); 175 } 176 if (*(++pty_digit) == '\0') { 177 pty_digit = pty_digits; 178 if (*(++pty_bank) == '\0') 179 break; 180 } 181 } 182 ptc_dip = devi; 183 return (DDI_SUCCESS); 184 } 185 186 /* ARGSUSED */ 187 static int 188 ptc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 189 { 190 int error; 191 192 switch (infocmd) { 193 case DDI_INFO_DEVT2DEVINFO: 194 if (ptc_dip == NULL) { 195 *result = (void *)NULL; 196 error = DDI_FAILURE; 197 } else { 198 *result = (void *) ptc_dip; 199 error = DDI_SUCCESS; 200 } 201 break; 202 case DDI_INFO_DEVT2INSTANCE: 203 *result = (void *)0; 204 error = DDI_SUCCESS; 205 break; 206 default: 207 error = DDI_FAILURE; 208 } 209 return (error); 210 } 211 212 static void 213 ptc_init(void) 214 { 215 minor_t dev; 216 217 for (dev = 0; dev < npty; dev++) { 218 cv_init(&pty_softc[dev].pt_cv_flags, NULL, CV_DEFAULT, NULL); 219 cv_init(&pty_softc[dev].pt_cv_readq, NULL, CV_DEFAULT, NULL); 220 cv_init(&pty_softc[dev].pt_cv_writeq, NULL, CV_DEFAULT, NULL); 221 mutex_init(&pty_softc[dev].ptc_lock, NULL, MUTEX_DEFAULT, NULL); 222 } 223 } 224 225 static void 226 ptc_uninit(void) 227 { 228 minor_t dev; 229 230 for (dev = 0; dev < npty; dev++) { 231 cv_destroy(&pty_softc[dev].pt_cv_flags); 232 cv_destroy(&pty_softc[dev].pt_cv_readq); 233 cv_destroy(&pty_softc[dev].pt_cv_writeq); 234 mutex_destroy(&pty_softc[dev].ptc_lock); 235 } 236 } 237 238 /* 239 * Manager side. This is not, alas, a streams device; there are too 240 * many old features that we must support and that don't work well 241 * with streams. 242 */ 243 244 int 245 ptcopen(dev_t *devp, int flag, int otyp, struct cred *cred) 246 { 247 dev_t dev = *devp; 248 struct pty *pty; 249 queue_t *q; 250 251 if (getminor(dev) >= npty) { 252 return (ENXIO); 253 } 254 pty = &pty_softc[getminor(dev)]; 255 mutex_enter(&pty->ptc_lock); 256 if (pty->pt_flags & PF_CARR_ON) { 257 mutex_exit(&pty->ptc_lock); 258 return (EIO); /* manager is exclusive use */ 259 /* XXX - should be EBUSY! */ 260 } 261 if (pty->pt_flags & PF_WOPEN) { 262 pty->pt_flags &= ~PF_WOPEN; 263 cv_broadcast(&pty->pt_cv_flags); 264 } 265 266 if ((q = pty->pt_ttycommon.t_readq) != NULL) { 267 /* 268 * Send an un-hangup to the subsidiary, since "carrier" is 269 * coming back up. Make sure we're doing canonicalization. 270 */ 271 (void) putctl(q, M_UNHANGUP); 272 (void) putctl1(q, M_CTL, MC_DOCANON); 273 } 274 pty->pt_flags |= PF_CARR_ON; 275 pty->pt_send = 0; 276 pty->pt_ucntl = 0; 277 278 mutex_exit(&pty->ptc_lock); 279 return (0); 280 } 281 282 int 283 ptcclose(dev_t dev, int flag, int otyp, struct cred *cred) 284 { 285 struct pty *pty; 286 mblk_t *bp; 287 queue_t *q; 288 289 pty = &pty_softc[getminor(dev)]; 290 291 mutex_enter(&pty->ptc_lock); 292 if ((q = pty->pt_ttycommon.t_readq) != NULL) { 293 /* 294 * Send a hangup to the subsidiary, since "carrier" is dropping. 295 */ 296 (void) putctl(q, M_HANGUP); 297 } 298 299 /* 300 * Clear out all the manager-side state. This also 301 * clears PF_CARR_ON, which is correct because the 302 * "carrier" is dropping since the manager process 303 * is going away. 304 */ 305 pty->pt_flags &= (PF_WOPEN|PF_STOPPED|PF_NOSTOP); 306 while ((bp = pty->pt_stuffqfirst) != NULL) { 307 if ((pty->pt_stuffqfirst = bp->b_next) == NULL) 308 pty->pt_stuffqlast = NULL; 309 else 310 pty->pt_stuffqfirst->b_prev = NULL; 311 pty->pt_stuffqlen--; 312 bp->b_next = bp->b_prev = NULL; 313 freemsg(bp); 314 } 315 mutex_exit(&pty->ptc_lock); 316 return (0); 317 } 318 319 int 320 ptcread(dev_t dev, struct uio *uio, struct cred *cred) 321 { 322 struct pty *pty = &pty_softc[getminor(dev)]; 323 mblk_t *bp, *nbp; 324 queue_t *q; 325 unsigned char tmp; 326 ssize_t cc; 327 int error; 328 off_t off; 329 330 off = uio->uio_offset; 331 332 mutex_enter(&pty->ptc_lock); 333 334 for (;;) { 335 while (pty->pt_flags & PF_READ) { 336 pty->pt_flags |= PF_WREAD; 337 cv_wait(&pty->pt_cv_flags, &pty->ptc_lock); 338 } 339 pty->pt_flags |= PF_READ; 340 341 /* 342 * If there's a TIOCPKT packet waiting, pass it back. 343 */ 344 while (pty->pt_flags&(PF_PKT|PF_UCNTL) && pty->pt_send) { 345 tmp = pty->pt_send; 346 pty->pt_send = 0; 347 mutex_exit(&pty->ptc_lock); 348 error = ureadc((int)tmp, uio); 349 uio->uio_offset = off; 350 mutex_enter(&pty->ptc_lock); 351 if (error) { 352 pty->pt_send |= tmp; 353 goto out; 354 } 355 if (pty->pt_send == 0) 356 goto out; 357 } 358 359 /* 360 * If there's a user-control packet waiting, pass the 361 * "ioctl" code back. 362 */ 363 while ((pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) && 364 pty->pt_ucntl) { 365 tmp = pty->pt_ucntl; 366 pty->pt_ucntl = 0; 367 mutex_exit(&pty->ptc_lock); 368 error = ureadc((int)tmp, uio); 369 uio->uio_offset = off; 370 mutex_enter(&pty->ptc_lock); 371 if (error) { 372 if (pty->pt_ucntl == 0) 373 pty->pt_ucntl = tmp; 374 goto out; 375 } 376 if (pty->pt_ucntl == 0) 377 goto out; 378 } 379 380 /* 381 * If there's any data waiting, pass it back. 382 */ 383 if ((q = pty->pt_ttycommon.t_writeq) != NULL && 384 q->q_first != NULL && 385 !(pty->pt_flags & PF_STOPPED)) { 386 if (pty->pt_flags & (PF_PKT|PF_UCNTL|PF_43UCNTL)) { 387 /* 388 * We're about to begin a move in packet or 389 * user-control mode; precede the data with a 390 * data header. 391 */ 392 mutex_exit(&pty->ptc_lock); 393 error = ureadc(TIOCPKT_DATA, uio); 394 uio->uio_offset = off; 395 mutex_enter(&pty->ptc_lock); 396 if (error != 0) 397 goto out; 398 if ((q = pty->pt_ttycommon.t_writeq) == NULL) 399 goto out; 400 } 401 if ((bp = getq(q)) == NULL) 402 goto out; 403 while (uio->uio_resid > 0) { 404 while ((cc = bp->b_wptr - bp->b_rptr) == 0) { 405 nbp = bp->b_cont; 406 freeb(bp); 407 if ((bp = nbp) == NULL) { 408 if ((q == NULL) || 409 (bp = getq(q)) == NULL) 410 goto out; 411 } 412 } 413 cc = MIN(cc, uio->uio_resid); 414 mutex_exit(&pty->ptc_lock); 415 error = uiomove((caddr_t)bp->b_rptr, 416 cc, UIO_READ, uio); 417 uio->uio_offset = off; 418 mutex_enter(&pty->ptc_lock); 419 if (error != 0) { 420 freemsg(bp); 421 goto out; 422 } 423 q = pty->pt_ttycommon.t_writeq; 424 bp->b_rptr += cc; 425 } 426 /* 427 * Strip off zero-length blocks from the front of 428 * what we're putting back on the queue. 429 */ 430 while ((bp->b_wptr - bp->b_rptr) == 0) { 431 nbp = bp->b_cont; 432 freeb(bp); 433 if ((bp = nbp) == NULL) 434 goto out; /* nothing left */ 435 } 436 if (q != NULL) 437 (void) putbq(q, bp); 438 else 439 freemsg(bp); 440 goto out; 441 } 442 443 /* 444 * If there's any TIOCSTI-stuffed characters, pass 445 * them back. (They currently arrive after all output; 446 * is this correct?) 447 */ 448 if (pty->pt_flags&PF_UCNTL && pty->pt_stuffqfirst != NULL) { 449 mutex_exit(&pty->ptc_lock); 450 error = ureadc(TIOCSTI&0xff, uio); 451 mutex_enter(&pty->ptc_lock); 452 while (error == 0 && 453 (bp = pty->pt_stuffqfirst) != NULL && 454 uio->uio_resid > 0) { 455 pty->pt_stuffqlen--; 456 if ((pty->pt_stuffqfirst = bp->b_next) == NULL) 457 pty->pt_stuffqlast = NULL; 458 else 459 pty->pt_stuffqfirst->b_prev = NULL; 460 mutex_exit(&pty->ptc_lock); 461 error = ureadc((int)*bp->b_rptr, uio); 462 bp->b_next = bp->b_prev = NULL; 463 freemsg(bp); 464 mutex_enter(&pty->ptc_lock); 465 } 466 uio->uio_offset = off; 467 goto out; 468 } 469 470 /* 471 * There's no data available. 472 * We want to block until the subsidiary is open, and there's 473 * something to read; but if we lost the subsidiary or we're 474 * NBIO, then return the appropriate error instead. 475 * POSIX-style non-block has top billing and gives -1 with 476 * errno = EAGAIN, BSD-style comes next and gives -1 with 477 * errno = EWOULDBLOCK, SVID-style comes last and gives 0. 478 */ 479 if (pty->pt_flags & PF_SUBSIDGONE) { 480 error = EIO; 481 goto out; 482 } 483 if (uio->uio_fmode & FNONBLOCK) { 484 error = EAGAIN; 485 goto out; 486 } 487 if (pty->pt_flags & PF_NBIO) { 488 error = EWOULDBLOCK; 489 goto out; 490 } 491 if (uio->uio_fmode & FNDELAY) 492 goto out; 493 494 if (pty->pt_flags & PF_WREAD) 495 cv_broadcast(&pty->pt_cv_flags); 496 497 pty->pt_flags &= ~(PF_READ | PF_WREAD); 498 499 500 if (!cv_wait_sig(&pty->pt_cv_writeq, &pty->ptc_lock)) { 501 mutex_exit(&pty->ptc_lock); 502 return (EINTR); 503 } 504 } 505 506 out: 507 if (pty->pt_flags & PF_WREAD) 508 cv_broadcast(&pty->pt_cv_flags); 509 510 pty->pt_flags &= ~(PF_READ | PF_WREAD); 511 512 mutex_exit(&pty->ptc_lock); 513 return (error); 514 } 515 516 int 517 ptcwrite(dev_t dev, struct uio *uio, struct cred *cred) 518 { 519 struct pty *pty = &pty_softc[getminor(dev)]; 520 queue_t *q; 521 int written; 522 mblk_t *mp; 523 int fmode = 0; 524 int error = 0; 525 526 off_t off; 527 off = uio->uio_offset; 528 529 mutex_enter(&pty->ptc_lock); 530 531 again: 532 while (pty->pt_flags & PF_WRITE) { 533 pty->pt_flags |= PF_WWRITE; 534 cv_wait(&pty->pt_cv_flags, &pty->ptc_lock); 535 } 536 537 pty->pt_flags |= PF_WRITE; 538 539 if ((q = pty->pt_ttycommon.t_readq) == NULL) { 540 541 /* 542 * Wait for subsidiary to open. 543 */ 544 if (pty->pt_flags & PF_SUBSIDGONE) { 545 error = EIO; 546 goto out; 547 } 548 if (uio->uio_fmode & FNONBLOCK) { 549 error = EAGAIN; 550 goto out; 551 } 552 if (pty->pt_flags & PF_NBIO) { 553 error = EWOULDBLOCK; 554 goto out; 555 } 556 if (uio->uio_fmode & FNDELAY) 557 goto out; 558 559 if (pty->pt_flags & PF_WWRITE) 560 cv_broadcast(&pty->pt_cv_flags); 561 562 pty->pt_flags &= ~(PF_WRITE | PF_WWRITE); 563 564 if (!cv_wait_sig(&pty->pt_cv_readq, &pty->ptc_lock)) { 565 mutex_exit(&pty->ptc_lock); 566 return (EINTR); 567 } 568 569 goto again; 570 } 571 572 /* 573 * If in remote mode, even zero-length writes generate messages. 574 */ 575 written = 0; 576 if ((pty->pt_flags & PF_REMOTE) || uio->uio_resid > 0) { 577 do { 578 while (!canput(q)) { 579 /* 580 * Wait for subsidiary's read queue to unclog. 581 */ 582 if (pty->pt_flags & PF_SUBSIDGONE) { 583 error = EIO; 584 goto out; 585 } 586 if (uio->uio_fmode & FNONBLOCK) { 587 if (!written) 588 error = EAGAIN; 589 goto out; 590 } 591 if (pty->pt_flags & PF_NBIO) { 592 if (!written) 593 error = EWOULDBLOCK; 594 goto out; 595 } 596 if (uio->uio_fmode & FNDELAY) 597 goto out; 598 599 if (pty->pt_flags & PF_WWRITE) 600 cv_broadcast(&pty->pt_cv_flags); 601 602 pty->pt_flags &= ~(PF_WRITE | PF_WWRITE); 603 604 if (!cv_wait_sig(&pty->pt_cv_readq, 605 &pty->ptc_lock)) { 606 mutex_exit(&pty->ptc_lock); 607 return (EINTR); 608 } 609 610 while (pty->pt_flags & PF_WRITE) { 611 pty->pt_flags |= PF_WWRITE; 612 cv_wait(&pty->pt_cv_flags, 613 &pty->ptc_lock); 614 } 615 616 pty->pt_flags |= PF_WRITE; 617 } 618 619 if ((pty->pt_flags & PF_NBIO) && 620 !(uio->uio_fmode & FNONBLOCK)) { 621 fmode = uio->uio_fmode; 622 uio->uio_fmode |= FNONBLOCK; 623 } 624 625 error = makemsg(uio->uio_resid, uio, pty, &mp); 626 uio->uio_offset = off; 627 if (fmode) 628 uio->uio_fmode = fmode; 629 if (error != 0) { 630 if (error != EAGAIN && error != EWOULDBLOCK) 631 goto out; 632 if (uio->uio_fmode & FNONBLOCK) { 633 if (!written) 634 error = EAGAIN; 635 goto out; 636 } 637 if (pty->pt_flags & PF_NBIO) { 638 if (!written) 639 error = EWOULDBLOCK; 640 goto out; 641 } 642 if (uio->uio_fmode & FNDELAY) 643 goto out; 644 cmn_err(CE_PANIC, 645 "ptcwrite: non null return from" 646 " makemsg"); 647 } 648 649 /* 650 * Check again for safety; since "uiomove" can take a 651 * page fault, there's no guarantee that "pt_flags" 652 * didn't change while it was happening. 653 */ 654 if ((q = pty->pt_ttycommon.t_readq) == NULL) { 655 if (mp) 656 freemsg(mp); 657 error = EIO; 658 goto out; 659 } 660 if (mp) 661 (void) putq(q, mp); 662 written = 1; 663 } while (uio->uio_resid > 0); 664 } 665 out: 666 if (pty->pt_flags & PF_WWRITE) 667 cv_broadcast(&pty->pt_cv_flags); 668 669 pty->pt_flags &= ~(PF_WRITE | PF_WWRITE); 670 671 mutex_exit(&pty->ptc_lock); 672 return (error); 673 } 674 675 #define copy_in(data, d_arg) \ 676 if (copyin((caddr_t)data, &d_arg, sizeof (int)) != 0) \ 677 return (EFAULT) 678 679 #define copy_out(d_arg, data) \ 680 if (copyout(&d_arg, (caddr_t)data, sizeof (int)) != 0) \ 681 return (EFAULT) 682 683 int 684 ptcioctl(dev_t dev, int cmd, intptr_t data, int flag, struct cred *cred, 685 int *rvalp) 686 { 687 struct pty *pty = &pty_softc[getminor(dev)]; 688 queue_t *q; 689 struct ttysize tty_arg; 690 struct winsize win_arg; 691 int d_arg; 692 int err; 693 694 switch (cmd) { 695 696 case TIOCPKT: 697 copy_in(data, d_arg); 698 mutex_enter(&pty->ptc_lock); 699 if (d_arg) { 700 if (pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) { 701 mutex_exit(&pty->ptc_lock); 702 return (EINVAL); 703 } 704 pty->pt_flags |= PF_PKT; 705 } else 706 pty->pt_flags &= ~PF_PKT; 707 mutex_exit(&pty->ptc_lock); 708 break; 709 710 case TIOCUCNTL: 711 copy_in(data, d_arg); 712 mutex_enter(&pty->ptc_lock); 713 if (d_arg) { 714 if (pty->pt_flags & (PF_PKT|PF_UCNTL)) { 715 mutex_exit(&pty->ptc_lock); 716 return (EINVAL); 717 } 718 pty->pt_flags |= PF_43UCNTL; 719 } else 720 pty->pt_flags &= ~PF_43UCNTL; 721 mutex_exit(&pty->ptc_lock); 722 break; 723 724 case TIOCTCNTL: 725 copy_in(data, d_arg); 726 mutex_enter(&pty->ptc_lock); 727 if (d_arg) { 728 if (pty->pt_flags & PF_PKT) { 729 mutex_exit(&pty->ptc_lock); 730 return (EINVAL); 731 } 732 pty->pt_flags |= PF_UCNTL; 733 } else 734 pty->pt_flags &= ~PF_UCNTL; 735 mutex_exit(&pty->ptc_lock); 736 break; 737 738 case TIOCREMOTE: 739 copy_in(data, d_arg); 740 mutex_enter(&pty->ptc_lock); 741 if (d_arg) { 742 if ((q = pty->pt_ttycommon.t_readq) != NULL) 743 (void) putctl1(q, M_CTL, MC_NOCANON); 744 pty->pt_flags |= PF_REMOTE; 745 } else { 746 if ((q = pty->pt_ttycommon.t_readq) != NULL) 747 (void) putctl1(q, M_CTL, MC_DOCANON); 748 pty->pt_flags &= ~PF_REMOTE; 749 } 750 mutex_exit(&pty->ptc_lock); 751 break; 752 753 case TIOCSIGNAL: 754 /* 755 * Blast a M_PCSIG message up the subsidiary stream; the 756 * signal number is the argument to the "ioctl". 757 */ 758 copy_in(data, d_arg); 759 mutex_enter(&pty->ptc_lock); 760 if ((q = pty->pt_ttycommon.t_readq) != NULL) 761 (void) putctl1(q, M_PCSIG, (int)d_arg); 762 mutex_exit(&pty->ptc_lock); 763 break; 764 765 case FIONBIO: 766 copy_in(data, d_arg); 767 mutex_enter(&pty->ptc_lock); 768 if (d_arg) 769 pty->pt_flags |= PF_NBIO; 770 else 771 pty->pt_flags &= ~PF_NBIO; 772 mutex_exit(&pty->ptc_lock); 773 break; 774 775 case FIOASYNC: 776 copy_in(data, d_arg); 777 mutex_enter(&pty->ptc_lock); 778 if (d_arg) 779 pty->pt_flags |= PF_ASYNC; 780 else 781 pty->pt_flags &= ~PF_ASYNC; 782 mutex_exit(&pty->ptc_lock); 783 break; 784 785 /* 786 * These, at least, can work on the manager-side process 787 * group. 788 */ 789 case FIOGETOWN: 790 mutex_enter(&pty->ptc_lock); 791 d_arg = -pty->pt_pgrp; 792 mutex_exit(&pty->ptc_lock); 793 copy_out(d_arg, data); 794 break; 795 796 case FIOSETOWN: 797 copy_in(data, d_arg); 798 mutex_enter(&pty->ptc_lock); 799 pty->pt_pgrp = (short)(-d_arg); 800 mutex_exit(&pty->ptc_lock); 801 break; 802 803 case FIONREAD: { 804 /* 805 * Return the total number of bytes of data in all messages in 806 * subsidiary write queue, which is manager read queue, unless 807 * a special message would be read. 808 */ 809 mblk_t *mp; 810 size_t count = 0; 811 812 mutex_enter(&pty->ptc_lock); 813 if (pty->pt_flags&(PF_PKT|PF_UCNTL) && pty->pt_send) 814 count = 1; /* will return 1 byte */ 815 else if ((pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) && 816 pty->pt_ucntl) 817 count = 1; /* will return 1 byte */ 818 else if ((q = pty->pt_ttycommon.t_writeq) != NULL && 819 q->q_first != NULL && !(pty->pt_flags & PF_STOPPED)) { 820 /* 821 * Will return whatever data is queued up. 822 */ 823 for (mp = q->q_first; mp != NULL; mp = mp->b_next) 824 count += msgdsize(mp); 825 } else if ((pty->pt_flags & PF_UCNTL) && 826 pty->pt_stuffqfirst != NULL) { 827 /* 828 * Will return STI'ed data. 829 */ 830 count = pty->pt_stuffqlen + 1; 831 } 832 833 /* 834 * Under LP64 we could have more than INT_MAX bytes to report, 835 * but the interface is defined in terms of int, so we cap it. 836 */ 837 d_arg = MIN(count, INT_MAX); 838 mutex_exit(&pty->ptc_lock); 839 copy_out(d_arg, data); 840 break; 841 } 842 843 case TIOCSWINSZ: 844 /* 845 * Unfortunately, TIOCSWINSZ and the old TIOCSSIZE "ioctl"s 846 * share the same code. If the upper 16 bits of the number 847 * of lines is non-zero, it was probably a TIOCSWINSZ, 848 * with both "ws_row" and "ws_col" non-zero. 849 */ 850 if (copyin((caddr_t)data, 851 &tty_arg, sizeof (struct ttysize)) != 0) 852 return (EFAULT); 853 854 if ((tty_arg.ts_lines & 0xffff0000) != 0) { 855 /* 856 * It's a TIOCSWINSZ. 857 */ 858 win_arg = *(struct winsize *)&tty_arg; 859 860 mutex_enter(&pty->ptc_lock); 861 /* 862 * If the window size changed, send a SIGWINCH. 863 */ 864 if (bcmp(&pty->pt_ttycommon.t_size, 865 &win_arg, sizeof (struct winsize))) { 866 pty->pt_ttycommon.t_size = win_arg; 867 if ((q = pty->pt_ttycommon.t_readq) != NULL) 868 (void) putctl1(q, M_PCSIG, SIGWINCH); 869 } 870 mutex_exit(&pty->ptc_lock); 871 break; 872 } 873 /* FALLTHROUGH */ 874 875 case TIOCSSIZE: 876 if (copyin((caddr_t)data, 877 &tty_arg, sizeof (struct ttysize)) != 0) 878 return (EFAULT); 879 mutex_enter(&pty->ptc_lock); 880 pty->pt_ttycommon.t_size.ws_row = (ushort_t)tty_arg.ts_lines; 881 pty->pt_ttycommon.t_size.ws_col = (ushort_t)tty_arg.ts_cols; 882 pty->pt_ttycommon.t_size.ws_xpixel = 0; 883 pty->pt_ttycommon.t_size.ws_ypixel = 0; 884 mutex_exit(&pty->ptc_lock); 885 break; 886 887 case TIOCGWINSZ: 888 mutex_enter(&pty->ptc_lock); 889 win_arg = pty->pt_ttycommon.t_size; 890 mutex_exit(&pty->ptc_lock); 891 if (copyout(&win_arg, (caddr_t)data, 892 sizeof (struct winsize)) != 0) 893 return (EFAULT); 894 break; 895 896 case TIOCGSIZE: 897 mutex_enter(&pty->ptc_lock); 898 tty_arg.ts_lines = pty->pt_ttycommon.t_size.ws_row; 899 tty_arg.ts_cols = pty->pt_ttycommon.t_size.ws_col; 900 mutex_exit(&pty->ptc_lock); 901 if (copyout(&tty_arg, (caddr_t)data, 902 sizeof (struct ttysize)) != 0) 903 return (EFAULT); 904 break; 905 906 /* 907 * XXX These should not be here. The only reason why an 908 * "ioctl" on the manager side should get the 909 * subsidiary side's process group is so that the process on 910 * the manager side can send a signal to the subsidiary 911 * side's process group; however, this is better done 912 * with TIOCSIGNAL, both because it doesn't require us 913 * to know about the subsidiary side's process group and because 914 * the manager side process may not have permission to 915 * send that signal to the entire process group. 916 * 917 * However, since vanilla 4BSD doesn't provide TIOCSIGNAL, 918 * we can't just get rid of them. 919 */ 920 case TIOCGPGRP: 921 case TIOCSPGRP: 922 /* 923 * This is amazingly disgusting, but the stupid semantics of 924 * 4BSD pseudo-ttys makes us do it. If we do one of these guys 925 * on the manager side, it really applies to the subsidiary-side 926 * stream. It should NEVER have been possible to do ANY sort 927 * of tty operations on the manager side, but it's too late 928 * to fix that now. However, we won't waste our time implementing 929 * anything that the original pseudo-tty driver didn't handle. 930 */ 931 case TIOCGETP: 932 case TIOCSETP: 933 case TIOCSETN: 934 case TIOCGETC: 935 case TIOCSETC: 936 case TIOCGLTC: 937 case TIOCSLTC: 938 case TIOCLGET: 939 case TIOCLSET: 940 case TIOCLBIS: 941 case TIOCLBIC: 942 mutex_enter(&pty->ptc_lock); 943 if (pty->pt_vnode == NULL) { 944 mutex_exit(&pty->ptc_lock); 945 return (EIO); 946 } 947 pty->pt_flags |= PF_IOCTL; 948 mutex_exit(&pty->ptc_lock); 949 err = strioctl(pty->pt_vnode, cmd, data, flag, 950 U_TO_K, cred, rvalp); 951 mutex_enter(&pty->ptc_lock); 952 if (pty->pt_flags & PF_WAIT) 953 cv_signal(&pty->pt_cv_flags); 954 pty->pt_flags &= ~(PF_IOCTL|PF_WAIT); 955 mutex_exit(&pty->ptc_lock); 956 return (err); 957 958 default: 959 return (ENOTTY); 960 } 961 962 return (0); 963 } 964 965 966 int 967 ptcpoll(dev_t dev, short events, int anyyet, short *reventsp, 968 struct pollhead **phpp) 969 { 970 struct pty *pty = &pty_softc[getminor(dev)]; 971 pollhead_t *php = &ptcph; 972 queue_t *q; 973 int pos = 0; 974 975 if (polllock(php, &pty->ptc_lock) != 0) { 976 *reventsp = POLLNVAL; 977 return (0); 978 } 979 980 ASSERT(MUTEX_HELD(&pty->ptc_lock)); 981 982 *reventsp = 0; 983 if (pty->pt_flags & PF_SUBSIDGONE) { 984 if (events & (POLLIN|POLLRDNORM)) 985 *reventsp |= (events & (POLLIN|POLLRDNORM)); 986 if (events & (POLLOUT|POLLWRNORM)) 987 *reventsp |= (events & (POLLOUT|POLLWRNORM)); 988 mutex_exit(&pty->ptc_lock); 989 /* 990 * A non NULL pollhead pointer should be returned in case 991 * user polls for 0 events. 992 */ 993 *phpp = !anyyet && !*reventsp ? php : (struct pollhead *)NULL; 994 return (0); 995 } 996 if (events & (POLLIN|POLLRDNORM)) { 997 if ((q = pty->pt_ttycommon.t_writeq) != NULL && 998 q->q_first != NULL && !(pty->pt_flags & PF_STOPPED)) { 999 /* 1000 * Regular data is available. 1001 */ 1002 *reventsp |= (events & (POLLIN|POLLRDNORM)); 1003 pos++; 1004 } 1005 if (pty->pt_flags & (PF_PKT|PF_UCNTL) && pty->pt_send) { 1006 /* 1007 * A control packet is available. 1008 */ 1009 *reventsp |= (events & (POLLIN|POLLRDNORM)); 1010 pos++; 1011 } 1012 if ((pty->pt_flags & PF_UCNTL) && 1013 (pty->pt_ucntl || pty->pt_stuffqfirst != NULL)) { 1014 /* 1015 * "ioctl" or TIOCSTI data is available. 1016 */ 1017 *reventsp |= (events & (POLLIN|POLLRDNORM)); 1018 pos++; 1019 } 1020 if ((pty->pt_flags & PF_43UCNTL) && pty->pt_ucntl) { 1021 *reventsp |= (events & (POLLIN|POLLRDNORM)); 1022 pos++; 1023 } 1024 } 1025 if (events & (POLLOUT|POLLWRNORM)) { 1026 if ((q = pty->pt_ttycommon.t_readq) != NULL && 1027 canput(q)) { 1028 *reventsp |= (events & (POLLOUT|POLLWRNORM)); 1029 pos++; 1030 } 1031 } 1032 if (events & POLLERR) { 1033 *reventsp |= POLLERR; 1034 pos++; 1035 } 1036 if (events == 0) { /* "exceptional conditions" */ 1037 if (((pty->pt_flags & (PF_PKT|PF_UCNTL)) && pty->pt_send) || 1038 ((pty->pt_flags & PF_UCNTL) && 1039 (pty->pt_ucntl || pty->pt_stuffqfirst != NULL))) { 1040 pos++; 1041 } 1042 if ((pty->pt_flags & PF_43UCNTL) && pty->pt_ucntl) { 1043 pos++; 1044 } 1045 } 1046 1047 /* 1048 * Arrange to have poll waken up when event occurs. 1049 * if (!anyyet) 1050 */ 1051 if (!pos) { 1052 *phpp = php; 1053 *reventsp = 0; 1054 } 1055 1056 mutex_exit(&pty->ptc_lock); 1057 return (0); 1058 } 1059 1060 void 1061 gsignal(int pid, int sig) 1062 { 1063 procset_t set; 1064 sigsend_t v; 1065 1066 bzero(&v, sizeof (v)); 1067 v.sig = sig; 1068 v.perm = 0; 1069 v.checkperm = 1; 1070 v.value.sival_ptr = NULL; 1071 1072 setprocset(&set, POP_AND, P_PGID, -pid, P_ALL, P_MYID); 1073 (void) sigsendset(&set, &v); 1074 } 1075 1076 static int 1077 makemsg(ssize_t count, struct uio *uiop, struct pty *pty, mblk_t **mpp) 1078 { 1079 int pri = BPRI_LO; 1080 int error; 1081 mblk_t *bp = NULL; 1082 1083 ASSERT(MUTEX_HELD(&pty->ptc_lock)); 1084 1085 *mpp = NULL; 1086 1087 /* 1088 * Create data part of message, if any. 1089 */ 1090 if (count >= 0) { 1091 if ((bp = allocb(count, pri)) == NULL) 1092 return (ENOSR); 1093 1094 mutex_exit(&pty->ptc_lock); 1095 error = uiomove((caddr_t)bp->b_wptr, count, UIO_WRITE, uiop); 1096 mutex_enter(&pty->ptc_lock); 1097 if (error) { 1098 freeb(bp); 1099 return (error); 1100 } 1101 1102 bp->b_wptr += count; 1103 } 1104 1105 *mpp = bp; 1106 return (0); 1107 } 1108