1 /* 2 * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)tty_pty.c 7.21 (Berkeley) 5/30/91 34 * $Id: tty_pty.c,v 1.6 1993/06/06 23:05:15 cgd Exp $ 35 */ 36 37 /* 38 * Pseudo-teletype Driver 39 * (Actually two drivers, requiring two entries in 'cdevsw') 40 */ 41 #include "pty.h" 42 43 #if NPTY > 0 44 #include "param.h" 45 #include "systm.h" 46 #include "ioctl.h" 47 #include "select.h" 48 #include "tty.h" 49 #include "conf.h" 50 #include "file.h" 51 #include "malloc.h" 52 #include "proc.h" 53 #include "uio.h" 54 #include "kernel.h" 55 #include "vnode.h" 56 57 #if NPTY == 1 58 #undef NPTY 59 #define NPTY 32 /* crude XXX */ 60 #endif 61 62 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 63 64 /* 65 * pts == /dev/tty[pqrs]? 66 * ptc == /dev/pty[pqrs]? 67 */ 68 struct tty *pt_tty[NPTY]; 69 struct pt_ioctl { 70 int pt_flags; 71 struct selinfo pt_selr, pt_selw; 72 u_char pt_send; 73 u_char pt_ucntl; 74 } pt_ioctl[NPTY]; 75 int npty = NPTY; /* for pstat -t */ 76 77 #define PF_RCOLL 0x01 78 #define PF_WCOLL 0x02 79 #define PF_PKT 0x08 /* packet mode */ 80 #define PF_STOPPED 0x10 /* user told stopped */ 81 #define PF_REMOTE 0x20 /* remote and flow controlled input */ 82 #define PF_NOSTOP 0x40 83 #define PF_UCNTL 0x80 /* user control mode */ 84 85 /*ARGSUSED*/ 86 ptsopen(dev, flag, devtype, p) 87 dev_t dev; 88 struct proc *p; 89 { 90 register struct tty *tp; 91 int error; 92 93 #ifdef lint 94 npty = npty; 95 #endif 96 if (minor(dev) >= NPTY) 97 return (ENXIO); 98 if(!pt_tty[minor(dev)]) { 99 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK); 100 bzero(tp, sizeof(struct tty)); 101 pt_tty[minor(dev)] = tp; 102 } else 103 tp = pt_tty[minor(dev)]; 104 if ((tp->t_state & TS_ISOPEN) == 0) { 105 tp->t_state |= TS_WOPEN; 106 ttychars(tp); /* Set up default chars */ 107 tp->t_iflag = TTYDEF_IFLAG; 108 tp->t_oflag = TTYDEF_OFLAG; 109 tp->t_lflag = TTYDEF_LFLAG; 110 tp->t_cflag = TTYDEF_CFLAG; 111 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 112 ttsetwater(tp); /* would be done in xxparam() */ 113 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 114 return (EBUSY); 115 if (tp->t_oproc) /* Ctrlr still around. */ 116 tp->t_state |= TS_CARR_ON; 117 while ((tp->t_state & TS_CARR_ON) == 0) { 118 tp->t_state |= TS_WOPEN; 119 if (flag&FNONBLOCK) 120 break; 121 if (error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH, 122 ttopen, 0)) 123 return (error); 124 } 125 error = (*linesw[tp->t_line].l_open)(dev, tp, flag); 126 ptcwakeup(tp, FREAD|FWRITE); 127 return (error); 128 } 129 130 ptsclose(dev, flag, mode, p) 131 dev_t dev; 132 int flag, mode; 133 struct proc *p; 134 { 135 register struct tty *tp; 136 137 tp = pt_tty[minor(dev)]; 138 (*linesw[tp->t_line].l_close)(tp, flag); 139 ttyclose(tp); 140 ptcwakeup(tp, FREAD|FWRITE); 141 return(0); 142 } 143 144 ptsread(dev, uio, flag) 145 dev_t dev; 146 struct uio *uio; 147 { 148 struct proc *p = curproc; 149 register struct tty *tp = pt_tty[minor(dev)]; 150 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 151 int error = 0; 152 153 again: 154 if (pti->pt_flags & PF_REMOTE) { 155 while (isbackground(p, tp)) { 156 if ((p->p_sigignore & sigmask(SIGTTIN)) || 157 (p->p_sigmask & sigmask(SIGTTIN)) || 158 p->p_pgrp->pg_jobc == 0 || 159 p->p_flag&SPPWAIT) 160 return (EIO); 161 pgsignal(p->p_pgrp, SIGTTIN, 1); 162 if (error = ttysleep(tp, (caddr_t)&lbolt, 163 TTIPRI | PCATCH, ttybg, 0)) 164 return (error); 165 } 166 if (RB_LEN(&tp->t_can) == 0) { 167 if (flag & IO_NDELAY) 168 return (EWOULDBLOCK); 169 if (error = ttysleep(tp, (caddr_t)&tp->t_can, 170 TTIPRI | PCATCH, ttyin, 0)) 171 return (error); 172 goto again; 173 } 174 while (RB_LEN(&tp->t_can) > 1 && uio->uio_resid > 0) 175 if (ureadc(rbgetc(&tp->t_can), uio) < 0) { 176 error = EFAULT; 177 break; 178 } 179 if (RB_LEN(&tp->t_can) == 1) 180 (void) rbgetc(&tp->t_can); 181 if (RB_LEN(&tp->t_can)) 182 return (error); 183 } else 184 if (tp->t_oproc) 185 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 186 ptcwakeup(tp, FWRITE); 187 return (error); 188 } 189 190 /* 191 * Write to pseudo-tty. 192 * Wakeups of controlling tty will happen 193 * indirectly, when tty driver calls ptsstart. 194 */ 195 ptswrite(dev, uio, flag) 196 dev_t dev; 197 struct uio *uio; 198 { 199 register struct tty *tp; 200 201 tp = pt_tty[minor(dev)]; 202 if (tp->t_oproc == 0) 203 return (EIO); 204 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 205 } 206 207 /* 208 * Start output on pseudo-tty. 209 * Wake up process selecting or sleeping for input from controlling tty. 210 */ 211 ptsstart(tp) 212 struct tty *tp; 213 { 214 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 215 216 if (tp->t_state & TS_TTSTOP) 217 return; 218 if (pti->pt_flags & PF_STOPPED) { 219 pti->pt_flags &= ~PF_STOPPED; 220 pti->pt_send = TIOCPKT_START; 221 } 222 ptcwakeup(tp, FREAD); 223 } 224 225 ptcwakeup(tp, flag) 226 struct tty *tp; 227 { 228 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 229 230 if (flag & FREAD) { 231 selwakeup(&pti->pt_selr); 232 wakeup((caddr_t)&tp->t_out.rb_tl); 233 } 234 if (flag & FWRITE) { 235 selwakeup(&pti->pt_selw); 236 wakeup((caddr_t)&tp->t_raw.rb_hd); 237 } 238 } 239 240 /*ARGSUSED*/ 241 #ifdef __STDC__ 242 ptcopen(dev_t dev, int flag, int devtype, struct proc *p) 243 #else 244 ptcopen(dev, flag, devtype, p) 245 dev_t dev; 246 int flag, devtype; 247 struct proc *p; 248 #endif 249 { 250 register struct tty *tp; 251 struct pt_ioctl *pti; 252 253 if (minor(dev) >= NPTY) 254 return (ENXIO); 255 if(!pt_tty[minor(dev)]) { 256 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK); 257 bzero(tp, sizeof(struct tty)); 258 pt_tty[minor(dev)] = tp; 259 } else 260 tp = pt_tty[minor(dev)]; 261 if (tp->t_oproc) 262 return (EIO); 263 tp->t_oproc = ptsstart; 264 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 265 tp->t_lflag &= ~EXTPROC; 266 pti = &pt_ioctl[minor(dev)]; 267 pti->pt_flags = 0; 268 pti->pt_send = 0; 269 pti->pt_ucntl = 0; 270 return (0); 271 } 272 273 extern struct tty *constty; /* -hv- 06.Oct.92*/ 274 ptcclose(dev) 275 dev_t dev; 276 { 277 register struct tty *tp; 278 279 tp = pt_tty[minor(dev)]; 280 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 281 tp->t_state &= ~TS_CARR_ON; 282 tp->t_oproc = 0; /* mark closed */ 283 tp->t_session = 0; 284 285 /* XXX -hv- 6.Oct.92 this prevents the "hanging console bug" with X11 */ 286 if (constty==tp) 287 constty = 0; 288 289 #if 0 290 /* 291 * currently, we do not free the pty structures once they have 292 * been allocated. Two reasons: cheap to keep them around, and 293 * I don't want to spend my time finding the exact variables that 294 * will tell me if the slave/master are closed and if I can free 295 * them. <deraadt@fsa.ca> 296 */ 297 FREE(tp, M_TTYS); 298 pt_tty[minor(dev)] = (struct tty *)NULL; 299 #endif 300 return (0); 301 } 302 303 ptcread(dev, uio, flag) 304 dev_t dev; 305 struct uio *uio; 306 { 307 register struct tty *tp = pt_tty[minor(dev)]; 308 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 309 char buf[BUFSIZ]; 310 int error = 0, cc; 311 312 /* 313 * We want to block until the slave 314 * is open, and there's something to read; 315 * but if we lost the slave or we're NBIO, 316 * then return the appropriate error instead. 317 */ 318 for (;;) { 319 if (tp->t_state&TS_ISOPEN) { 320 if (pti->pt_flags&PF_PKT && pti->pt_send) { 321 error = ureadc((int)pti->pt_send, uio); 322 if (error) 323 return (error); 324 if (pti->pt_send & TIOCPKT_IOCTL) { 325 cc = MIN(uio->uio_resid, 326 sizeof(tp->t_termios)); 327 uiomove(&tp->t_termios, cc, uio); 328 } 329 pti->pt_send = 0; 330 return (0); 331 } 332 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 333 error = ureadc((int)pti->pt_ucntl, uio); 334 if (error) 335 return (error); 336 pti->pt_ucntl = 0; 337 return (0); 338 } 339 if (RB_LEN(&tp->t_out) && (tp->t_state&TS_TTSTOP) == 0) 340 break; 341 } 342 if ((tp->t_state&TS_CARR_ON) == 0) 343 return (0); /* EOF */ 344 if (flag & IO_NDELAY) 345 return (EWOULDBLOCK); 346 if (error = tsleep((caddr_t)&tp->t_out.rb_tl, TTIPRI | PCATCH, 347 ttyin, 0)) 348 return (error); 349 } 350 if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 351 error = ureadc(0, uio); 352 while (uio->uio_resid > 0 && error == 0) { 353 #ifdef was 354 cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 355 #else 356 cc = min(MIN(uio->uio_resid, BUFSIZ), RB_CONTIGGET(&tp->t_out)); 357 if (cc) { 358 rbunpack(tp->t_out.rb_hd, buf, cc); 359 tp->t_out.rb_hd = 360 RB_ROLLOVER(&tp->t_out, tp->t_out.rb_hd+cc); 361 } 362 #endif 363 if (cc <= 0) 364 break; 365 error = uiomove(buf, cc, uio); 366 } 367 if (RB_LEN(&tp->t_out) <= tp->t_lowat) { 368 if (tp->t_state&TS_ASLEEP) { 369 tp->t_state &= ~TS_ASLEEP; 370 wakeup((caddr_t)&tp->t_out); 371 } 372 selwakeup(&tp->t_wsel); 373 } 374 return (error); 375 } 376 377 ptsstop(tp, flush) 378 register struct tty *tp; 379 int flush; 380 { 381 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 382 int flag; 383 384 /* note: FLUSHREAD and FLUSHWRITE already ok */ 385 if (flush == 0) { 386 flush = TIOCPKT_STOP; 387 pti->pt_flags |= PF_STOPPED; 388 } else 389 pti->pt_flags &= ~PF_STOPPED; 390 pti->pt_send |= flush; 391 /* change of perspective */ 392 flag = 0; 393 if (flush & FREAD) 394 flag |= FWRITE; 395 if (flush & FWRITE) 396 flag |= FREAD; 397 ptcwakeup(tp, flag); 398 } 399 400 ptcselect(dev, rw, p) 401 dev_t dev; 402 int rw; 403 struct proc *p; 404 { 405 register struct tty *tp = pt_tty[minor(dev)]; 406 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 407 struct proc *prev; 408 int s; 409 410 if ((tp->t_state&TS_CARR_ON) == 0) 411 return (1); 412 switch (rw) { 413 414 case FREAD: 415 /* 416 * Need to block timeouts (ttrstart). 417 */ 418 s = spltty(); 419 if ((tp->t_state&TS_ISOPEN) && 420 RB_LEN(&tp->t_out) && (tp->t_state&TS_TTSTOP) == 0) { 421 splx(s); 422 return (1); 423 } 424 splx(s); 425 /* FALLTHROUGH */ 426 427 case 0: /* exceptional */ 428 if ((tp->t_state&TS_ISOPEN) && 429 (pti->pt_flags&PF_PKT && pti->pt_send || 430 pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 431 return (1); 432 selrecord(p, &pti->pt_selr); 433 break; 434 435 436 case FWRITE: 437 if (tp->t_state&TS_ISOPEN) { 438 if (pti->pt_flags & PF_REMOTE) { 439 if (RB_LEN(&tp->t_can) == 0) 440 return (1); 441 } else { 442 if (RB_LEN(&tp->t_raw) + RB_LEN(&tp->t_can) < TTYHOG-2) 443 return (1); 444 if (RB_LEN(&tp->t_can) == 0 && (tp->t_iflag&ICANON)) 445 return (1); 446 } 447 } 448 selrecord(p, &pti->pt_selw); 449 break; 450 451 } 452 return (0); 453 } 454 455 ptcwrite(dev, uio, flag) 456 dev_t dev; 457 register struct uio *uio; 458 { 459 register struct tty *tp = pt_tty[minor(dev)]; 460 register u_char *cp; 461 register int cc = 0; 462 u_char locbuf[BUFSIZ]; 463 int cnt = 0; 464 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 465 int error = 0; 466 467 again: 468 if ((tp->t_state&TS_ISOPEN) == 0) 469 goto block; 470 if (pti->pt_flags & PF_REMOTE) { 471 if (RB_LEN(&tp->t_can)) 472 goto block; 473 while (uio->uio_resid > 0 && RB_LEN(&tp->t_can) < TTYHOG - 1) { 474 if (cc == 0) { 475 cc = min(uio->uio_resid, BUFSIZ); 476 cc = min(cc, TTYHOG - 1 - RB_CONTIGPUT(&tp->t_can)); 477 cp = locbuf; 478 error = uiomove((caddr_t)cp, cc, uio); 479 if (error) 480 return (error); 481 /* check again for safety */ 482 if ((tp->t_state&TS_ISOPEN) == 0) 483 return (EIO); 484 } 485 #ifdef was 486 if (cc) 487 (void) b_to_q((char *)cp, cc, &tp->t_canq); 488 #else 489 if (cc) { 490 rbpack(cp, tp->t_can.rb_tl, cc); 491 tp->t_can.rb_tl = 492 RB_ROLLOVER(&tp->t_can, tp->t_can.rb_tl+cc); 493 } 494 #endif 495 cc = 0; 496 } 497 (void) putc(0, &tp->t_can); 498 ttwakeup(tp); 499 wakeup((caddr_t)&tp->t_can); 500 return (0); 501 } 502 while (uio->uio_resid > 0) { 503 if (cc == 0) { 504 cc = min(uio->uio_resid, BUFSIZ); 505 cp = locbuf; 506 error = uiomove((caddr_t)cp, cc, uio); 507 if (error) 508 return (error); 509 /* check again for safety */ 510 if ((tp->t_state&TS_ISOPEN) == 0) 511 return (EIO); 512 } 513 while (cc > 0) { 514 if ((RB_LEN(&tp->t_raw) + RB_LEN(&tp->t_can)) >= TTYHOG - 2 && 515 (RB_LEN(&tp->t_can) > 0 || !(tp->t_iflag&ICANON))) { 516 wakeup((caddr_t)&tp->t_raw); 517 goto block; 518 } 519 (*linesw[tp->t_line].l_rint)(*cp++, tp); 520 cnt++; 521 cc--; 522 } 523 cc = 0; 524 } 525 return (0); 526 block: 527 /* 528 * Come here to wait for slave to open, for space 529 * in outq, or space in rawq. 530 */ 531 if ((tp->t_state&TS_CARR_ON) == 0) 532 return (EIO); 533 if (flag & IO_NDELAY) { 534 /* adjust for data copied in but not written */ 535 uio->uio_resid += cc; 536 if (cnt == 0) 537 return (EWOULDBLOCK); 538 return (0); 539 } 540 if (error = tsleep((caddr_t)&tp->t_raw.rb_hd, TTOPRI | PCATCH, 541 ttyout, 0)) { 542 /* adjust for data copied in but not written */ 543 uio->uio_resid += cc; 544 return (error); 545 } 546 goto again; 547 } 548 549 /*ARGSUSED*/ 550 ptyioctl(dev, cmd, data, flag) 551 caddr_t data; 552 dev_t dev; 553 { 554 register struct tty *tp = pt_tty[minor(dev)]; 555 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 556 register u_char *cc = tp->t_cc; 557 int stop, error; 558 extern ttyinput(); 559 560 /* 561 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 562 * ttywflush(tp) will hang if there are characters in the outq. 563 */ 564 if (cmd == TIOCEXT) { 565 /* 566 * When the EXTPROC bit is being toggled, we need 567 * to send an TIOCPKT_IOCTL if the packet driver 568 * is turned on. 569 */ 570 if (*(int *)data) { 571 if (pti->pt_flags & PF_PKT) { 572 pti->pt_send |= TIOCPKT_IOCTL; 573 ptcwakeup(tp, FREAD); 574 } 575 tp->t_lflag |= EXTPROC; 576 } else { 577 if ((tp->t_state & EXTPROC) && 578 (pti->pt_flags & PF_PKT)) { 579 pti->pt_send |= TIOCPKT_IOCTL; 580 ptcwakeup(tp, FREAD); 581 } 582 tp->t_lflag &= ~EXTPROC; 583 } 584 return(0); 585 } else 586 if (cdevsw[major(dev)].d_open == ptcopen) 587 switch (cmd) { 588 589 case TIOCGPGRP: 590 /* 591 * We aviod calling ttioctl on the controller since, 592 * in that case, tp must be the controlling terminal. 593 */ 594 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 595 return (0); 596 597 case TIOCPKT: 598 if (*(int *)data) { 599 if (pti->pt_flags & PF_UCNTL) 600 return (EINVAL); 601 pti->pt_flags |= PF_PKT; 602 } else 603 pti->pt_flags &= ~PF_PKT; 604 return (0); 605 606 case TIOCUCNTL: 607 if (*(int *)data) { 608 if (pti->pt_flags & PF_PKT) 609 return (EINVAL); 610 pti->pt_flags |= PF_UCNTL; 611 } else 612 pti->pt_flags &= ~PF_UCNTL; 613 return (0); 614 615 case TIOCREMOTE: 616 if (*(int *)data) 617 pti->pt_flags |= PF_REMOTE; 618 else 619 pti->pt_flags &= ~PF_REMOTE; 620 ttyflush(tp, FREAD|FWRITE); 621 return (0); 622 623 #ifdef COMPAT_43 624 /* wkt */ 625 case TIOCSETP: 626 case TIOCSETN: 627 #endif 628 case TIOCSETD: 629 case TIOCSETA: 630 case TIOCSETAW: 631 case TIOCSETAF: 632 while (rbgetc(&tp->t_out) >= 0) 633 ; 634 break; 635 636 case TIOCSIG: 637 if (*(unsigned int *)data >= NSIG) 638 return(EINVAL); 639 if ((tp->t_lflag&NOFLSH) == 0) 640 ttyflush(tp, FREAD|FWRITE); 641 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); 642 if ((*(unsigned int *)data == SIGINFO) && 643 ((tp->t_lflag&NOKERNINFO) == 0)) 644 ttyinfo(tp); 645 return(0); 646 } 647 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 648 if (error < 0) 649 error = ttioctl(tp, cmd, data, flag); 650 /* 651 * Since we use the tty queues internally, 652 * pty's can't be switched to disciplines which overwrite 653 * the queues. We can't tell anything about the discipline 654 * from here... 655 */ 656 if (linesw[tp->t_line].l_rint != ttyinput) { 657 (*linesw[tp->t_line].l_close)(tp, flag); 658 tp->t_line = TTYDISC; 659 (void)(*linesw[tp->t_line].l_open)(dev, tp, flag); 660 error = ENOTTY; 661 } 662 if (error < 0) { 663 if (pti->pt_flags & PF_UCNTL && 664 (cmd & ~0xff) == UIOCCMD(0)) { 665 if (cmd & 0xff) { 666 pti->pt_ucntl = (u_char)cmd; 667 ptcwakeup(tp, FREAD); 668 } 669 return (0); 670 } 671 error = ENOTTY; 672 } 673 /* 674 * If external processing and packet mode send ioctl packet. 675 */ 676 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { 677 switch(cmd) { 678 case TIOCSETA: 679 case TIOCSETAW: 680 case TIOCSETAF: 681 #ifdef COMPAT_43 682 /* wkt */ 683 case TIOCSETP: 684 case TIOCSETN: 685 case TIOCSETC: 686 case TIOCSLTC: 687 case TIOCLBIS: 688 case TIOCLBIC: 689 case TIOCLSET: 690 #endif 691 pti->pt_send |= TIOCPKT_IOCTL; 692 default: 693 break; 694 } 695 } 696 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) 697 && CCEQ(cc[VSTART], CTRL('q')); 698 if (pti->pt_flags & PF_NOSTOP) { 699 if (stop) { 700 pti->pt_send &= ~TIOCPKT_NOSTOP; 701 pti->pt_send |= TIOCPKT_DOSTOP; 702 pti->pt_flags &= ~PF_NOSTOP; 703 ptcwakeup(tp, FREAD); 704 } 705 } else { 706 if (!stop) { 707 pti->pt_send &= ~TIOCPKT_DOSTOP; 708 pti->pt_send |= TIOCPKT_NOSTOP; 709 pti->pt_flags |= PF_NOSTOP; 710 ptcwakeup(tp, FREAD); 711 } 712 } 713 return (error); 714 } 715 #endif 716