1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)tty_pty.c 7.3.1.1 (Berkeley) 01/13/88 7 */ 8 9 /* 10 * Pseudo-teletype Driver 11 * (Actually two drivers, requiring two entries in 'cdevsw') 12 */ 13 #include "pty.h" 14 15 #if NPTY > 0 16 #include "param.h" 17 #include "systm.h" 18 #include "ioctl.h" 19 #include "tty.h" 20 #include "dir.h" 21 #include "user.h" 22 #include "conf.h" 23 #include "file.h" 24 #include "proc.h" 25 #include "uio.h" 26 #include "kernel.h" 27 #include "tsleep.h" 28 29 #if NPTY == 1 30 #undef NPTY 31 #define NPTY 32 /* crude XXX */ 32 #endif 33 34 #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 35 36 /* 37 * pts == /dev/tty[pqrs]? 38 * ptc == /dev/pty[pqrs]? 39 */ 40 struct tty pt_tty[NPTY]; 41 struct pt_ioctl { 42 int pt_flags; 43 struct proc *pt_selr, *pt_selw; 44 u_char pt_send; 45 u_char pt_ucntl; 46 struct clist pt_ioc; 47 } pt_ioctl[NPTY]; 48 int npty = NPTY; /* for pstat -t */ 49 50 #define PF_RCOLL 0x0001 51 #define PF_WCOLL 0x0002 52 #define PF_NBIO 0x0004 53 #define PF_PKT 0x0008 /* packet mode */ 54 #define PF_STOPPED 0x0010 /* user told stopped */ 55 #define PF_REMOTE 0x0020 /* remote and flow controlled input */ 56 #define PF_NOSTOP 0x0040 57 #define PF_UCNTL 0x0080 /* user control mode */ 58 #define PF_TIOC 0x0100 /* transparent control mode */ 59 #define PF_LIOC 0x0200 /* transparent control locked */ 60 #define PF_WIOC 0x0400 /* waiting for PF_LIOC to clear */ 61 #define PF_BLOCK 0x0800 /* block writes to slave */ 62 #define PF_OWAIT 0x1000 /* waiting for PF_BLOCK to clear */ 63 64 /*ARGSUSED*/ 65 ptsopen(dev, flag) 66 dev_t dev; 67 { 68 register struct tty *tp; 69 int error; 70 71 #ifdef lint 72 npty = npty; 73 #endif 74 if (minor(dev) >= NPTY) 75 return (ENXIO); 76 tp = &pt_tty[minor(dev)]; 77 if ((tp->t_state & TS_ISOPEN) == 0) { 78 ttychars(tp); /* Set up default chars */ 79 tp->t_ispeed = tp->t_ospeed = EXTB; 80 tp->t_flags = 0; /* No features (nor raw mode) */ 81 } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 82 return (EBUSY); 83 if (tp->t_oproc) /* Ctrlr still around. */ 84 tp->t_state |= TS_CARR_ON; 85 while ((tp->t_state & TS_CARR_ON) == 0) { 86 tp->t_state |= TS_WOPEN; 87 sleep((caddr_t)&tp->t_rawq, TTIPRI); 88 } 89 error = (*linesw[tp->t_line].l_open)(dev, tp); 90 ptcwakeup(tp, FREAD|FWRITE); 91 return (error); 92 } 93 94 ptsclose(dev) 95 dev_t dev; 96 { 97 register struct tty *tp; 98 99 tp = &pt_tty[minor(dev)]; 100 (*linesw[tp->t_line].l_close)(tp); 101 ttyclose(tp); 102 ptcwakeup(tp, FREAD|FWRITE); 103 return (0); 104 } 105 106 ptsread(dev, uio) 107 dev_t dev; 108 struct uio *uio; 109 { 110 register struct tty *tp = &pt_tty[minor(dev)]; 111 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 112 int error = 0; 113 114 again: 115 if (pti->pt_flags & PF_REMOTE) { 116 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 117 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 118 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 119 u.u_procp->p_flag&SVFORK) 120 return (EIO); 121 gsignal(u.u_procp->p_pgrp, SIGTTIN); 122 sleep((caddr_t)&lbolt, TTIPRI); 123 } 124 if (tp->t_canq.c_cc == 0) { 125 if (tp->t_state & TS_NBIO) 126 return (EWOULDBLOCK); 127 sleep((caddr_t)&tp->t_canq, TTIPRI); 128 goto again; 129 } 130 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 131 if (ureadc(getc(&tp->t_canq), uio) < 0) { 132 error = EFAULT; 133 break; 134 } 135 if (tp->t_canq.c_cc == 1) 136 (void) getc(&tp->t_canq); 137 if (tp->t_canq.c_cc) 138 return (error); 139 } else 140 if (tp->t_oproc) 141 error = (*linesw[tp->t_line].l_read)(tp, uio); 142 ptcwakeup(tp, FWRITE); 143 return (error); 144 } 145 146 /* 147 * Write to pseudo-tty. 148 * Wakeups of controlling tty will happen 149 * indirectly, when tty driver calls ptsstart. 150 */ 151 ptswrite(dev, uio) 152 dev_t dev; 153 struct uio *uio; 154 { 155 register struct tty *tp = &pt_tty[minor(dev)]; 156 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 157 158 if (tp->t_oproc == 0) 159 return (EIO); 160 161 while (pti->pt_flags & PF_BLOCK) { 162 pti->pt_flags |= PF_OWAIT; 163 sleep((caddr_t)pti + 1, TTOPRI); 164 } 165 166 return ((*linesw[tp->t_line].l_write)(tp, uio)); 167 } 168 169 /* 170 * Start output on pseudo-tty. 171 * Wake up process selecting or sleeping for input from controlling tty. 172 */ 173 ptsstart(tp) 174 struct tty *tp; 175 { 176 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 177 178 if (tp->t_state & TS_TTSTOP) 179 return; 180 if (pti->pt_flags & PF_STOPPED) { 181 pti->pt_flags &= ~PF_STOPPED; 182 pti->pt_send = TIOCPKT_START; 183 } 184 ptcwakeup(tp, FREAD); 185 } 186 187 ptcwakeup(tp, flag) 188 struct tty *tp; 189 { 190 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 191 192 if (flag & FREAD) { 193 if (pti->pt_selr) { 194 selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 195 pti->pt_selr = 0; 196 pti->pt_flags &= ~PF_RCOLL; 197 } 198 wakeup((caddr_t)&tp->t_outq.c_cf); 199 } 200 if (flag & FWRITE) { 201 if (pti->pt_selw) { 202 selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 203 pti->pt_selw = 0; 204 pti->pt_flags &= ~PF_WCOLL; 205 } 206 wakeup((caddr_t)&tp->t_rawq.c_cf); 207 } 208 } 209 210 /*ARGSUSED*/ 211 ptcopen(dev, flag) 212 dev_t dev; 213 int flag; 214 { 215 register struct tty *tp; 216 struct pt_ioctl *pti; 217 218 if (minor(dev) >= NPTY) 219 return (ENXIO); 220 tp = &pt_tty[minor(dev)]; 221 if (tp->t_oproc) 222 return (EIO); 223 tp->t_oproc = ptsstart; 224 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 225 pti = &pt_ioctl[minor(dev)]; 226 pti->pt_flags = 0; 227 pti->pt_send = 0; 228 pti->pt_ucntl = 0; 229 return (0); 230 } 231 232 ptcclose(dev) 233 dev_t dev; 234 { 235 register struct tty *tp; 236 237 tp = &pt_tty[minor(dev)]; 238 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 239 tp->t_state &= ~TS_CARR_ON; 240 tp->t_oproc = 0; /* mark closed */ 241 return (0); 242 } 243 244 ptcread(dev, uio) 245 dev_t dev; 246 struct uio *uio; 247 { 248 register struct tty *tp = &pt_tty[minor(dev)]; 249 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 250 char buf[BUFSIZ]; 251 int error = 0, cc; 252 253 /* 254 * We want to block until the slave 255 * is open, and there's something to read; 256 * but if we lost the slave or we're NBIO, 257 * then return the appropriate error instead. 258 */ 259 for (;;) { 260 if (tp->t_state&TS_ISOPEN) { 261 if (pti->pt_flags&PF_PKT && pti->pt_send) { 262 error = ureadc((int)pti->pt_send, uio); 263 if (error) 264 return (error); 265 pti->pt_send = 0; 266 return (0); 267 } 268 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 269 error = ureadc((int)pti->pt_ucntl, uio); 270 if (error) 271 return (error); 272 pti->pt_ucntl = 0; 273 return (0); 274 } 275 if (pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc) { 276 if (uio->uio_resid < pti->pt_ioc.c_cc + 1) 277 return (E2BIG); 278 error = ureadc(TIOCPKT_TIOC, uio); 279 while (error == 0 && pti->pt_ioc.c_cc > 0) { 280 cc = q_to_b(&pti->pt_ioc, buf, 281 MIN(pti->pt_ioc.c_cc, BUFSIZ)); 282 if (cc <= 0) /* impossible? */ 283 break; 284 error = uiomove(buf, cc, UIO_READ, uio); 285 } 286 return (error); 287 } 288 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 289 break; 290 } 291 if ((tp->t_state&TS_CARR_ON) == 0) 292 return (EIO); 293 if (pti->pt_flags&PF_NBIO) 294 return (EWOULDBLOCK); 295 sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 296 } 297 if (pti->pt_flags & (PF_PKT|PF_UCNTL|PF_TIOC)) 298 error = ureadc(0, uio); 299 while (uio->uio_resid > 0 && error == 0) { 300 cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 301 if (cc <= 0) 302 break; 303 error = uiomove(buf, cc, UIO_READ, uio); 304 } 305 if (tp->t_outq.c_cc <= TTLOWAT(tp) && !(pti->pt_flags & PF_BLOCK)) 306 ptswake(tp); 307 return (error); 308 } 309 310 ptswake(tp) 311 register struct tty *tp; 312 { 313 if (tp->t_state&TS_ASLEEP) { 314 tp->t_state &= ~TS_ASLEEP; 315 wakeup((caddr_t)&tp->t_outq); 316 } 317 if (tp->t_wsel) { 318 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 319 tp->t_wsel = 0; 320 tp->t_state &= ~TS_WCOLL; 321 } 322 } 323 324 ptsstop(tp, flush) 325 register struct tty *tp; 326 int flush; 327 { 328 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 329 int flag; 330 331 /* note: FLUSHREAD and FLUSHWRITE already ok */ 332 if (flush == 0) { 333 flush = TIOCPKT_STOP; 334 pti->pt_flags |= PF_STOPPED; 335 } else 336 pti->pt_flags &= ~PF_STOPPED; 337 pti->pt_send |= flush; 338 /* change of perspective */ 339 flag = 0; 340 if (flush & FREAD) 341 flag |= FWRITE; 342 if (flush & FWRITE) 343 flag |= FREAD; 344 ptcwakeup(tp, flag); 345 } 346 347 ptcselect(dev, rw) 348 dev_t dev; 349 int rw; 350 { 351 register struct tty *tp = &pt_tty[minor(dev)]; 352 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 353 struct proc *p; 354 int s; 355 356 if ((tp->t_state&TS_CARR_ON) == 0) 357 return (1); 358 switch (rw) { 359 360 case FREAD: 361 /* 362 * Need to block timeouts (ttrstart). 363 */ 364 s = spltty(); 365 if ((tp->t_state&TS_ISOPEN) && 366 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { 367 splx(s); 368 return (1); 369 } 370 splx(s); 371 /* FALLTHROUGH */ 372 373 case 0: /* exceptional */ 374 if ((tp->t_state&TS_ISOPEN) && 375 (pti->pt_flags&PF_PKT && pti->pt_send || 376 pti->pt_flags&PF_TIOC && pti->pt_ioc.c_cc || 377 pti->pt_flags&PF_UCNTL && pti->pt_ucntl)) 378 return (1); 379 if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 380 pti->pt_flags |= PF_RCOLL; 381 else 382 pti->pt_selr = u.u_procp; 383 break; 384 385 386 case FWRITE: 387 if (tp->t_state&TS_ISOPEN) { 388 if (pti->pt_flags & PF_REMOTE) { 389 if (tp->t_canq.c_cc == 0) 390 return (1); 391 } else { 392 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) 393 return (1); 394 if (tp->t_canq.c_cc == 0 && 395 (tp->t_flags & (RAW|CBREAK)) == 0) 396 return (1); 397 } 398 } 399 if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 400 pti->pt_flags |= PF_WCOLL; 401 else 402 pti->pt_selw = u.u_procp; 403 break; 404 405 } 406 return (0); 407 } 408 409 ptcwrite(dev, uio) 410 dev_t dev; 411 register struct uio *uio; 412 { 413 register struct tty *tp = &pt_tty[minor(dev)]; 414 register struct iovec *iov; 415 register char *cp; 416 register int cc = 0; 417 char locbuf[BUFSIZ]; 418 int cnt = 0; 419 struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 420 int error = 0; 421 422 again: 423 if ((tp->t_state&TS_ISOPEN) == 0) 424 goto block; 425 if (pti->pt_flags & PF_REMOTE) { 426 if (tp->t_canq.c_cc) 427 goto block; 428 while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 429 iov = uio->uio_iov; 430 if (iov->iov_len == 0) { 431 uio->uio_iovcnt--; 432 uio->uio_iov++; 433 continue; 434 } 435 if (cc == 0) { 436 cc = MIN(iov->iov_len, BUFSIZ); 437 cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 438 cp = locbuf; 439 error = uiomove(cp, cc, UIO_WRITE, uio); 440 if (error) 441 return (error); 442 /* check again for safety */ 443 if ((tp->t_state&TS_ISOPEN) == 0) 444 return (EIO); 445 } 446 if (cc) 447 (void) b_to_q(cp, cc, &tp->t_canq); 448 cc = 0; 449 } 450 (void) putc(0, &tp->t_canq); 451 ttwakeup(tp); 452 wakeup((caddr_t)&tp->t_canq); 453 return (0); 454 } 455 while (uio->uio_iovcnt > 0) { 456 iov = uio->uio_iov; 457 if (cc == 0) { 458 if (iov->iov_len == 0) { 459 uio->uio_iovcnt--; 460 uio->uio_iov++; 461 continue; 462 } 463 cc = MIN(iov->iov_len, BUFSIZ); 464 cp = locbuf; 465 error = uiomove(cp, cc, UIO_WRITE, uio); 466 if (error) 467 return (error); 468 /* check again for safety */ 469 if ((tp->t_state&TS_ISOPEN) == 0) 470 return (EIO); 471 } 472 while (cc > 0) { 473 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 474 (tp->t_canq.c_cc > 0 || 475 tp->t_flags & (RAW|CBREAK))) { 476 wakeup((caddr_t)&tp->t_rawq); 477 goto block; 478 } 479 (*linesw[tp->t_line].l_rint)(*cp++, tp); 480 cnt++; 481 cc--; 482 } 483 cc = 0; 484 } 485 return (0); 486 block: 487 /* 488 * Come here to wait for slave to open, for space 489 * in outq, or space in rawq. 490 */ 491 if ((tp->t_state&TS_CARR_ON) == 0) 492 return (EIO); 493 if (pti->pt_flags & PF_NBIO) { 494 iov->iov_base -= cc; 495 iov->iov_len += cc; 496 uio->uio_resid += cc; 497 uio->uio_offset -= cc; 498 if (cnt == 0) 499 return (EWOULDBLOCK); 500 return (0); 501 } 502 sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 503 goto again; 504 } 505 506 /*ARGSUSED*/ 507 ptyioctl(dev, cmd, data, flag) 508 caddr_t data; 509 dev_t dev; 510 { 511 register struct tty *tp = &pt_tty[minor(dev)]; 512 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 513 int stop, error; 514 extern ttyinput(); 515 516 /* 517 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. 518 * ttywflush(tp) will hang if there are characters in the outq. 519 */ 520 if (cdevsw[major(dev)].d_open == ptcopen) { 521 if ((cmd & 0xffff) == (TIOCIOANS(0) & 0xffff)) { 522 if (!(pti->pt_flags & PF_LIOC) || pti->pt_ioc.c_cc) 523 return (EINVAL); 524 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc); 525 wakeup((caddr_t)&pti->pt_ioc); 526 return (0); 527 } 528 switch (cmd) { 529 530 case TIOCPKT: 531 if (*(int *)data) { 532 if (pti->pt_flags & PF_UCNTL) 533 return (EINVAL); 534 pti->pt_flags |= PF_PKT; 535 } else 536 pti->pt_flags &= ~PF_PKT; 537 return (0); 538 539 case TIOCUCNTL: 540 if (*(int *)data) { 541 if (pti->pt_flags & PF_PKT) 542 return (EINVAL); 543 pti->pt_flags |= PF_UCNTL; 544 } else 545 pti->pt_flags &= ~PF_UCNTL; 546 return (0); 547 548 case TIOCTIOC: 549 if (*(int *)data) { 550 if (pti->pt_flags & PF_UCNTL) 551 return (EINVAL); 552 pti->pt_flags |= PF_TIOC; 553 } else { 554 pti->pt_flags &= ~(PF_TIOC|PF_LIOC|PF_WIOC); 555 while (pti->pt_ioc.c_cc) 556 (void) getc(&pti->pt_ioc); 557 wakeup((caddr_t)&pti->pt_ioc); 558 } 559 return (0); 560 561 case TIOCBLK: 562 if (*(int *)data) 563 pti->pt_flags |= PF_BLOCK; 564 else { 565 if (pti->pt_flags & PF_OWAIT) 566 wakeup((caddr_t)pti + 1); 567 pti->pt_flags &= ~(PF_BLOCK|PF_OWAIT); 568 ptswake(tp); 569 } 570 return (0); 571 572 case TIOCREMOTE: 573 if (*(int *)data) 574 pti->pt_flags |= PF_REMOTE; 575 else 576 pti->pt_flags &= ~PF_REMOTE; 577 ttyflush(tp, FREAD|FWRITE); 578 return (0); 579 580 case FIONBIO: 581 if (*(int *)data) 582 pti->pt_flags |= PF_NBIO; 583 else 584 pti->pt_flags &= ~PF_NBIO; 585 return (0); 586 587 case FIONREAD: 588 *(int *)data = tp->t_outq.c_cc; 589 return (0); 590 591 case TIOCSETP: 592 case TIOCSETN: 593 case TIOCSETD: 594 while (getc(&tp->t_outq) >= 0) 595 ; 596 break; 597 } 598 } else if (pti->pt_flags & PF_TIOC) { 599 while (pti->pt_flags & PF_LIOC) { 600 pti->pt_flags |= PF_WIOC; 601 switch (tsleep((caddr_t)&pti->pt_flags,TTIPRI-1,5*hz)) { 602 case TS_OK: 603 continue; 604 case TS_SIG: 605 case TS_TIME: 606 return (EBUSY); 607 } 608 } 609 pti->pt_flags |= PF_LIOC | PF_BLOCK; 610 while (pti->pt_ioc.c_cc) 611 (void) getc(&pti->pt_ioc); 612 (void) b_to_q(&cmd, sizeof cmd, &pti->pt_ioc); 613 if (cmd & IOC_IN) 614 (void) b_to_q(data, IOCPARM_LEN(cmd), &pti->pt_ioc); 615 ptcwakeup(tp, FREAD); 616 switch (tsleep((caddr_t)&pti->pt_ioc, TTIPRI-1, 5*hz)) { 617 case TS_SIG: 618 case TS_TIME: 619 while (pti->pt_ioc.c_cc) 620 (void) getc(&pti->pt_ioc); 621 if (pti->pt_flags & PF_WIOC) 622 wakeup((caddr_t)&pti->pt_flags); 623 if (pti->pt_flags & PF_OWAIT) 624 wakeup((caddr_t)pti + 1); 625 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT); 626 ptswake(tp); 627 return (EBUSY); 628 case TS_OK: 629 break; 630 } 631 if (pti->pt_ioc.c_cc == 0) { 632 if (pti->pt_flags & PF_WIOC) 633 wakeup((caddr_t)&pti->pt_flags); 634 if (pti->pt_flags & PF_OWAIT) 635 wakeup((caddr_t)pti + 1); 636 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT); 637 ptswake(tp); 638 goto doioctl; 639 } 640 if (q_to_b(&pti->pt_ioc, &error, sizeof error) != sizeof error) 641 error = EINVAL; 642 if (error == 0 && cmd & IOC_OUT) { 643 if (IOCPARM_LEN(cmd) != pti->pt_ioc.c_cc) 644 error = EINVAL; 645 else 646 (void) q_to_b(&pti->pt_ioc, data, 647 pti->pt_ioc.c_cc); 648 } 649 while (pti->pt_ioc.c_cc) 650 (void) getc(&pti->pt_ioc); 651 if (pti->pt_flags & PF_WIOC) 652 wakeup((caddr_t)&pti->pt_flags); 653 if (pti->pt_flags & PF_OWAIT) 654 wakeup((caddr_t)pti + 1); 655 pti->pt_flags &= ~(PF_LIOC|PF_WIOC|PF_BLOCK|PF_OWAIT); 656 ptswake(tp); 657 return (error); 658 } 659 660 doioctl: 661 error = ttioctl(tp, cmd, data, flag); 662 /* 663 * Since we use the tty queues internally, 664 * pty's can't be switched to disciplines which overwrite 665 * the queues. We can't tell anything about the discipline 666 * from here... 667 * 668 * Nb: this is not really good enough, the line disc open routine 669 * may have done anything at all, no guarantees that close 670 * will fix it. This also has the effect of losing the 671 * previous discipline, which an error on a TIOCSETD shouldn't 672 * do... Sometime it should be done via an explicit check 673 * for TIOCSETD, then check to see what linesw[new_number].l_rint 674 * really is. 675 */ 676 if (linesw[tp->t_line].l_rint != ttyinput) { 677 (*linesw[tp->t_line].l_close)(tp); 678 tp->t_line = 0; 679 (void)(*linesw[tp->t_line].l_open)(dev, tp); 680 error = ENOTTY; 681 } 682 683 if (error < 0) { 684 if (pti->pt_flags & PF_UCNTL && 685 (cmd & ~0xff) == UIOCCMD(0)) { 686 if (cmd & 0xff) { 687 pti->pt_ucntl = (u_char)cmd; 688 ptcwakeup(tp, FREAD); 689 } 690 return (0); 691 } 692 error = ENOTTY; 693 } 694 stop = (tp->t_flags & RAW) == 0 && 695 tp->t_stopc == CTRL('s') && tp->t_startc == CTRL('q'); 696 if (pti->pt_flags & PF_NOSTOP) { 697 if (stop) { 698 pti->pt_send &= ~TIOCPKT_NOSTOP; 699 pti->pt_send |= TIOCPKT_DOSTOP; 700 pti->pt_flags &= ~PF_NOSTOP; 701 ptcwakeup(tp, FREAD); 702 } 703 } else { 704 if (!stop) { 705 pti->pt_send &= ~TIOCPKT_DOSTOP; 706 pti->pt_send |= TIOCPKT_NOSTOP; 707 pti->pt_flags |= PF_NOSTOP; 708 ptcwakeup(tp, FREAD); 709 } 710 } 711 return (error); 712 } 713 #endif 714