1 /*
   2  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
   3  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   4  * Use is subject to license terms.
   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.
  15  * This is the "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/strsun.h>
  29 #include <sys/tty.h>
  30 #include <sys/user.h>
  31 #include <sys/conf.h>
  32 #include <sys/file.h>
  33 #include <sys/vnode.h>    /* 1/0 on the vomit meter */
  34 #include <sys/proc.h>
  35 #include <sys/uio.h>
  36 #include <sys/errno.h>
  37 #include <sys/strsubr.h>
  38 #include <sys/poll.h>
  39 #include <sys/sysmacros.h>
  40 #include <sys/debug.h>
  41 #include <sys/procset.h>
  42 #include <sys/cred.h>
  43 #include <sys/ptyvar.h>
  44 #include <sys/suntty.h>
  45 #include <sys/stat.h>
  46 #include <sys/policy.h>
  47 
  48 #include <sys/conf.h>
  49 #include <sys/ddi.h>
  50 #include <sys/sunddi.h>
  51 
  52 extern void gsignal(int pid, int sig);
  53 
  54 extern  int npty;       /* number of pseudo-ttys configured in */
  55 extern struct pty *pty_softc;
  56 
  57 extern struct pollhead  ptcph;  /* poll head for ptcpoll() use */
  58 
  59 #define IFLAGS  (CS7|CREAD|PARENB)
  60 
  61 
  62 /*
  63  * Most of these should be "void", but the people who defined the "streams"
  64  * data structure for S5 didn't understand data types.
  65  */
  66 
  67 /*
  68  * Slave side.  This is a streams device.
  69  */
  70 static int ptslopen(queue_t *, dev_t *, int flag, int, cred_t *);
  71 static int ptslclose(queue_t *, int, cred_t *);
  72 static int ptslrserv(queue_t *);
  73 
  74 /*
  75  * To save instructions, since STREAMS ignores the return value
  76  * from this function, it is defined as void here. Kind of icky, but...
  77  */
  78 
  79 static void ptslwput(queue_t *q, mblk_t *mp);
  80 
  81 static struct module_info ptslm_info = {
  82         0,
  83         "ptys",
  84         0,
  85         INFPSZ,
  86         2048,
  87         200
  88 };
  89 
  90 static struct qinit ptslrinit = {
  91         putq,
  92         ptslrserv,
  93         ptslopen,
  94         ptslclose,
  95         NULL,
  96         &ptslm_info,
  97         NULL
  98 };
  99 
 100 static struct qinit ptslwinit = {
 101         (int (*)())ptslwput,
 102         NULL,
 103         NULL,
 104         NULL,
 105         NULL,
 106         &ptslm_info,
 107         NULL
 108 };
 109 
 110 struct  streamtab ptysinfo = {
 111         &ptslrinit,
 112         &ptslwinit,
 113         NULL,
 114         NULL
 115 };
 116 
 117 static void     ptslreioctl(void *);
 118 static void     ptslioctl(struct pty *, queue_t *, mblk_t *);
 119 static void     pt_sendstop(struct pty *);
 120 static void     ptcpollwakeup(struct pty *, int);
 121 
 122 
 123 static int ptsl_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
 124 static int ptsl_attach(dev_info_t *, ddi_attach_cmd_t);
 125 static dev_info_t *ptsl_dip;    /* for dev-to-dip conversions */
 126 
 127 DDI_DEFINE_STREAM_OPS(ptsl_ops, nulldev, nulldev,
 128     ptsl_attach, nodev, nodev, ptsl_info, D_MP, &ptysinfo,
 129     ddi_quiesce_not_supported);
 130 
 131 #include <sys/types.h>
 132 #include <sys/conf.h>
 133 #include <sys/param.h>
 134 #include <sys/systm.h>
 135 #include <sys/errno.h>
 136 #include <sys/modctl.h>
 137 
 138 /*
 139  * Module linkage information for the kernel.
 140  */
 141 
 142 static struct modldrv modldrv = {
 143         &mod_driverops, /* Type of module.  This one is a pseudo driver */
 144         "tty pseudo driver slave 'ptsl'",
 145         &ptsl_ops,  /* driver ops */
 146 };
 147 
 148 static struct modlinkage modlinkage = {
 149         MODREV_1,
 150         { &modldrv, NULL }
 151 };
 152 
 153 int
 154 _init(void)
 155 {
 156         return (mod_install(&modlinkage));
 157 }
 158 
 159 int
 160 _fini(void)
 161 {
 162         return (mod_remove(&modlinkage));
 163 }
 164 
 165 int
 166 _info(struct modinfo *modinfop)
 167 {
 168         return (mod_info(&modlinkage, modinfop));
 169 }
 170 
 171 static char     *tty_banks = PTY_BANKS;
 172 static char     *tty_digits = PTY_DIGITS;
 173 
 174 /* ARGSUSED */
 175 static int
 176 ptsl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
 177 {
 178         char    name[8];
 179         int     tty_num;
 180         char    *tty_digit = tty_digits;
 181         char    *tty_bank = tty_banks;
 182 
 183         for (tty_num = 0; tty_num < npty; tty_num++) {
 184                 (void) sprintf(name, "tty%c%c", *tty_bank, *tty_digit);
 185                 if (ddi_create_minor_node(devi, name, S_IFCHR,
 186                     tty_num, DDI_PSEUDO, NULL) == DDI_FAILURE) {
 187                         ddi_remove_minor_node(devi, NULL);
 188                         return (-1);
 189                 }
 190                 if (*(++tty_digit) == '\0') {
 191                         tty_digit = tty_digits;
 192                         if (*(++tty_bank) == '\0')
 193                                 break;
 194                 }
 195         }
 196         ptsl_dip = devi;
 197         return (DDI_SUCCESS);
 198 }
 199 
 200 /* ARGSUSED */
 201 static int
 202 ptsl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 203     void **result)
 204 {
 205         int error;
 206 
 207         switch (infocmd) {
 208         case DDI_INFO_DEVT2DEVINFO:
 209                 if (ptsl_dip == NULL) {
 210                         error = DDI_FAILURE;
 211                 } else {
 212                         *result = (void *)ptsl_dip;
 213                         error = DDI_SUCCESS;
 214                 }
 215                 break;
 216         case DDI_INFO_DEVT2INSTANCE:
 217                 *result = (void *)0;
 218                 error = DDI_SUCCESS;
 219                 break;
 220         default:
 221                 error = DDI_FAILURE;
 222         }
 223         return (error);
 224 }
 225 
 226 
 227 /*
 228  * Open the slave side of a pty.
 229  */
 230 /*ARGSUSED*/
 231 static int
 232 ptslopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cred)
 233 {
 234         minor_t unit;
 235         dev_t dev = *devp;
 236         struct pty *pty;
 237 
 238         unit = getminor(dev);
 239         if (unit >= npty)
 240                 return (ENXIO);
 241 
 242         pty = &pty_softc[unit];
 243 
 244         mutex_enter(&pty->ptc_lock);
 245         /*
 246          * Block waiting for controller to open, unless this is a no-delay
 247          * open.
 248          */
 249 again:
 250         if (pty->pt_ttycommon.t_writeq == NULL) {
 251                 pty->pt_ttycommon.t_iflag = 0;
 252                 pty->pt_ttycommon.t_cflag = (B38400 << IBSHIFT)|B38400|IFLAGS;
 253                 pty->pt_ttycommon.t_iocpending = NULL;
 254                 pty->pt_wbufcid = 0;
 255                 pty->pt_ttycommon.t_size.ws_row = 0;
 256                 pty->pt_ttycommon.t_size.ws_col = 0;
 257                 pty->pt_ttycommon.t_size.ws_xpixel = 0;
 258                 pty->pt_ttycommon.t_size.ws_ypixel = 0;
 259         } else if ((pty->pt_ttycommon.t_flags & TS_XCLUDE) &&
 260             secpolicy_excl_open(cred) != 0) {
 261                 mutex_exit(&pty->ptc_lock);
 262                 return (EBUSY);
 263         }
 264         if (!(flag & (FNONBLOCK|FNDELAY)) &&
 265             !(pty->pt_ttycommon.t_cflag & CLOCAL)) {
 266                 if (!(pty->pt_flags & PF_CARR_ON)) {
 267                         pty->pt_flags |= PF_WOPEN;
 268                         if (!cv_wait_sig(&pty->pt_cv_flags, &pty->ptc_lock)) {
 269                                 pty->pt_flags &= ~PF_WOPEN;
 270                                 mutex_exit(&pty->ptc_lock);
 271                                 return (EINTR);
 272                         }
 273                         goto again;
 274                 }
 275         }
 276 
 277         pty->pt_sdev = dev;
 278         q->q_ptr = WR(q)->q_ptr = pty;
 279         pty->pt_flags &= ~PF_SLAVEGONE;
 280         pty->pt_ttycommon.t_readq = pty->pt_ttycommon.t_writeq = NULL;
 281 
 282         /*
 283          * Slave is ready to accept messages but master still can't send
 284          * messages to the slave queue since it is not plumbed
 285          * yet. So do qprocson() and finish slave initialization.
 286          */
 287 
 288         mutex_exit(&pty->ptc_lock);
 289 
 290         qprocson(q);
 291 
 292         /*
 293          * Now it is safe to send messages to q, so wakeup master possibly
 294          * waiting for slave queue to finish open.
 295          */
 296         mutex_enter(&pty->ptc_lock);
 297         /*
 298          * queue has already been setup with a pointer to
 299          * the stream head that is being referenced
 300          */
 301         pty->pt_vnode = strq2vp(q);
 302         VN_RELE(pty->pt_vnode);
 303         pty->pt_ttycommon.t_readq = q;
 304         pty->pt_ttycommon.t_writeq = WR(q);
 305         /* tell master device that slave is ready for writing */
 306         if (pty->pt_flags & PF_CARR_ON)
 307                 cv_broadcast(&pty->pt_cv_readq);
 308         mutex_exit(&pty->ptc_lock);
 309 
 310         return (0);
 311 }
 312 
 313 static int
 314 ptslclose(queue_t *q, int flag, cred_t *cred)
 315 {
 316         struct pty *pty;
 317         bufcall_id_t pt_wbufcid = 0;
 318 
 319 #ifdef lint
 320         flag = flag;
 321         cred = cred;
 322 #endif
 323 
 324         if ((pty = (struct pty *)q->q_ptr) == NULL)
 325                 return (ENODEV);        /* already been closed once */
 326 
 327         /*
 328          * Prevent the queues from being uses by master device.
 329          * This should be done before qprocsoff or writer may attempt
 330          * to use the slave queue after qprocsoff removed it from the stream and
 331          * before entering mutex_enter().
 332          */
 333         mutex_enter(&pty->ptc_lock);
 334         pty->pt_ttycommon.t_readq = NULL;
 335         pty->pt_ttycommon.t_writeq = NULL;
 336         while (pty->pt_flags & PF_IOCTL) {
 337                 pty->pt_flags |= PF_WAIT;
 338                 cv_wait(&pty->pt_cv_flags, &pty->ptc_lock);
 339         }
 340         pty->pt_vnode = NULL;
 341         mutex_exit(&pty->ptc_lock);
 342 
 343         qprocsoff(q);
 344 
 345         mutex_enter(&pty->ptc_lock);
 346         /*
 347          * ptc_lock mutex is not dropped across
 348          * the call to the routine ttycommon_close
 349          */
 350         ttycommon_close(&pty->pt_ttycommon);
 351 
 352         /*
 353          * Cancel outstanding "bufcall" request.
 354          */
 355         if (pty->pt_wbufcid) {
 356                 pt_wbufcid = pty->pt_wbufcid;
 357                 pty->pt_wbufcid = 0;
 358         }
 359 
 360         /*
 361          * Clear out all the slave-side state.
 362          */
 363         pty->pt_flags &= ~(PF_WOPEN|PF_STOPPED|PF_NOSTOP);
 364         if (pty->pt_flags & PF_CARR_ON) {
 365                 pty->pt_flags |= PF_SLAVEGONE;       /* let the controller know */
 366                 ptcpollwakeup(pty, 0);  /* wake up readers/selectors */
 367                 ptcpollwakeup(pty, FWRITE);     /* wake up writers/selectors */
 368                 cv_broadcast(&pty->pt_cv_flags);
 369         }
 370         pty->pt_sdev = 0;
 371         q->q_ptr = WR(q)->q_ptr = NULL;
 372         mutex_exit(&pty->ptc_lock);
 373 
 374         if (pt_wbufcid)
 375                 unbufcall(pt_wbufcid);
 376 
 377         return (0);
 378 }
 379 
 380 /*
 381  * Put procedure for write queue.
 382  * Respond to M_STOP, M_START, M_IOCTL, and M_FLUSH messages here;
 383  * queue up M_DATA messages for processing by the controller "read"
 384  * routine; discard everything else.
 385  */
 386 static void
 387 ptslwput(queue_t *q, mblk_t *mp)
 388 {
 389         struct pty *pty;
 390         mblk_t *bp;
 391 
 392         pty = (struct pty *)q->q_ptr;
 393 
 394         mutex_enter(&pty->ptc_lock);
 395 
 396         switch (mp->b_datap->db_type) {
 397 
 398         case M_STOP:
 399                 if (!(pty->pt_flags & PF_STOPPED)) {
 400                         pty->pt_flags |= PF_STOPPED;
 401                         pty->pt_send |= TIOCPKT_STOP;
 402                         ptcpollwakeup(pty, 0);
 403                 }
 404                 freemsg(mp);
 405                 break;
 406 
 407         case M_START:
 408                 if (pty->pt_flags & PF_STOPPED) {
 409                         pty->pt_flags &= ~PF_STOPPED;
 410                         pty->pt_send = TIOCPKT_START;
 411                         ptcpollwakeup(pty, 0);
 412                 }
 413                 ptcpollwakeup(pty, FREAD);      /* permit controller to read */
 414                 freemsg(mp);
 415                 break;
 416 
 417         case M_IOCTL:
 418                 ptslioctl(pty, q, mp);
 419                 break;
 420 
 421         case M_FLUSH:
 422                 if (*mp->b_rptr & FLUSHW) {
 423                         /*
 424                          * Set the "flush write" flag, so that we
 425                          * notify the controller if they're in packet
 426                          * or user control mode.
 427                          */
 428                         if (!(pty->pt_send & TIOCPKT_FLUSHWRITE)) {
 429                                 pty->pt_send |= TIOCPKT_FLUSHWRITE;
 430                                 ptcpollwakeup(pty, 0);
 431                         }
 432                         /*
 433                          * Flush our write queue.
 434                          */
 435                         flushq(q, FLUSHDATA);   /* XXX doesn't flush M_DELAY */
 436                         *mp->b_rptr &= ~FLUSHW;  /* it has been flushed */
 437                 }
 438                 if (*mp->b_rptr & FLUSHR) {
 439                         /*
 440                          * Set the "flush read" flag, so that we
 441                          * notify the controller if they're in packet
 442                          * mode.
 443                          */
 444                         if (!(pty->pt_send & TIOCPKT_FLUSHREAD)) {
 445                                 pty->pt_send |= TIOCPKT_FLUSHREAD;
 446                                 ptcpollwakeup(pty, 0);
 447                         }
 448                         flushq(RD(q), FLUSHDATA);
 449                         mutex_exit(&pty->ptc_lock);
 450                         qreply(q, mp);  /* give the read queues a crack at it */
 451                         return;
 452                 } else
 453                         freemsg(mp);
 454                 break;
 455 
 456         case M_DATA:
 457                 /*
 458                  * Throw away any leading zero-length blocks, and queue it up
 459                  * for the controller to read.
 460                  */
 461                 if (pty->pt_flags & PF_CARR_ON) {
 462                         bp = mp;
 463                         while ((bp->b_wptr - bp->b_rptr) == 0) {
 464                                 mp = bp->b_cont;
 465                                 freeb(bp);
 466                                 if (mp == NULL) {
 467                                         mutex_exit(&pty->ptc_lock);
 468                                         return; /* damp squib of a message */
 469                                 }
 470                                 bp = mp;
 471                         }
 472                         (void) putq(q, mp);
 473                         ptcpollwakeup(pty, FREAD);      /* soup's on! */
 474                 } else
 475                         freemsg(mp);    /* nobody listening */
 476                 break;
 477 
 478         case M_CTL:
 479                 if ((*(int *)mp->b_rptr) == MC_CANONQUERY) {
 480                         /*
 481                          * We're being asked whether we do canonicalization
 482                          * or not.  Send a reply back up indicating whether
 483                          * we do or not.
 484                          */
 485                         (void) putctl1(RD(q), M_CTL,
 486                             (pty->pt_flags & PF_REMOTE) ?
 487                             MC_NOCANON : MC_DOCANON);
 488                 }
 489                 freemsg(mp);
 490                 break;
 491 
 492         default:
 493                 /*
 494                  * "No, I don't want a subscription to Chain Store Age,
 495                  * thank you anyway."
 496                  */
 497                 freemsg(mp);
 498                 break;
 499         }
 500         mutex_exit(&pty->ptc_lock);
 501 }
 502 
 503 /*
 504  * Retry an "ioctl", now that "bufcall" claims we may be able to allocate
 505  * the buffer we need.
 506  */
 507 static void
 508 ptslreioctl(void *arg)
 509 {
 510         struct pty *pty = arg;
 511         queue_t *q;
 512         mblk_t *mp;
 513 
 514         mutex_enter(&pty->ptc_lock);
 515         /*
 516          * The bufcall is no longer pending.
 517          */
 518         if (pty->pt_wbufcid == 0) {
 519                 mutex_exit(&pty->ptc_lock);
 520                 return;
 521         }
 522 
 523         pty->pt_wbufcid = 0;
 524         if ((q = pty->pt_ttycommon.t_writeq) == NULL) {
 525                 mutex_exit(&pty->ptc_lock);
 526                 return;
 527         }
 528         if ((mp = pty->pt_ttycommon.t_iocpending) != NULL) {
 529                 /* It's not pending any more. */
 530                 pty->pt_ttycommon.t_iocpending = NULL;
 531                 ptslioctl(pty, q, mp);
 532         }
 533         mutex_exit(&pty->ptc_lock);
 534 }
 535 
 536 /*
 537  * Process an "ioctl" message sent down to us.
 538  * Drops pty's ptc_lock mutex and then reacquire
 539  */
 540 static void
 541 ptslioctl(struct pty *pty, queue_t *q, mblk_t *mp)
 542 {
 543         struct iocblk *iocp;
 544         int cmd;
 545         size_t datasize;
 546         int error = 0;
 547 
 548         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 549 
 550         iocp = (struct iocblk *)mp->b_rptr;
 551         cmd = iocp->ioc_cmd;
 552 
 553         switch (cmd) {
 554 
 555         case TIOCSTI: {
 556                 /*
 557                  * The permission checking has already been done at the stream
 558                  * head, since it has to be done in the context of the process
 559                  * doing the call.
 560                  */
 561                 mblk_t *bp;
 562 
 563                 error = miocpullup(mp, sizeof (char));
 564                 if (error != 0)
 565                         goto out;
 566 
 567                 /*
 568                  * Simulate typing of a character at the terminal.
 569                  */
 570                 if ((bp = allocb(1, BPRI_MED)) != NULL) {
 571                         *bp->b_wptr++ = *mp->b_cont->b_rptr;
 572                         if (!(pty->pt_flags & PF_REMOTE)) {
 573                                 if (!canput(pty->pt_ttycommon.t_readq)) {
 574                                         mutex_exit(&pty->ptc_lock);
 575                                         ttycommon_qfull(&pty->pt_ttycommon, q);
 576                                         mutex_enter(&pty->ptc_lock);
 577                                         freemsg(bp);
 578                                         error = EAGAIN;
 579                                         goto out;
 580                                 } else
 581                                         (void) putq(
 582                                             pty->pt_ttycommon.t_readq, bp);
 583                         } else {
 584                                 if (pty->pt_flags & PF_UCNTL) {
 585                                         /*
 586                                          * XXX - flow control; don't overflow
 587                                          * this "queue".
 588                                          */
 589                                         if (pty->pt_stuffqfirst != NULL) {
 590                                                 pty->pt_stuffqlast->b_next = bp;
 591                                                 bp->b_prev = pty->pt_stuffqlast;
 592                                         } else {
 593                                                 pty->pt_stuffqfirst = bp;
 594                                                 bp->b_prev = NULL;
 595                                         }
 596                                         bp->b_next = NULL;
 597                                         pty->pt_stuffqlast = bp;
 598                                         pty->pt_stuffqlen++;
 599                                         ptcpollwakeup(pty, 0);
 600                                 }
 601                         }
 602                 } else {
 603                         error = EAGAIN;
 604                         goto out;
 605                 }
 606 
 607                 /*
 608                  * Turn the ioctl message into an ioctl ACK message.
 609                  */
 610                 iocp->ioc_count = 0; /* no data returned */
 611                 mp->b_datap->db_type = M_IOCACK;
 612                 goto out;
 613         }
 614 
 615         case TIOCSSIZE: {
 616                 tty_common_t *tc = &pty->pt_ttycommon;
 617                 struct ttysize *tp;
 618 
 619                 error = miocpullup(mp, sizeof (struct ttysize));
 620                 if (error != 0)
 621                         goto out;
 622 
 623                 /*
 624                  * Set the window size, but don't send a SIGWINCH.
 625                  */
 626                 tp = (struct ttysize *)mp->b_cont->b_rptr;
 627                 tc->t_size.ws_row = tp->ts_lines;
 628                 tc->t_size.ws_col = tp->ts_cols;
 629                 tc->t_size.ws_xpixel = 0;
 630                 tc->t_size.ws_ypixel = 0;
 631 
 632                 /*
 633                  * Send an ACK back.
 634                  */
 635                 iocp->ioc_count = 0; /* no data returned */
 636                 mp->b_datap->db_type = M_IOCACK;
 637                 goto out;
 638         }
 639 
 640         case TIOCGSIZE: {
 641                 tty_common_t *tc = &pty->pt_ttycommon;
 642                 mblk_t *datap;
 643                 struct ttysize *tp;
 644 
 645                 if ((datap = allocb(sizeof (struct ttysize),
 646                     BPRI_HI)) == NULL) {
 647                         if (pty->pt_wbufcid) {
 648                                 if (pty->pt_ttycommon.t_iocpending)
 649                                         freemsg(pty->pt_ttycommon.t_iocpending);
 650                                 pty->pt_ttycommon.t_iocpending = mp;
 651                                 return;
 652                         }
 653                         pty->pt_wbufcid = bufcall(sizeof (struct ttysize),
 654                             BPRI_HI, ptslreioctl, pty);
 655                         if (pty->pt_wbufcid == 0) {
 656                                 error = ENOMEM;
 657                                 goto out;
 658                         }
 659                         pty->pt_ttycommon.t_iocpending = mp;
 660                         return;
 661                 }
 662                 /*
 663                  * Return the current size.
 664                  */
 665                 tp = (struct ttysize *)datap->b_wptr;
 666                 tp->ts_lines = tc->t_size.ws_row;
 667                 tp->ts_cols = tc->t_size.ws_col;
 668                 datap->b_wptr += sizeof (struct ttysize);
 669                 iocp->ioc_count = sizeof (struct ttysize);
 670 
 671                 if (mp->b_cont != NULL)
 672                         freemsg(mp->b_cont);
 673                 mp->b_cont = datap;
 674                 mp->b_datap->db_type = M_IOCACK;
 675                 goto out;
 676         }
 677 
 678         /*
 679          * Imported from ttycommon_ioctl routine
 680          */
 681 
 682         case TCSETSF: {
 683                 tty_common_t *tc = &pty->pt_ttycommon;
 684                 struct termios *cb;
 685 
 686                 error = miocpullup(mp, sizeof (struct termios));
 687                 if (error != 0)
 688                         goto out;
 689 
 690                 cb = (struct termios *)mp->b_cont->b_rptr;
 691 
 692                 flushq(RD(q), FLUSHDATA);
 693                 mutex_exit(&pty->ptc_lock);
 694                 (void) putnextctl1(RD(q), M_FLUSH, FLUSHR);
 695                 mutex_enter(&pty->ptc_lock);
 696                 mutex_enter(&tc->t_excl);
 697                 tc->t_iflag = cb->c_iflag;
 698                 tc->t_cflag = cb->c_cflag;
 699                 tc->t_stopc = cb->c_cc[VSTOP];
 700                 tc->t_startc = cb->c_cc[VSTART];
 701                 mutex_exit(&tc->t_excl);
 702 
 703                 /*
 704                  * Turn the ioctl message into an ioctl ACK message.
 705                  */
 706                 iocp->ioc_count = 0; /* no data returned */
 707                 mp->b_datap->db_type = M_IOCACK;
 708                 goto ioctldone;
 709         }
 710 
 711         case TCSETAF: {
 712                 tty_common_t *tc = &pty->pt_ttycommon;
 713                 struct termios *cb;
 714 
 715                 error = miocpullup(mp, sizeof (struct termios));
 716                 if (error != 0)
 717                         goto out;
 718 
 719                 cb = (struct termios *)mp->b_cont->b_rptr;
 720 
 721                 flushq(RD(q), FLUSHDATA);
 722                 mutex_exit(&pty->ptc_lock);
 723                 (void) putnextctl1(RD(q), M_FLUSH, FLUSHR);
 724                 mutex_enter(&pty->ptc_lock);
 725                 mutex_enter(&tc->t_excl);
 726                 tc->t_iflag = (tc->t_iflag & 0xffff0000 | cb->c_iflag);
 727                 tc->t_cflag = (tc->t_cflag & 0xffff0000 | cb->c_cflag);
 728                 mutex_exit(&tc->t_excl);
 729 
 730                 /*
 731                  * Turn the ioctl message into an ioctl ACK message.
 732                  */
 733                 iocp->ioc_count = 0; /* no data returned */
 734                 mp->b_datap->db_type = M_IOCACK;
 735                 goto ioctldone;
 736         }
 737 
 738         case TIOCSWINSZ: {
 739                 tty_common_t *tc = &pty->pt_ttycommon;
 740                 struct winsize *ws;
 741 
 742                 error = miocpullup(mp, sizeof (struct winsize));
 743                 if (error != 0)
 744                         goto out;
 745 
 746                 ws = (struct winsize *)mp->b_cont->b_rptr;
 747                 /*
 748                  * If the window size changed, send a SIGWINCH.
 749                  */
 750                 mutex_enter(&tc->t_excl);
 751                 if (bcmp(&tc->t_size, ws, sizeof (struct winsize))) {
 752                         tc->t_size = *ws;
 753                         mutex_exit(&tc->t_excl);
 754                         mutex_exit(&pty->ptc_lock);
 755                         (void) putnextctl1(RD(q), M_PCSIG, SIGWINCH);
 756                         mutex_enter(&pty->ptc_lock);
 757                 } else
 758                         mutex_exit(&tc->t_excl);
 759 
 760                 /*
 761                  * Turn the ioctl message into an ioctl ACK message.
 762                  */
 763                 iocp->ioc_count = 0; /* no data returned */
 764                 mp->b_datap->db_type = M_IOCACK;
 765                 goto ioctldone;
 766         }
 767 
 768         /*
 769          * If they were just trying to drain output, that's OK.
 770          * If they are actually trying to send a break it's an error.
 771          */
 772         case TCSBRK:
 773                 error = miocpullup(mp, sizeof (int));
 774                 if (error != 0)
 775                         goto out;
 776 
 777                 if (*(int *)mp->b_cont->b_rptr != 0) {
 778                         /*
 779                          * Turn the ioctl message into an ioctl ACK message.
 780                          */
 781                         iocp->ioc_count = 0; /* no data returned */
 782                         mp->b_datap->db_type = M_IOCACK;
 783                 } else {
 784                         error = ENOTTY;
 785                 }
 786                 goto out;
 787         }
 788 
 789         /*
 790          * The only way in which "ttycommon_ioctl" can fail is if the "ioctl"
 791          * requires a response containing data to be returned to the user,
 792          * and no mblk could be allocated for the data.
 793          * No such "ioctl" alters our state.  Thus, we always go ahead and
 794          * do any state-changes the "ioctl" calls for.  If we couldn't allocate
 795          * the data, "ttycommon_ioctl" has stashed the "ioctl" away safely, so
 796          * we just call "bufcall" to request that we be called back when we
 797          * stand a better chance of allocating the data.
 798          */
 799         if ((datasize =
 800             ttycommon_ioctl(&pty->pt_ttycommon, q, mp, &error)) != 0) {
 801                 if (pty->pt_wbufcid) {
 802                         if (pty->pt_ttycommon.t_iocpending)
 803                                 freemsg(pty->pt_ttycommon.t_iocpending);
 804                         pty->pt_ttycommon.t_iocpending = mp;
 805                         return;
 806                 }
 807                 pty->pt_wbufcid = bufcall(datasize, BPRI_HI, ptslreioctl, pty);
 808                 if (pty->pt_wbufcid == 0) {
 809                         error = ENOMEM;
 810                         goto out;
 811                 }
 812                 pty->pt_ttycommon.t_iocpending = mp;
 813                 return;
 814         }
 815 
 816 ioctldone:
 817         if (error == 0) {
 818                 /*
 819                  * "ttycommon_ioctl" did most of the work; we just use the
 820                  * data it set up.
 821                  */
 822                 switch (cmd) {
 823 
 824                 case TCSETSF:
 825                 case TCSETAF:
 826                         /*
 827                          * Set the "flush read" flag, so that we
 828                          * notify the controller if they're in packet
 829                          * mode.
 830                          */
 831                         if (!(pty->pt_send & TIOCPKT_FLUSHREAD)) {
 832                                 pty->pt_send |= TIOCPKT_FLUSHREAD;
 833                                 ptcpollwakeup(pty, 0);
 834                         }
 835                         /*FALLTHROUGH*/
 836 
 837                 case TCSETSW:
 838                 case TCSETAW:
 839                         cmd = TIOCSETP; /* map backwards to old codes */
 840                         pt_sendstop(pty);
 841                         break;
 842 
 843                 case TCSETS:
 844                 case TCSETA:
 845                         cmd = TIOCSETN; /* map backwards to old codes */
 846                         pt_sendstop(pty);
 847                         break;
 848                 }
 849         }
 850 
 851         if (pty->pt_flags & PF_43UCNTL) {
 852                 if (error < 0) {
 853                         if ((cmd & ~0xff) == _IO('u', 0)) {
 854                                 if (cmd & 0xff) {
 855                                         pty->pt_ucntl = (uchar_t)cmd & 0xff;
 856                                         ptcpollwakeup(pty, FREAD);
 857                                 }
 858                                 error = 0; /* XXX */
 859                                 goto out;
 860                         }
 861                         error = ENOTTY;
 862                 }
 863         } else {
 864                 if ((pty->pt_flags & PF_UCNTL) &&
 865                     (cmd & (IOC_INOUT | 0xff00)) == (IOC_IN|('t'<<8)) &&
 866                     (cmd & 0xff)) {
 867                         pty->pt_ucntl = (uchar_t)cmd & 0xff;
 868                         ptcpollwakeup(pty, FREAD);
 869                         goto out;
 870                 }
 871                 if (error < 0)
 872                         error = ENOTTY;
 873         }
 874 
 875 out:
 876         if (error != 0) {
 877                 ((struct iocblk *)mp->b_rptr)->ioc_error = error;
 878                 mp->b_datap->db_type = M_IOCNAK;
 879         }
 880 
 881         mutex_exit(&pty->ptc_lock);
 882         qreply(q, mp);
 883         mutex_enter(&pty->ptc_lock);
 884 }
 885 
 886 /*
 887  * Service routine for read queue.
 888  * Just wakes the controller side up so it can write some more data
 889  * to that queue.
 890  */
 891 static int
 892 ptslrserv(queue_t *q)
 893 {
 894         struct pty *pty = (struct pty *)q->q_ptr;
 895         mblk_t *mp;
 896         mblk_t *head = NULL, *tail = NULL;
 897         /*
 898          * Build up the link list of messages, then drop
 899          * drop the lock and do putnext()
 900          */
 901         mutex_enter(&pty->ptc_lock);
 902 
 903         while ((mp = getq(q)) != NULL) {
 904                 if ((mp->b_datap->db_type < QPCTL) && !canputnext(q)) {
 905                         (void) putbq(q, mp);
 906                         break;
 907                 }
 908                 if (!head) {
 909                         head = mp;
 910                         tail = mp;
 911                 } else {
 912                         tail->b_next = mp;
 913                         tail = mp;
 914                 }
 915         }
 916 
 917         if (q->q_count <= q->q_lowat)
 918                 ptcpollwakeup((struct pty *)q->q_ptr, FWRITE);
 919 
 920         mutex_exit(&pty->ptc_lock);
 921 
 922         while (head) {
 923                 mp = head;
 924                 head = mp->b_next;
 925                 mp->b_next = NULL;
 926                 putnext(q, mp);
 927         }
 928 
 929         return (0);
 930 }
 931 
 932 static void
 933 pt_sendstop(struct pty *pty)
 934 {
 935         int stop;
 936 
 937         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 938 
 939         if ((pty->pt_ttycommon.t_cflag&CBAUD) == 0) {
 940                 if (pty->pt_flags & PF_CARR_ON) {
 941                         /*
 942                          * Let the controller know, then wake up
 943                          * readers/selectors and writers/selectors.
 944                          */
 945                         pty->pt_flags |= PF_SLAVEGONE;
 946                         ptcpollwakeup(pty, 0);
 947                         ptcpollwakeup(pty, FWRITE);
 948                 }
 949         }
 950 
 951         stop = (pty->pt_ttycommon.t_iflag & IXON) &&
 952             pty->pt_ttycommon.t_stopc == CTRL('s') &&
 953             pty->pt_ttycommon.t_startc == CTRL('q');
 954 
 955         if (pty->pt_flags & PF_NOSTOP) {
 956                 if (stop) {
 957                         pty->pt_send &= ~TIOCPKT_NOSTOP;
 958                         pty->pt_send |= TIOCPKT_DOSTOP;
 959                         pty->pt_flags &= ~PF_NOSTOP;
 960                         ptcpollwakeup(pty, 0);
 961                 }
 962         } else {
 963                 if (!stop) {
 964                         pty->pt_send &= ~TIOCPKT_DOSTOP;
 965                         pty->pt_send |= TIOCPKT_NOSTOP;
 966                         pty->pt_flags |= PF_NOSTOP;
 967                         ptcpollwakeup(pty, 0);
 968                 }
 969         }
 970 }
 971 
 972 /*
 973  * Wake up controller side.  "flag" is 0 if a special packet or
 974  * user control mode message has been queued up (this data is readable,
 975  * so we also treat it as a regular data event; should we send SIGIO,
 976  * though?), FREAD if regular data has been queued up, or FWRITE if
 977  * the slave's read queue has drained sufficiently to allow writing.
 978  */
 979 static void
 980 ptcpollwakeup(struct pty *pty, int flag)
 981 {
 982         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 983 
 984         if (flag == 0) {
 985                 /*
 986                  * "Exceptional condition" occurred.  This means that
 987                  * a "read" is now possible, so do a "read" wakeup.
 988                  */
 989                 flag = FREAD;
 990                 pollwakeup(&ptcph, POLLIN | POLLRDBAND);
 991                 if (pty->pt_flags & PF_ASYNC)
 992                         gsignal(pty->pt_pgrp, SIGURG);
 993         }
 994         if (flag & FREAD) {
 995                 /*
 996                  * Wake up the parent process as there is regular
 997                  * data to read from slave's write queue
 998                  */
 999                 pollwakeup(&ptcph, POLLIN | POLLRDNORM);
1000                 cv_broadcast(&pty->pt_cv_writeq);
1001                 if (pty->pt_flags & PF_ASYNC)
1002                         gsignal(pty->pt_pgrp, SIGIO);
1003         }
1004         if (flag & FWRITE) {
1005                 /*
1006                  * Wake up the parent process to write
1007                  * data into slave's read queue as the
1008                  * read queue has drained enough
1009                  */
1010                 pollwakeup(&ptcph, POLLOUT | POLLWRNORM);
1011                 cv_broadcast(&pty->pt_cv_readq);
1012                 if (pty->pt_flags & PF_ASYNC)
1013                         gsignal(pty->pt_pgrp, SIGIO);
1014         }
1015 }