Print this page
14249 pseudo-terminal nomenclature should reflect POSIX
Change-Id: Ib4a3cef899ff4c71b09cb0dc6878863c5e8357bc
   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-tty" device.  For each "controller" side
  15  * it connects to a "slave" 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>    /* 1/0 on the vomit meter */
  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 */


  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, /* Type of module.  This one is a pseudo driver */
 120         "tty pseudo driver control 'ptc'",
 121         &ptc_ops,   /* driver 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


 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  * Controller 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 /*ARGSUSED*/
 245 int
 246 ptcopen(dev_t *devp, int flag, int otyp, struct cred *cred)
 247 {
 248         dev_t dev = *devp;
 249         struct pty *pty;
 250         queue_t *q;
 251 
 252         if (getminor(dev) >= npty) {
 253                 return (ENXIO);
 254         }
 255         pty = &pty_softc[getminor(dev)];
 256         mutex_enter(&pty->ptc_lock);
 257         if (pty->pt_flags & PF_CARR_ON) {
 258                 mutex_exit(&pty->ptc_lock);
 259                 return (EIO);   /* controller is exclusive use */
 260                                 /* XXX - should be EBUSY! */
 261         }
 262         if (pty->pt_flags & PF_WOPEN) {
 263                 pty->pt_flags &= ~PF_WOPEN;
 264                 cv_broadcast(&pty->pt_cv_flags);
 265         }
 266 
 267         if ((q = pty->pt_ttycommon.t_readq) != NULL) {
 268                 /*
 269                  * Send an un-hangup to the slave, since "carrier" is
 270                  * coming back up.  Make sure we're doing canonicalization.
 271                  */
 272                 (void) putctl(q, M_UNHANGUP);
 273                 (void) putctl1(q, M_CTL, MC_DOCANON);
 274         }
 275         pty->pt_flags |= PF_CARR_ON;
 276         pty->pt_send = 0;
 277         pty->pt_ucntl = 0;
 278 
 279         mutex_exit(&pty->ptc_lock);
 280         return (0);
 281 }
 282 
 283 /*ARGSUSED1*/
 284 int
 285 ptcclose(dev_t dev, int flag, int otyp, struct cred *cred)
 286 {
 287         struct pty *pty;
 288         mblk_t *bp;
 289         queue_t *q;
 290 
 291         pty = &pty_softc[getminor(dev)];
 292 
 293         mutex_enter(&pty->ptc_lock);
 294         if ((q = pty->pt_ttycommon.t_readq) != NULL) {
 295                 /*
 296                  * Send a hangup to the slave, since "carrier" is dropping.
 297                  */
 298                 (void) putctl(q, M_HANGUP);
 299         }
 300 
 301         /*
 302          * Clear out all the controller-side state.  This also
 303          * clears PF_CARR_ON, which is correct because the
 304          * "carrier" is dropping since the controller process
 305          * is going away.
 306          */
 307         pty->pt_flags &= (PF_WOPEN|PF_STOPPED|PF_NOSTOP);
 308         while ((bp = pty->pt_stuffqfirst) != NULL) {
 309                 if ((pty->pt_stuffqfirst = bp->b_next) == NULL)
 310                         pty->pt_stuffqlast = NULL;
 311                 else
 312                         pty->pt_stuffqfirst->b_prev = NULL;
 313                 pty->pt_stuffqlen--;
 314                 bp->b_next = bp->b_prev = NULL;
 315                 freemsg(bp);
 316         }
 317         mutex_exit(&pty->ptc_lock);
 318         return (0);
 319 }
 320 
 321 int
 322 ptcread(dev_t dev, struct uio *uio, struct cred *cred)
 323 {
 324         struct pty *pty = &pty_softc[getminor(dev)];
 325         mblk_t *bp, *nbp;
 326         queue_t *q;
 327         unsigned char tmp;
 328         ssize_t cc;
 329         int error;
 330         off_t off;
 331 
 332 #ifdef lint
 333         cred = cred;
 334 #endif
 335 
 336         off = uio->uio_offset;
 337 
 338         mutex_enter(&pty->ptc_lock);
 339 
 340         for (;;) {
 341                 while (pty->pt_flags & PF_READ) {
 342                         pty->pt_flags |= PF_WREAD;
 343                         cv_wait(&pty->pt_cv_flags, &pty->ptc_lock);
 344                 }
 345                 pty->pt_flags |= PF_READ;
 346 
 347                 /*
 348                  * If there's a TIOCPKT packet waiting, pass it back.
 349                  */
 350                 while (pty->pt_flags&(PF_PKT|PF_UCNTL) && pty->pt_send) {
 351                         tmp = pty->pt_send;
 352                         pty->pt_send = 0;
 353                         mutex_exit(&pty->ptc_lock);
 354                         error = ureadc((int)tmp, uio);
 355                         uio->uio_offset = off;


 458                         while (error == 0 &&
 459                             (bp = pty->pt_stuffqfirst) != NULL &&
 460                             uio->uio_resid > 0) {
 461                                 pty->pt_stuffqlen--;
 462                                 if ((pty->pt_stuffqfirst = bp->b_next) == NULL)
 463                                         pty->pt_stuffqlast = NULL;
 464                                 else
 465                                         pty->pt_stuffqfirst->b_prev = NULL;
 466                                 mutex_exit(&pty->ptc_lock);
 467                                 error = ureadc((int)*bp->b_rptr, uio);
 468                                 bp->b_next = bp->b_prev = NULL;
 469                                 freemsg(bp);
 470                                 mutex_enter(&pty->ptc_lock);
 471                         }
 472                         uio->uio_offset = off;
 473                         goto out;
 474                 }
 475 
 476                 /*
 477                  * There's no data available.
 478                  * We want to block until the slave is open, and there's
 479                  * something to read; but if we lost the slave or we're NBIO,
 480                  * then return the appropriate error instead.  POSIX-style
 481                  * non-block has top billing and gives -1 with errno = EAGAIN,
 482                  * BSD-style comes next and gives -1 with errno = EWOULDBLOCK,
 483                  * SVID-style comes last and gives 0.
 484                  */
 485                 if (pty->pt_flags & PF_SLAVEGONE) {
 486                         error = EIO;
 487                         goto out;
 488                 }
 489                 if (uio->uio_fmode & FNONBLOCK) {
 490                         error = EAGAIN;
 491                         goto out;
 492                 }
 493                 if (pty->pt_flags & PF_NBIO) {
 494                         error = EWOULDBLOCK;
 495                         goto out;
 496                 }
 497                 if (uio->uio_fmode & FNDELAY)
 498                         goto out;
 499 
 500                 if (pty->pt_flags & PF_WREAD)
 501                         cv_broadcast(&pty->pt_cv_flags);
 502 
 503                 pty->pt_flags &= ~(PF_READ | PF_WREAD);
 504 
 505 


 515 
 516         pty->pt_flags &= ~(PF_READ | PF_WREAD);
 517 
 518         mutex_exit(&pty->ptc_lock);
 519         return (error);
 520 }
 521 
 522 int
 523 ptcwrite(dev_t dev, struct uio *uio, struct cred *cred)
 524 {
 525         struct pty *pty = &pty_softc[getminor(dev)];
 526         queue_t *q;
 527         int written;
 528         mblk_t *mp;
 529         int fmode = 0;
 530         int error = 0;
 531 
 532         off_t off;
 533         off = uio->uio_offset;
 534 
 535 #ifdef lint
 536         cred = cred;
 537 #endif
 538 
 539 
 540         mutex_enter(&pty->ptc_lock);
 541 
 542 again:
 543         while (pty->pt_flags & PF_WRITE) {
 544                 pty->pt_flags |= PF_WWRITE;
 545                 cv_wait(&pty->pt_cv_flags, &pty->ptc_lock);
 546         }
 547 
 548         pty->pt_flags |= PF_WRITE;
 549 
 550         if ((q = pty->pt_ttycommon.t_readq) == NULL) {
 551 
 552                 /*
 553                  * Wait for slave to open.
 554                  */
 555                 if (pty->pt_flags & PF_SLAVEGONE) {
 556                         error = EIO;
 557                         goto out;
 558                 }
 559                 if (uio->uio_fmode & FNONBLOCK) {
 560                         error = EAGAIN;
 561                         goto out;
 562                 }
 563                 if (pty->pt_flags & PF_NBIO) {
 564                         error = EWOULDBLOCK;
 565                         goto out;
 566                 }
 567                 if (uio->uio_fmode & FNDELAY)
 568                         goto out;
 569 
 570                 if (pty->pt_flags & PF_WWRITE)
 571                         cv_broadcast(&pty->pt_cv_flags);
 572 
 573                 pty->pt_flags &= ~(PF_WRITE | PF_WWRITE);
 574 
 575                 if (!cv_wait_sig(&pty->pt_cv_readq, &pty->ptc_lock)) {
 576                         mutex_exit(&pty->ptc_lock);
 577                         return (EINTR);
 578                 }
 579 
 580                 goto again;
 581         }
 582 
 583         /*
 584          * If in remote mode, even zero-length writes generate messages.
 585          */
 586         written = 0;
 587         if ((pty->pt_flags & PF_REMOTE) || uio->uio_resid > 0) {
 588                 do {
 589                         while (!canput(q)) {
 590                                 /*
 591                                  * Wait for slave's read queue to unclog.
 592                                  */
 593                                 if (pty->pt_flags & PF_SLAVEGONE) {
 594                                         error = EIO;
 595                                         goto out;
 596                                 }
 597                                 if (uio->uio_fmode & FNONBLOCK) {
 598                                         if (!written)
 599                                                 error = EAGAIN;
 600                                         goto out;
 601                                 }
 602                                 if (pty->pt_flags & PF_NBIO) {
 603                                         if (!written)
 604                                                 error = EWOULDBLOCK;
 605                                         goto out;
 606                                 }
 607                                 if (uio->uio_fmode & FNDELAY)
 608                                         goto out;
 609 
 610                                 if (pty->pt_flags & PF_WWRITE)
 611                                         cv_broadcast(&pty->pt_cv_flags);
 612 
 613                                 pty->pt_flags &= ~(PF_WRITE | PF_WWRITE);


 746                 mutex_exit(&pty->ptc_lock);
 747                 break;
 748 
 749         case TIOCREMOTE:
 750                 copy_in(data, d_arg);
 751                 mutex_enter(&pty->ptc_lock);
 752                 if (d_arg) {
 753                         if ((q = pty->pt_ttycommon.t_readq) != NULL)
 754                                 (void) putctl1(q, M_CTL, MC_NOCANON);
 755                         pty->pt_flags |= PF_REMOTE;
 756                 } else {
 757                         if ((q = pty->pt_ttycommon.t_readq) != NULL)
 758                                 (void) putctl1(q, M_CTL, MC_DOCANON);
 759                         pty->pt_flags &= ~PF_REMOTE;
 760                 }
 761                 mutex_exit(&pty->ptc_lock);
 762                 break;
 763 
 764         case TIOCSIGNAL:
 765                 /*
 766                  * Blast a M_PCSIG message up the slave stream; the
 767                  * signal number is the argument to the "ioctl".
 768                  */
 769                 copy_in(data, d_arg);
 770                 mutex_enter(&pty->ptc_lock);
 771                 if ((q = pty->pt_ttycommon.t_readq) != NULL)
 772                         (void) putctl1(q, M_PCSIG, (int)d_arg);
 773                 mutex_exit(&pty->ptc_lock);
 774                 break;
 775 
 776         case FIONBIO:
 777                 copy_in(data, d_arg);
 778                 mutex_enter(&pty->ptc_lock);
 779                 if (d_arg)
 780                         pty->pt_flags |= PF_NBIO;
 781                 else
 782                         pty->pt_flags &= ~PF_NBIO;
 783                 mutex_exit(&pty->ptc_lock);
 784                 break;
 785 
 786         case FIOASYNC:
 787                 copy_in(data, d_arg);
 788                 mutex_enter(&pty->ptc_lock);
 789                 if (d_arg)
 790                         pty->pt_flags |= PF_ASYNC;
 791                 else
 792                         pty->pt_flags &= ~PF_ASYNC;
 793                 mutex_exit(&pty->ptc_lock);
 794                 break;
 795 
 796         /*
 797          * These, at least, can work on the controller-side process
 798          * group.
 799          */
 800         case FIOGETOWN:
 801                 mutex_enter(&pty->ptc_lock);
 802                 d_arg = -pty->pt_pgrp;
 803                 mutex_exit(&pty->ptc_lock);
 804                 copy_out(d_arg, data);
 805                 break;
 806 
 807         case FIOSETOWN:
 808                 copy_in(data, d_arg);
 809                 mutex_enter(&pty->ptc_lock);
 810                 pty->pt_pgrp = (short)(-d_arg);
 811                 mutex_exit(&pty->ptc_lock);
 812                 break;
 813 
 814         case FIONREAD: {
 815                 /*
 816                  * Return the total number of bytes of data in all messages
 817                  * in slave write queue, which is master read queue, unless a
 818                  * special message would be read.
 819                  */
 820                 mblk_t *mp;
 821                 size_t count = 0;
 822 
 823                 mutex_enter(&pty->ptc_lock);
 824                 if (pty->pt_flags&(PF_PKT|PF_UCNTL) && pty->pt_send)
 825                         count = 1;      /* will return 1 byte */
 826                 else if ((pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) &&
 827                     pty->pt_ucntl)
 828                         count = 1;      /* will return 1 byte */
 829                 else if ((q = pty->pt_ttycommon.t_writeq) != NULL &&
 830                     q->q_first != NULL && !(pty->pt_flags & PF_STOPPED)) {
 831                         /*
 832                          * Will return whatever data is queued up.
 833                          */
 834                         for (mp = q->q_first; mp != NULL; mp = mp->b_next)
 835                                 count += msgdsize(mp);
 836                 } else if ((pty->pt_flags & PF_UCNTL) &&
 837                     pty->pt_stuffqfirst != NULL) {
 838                         /*


 899                 mutex_enter(&pty->ptc_lock);
 900                 win_arg = pty->pt_ttycommon.t_size;
 901                 mutex_exit(&pty->ptc_lock);
 902                 if (copyout(&win_arg, (caddr_t)data,
 903                     sizeof (struct winsize)) != 0)
 904                         return (EFAULT);
 905                 break;
 906 
 907         case TIOCGSIZE:
 908                 mutex_enter(&pty->ptc_lock);
 909                 tty_arg.ts_lines = pty->pt_ttycommon.t_size.ws_row;
 910                 tty_arg.ts_cols = pty->pt_ttycommon.t_size.ws_col;
 911                 mutex_exit(&pty->ptc_lock);
 912                 if (copyout(&tty_arg, (caddr_t)data,
 913                     sizeof (struct ttysize)) != 0)
 914                         return (EFAULT);
 915                 break;
 916 
 917         /*
 918          * XXX These should not be here.  The only reason why an
 919          * "ioctl" on the controller side should get the
 920          * slave side's process group is so that the process on
 921          * the controller side can send a signal to the slave
 922          * side's process group; however, this is better done
 923          * with TIOCSIGNAL, both because it doesn't require us
 924          * to know about the slave side's process group and because
 925          * the controller side process may not have permission to
 926          * send that signal to the entire process group.
 927          *
 928          * However, since vanilla 4BSD doesn't provide TIOCSIGNAL,
 929          * we can't just get rid of them.
 930          */
 931         case TIOCGPGRP:
 932         case TIOCSPGRP:
 933         /*
 934          * This is amazingly disgusting, but the stupid semantics of
 935          * 4BSD pseudo-ttys makes us do it.  If we do one of these guys
 936          * on the controller side, it really applies to the slave-side
 937          * stream.  It should NEVER have been possible to do ANY sort
 938          * of tty operations on the controller side, but it's too late
 939          * to fix that now.  However, we won't waste our time implementing
 940          * anything that the original pseudo-tty driver didn't handle.
 941          */
 942         case TIOCGETP:
 943         case TIOCSETP:
 944         case TIOCSETN:
 945         case TIOCGETC:
 946         case TIOCSETC:
 947         case TIOCGLTC:
 948         case TIOCSLTC:
 949         case TIOCLGET:
 950         case TIOCLSET:
 951         case TIOCLBIS:
 952         case TIOCLBIC:
 953                 mutex_enter(&pty->ptc_lock);
 954                 if (pty->pt_vnode == NULL) {
 955                         mutex_exit(&pty->ptc_lock);
 956                         return (EIO);
 957                 }
 958                 pty->pt_flags |= PF_IOCTL;


 966                 mutex_exit(&pty->ptc_lock);
 967                 return (err);
 968 
 969         default:
 970                 return (ENOTTY);
 971         }
 972 
 973         return (0);
 974 }
 975 
 976 
 977 int
 978 ptcpoll(dev_t dev, short events, int anyyet, short *reventsp,
 979     struct pollhead **phpp)
 980 {
 981         struct pty *pty = &pty_softc[getminor(dev)];
 982         pollhead_t *php = &ptcph;
 983         queue_t *q;
 984         int pos = 0;
 985 
 986 #ifdef lint
 987         anyyet = anyyet;
 988 #endif
 989         if (polllock(php, &pty->ptc_lock) != 0) {
 990                 *reventsp = POLLNVAL;
 991                 return (0);
 992         }
 993 
 994         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 995 
 996         *reventsp = 0;
 997         if (pty->pt_flags & PF_SLAVEGONE) {
 998                 if (events & (POLLIN|POLLRDNORM))
 999                         *reventsp |= (events & (POLLIN|POLLRDNORM));
1000                 if (events & (POLLOUT|POLLWRNORM))
1001                         *reventsp |= (events & (POLLOUT|POLLWRNORM));
1002                 mutex_exit(&pty->ptc_lock);
1003                 /*
1004                  * A non NULL pollhead pointer should be returned in case
1005                  * user polls for 0 events.
1006                  */
1007                 *phpp = !anyyet && !*reventsp ? php : (struct pollhead *)NULL;
1008                 return (0);
1009         }
1010         if (events & (POLLIN|POLLRDNORM)) {
1011                 if ((q = pty->pt_ttycommon.t_writeq) != NULL &&
1012                     q->q_first != NULL && !(pty->pt_flags & PF_STOPPED)) {
1013                         /*
1014                          * Regular data is available.
1015                          */
1016                         *reventsp |= (events & (POLLIN|POLLRDNORM));
1017                         pos++;


   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 */


  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


 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;


 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 


 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);


 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                         /*


 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;


 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++;