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 */
  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, /* 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
 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, NULL) == 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  * 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;
 356                         mutex_enter(&pty->ptc_lock);
 357                         if (error) {
 358                                 pty->pt_send |= tmp;
 359                                 goto out;
 360                         }
 361                         if (pty->pt_send == 0)
 362                                 goto out;
 363                 }
 364 
 365                 /*
 366                  * If there's a user-control packet waiting, pass the
 367                  * "ioctl" code back.
 368                  */
 369                 while ((pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) &&
 370                     pty->pt_ucntl) {
 371                         tmp = pty->pt_ucntl;
 372                         pty->pt_ucntl = 0;
 373                         mutex_exit(&pty->ptc_lock);
 374                         error = ureadc((int)tmp, uio);
 375                         uio->uio_offset = off;
 376                         mutex_enter(&pty->ptc_lock);
 377                         if (error) {
 378                                 if (pty->pt_ucntl == 0)
 379                                         pty->pt_ucntl = tmp;
 380                                 goto out;
 381                         }
 382                         if (pty->pt_ucntl == 0)
 383                                 goto out;
 384                 }
 385 
 386                 /*
 387                  * If there's any data waiting, pass it back.
 388                  */
 389                 if ((q = pty->pt_ttycommon.t_writeq) != NULL &&
 390                     q->q_first != NULL &&
 391                     !(pty->pt_flags & PF_STOPPED)) {
 392                         if (pty->pt_flags & (PF_PKT|PF_UCNTL|PF_43UCNTL)) {
 393                                 /*
 394                                  * We're about to begin a move in packet or
 395                                  * user-control mode; precede the data with a
 396                                  * data header.
 397                                  */
 398                                 mutex_exit(&pty->ptc_lock);
 399                                 error = ureadc(TIOCPKT_DATA, uio);
 400                                 uio->uio_offset = off;
 401                                 mutex_enter(&pty->ptc_lock);
 402                                 if (error != 0)
 403                                         goto out;
 404                                 if ((q = pty->pt_ttycommon.t_writeq) == NULL)
 405                                         goto out;
 406                         }
 407                         if ((bp = getq(q)) == NULL)
 408                                 goto out;
 409                         while (uio->uio_resid > 0) {
 410                                 while ((cc = bp->b_wptr - bp->b_rptr) == 0) {
 411                                         nbp = bp->b_cont;
 412                                         freeb(bp);
 413                                         if ((bp = nbp) == NULL) {
 414                                                 if ((q == NULL) ||
 415                                                     (bp = getq(q)) == NULL)
 416                                                         goto out;
 417                                         }
 418                                 }
 419                                 cc = MIN(cc, uio->uio_resid);
 420                                 mutex_exit(&pty->ptc_lock);
 421                                 error = uiomove((caddr_t)bp->b_rptr,
 422                                     cc, UIO_READ, uio);
 423                                 uio->uio_offset = off;
 424                                 mutex_enter(&pty->ptc_lock);
 425                                 if (error != 0) {
 426                                         freemsg(bp);
 427                                         goto out;
 428                                 }
 429                                 q = pty->pt_ttycommon.t_writeq;
 430                                 bp->b_rptr += cc;
 431                         }
 432                         /*
 433                          * Strip off zero-length blocks from the front of
 434                          * what we're putting back on the queue.
 435                          */
 436                         while ((bp->b_wptr - bp->b_rptr) == 0) {
 437                                 nbp = bp->b_cont;
 438                                 freeb(bp);
 439                                 if ((bp = nbp) == NULL)
 440                                         goto out;       /* nothing left */
 441                         }
 442                         if (q != NULL)
 443                                 (void) putbq(q, bp);
 444                         else
 445                                 freemsg(bp);
 446                         goto out;
 447                 }
 448 
 449                 /*
 450                  * If there's any TIOCSTI-stuffed characters, pass
 451                  * them back.  (They currently arrive after all output;
 452                  * is this correct?)
 453                  */
 454                 if (pty->pt_flags&PF_UCNTL && pty->pt_stuffqfirst != NULL) {
 455                         mutex_exit(&pty->ptc_lock);
 456                         error = ureadc(TIOCSTI&0xff, uio);
 457                         mutex_enter(&pty->ptc_lock);
 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 
 506                 if (!cv_wait_sig(&pty->pt_cv_writeq, &pty->ptc_lock)) {
 507                         mutex_exit(&pty->ptc_lock);
 508                         return (EINTR);
 509                 }
 510         }
 511 
 512 out:
 513         if (pty->pt_flags & PF_WREAD)
 514                 cv_broadcast(&pty->pt_cv_flags);
 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);
 614 
 615                                 if (!cv_wait_sig(&pty->pt_cv_readq,
 616                                     &pty->ptc_lock)) {
 617                                         mutex_exit(&pty->ptc_lock);
 618                                         return (EINTR);
 619                                 }
 620 
 621                                 while (pty->pt_flags & PF_WRITE) {
 622                                         pty->pt_flags |= PF_WWRITE;
 623                                         cv_wait(&pty->pt_cv_flags,
 624                                             &pty->ptc_lock);
 625                                 }
 626 
 627                                 pty->pt_flags |= PF_WRITE;
 628                         }
 629 
 630                         if ((pty->pt_flags & PF_NBIO) &&
 631                             !(uio->uio_fmode & FNONBLOCK)) {
 632                                 fmode = uio->uio_fmode;
 633                                 uio->uio_fmode |= FNONBLOCK;
 634                         }
 635 
 636                         error = makemsg(uio->uio_resid, uio, pty, &mp);
 637                         uio->uio_offset = off;
 638                         if (fmode)
 639                                 uio->uio_fmode = fmode;
 640                         if (error != 0) {
 641                                 if (error != EAGAIN && error != EWOULDBLOCK)
 642                                         goto out;
 643                                 if (uio->uio_fmode & FNONBLOCK) {
 644                                         if (!written)
 645                                                 error = EAGAIN;
 646                                         goto out;
 647                                 }
 648                                 if (pty->pt_flags & PF_NBIO) {
 649                                         if (!written)
 650                                                 error = EWOULDBLOCK;
 651                                         goto out;
 652                                 }
 653                                 if (uio->uio_fmode & FNDELAY)
 654                                         goto out;
 655                                 cmn_err(CE_PANIC,
 656                                     "ptcwrite: non null return from"
 657                                     " makemsg");
 658                         }
 659 
 660                         /*
 661                          * Check again for safety; since "uiomove" can take a
 662                          * page fault, there's no guarantee that "pt_flags"
 663                          * didn't change while it was happening.
 664                          */
 665                         if ((q = pty->pt_ttycommon.t_readq) == NULL) {
 666                                 if (mp)
 667                                         freemsg(mp);
 668                                 error = EIO;
 669                                 goto out;
 670                         }
 671                         if (mp)
 672                                 (void) putq(q, mp);
 673                         written = 1;
 674                 } while (uio->uio_resid > 0);
 675         }
 676 out:
 677         if (pty->pt_flags & PF_WWRITE)
 678                 cv_broadcast(&pty->pt_cv_flags);
 679 
 680         pty->pt_flags &= ~(PF_WRITE | PF_WWRITE);
 681 
 682         mutex_exit(&pty->ptc_lock);
 683         return (error);
 684 }
 685 
 686 #define copy_in(data, d_arg) \
 687         if (copyin((caddr_t)data, &d_arg, sizeof (int)) != 0) \
 688                 return (EFAULT)
 689 
 690 #define copy_out(d_arg, data) \
 691         if (copyout(&d_arg, (caddr_t)data, sizeof (int)) != 0) \
 692                 return (EFAULT)
 693 
 694 int
 695 ptcioctl(dev_t dev, int cmd, intptr_t data, int flag, struct cred *cred,
 696     int *rvalp)
 697 {
 698         struct pty *pty = &pty_softc[getminor(dev)];
 699         queue_t *q;
 700         struct ttysize tty_arg;
 701         struct winsize win_arg;
 702         int d_arg;
 703         int err;
 704 
 705         switch (cmd) {
 706 
 707         case TIOCPKT:
 708                 copy_in(data, d_arg);
 709                 mutex_enter(&pty->ptc_lock);
 710                 if (d_arg) {
 711                         if (pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) {
 712                                 mutex_exit(&pty->ptc_lock);
 713                                 return (EINVAL);
 714                         }
 715                         pty->pt_flags |= PF_PKT;
 716                 } else
 717                         pty->pt_flags &= ~PF_PKT;
 718                 mutex_exit(&pty->ptc_lock);
 719                 break;
 720 
 721         case TIOCUCNTL:
 722                 copy_in(data, d_arg);
 723                 mutex_enter(&pty->ptc_lock);
 724                 if (d_arg) {
 725                         if (pty->pt_flags & (PF_PKT|PF_UCNTL)) {
 726                                 mutex_exit(&pty->ptc_lock);
 727                                 return (EINVAL);
 728                         }
 729                         pty->pt_flags |= PF_43UCNTL;
 730                 } else
 731                         pty->pt_flags &= ~PF_43UCNTL;
 732                 mutex_exit(&pty->ptc_lock);
 733                 break;
 734 
 735         case TIOCTCNTL:
 736                 copy_in(data, d_arg);
 737                 mutex_enter(&pty->ptc_lock);
 738                 if (d_arg) {
 739                         if (pty->pt_flags & PF_PKT) {
 740                                 mutex_exit(&pty->ptc_lock);
 741                                 return (EINVAL);
 742                         }
 743                         pty->pt_flags |= PF_UCNTL;
 744                 } else
 745                         pty->pt_flags &= ~PF_UCNTL;
 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                         /*
 839                          * Will return STI'ed data.
 840                          */
 841                         count = pty->pt_stuffqlen + 1;
 842                 }
 843 
 844                 /*
 845                  * Under LP64 we could have more than INT_MAX bytes to report,
 846                  * but the interface is defined in terms of int, so we cap it.
 847                  */
 848                 d_arg = MIN(count, INT_MAX);
 849                 mutex_exit(&pty->ptc_lock);
 850                 copy_out(d_arg, data);
 851                 break;
 852         }
 853 
 854         case TIOCSWINSZ:
 855                 /*
 856                  * Unfortunately, TIOCSWINSZ and the old TIOCSSIZE "ioctl"s
 857                  * share the same code.  If the upper 16 bits of the number
 858                  * of lines is non-zero, it was probably a TIOCSWINSZ,
 859                  * with both "ws_row" and "ws_col" non-zero.
 860                  */
 861                 if (copyin((caddr_t)data,
 862                     &tty_arg, sizeof (struct ttysize)) != 0)
 863                         return (EFAULT);
 864 
 865                 if ((tty_arg.ts_lines & 0xffff0000) != 0) {
 866                         /*
 867                          * It's a TIOCSWINSZ.
 868                          */
 869                         win_arg = *(struct winsize *)&tty_arg;
 870 
 871                         mutex_enter(&pty->ptc_lock);
 872                         /*
 873                          * If the window size changed, send a SIGWINCH.
 874                          */
 875                         if (bcmp(&pty->pt_ttycommon.t_size,
 876                             &win_arg, sizeof (struct winsize))) {
 877                                 pty->pt_ttycommon.t_size = win_arg;
 878                                 if ((q = pty->pt_ttycommon.t_readq) != NULL)
 879                                         (void) putctl1(q, M_PCSIG, SIGWINCH);
 880                         }
 881                         mutex_exit(&pty->ptc_lock);
 882                         break;
 883                 }
 884                 /* FALLTHROUGH */
 885 
 886         case TIOCSSIZE:
 887                 if (copyin((caddr_t)data,
 888                     &tty_arg, sizeof (struct ttysize)) != 0)
 889                         return (EFAULT);
 890                 mutex_enter(&pty->ptc_lock);
 891                 pty->pt_ttycommon.t_size.ws_row = (ushort_t)tty_arg.ts_lines;
 892                 pty->pt_ttycommon.t_size.ws_col = (ushort_t)tty_arg.ts_cols;
 893                 pty->pt_ttycommon.t_size.ws_xpixel = 0;
 894                 pty->pt_ttycommon.t_size.ws_ypixel = 0;
 895                 mutex_exit(&pty->ptc_lock);
 896                 break;
 897 
 898         case TIOCGWINSZ:
 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;
 959                 mutex_exit(&pty->ptc_lock);
 960                 err = strioctl(pty->pt_vnode, cmd, data, flag,
 961                     U_TO_K, cred, rvalp);
 962                 mutex_enter(&pty->ptc_lock);
 963                 if (pty->pt_flags & PF_WAIT)
 964                         cv_signal(&pty->pt_cv_flags);
 965                 pty->pt_flags &= ~(PF_IOCTL|PF_WAIT);
 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,
 979         short events,
 980         int anyyet,
 981         short *reventsp,
 982         struct pollhead **phpp)
 983 {
 984         struct pty *pty = &pty_softc[getminor(dev)];
 985         pollhead_t *php = &ptcph;
 986         queue_t *q;
 987         int pos = 0;
 988 
 989 #ifdef lint
 990         anyyet = anyyet;
 991 #endif
 992         if (polllock(php, &pty->ptc_lock) != 0) {
 993                 *reventsp = POLLNVAL;
 994                 return (0);
 995         }
 996 
 997         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 998 
 999         *reventsp = 0;
1000         if (pty->pt_flags & PF_SLAVEGONE) {
1001                 if (events & (POLLIN|POLLRDNORM))
1002                         *reventsp |= (events & (POLLIN|POLLRDNORM));
1003                 if (events & (POLLOUT|POLLWRNORM))
1004                         *reventsp |= (events & (POLLOUT|POLLWRNORM));
1005                 mutex_exit(&pty->ptc_lock);
1006                 /*
1007                  * A non NULL pollhead pointer should be returned in case
1008                  * user polls for 0 events.
1009                  */
1010                 *phpp = !anyyet && !*reventsp ? php : (struct pollhead *)NULL;
1011                 return (0);
1012         }
1013         if (events & (POLLIN|POLLRDNORM)) {
1014                 if ((q = pty->pt_ttycommon.t_writeq) != NULL &&
1015                     q->q_first != NULL && !(pty->pt_flags & PF_STOPPED)) {
1016                         /*
1017                          * Regular data is available.
1018                          */
1019                         *reventsp |= (events & (POLLIN|POLLRDNORM));
1020                         pos++;
1021                 }
1022                 if (pty->pt_flags & (PF_PKT|PF_UCNTL) && pty->pt_send) {
1023                         /*
1024                          * A control packet is available.
1025                          */
1026                         *reventsp |= (events & (POLLIN|POLLRDNORM));
1027                         pos++;
1028                 }
1029                 if ((pty->pt_flags & PF_UCNTL) &&
1030                     (pty->pt_ucntl || pty->pt_stuffqfirst != NULL)) {
1031                         /*
1032                          * "ioctl" or TIOCSTI data is available.
1033                          */
1034                         *reventsp |= (events & (POLLIN|POLLRDNORM));
1035                         pos++;
1036                 }
1037                 if ((pty->pt_flags & PF_43UCNTL) && pty->pt_ucntl) {
1038                         *reventsp |= (events & (POLLIN|POLLRDNORM));
1039                         pos++;
1040                 }
1041         }
1042         if (events & (POLLOUT|POLLWRNORM)) {
1043                 if ((q = pty->pt_ttycommon.t_readq) != NULL &&
1044                     canput(q)) {
1045                         *reventsp |= (events & (POLLOUT|POLLWRNORM));
1046                         pos++;
1047                 }
1048         }
1049         if (events & POLLERR) {
1050                 *reventsp |= POLLERR;
1051                 pos++;
1052         }
1053         if (events == 0) {      /* "exceptional conditions" */
1054                 if (((pty->pt_flags & (PF_PKT|PF_UCNTL)) && pty->pt_send) ||
1055                     ((pty->pt_flags & PF_UCNTL) &&
1056                     (pty->pt_ucntl || pty->pt_stuffqfirst != NULL))) {
1057                         pos++;
1058                 }
1059                 if ((pty->pt_flags & PF_43UCNTL) && pty->pt_ucntl) {
1060                         pos++;
1061                 }
1062         }
1063 
1064         /*
1065          * Arrange to have poll waken up when event occurs.
1066          * if (!anyyet)
1067          */
1068         if (!pos) {
1069                 *phpp = php;
1070                 *reventsp = 0;
1071         }
1072 
1073         mutex_exit(&pty->ptc_lock);
1074         return (0);
1075 }
1076 
1077 void
1078 gsignal(int pid, int sig)
1079 {
1080         procset_t set;
1081         sigsend_t v;
1082 
1083         bzero(&v, sizeof (v));
1084         v.sig = sig;
1085         v.perm = 0;
1086         v.checkperm = 1;
1087         v.value.sival_ptr = NULL;
1088 
1089         setprocset(&set, POP_AND, P_PGID, -pid, P_ALL, P_MYID);
1090         (void) sigsendset(&set, &v);
1091 }
1092 
1093 static int
1094 makemsg(ssize_t count, struct uio *uiop, struct pty *pty, mblk_t **mpp)
1095 {
1096         int pri = BPRI_LO;
1097         int error;
1098         mblk_t *bp = NULL;
1099 
1100         ASSERT(MUTEX_HELD(&pty->ptc_lock));
1101 
1102         *mpp = NULL;
1103 
1104         /*
1105          * Create data part of message, if any.
1106          */
1107         if (count >= 0) {
1108                 if ((bp = allocb(count, pri)) == NULL)
1109                         return (ENOSR);
1110 
1111                 mutex_exit(&pty->ptc_lock);
1112                 error = uiomove((caddr_t)bp->b_wptr, count, UIO_WRITE, uiop);
1113                 mutex_enter(&pty->ptc_lock);
1114                 if (error) {
1115                         freeb(bp);
1116                         return (error);
1117                 }
1118 
1119                 bp->b_wptr += count;
1120         }
1121 
1122         *mpp = bp;
1123         return (0);
1124 }