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 }