Print this page
14249 pseudo-terminal nomenclature should reflect POSIX
Change-Id: Ib4a3cef899ff4c71b09cb0dc6878863c5e8357bc
   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 int 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 };


 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 }


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


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


 925         while (head) {
 926                 mp = head;
 927                 head = mp->b_next;
 928                 mp->b_next = NULL;
 929                 putnext(q, mp);
 930         }
 931 
 932         return (0);
 933 }
 934 
 935 static void
 936 pt_sendstop(struct pty *pty)
 937 {
 938         int stop;
 939 
 940         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 941 
 942         if ((pty->pt_ttycommon.t_cflag&CBAUD) == 0) {
 943                 if (pty->pt_flags & PF_CARR_ON) {
 944                         /*
 945                          * Let the controller know, then wake up
 946                          * readers/selectors and writers/selectors.
 947                          */
 948                         pty->pt_flags |= PF_SLAVEGONE;
 949                         ptcpollwakeup(pty, 0);
 950                         ptcpollwakeup(pty, FWRITE);
 951                 }
 952         }
 953 
 954         stop = (pty->pt_ttycommon.t_iflag & IXON) &&
 955             pty->pt_ttycommon.t_stopc == CTRL('s') &&
 956             pty->pt_ttycommon.t_startc == CTRL('q');
 957 
 958         if (pty->pt_flags & PF_NOSTOP) {
 959                 if (stop) {
 960                         pty->pt_send &= ~TIOCPKT_NOSTOP;
 961                         pty->pt_send |= TIOCPKT_DOSTOP;
 962                         pty->pt_flags &= ~PF_NOSTOP;
 963                         ptcpollwakeup(pty, 0);
 964                 }
 965         } else {
 966                 if (!stop) {
 967                         pty->pt_send &= ~TIOCPKT_DOSTOP;
 968                         pty->pt_send |= TIOCPKT_NOSTOP;
 969                         pty->pt_flags |= PF_NOSTOP;
 970                         ptcpollwakeup(pty, 0);
 971                 }
 972         }
 973 }
 974 
 975 /*
 976  * Wake up controller side.  "flag" is 0 if a special packet or
 977  * user control mode message has been queued up (this data is readable,
 978  * so we also treat it as a regular data event; should we send SIGIO,
 979  * though?), FREAD if regular data has been queued up, or FWRITE if
 980  * the slave's read queue has drained sufficiently to allow writing.
 981  */
 982 static void
 983 ptcpollwakeup(struct pty *pty, int flag)
 984 {
 985         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 986 
 987         if (flag == 0) {
 988                 /*
 989                  * "Exceptional condition" occurred.  This means that
 990                  * a "read" is now possible, so do a "read" wakeup.
 991                  */
 992                 flag = FREAD;
 993                 pollwakeup(&ptcph, POLLIN | POLLRDBAND);
 994                 if (pty->pt_flags & PF_ASYNC)
 995                         gsignal(pty->pt_pgrp, SIGURG);
 996         }
 997         if (flag & FREAD) {
 998                 /*
 999                  * Wake up the parent process as there is regular
1000                  * data to read from slave's write queue
1001                  */
1002                 pollwakeup(&ptcph, POLLIN | POLLRDNORM);
1003                 cv_broadcast(&pty->pt_cv_writeq);
1004                 if (pty->pt_flags & PF_ASYNC)
1005                         gsignal(pty->pt_pgrp, SIGIO);
1006         }
1007         if (flag & FWRITE) {
1008                 /*
1009                  * Wake up the parent process to write
1010                  * data into slave's read queue as the
1011                  * read queue has drained enough
1012                  */
1013                 pollwakeup(&ptcph, POLLOUT | POLLWRNORM);
1014                 cv_broadcast(&pty->pt_cv_readq);
1015                 if (pty->pt_flags & PF_ASYNC)
1016                         gsignal(pty->pt_pgrp, SIGIO);
1017         }
1018 }
   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 "subsidiary" side.
  16  */
  17 
  18 
  19 #include <sys/param.h>
  20 #include <sys/systm.h>
  21 #include <sys/filio.h>
  22 #include <sys/ioccom.h>
  23 #include <sys/termios.h>
  24 #include <sys/termio.h>
  25 #include <sys/ttold.h>
  26 #include <sys/stropts.h>
  27 #include <sys/stream.h>
  28 #include <sys/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>
  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  * Subsidiary 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 int 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 };


 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 subsidiary '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 }


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


 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_SUBSIDGONE;
 281         pty->pt_ttycommon.t_readq = pty->pt_ttycommon.t_writeq = NULL;
 282 
 283         /*
 284          * Subsidiary is ready to accept messages but manager still can't send
 285          * messages to the subsidiary queue since it is not plumbed
 286          * yet. So do qprocson() and finish subsidiary 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 manager possibly
 295          * waiting for subsidiary 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 manager device that subsidiary 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 manager device.  This should
 330          * be done before qprocsoff or writer may attempt to use the subsidiary
 331          * queue after qprocsoff removed it from the stream and before entering
 332          * 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 subsidiary-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_SUBSIDGONE;      /* 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  */


 925         while (head) {
 926                 mp = head;
 927                 head = mp->b_next;
 928                 mp->b_next = NULL;
 929                 putnext(q, mp);
 930         }
 931 
 932         return (0);
 933 }
 934 
 935 static void
 936 pt_sendstop(struct pty *pty)
 937 {
 938         int stop;
 939 
 940         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 941 
 942         if ((pty->pt_ttycommon.t_cflag&CBAUD) == 0) {
 943                 if (pty->pt_flags & PF_CARR_ON) {
 944                         /*
 945                          * Let the manager know, then wake up
 946                          * readers/selectors and writers/selectors.
 947                          */
 948                         pty->pt_flags |= PF_SUBSIDGONE;
 949                         ptcpollwakeup(pty, 0);
 950                         ptcpollwakeup(pty, FWRITE);
 951                 }
 952         }
 953 
 954         stop = (pty->pt_ttycommon.t_iflag & IXON) &&
 955             pty->pt_ttycommon.t_stopc == CTRL('s') &&
 956             pty->pt_ttycommon.t_startc == CTRL('q');
 957 
 958         if (pty->pt_flags & PF_NOSTOP) {
 959                 if (stop) {
 960                         pty->pt_send &= ~TIOCPKT_NOSTOP;
 961                         pty->pt_send |= TIOCPKT_DOSTOP;
 962                         pty->pt_flags &= ~PF_NOSTOP;
 963                         ptcpollwakeup(pty, 0);
 964                 }
 965         } else {
 966                 if (!stop) {
 967                         pty->pt_send &= ~TIOCPKT_DOSTOP;
 968                         pty->pt_send |= TIOCPKT_NOSTOP;
 969                         pty->pt_flags |= PF_NOSTOP;
 970                         ptcpollwakeup(pty, 0);
 971                 }
 972         }
 973 }
 974 
 975 /*
 976  * Wake up controller side.  "flag" is 0 if a special packet or
 977  * user control mode message has been queued up (this data is readable,
 978  * so we also treat it as a regular data event; should we send SIGIO,
 979  * though?), FREAD if regular data has been queued up, or FWRITE if
 980  * the subsidiary's read queue has drained sufficiently to allow writing.
 981  */
 982 static void
 983 ptcpollwakeup(struct pty *pty, int flag)
 984 {
 985         ASSERT(MUTEX_HELD(&pty->ptc_lock));
 986 
 987         if (flag == 0) {
 988                 /*
 989                  * "Exceptional condition" occurred.  This means that
 990                  * a "read" is now possible, so do a "read" wakeup.
 991                  */
 992                 flag = FREAD;
 993                 pollwakeup(&ptcph, POLLIN | POLLRDBAND);
 994                 if (pty->pt_flags & PF_ASYNC)
 995                         gsignal(pty->pt_pgrp, SIGURG);
 996         }
 997         if (flag & FREAD) {
 998                 /*
 999                  * Wake up the parent process as there is regular
1000                  * data to read from subsidiary's write queue
1001                  */
1002                 pollwakeup(&ptcph, POLLIN | POLLRDNORM);
1003                 cv_broadcast(&pty->pt_cv_writeq);
1004                 if (pty->pt_flags & PF_ASYNC)
1005                         gsignal(pty->pt_pgrp, SIGIO);
1006         }
1007         if (flag & FWRITE) {
1008                 /*
1009                  * Wake up the parent process to write
1010                  * data into subsidiary's read queue as the
1011                  * read queue has drained enough
1012                  */
1013                 pollwakeup(&ptcph, POLLOUT | POLLWRNORM);
1014                 cv_broadcast(&pty->pt_cv_readq);
1015                 if (pty->pt_flags & PF_ASYNC)
1016                         gsignal(pty->pt_pgrp, SIGIO);
1017         }
1018 }