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